CMake:静态库和动态库的制作与使用(四)

embedded/2024/9/24 12:47:35/
1、制作库
  • 有些时候我们编写的源代码并不需要将他们编译生成可执行程序,而是生成一些静态库或者动态库提供给第三方使用,而在CMake中生成这两类库文件的方法

  • 在CMake中制作静态库需要使用如下的命令:

    add_library(库名称 STATIC/SHARED [源文件1 源文件2 ...])# Makfile中的制作静态库的命令
    ar -r libcalc.a *.cpp# Makfile中的制作动态库的命令
    g++ -shared -fPIC *.cpp -o libcalc.so
    
    • STATIC:表示制作静态库,格式:lib + 库名字 + .a(Linux)、lib + 库名字 + .lib(Windows)
    • SHARED:表示制作动态库,格式:lib + 库名字 + .so(Linux)、lib + 库名字 + .dll(Windows)
    • CMake中只需要指定库名字就可以,另外两部分在生成该文件的时候自动填充
$ tree
.
├── build
├── CMakeLists.txt
├── inc
│   └── head.h
├── lib
└── src├── add.cpp├── dived.cpp├── mul.cpp└── sub.cpp
  • build:CMake编译目录,生成Makefile文件并继续执行make生成库

  • lib:存放生成的库文件目录

  • inc:头文件目录

  • src:存放需要制作库的源代码

  • CMakeLists.txt文件编写:

    cmake_minimum_required(VERSION 3.10.2)# 指定标准
    set(CMAKE_CXX_STANDARD 14)# 指定源文件列表
    aux_source_directory(${PROJECT_SOURCE_DIR}/src src_list)# 生成一个静态库 ar rcs libcalc.a *.cpp
    add_library(calc STATIC ${src_list})# 制作动态库 g++ -shared -fPIC *.cpp -o libcalc.so
    #add_library(calc SHARED ${src_list})# 设置静态库的存放路径
    set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
    
    • LIBRARY_OUTPUT_PATH:库文件输出位置宏,将库文件生成到指定的位置
2、连接使用库
  • 对于使用静态库和动态库是有区别的

    • 静态库在编译可执行程序期间会将所有源代码引入到可执行程序中进行编译
    • 动态库则是在编译时预留一部分的地址,当使用时进行加载。
  • 链接器:工作于链接阶段,工作时需要-l和-L分别指定库名和动态库路径

  • 动态链接器:工作与程序运行阶段,工作时需要提供动态库所在目录位置,而动态库加载,程序是默认从几个系统指定的位置加载。当前位置的加载,因此需要给给定一个路径使得系统能够加载到动态库

2.1、链接使用静态库

在CMakeLists.txt中进行链接静态库

# 添加静态库名称
link_libraries(calc)# 添加静态库头文件路径
link_directories(${PROJECT_SOURCE_DIR}/lib)# 生成目标路径, 在当前目录下bin文件夹下
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)# 生成可执行程序
add_executable(main main.cpp)
  • link_libraries:指定出要连接的静态库的名称
    • 可以链接一个静态库和可以链接多个静态库
    • 传入的名字可以是全名libxxx.a,也可以是掐头(lib)去尾(.a)之后的名字xxx
  • link_directories:如果该静态库不是系统提供的(自己制作的或者使用第三方提供的静态库)可能出现静态库找不到的情况,需要将静态库的路径制定出来
2.2、链接使用动态库
  • 在程序编写过程中,除了在项目中引入静态库,好多时候也会使用一些标准的或者第三方提供的动态库,例如:基础IO流库、多线程库…

  • 在CMake中链接动态库

    target_link_libraries(<target><PRIVATE | PUBLIC | INTERFACE> <item>...[<PRIVATE | PUBLIC | INTERFACE> <item>...])
    
    • target:指定要加载的动态库的文件的名字

      • 该文件可能是一个源文件、动态库文件、可执行文件
    • PRIVATE | PUBLIC | INTERFACE:动态库的访问权限,默认为PUBLIC

      • 如果各个动态库之间没有依赖关系,无序做任何设置,三者没有任何区别(一般都使用默认的PUBLIC)

      • 传递性:动态库的链接具有传递性,如果动态库A链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法

        target_link_libraries(A B C)
        target_link_libraries(D A)
        
      • PUBLIC:在public后面的库会被Link到前面的target中,并且里面的符号也会被导出,提供给第三方使用

      • PRIVATE:在private后面的库仅被link到前面的target中,并且终止掉,第三方不能感知调用了哪个库

      • INTERFACE:在interface后面引入的库不会被链接到前面的target中,只会导出符号。

  • 动态库的链接和静态库的链接是完全不同的

    • 静态库在生成可执行程序的链接阶段会被打包到可执行程序中,所以可执行程序启动静态库就一起被加载到内存中
    • 动态库在生成可执行程序的链接阶段不会被打包到可执行程序中,当可执行程序启动并且调用动态库中的函数时候,动态库才会被加载到内存
  • 在CMake中指定要连接的动态库的时候,应该将命令写到生成了可执行文件之后

    add_executable(main main.cpp)
    target_link_libraries(main pthread)
    

    target_link_libraries(main pthread)中:

    • main:对应的是最终的生成的可执行程序的名字
    • pthread:这是可执行程序需要加载的动态库,这个库是系统提供的多线程库,全名libpthread.so,在指定的时候掐头去尾
  • CMakeLists.txt编写

    cmake_minimum_required(VERSION 3.10.2)# 指定标准
    set(CMAKE_CXX_STANDARD 14)# 指定源文件列表
    aux_source_directory(${PROJECT_SOURCE_DIR}/src src_list)# 制作动态库 g++ -shared -fPIC *.cpp -o libcalc.so
    add_library(calc SHARED ${src_list})# 设置静态库的存放路径
    set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)# 生成目标路径, 在当前目录下bin文件夹下
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
    # 生成可执行程序
    add_executable(main main.cpp)# 链接动态库
    link_directories(${PROJECT_SOURCE_DIR}/inc)
    target_link_libraries(main calc)
    

http://www.ppmy.cn/embedded/29625.html

相关文章

google chromeDriver 地址

#chrome driver 下载地址 https://getwebdriver.com/chromedriver #chrome brower下载地址 https://googlechromelabs.github.io/chrome-for-testing/ centos 安装的dockerFile的部分命令&#xff1a; #安装browser wget https://dl.google.com/linux/chrome/rpm/stable/x86_…

Flutter笔记:使用Flutter私有类涉及的授权协议问题

Flutter笔记 使用Flutter私有类涉及的授权协议问题 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.cs…

AI图书推荐:用ChatGPT快速创建在线课程

您是否是您领域的专家&#xff0c;拥有丰富的知识和技能可以分享&#xff1f;您是否曾想过创建一个在线课程&#xff0c;但被这个过程吓倒了&#xff1f;那么&#xff0c;是时候把这些担忧放在一边&#xff0c;迈出这一步了&#xff01;有了这本指南和ChatGPT的帮助&#xff0c…

IDEA 2022.1版本开始,可以直接运行Markdown里的命令行

参照这种格式&#xff1a; shell mvn clean install注意idea支持的版本&#xff1a;是从 2022.1版本开始的。 ps&#xff1a;之前有人写过了&#xff0c;感觉很实用但是蛮多开发者不一定会知道的功能。 参考资料&#xff1a; https://www.cnblogs.com/didispace/p/16144107.h…

ElasticSearch教程入门到精通——第一部分(基于ELK技术栈elasticsearch 8.x新特性)

ElasticSearch教程入门到精通——第一部分&#xff08;基于ELK技术栈elasticsearch 8.x新特性&#xff09; 1. ElasticSearch安装&#xff08;略&#xff09;2. ElasticSearch基础功能2.1 索引操作2.1.1 创建索引2.1.2 Head 索引2.1.3 查询索引2.1.3.1 查询单独索引2.1.3.2 查询…

【Docker】docker部署lnmp和搭建wordpress网站

环境准备 docker&#xff1a;192.168.67.30 虚拟机&#xff1a;4核4G systemctl stop firewalld systemctl disable firewalld setenforce 0 安装docker #安装依赖包 yum -y install yum-utils device-mapper-persistent-data lvm2 #设置阿里云镜像 yum-config-manager --add…

C语言/数据结构——每日一题(反转链表)

一.前言 大家好&#xff01;今天又是每日一题环节。今天我为大家分享了一道单链表题——反转链表。 废话不多说&#xff0c;让我们直接进入正题吧。 二.正文 1.1题目信息 这是一道leetCode上面的一道题&#xff1a;https://leetcode.cn/problems/reverse-linked-list 1.2解…

【再探】设计模式— 工厂方法、单例及原型模式

创建型设计模式是处理对象创建的设计模式&#xff0c;主要特点是“将对象的创建与业务代码分离”。一共有五种&#xff1a;工厂方法模式、单例模式、原型模式、抽象工厂模式及建造者模式。 1 单例模式 需求&#xff1a; 在整个系统中只需要一个实例。管理共享资源&#xff0…