编译工具:CMake(三)| 最简单的实例升级

编译工具:CMake(三)| 最简单的实例升级

  • 前言
  • 过程
    • 语法解释
      • ADD_SUBDIRECTORY 指令
    • 如何安装
      • 目标文件的安装
      • 普通文件的安装:
      • 非目标文件的可执行程序安装(比如脚本之类)
      • 目录的安装
  • 修改 Helloworld 支持安装
  • 测试

在这里插入图片描述

前言

本篇博客的任务是让前面的 Hello World 更像一个工程,我们需要作的是:

  • 为工程添加一个子目录 src,用来放置工程源代码;
  • 添加一个子目录 doc,用来放置这个工程的文档 hello.txt
  • 在工程目录添加文本文件 COPYRIGHT, README;
  • 在工程目录添加一个 runhello.sh 脚本,用来调用 hello 二进制
  • 将构建后的目标文件放入构建目录的 bin 子目录;
  • 最终安装这些文件:将 hello 二进制与 runhello.sh 安装至/usr/bin,将 doc 目录的内容以及 COPYRIGHT/README 安装到/usr/share/doc/cmake/test2

过程

在/Compilation_tool/cmake/目录下建立 test2 目录。
将 test1 工程的 main.c 和 CMakeLists.txt 拷贝到 test2 目录中。

添加子目录 src
将main.c文件移动到src文件夹

mkdir src
mv main.c src

现在的工程是这个样子:
一个子目录 src,一个 CMakeLists.txt。
在这里插入图片描述
CMake要求为任何子目录建立一个CMakeLists.txt

所以进入src子目录,编写CMakeLists.txt如下:

ADD_EXECUTABLE(hello main.c)

将test2工程的CMakeLists.txt修改为:

PROJECT(HELLO)
ADD_SUBDIRECTORY(src bin)

然后建立 build 目录,进入 build 目录进行外部编译。

mkdir build
cd build
cmake ..
make

构建完成后,你会发现生成的目标文件 hello 位于 build/bin 目录中。
在这里插入图片描述

语法解释

ADD_SUBDIRECTORY 指令

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

这个指令用于向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置。

EXCLUDE_FROM_ALL 参数的含义是将这个目录从编译过程中排除,比如,工程的 example,可能就需要工程构建完成后,再进入 example 目录单独进行构建(当然,也可以通过定义依赖来解决此类问题)。

上面的例子定义了将 src 子目录加入工程,并指定编译输出(包含编译中间结果)路径为bin 目录。

如果不进行 bin 目录的指定,那么编译结果(包括中间结果)都将存放在build/src 目录(这个目录跟原有的 src 目录对应),

指定 bin 目录后,相当于在编译时将 src 重命名为 bin,所有的中间结果和目标二进制都将存放在 bin 目录。

换个地方保存目标二进制
ADD_SUBDIRECTORY 指令(不论是否指定编译输出目录),可以通过 SET 指令重新定义EXECUTABLE_OUTPUT_PATHLIBRARY_OUTPUT_PATH 变量,来指定最终的目标二进制的位置(指最终生成的 hello 或者最终的共享库,不包含编译生成
的中间文件)

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

<projectname>_BINARY_DIR PROJECT_BINARY_DIR 变量,他们指的编译发生的当前目录,如果是内部编译,就相当于 PROJECT_SOURCE_DIR 也就是工程代码所在目录,如果是外部编译,指的是外部编译所在目录,也就是本例中的 build
目录。

所以,上面两个指令分别定义了:可执行二进制的输出路径为 build/bin 和库的输出路径为 build/lib.
应该把这两条指令写在工程的 CMakeLists.txt 还是 src 目录下的CMakeLists.txt,把握一个简单的原则,在哪里 ADD_EXECUTABLEADD_LIBRARY,如果需要改变目标存放路径,就在哪里加入上述的定义。
在这个例子里,当然就是指 src 下的 CMakeLists.txt 了。

如何安装

安装的需要有两种,一种是从代码编译后直接 make install 安装,一种是打包时的指定目录安装。

HelloWorld 进行安装需要引入一个新的 cmake 指令INSTALL 和一个非常有用的变量CMAKE_INSTALL_PREFIX

CMAKE_INSTALL_PREFIX变量类似于 configure 脚本的 – prefix

常见的使用方法是这个样子:

cmake -DCMAKE_INSTALL_PREFIX=/usr 

INSTALL 指令用于定义安装规则,安装的内容可以包括目标二进制、动态库、静态库以及文件、目录、脚本等。

INSTALL 指令包含了各种安装类型,分开解释如下:

目标文件的安装

INSTALL(TARGETS targets...[[ARCHIVE|LIBRARY|RUNTIME][DESTINATION <dir>][PERMISSIONS permissions...][CONFIGURATIONS[Debug|Release|...]][COMPONENT <component>][OPTIONAL]] [...])

参数中的 TARGETS 后面跟的就是我们通过 ADD_EXECUTABLE 或者ADD_LIBRARY定义的目标文件,可能是可执行二进制、动态库、静态库。

目标类型也就相对应的有三种,ARCHIVE 特指静态库,LIBRARY 特指动态库,RUNTIME特指可执行目标二进制。

DESTINATION 定义了安装的路径,如果路径以/开头,那么指的是绝对路径,这时候CMAKE_INSTALL_PREFIX 其实就无效了。如果你希望使用 CMAKE_INSTALL_PREFIX 来定义安装路径,就要写成相对路径,即不要以/开头,那么安装后的路径就是

${CMAKE_INSTALL_PREFIX}/<DESTINATION 定义的路径>

举个简单的例子:

INSTALL(TARGETS myrun mylib mystaticlibRUNTIME DESTINATION binLIBRARY DESTINATION libARCHIVE DESTINATION libstatic)

上面的例子会将:
可执行二进制 myrun 安装到${CMAKE_INSTALL_PREFIX}/bin 目录
动态库 libmylib 安装到${CMAKE_INSTALL_PREFIX}/lib 目录
静态库 libmystaticlib 安装到${CMAKE_INSTALL_PREFIX}/libstatic 目录

特别注意的是不需要关心 TARGETS 具体生成的路径,只需要写上 TARGETS 名称就可以了。

普通文件的安装:

INSTALL(FILES files... DESTINATION <dir>[PERMISSIONS permissions...][CONFIGURATIONS [Debug|Release|...]][COMPONENT <component>][RENAME <name>] [OPTIONAL])

可用于安装一般文件,并可以指定访问权限,文件名是此指令所在路径下的相对路径。如果默认不定义权限 PERMISSIONS,安装后的权限为:OWNER_WRITE, OWNER_READ,GROUP_READ,和 WORLD_READ,即 644 权限。

非目标文件的可执行程序安装(比如脚本之类)

INSTALL(PROGRAMS files... DESTINATION <dir>
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[RENAME <name>] [OPTIONAL])

跟上面的 FILES 指令使用方法一样,唯一的不同是安装后权限为:
OWNER_EXECUTE, GROUP_EXECUTE, 和 WORLD_EXECUTE,即 755 权限

目录的安装

INSTALL(DIRECTORY dirs... DESTINATION <dir>[FILE_PERMISSIONS permissions...][DIRECTORY_PERMISSIONS permissions...][USE_SOURCE_PERMISSIONS][CONFIGURATIONS [Debug|Release|...]][COMPONENT <component>][[PATTERN <pattern> | REGEX <regex>][EXCLUDE] [PERMISSIONS permissions...]] [...])

这里主要介绍其中的 DIRECTORYPATTERN 以及PERMISSIONS参数。
DIRECTORY 后面连接的是所在 Source 目录的相对路径,但务必注意:
abc 和 abc/有很大的区别。如果目录名不以/结尾,那么这个目录将被安装为目标路径下的 abc,如果目录名以/结尾,
代表将这个目录中的内容安装到目标路径,但不包括这个目录本身。PATTERN用于使用正则表达式进行过滤,PERMISSIONS 用于指定 PATTERN 过滤后的文件权限。

修改 Helloworld 支持安装

添加 doc 目录及文件:

cd /Compilation_tool/cmake/test2
mkdir doc
vi doc/hello.txt

随便填写一些内容并保存

在工程目录添加 runhello.sh 脚本,内容为:

hello

添加工程目录中的 COPYRIGHT 和 README
touch COPYRIGHT
touch README

下面改写各目录的 CMakeLists.txt 文件。

1、安装 COPYRIGHT/README,直接修改主工程文件 CMakelists.txt,加入以下指令:

INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake/t2)

2、安装 runhello.sh,直接修改主工程文件 CMakeLists.txt,加入如下指令:

INSTALL(PROGRAMS runhello.sh DESTINATION bin)

3、安装 doc 中的 hello.txt
因为 hello.txt 要安装到//share/doc/cmake/t2,所以我们不能直接安装整个 doc 目录,这里采用的方式是安装 doc 目录中的内容,也就是使用 ” doc/” 在工程文件中添加

INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake/t2)

测试

现在进入 build 目录进行外部编译,注意使用 CMAKE_INSTALL_PREFIX 参数,这里我们将它安装到了/tmp/t2 目录:

cmake -DCMAKE_INSTALL_PREFIX=/tmp/t2/usr ..

然后运行

make
make install

这时候在计算机的 tmp路径下就多了 t2 文件夹
t2的目录为
在这里插入图片描述

如果你要直接安装到系统,可以使用如下指令:

cmake -DCMAKE_INSTALL_PREFIX=/usr ..

如果没有定义CMAKE_INSTALL_PREFIX会安装到什么地方?
CMAKE_INSTALL_PREFIX 的默认定义是/usr/local

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

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

相关文章

解决右键打印html只能识别1页的问题

hello,大家好久不见,昨天在开发中遇到了一个问题,就是在自己开发的网页中右键-->打印&#xff0c;由于页面内容过多&#xff0c;打印出来的内容只被识别到一页。 针对这一问题&#xff0c;查阅了好多资料最终解决啦。 1.问题重现 大家可以看到这个是我们开发的页面,公司需要…

2023最新最全最细版本~ESP8266/ESP01S烧录AT固件

硬件准备 图上有两种型号的模块均可刷写AT固件 ① ESP01S ② ESP8266NODEMCU 软件准备(私聊免费分享) ESP01S1烧录方式 如图使用模块烧录座的方式~ 模块插入烧录座后直接连接电脑的USB接口即可~ ESP8266NODEMCU烧录方式 如图usb直接连接的方式~ 一端接模块的USB口&…

数据暴涨时代,该如何数据治理?_光点科技

随着信息技术的迅猛发展&#xff0c;数据已经成为现代社会的核心资源。在这个被称为"数据暴涨时代"的时代里&#xff0c;大量的数据源源不断地被产生和积累&#xff0c;但如何有效地管理、分析和利用这些数据成为了一个迫切需要解决的问题。数据治理&#xff0c;作为…

【Spring源码】Spring扩展点及顺序

Spring扩展点及顺序 01-调用BeanFactoryPostProcessor的构造器 02-调用了BeanFactoryPostProcessor的postProcessBeanFactory 03-调用了BeanPostProcessor构造器 04-调用InstantiationAwareBeanPostProcessor构造方法 05-调用了InstantiationAwareBeanPostProcessor接口的Befo…

Memory Analyzer(MAT)分析内存

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、 使用3.1 hprof 文件准备3.1.1 Android sutdi…

【SpringBoot学习笔记】04. Thymeleaf模板引擎

模板引擎 所有的html元素都可以被thymeleaf替换接管 th:元素名 templates下的只能通过Controller来跳转&#xff0c;templates前后端分离&#xff0c;需要模板引擎thymeleaf支持 模板引擎的作用就是我们来写一个页面模板&#xff0c;比如有些值呢&#xff0c;是动态的&#x…

cuda+anaconda+pytorch按照教程

首先安装显卡对应的CUDA版本&#xff0c;关键点在于区别显卡支持的CUDA最高版本和运行版本 1、查看当前显卡支持的最高版本&#xff0c;有两种方式&#xff1a; 1&#xff09;NVIDIA控制面板—>帮助—>系统信息—>组件—>NVCUDA.dll对应版本 请注意&#xff0c;12…

2023年国赛数学建模思路 - 案例:ID3-决策树分类算法

文章目录 0 赛题思路1 算法介绍2 FP树表示法3 构建FP树4 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模…

项目:基于UDP的TFTP文件传输

1&#xff09;tftp协议概述 简单文件传输协议&#xff0c;适用于在网络上进行文件传输的一套标准协议&#xff0c;使用UDP传输特点&#xff1a; 是应用层协议 基于UDP协议实现 数据传输模式 octet&#xff1a;二进制模式&#xff08;常用&#xff09; mail&#xff1a;已经不再…

分布式 - 服务器Nginx:一小时入门系列之代理缓冲与缓存

官方文档&#xff1a;https://nginx.org/en/docs/http/ngx_http_proxy_module.html 1. 代理缓冲 proxy_buffer 代理缓冲用于临时存储从后端服务器返回的响应数据。通过使用代理缓冲&#xff0c;Nginx可以在接收完整的响应后再将其发送给客户端&#xff0c;从而提高性能和效率…

照耀国产的星火,再度上新!

国产之光&#xff0c;星火闪耀 ⭐ 新时代的星火⭐ 多模态能力⭐ 图像生成与虚拟人视频生成⭐ 音频生成与OCR笔记收藏⭐ 助手模式更新⭐ 插件能力⭐ 代码能力⭐ 写在最后 ⭐ 新时代的星火 在这个快速变革的时代&#xff0c;人工智能正迅猛地催生着前所未有的革命。从医疗到金融…

【管理运筹学】第 5 章 | 整数规划 (1,问题提出与分支定界法)

文章目录 引言一、整数规划问题的提出1.1 整数规划的数学模型1.2 整数规划问题的求解 二、分支定界法2.1 分支与定界2.2 基本求解步骤&#xff08;一&#xff09;初始化&#xff08;二&#xff09;分支与分支树&#xff08;三&#xff09;定界与剪枝&#xff08;四&#xff09;…

SpringBoot之HandlerInterceptor拦截器的使用

&#x1f600;前言 本篇博文是关于拦截器-HandlerInterceptor的使用&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的动…

Linux 多进程

目录 0x01 linux中特殊的进程 0x02 进程的标识 0x03 创建子进程 0x01 linux中特殊的进程 0号进程&#xff1a;idle进程&#xff0c;系统启动加载的进程1号进程&#xff1a;systemd进程&#xff0c;系统初始化&#xff0c;是所有进程的祖先进程 init2号进程&#xff1a;kthre…

YOLOv5白皮书-第Y6周:模型改进

&#x1f4cc;本周任务&#xff1a;模型改进&#x1f4cc; 注&#xff1a;对yolov5l.yaml文件中的backbone模块和head模块进行改进。 任务结构图&#xff1a; YOLOv5s网络结构图: 原始模型代码&#xff1a; # YOLOv5 v6.0 backbone backbone:# [from, number, module, args]…

每日汇评:黄金在 200 日移动平均线附近似乎很脆弱,关注美国零售销售

1、金价预计将巩固其近期跌势&#xff0c;至 6 月初以来的最低水平&#xff1b; 2、对美联储再次加息的押注继续限制了贵金属的上涨&#xff1b; 3、金融市场现在期待美国零售销售报告带来一些有意义的推动&#xff1b; 周二金价难以获得任何有意义的牵引力&#xff0c;并在…

Mac RN环境搭建

IOS RN ios android原生环境搭建有时候是真恶心&#xff0c;电脑环境不一样配置也有差异。 我已经安装官网的文档配置了ios环境 执行 npx react-nativelatest init AwesomeProject 报错 然后自己百度查呀执行 gem update --system 说是没有权限&#xff0c;执行失败。因…

POSTGRESQL 关于安装中自动启动的问题 详解

开头还是介绍一下群&#xff0c;如果感兴趣Polardb ,mongodb ,MySQL ,Postgresql ,redis &#xff0c;SQL SERVER ,ORACLE,Oceanbase 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请加 liuaustin3微信号 &…

OpenSSH 远程升级到 9.4p1

OpenSSH 远程升级到 9.4p1 文章目录 OpenSSH 远程升级到 9.4p1背景升级前提1. 升级 OpenSSL2. 安装并启用Telnet 升级OpenSSH 背景 最近的护网行动&#xff0c;被查出来了好几个关于OpenSSH 的漏洞。这是因为服务器系统安装后&#xff0c;直接使用了系统自带版本的OpenSSH &am…

2023-08-15 linux mipi 屏幕调试:有一个屏幕开机时候不显示,开机后按power 按键休眠唤醒就可以显示。原因是reset gpio 被复用

一、现象&#xff1a;今天更新了一个新版本的buildroot linux sdk &#xff0c;调试两个mipi 屏幕&#xff0c;这两个屏幕之前在其他的sdk都调好了的&#xff0c;所有直接把配置搬过来。但是有一个屏幕可以正常显示&#xff0c;有一个屏幕开机时候不显示&#xff0c;开机后按po…