如何避免每次重新编译所有文件?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何避免每次重新编译所有文件?相关的知识,希望对你有一定的参考价值。

我有大约20个.cpp文件和多个.h文件。当我编译我做

g++ -std=c++11 main.cpp -o main

在main.cpp中,我从一些前向声明开始,然后包含所有.h和.cpp文件。

因此,在每次编译时,必须重新编译所有文件,这会令人不舒服地放慢速度。我想我需要使用.so和/或.dll文件,以便在将来的编译中,只需要重新编译修改后的代码。我真的不知道该怎么做。你能给我一些建议吗?

答案

您通常希望每个translation unit分别编译,您甚至可以并行编译它们(例如使用make -j,见下文)。

(我猜测并希望你在Linux上并使用GCC作为g++;如果没有,请将此答案适用于您的编译器和操作系统。)

如果你有src1.cpp src2.cpp src3.cpp(每个包含适当的#include directives,可能有一个共同的头文件)你可以将src1.cpp编译成object file src1.o using GCC

g++ -Wall -Wextra -g src1.cpp -c -o src1.o

-Wall -Wextra选项要求所有警告和一些额外的警告,你真的想要它们(改进你的代码不得警告)。 -g选项要求DWARF调试信息(以后可以使用use the gdb debugger,也可以使用valgrind)。 -c选项只需要编译步骤而不需要链接。 -o src1.o表示输出对象文件。

同样,你将src2.cpp编译成src2.o

g++ -Wall -Wextra -g src2.cpp -c -o src2.o

src3.cpp

g++ -Wall -Wextra -g src3.cpp -c -o src3.o

顺便说一句,我更喜欢较短的.cc后缀.cpp。出于基准测试目的,请在编译器中启用optimizations,例如:通过在-O2 -march=native之后添加-g

最后你想link所有你的三个对象文件src1.osrc2.osrc3.omyprog executable

g++ -g src1.o src2.o src3.o -o myprog

您可以添加其他选项,例如链接外部库。

请注意C++14(以及C ++ 11甚至C ++ 17)没有真正的modules(与Ocaml或Go相反)。所以预处理器经常使用,你实际上需要包含很多代码;例如,#include <vector>从我的Linux / Debian桌面上的标准和内部头文件中提取了超过一万行C ++代码。这解释了为什么C ++编译器很慢,因此我建议避免使用太小的C ++文件(例如,只包含几百个C ++行的源文件,包括几个头文件,实际上会从各种内部头文件中提取数十万个C ++行)。我的偏好是在每一个或几千行C ++的.cc(或.cpp)源文件中定义几个相关的函数(也许是类)。

(未来的C ++标准,也许是C++20,可能会为该语言添加模块;但这可能会被推迟......)

我的建议是学习使用GNU makeninja。确实,你需要一个build automation工具。

您当然应该学习如何在命令行上调用编译器。如果你使用invoking GCC,请阅读g++g++的论点顺序非常重要。

您可以使用cmakemeson等工具生成配置文件(适用于makeninja)。但我推荐比cmakemeson更简单的东西(例如用手编码你的Makefile并使用make)。 HereMakefilemake的一个例子。您需要了解您的构建过程。在某些情况下,您可能会在构建期间生成一些(简单的)C ++文件(例如,使用GNU bisonQt moc或您自己的脚本或程序发出一些C ++文件)。

我想我需要使用.so

不必要。 .so文件是共享库中使用的共享对象。见this。如上所述,您可以(并且可能首先,您想要)拥有多个目标文件。您可能稍后考虑制作自己的软件libraries,但这仅适用于可重用的源代码。

要链接外部库,您甚至可能希望使用pkg-config(对于知道它的那些包),它扩展为g++的适当构建选项。

还要了解现有的free software项目的灵感,并研究它们的源代码(包括它们的构建过程)。您可以在Linux发行版中找到它们中的许多,在githubsourceforge和其他地方。

另一答案

...然后我包含所有.h和.cpp文件。

.cpp文件(又名翻译单位)并不包括在内。您应该使用脚本或任何其他类型的构建系统,它们分别编译每个.cpp文件,并将所有生成的.o目标文件链接到可执行程序中。

如果它们不受头文件更改的影响,则可以启用此选项以避免重新编译所有.cpp文件。

以上是关于如何避免每次重新编译所有文件?的主要内容,如果未能解决你的问题,请参考以下文章

使用导航架构操作点击返回按钮时如何避免片段重新创建?

vs2010如何生成单个项目,每次编译所有的项目都全部重新生成了

使用 Roslyn 编译 C# 项目时,如何避免完全重新编译?

是否可以在 OnStop() 回收所有数据并使用保留片段?

如何避免 FragmentManager 重新创建片段?

是否可以在OnStop()上回收所有数据并使用保留片段?