CMake系列讲解(入门篇)1.7 基础命令CMake-target_link_libraries()


基础命令target_link_libraries()

〓〓〓〓〓〓〓〓踏实学CMake总目录〓〓〓〓〓〓〓〓〓〓


7. target_link_libraries

不想看理论的可以直接跳转7.3查看实际使用示例即可。

7.1 命令格式:

该命令用于用于将目标与所需的库进行链接。它用于指定一个目标(例如可执行文件或库)需要依赖的其他库,以便在构建过程中正确地链接这些库。该命令有多种使用方法,但他们都符合下面的命令格式

target_link_libraries(<target> ... <item>... ...)

7.2 参数说明

target:要链接库的目标

target必须是由add_executable()或add_library()等命令创建的,并且不能是ALIAS目标。
对同一target的重复调用按照调用的顺序追加项。

item:item可以是:

(1) 一个库目标的名称:

  当使用target_link_libraries命令将目标与库进行链接时,生成的链接行(link line)将包含与目标关联的可链接库文件的完整路径。这意味着构建系统将依赖于目标链接的库文件,如果库文件发生更改,将重新链接目标。
  链接的库必须是由项目中的add_library()创建或者作为导入库创建。如果是在项目中创建的,则会在构建系统中自动添加排序依赖项,以确保指定的库目标在被链接时是最新的

注:链接行(link line)指的是使用CMake最终生成的命令行,例如,当我们使用target_link_libraries链接名为myapp的可执行文件和名为mylib的库时,可能会生成类似以下形式的链接行:
g++ main.o -o myapp -L/path/to/lib -lmylib

注: 构建系统自动添加排序依赖项,指的是在构建项目时,当目标(例如可执行文件或库)依赖于其他目标(通常是库)时,构建系统会确保按正确的顺序构建这些目标,以满足依赖关系。比如:
add_library(mylib1 ...)
target_link_libraries(mylib2 PRIVATE mylib1)
add_executable(myapp ...)
target_link_libraries(myapp PRIVATE mylib2)
add_library(mylib2 ...)
在这个例子中,myapp可执行文件依赖于mylib2库,而mylib2库又依赖于mylib1库。由于存在这种依赖关系,构建系统会自动添加构建规则,确保在构建myapp可执行文件之前,先构建mylib2库,而在构建mylib2库之前,先构建mylib1库。

(2) 库文件的完整路径:

 生成的链接行通常会保留文件的完整路径。 如果库文件发生更改,构建系统将具有重新链接 target的依赖关系。

(3) 普通的库名称:

 生成的链接行将要求链接器搜索库(例如 foo 变为 -lfoo 或 foo.lib)。
库名称/标志被视为命令行字符串片段,并且将在没有额外引用或转义的情况下使用。具体来说就是库名称会被转换成链接器可以识别的格式。例如将库名"foo"转换为"-lfoo"或"foo.lib"。这样链接器就能够根据这个名称来搜索相应的库文件进行链接。

(4) 链接标志:

  以 - 开头但不是 -l 或 -framework 的item被视为链接器标志。 请注意,出于传递依赖性的目的,此类标志将像任何其他库链接项一样被对待,因此通常可以安全地将它们仅指定为不会传播到依赖项的私有链接项。

(5) 一个生成器表达式

生成器表达式是一种方便的语法,可以生成一系列项。生成器表达式可以产生的项的类型包括字符串、数字、文件名等。

(6) 构建配置的关键字

这些关键字往往后边紧跟着另外一个item,常见的关键字有debug、optimized和general等。

  • debug关键字对应于debug配置(如果设置了DEBUG_CONFIGURATIONS全局属性,则对应于DEBUG_CONFIGURATIONS中指定的配置)
  • optimized关键字对应于其他的所有配置
  • general关键字对应于所有配置,是可选的。

这些关键字由该命令立即解释,因此在生成器表达式生成时没有特殊含义。

7.3 使用示例

7.3.1 最常使用方式

target_link_libraries(<target>
                      <PRIVATE|PUBLIC|INTERFACE> <item>...
                     [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

在这个命令中,可以使用PUBLIC、PRIVATE和INTERFACE这三个作用域关键字来指定链接的依赖项和链接接口

  • PUBLIC表示将指定的库或目标链接到目标,并将其作为链接接口的一部分。这意味着当其他目标链接到当前目标时,也会自动链接这些PUBLIC作用域的依赖项。这样的依赖项将被传递给依赖于当前目标的其他目标
  • PRIVATE表示将指定的库或目标链接到目标,但不将其作为链接接口的一部分。这意味着这些PRIVATE作用域的依赖项只会影响当前目标,而不会传递给依赖于当前目标的其他目标
  • INTERFACE表示将指定的库链接到链接接口,而不进行实际的链接操作。这意味着这些INTERFACE作用域的依赖项不会对当前目标产生影响,但会被传递给依赖于当前目标的其他目标这通常用于定义一组接口,以满足其他目标的特定要求。

具体可以为:

cmake_minimum_required(VERSION 3.5)
project(hello_library)
add_library(hello_library STATIC 
    src/Hello.cpp
)
target_include_directories(hello_library
    PUBLIC 
        ${
    
    PROJECT_SOURCE_DIR}/include
)
add_executable(hello_binary 
    src/main.cpp
)
# link the new hello_library target with the hello_binary target
target_link_libraries( hello_binary
    PRIVATE 
        hello_library
)

此例中将生成的hello_library库链接给名为hello_library的target,且作用域为PRIVATE,表示hello_library库只会被链接给hello_library这个target,如果还有其他target依赖hello_library这个target,hello_library库不会被链接给其他target。

7.3.2 不指定作用域

target_link_libraries(<target> <item>...)

根据这个命令的默认行为,库的依赖关系是传递的,即如果一个目标链接到了另一个目标,那么链接到这个目标的库也会出现在另一个目标的链接行中。

例如:假设你有两个目标:my_app和my_library。你想要将my_library链接到my_app中。

# 定义my_library目标
add_library(my_library STATIC my_library.cpp)
# 定义my_app目标,并将my_library链接到my_app中
add_executable(my_app main.cpp)
target_link_libraries(my_app my_library)

# 定义other_library目标
add_library(other_library STATIC other_library.cpp)
# 将other_library链接到my_library中
target_link_libraries(my_library other_library)
# 将my_library链接到my_app中
target_link_libraries(my_app my_library)

在此例中,先将my_library链接到了my_app中,接着又将other_library链接到了my_library,最后将my_library链接到了my_app,因此,当构建my_app时,my_app会链接到my_library和other_library,并将它们一起包含在最终的可执行文件中。

7.3.3 不推荐使用的其他形式

使用LINK_PRIVATE|LINK_PUBLIC指定作用域

target_link_libraries(<target>
                      <LINK_PRIVATE|LINK_PUBLIC> <lib>...
                     [<LINK_PRIVATE|LINK_PUBLIC> <lib>...]...)

这种方式通过LINK_PRIVATE或者LINK_PUBLIC指定作用域,但不推荐使用此方式,推荐使用PUBLIC和PRIVATE,即上文第一种方式。

使用LINK_INTERFACE_LIBRARIES指定作用域

target_link_libraries(<target> LINK_INTERFACE_LIBRARIES <item>...)

这种方式通过LINK_INTERFACE_LIBRARIES 指定作用域,但不推荐使用此方式,推荐使用INTERFACE,即上文第一种方式。


附:返回总目录的传送门如下:

〓〓〓〓〓〓〓〓踏实学CMake总目录〓〓〓〓〓〓〓〓〓〓

猜你喜欢

转载自blog.csdn.net/mataojie/article/details/133352276