【问题标题】:Makefiles: subdirectories and similar filenames [closed]Makefiles:子目录和类似的文件名[关闭]
【发布时间】:2018-01-05 17:04:50
【问题描述】:

为了了解 C/C++ 开发工具并停止依赖 IDE,改用 Visual Studio Code。我尝试为此目的使用 Makefile,因为它允许通过命令行在目标设备上运行编译(无 GUI == 无 IDE)。到目前为止,我已经设法制作了一个通用的 Makefile,它将所有 .cpp 文件编译为相应的 .o 文件,然后将它们链接在一起。它适用于将所有源存储在单个目录中的小型项目。现在我必须移植我正在工作的 Xcode 项目。

问题在于源文件存储在目录树中(没有单个目录),并且可能同时是CC++。有些文件具有相似的文件名,但位于不同的文件夹中。从 C++ 的角度来看,这意味着类具有相同的名称,但名称空间不同。各种 IDE 可以轻松处理这个问题,但 Makefile 给我带来了各种各样的问题,因为我还不是 make 大师。

我尝试在每个目录中创建 Makefile(我失败了),但后来我读到这被认为是一种不好的方法,所以我切换到了单个 Makefile 方法。有人说我应该切换到 CMake,但我认为如果不首先了解 Makefile 创建是没有意义的,因为 CMake 最终会创建一个。它还允许在没有 CMake 和其他酷工具的设备上构建和安装(例如,如果没有 Internet 连接来下载 CMake)。

这是一个基本的想法:

- project-name/
  - application/
    - core/
      - loader.hpp
      - loader.cpp
      - ...
    - loader.hpp
    - loader.cpp
    - ...
  - hardware/
    - loader.hpp
    - loader.cpp
    - ...
  - some-c-library
    - library.h
    - library.c
    - ...
  - main.cpp
- project-name.xcodeproj
- Makefile

TR&DL: 无法制作复杂的 Makefile。 GNU 手册很难理解,在线博客/教程大多只涉及基本内容。

【问题讨论】:

  • 我知道您想了解 Makefile,但是对于这种复杂的场景,我强烈建议您使用 makefile 生成器(如 CMake)。一个原因是原始 Makefile 不会自动跟踪依赖关系:如果您添加新的 #include,您还必须记住更新相应的 Makefile 以添加对该标头的依赖关系,否则您的源文件可能无法按预期编译它到了,你会因为试图找出链接器错误而头疼。
  • 您不需要 CMake 来自动生成依赖项——您可以简单地使用 gcc see here 中的 -M 标志。
  • 你面临什么样的问题,因为我看不出你当前的设置有什么复杂的地方——除了 Makefile 应该在项目目录中
  • @Vroomfondel:重复的文件名并不少见。假设文件名不(或将来不会)冲突不是一个过度可扩展的解决方案,因此我个人不鼓励不处理它们的做法。将路径名放在包含指令等中以避免冲突很简单。

标签: makefile


【解决方案1】:

我真的不确定您是否需要过于复杂。当然,您可以让 Makefile 为每个 C 和 C++ 文件搜索您的目录树,但是如果您添加了一个您还不想编译的新文件呢?

不过,您可以让事情变得更简单而不会太复杂。将源文件列表分配给变量 - 这样您就可以在需要时引用它们。

CPPSOURCES=hardware/loader.cpp application/core/loader.cpp main.cpp
CSOURCES=some-c-library/library.c

然后将这些文件名转换为对象文件名 - 这只是将 .cpp 替换为 .o 等...

CPPOBJS=$(CPPSOURCES:.cpp=.o)
COBJS=$(CSOURCES:.c=.o)

还有一些标准变量用于指定传递给 C++ 和 C 编译器的标志

CXXFLAGS-g
CFLAGS-g

那么您就有了构建项目的规则。 $@ 是规则正在构建的事物的名称(即“myproject”),$^ 是依赖项列表。

myproject: $(COBJS) $(CPPOBJS)
   $(CXX) $(CXXFLAGS) -o $@ $^

Make 带有一堆默认规则,因此它已经知道如果您要求它构建“some/where/deep/in/my/project/somefile.o”,它正在寻找“some/where/deep” /in/my/project/somefile.cpp”例如。

您可以添加一条规则来删除所有目标文件 - 这就是使用变量很方便的原因

clean:
    rm $(COBJS) $(CXXOBJS)

您需要担心的唯一另一件事是依赖关系,例如下面的示例,它告诉 make 它需要在“hardware/loader.hpp”或“application/core/”时构建“hardware/loader.o” loader.hpp" 较新。

hardware/loader.o: hardware/loader.hpp application/core/loader.hpp

这可能是您想要研究自动生成的一个领域,因为很容易错过一个依赖项,然后它就不会在标题中获取任何更改。如 cmets 中所述,当您使用 -M 命令行选项构建代码时,gcc/g++ 可以为您生成包含它们的文件,您可以使用 Makefile 中的include 指令添加它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 2020-09-12
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多