我们有使用gcc和make文件的项目。项目还包含一个大的子项目(SDK)和许多使用该SDK和一些共享框架的相对较小的子项目。
我们使用预编译头,但这有助于重新编译更快。
是否有任何已知的技术和工具可以帮助构建时优化?或者您可能知道一些关于这个或相关主题的文章/资源?
答案 0 :(得分:15)
您可以从两个方面解决问题:重构代码以降低编译器看到的复杂性,或加快编译器执行速度。
无需触摸代码,您可以为其添加更多编译功能。使用ccache避免重新编译已编译的文件和distcc以在更多计算机之间分配构建时间。使用make -j,其中N是核心数量+ 1如果在本地编译,或者更大数量用于分布式构建。该标志将并行运行多个编译器。
重构代码。更喜欢前向声明包括(简单)。尽可能地去耦以避免依赖(使用PIMPL习语)。
模板实例化很昂贵,它们在每个使用它们的编译单元中重新编译。如果您可以重构模板以转发声明它们,然后只在一个编译单元中实例化它们。
答案 1 :(得分:7)
使用make
我能想到的最好的是-j
选项。这告诉make
并行运行尽可能多的作业:
make -j
如果要将并发作业数限制为 n ,可以使用:
make -j
n
确保依赖项是正确的,因此make
不会运行它不需要的作业。
要考虑的另一件事是gcc
对-O
切换的优化。您可以指定各种级别的优化。优化越高,编译和链接时间越长。我使用的项目需要2分钟才能与-O3
相关联,而半分钟则与-O1
相关联。你应该确保你没有超出你需要的优化。您可以在不对开发构建进行优化的情况下构建,也可以针对部署构建进行优化。
使用调试信息(gcc -g
)进行编译可能会增加可执行文件的大小,并可能影响您的构建时间。如果您不需要它,请尝试将其删除以查看它是否会影响您。
链接的类型(静态与动态)应该有所不同。据我所知,静态链接需要更长时间(虽然我可能在这里错了)。您应该看看这是否会影响您的构建。
答案 2 :(得分:4)
从项目的描述中我猜你每个目录都有一个Makefile,并且使用recursive make很多。在这种情况下,来自"Recursive Make Considered Harmful"的技术应该非常有用。
答案 3 :(得分:2)
答案 4 :(得分:2)
此外,您可能希望保持源代码文件尽可能小/自包含/可行,即在一个巨大的单个目标文件中更喜欢许多较小的目标文件。
这也有助于避免不必要的重新编译,此外,您可以为每个源代码目录或模块创建一个带有目标文件的静态库,基本上允许编译器尽可能多地重用以前编译的代码。
在之前的任何响应中都没有提到的其他东西,正在使符号链接尽可能“私有”,即如果不必是代码,则更喜欢代码的静态链接(函数,变量)外部可见。
此外,您可能还希望使用GNU gold linker much more efficient来编译ELF目标的C ++代码。
基本上,我建议您仔细分析构建过程并检查花费最多的时间,这将为您提供有关如何优化构建过程或项目源代码结构的一些提示。
答案 5 :(得分:2)
您可以考虑切换到不同的构建系统(显然不适用于所有人),例如SCons。 SCons比make更聪明。它会自动扫描标头依赖项,因此您始终拥有最小的重建依赖项集。通过将行Decider('MD5-timestamp')
添加到SConstruct文件,SCons将首先查看文件的时间戳,如果它比以前构建的时间戳更新,它将使用文件的MD5来确保实际改变了一些事这不仅适用于源文件,也适用于目标文件。这意味着,例如,如果您更改注释,则无需重新链接。
头文件的自动扫描也确保了我永远不必输入scons --clean。它总能做正确的事。
答案 6 :(得分:0)
如果你有一台带有开发者机器的局域网,也许你应该尝试实施分布式编译器解决方案,例如distcc。
如果构建过程中的所有时间都花在分析依赖关系或执行单个串行任务上,那么这可能无济于事。对于将许多源文件编译成目标文件的原始危机,并行构建显然有助于Nathan建议(在一台机器上)。跨多台机器并行化可以更进一步。
答案 7 :(得分:0)
http://ccache.samba.org/加快了时间。
我从事中型项目,这是我们加快编译时间的唯一方法。
答案 8 :(得分:0)
如果您可以访问多台计算机,则可以使用distcc分布式编译器来缩短构建时间。 这是来自IBM developerWorks的一篇关于distcc的文章以及如何使用它: http://www.ibm.com/developerworks/linux/library/l-distcc.html
减少构建时间的另一种方法是使用预编译头。这是一个starting point for gcc。
如果您的机器有多个cpu / core(2x核心/ cpus就好了),也不要忘记在使用make构建时使用-j。
答案 9 :(得分:0)
使用小文件可能并不总是一个好建议。磁盘的扇区大小为32或64K,文件至少占用一个扇区。因此,1024个3K大小的文件(内部小代码)实际上将在磁盘上占用32或64兆,而不是预期的3兆。 32/64 meg需要驱动器读取。如果文件分散在磁盘上,则可以在寻道时间内增加读取时间。这显然有助于磁盘缓存,达到极限。预编译的标题也可以很好地帮助减轻这一点。
因此,在充分尊重编码指南的情况下,将每个strcuct,typedef或实用程序类放入单独的文件中是没有意义的。