在CMake中,target_link_libraries
命令用于链接库到目标(例如可执行文件或其他库)。它支持三种链接范围:PRIVATE, PUBLIC, 和INTERFACE,这些范围影响链接库的可见性和传播。
target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <library>...)
<target>
: 目标名称(可执行文件或库)。<PRIVATE|PUBLIC|INTERFACE>
: 指定链接范围。<library>
: 要链接的库名称。库的名称:这是最常见的用法,直接指定要链接的库的名称。例如,如果你想链接一个名为mylib
的库,可以这样写:
target_link_libraries(my_target PUBLIC mylib)
库的别名:如果你在CMake中使用了别名(通过add_library
),可以使用这个别名作为参数。例如:
add_library(mylib_alias ALIAS mylib)
target_link_libraries(my_target PUBLIC mylib_alias)
库的完整路径:如果要链接的库不在标准路径中,可以直接指定库文件的完整路径。例如:
target_link_libraries(my_target PUBLIC /path/to/libmylib.so)
导入的目标:如果使用了find_package
或其他方式导入了目标,可以直接使用这个导入的目标。例如,使用find_package(Boost ...)
后,可以链接Boost库:
target_link_libraries(my_target PUBLIC Boost::boost)
PRIVATE
定义: PRIVATE
关键字指定的库仅用于当前目标(比如可执行文件或库),且不会传递给依赖该目标的其他目标。
适用场景:
举例: 如果你的库A
在其源文件中使用了库B
,但B
不在A
的公共API中出现,那么应该使用PRIVATE
链接B
。
当你使用
PRIVATE
关键字时,链接的库仅在定义它的目标中可用。它不会传递给依赖这个目标的其他目标。假设你有一个库
libA
和一个可执行文件app
,app
依赖于libA
,但是你不想让libA
的依赖传递给app
:
cmakeCopy codeadd_library(libA STATIC libA.cpp)
target_link_libraries(libA PRIVATE some_other_lib)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE libA)
在这个例子中,
some_other_lib
仅在libA
内部使用,app
不会直接链接到some_other_lib
。
PUBLIC
PUBLIC
关键字指定的库既用于当前目标,也会传递给依赖该目标的其他目标。A
在其公共头文件中使用了库B
的功能,那么B
应该作为PUBLIC
链接到A
。
PUBLIC
关键字意味着链接的库在定义它的目标中可用,同时也会传递给依赖这个目标的其他目标。假设你希望
app
不仅链接libA
,还链接libA
所依赖的所有库:
cmakeCopy codeadd_library(libA STATIC libA.cpp)
target_link_libraries(libA PUBLIC some_other_lib)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE libA)
这里,
some_other_lib
是libA
的公共依赖,因此它也会被app
链接。
INTERFACE
定义: INTERFACE
关键字用于仅在接口级别传递库,这意味着它们不会直接链接到当前目标,但会传递给依赖该目标的其他目标。
适用场景:
举例: 如果库A
的公共头文件需要库B
的头文件,但A
不直接链接B
,那么B
应该作为INTERFACE
链接到A
。
INTERFACE
关键字用于当你不需要在当前目标中链接库,但希望将库传递给依赖当前目标的其他目标。假设你有一个头文件库(只包含头文件的库),并希望任何链接此库的目标也能链接到另一个特定的库:
add_library(header_lib INTERFACE)
target_link_libraries(header_lib INTERFACE some_other_lib)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE header_lib)
在这个例子中,
app
将链接到some_other_lib
,尽管header_lib
本身不链接到任何东西。
总结
PRIVATE用于仅限于当前目标的内部依赖。
PUBLIC用于需要传播给其他目标的依赖。
INTERFACE用于只影响依赖当前目标的其他目标的接口级依赖。
假设有静态库my_static_lib
和动态库my_shared_lib
:
# 创建库
add_library(my_static_lib STATIC lib1.cpp)
add_library(my_shared_lib SHARED lib2.cpp)
# 创建可执行文件
add_executable(my_executable main.cpp)
# 链接库
target_link_libraries(my_executable PRIVATE my_static_lib)
target_link_libraries(my_executable PUBLIC my_shared_lib)
在此示例中,my_static_lib
作为PRIVATE链接到my_executable
,因此不会传播给其他目标。而my_shared_lib
作为PUBLIC链接,它的接口和依赖项会传播给链接了my_executable
的目标。
target_link_libraries
是CMake中管理项目依赖的关键命令。通过合理选择PRIVATE, PUBLIC, 或INTERFACE链接范围,可以有效地控制依赖传播,优化构建过程,并提高项目的可维护性和可扩展性。在项目开发中,正确使用此命令至关重要,以确保构建稳定性和高效性。