add_library¶
使用指定的源文件将库添加到项目中。
普通库¶
- add_library(<name> [<type>] [EXCLUDE_FROM_ALL] <sources>...)¶
添加一个名为
<name>的库目标,由命令调用中列出的源文件构建。可选参数
<type>指定了要创建的库类型:STATIC静态库 (Static Library):目标文件归档,用于链接其他目标。
SHARED共享库 (Shared Library):一种动态库,可由其他目标链接并在运行时加载。
MODULE模块库 (Module Library):一种插件,不可被其他目标链接,但可在运行时使用类似于 dlopen 的功能动态加载。
如果未指定
<type>,则默认值为STATIC或SHARED,具体取决于BUILD_SHARED_LIBS变量的值。选项包括
EXCLUDE_FROM_ALL自动设置
EXCLUDE_FROM_ALL目标属性。有关详细信息,请参阅该目标属性的文档。
<name> 对应于逻辑目标名称,在项目中必须全局唯一。实际生成的库文件名根据原生平台的约定进行构建(例如 lib<name>.a 或 <name>.lib)。
版本 3.1 新增:add_library 的源参数可以使用语法为 $<...> 的“生成器表达式”。请参阅 cmake-generator-expressions(7) 手册获取可用表达式。
版本 3.11 新增:如果稍后使用 target_sources() 添加源文件,则可以省略此处源文件。
对于 SHARED 和 MODULE 库,目标属性 POSITION_INDEPENDENT_CODE 会自动设置为 ON。共享库(SHARED)可以使用 FRAMEWORK 目标属性来创建 macOS 框架。
版本 3.8 新增:静态库(STATIC)可以使用 FRAMEWORK 目标属性来创建静态框架。
如果库不导出任何符号,则不得将其声明为 SHARED 库。例如,不导出任何非托管符号的 Windows 资源 DLL 或托管 C++/CLI DLL 必须作为 MODULE 库。这是因为 CMake 期望 Windows 上的 SHARED 库始终具有关联的导入库。
默认情况下,库文件将在构建树中与调用该命令的源树目录相对应的目录下创建。请参阅 ARCHIVE_OUTPUT_DIRECTORY、LIBRARY_OUTPUT_DIRECTORY 和 RUNTIME_OUTPUT_DIRECTORY 目标属性的文档以更改此位置。请参阅 OUTPUT_NAME 目标属性的文档以更改最终文件名的 <name> 部分。
有关定义构建系统属性的更多信息,请参阅 cmake-buildsystem(7) 手册。
如果某些源文件是经过预处理的,且希望在 IDE 中能够访问原始源文件,请参阅 HEADER_FILE_ONLY 了解如何操作。
版本 3.30 更改:在不支持共享库的平台上,add_library 现在会在尝试创建 SHARED 库时失败,而不是像以前那样自动将其转换为 STATIC 库。请参阅策略 CMP0164。
对象库 (Object Libraries)¶
由 add_library 或 add_executable() 创建的其他目标可以使用 $<TARGET_OBJECTS:objlib> 形式的表达式引用这些对象,其中 objlib 是对象库的名称。例如:
add_library(... $<TARGET_OBJECTS:objlib> ...)
add_executable(... $<TARGET_OBJECTS:objlib> ...)
将把 objlib 的目标文件包含在库和可执行文件中,并与它们各自编译的源文件一起链接。对象库只能包含可编译的源文件、头文件以及不会影响普通库链接的其他文件(例如 .txt)。它们可以包含生成此类源文件的自定义命令,但不能包含 PRE_BUILD、PRE_LINK 或 POST_BUILD 命令。某些原生构建系统(例如 Xcode)可能不喜欢仅包含目标文件的库,因此请考虑向引用 $<TARGET_OBJECTS:objlib> 的任何目标添加至少一个实际的源文件。
版本 3.12 新增:对象库可以使用 target_link_libraries() 进行链接。
接口库 (Interface Libraries)¶
- add_library(<name> INTERFACE)¶
添加一个 接口库 目标,它可以指定依赖项的使用要求,但不编译源文件,也不会在磁盘上生成库工件。
没有源文件的接口库不会作为目标包含在生成的构建系统中。但是,可以为其设置属性,并且可以安装和导出它。通常,接口目标上的
INTERFACE_*属性是通过以下命令填充的:然后它像任何其他目标一样作为参数传递给
target_link_libraries()。版本 3.15 新增:接口库可以具有
PUBLIC_HEADER和PRIVATE_HEADER属性。这些属性指定的头文件可以使用install(TARGETS)命令安装。
- add_library(<name> INTERFACE [EXCLUDE_FROM_ALL] <sources>...)¶
3.19 版本新增。
添加一个带有源文件的 接口库 目标(除了上述签名文档中的使用要求和属性之外)。源文件可以直接在
add_library调用中列出,也可以稍后通过使用PRIVATE或PUBLIC关键字调用target_sources()来添加。如果一个接口库有源文件(即设置了
SOURCES目标属性)或头文件集(即设置了HEADER_SETS目标属性),它将作为构建目标出现在生成的构建系统中,非常类似于由add_custom_target()命令定义的目标。它不编译任何源文件,但包含由add_custom_command()命令创建的自定义命令的构建规则。选项包括
EXCLUDE_FROM_ALL自动设置
EXCLUDE_FROM_ALL目标属性。详细信息请参阅该目标属性的文档。
注意
在大多数出现
INTERFACE关键字的命令签名中,其后列出的项仅成为该目标使用要求的一部分,而不是目标自身设置的一部分。然而,在add_library的此签名中,INTERFACE关键字仅指库类型。在add_library调用中其后列出的源文件对于该接口库而言是PRIVATE的,不会出现在其INTERFACE_SOURCES目标属性中。
- add_library(<name> INTERFACE SYMBOLIC)¶
版本 4.2 中添加。
添加一个符号化的 接口库 目标。符号化接口库对于表示包中的可选组件或功能非常有用。它们没有使用要求,不编译源文件,也不在磁盘上产生库工件,但可以被导出和安装。它们还可以通过常规的
if(TARGET)子命令进行存在性测试。符号化接口库可以用作可链接目标,以强制依赖项中存在可选组件。例如,如果库
libgui可能提供也可能不提供功能widget,则消费者包可以链接widget以表示它要求该组件可用。这允许声明所需组件的find_package()调用通过链接相应的符号化目标来验证。符号化接口库设置了
SYMBOLIC目标属性为 true。
导入库 (Imported Libraries)¶
- add_library(<name> <type> IMPORTED [GLOBAL])¶
添加一个名为
<name>的 IMPORTED 库目标。目标名称可以像项目内构建的任何目标一样被引用,区别在于默认情况下它仅在创建它的目录及其子目录中可见。<type>必须是以下之一:STATIC,SHARED,MODULE,UNKNOWN引用位于项目之外的库文件。
IMPORTED_LOCATION目标属性(或其配置特定变体IMPORTED_LOCATION_<CONFIG>)指定了磁盘上主库文件的位置。对于大多数非 Windows 平台上的
SHARED库,主库文件是链接器和动态加载器使用的.so或.dylib文件。如果引用的库文件具有SONAME(或在 macOS 上,具有以@rpath/开头的LC_ID_DYLIB),则应在该字段中设置IMPORTED_SONAME目标属性的值。如果引用的库文件没有SONAME,但平台支持它,则应设置IMPORTED_NO_SONAME目标属性。对于 Windows 上的
SHARED库,IMPORTED_IMPLIB目标属性(或其配置特定变体IMPORTED_IMPLIB_<CONFIG>)指定磁盘上 DLL 导入库文件(.lib或.dll.a)的位置,而IMPORTED_LOCATION是.dll运行时库的位置(它是可选的,但TARGET_RUNTIME_DLLS生成器表达式需要它)。
额外的使用要求可以在
INTERFACE_*属性中指定。UNKNOWN库类型通常仅用于 Find 模块 的实现中。它允许在无需确切知道库类型的情况下使用已导入库的路径(通常使用find_library()命令找到)。这在 Windows 上特别有用,因为静态库和 DLL 的导入库具有相同的文件扩展名。OBJECT引用位于项目之外的一组对象文件。
IMPORTED_OBJECTS目标属性(或其配置特定变体IMPORTED_OBJECTS_<CONFIG>)指定了磁盘上目标文件的位置。额外的使用要求可以在INTERFACE_*属性中指定。INTERFACE不引用磁盘上的任何库或对象文件,但可以在
INTERFACE_*属性中指定使用要求。
选项包括
GLOBAL使目标名称全局可见。
不会生成构建已导入目标的规则,且 IMPORTED 目标属性为 True。已导入库对于诸如 target_link_libraries() 等命令的方便引用非常有用。
有关已导入库的详细信息通过设置名称以 IMPORTED_ 和 INTERFACE_ 开头的属性来指定。有关更多信息,请参阅此类属性的文档。
别名库 (Alias Libraries)¶
- add_library(<name> ALIAS <target>)¶
创建一个 别名目标,以便
<name>可用于在后续命令中引用<target>。<name>不会作为 make 目标出现在生成的构建系统中。<target>不能是ALIAS。
版本 3.11 新增:ALIAS 可以指向 GLOBAL 已导入目标。
版本 3.18 新增:ALIAS 可以指向非 GLOBAL 的已导入目标。此类别名的作用域限于创建它的目录及其子目录。ALIAS_GLOBAL 目标属性可用于检查别名是否为全局。
ALIAS 目标可以用作可链接目标,也可以用作从中读取属性的目标。它们还可以通过常规的 if(TARGET) 子命令进行存在性测试。<name> 不能用于修改 <target> 的属性,也就是说,它不能用作 set_property()、set_target_properties()、target_link_libraries() 等的运算对象。ALIAS 目标不能被安装或导出。