当前位置: 首页 > news >正文

【CMake】CMake创建、安装、使用静态库和动态库

一、CMake创建静态库/动态库

使用CMake可以轻松生成对应程序编译好的静态库和动态库,用于打包发布,下面详细介绍如何实现

程序文件

首先我们有如下的程序,一些简单的数学运算,需要将它编译成静态库/动态库

mymath.h

#pragma onceint add(int x,int y);int sub(int x,int y);int multiply(int x,int y);int divide(int x,int y);

mymath.cpp

#include"mymath.h"int add(int x,int y){return x + y;    
}int sub(int x,int y){return x - y;
}int mutiply(int x,int y){return x * y;
}int divide(int x,int y){return x - y;
}

项目的结构如下

在这里插入图片描述

编写CMakeLists.txt

动态库

这里需要编写src/文件夹下的CMakeLists.txt,具体如下

ADD_EXECUTABLE(main main.cpp)SET(LIBMYMATH_SRC mymath.cpp)
ADD_LIBRARY(mymath SHARED ${LIBMYMATH_SRC})
  • 这里使用SET(LIBMYMATH_SRC mymath.cpp)定义了一个变量LIBMYMATH_SRC,代表了这个动态库所需的源文件

  • 然后使用ADD_LIBRARY关键字将动态库所需的源文件编译为动态库

    1. mymath是库名,也就是我们编译出来的动态库,编译后会有前缀lib以及后缀.so,即libmymath.so
    2. SHARED关键字,声明编译为动态库,最后的${LIBMYMATH_SRC}是上述定义的源文件的变量名,用于生成动态库

进入build路径,执行构建 & 编译指令

cmake .. && make 

最外层的CMakeLists.txt如下,设置了库文件的生成路径为 ${PROJECT_BINARY_DIR}/lib,即build/lib

PROJECT(HELLO)SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake/)INSTALL(PROGRAMS runhello.sh DESTINATION /usr/bin)INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake/)ADD_SUBDIRECTORY(src)

build/lib路径下,可以查看到我们编译生成的动态库libmymath.so
在这里插入图片描述

静态库

类似动态库,我们也可以生成静态库,只需要将SHARED关键字修改为STATIC关键字即可,因此不需要CMakeLists.txt几乎没改变

ADD_EXECUTABLE(main main.cpp)SET(LIBMYMATH_SRC mymath.cpp)# ADD_LIBRARY(mymath SHARED ${LIBMYMATH_SRC})ADD_LIBRARY(mymath STATIC ${LIBMYMATH_SRC})

构建、编译后,同样在build/lib下生成了静态库,前缀为lib,后缀为.a,即libmymath.a
在这里插入图片描述

同时创建静态库和动态库

如果同时生成静态库和动态库,如下的方法是不行的,只会生成动态库

ADD_EXECUTABLE(main main.cpp)SET(LIBMYMATH_SRC mymath.cpp)ADD_LIBRARY(mymath SHARED ${LIBMYMATH_SRC})ADD_LIBRARY(mymath STATIC ${LIBMYMATH_SRC})

构建、编译

cmake .. && make

发现build/lib下只有动态库生成,显然这样不是我们需要的结果

在这里插入图片描述

SET_TARGET_PROPERTIES 关键字
  • 我们需要使用到SET_TARGET_PROPERTIES关键字来帮助我们同时生成动态库和静态库

  • SET_TARGET_PROPERTIES 用于设置输出的名称,对于动态库,还可以用于指定动态库的版本和API版本

需要修改的CMakeLists.txt如下

ADD_EXECUTABLE(main main.cpp)SET(LIBMYMATH_SRC mymath.cpp)ADD_LIBRARY(mymath_static STATIC ${LIBMYMATH_SRC})#设置 mymath_static 输出为 mymath
SET_TARGET_PROPERTIES(mymath_static PROPERTIES OUTPUT_NAME "mymath")ADD_LIBRARY(mymath SHARED ${LIBMYMATH_SRC})

这样就不会冲突了,构建、编译后在build/lib目录下同时可以找到静态库和动态库

在这里插入图片描述

二、安装动态库和头文件

配合INSTALL关键字可以将静态库、动态库和头文件安装到指定路径,我们这里安装到:

  1. usr/local/lib
  2. usr/local/lib
  3. usr/local/include/mymath
  • 修改的是内层的CMakeLists.txt
  • 注意这里头文件使用的是FILES,静态库是ARCHIVE,动态库是LIBRARY,可执行文件是RUNTIME
  • 这些都是目标文件,因此需要使用TARGETS
ADD_EXECUTABLE(main main.cpp)SET(LIBMYMATH_SRC mymath.cpp)ADD_LIBRARY(mymath_static STATIC ${LIBMYMATH_SRC})#设置 mymath_static 输出为 mymath
SET_TARGET_PROPERTIES(mymath_static PROPERTIES OUTPUT_NAME "mymath")ADD_LIBRARY(mymath SHARED ${LIBMYMATH_SRC})INSTALL(FILES mymath.h DESTINATION include/mymath)INSTALL(TARGETS main mymath_static mymath 
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib 
LIBRARY DESTINATION lib)

进入到安装目录,查看是否存在对应的头文件、库文件、可执行文件,符合预期

在这里插入图片描述

三、使用静态库、动态库

  • 我们刚才已经成功编译好了库文件,并且将它们安装到了指定的位置,现在让我们看看如何使用它们吧
  • 为了方便测试,我们这里先删除mymath.cpp源文件和mymath.h头文件
rm mymath.cpp mymath.h

main.cpp中使用我们刚才编译的库的函数

#include<iostream>
#include"mymath.h"int main(){int x = 1, y = 1;int z = add(x,y);std::cout << "x + y = " << z << std::endl;return 0;
}

显然,这里找不到mymath.h这个头文件

在这里插入图片描述

  • 一种方法是,直接指定usr/local/include/mymath这个路径,但是这样比较死板,而且一般不会这样使用
  • 这里因为头文件默认的搜索路径是从/usr/local/include/以及/usr/include/开始,因此这里可以直接写mymath/mymath.h
#include<iostream>
#include"mymath/mymath.h"int main(){int x = 1, y = 1;int z = add(x,y);std::cout << "x + y = " << z << std::endl;return 0;
}

另一种方法,就是在src/CMakeLists.txt中加入如下的头文件搜索路径,这样直接指定mymath.h就可以找到了

INCLUDE_DIRECTORIES(/usr/local/include/mymath)

构建、编译

cmake && make

此时编译失败,因为找不到对应的函数,因为没有链接库

在这里插入图片描述

链接静态库

我们演示如何链接静态库,这里介绍一种方法:

  1. 使用LINK_DIRECTORIES命令指定链接的静态库的路径
  2. 使用TARGET_LINK_LIBRARIES命令添加指定路径下的库名,这里是libmymath.a
  3. 如果在TARGET_LINK_LIBRARIES前未指定路径,则使用默认的路径,如usr/libusr/local/lib

修改CMakeLists.txt

ADD_EXECUTABLE(main main.cpp)INCLUDE_DIRECTORIES(/usr/local/include/mymath)LINK_DIRECTORIES(/usr/local/lib)
TARGET_LINK_LIBRARIES(main libmymath.a)

构建、编译、运行

cmake .. && make && ./bin/main 

在这里插入图片描述

链接动态库

保留上面的CMakeLists.txt,只需要将libmymath.a改为libmymath.so,然后正常构建、编译

ADD_EXECUTABLE(main main.cpp)INCLUDE_DIRECTORIES(/usr/local/include/mymath)LINK_DIRECTORIES(/usr/local/lib)TARGET_LINK_LIBRARIES(main libmymath.so)

但是这样,运行时找不到对应的动态库,我们可以使用ldd ./bin/main查看是否找到了依赖的运行库

ldd ./bin/main

在这里插入图片描述

显然这里找不到,因此运行起来肯定不行

在这里插入图片描述

一种方法是,使用export设置LD_LIBRARY_PATH添加环境变量,但是这样关闭bash后就会失效

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

另一种方法,修改/etc/ld.so.conf.d/mymath.conf文件,添加上对应路径/usr/local/lib

sudo vim /etc/ld.so.conf.d/mymath.conf

添加上动态库路径

在这里插入图片描述

然后刷新缓存

sudo ldconifg

再次运行,成功找到了动态库

在这里插入图片描述

更多资料:https://github.com/0voice

http://www.lryc.cn/news/587108.html

相关文章:

  • LeetCode|Day8|1047. 删除字符串中的所有相邻重复项|Python刷题笔记
  • java.net.InetAddress
  • 嵌入式 Linux开发环境构建之安装 SSH 软件
  • MongoDB数据基本介绍
  • 小白成长之路-LVS
  • 【VSCode+LaTeX】科研写作环境搭建
  • C语言的一些随笔
  • 面试150 填充每个节点的下一个右侧节点指针Ⅱ
  • 006_测试评估与安全实践
  • 2025上海市“星光计划“信息安全管理与评估赛项二三阶段任务书
  • RAG篇(RAG的流程)
  • STM32-第六节-TIM定时器-2(输出比较)
  • Linux驱动开发2:字符设备驱动
  • iOS UI视图面试相关
  • 哪些行业的“反内卷”前景更好?
  • ADB 调试日志全攻略:如何开启与关闭 `ADB_TRACE` 日志
  • 【Datawhale夏令营】用AI做带货视频评论分析
  • [附源码+数据库+毕业论文+答辩PPT+部署教程+配套软件]基于SpringBoot+MyBatis+MySQL+Maven+Vue实现的交流互动管理系统
  • 每天学一个八股(二)——详解HashMap
  • 26-计组-指令执行过程
  • HTML5 离线存储
  • MyBatis04-MyBatis小技巧
  • Typecho后台编辑器自定义按钮开发实战指南
  • Spring Boot 集成 Spring Security 完整示例
  • Sping AI Alibaba
  • 《区间dp》
  • Linux锁的概念及线程同步
  • Python异步编程
  • 【版本控制】Perforce Helix Core (P4V) 完全入门指南(含虚幻引擎实战)
  • CAU数据挖掘第四章 分类问题