add_library¶
使用指定的源文件向项目添加库。
普通库¶
- add_library(<name> [<type>] [EXCLUDE_FROM_ALL] <sources>...)¶
添加一个名为
<name>
的库目标,该目标将从命令调用中列出的源文件构建。可选的
<type>
指定要创建的库的类型STATIC
静态库:对象文件的归档,用于链接其他目标时使用。
SHARED
共享库:一种动态库,可以被其他目标链接并在运行时加载。
MODULE
模块库:一种插件,可能不会被其他目标链接,但可以使用类似 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 期望 SHARED
库始终在 Windows 上具有关联的导入库。
默认情况下,库文件将在构建树目录中创建,该目录对应于调用命令的源代码树目录。 有关更改此位置的信息,请参阅 ARCHIVE_OUTPUT_DIRECTORY
、LIBRARY_OUTPUT_DIRECTORY
和 RUNTIME_OUTPUT_DIRECTORY
目标属性的文档。 有关更改最终文件名的 <name>
部分的信息,请参阅 OUTPUT_NAME
目标属性的文档。
有关定义构建系统属性的更多信息,请参阅 cmake-buildsystem(7)
手册。
另请参阅 HEADER_FILE_ONLY
,了解在某些源文件是预处理的情况下,以及您希望从 IDE 中访问原始源文件时该怎么做。
在 3.30 版本中变更: 在不支持共享库的平台上,add_library
现在在创建 SHARED
库的调用时会失败,而不是像以前那样自动将其转换为 STATIC
库。 请参阅策略 CMP0164
。
对象库¶
由 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()
链接。
接口库¶
- 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> <type> IMPORTED [GLOBAL])¶
添加一个名为
<name>
的 导入库目标。 目标名称可以像项目内构建的任何目标一样被引用,但默认情况下,它仅在创建它的目录及其下方的目录中可见。<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 Modules 的实现中使用。 它允许使用导入库的路径(通常使用find_library()
命令找到),而无需知道它是哪种类型的库。 这在 Windows 上尤其有用,在 Windows 上,静态库和 DLL 的导入库都具有相同的文件扩展名。OBJECT
引用项目外部的一组对象文件。
IMPORTED_OBJECTS
目标属性(或其按配置变量IMPORTED_OBJECTS_<CONFIG>
)指定磁盘上对象文件的位置。 其他用法要求可以在INTERFACE_*
属性中指定。INTERFACE
不引用磁盘上的任何库或对象文件,但可以在
INTERFACE_*
属性中指定用法要求。
选项有
GLOBAL
使目标名称全局可见。
不会生成用于构建导入目标的规则,并且 IMPORTED
目标属性为 True
。 导入库对于从诸如 target_link_libraries()
之类的命令中方便地引用非常有用。
有关导入库的详细信息通过设置名称以 IMPORTED_
和 INTERFACE_
开头的属性来指定。 有关更多信息,请参阅此类属性的文档。
别名库¶
- 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
目标可能无法安装或导出。