UNITY_BUILD¶
3.16 版新增。
当此属性设置为 true 时,目标源文件将被组合成批次以加快编译速度。其实现方式是创建一组统一源文件(unity sources),这些文件通过 #include 指令包含原始源文件,然后编译这些统一源文件,而不是直接编译原始文件。这被称为“统一构建”(Unity build)或“巨型构建”(Jumbo build)。
CMake 提供了不同的算法来选择哪些源文件被组合到一个“桶”(bucket)中。算法的选择由 UNITY_BUILD_MODE 目标属性决定,该属性接受以下值:
BATCH在此模式下,CMake 决定哪些文件被归为一组。UNITY_BUILD_BATCH_SIZE属性控制每个统一源文件中最多可以组合多少个源文件。GROUP在此模式下,每个目标显式指定如何对源文件进行分组。具有相同UNITY_GROUP值的每个源文件将被组合在一起。任何没有此属性的源文件都将单独编译。使用此模式时,UNITY_BUILD_BATCH_SIZE属性将被忽略。
如果没有显式指定 UNITY_BUILD_MODE,CMake 将默认为 BATCH。
以下语言支持统一构建:
C3.16 版新增。
CXX3.16 版新增。
CUDA在版本 3.31 中添加。
OBJC在版本 3.29 中添加。
OBJCXX在版本 3.29 中添加。
对于混合了多种语言源文件的目标,CMake 会对语言进行分离,确保每个生成的统一源文件仅包含单一语言的源文件。
此属性在创建目标时由 CMAKE_UNITY_BUILD 变量的值进行初始化。
注意
项目不应直接将 UNITY_BUILD 属性或其关联的 CMAKE_UNITY_BUILD 变量设置为 true。根据构建机器和所用编译器的能力,启用统一构建可能合适,也可能不合适。因此,此功能应由开发者控制,通常通过开发者选择是否在 cmake(1) 命令行上设置 CMAKE_UNITY_BUILD 变量或其他等效方法来实现。但是,如果已知为某个目标启用统一构建会导致问题,则建议将 UNITY_BUILD 目标属性设置为 false。
ODR(单一定义规则)错误¶
当多个源文件被包含到一个源文件中时(统一构建的做法),可能会导致 ODR 错误。CMake 提供了多种措施来帮助解决此类问题:
任何具有非空
COMPILE_OPTIONS、COMPILE_DEFINITIONS、COMPILE_FLAGS或INCLUDE_DIRECTORIES源属性的源文件,都不会被组合到统一源文件中。任何通过
CXX_SCAN_FOR_MODULES、CXX_SCAN_FOR_MODULES扫描 C++ 模块源文件,或者属于CXX_MODULES文件集的源文件,都不会被组合到统一源文件中。有关详细信息,请参见cmake-cxxmodules(7)。项目可以通过将其
SKIP_UNITY_BUILD_INCLUSION源属性设置为 true,来防止单个源文件被组合到统一源文件中。与为整个目标禁用统一构建相比,这可能是解决特定文件问题的更有效方法。项目可以设置
UNITY_BUILD_UNIQUE_ID,以生成在统一构建中每个文件唯一的有效 C 标识符。这可用于避免统一构建中匿名命名空间引起的问题。UNITY_BUILD_CODE_BEFORE_INCLUDE和UNITY_BUILD_CODE_AFTER_INCLUDE目标属性可用于在每个#include语句前后向统一源文件中注入代码。通过
add_library()、add_executable()或target_sources()等命令添加到目标的源文件的顺序,将在生成的统一源文件中保持不变。这可用于根据UNITY_BUILD_BATCH_SIZE目标属性手动强制执行特定的分组。