在各种项目类型中,可能我们的项目就是一个 库 项目,向其他人提供 我们开发好的 库 (windows下的 dll /lib ; linux下的 .a / .so);有时候在一个项目中,我们对部分功能 打包成 库,方便在不同地方进行调用

静态库 和 动态库 对项目 实现了 不同程度的解耦,

  • 静态库,往往会 链接时 加载,代码会复制一起打包到 可执行程序中
  • 动态库 更多是 运行时 加载,加载到内存,供可执行程序调用

学会使用 cmake 构建 静态库 和 动态库,是我们这篇文章的主要内容

本专栏的实践代码全部放在 github 上,欢迎 star !!!

如有问题,欢迎留言、或加群【392784757】交流

涉及命令

add_library(<name> [<type>] [EXCLUDE_FROM_ALL] <sources>...)

其中 type 用来指定构建库的类型【本篇 只针对 shared static 展开】

type

  • shared
  • static
  • ...

使用库

# 路径配置相关 有时候需要
include_directories()
link_directories() target_link_libraries() # 关键代码

代码部分

log/

|---|---|log.cpp

|---|---|log.h

|---|---|CMakeLists.txt

test_log/

|---|---|test_log.cpp

|---|---|CMakeLists.txt

CMakeLists.txt

log.h

// log.h
#ifndef LOG_H
#define LOG_H class Log
{
public:
Log();
};
#endif

log.cpp

#include "log.h"
#include <iostream>
using namespace std; Log::Log()
{
cout << "create Log" << endl;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.20)

project(log)

add_library(log STATIC log.cpp log.h)

test_log 下

test_log.cpp

#include <iostream>
#include "log.h"
using namespace std; int main()
{
Log log;
cout << "test log" << endl;
return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.20)

project(test_log)

include_directories("../log") # 头文件路径

# 指定库查找路径 windows 自动找 ../log/build/Debug ../log/build/Release
link_directories("../log/build") add_executable(test_log test_log.cpp) #指定加载的库
target_link_libraries(test_log log)

构建静态库

type 指定的是 static

cd log
cmake -B build -S .
cmake --build build cd test_log
cmake -B build -S .
cmake --build build

具体的还可以指定 lib的输出路径

动态库构建

我们 在 log 同级目录下 创建 CMakeLists.txt 内容如下

cmake_minimum_required(VERSION 3.20)

project(log)

include_directories(log)

# 添加log库编译 项目自带预处理变量 log_EXPORTS
add_library(log SHARED log/log.cpp) add_executable(test_log test_log/test_log.cpp log) target_link_libraries(test_log log)

windows下构建动态库存在问题

如果我们把 STATIC 改为 SHARED ,然后构建,发现会报错

LINK : fatal error LNK1104: 无法打开文件“Debug\log.lib”

其实 也就是 找不到.lib 文件

log.h 修改

// log.h
#ifndef LOG_H
#define LOG_H // __declspec(dllexport) 导出 log 到lib文件中 #ifndef _WIN32
#define CPP_API
#else
// 针对 windows 平台
// log 库文件调用 dllexport
// test_log 调用 dllimport
// 通过预定义宏 确定是谁在调用
#ifdef log_EXPORTS
#define CPP_API __declspec(dllexport) // 库项目调用
#else
#define CPP_API __declspec(dllimport) // 调用库项目 调用
#endif
#endif class CPP_API Log
{
public:
Log();
};
#endif

需要将 dll 中定义的 函数、类符号 等导出到lib 才能找到 【也就是 符号导出】

  • dll 二进制代码
  • lib 函数 符号 地址 【理解程度有限】

做法就是在 函数、类等 前面 添加 _declspec(dllexport),

关于 dllexport dllimport 的更详细解释,推荐这个

https://zhuanlan.zhihu.com/p/680966160

然后进行构建,成功!



【CMake系列】05-静态库与动态库编译的更多相关文章

  1. C++ 系列:静态库与动态库

    转载自http://www.cnblogs.com/skynet/p/3372855.html 这次分享的宗旨是——让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择 ...

  2. (转)HelloWorld CMake CMake中构建静态库与动态库及其使用

    继续完善Hello World,建立它的共享库, 包括静态库和动态库. 本节的任务: 1,建立一个静态库和动态库,提供HelloFunc函数供其他程序编程使用,HelloFunc 向终端输出Hello ...

  3. VisualGDB系列7:使用VS创建Linux静态库和动态库

    根据VisualGDB官网(https://visualgdb.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指正. 本文介绍如何在VS中创建静态库和动态库, ...

  4. C++静态库与动态库

    C++静态库与动态库 这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一 ...

  5. 在Linux下如何使用GCC编译程序、简单生成 静态库及动态库

      最近在编写的一个Apache  kafka 的C/C++客户端,,在看他写的 example中,他的编译是用librdkafka++.a和librdkafka.a    静态库编译的,,,而我们这 ...

  6. (转)C++静态库与动态库

    转自:http://www.cnblogs.com/skynet/p/3372855.html C++静态库与动态库 这次分享的宗旨是——让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别, ...

  7. 【转】C++静态库与动态库

    C++静态库与动态库 这次分享的宗旨是——让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一 ...

  8. C++静态库与动态库(比较透彻)

    这次分享的宗旨是——让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一本书<程序员的自 ...

  9. C++静态库与动态库详解

    1 库的概念? 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库. 2 动态库与静态库的概念? 先回顾一下编译过程: 2.1 静态库 静态库在链接阶段,会将汇编生成的目 ...

  10. Windows下静态库、动态库的创建和调用过程

    静态库和动态库的使用包括两个方面,1是使用已有的库(调用过程),2是编写一个库供别人使用(创建过程).这里不讲述过多的原理,只说明如何编写,以及不正确编写时会遇见的问题. //注:本文先从简单到复杂, ...

随机推荐

  1. Linux内核的5个子系统

    --- title: Linux内核的5个子系统 EntryName: subsystems_in_linux_kernel date: 2020-10-10 03:07:07 categories: ...

  2. I2S 总线学习:1-有关概念

    背景 I2S总线 是一种常见的总线,也是需要掌握的. 概念 I2S(Inter-IC Sound)总线, 又称 集成电路内置音频总线,是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准, ...

  3. joig2022_e 题解

    设计 \(f_i\) 表示以第 \(i\) 个数结尾的选择的最大值. 有 \(f_i = f_j + a_i\)(\(type_i \not = type_j\)). 发现可以选择的种类其实构成两段连 ...

  4. yb课堂实战之轮播图接口引入本地缓存 《二十一》

    轮播图接口引入缓存 CacheKeyManager.java package net.ybclass.online_ybclass.config; /** * 缓存key管理类 */ public c ...

  5. MySQL中为什么要使用索引合并(Index Merge)?

    本文分享自华为云社区<[华为云MySQL技术专栏]MySQL中为什么要使用索引合并(Index Merge)?>,作者:GaussDB 数据库. 在生产环境中,MySQL语句的where查 ...

  6. 万维网WWW

    万维网是一个大规模的联机式信息储存场所,能方便地从一个网络站点访问另一个网络站点.万维网是一个分布式的超媒体系统. 统一资源定位符URL URL表示从互联网上得到的资源位置和访问这些资源的方法,实际上 ...

  7. AI驱动音乐创新,网易数帆X云音乐刷新MIREX世界纪录 网易数帆 网易数帆

    在近期揭榜的2021国际音频检索评测大赛(MIREX)上,网易数帆易智语音团队携手网易云音乐音视频实验室,凭借生产级AI技术创新能力,在歌词识别和歌单识别两个赛道大幅打破世界纪录夺得冠军. MIREX ...

  8. mysql 临时表的好处

    客户端新建了一个会话,这个会话只是服务器与客户端1对1的关系,客户端可能在服务端建立一个临时表,满足客户端处理某些事务的需求,当客户端退出会话后,这个临时表自动drop,没有任何数据信息占用数据库空间 ...

  9. leetcode简单(数组,字符串,链表):[66, 67, 70, 83, 121, 141, 160, 169, ,206, 338]

    目录 66. 加一 67. 二进制求和 70. 爬楼梯 83. 删除排序链表中的重复元素 121. 买卖股票的最佳时机 141. 环形链表 160. 相交链表 169. 多数元素 206. 反转链表 ...

  10. oeasy教您玩转linux010204-figlet

    我们来回顾一下 上一部分我们都讲了什么? 用 apt 查询并下载了 linuxlogo 用字符画出了 linux 发行版的 logo 还查了手册,通过改参数控制输出信息 我们还能玩点什么呢? 这个实验 ...