添加_库¶
使用指定的源文件将库添加到项目中。
普通图书馆¶
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[<source>...])
添加一个名为 <name>
的库目标,以从命令调用中列出的源文件构建。 <name>
对应于逻辑目标名称,并且在项目中必须是全局唯一的。构建的库的实际文件名是根据本机平台的约定构建的(例如 lib<name>.a
或 <name>.lib
)。
在 3.1 版本加入: add_library
的源参数可以使用语法为``$<...>`` 的“生成器表达式”。请参阅 cmake-generator-expressions(7)
手册了解可用的表达式。
在 3.11 版本加入: 如果稍后使用 target_sources()
添加源文件,则可以省略它们。
可以给出 STATIC
、SHARED
或 MODULE
来指定要创建的库的类型。 STATIC
库是目标文件的存档,供链接其他目标时使用。 SHARED
库动态链接并在运行时加载。 MODULE
库是不链接到其他目标但可以在运行时使用类似 dlopen 的功能动态加载的插件。如果没有明确给出类型,则类型是 STATIC
或 SHARED
取决于变量的当前值 BUILD_SHARED_LIBS
是否为 ON
。对于 SHARED
和 MODULE
库, POSITION_INDEPENDENT_CODE
目标属性自动设置为 ON
。 SHARED
库可以用 FRAMEWORK
目标属性标记以创建 macOS 框架。
在 3.8 版本加入: STATIC
库可以用 FRAMEWORK
目标属性标记以创建静态框架。
如果库不导出任何符号,则不得将其声明为“共享”库。例如,Windows 资源 DLL 或不导出非托管符号的托管 C++/CLI DLL 需要是一个“MODULE”库。这是因为 CMake 期望 SHARED
库在 Windows 上始终具有关联的导入库。
默认情况下,库文件将在与调用命令的源树目录相对应的构建树目录中创建。请参阅 ARCHIVE_OUTPUT_DIRECTORY
、 LIBRARY_OUTPUT_DIRECTORY
和 RUNTIME_OUTPUT_DIRECTORY
目标属性的文档以更改此位置。请参阅 OUTPUT_NAME
目标属性的文档以更改最终文件名的 <name>
部分。
如果给出 EXCLUDE_FROM_ALL
,则将在创建的目标上设置相应的属性。有关详细信息,请参阅 EXCLUDE_FROM_ALL
目标属性的文档。
有关定义构建系统属性的更多信息,请参阅 cmake-buildsystem(7)
手册。
另请参阅 HEADER_FILE_ONLY
了解如果对某些源进行了预处理,并且您希望可以从 IDE 中访问原始源,该怎么做。
对象库¶
add_library(<name> OBJECT [<source>...])
创建一个 Object Library。目标库编译源文件但不将它们的目标文件存档或链接到库中。相反,由 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 版本加入: 对象库可以链接到:command:target_link_libraries。
接口库¶
add_library(<name> INTERFACE)
创建一个 Interface Library。 INTERFACE
库目标不会编译源代码,也不会在磁盘上生成库工件。但是,它可能设置了属性,并且可以安装和导出。通常,使用以下命令在接口目标上填充 INTERFACE_*
属性:
target_link_libraries(接口)()
,target_link_options(接口)()
,target_include_directories(接口)()
,target_compile_options(接口)()
,target_sources(接口)()
,
然后它像任何其他目标一样用作 target_link_libraries()
的参数。
使用上述签名创建的接口库本身没有源文件,也不会作为目标包含在生成的构建系统中。
在 3.15 版本加入: 接口库可以具有 PUBLIC_HEADER
和 PRIVATE_HEADER
属性。可以使用 install(TARGETS)
命令安装由这些属性指定的标头。
在 3.19 版本加入: 可以使用源文件创建接口库目标:
add_library(<name> INTERFACE [<source>...] [EXCLUDE_FROM_ALL])
源文件可以直接在 add_library
调用中列出,或者稍后通过使用 PRIVATE
或 PUBLIC
关键字调用:command:target_sources 添加。
如果接口库有源文件(即设置了 SOURCES
目标属性),或设置了头文件(即设置了 HEADER_SETS
目标属性),它将作为构建出现在生成的构建系统中target 很像 add_custom_target()
命令定义的目标。它不编译任何源代码,但包含由 add_custom_command()
命令创建的自定义命令的构建规则。
备注
在大多数出现 INTERFACE
关键字的命令签名中,其后列出的项目仅成为该目标使用要求的一部分,而不是目标自身设置的一部分。然而,在 add_library
的签名中,INTERFACE
关键字仅指库类型。在 add_library
调用中它后面列出的源是接口库的 PRIVATE
并且不会出现在它的 INTERFACE_SOURCES 目标属性中。
导入库¶
add_library(<name> <type> IMPORTED [GLOBAL])
创建一个名为 <name>
的 IMPORTED 库目标。没有生成规则来构建它,并且 IMPORTED
目标属性是 True
。目标名称在其创建目录及以下目录中具有范围,但 GLOBAL
选项扩展了可见性。它可以像项目中构建的任何目标一样被引用。 IMPORTED
库可用于方便地从 target_link_libraries()
等命令中引用。有关导入库的详细信息通过设置名称以“IMPORTED_”和“INTERFACE_”开头的属性来指定。
<type>
必须是以下之一:
静态
,共享
,模块
,未知
引用位于项目外部的库文件。
IMPORTED_LOCATION
目标属性(或其每个配置变体IMPORTED_LOCATION_<CONFIG>
)指定主库文件在磁盘上的位置:对于大多数非 Windows 平台上的“共享”库,主库文件是链接器和动态加载器使用的“.so”或“.dylib”文件。如果引用的库文件有一个
SONAME``(或者在 macOS 上,有一个 ``LC_ID_DYLIB
从@rpath/
开始),该字段的值应该在IMPORTED_SONAME 中设置
目标属性。如果引用的库文件没有SONAME
,但平台支持它,则应设置IMPORTED_NO_SONAME
目标属性。对于 Windows 上的
SHARED
库,IMPORTED_IMPLIB
目标属性(或其每个配置变体:prop_tgt:IMPORTED_IMPLIB_<CONFIG>)指定 DLL 导入库文件 (. lib
或.dll.a
) 在磁盘上,而IMPORTED_LOCATION
是.dll
运行时库的位置(并且是可选的,但TARGET_RUNTIME_DLLS 需要
生成器表达式)。
额外的使用要求可以在
INTERFACE_*
属性中指定。UNKNOWN
库类型通常仅用于 查找模块 的实现。它允许使用导入库的路径(通常使用find_library()
命令找到),而不必知道它是什么类型的库。这在 Windows 上特别有用,其中静态库和 DLL 的导入库都具有相同的文件扩展名。对象
引用位于项目外部的一组目标文件。
IMPORTED_OBJECTS
目标属性(或其每个配置变体IMPORTED_OBJECTS_<CONFIG>
)指定目标文件在磁盘上的位置。额外的使用要求可以在INTERFACE_*
属性中指定。界面
不引用磁盘上的任何库或对象文件,但可以在
INTERFACE_*
属性中指定使用要求。
有关更多信息,请参阅 IMPORTED_*
和 INTERFACE_*
属性的文档。
别名库¶
add_library(<name> ALIAS <target>)
创建一个 Alias Target,这样 <name>
可用于在后续命令中引用 <target>
。 <name>
不会作为生成目标出现在生成的构建系统中。 <target>
可能不是 ALIAS
。
在 3.11 版本加入: ALIAS
可以针对 GLOBAL
Imported Target
在 3.18 版本加入: ALIAS
可以针对非``GLOBAL`` 导入目标。此类别名的范围限于创建它的目录及以下目录。 ALIAS_GLOBAL
目标属性可用于检查别名是否为全局别名。
ALIAS
目标可以用作可链接的目标和从中读取属性的目标。也可以使用常规的 if(TARGET) 子命令来测试它们是否存在。 <name>
不得用于修改 <target>
的属性,也就是说,它不得用作 set_property()
、 set_target_properties()
的操作数, target_link_libraries()
等 ALIAS
目标可能无法安装或导出。