使用CMake构建静态库和动态库

news2024/11/15 19:27:15

使用CMake构建静态库和动态库

  • 一、准备工作
  • 二、动态库的构建
    • 2.1 工程改造
    • 2.2 编译动态库
    • 2.3 更多的说明
  • 三、静态库的构建
    • 3.1 错误的尝试
    • 3.2 新的构建指令
  • 四、动态库的版本号
  • 五、安装动态库和头文件

一、准备工作

本机演示环境为:
主机windows11 + vscode
虚拟机安装的是RHEL7.6系统
使用vscode远程ssh连接linux虚拟机。

使用CMake Tool自动创建一个名为hellolib的工程。创建方式此处不再赘述。可以参考我的另一篇博文:
《vscode使用CMake Tool插件构建第一个CMake的helloworld工程》

下面会对其进行一番改造。

二、动态库的构建

2.1 工程改造

hellolib工程根目录下新建一个子目录lib,放入源文件hello.hpp和hello.cpp

hello.hpp:

#pragma once

void say_hello();

hello.cpp:

#include "hello.hpp"
#include <iostream>

void say_hello(){
    std::cout << "Hello, from hellolib!\n";
}

在lib子目录下新建一个CMakeLists.txt, 内容如下:

set(LIBHELLO_SRC hello.cpp)
add_library(hello SHARED ${LIBHELLO_SRC})

修改hellolib工程根目录下的CMakeLists.txt, 内容如下:

cmake_minimum_required(VERSION 3.0.0)
project(hellolib VERSION 0.1.0)

add_subdirectory(lib)

# 下面都是CMake Tool自动生成的,本例中非必须
include(CTest)
enable_testing()

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

现在的工程看起来是这个样子:

20230101180244

2.2 编译动态库

仍然采用外部构建,工程根目录下新建一个build子目录:

cd build
cmake ..
make

此时我们就可以在 build/lib 子目录中得到一个 libhello.so , 这就是我们期望的动态库。

如果你要指定 libhello.so 生成的位置,可以通过在主工程文件 CMakeLists.txt 中修改 ADD_SUBDIRECTORY(lib)指令来指定一个编译输出位置或者在 lib/CMakeLists.txt 中添加SET(LIBRARY_OUTPUT_PATH <路径>)来指定一个新的位置。

2.3 更多的说明

关于上面的指令 add_library , 其语法格式如下:

ADD_LIBRARY(libname [SHARED|STATIC|MODULE]
    [EXCLUDE_FROM_ALL]
        source1 source2 ... sourceN)

你不需要写全 libhello.so,只需要填写 hello 即可,cmake 系统会自动为你生成
libhello.X

库的类型有三种:

  • SHARED,动态库
  • STATIC,静态库
  • MODULE,在使用 dyld 的系统有效,如果不支持 dyld,则被当作 SHARED 对待。

EXCLUDE_FROM_ALL 参数的意思是这个库不会被默认构建,除非有其他的组件依赖或者手
工构建。

三、静态库的构建

3.1 错误的尝试

同样使用上面的指令,我们在支持动态库的基础上再为工程添加一个静态库,按照一般的习惯,静态库名字跟动态库名字应该是一致的,只不过后缀是.a 罢了。

下面我们用这个指令再来添加静态库:

ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})

然后再在 build 目录进行外部编译,我们会发现,静态库根本没有被构建,仍然只生成了一个动态库。因为 hello 作为一个 target 是不能重名的,所以,静态库构建指令无效。

如果我们把上面的 hello 修改为 hello_static:

ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})

就可以构建一个 libhello_static.a 的静态库了。

这种结果显示不是我们想要的,我们需要的是名字相同的静态库和动态库,因为 target 名称是唯一的,所以,我们肯定不能通过 ADD_LIBRARY 指令来实现了。

3.2 新的构建指令

既然不能通过 ADD_LIBRARY 指令来实现, 那么这时候我们需要用到另外一个指令
SET_TARGET_PROPERTIES,其基本语法是:

SET_TARGET_PROPERTIES(target1 target2 ...
    PROPERTIES prop1 value1
    prop2 value2 ...)

这条指令可以用来设置输出的名称,对于动态库,还可以用来指定动态库版本和 API 版本。

在本例中,我们需要作的是向 lib/CMakeLists.txt 中添加一条:

SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")

这样,我们就可以同时得到 libhello.so/libhello.a 两个库了。

此时,lib子目录下的CMakeLists.txt内容是这样的:

set(LIBHELLO_SRC hello.cpp)
set(LIBNAME hello)
add_library(${LIBNAME} SHARED ${LIBHELLO_SRC})

add_library(hello_static STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME ${LIBNAME})

再次构建:

cd build
make clean
cmake ..
make

20230101183109

四、动态库的版本号

按照规则,动态库是应该包含一个版本号的,看起来像这个样子:

libhello.so.1.2
libhello.so ->libhello.so.1
libhello.so.1->libhello.so.1.2

为了实现动态库版本号,我们仍然需要使用 SET_TARGET_PROPERTIES 指令。具体使用方法如下:

SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)

将上述指令加入 lib/CMakeLists.txt 中,

set(LIBHELLO_SRC hello.cpp)
set(LIBNAME hello)
add_library(${LIBNAME} SHARED ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION 1.2 SOVERSION 1)

add_library(hello_static STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME ${LIBNAME})

20230101191651

五、安装动态库和头文件

动态库或者静态库构建完成后,还需要将libhello.a, libhello.so.x 以及 hello.hpp 安装到系统目录,才能真正让其他人开发使用,在本例中我们将 hello 的共享库安装到<prefix>/lib目录,将 hello.hpp 安装到<prefix>/include/hello 目录。

这里需要使用install指令,关于install指令的详细说明,请参考我的另一篇博文:
《第一个完整的CMake工程》

我们向 lib/CMakeLists.txt 中添加install指令:

set(LIBHELLO_SRC hello.cpp)
set(LIBNAME hello)
add_library(${LIBNAME} SHARED ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION 1.2 SOVERSION 1)

set(LIBNAMESTATIC hello_static)
add_library(${LIBNAMESTATIC} STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(${LIBNAMESTATIC} PROPERTIES OUTPUT_NAME ${LIBNAME})

install(TARGETS ${LIBNAME} ${LIBNAMESTATIC}
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)

install(FILES hello.hpp DESTINATION include/hello)

重新构建并安装:

cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
sudo make install

这里需要注意,如果是普通用户执行make install,可能会因为缺少权限导致执行失败,所以需要加上sudo,执行完毕后,就可以看到头文件和库文件已经安装到指定目录了,执行效果如下:

20230101193850

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

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

相关文章

人工智能在药物研发和生物技术中的应用:回顾与展望

人工智能(Artificial intelligence, AI)的出现正在重新塑造整个制药和生物技术行业的发展。几乎所有大大小小的生命科学和药物发现机构&#xff0c;都对采用人工智能驱动的发现平台表现出浓厚的兴趣&#xff0c;希望通过AI来简化研发工作&#xff0c;减少发现时间和成本&#x…

【C++基础】10:STL(二)

CppSTL&#xff08;二&#xff09; OVERVIEWCppSTL&#xff08;二&#xff09;一、函数对象1.函数对象&#xff1a;&#xff08;1&#xff09;概述&#xff1a;&#xff08;2&#xff09;简单使用&#xff1a;2.谓词&#xff1a;&#xff08;1&#xff09;一元谓词&#xff1a;…

LVGL学习笔记10 - 按钮Button

目录 1. Check型按钮 2. 修改样式 2.1 设置背景 2.1.1 颜色 2.1.2 透明度 2.1.3 渐变色 2.1.4 渐变色起始位置设置 2.2 修改边界 2.2.1 宽度 2.2.2 颜色 2.2.3 透明度 2.2.4 指定边 2.3 修改边框 2.4 修改阴影 2.4.1 宽度 2.4.2 透明度 2.4.3 偏移坐标 2.3.…

PHP代码审计系列(五)

PHP代码审计系列&#xff08;五&#xff09; 本系列将收集多个PHP代码安全审计项目从易到难&#xff0c;并加入个人详细的源码解读。此系列将进行持续更新。 数字验证正则绕过 源码如下 <?phperror_reporting(0); $flag flag{test}; if ("POST" $_SERVER[…

数值优化之凸集

本文ppt来自深蓝学院《机器人中的数值优化》 目录 1 凸集的定义 2 凸集的运算 1 凸集的定义 集合中任意两点连线形成的线段属于这个集合&#xff0c;这个集合是凸集。 注意&#xff1a;是否是凸集&#xff0c;集合的边界是否属于这个集合很重要 这涉及到构造最小凸包的问题…

行锁功过:怎么减少行锁对性能的影响?

在上一篇文章中,我跟你介绍了 MySQL 的全局锁和表级锁,今天我们就来讲讲 MySQL 的行锁。 MySQL 的行锁是在引擎层由各个引擎自己实现的。但并不是所有的引擎都支持行锁,比如 MyISAM 引擎就不支持行锁。不支持行锁意味着并发控制只能使用表锁,对于这种引擎的表,同一张表上…

Java中的四种引用类型

1.对象引用介绍 从 JDK1.2 版本开始&#xff0c;把对象的引用分为四种级别&#xff0c;从而使程序更加灵活的控制对象的生命周期。这四种级别由高到低依次为&#xff1a;强引用、软引用、弱引用和虚引用。 用表格整理之后&#xff0c;各个引用类型的区别如下&#xff1a; 2.强…

BOM编程:location对象

document 对象和window对象的location的区别 document对象的位置获取步骤是返回这个相关的全局对象的位置对象&#xff0c;如果这是完全活动的&#xff0c;否则为空。 Window对象的位置获取步骤是返回它的位置对象。每个Window对象都与创建Window对象时分配的Location对象的唯…

Spark01:Spark工作原理

1. Spark执行数据计算的整个流程 首先通过Spark客户端提交任务到Spark集群&#xff0c;然后Spark任务在执行的时候会读取数据源HDFS中的数据&#xff0c;将数据加载到内存中&#xff0c;转化为RDD&#xff0c;然后针对RDD调用一些高阶函数对数据进行处理&#xff0c;中间可以调…

ElementUI——案例1用户管理(基于SpringBoot)

1.前期准备 备注&#xff1a;主要涉及组件container组件&#xff0c;导航菜单组件&#xff0c;router路由组件&#xff0c;carousel 走马灯组件&#xff0c;Image组件&#xff0c;Table表格组件 #1.在项目开发目录使用脚手架新建vue项目&#xff08;需要提前安装好node和webp…

无字母数字webshell提高

前言 元旦快乐 -- 转眼就到了2023年 新的一年继续努力 在p神博客中看到一个 通过上传临时文件进行rce&#xff0c;便想着写一篇文章&#xff0c;记录一下这个小trick。太强了 比如给你下面这么一串代码。正如文章标题 无字母数字&#xff0c;如果匹配到字母和数字&#xf…

【Vuex快速入门】vuex基础知识与安装配置

vuex快速入门——什么是vuex&#xff1f;创作背景vuex基础知识一、vuex是什么&#xff1f;二、vuex的组成三、为什么使用vuex&#xff1f;四、什么时候使用vuex&#xff1f;vuex的安装配置一、直接下载 / CDN引用二、npm安装vuex三、yarn安装四、自己构建更多内容可参考Vuex官方…

[从零开始]用python制作识图翻译器·二

AlsoEasy-RecognitionTranslator需求分析系统分析功能拆解工程语言选择技术可行性分析具体实现需求分析 见上篇[从零开始]用python制作识图翻译器一 上篇分析了该产品的需求以及市场上的可行性&#xff08;没有被吊打的竞品&#xff09;。而本篇将着重于分析如何实现。 系统分析…

gateway基本配置

目录 1、gateway简介 2、gateway核心概念 3、路由 4、断言 5、过滤器 5.1、过滤器介绍 5.2、内置局部过滤器与使用 5.3、内置全局过滤器 5.4、自定义全局过滤器 5.4.1、黑名单校验 5.4.2、模拟登录校验 6、一个简单的gateway配置实例 1、gateway简介 路由转发 执行…

Linear Regression with PyTorch 用PyTorch实现线性回归

文章目录4、Linear Regression with PyTorch 用PyTorch实现线性回归4.1 Prepare dataset 准备数据集4.2 Design Model 设计模型4.2.1 __call__() 作用4.3 Construct Loss and Optimizer 构造损失和优化器4.4 Training Cycle 训练周期4.5 Test Model 测试模型4.6 Different Opti…

redis缓存淘汰策略

定时删除 Redis不可能时时刻刻遍历所有被设置了生存时间的key&#xff0c;来检测数据是否已经到达过期时间&#xff0c;然后对它进行删除。 立即删除能保证内存中数据的最大新鲜度&#xff0c;因为它保证过期键值会在过期后马上被删除&#xff0c;其所占用的内存也会随之释放。…

zookeeper学习笔记2(小D课堂)

zookeeper数据模型&#xff1a; 我们的zookeeper是以节点的形式存在的&#xff0c;这样的形式和数据结构中的树的形式很像。同时也很像我们的linux的结构&#xff0c;例如linux的/user/local目录下可以有我们的/usr/local/tomcat目录。这样的节点形式。 我们的zookeeper中的每…

算法练习-常用查找算法复现

一个不知名大学生&#xff0c;江湖人称菜狗 original author: jacky Li Email : 3435673055qq.com Time of completion&#xff1a;2023.1.1 Last edited: 2023.1.1 目录 算法练习-常用查找算法复现&#xff08;PS&#xff1a;1 -- 3自己写的&#xff0c;4、5懒得写了&#xf…

PHP开发者之路

我们经常会发现&#xff0c;历时四年软件专业的大学生毕业居然找不到工作&#xff0c;即便找到了工作也只能是做一些简单的辅助性工作。 那么我们不禁要问&#xff0c;究竟是什么原因让我们可爱的大学生们学而无用&#xff0c;或者用而不学呢&#xff1f; 我认为主要是因为现…

三角形年份aabb3n+1近似计算阶乘之和数据统计水仙花数韩信点兵倒三角形子序列的和分数化小数排列蛇形填数sprintf竖式问题

目录 P16_习题1-6_三角形 P16_习题1-7_年份 P20_eg2-1_aabb 为什么是int n a*1100 b*11 为什么要将向下取整&#xff1f; P22_eg2-2_3n1问题 P24_eg2-3_近似计算 P25_eg2-4_阶乘之和 P27_eg2-5_数据统计 P34_习题2-1_水仙花数 P34_习题2-2_韩信点兵 P34_习题2-3_倒…