CMake中target_link_libraries的使用

news2024/9/20 0:56:55

      CMake中的target_link_libraries命令用于指定链接给定目标和/或其依赖项时要使用的库或标志来自链接库目标的使用要求将被传播(propagated)。目标依赖项的使用要求会影响其自身源代码的编译。其格式如下:

target_link_libraries(<target> ... <item>... ...) # general form
target_link_libraries(<target>
                      <PRIVATE|PUBLIC|INTERFACE> <item>...
                     [<PRIVATE|PUBLIC|INTERFACE> <item>...]...) # Libraries for a Target and/or its Dependents
target_link_libraries(<target> <item>...) # Libraries for both a Target and its Dependents
target_link_libraries(<target>
                      <LINK_PRIVATE|LINK_PUBLIC> <lib>...
                     [<LINK_PRIVATE|LINK_PUBLIC> <lib>...]...) # Libraries for a Target and/or its Dependents (Legacy)
target_link_libraries(<target> LINK_INTERFACE_LIBRARIES <item>...) # Libraries for Dependents Only (Legacy)

      1.general form: 命名的<target>必须由诸如add_executable或add_library之类的命令创建,并且不能是ALIAS target。如果策略CMP0079未设置为NEW,则target必须已在当前目录中创建。重复调用相同的<target>会按调用顺序追加项目(Repeated calls for the same <target> append items in the order called)。
      <target>不必在与target_link_libraries调用相同的目录中定义
      每个<item>可能是:
      (1).A library target name:生成的链接行(link line)将具有与target关联的可链接库文件的完整路径。如果库文件发生更改,构建系统将具有重新链接<target>的依赖性。
      命名的target必须由项目中的add_library命令创建或作为IMPORTED库创建。如果它是在项目中创建的,则会在构建系统中自动添加一个排序依赖项,以确保指定的库目标在<target>链接之前是最新的。
      如果导入的库设置了IMPORTED_NO_SONAME目标属性,CMake可能会要求链接器搜索库而不是使用完整路径(例如/usr/lib/libfoo.so变为-lfoo)。
      目标工件(target's artifact)的完整路径将自动为shell加引号/转义(quoted/escaped).
      (2).A full path to a library file:生成的链接行通常会保留文件的完整路径。如果库文件更改,构建系统将具有重新链接<target>的依赖性。
      在某些情况下,CMake可能会询问链接器搜索的库(例如/usr/lib/libfoo.so变为-lfoo),例如,当检测到共享库没有SONAME字段时。
      如果库文件在macOS框架(framework)中,框架的Headers目录也会作为使用需求处理。
      在VS2010及更高版本的Visual Studio Generators上,以.targets结尾的库文件将被视为MSBuild目标文件并导入到生成的项目文件中。
      库文件的完整路径将自动为shell加引号/转义(quoted/escaped).
      (3).A plain library name:生成的链接行将要求链接器搜索库(例如,foo变为-lfoo或foo.lib).
      库名称/标志被视为命令行字符串片段,将在没有额外引号或转义的情况下使用。
      (4).A link flag:以-开头但不是-l或-framework的项目名称被视为链接器标志。
      链接标志被视为命令行字符串片段,将在没有额外引号或转义的情况下使用。
      (5).A generator expression:$<...>生成器表达式可以评估上述任何items或以分号分割的列表。如果...包含任何;字符,则必须使用显式引用的参数"$<...>",以便此命令将其作为单个<item>接收。
      此外,生成器表达式可以用作上述任何items的片段,例如foo$<1:_d>
      注意:生成器表达式将不会用于策略CMP0003或策略CMP0004的OLD处理中。
      (6).A debug, optimized, or general keyword immediately followed by another <item>:这样的关键字后面的item将仅用于相应的构建配置。debug关键字对应于Debug配置。optimized关键字对应于所有其它配置。general关键字对应所有配置,完全是可选的。通过创建和链接到IMPORTED库目标,可以为每个配置规则实现更高的粒度。这些关键字由该命令立即解释,因此在由生成器表达式生成时,它们没有特殊含义。
      包含::的项目,如Foo::Bar,被假定为IMPORTED或ALIAS库目标名称,如果不存在这样的目标,将导致错误。

cmake_policy(GET CMP0079 var) # 3.22
message("var: ${var}") # var: NEW

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(add_shared SHARED ${CMAKE_CURRENT_SOURCE_DIR}/source/add.cpp) # 将会在build目录下生成libadd_shared.so

add_executable(sample_add ${CMAKE_CURRENT_SOURCE_DIR}/samples/sample_add.cpp)
target_link_libraries(sample_add add_shared) # 若注释掉此句,则会报 error: sample_add.cpp:(.text+0x25): undefined reference to 'add(int, int)'

      2.Libraries for a Target and/or its Dependents:PUBLIC, PRIVATE和INTERFACE关键字可用于在一个命令中指定link dependencies and the link interface。
      PUBLIC之后的库和目标链接到链接接口,并成为链接接口的一部分。PRIVATE之后的库和目标被链接到,但不是链接接口的一部分。INTERFACE之后的库被附加到链接接口,不用于链接<target>.

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(add_shared SHARED ${CMAKE_CURRENT_SOURCE_DIR}/source/add.cpp) # 将会在build目录下生成libadd_shared.so

add_executable(sample_add ${CMAKE_CURRENT_SOURCE_DIR}/samples/sample_add.cpp)
target_link_libraries(sample_add PRIVATE add_shared) # 也可以为PUBLIC;但不能为INTERFACE,若为INTERFACE,则会报error: sample_add.cpp:(.text+0x25): undefined reference to `add(int, int)'

      3.Libraries for both a Target and its Dependents:默认情况下,库依赖使用此签名是可传递(transitive)的。当这个target链接到另一个target时,链接到该target的库也将出现在另一个target的链接行上。这个可传递的"链接接口"存储在INTERFACE_LINK_LIBRARIES target属性中,可以通过直接设置该属性来覆盖。当CMP0022未设置为NEW时,传递链接是内置的,但可能会被LINK_INTERFACE_LIBRARIES属性覆盖。

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(add_shared SHARED ${CMAKE_CURRENT_SOURCE_DIR}/source/add.cpp) # 将会在build目录下生成libadd_shared.so
add_library(subtraction_shared SHARED ${CMAKE_CURRENT_SOURCE_DIR}/source/subtraction.cpp)

target_link_libraries(subtraction_shared INTERFACE add_shared) # 也可以为PUBLIC;但不可以为PRIVATE,若为PRIVATE,则会报error:sample_add.cpp:(.text+0x25): undefined reference to `add(int, int)'

add_executable(sample_add ${CMAKE_CURRENT_SOURCE_DIR}/samples/sample_add.cpp)
target_link_libraries(sample_add subtraction_shared) # 注意:此处sample_add链接的是subtraction_shared而不是add_shared
                                                        # 可查看build/CMakeFiles/sample_add.dir/link.txt文件

      4.Libraries for a Target and/or its Dependents (Legacy):该签名仅用于兼容性,请改用PUBLIC或PRIVATE关键字。

      5.Libraries for Dependents Only (Legacy):该签名仅用于兼容性,请改用INTERFACE模式。

      6.Linking Object Libraries:Object Libraries可用作target_link_libraries的<target>的(第一个)参数,以指定其源对其他库的依赖。
      OBJECT library类型定义了编译给定源文件所产生的目标文件的非归档集合(The OBJECT library type defines a non-archival collection of object files resulting from compiling the given source files).通过使用语法$<TARGET_OBJECTS:name>,目标文件集合(object files collection)可以用作其它target的源输入。

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(Add SHARED ${CMAKE_CURRENT_SOURCE_DIR}/source/add.cpp)
# target_compile_definitions(Add PUBLIC Add) # 有无此句好像都能执行

# compiles subtraction.cpp(obj.cpp) with -DAdd -DOBJ
add_library(Obj OBJECT ${CMAKE_CURRENT_SOURCE_DIR}/source/subtraction.cpp)
# target_compile_definitions(Obj PUBLIC Obj)
target_link_libraries(Obj PUBLIC Add)

# compiles multipy.cpp with -DAdd -DOBJ
add_library(Multipy SHARED ${CMAKE_CURRENT_SOURCE_DIR}/source/multipy.cpp)
target_link_libraries(Multipy PUBLIC Obj)

# compiles sample_add.cpp with -DAdd -DObj and links executable main to Multipy and Add
add_executable(main ${CMAKE_CURRENT_SOURCE_DIR}/samples/sample_add.cpp)
target_link_libraries(main Multipy)

      7.Linking Object Libraries via $<TARGET_OBJECTS>:与object library关联的object file可以由$<TARGET_OBJECTS>生成器表达式引用(referenced).这样的object file放在所有库之前的链接行上,不管它们的相对顺序如何。
      这也可以通过静态库传递(transitively)。

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(Obj OBJECT ${CMAKE_CURRENT_SOURCE_DIR}/source/subtraction.cpp)
# target_compile_definitions(Obj PUBLIC Obj) # 有无此句好像都能执行

add_executable(main ${CMAKE_CURRENT_SOURCE_DIR}/samples/sample_subtraction.cpp)
# links executable main with object files from sample_subtraction.cpp and subtraction.cpp followed by the pthread and dl libraries
target_link_libraries(main PRIVATE pthread $<TARGET_OBJECTS:Obj> dl)

add_library(iface_obj INTERFACE)
target_link_libraries(iface_obj INTERFACE Obj $<TARGET_OBJECTS:Obj>)

# compiles sample_subtraction.cpp with -DObj and links executable main2 with object files from sample_subtraction.cpp and subtraction.cpp
add_executable(main2 ${CMAKE_CURRENT_SOURCE_DIR}/samples/sample_subtraction.cpp)
target_link_libraries(main2 PRIVATE iface_obj)

# this also works transitively through a static library.
add_library(add STATIC ${CMAKE_CURRENT_SOURCE_DIR}/source/add.cpp)
target_link_libraries(add PRIVATE iface_obj)

add_executable(main3 ${CMAKE_CURRENT_SOURCE_DIR}/samples/sample_subtraction.cpp)
target_link_libraries(main3 PRIVATE add)

      8.Cyclic Dependencies of Static Libraries(静态库的循环依赖):库依赖图通常是非循环的(DAG),但在相互依赖的STATIC库的情况下,CMake允许该图包含循环(强连接组件)。当另一个target链接到其中一个库时,CMake会重复整个连接的组件。
      虽然一次重复通常就足够了,但病理对象文件和符号排列(pathological object file and symbol arrangements)可能需要更多。可以通过使用LINK_INTERFACE_MULTIPLICITY target属性或在上次target_link_libraries调用中手动重复该组件来处理此类情况。然而,如果两个存档(archives)真的如此相互依赖,那么应该使用Object Libraries将它们组合成一个单一的存档。

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)

add_library(add STATIC ${CMAKE_CURRENT_SOURCE_DIR}/source/add.cpp)
add_library(subtraction STATIC ${CMAKE_CURRENT_SOURCE_DIR}/source/subtraction.cpp)
target_link_libraries(add subtraction)
target_link_libraries(subtraction add)

# links main to add subtraction add subtraction
add_executable(main ${CMAKE_CURRENT_SOURCE_DIR}/samples/sample_add.cpp)
target_link_libraries(main subtraction)

      执行测试代码需要多个文件

      build.sh内容如下:

#! /bin/bash

# supported input parameters(cmake commands)
params=(function macro cmake_parse_arguments \
		find_library find_path find_file find_program find_package \
		cmake_policy cmake_minimum_required project include \
		string list set foreach message option if while return \
		math file configure_file \
		include_directories add_executable add_library target_link_libraries install)

usage()
{
	echo "Error: $0 needs to have an input parameter"

	echo "supported input parameters:"
	for param in ${params[@]}; do
		echo "  $0 ${param}"
	done

	exit -1
}

if [ $# != 1 ]; then
	usage
fi

flag=0
for param in ${params[@]}; do
	if [ $1 == ${param} ]; then
		flag=1
		break
	fi
done

if [ ${flag} == 0 ]; then
	echo "Error: parameter \"$1\" is not supported"
	usage
	exit -1
fi

if [[ ! -d "build" ]]; then
	mkdir build
	cd build
else
	cd build
fi

echo "==== test $1 ===="

# test_set.cmake: cmake -DTEST_CMAKE_FEATURE=$1 --log-level=verbose ..
# test_option.cmake: cmake -DTEST_CMAKE_FEATURE=$1 -DBUILD_PYTORCH=ON ..
cmake -DTEST_CMAKE_FEATURE=$1 ..
# It can be executed directly on the terminal, no need to execute build.sh, for example: cmake -P test_set.cmake
make
# make install # only used in cmake files with install command

      CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.22)
project(cmake_feature_usage)

message("#### current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
include(test_${TEST_CMAKE_FEATURE}.cmake)
message("==== test finish ====")

      test_target_link_libraries.cmake内容为上面的所有测试代码段。

      另外还包括三个目录:include,source,samples,它们都是非常简单的实现,仅用于测试,如下:

      可能的执行结果如下图所示: 

      GitHub: https://github.com/fengbingchun/Linux_Code_Test

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/58620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用Rust写一个链表,非常详细,一遍看懂

前言 在Rust里写一个链表可不是一件容易的事&#xff0c;涉及到很多的知识点&#xff0c;需要熟练掌握之后才能写出一个不错的链表。这篇文章主要介绍了如何写一个Rust链表&#xff0c;并且补充了涉及到的很多的额外知识点&#xff0c;尤其是所有权问题。 首先&#xff0c;你需…

人工智能内容生成元年—AI绘画原理解析

AIGC体验生成一、背景 2022年AIGC&#xff08;AI生成内容&#xff09;焕发出了勃勃生机&#xff0c;大有元年之势&#xff0c;技术与应用迭代都扎堆呈现。在各种新闻媒体处可以看到诸多关于学术前沿研究&#xff0c;以及相应落地的商用案例。可谓出现了现象级的学术-商业共振。…

phpbugs代码审计第三题多重加密答案错误

phpbugs多重加密 这题官方给的答案是错的&#xff0c;网上给的也是错的&#xff0c;麻烦别直接拿给的答案来抄好吗&#xff1f;就想纠正一下别误导别人了 源码如下: <?phpinclude common.php;$requset array_merge($_GET, $_POST, $_SESSION, $_COOKIE);//把一个或多个…

安卓期末大作业——售票APP源码和设计报告

大作业文档 项目名称&#xff1a;售票APP专业&#xff1a;班级&#xff1a;学号&#xff1a;姓名&#xff1a; 目 录 目录 一、项目功能介绍3二、项目运行环境31、开发环境32、运行环境33、是否需要联网3三、项目配置文件及工程结构31、工程配置文件32、工程结构目录4四、项…

【C语言 数据结构】串 - 顺序

文章目录串 - 顺序一、串的表示及实现1.1 串的概念1.2 串的初始化1.3 复制串1.4 串的判空1.5 串的比较1.6 串的长度1.7 清空串1.8 串的拼接1.9 串的截取1.10 插入子串1.11 串的打印二、串的应用2.1 串的模式匹配 - 基本操作2.2 串的模式匹配 - BF2.3 串的模式匹配 - KMPnext数组…

【学习笔记77】ajax的函数封装

一、封装分析 &#xff08;一 &#xff09;封装方案 1、回调函数方式 将来使用的时候, 可能会遇到回调地狱 2、promise方式 效果不会有变化, 而且还能和 async/await 一起使用 &#xff08;二&#xff09;函数的参数 请求方式: method > 默认值 get请求地址: url > 必填…

Android开发——Jetpack Compose的使用

Android开发——Jetpack Compose的使用什么是Jetpack ComposeJetpack Compose带来的变化Jetpack Compose的两种运用方法将Jetpack Compose 添加到现有项目1.gradle 配置2.使用Kotlin-Gradle 插件3. 添加依赖项创建一个新的支持Jetpack Compose的项目1.创建一些简单应用定义可组…

12.3做题

一.车队问题 1.思路: 先把所在位置进行排序,升序排序, 计算出每辆车在不受其余车的影响时&#xff0c;行驶到终点需要的时间 从后往前看 对于相邻的两辆车 S 和 F&#xff0c;F 的起始位置大于 S&#xff0c;如果 S 行驶到终点需要的时间小于等于 F&#xff0c;那么 S 一定…

MySQL集群搭建-MMM高可用架构

MySQL集群搭建-MMM高可用架构 原文地址 https://segmentfault.com/a/1190000017286307&#xfeff; 1 MMM 介绍 1.1 简介 MMM 是一套支持双主故障切换以及双主日常管理的第三方软件。MMM 由 Perl 开发&#xff0c;用来管理和监控双主复制&#xff0c;虽然是双主架构&#xff…

volatile

是java虚拟机提供的轻量级的同步机制&#xff08;乞丐版的synchronized) 具备三个性质&#xff1a;保证可见性&#xff0c;不保证原子性&#xff0c;禁止指令重排 前置知识&#xff1a; …

JS读取本地CSV文件数据

JS读取本地CSV文件数据 文件中的部分数据如图 需求是需要提取出文件的数据 使用到的模块是 Papa Parse 1. 依赖安装 yarn add papaparse papaparse的基本使用可以参考官方demo 2. 解析本地文件 首先需要注意, papaparse解析本地文件, 需要的文件格式是从DOM中获得的File…

GO高级特性 之 并发模型

本文介绍一些并发的基础知识、常见的并发模型一级Go语言的MPG并发模型及其运行原理 并发与并行的区别 -并发并行概念并发指同一时间段&#xff0c;多条命令在CPU上同时执行。并行指同一时刻&#xff0c;多条命令在CPU上执行运行原理并发程序不要求计算机有多核计算能力&#…

毕设选题推荐基于python的django框架医疗急诊预约系统

&#x1f496;&#x1f525;作者主页&#xff1a;计算机毕设老哥&#x1f525; &#x1f496; 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; Java实战项目专栏 Python实…

项目成本管理质量管理

项目成本管理-控制成本目录概述需求&#xff1a;设计思路实现思路分析1.EVM2.偏差指标3.Question:4.绩效指标5.典型偏差TCPIS曲线图绩效审查参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip …

[近两万字] MySQL大全

目录 单元1 创建数据库 1.1 创建数据库 1.查看数据库 2.选择数据库 3.删除数据库 1.2 创建数据表 1.查看表结构 2.查看所有数据表 3.复制表结构 4.删除表 5.修改表数据 5.1 修改表名 5.2 添加字段 5.3删除字段 5.4修改字段的数据类型 5.5修改字段的名称 5.6修改字段…

[网络工程师]-应用层协议-SNMP

简单网络管理协议&#xff08;Simple Network Management Protocol&#xff0c;SNMP&#xff09;是在应用层上进行网络设备间通信的管理协议&#xff0c;可以用于网络状态监视、网络参数设定、网络流量统计与分析、发现网络故障等。SNMP基于UDP协议&#xff0c;由SNMP协议、管理…

【交通建模】基于模型的自主交通仿真框架附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

【深入浅出Java并发编程指南】「难点 - 核心 - 遗漏」让我们一起探索一下CyclicBarrier的技术原理和源码分析

CyclicBarrier和CountDownLatch CyclicBarrier和CountDownLatch 都位于java.util.concurrent这个包下&#xff0c;其工作原理的核心要点&#xff1a; CyclicBarrier工作原理分析 那么接下来给大家分享分析一下JDK1.8的CyclicBarrier的工作原理。 简单认识CyclicBarrier 何为…

Nginx动静分离、缓存配置、性能调优、集群配置

一. Nginx动静分离 1. 准备 1个web程序&#xff1a;部署在7061端口&#xff0c;启动 【dotnet NginxWeb.dll --urls"http://*:7061" --ip"127.0.0.1" --port7061】 Nginx程序&#xff1a;监听7000端口 2. 目的 比如单独启动部署在7061端口下的web程序&am…

c++ 静态库,动态库的制作和使用

文章目录1.什么是库&#xff1f;2.静态库的制作1.静态库的命名规则2.静态库的制作与使用1.静态库的制作2.静态库的使用3.动态库的制作1.动态库的命名规则2.动态库的制作与使用1.动态库的制作2.动态库的使用3.动态库加载失败的原因4.静态库和动态库的对比1.程序编译成可执行文件…