CMake入门教程【核心篇】链接库(target_link_libraries)

2024-01-03 12:55:04

概述

在CMake中,target_link_libraries命令用于链接库到目标(例如可执行文件或其他库)。它支持三种链接范围:PRIVATE, PUBLIC, 和INTERFACE,这些范围影响链接库的可见性和传播。

基本语法

target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <library>...)
  • <target>: 目标名称(可执行文件或库)。
  • <PRIVATE|PUBLIC|INTERFACE>: 指定链接范围。
  • <library>: 要链接的库名称。

library参数

  1. 库的名称:这是最常见的用法,直接指定要链接的库的名称。例如,如果你想链接一个名为mylib的库,可以这样写:

    target_link_libraries(my_target PUBLIC mylib)
    
  2. 库的别名:如果你在CMake中使用了别名(通过add_library),可以使用这个别名作为参数。例如:

    add_library(mylib_alias ALIAS mylib)
    target_link_libraries(my_target PUBLIC mylib_alias)
    
  3. 库的完整路径:如果要链接的库不在标准路径中,可以直接指定库文件的完整路径。例如:

    target_link_libraries(my_target PUBLIC /path/to/libmylib.so)
    
  4. 导入的目标:如果使用了find_package或其他方式导入了目标,可以直接使用这个导入的目标。例如,使用find_package(Boost ...)后,可以链接Boost库:

    target_link_libraries(my_target PUBLIC Boost::boost)
    

PRIVATE|PUBLIC|INTERFACE

  • PRIVATE

    • 定义: PRIVATE关键字指定的库仅用于当前目标(比如可执行文件或库),且不会传递给依赖该目标的其他目标。

    • 适用场景:

      • 当你不希望库的依赖被外部使用时。
      • 对于只在内部实现中使用,而不在公共头文件中使用的库。
    • 举例: 如果你的库A在其源文件中使用了库B,但B不在A的公共API中出现,那么应该使用PRIVATE链接B

    当你使用PRIVATE关键字时,链接的库仅在定义它的目标中可用。它不会传递给依赖这个目标的其他目标。

    假设你有一个库libA和一个可执行文件appapp依赖于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_liblibA的公共依赖,因此它也会被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的目标。

使用技巧

  • 使用PRIVATE链接最小化所需依赖,提高编译效率。
  • 使用PUBLIC链接共享公共接口和依赖项。
  • 使用INTERFACE在不直接使用库的情况下传播依赖项。

注意事项

  • 确保正确的链接顺序,尤其是在UNIX平台。
  • 留意库的兼容性,尤其是在链接不同类型的库时。
  • 确保动态库在运行时环境中可访问。

总结与分析

target_link_libraries是CMake中管理项目依赖的关键命令。通过合理选择PRIVATE, PUBLIC, 或INTERFACE链接范围,可以有效地控制依赖传播,优化构建过程,并提高项目的可维护性和可扩展性。在项目开发中,正确使用此命令至关重要,以确保构建稳定性和高效性。

文章来源:https://blog.csdn.net/hiwoshixiaoyu/article/details/135310658
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。