cmake可以直接从源文件编译成二进制文件吗?

时间:2015-06-22 18:37:27

标签: gcc cmake

cmake首先将.c文件编译为.o文件,然后将它们链接在一起:

gcc a.c -o a.c.o
gcc b.c -o b.c.o
gcc c.c -o c.c.o
gcc a.c.o b.c.o c.c.o -o a.out

而不是直接从源文件编译为二进制文件:

gcc a.c b.c c.c -o a.out

通常我会使用链接时优化(-flto)来允许编译器进行跨二进制优化,但不幸的是,我必须使用不支持链接时的旧编译器 - 优化

这意味着,如果我使用cmake,我的二进制文件比直接从源文件编译为二进制文件要大3倍,因为缺少交叉二进制优化

您是否知道将cmake直接从源文件编译为二进制文件的方法,或者您是否知道另一种解决方法?

2 个答案:

答案 0 :(得分:0)

使用a custom commandtarget并使用COMMAND参数来构建源文件。

答案 1 :(得分:0)

根据我的经验,如果您在使用CMake时遇到二进制大3倍的问题,则需要查看完整的构建过程。

首先检查编译器/链接器选项是否完全相同:Using CMake with GNU Make: How can I see the exact commands?

如果它们都匹配,你可以 - 找出哪些部分实际上更大 - 比较CMake和非CMake情况下输出的地图文件。在CMake中,您需要将-Wl,-Map=<TARGET_NAME>.map添加到链接器标志。如何添加链接器标志,请参阅:CMake: How to set the LDFLAGS in CMakeLists.txt?

或者在nm上使用sizea.outTool to analyze size of ELF sections and symbol

最后,您尝试激活链接器的其他优化选项(即使是较旧的编译器也应支持通用-O选项)。另见:Remove useless files, includes, global variables and functions in C++

.c vs .o和Windows上的GNU

将源文件或目标文件提供给gcc之间应该没有区别。但如果你在Windows上使用GNU工具链,你可能会偶然发现Windows-GNU.cmake中的一种解决方法:

# The gcc/collect2/ld toolchain does not use response files
# internally so we cannot pass long object lists.  Instead pass
# the object file list in a response file to the archiver to put
# them in a temporary archive.  Hand the archive to the linker.

此解决方法确实导致:

gcc a.c -o a.c.o
gcc b.c -o b.c.o
gcc c.c -o c.c.o
rm objects.a
ar cr a.c.o b.c.o c.c.o -o objects.a
gcc objects.a -o a.out

问题是中间的ar电话。如果CMake将直接获取.o文件,那就没问题了。

您可以在CMAKE_C_LINK_EXECUTABLE命令后将project()恢复为默认值来覆盖此变通方法:

set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET> <LINK_LIBRARIES>")

其他参考:CMake: use a custom linker