CMake教程(二)- 添加静态库文件和动态库文件

2023-05-16

CMake教程(二)- 添加静态库文件和动态库文件

    • 什么是库文件
      • 静态链接库
      • 动态链接库
      • 静态库和动态库的区别
    • 如何在CMake中添加库文件
    • CMake 中 target_link_libraries 的 PRIVATE,PUBLIC 和 INTERFACE 的区别

什么是库文件

一般来说,一个程序,通常都会包含目标文件和若干个库文件。经过汇编得到的目标文件再经过和库文件的链接,就能构成可执行文件。库文件像是一个代码仓库或代码组件的集合,为目标文件提供可直接使用的变量、函数、类等。

库文件包含了静态链接库动态链接库两种。两者最根本的区别在与在程序编译的过程中,如何处理库文件和目标文件的链接关系。
在这里插入图片描述

静态链接库

静态链接库在Linux系统中以.a文件的形式存在。

在上图程序编译的链接阶段静态库会完全复制到可执行文件中,一旦可执行文件构建完成,就不再需要静态库的存在,可执行文件在后续的使用中,也不再依赖这个静态库。

动态链接库

虽然静态库非常容易理解且不会引入依赖问题,但是试想一下,如果你在统筹构建一个无比庞大的工程,这时,其中一个开发者升级了他所开发的库。这时,你就需要花费很长的时间来重新构建这个如此庞大的工程。这时,你就可以使用动态库来避免这个问题。

动态库在程序编译的链接阶段,仅将一些重要的信息,如重定位和符号表信息复制到可执行文件中,可执行文件在后面执行的过程中,如果需要引用这个库文件,就会根据这些信息从系统中寻找对应的库文件以实现对应的功能。

静态库和动态库的区别

区别静态库动态库
可执行文件大小较大
(因为动态库的内容会被完全复制到可执行文件中)
较小
占用磁盘大小较大
(如果有多个可执行文件都用到同一个静态库,这个静态库会被多次复制到不同的可执行文件中)
较小
(即使多个可执行文件都需要用到同一个动态库,他们也只是共用同一个动态库文件)
拓展性与兼容性全量更新
(库文件的更新会引起整个可执行文件的重新编译及发布)
增量更新
(不需要重新编译可执行文件,只需发布动态库文件)
依赖问题无依赖问题
(已构建的可执行文件不依赖其他静态库文件)
有依赖问题
(可执行文件的执行需要系统存在依赖的动态库文件)
复杂程度简单复杂
(会引起很多问题,例如如何在运行时确定地址,库文件版本管理等)
加载速度

如何在CMake中添加库文件

下面是一个C++工程,包含了一个主程序文件和两个准备用于生成库文件的源文件。
在这里插入图片描述
这里有一个简单的主程序,其中调用了两个来自库文件的函数:print_char()print_int(),其中print_char()来自静态库文件,print_int()来自动态库文件。

#include <iostream>
#include "printer_char.hpp"
#include "printer_int.hpp"

using namespace std;

int main(int argc, char* argv)
{
    // 静态库 + 动态库
    print_char('A');        // print_char() 来自静态库
    print_int(5);           // print_int() 来自动态库
    return 0;
}

使用CMake来构建MakeFile,并将指定的源文件制作为静态库和动态库。

cmake_minimum_required(VERSION 3.10)

# 设置项目名
project(CMakeTutorial VERSION 1.2)

# 添加头文件搜索路径
include_directories(
${PROJECT_SOURCE_DIR}/inc
)

# 生成库
add_library(PrinterChar STATIC src/printer_char.cpp)    # 静态库
add_library(PrinterInt SHARED src/printer_int.cpp)      # 动态库

# 添加需要构建的可执行文件
#------方法对比 1.1 - 不用库的写法
# add_executable(LinkLibraryDemo link_library_demo.cpp src/printer_char.cpp src/printer_int.cpp)
#------方法对比 1.2 - 用库的写法
add_executable(LinkLibraryDemo demo/link_library_demo.cpp)
target_link_libraries(LinkLibraryDemo PRIVATE PrinterChar)   # 为目标添加静态库
target_link_libraries(LinkLibraryDemo PRIVATE PrinterInt)    # 为目标添加动态库

然后执行下面的命令来生成库文件和可执行文件

本人习惯在工程的根目录下创建一个cmake目录用于构建工程,以避免污染根目录。是在cmake目录下执行的cmake指令,所以指定的CMakeLists.txt文件是在当前目录的上一级目录。请根据你的工程目录结构选择正确的cmake指令的目录。

cmake ..
make

在这里插入图片描述
可见编译生成了两个库文件,静态库libPrinterChar.a和动态库libPrinterInt.so。此时可执行文件能够成功运行。

尝试一下删除静态库libPrinterChar.a,并再次运行程序,发现程序依然能成功运行。这说明可执行文件的运行并不依赖静态库文件存在。
在这里插入图片描述
再尝试把动态库文件删掉,再运行可执行文件,运行失败,提示找不到对应的.so动态库文件。说明可执行文件的运行依赖对应的动态库文件的存在。
在这里插入图片描述

CMake 中 target_link_libraries 的 PRIVATE,PUBLIC 和 INTERFACE 的区别

情况使用参数
只有源文件(.cpp)中包含了库文件PRIVATE
只有头文件(.hpp)中包含了库文件INTERFACE
源文件和头文件都包含了库文件PUBLIC

关于这个问题可以参考这里

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CMake教程(二)- 添加静态库文件和动态库文件 的相关文章

随机推荐

  • TCP/IP四层模型及各层协议首部详述

    1 OSI七层和TCP IP四层的关系 1 1 OSI引入了服务 接口 协议 分层的概念 xff0c TCP IP借鉴了OSI的这些概念建立TCP IP模型 1 2 OSI先有模型 xff0c 后有协议 xff0c 先有标准 xff0c 后
  • 位域的定义和使用

    位域 xff1a 有些信息在存储时 xff0c 并不需要占用一个完整的字节 xff0c 而只需占几个或一个二进制位 例如在存放一个开关量时 xff0c 只有0和1 两种状态 xff0c 用一位二进位即可 为了节省存储空间 xff0c 并使处
  • Makefile 的运行(六)

    一般来说 xff0c 最简单的就是直接在命令行下输入make命令 xff0c make命令会找当前目录的makefile来执行 xff0c 一切都是自动的 但也有时你也许只想让make重编译某些文件 xff0c 而不是整个工程 xff0c
  • FreeRTOS 任务优先级说明

    freeRTOS任务优先级与Unix进程优先级不同 FreeRTOS 任务优先 xff1a 任务优先级数值越小 xff0c 任务优先级越低 Unix 任务优先 xff1a 进程优先级数值越小 xff0c 进程优先级越高 下面对 FreeRT
  • QT子线程读取串口数据并传到主线程

    转载 读取串口部分借鉴于Quartz010的文章 如何在QT中读取串口数据 http blog csdn net zz709196484 article details 66474917 这是博客网址 大致思路就是子线程去读取串口数据并传送
  • 最常用的Java库一览

    一个典型的Java项目依赖于第三方库 本文总结的Java库适用于各种应用 xff0c 比较流行并且广泛使用 其中一些还提供简单的示例 xff08 来自ProgramCreek xff09 Java SDK 肯定是使用最广的库 xff0c 所
  • C#Socket编程详解(一)TCP与UDP简介

    一 TCP与UDP 1 TCP 1 1 定义 TCP xff08 TransmissionControl Protocol xff09 传输控制协议 是一种可靠的 面向连接的协议 xff08 eg 打电话 xff09 传输效率低全双工通信
  • AD19导出bom表的方法(按照元件不同数值分类,重点信息突出)

    我画电路图用的是AD19的软件 xff0c 最后板子画好了要进行元器件采购要生成bom表 xff0c 查了一下相关的资料 xff0c 总结整理一下 xff1a 1 在报告 xff08 report xff09 打开Bill of Mater
  • 为什么c++要“在头文件中声明,在源文件中定义”?

    gt gt gt 搬运一个知乎问答 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 下面是回答 61 61 61 61 61 61 61 61 61 61 61 61 61
  • HTTP header 参数丢失情况分析以及解决防范

    HTTP header 参数丢失情况分析以及解决防范 1 问题 当项目有Nginx做了代理的时候 xff0c 请求头中传参 34 user ip 34 xff0c 接口接收不到 2 问题分析 默认nginx是不能转发带 的header信息的
  • Keil 调试局部变量查看显示not in scope

    调整优化级别 不同的优化级别允许您在编译代码中可用的调试信息级别与代码性能之间进行权衡 可以使用以下优化级别 xff1a o O0应用最小优化 大多数优化都被关闭 xff0c 生成的代码具有最佳的调试视图 o O1应用受限优化 例如 xff
  • 【32单片机学习】(6)STM32串口+DMA收发不定长数据

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 目录 前言 1 DMA介绍 2 串口接收数据 3 实验现象 1 实验电路图 2 串口收发不定长数据视频演示 3 OLED 显示接收数据 4
  • www-authenticate认证过程浅析

    文档 xff1a www authenticate认证过程简单研究 创建 xff1a http hi baidu com netee 日期 xff1a 2009 10 07 版权 xff1a 原创内容 xff0c 转载请注明出处 xff0c
  • STM32F407ZG 串口通信+固定帧头帧尾传输数据帧

    STM32F407ZG开发板学习 xff08 4 xff09 串口简介通信接口USART接线电平标准数据帧 实验 xff1a 固定帧头帧尾数据传输需求最终思路以及思考过程思路中断函数程序段长度的问题缓冲区数据结构的决定 初始化配置中断服务函
  • 基于杰理RTOS平台的433射频无线数传通信

    在杰理的AC7916N实现了433射频的数据发送 xff0c 在杰理的AD15系列实现433射频接收 xff0c 本代码用于门铃项目收发 xff0c 下面请看代码 首先是AC7916N的433数据发送代码 xff0c 发送部分的程序放在一个
  • boost简介

    我认为做为一名c 43 43 编程人员 xff0c 对boost库必须要有一定的了解与使用 这对于代码的整洁和效率有很大的帮助 借着这个机会整理一下使用boost库的经验 xff0c 顺便再学习一下 首先 xff0c 什么是boost库 b
  • Android上增加对M3U8文件下载的功能

    最近给一个客户提了一个需求 xff0c 想对他们网站的视频做一个下载的功能 xff0c 希望他的App能够缓存视频功能 xff0c 然后用户可以在下次快速播放视频 一开始接到这个需求 xff0c 自然是去搜罗一遍 xff0c 有没有可靠稳定
  • VLC自定义m3u8协议片段加密方式

    hls xff08 m3u8 xff09 本身有一套自己的加密方式 xff0c 可以保证片段是安全的 但是本身在传输的过程中加密key请求容易被截获 xff0c 这样存在一点片段key被截取的风险 xff0c 截取者就可以根据片段和key重
  • Fragment里使用CordovaWebView

    因为CordovaWebView 默认的初始化里判断了Content是不是继承CordovaInterface xff0c 如果直接使用Fragment继承CordovaInterface xff0c CordovaInterface有个抽
  • CMake教程(二)- 添加静态库文件和动态库文件

    CMake教程 xff08 二 xff09 添加静态库文件和动态库文件 什么是库文件静态链接库动态链接库静态库和动态库的区别 如何在CMake中添加库文件CMake 中 target link libraries 的 PRIVATE xff