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直接从源文件编译为二进制文件的方法,或者您是否知道另一种解决方法?
答案 0 :(得分:0)
使用a custom command或target并使用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
上使用size
或a.out
:Tool 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>")