【问题标题】:Generalizing include statements in c++ files when building with make使用 make 构建时在 c++ 文件中概括包含语句
【发布时间】:2013-02-15 19:03:32
【问题描述】:

您好(我使用的是 Windows,mingw g++ 编译器和 mingw32-make)
为了概括我的问题,我想学习如何编写 C++ 源文件,如下所示:

假设 foo.cpp 依赖于 foo.h,其中 foo.cpp 在 src\ 而 foo.h 在 include\
// foo.cpp
#include "foo.h"

通常我会这样写
//foo.cpp
#include "..\include\foo.h"

但我发现随着项目的增长,我开始需要更多的组织,这种方法不够动态。原因是如果我想将 foo.h 移动到新目录(比如 include\bar\foo.h),我必须更改每个文件的每个包含。有没有办法让 make 实现这一目标。如果是这样,它也可以用于头文件依赖项。

作为旁注,我是 makefile 的新手。我什至不确定它是否知道这些包含存在,因为它们在代码中(事实上据我了解它没有)。这将导致我遇到一个不幸的次要问题,即可以看到这些包括吗?如果不是,是否可以更改它以使其可以?随意回答你将如何解决这个问题,因为我觉得我通过将包含放在文件中而不是将它们链接到 makefile 中以错误的方式解决这个问题。

【问题讨论】:

    标签: c++ windows makefile g++


    【解决方案1】:

    编译器总是在寻找一些默认路径来查找 .h 文件。您可以添加路径。

    例如gcc 接受多个包含路径的-I 参数。在您的foo.cpp 中,您可以:

    #include "foo.h"
    

    编译时你说:

    g++ -I../include foo.cpp -c [other options]
    

    .

    关于您问题的第二部分:makefile 和对make 的调用通常对要编译的文件和您的项目一无所知。但是 make 中有几个默认变量和指令会导致这种印象:可能是,在您的环境中,您只需要更改 CFLAGSCPPFLAGS 变量以添加 -I-argument 并且它会起作用.

    【讨论】:

    • 感谢您的快速回复和直截了当的回答。当我再次访问该项目时,我会尝试它。
    【解决方案2】:

    Patrick B 已经很好地回答了如何让编译器知道从哪里包含,但不是以下位:

    作为旁注,我是 makefile 的新手。我什至不确定它是否知道 这些包括在那里,因为它们在代码中(实际上来自 我的理解不是)。那会导致我不幸 第二个问题,哪些是可以看到这些包括?如果不是的话 是否可以更改它以使其可以?

    不,make 不了解您的源文件包含什么,或者它们如何依赖于其他文件 [make 也不真正关心您是否使用 C、C++、Fortran、Pascal、ADA、Lisp、Cobol 或Haskell - 只要文件之间存在“如果你有这样的文件,并且想要通过做某事得到这样的文件”关系,make 就会为你排序。

    有几种方法可以做到这一点。您可以手动添加:

     foo.cpp: foo.h
    

    或者你可以为你的包含文件使用一个依赖文件,并让make自动构建它,通过添加这个,例如:

     SOURCES = foo.cpp    # Add any further source files here. 
     INCLUDES = -I../includes   # Add other include directories if needed. 
    
     CFLAGS += ${INCLUDES}
    
     TARGET = foo.exe   # in Windows. Just foo in linux/MacOS.
    
     all: ${TARGET} deps.mk
    
     ${TARGET}: ${SOURCES}
         gcc -O $@ $^      
    
     desp.mk: ${SOURCES}
         gcc -MM ${INCLUDES} $^ > $@
    
     include deps.mk
    

    请注意,makefile 依赖于作为制表符的缩进。这篇文章使用了空格,因此您需要“标记”收据。另请注意,在“正确的”makefile 中,您将从foo.cpp 等创建foo.o,并将所有不同的.o 文件链接在一起。这样,对于大型项目来说,编译会更快一些。为了便于阅读,我对其进行了简化。

    也许我应该扩大一点:

    gcc -MM 给出正在“编译”的文件及其所有依赖项的列表(标准输出)。它实际上并不编译代码(只要代码至少有点)接近可编译,它会愉快地处理您的文件。

    有关gcc -MM 及相关的更多详细信息,请查看GCC invocation 文档。

    $@$&^make 所称的“自动变量”——它们扩展为“目标”(容易记住,因为它看起来有点像射箭或类似的目标)和分别是“所有依赖项”(恐怕这里没有视觉线索 - 并且时不时地,我必须提醒自己)。查看here了解更多详情。

    【讨论】:

    • 补充:一些编译器有一个选项,例如-M,为make生成一个依赖文件。
    • 是的,gcc -MM 就是这样 - -M 还列出了标准库文件,这些文件在 makefile 中通常不需要 [因为它们通常不会经常更改,在实际影响程序的方式]。
    • 希望您和帕特里克完美地回答了我的问题。当我有时间测试这个时,我会回复你的结果。
    猜你喜欢
    • 1970-01-01
    • 2013-11-17
    • 2014-06-14
    • 2019-09-27
    • 2012-02-28
    • 2012-02-26
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    相关资源
    最近更新 更多