为什么使用 add_library({tgt} IMPORTED) 而不是 target_link_libraries( -l {.so | .a})?

Why use add_library({tgt} IMPORTED) versus target_link_libraries( -l {.so | .a})?

使用语句的目的是什么:

add_library(<tgt> [SHARED|STATIC] IMPORTED)

根据我的发现,即使您在上面创建了一个导入的库目标,您仍然需要指定实际 .so 或 .a 的具体位置。这至少需要 3 个 cmake 命令才能 link 到可执行文件,编译器仍然不会自动搜索 OS.

上的公共包含目录

示例:

从 CMake 文档中,我了解到确实有 3 种方法可以 link 一个库,该库不是作为您总体 application/library 的子项目中的目标构建的。

CMake target_link_libraries() documentation

  1. 使用 CMake 包作为其中一个包脚本。
  2. 使用 linker 标志:

    target_link_libraries(<tgt> [SHARED|STATIC|...] -lncursesw)
    
  3. 或者使用 IMPORTED 库方法(在顶部的代码中展示)。

使用第二种方法的一个主要区别是它只需要一行代码,并且会搜索您编译器的所有预定义包含目录 OS。谁能帮我理解为什么使用 add_library() 方法?


其他相关的 SO 帖子:

CMake imported library behavior

只要您需要为 <tgt>、and/or 设置依赖项、编译定义、编译标志等属性,扩展为 and/or 的任何目标,您都应该使用 add_library(<tgt> [SHARED|STATIC] IMPORTED) 45=]反对 <tgt>.

假设您有两个静态库; libfoobar.alibraboof.a,其中 libfoobar.a 需要 libraboof.a。我们还假设这些库包含一些由 -DSOME_FEATURE.

启用的功能
add_library(raboof STATIC IMPORTED)
set_target_properties(raboof PROPERTIES
    IMPORTED_LOCATION <path-to-libraboof.a>
    INTERFACE_COMPILE_DEFINITIONS "SOME_FEATURE"
)

add_library(foobar STATIC IMPORTED)
set_target_properties(foobar PROPERTIES
    IMPORTED_LOCATION <path-to-libfoobar.a>
    INTERFACE_LINK_LIBRARIES raboof
)

所以当你 link 对抗 libfoobar.a:

add_executable(my_app main.cpp)
target_link_libraries(my_app foobar)

CMake 将确保 link 所有依赖项的顺序正确,并且在这种情况下还会在构建 my_app 时将 -DSOME_FEATURE 附加到编译标志。请注意,由于我们将 libraboof.a 添加为 libfoobar.a 的依赖项,因此 -DSOME_FEATURE 通过传递 属性 添加到 link 针对 libfoobar.a 的任何目标.

如果您在这种情况下不使用 add_library(<tgt> <SHARED|STATIC> IMPORTED),您将不得不自己为每个目标管理任何依赖项和所需的构建选项,这相当 error-prone.

此方法也常用于 Config-modules for multi-component 库来管理组件之间的依赖关系。