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

news2024/11/27 12:16:20

编译工具: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 mystaticlib
	RUNTIME DESTINATION bin
	LIBRARY DESTINATION lib
	ARCHIVE 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.coloradmin.cn/o/882513.html

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

相关文章

H3C交换机MIB库

非常齐全的官方MIB库 为Zabbix监控华三交换机提供诸多方便。 如下信息提供下载链接和下载账号: MIB清单下载:交换机-新华三集团-H3C MIB库:MIB-新华三集团-H3C

Python Opencv实践 - 图像透射变换

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) rows,cols img.shape[:2] print(rows,cols)#opencv中的透射变换&#xff0c;需要一个3x3透射变换矩阵 #这个矩阵可以通过…

基于IDE Eval Resetter延长IntelliJ IDEA等软件试用期的方法(包含新版本软件的操作方法)

本文介绍基于IDE Eval Resetter插件&#xff0c;对集成开发环境IntelliJ IDEA等JetBrains公司下属的多个开发软件&#xff0c;加以试用期延长的方法。 我们这里就以IntelliJ IDEA为例&#xff0c;来介绍这一插件发挥作用的具体方式。不过&#xff0c;需要说明使用IDE Eval Rese…

Spring Boot+Redis 实现消息队列实践示例

Spring BootRedis 实现一个轻量级的消息队列 文章目录 Spring BootRedis 实现一个轻量级的消息队列0.前言1.基础介绍2.步骤2.1. 引入依赖2.2. 配置文件2.3. 核心源码 4.总结答疑 5.参考文档6. Redis从入门到精通系列文章 0.前言 本文将介绍如何利用Spring Boot与Redis结合实现…

二自由度机械臂的gazebo仿真

一、创建ros软件包 #1、创建工作空间 mkdir 2d_robot_ws cd 2d_robot_ws mkdir src cd src catkin_init_workspace #2、编译工作空间 cd .. catkin_make #3、创建软件包 catkin_create_pkg 2d_robot std_msgs rospy roscpp二、创建模型文件 1、编写urdf模型文件 在2d_robot_…

科研经费的来源有哪些?

目前&#xff0c;高校在我国科技创新中发挥着越来越重要的作用&#xff0c;自然高校获得经费也越来越多。一所高校的科研经费充足&#xff0c;越有利于科研学术水平的提高。那么科研经费的来源有哪些呢&#xff1f; 1. 国家拨款 对于高校的科研发展享有国家的重点支持。近年来…

人工智能原理(3)

目录 一、搜索策略 1、引言 2、盲目搜索 3、启发式搜索 二、基于状态空间图搜索技术 1、图搜索基本概念 2、状态空间搜索 3、一般的图搜索算法 三、盲目搜索 1、广度优先搜索 2、深度优先搜索 3、有界深度搜索和迭代加深搜索 四、启发式算法 1、启发性信息和评估…

容器技术发展和编排技术演进之路

目录 Jail 时代 1979 年 贝尔实验室发明 chroot 2000 年 FreeBSD 4.0 发行 FreeBSD Jail 2001 年 Linux VServer 发行 2004 年 Solaris Containers 发行 云时代 2006 年 google 推出 Process Containers 2008 年 LXC 推出 2011 年 CloudFoundry 推出 Warden 2013 年 LMCTFY 启动…

JavaScript 【DOM】

【DOM】 原创内容&#xff0c;转载请注明出处&#xff01; 一、DOM基本概念 DOM&#xff08;Document Object Model&#xff0c;文档对象模型&#xff09;是 JavaScript 操作 HTML 文档的接口&#xff0c;使文档操作变得非常优雅、简便。 DOM 最大的特点就是将 HTML 文档表示…

Pycharm找不到Conda可执行文件路径(Pycharm无法导入Anaconda已有环境)

在使用Pycharm时发现无法导入Anaconda创建好的环境&#xff0c;会出现找不到Conda可执行文件路径的问题。 解决 在输入框内输入D:\anaconda3\Scripts\conda.exe&#xff0c;点击加载环境。 注意前面目录是自己Anaconda的安装位置&#xff0c;之后就可以找到Anaconda的现有环…

STM32F407使用Helix库软解MP3并通过DAC输出,最精简的STM32+SD卡实现MP3播放器

只用STM32单片机SD卡耳机插座&#xff0c;实现播放MP3播放器&#xff01; 看过很多STM32软解MP3的方案&#xff0c;即不通过类似VS1053之类的解码器芯片&#xff0c;直接用STM32和软件库解码MP3文件&#xff0c;通常使用了labmad或者Helix解码库实现&#xff0c;Helix相对labm…

Mariadb高可用MHA

本节主要学习了Mariadb高可用MHA的概述&#xff0c;案例如何构建MHA 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、概述 1、概念 MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。…

如何使用Kali Linux进行渗透测试?

1. 渗透测试简介 渗透测试是通过模拟恶意攻击&#xff0c;评估系统、应用或网络的安全性的过程。Kali Linux为渗透测试人员提供了丰富的工具和资源&#xff0c;用于发现漏洞、弱点和安全风险。 2. 使用Kali Linux进行渗透测试的步骤 以下是使用Kali Linux进行渗透测试的基本…

搭建WebDAV服务手机ES文件浏览器远程访问

文章目录 1. 安装启用WebDAV2. 安装cpolar3. 配置公网访问地址4. 公网测试连接5. 固定连接公网地址6. 使用固定地址测试连接 有时候我们想通过移动设备访问群晖NAS 中的文件,以满足特殊需求,我们在群辉中开启WebDav服务,结合cpolar内网工具生成的公网地址,通过移动客户端ES文件…

【Unity每日一记】进行发射,位置相关的方法总结

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

绘制世界地图or中国地图

写在前面 在8月初,自己需要使用中国地图的图形,自己就此也查询相关的教程,自己也做一下小小总结,希望对自己和同学们有所帮助。 最终图形 这个系列从2022年开始,一直更新使用R语言分析数据及绘制精美图形。小杜的生信笔记主要分享小杜学习日常!如果,你对此感兴趣可以加…

【C++面向对象】--- 继承 的奥秘(下篇)

个人主页&#xff1a;平行线也会相交&#x1f4aa; 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【C之路】&#x1f48c; 本专栏旨在记录C的学习路线&#xff0c;望对大家有所帮助&#x1f647;‍ 希望我们一起努力、成长&…

自动化测试用例设计实例

在编写用例之间&#xff0c;笔者再次强调几点编写自动化测试用例的原则&#xff1a; 1、一个脚本是一个完整的场景&#xff0c;从用户登陆操作到用户退出系统关闭浏览器。 2、一个脚本脚本只验证一个功能点&#xff0c;不要试图用户登陆系统后把所有的功能都进行验证再退出系统…

CAS 的执行流程 ?CAS 中 ABA 问题如何解决 ?CAS 在 Java 中有哪些实现类 ?

目录 1. CAS 的执行流程 2. CAS 中的 ABA 问题 3. 如何解决 CAS 中的 ABA 问题 4.CAS 在Java 中的实现类有哪些 1. CAS 的执行流程 CAS 比较并替换的大致流程是这样的&#xff1a; 它有三个操作单位&#xff1a;V&#xff08;内存值&#xff09;&#xff0c;A&#xff08;…

【C++】做一个飞机空战小游戏(八)——生成敌方炮弹(rand()和srand()函数应用)

[导读]本系列博文内容链接如下&#xff1a; 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C】做一个飞…