使用Makefile的大型C ++项目有什么好的目录结构?
这就是我目前的目录结构:
lib/ (class implementations *.cpp)
include/ (class definitions *.h)
tests/ (main.cpp for quick tests)
现在,我不确定我的Makefile应该是什么样子......当.cpp文件和.h文件不在同一目录中时,它似乎不起作用。任何人都可以指向一个带有Makefile的公共目录结构,以便我不重新发明轮子吗?
答案 0 :(得分:57)
分离.h文件的.cpp并不总是一个好的解决方案。通常我在将它们用作库时将它们分开(include中的公共头和包含源代码的私有头)。
如果它是一个库,这个结构就可以了。
lib/ (class implementations *.cpp .h)
include/ (class definitions *.h) <- Only those to be installed in your system
tests/ (main.cpp for quick tests)
doc/ (doxygen or any kind of documentation)
如果是应用程序
src/ (source for the application)
lib/ (source for the application library *.cpp *.hpp)
include/ (interface for the library *.h)
tests/ (main.cpp for quick tests) <- use cppunit for this part
doc/ (doxygen or any kind of documentation)
使用标志-I $(PROJECT_BASE)/ include指定编译的包含路径
如果它是一个大项目,使用 autoconf / automake 或 cmake 等工具构建所有内容可能会很好。它将缓解发展。
答案 1 :(得分:12)
如果您有许多源文件,那么进一步细分源目录也是一个好主意。例如,一个用于应用程序核心功能的子目录,一个用于GUI的子目录等。
src/core
src/database
src/effects
src/gui
...
这样做也会强制您避免“模块”之间不必要的关系,这是良好和可重用代码的先决条件。
答案 2 :(得分:12)
没有特定或必需的目录结构。
你可以随意设置它。你的问题很容易解决。只需指示Makefile查看子目录或将编译对象放入子目录中,而不是仅使用当前目录。
您只需在Makefile路径中使用:
%.o : %.cpp
替换为
bin/%.o : %.cpp
因此,它将检查目录bin
中的二进制文件是否存在等等,您可以将其应用于编译文件的位置。
有多种方法可以添加/删除/修改源文件和目标文件的路径。
查看gnu make manual,特别是 8.3文件名函数部分,以及 8.2字符串替换和分析函数之前的部分。
您可以执行以下操作:
从当前目录中的源文件列表中获取对象列表:
OBJ = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
输出:
Application.o Market.o ordermatch.o
如果二进制对象位于子目录bin
中,但源代码位于当前目录中,则可以将前缀bin
应用于生成的目标文件:
OBJ = $(addprefix bin/,$(patsubst %.cpp, %.o, $(wildcard *.cpp)))
输出:
bin/Application.o bin/Market.o bin/ordermatch.o
等等。
答案 3 :(得分:6)
没有“良好的目录结构”。选择一个你感觉舒适的结构并坚持下去。有些人喜欢将源文件(头文件和实现文件)放在src/
目录中,因此项目的根目录只有一个makefile,一个自述文件和其他内容。有些人喜欢将帮助库放在lib/
目录下,在test/
或src/test/
下进行单元测试,在doc/
下进行文档编制。
我还没有听说有人将头文件和实现文件分成两个不同的目录。我个人不喜欢将文件分成很多目录。我通常将所有源代码放在一个目录中,将所有文档放在另一个目录中。如果我依赖于优秀的搜索工具,则不需要复杂的目录结构。
make可以处理makefile所在的结构与源不同的目录。唯一的事情是它将从makefile的目录中调用规则 - 编译器通常在编译某个子目录中的源代码时没有问题。您不必在#include
中指定相对路径;只需使用编译器标志(gcc的-I
标志等)指定包含路径。
答案 4 :(得分:4)
对于在2020年发现此问题的人,鲍里斯·科尔帕科夫(Boris Kolpackov)提出了另一种现代合理的C ++“规范项目结构”构想:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1204r0.html
简短-没有include/
和src/
拆分。所有标题,源代码,模块和单元测试都放在一个目录中。可以通过移至<name>/<name>/details/
子目录来将实现详细信息与公共API分开。
<name>/
├── <name>/
│ ├── headers...
│ ├── sources...
│ ├── modules...
│ └── unit tests...
└── tests/
├── functional_test1/
├── functional_test2/
├── integration_test1/
├── integration_test2/
└── ...
答案 5 :(得分:3)
如果您在阅读Recursive Make Considered Harmful之前没有看过它。
短,短版本:虽然很常见,递归制作习惯不是最优的,随着项目变得越来越大,越来越复杂,越来越糟糕。提出了另一种选择。
答案 6 :(得分:0)
这是一个古老的问题。但是您可以将“干草叉项目”视为一般指南。