CMake 是不是将包含的标头中的所有内容编译到可执行文件中,还是仅将主类中使用的部分编译为可执行文件?

Posted

技术标签:

【中文标题】CMake 是不是将包含的标头中的所有内容编译到可执行文件中,还是仅将主类中使用的部分编译为可执行文件?【英文标题】:Does CMake compile everything in the included headers into the executable or only the parts used in the main class?CMake 是否将包含的标头中的所有内容编译到可执行文件中,还是仅将主类中使用的部分编译为可执行文件? 【发布时间】:2018-12-28 08:53:22 【问题描述】:

我正在编写一个 C 程序,其中可执行文件大小的每一位都很重要。

例如,如果我的程序中只需要 stdlib.h 中的 printf(),是否包含标头实际上会导致该库中的所有内容都被复制到 CMake 编译的可执行文件中?

【问题讨论】:

否,但所有声明都可用。 【参考方案1】:

CMake 只是构建系统生成器。最终进入最终可执行文件的内容由链接器以及您使用的选项决定。典型的链接器只会将他们认为必要的链接到可执行文件中——除非您要求他们链接所有内容。但是,它们可以减少多少足迹是有限度的。

经验法则是,如果你使用 foo.o 中的函数,那么整个 foo.o 都会被链接;因此,如果大小优化是您的目标,最好为每个函数提供自己的编译单元。

您使用的标头没有任何影响,因为标头是在编译时处理的,而不是链接时。

最后但并非最不重要的一点:在标准库的大多数实现中,printf 系列函数是最重量级的函数之一,因此如果您正在计算 bean,请不要使用它们。

【讨论】:

【参考方案2】:

作为一个原则,标头应该是幂等的,也就是说,如果不使用声明,它们不应该影响可执行文件。 stdlib.h 应该只有原型、预处理器宏定义和结构定义之类的东西,它不应该包含可执行代码或变量声明。

标准库代码 由链接器根据需要包含在内。但是,C 运行时库 (RTL) 可能在 DLL 或共享对象中包含此代码,具体取决于您的平台。使用 DLL(或等效的)不会影响可执行文件的大小,但当然会影响所使用的内存。由于 DLL 代码在进程之间共享,因此 C RTL 保留在内存中的情况并不少见,但是,假设动态链接,无论运行的 C 进程数量如何,都只会有一份副本。大多数 C RTL 会为每个进程分配一些内存,但多少取决于编译器/平台。

【讨论】:

以上是关于CMake 是不是将包含的标头中的所有内容编译到可执行文件中,还是仅将主类中使用的部分编译为可执行文件?的主要内容,如果未能解决你的问题,请参考以下文章

在cmake的所有cpp文件中包含c ++标头[重复]

使用 CMake 将资源(例如,着色器代码;图像)嵌入到可执行文件/库中

如何将 yaws 中的“Vary: Accept-Encoding”标头添加到可缓存文件中

CMake:使用自定义工具输出生成标头

C/C++ - 从代码到可执行程序的过程

CMake - 同一项目中的应用程序/库之间的依赖项(标头)