1. 介绍

基于CMake的构建系统通过一系列高级逻辑目标定义了项目的编译和链接规则。每个目标都对应一个具体的可执行文件或库,或者包含自定义命令的特殊目标。在buildsystem中,目标之间的依赖关系通过依赖列表明确,定义了生成顺序和基于变更检测的重新生成规则。

2. 二进制目标

在CMake中,可执行文件和库是通过add_executableadd_library命令定义的。生成的二进制文件会根据目标平台的特定前缀、后缀和扩展名来命名。二进制目标之间的依赖关系通常用target_link_libraries命令来表示。

例如,在定义静态库和可执行文件的示例中:

add_library(archive archive.cpp zip.cpp lzma.cpp)
add_executable(zipapp zipapp.cpp)
target_link_libraries(zipapp archive)

archive 是一个静态库,由archive.cppzip.cpplzma.cpp编译而生成。而zipapp 则是通过编译zipapp.cpp形成的可执行文件,并通过依赖archive静态库进行链接。

2.1 二进制可执行文件

定义可执行目标的关键命令是add_executable

add_executable(mytool mytool.cpp)

CMake会确保在尝试运行命令之前生成该可执行文件。这可以让buildsystem规则在实际运行时有一个可靠的参考。

2.2 二进制库类型

2.2.1 普通库

默认情况下,add_library命令会创建一个静态库,除非指定了具体的库类型。例如,可以通过在命令中添加参数来定义共享库或静态库:

add_library(archive SHARED archive.cpp zip.cpp lzma.cpp) |add_library(archive STATIC archive.cpp zip.cpp lzma.cpp)

通过设置SHAREDSTATIC属性,可以控制库的类型,默认情况下为静态库。使用SHARED属性可以生成共享库,但需要确保库中有可导出的符号(尤其是在Windows环境下)。

2.2.2 Apple Frameworks

对于macOS或iOS框架,可以通过指定特定的目标属性来创建框架包。需要注意的是,共享库通常会用FRAMEWORK属性进行标记,同时也需要设置目标属性。macOS上这一操作通常遵循使用A值的约定,而MACOSX_FRAMEWORK_IDENTIFIER是唯一标识包的键。

add_library(MyFramework SHARED MyFramework.cpp)| 代码块> set_target_properties(MyFramework PROPERTIES FRAMEWORK TRUE FRAMEWORK_VERSION A # Version "A"符合macOS的约定 MACOSX_FRAMEWORK_IDENTIFIER org.cmake.MyFramework)

3. 对象库

OBJECT库类型的作用是将一组对象文件(由编译源文件生成)汇总成一个非存档的集合。这些对象文件可以被用作其他目标的输入,例如通过使用$<TARGET_OBJECTS:name>语法将OBJECT库的内容传递给其他目标。

例如,可以使用add_library命令定义一个OBJECT库:add_library(objs OBJECT objs.cpp)。

这种类型的库在复杂项目中非常有用,可以灵活地管理源文件和编译配置。通过这种方式,可以避免将大量源文件纳入所有目标,从而提高build效率。