add_library

使用指定的源文件向项目添加库。

普通库

add_library(<name> [<type>] [EXCLUDE_FROM_ALL] <sources>...)

添加一个名为 <name> 的库目标,该目标将从命令调用中列出的源文件中构建。

可选的 <type> 指定要创建的库的类型:

STATIC

一个 静态库:目标文件归档,用于链接其他目标。

SHARED

一个 共享库:动态库,可以被其他目标链接并在运行时加载。

MODULE

一个 模块库:插件,不能被其他目标链接,但可以使用类似 dlopen 的功能在运行时动态加载。

如果没有给出 <type>,则默认值为 STATICSHARED,具体取决于 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() 添加,则可以省略它们。

对于 SHAREDMODULE 库,POSITION_INDEPENDENT_CODE 目标属性会自动设置为 ON。一个 SHARED 库可以使用 FRAMEWORK 目标属性来创建一个 macOS Framework。

3.8 版新增: 一个 STATIC 库可以使用 FRAMEWORK 目标属性来创建一个静态 Framework。

如果库不导出任何符号,则不得将其声明为 SHARED 库。例如,一个不导出任何非托管符号的 Windows 资源 DLL 或托管的 C++/CLI DLL 需要是 MODULE 库。这是因为 CMake 期望 SHARED 库在 Windows 上始终有一个相关的导入库。

默认情况下,库文件将创建在与调用命令的源目录相对应的构建树目录中。有关更改此位置的详细信息,请参阅 ARCHIVE_OUTPUT_DIRECTORYLIBRARY_OUTPUT_DIRECTORYRUNTIME_OUTPUT_DIRECTORY 目标属性的文档。有关更改最终文件名中 <name> 部分的详细信息,请参阅 OUTPUT_NAME 目标属性的文档。

有关定义构建系统属性的更多信息,请参阅 cmake-buildsystem(7) 手册。

另请参阅 HEADER_FILE_ONLY,了解当某些源文件经过预处理,而您希望从 IDE 中访问原始源文件时该怎么做。

3.30 版已更改: 在不支持共享库的平台上,add_library 现在会在创建 SHARED 库的调用时失败,而不是像以前那样自动将其转换为 STATIC 库。请参阅策略 CMP0164

目标库

add_library(<name> OBJECT <sources>...)

添加一个 目标库 来编译源文件,而不将其目标文件归档或链接到库中。

add_libraryadd_executable() 创建的其他目标可以使用 $<TARGET_OBJECTS:objlib> 形式的表达式作为源来引用目标文件,其中 objlib 是目标库的名称。例如:

add_library(... $<TARGET_OBJECTS:objlib> ...)
add_executable(... $<TARGET_OBJECTS:objlib> ...)

将把 objlib 的目标文件及其自己的源文件编译的目标文件一起包含到库和可执行文件中。目标库只能包含编译文件、头文件以及不会影响普通库链接的文件(例如 .txt)。它们可以包含生成此类源文件的自定义命令,但不能包含 PRE_BUILDPRE_LINKPOST_BUILD 命令。某些原生构建系统(如 Xcode)可能不兼容仅包含目标文件的目标,因此请考虑向任何引用 $<TARGET_OBJECTS:objlib> 的目标添加至少一个实际的源文件。

3.12 版新增: 可以使用 target_link_libraries() 来链接目标库。

接口库

add_library(<name> INTERFACE)

添加一个 接口库 目标,该目标可以指定依赖项的使用要求,但不会编译源文件,也不会在磁盘上生成库文件。

没有源文件的接口库不会包含在生成的构建系统中作为目标。但是,可以为其设置属性,并且可以将其安装和导出。通常,使用以下命令将 INTERFACE_* 属性填充到接口目标上:

然后像任何其他目标一样,将其用作 target_link_libraries() 的参数。

3.15 版新增: 接口库可以拥有 PUBLIC_HEADERPRIVATE_HEADER 属性。通过这些属性指定的头文件可以使用 install(TARGETS) 命令进行安装。

add_library(<name> INTERFACE [EXCLUDE_FROM_ALL] <sources>...)

3.19 版本新增。

添加一个具有源文件的 接口库 目标(除了上面 签名 记录的使用要求和属性之外)。源文件可以直接列在 add_library 调用中,或稍后通过使用 PRIVATEPUBLIC 关键字的 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。

导入库

add_library(<name> <type> IMPORTED [GLOBAL])

添加一个名为 <name>导入库目标。该目标名称可以像项目中构建的任何目标一样被引用,但默认情况下它仅在创建它的目录及其下方可见。

<type> 必须是以下之一:

STATICSHAREDMODULEUNKNOWN

引用项目外部的库文件。 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 上尤其有用,因为静态库和 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> 不会作为生成系统的构建目标出现。 <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 目标不能被安装或导出。

另请参阅