为什么使用 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
- 使用 CMake 包作为其中一个包脚本。
使用 linker 标志:
target_link_libraries(<tgt> [SHARED|STATIC|...] -lncursesw)
- 或者使用 IMPORTED 库方法(在顶部的代码中展示)。
使用第二种方法的一个主要区别是它只需要一行代码,并且会搜索您编译器的所有预定义包含目录 OS。谁能帮我理解为什么使用 add_library() 方法?
其他相关的 SO 帖子:
CMake imported library behavior
只要您需要为 <tgt>
、and/or 设置依赖项、编译定义、编译标志等属性,扩展为 and/or 的任何目标,您都应该使用 add_library(<tgt> [SHARED|STATIC] IMPORTED)
45=]反对 <tgt>
.
假设您有两个静态库; libfoobar.a
和 libraboof.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 库来管理组件之间的依赖关系。
使用语句的目的是什么:
add_library(<tgt> [SHARED|STATIC] IMPORTED)
根据我的发现,即使您在上面创建了一个导入的库目标,您仍然需要指定实际 .so 或 .a 的具体位置。这至少需要 3 个 cmake 命令才能 link 到可执行文件,编译器仍然不会自动搜索 OS.
上的公共包含目录示例:
从 CMake 文档中,我了解到确实有 3 种方法可以 link 一个库,该库不是作为您总体 application/library 的子项目中的目标构建的。
CMake target_link_libraries() documentation
- 使用 CMake 包作为其中一个包脚本。
使用 linker 标志:
target_link_libraries(<tgt> [SHARED|STATIC|...] -lncursesw)
- 或者使用 IMPORTED 库方法(在顶部的代码中展示)。
使用第二种方法的一个主要区别是它只需要一行代码,并且会搜索您编译器的所有预定义包含目录 OS。谁能帮我理解为什么使用 add_library() 方法?
其他相关的 SO 帖子:
CMake imported library behavior
只要您需要为 <tgt>
、and/or 设置依赖项、编译定义、编译标志等属性,扩展为 and/or 的任何目标,您都应该使用 add_library(<tgt> [SHARED|STATIC] IMPORTED)
45=]反对 <tgt>
.
假设您有两个静态库; libfoobar.a
和 libraboof.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 库来管理组件之间的依赖关系。