CMakeList.txt -- 编写保姆式教程

news2024/11/27 4:39:41

     致每一个还坚持在互联网和软件行业的同路人。

     最近有朋友问我为什么选择当程序员,我也不明白。可能是缺少社交能力,可能更喜欢心理上保存平静,可能是为了那份对于从无到有的沉浸感和满足感。

 目录

欢迎加入陈达书--C++交流群: Errrr113(非诚勿扰)


 定义

PROJECT关键字 

 XXXX_BINARY_DIR 和 XXXX _SOURCE_DIR

SET关键字 

MESSAGE关键字

ADD_EXECUTABLE关键字

 语法的基本原则

内部构建和外部构建

HELLO更像一个工程

ADD_SUBDIRECTORY指令

更改二进制的保存路径

安装

静态库和动态库的构建

动态库的版本号

安装共享库和头文件

使用外部共享库和头文件

DEBUG编译

 定义

        cmake是一种高级编译工具,所有的操作系统都是通过编译CMakeList.txt来完成的,当多个人用不同的语言或者编译器开发同一个项目的时候,最终要输出一个可执行文件或者共享库的时候使用cmake很方便。

        camke的下载网址:cmake不同版本下载地址

PROJECT关键字 

        可以用来指定工程的名字和支持的语言,默认支持所有的语言。

        project(XXXX)            ===>          指定了工程的名字,并且支持所有语言

        project(XXXX CXX)     ===>        指定了工程的名字,并且支持的语言是C++

        project(XXXX C CXX)  ===>       指定了工程的名字,并且支持的语言是C 和 C++

 XXXX_BINARY_DIR 和 XXXX _SOURCE_DIR

        <projectname>_BINARY_DIR 和 <projectname>_SOURCE_DIR它们都指向了当前的工作目录,当工程的名字发生改变时这两个变量的名字也会跟着改变。

        使用 PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR

SET关键字 

        用来显示指定变量

        SET(SRC_LIST main.cpp) ==> SRC_LIST变量就包含了main.cpp

        SET(SRC_LIST main.cpp demo1.cpp demo3.cpp demo1.h) ==> SRC_LIST变量就包含了main.cpp demo1.cpp demo3.cpp demo1.h

        设置使用g++编译器

        set(CMAKE_CXX_COMPILER "g++")

        指定编译器

        set(CMAKE_CXX_STANDARD 11)

        添加c++11的支持,nation指定目标程序的cpu架构来进行程序优化 -O3优化等级

        set(CMAKE_CXX_FLAGS "-std=c++11 -march=native -O3")

        ===> native 就是相当于自检查cpu,-march是gcc优化选项,-Ox 这个参数只有在 cmake -DCMAKE_BUILD_TYPE=release时有效

        版本号

        set (XXXX VERSION 0.0.1) 

MESSAGE关键字

        向终端输出用户自定义的信息

        主要包含三种信息:

        SEND_ERROR    ==>   产生错误,生成编译过程中被跳过

        STAUS                 ==>   输出前缀为一的信息

        FATAL_ERROR   ==>   立即终止所有cmake过程

        message(STATUS "This is BINARY dir" $(PROJECT_BINARY_DIR))

        message(STATUS "This is SOURCE dir"  $(PROJECT_SOURCE_DIR))

ADD_EXECUTABLE关键字

        生成可执行文件

        ADD_EXECUTABLE(XXX ${SRC_LIST})   ===>  生成可执行文件hello,源文件读取变量SRC_LIST中的内容

        ADD_EXECUTABLE(XXX main.cpp) ===> 也可以直接填写 main.cpp

        工程名和生成的可执行文件hello是没有任何关系 ==> 工程名和可执行

 语法的基本原则

        变量使用${}方法取值,但是在IF控制语法中是直接使用变量名的

        指令(参数1 参数2...)参数使用括号()括起来,参数之间使用空格或者分号分隔。

        例如:ADD_EXECUTABLE(XXX main.cpp demo.cpp)

        或者ADD_EXECUTABLE(XXX main.cpp demo.cpp)

        指令是大小写无关的,参数和变量是大小写相关的 ==> 建立指令全部大写

        

        语法注意事项:

        SET{SRC_LIST main.cpp}可以写成SET{SRC_LIST "main.cpp"} ==> 如果源文件名中含有空格,就必须要加双引号。

        ADD_EXECUTABLE(hello main) =>  后缀可以不写,会自动寻找.c和.cpp文件,最好同时存在main.cpp和main.c

内部构建和外部构建

        内部构建: 上述例子就是内部构建,他产生的临时文件特别多,不方便清理。

        外部构建:  就会把生成的临时文件放到build目录下,不会对源文件源任何影响

        推荐使用外部构建:

        1.建立一个build目录,可以是任何地方,建立在当前目录下

        2.进入build,运行cmake .. ==> 表示上级目录,你可以写CMakeLists.txt所在的绝对路径,生成的文件都在build目录下了

        3.在build目录下,运行make来构建项目

        

        使用外部构建

        PROJECT_SOURCE_DIR ==> 指工程路径

        PROJECT_BINARY_DIR ==> 编译路径             build目录的绝对路径

HELLO更像一个工程

        1.为工程添加一个子目录src,用来放置工程源代码

        2.添加一个子目录dec,用来存放这个工程的文档

        3.在工程目录添加文本文件 COPYRIGHT README ==> 描述项目的安装、编译方法

        4.在工程目录添加一个 runhello.sh脚本,用来调用hello二进制

        5.将构建后的目标文件放入构建目标的bin子目录

        6.将doc目录的内容以及COPYRIGHT/README 安装到 /usr/share/doc/cmake

        .

        |---- build

        |---- CMakeList.txt

        |---- src

                |---- CMakeList.txt

                |---- main.cpp

# ==> 外层CMakeLists.txt
#     PROJECT(CmakeList)
#     ADD_SUBDIRECTORY(src bin)
# ==> src下的CMakeLists.txt
#     ADD_EXECUTABLE(hello main.cpp)

 

会生成很多中间文件,我们关注我们需要关注的部分就可以了

ADD_SUBDIRECTORY指令

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXECLUDE_FROM_ALL])

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

2.EXECLUDE_FROM_ALL函数从将某个目录排除在外

ADD_SUBDIRECTORY(src bin)

1.将src子目录加入工程并指定编译输出(包含编译中间结果) 路径为bin目录

2.如果不进行bin目录的指定,那么编译结果(包括中间结果)都将存放在build 和 src下

上述没有指定bin的路径,其实我们可以通过更改二进制的保存路径来指定bin目录,不使用默认生成的路径(build中)。

更改二进制的保存路径

SET 指令重新定义 EXECUTABLE_OUTPUT_PATH 和 LIBRARY_OUTPUT_PATH变量来指定最终的目标二进制的位置。

SET{EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin}

SET{LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib}

注:哪里要改变目标存放的路径,就在哪里加入上述的定义

  

安装

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

        指定目录安装:

        make install DESTDIR=/xxx/xxx

        ./configure -prefix=/xxx/xxx

-------------------------------------------------------------------------------------------------------------------------

        使用CMAKE一个指令: INSTALL

        INSTALL的安装可以包括:二进制、动态库、静态库、文件、目录、脚本等

        使用CMake一个新的变量: CMAKE_INSTALL_PREFIX

-------------------------------------------------------------------------------------------------------------------------

目录结构:

.
|__build
|__CMakeList.txt

|__COPYRIGHT
|__doc
|     |__hello.txt
|__README
|__XXXX.sh
|__src
     |__CMakeList.txt
     |__main.cpp

-------------------------------------------------------------------------------------------------------------------------安装文件COPYRIGHT和README

INSTALL(FILES COPYRIGHT README DESTINATION xxx/xxx/xxx/)

FILES ====>文件

DESTINATION ===> 路径

1.可以写绝对路径

2.可以写相对路径,相对路径实际是: ${CMAKE_INSTALL_PREFIX}/<DESTINATION>

 CMAKE_INSTALL_PREFIX 默认是  /usr/local/

 cmake -DCMAKE_INSTALL_PREFIX=/usr 在cmake的时候指定CMAKE_INSTALL_PREFIX

安装脚本

INSTALL(PROGRAMS xxxx.sh DESTINATION bin)

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

说明: 实际安装到的是 /usr/local/ ==> 默认路径是/usr/local

安装doc中的hello.txt

1.通过在doc目录构建CMakeList.txt,通过install下的file

2.直接通过在工程目录通过

INSTALL(DIRECTORY doc/ DESTINATION xxx/xxx/xxx)

DIRECTORY后面连接的是所在Source目录下的相对路径

注意:abc和abc/有很大区别:

目录名不以/结尾: 将整个目录安装到目标路径

目录名以/结尾: 将整个目录中的内容安装到目标路径

静态库和动态库的构建

任务:

1.建立一个静态库和动态库,提供HelloFunc函数供其他程序使用,HelloFunc向终端输出 Hello World

 2.安装头文件与共享库

静态库和动态库的区别:

1.静态库的扩展名一般为 ".a" 或者 ".lib",动态库的扩展名一般为".so"或者".dll"
2.静态库在编译时会直接整合到目标程序中,编译成功的可执行文件可独立运行
3.动态库在编译时不会放到连接的目标程序中,即可执行文件无法单独运行

构建实例:

.
|--- build
|--- CMakeLists.txt
|--- lib

      |--- CMakeLists.txt
      |--- hello.cpp
      |--- hello.h

 

同时构建静态库和动态库

1.一种错误的示范:这种方式只会构建一个动态库,不会构建出静态库,虽然静态库.a

ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})

2.修改动态库的名字,这样是可以的

ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})

3.但是在实际的开发过程中,我们往往希望静态库和动态库的名字相同

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

ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})

SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")

SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)

ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

SET_TARGET_PROPERTIES(hello PROPERTIES OUTPUT_NAME "hello")

SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)

 

动态库的版本号

SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1) 

安装共享库和头文件

<prefix>的默认路径是  /usr/local

文件放到该目录下

INSTALL(FILES hello.h DESTINATION include/hello)

二进制、静态库、动态库安装都用TARGETS

ARCHIVE 特指静态库,  LIBRARY 特指动态库, RUNTIME 特指可执行目标二进制

 

使用外部共享库和头文件

准备一个项目:去调用上面生成的动态库

.
|--- build
|--- CMakeLists
|--- src
       |--- CMakeLists.txt
       |--- main.cpp

 

 

DEBUG编译

cmake -DCMAKE_BUILD_TYPE=debug ..

cmake -DCMAKE_BUILD_TYPE=release ..

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

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

相关文章

LitCTF Writeup By AheadSec

文章目录 Web我Flag呢&#xff1f;Follow me and hack mePing导弹迷踪PHP是世界上最好的语言&#xff01;&#xff01;作业管理系统Vim yyds这是什么&#xff1f;SQL &#xff01;注一下 &#xff01;就当无事发生Flag点击就送&#xff01;Http pro max plus1zjs彩蛋 Pwn只需要…

Jenkins持续集成项目搭建与实践—基于Python Selenium自动化测试

Jenkins简介 Jenkins是Java编写的非常流行的持续集成&#xff08;CI&#xff09;服务&#xff0c;起源于Hudson项目。所以Jenkins和Hudson功能相似。 在华为工作了10年的大佬出的Web自动化测试教程&#xff0c;华为现用技术教程&#xff01;_哔哩哔哩_bilibili在华为工作了10…

如何批量归类文件,按自己批定位置保存

先来给大家看下目前文件是这样的&#xff0c;一个文件夹里面保存是图片 &#xff0c;另一个文件夹保存是文档&#xff0c;我是需要一个图片对应一个文档&#xff0c;保存在同一个文件夹中。 这个是图片 这个是文档 我的需求是一张图片和一个文档保存同一个文件夹中&#xff0c…

面试篇:JVM虚拟机

一、JVM介绍&#xff0c;JVM运行流程 1、什么是JVM Java Virtual Machine&#xff1a;Java程序的运行环境 (java二进制字节码的运行环境) 好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收机制 2、JVM运行流程 二、什么是程序计数器&#x…

Rufus v4.0.2035 开源USB引导启动盘制作工具单文件版

Rufus 是一个可以帮助格式化和创建可引导USB闪存盘的工具&#xff0c;比如 USB 随身碟&#xff0c;记忆棒等等。在如下场景中会非常有用&#xff1a;你需要把一些可引导的ISO格式的镜像&#xff08;Windows&#xff0c;Linux&#xff0c;UEFI等&#xff09;创建成USB安装盘的时…

Selenium自动化测试之使用真实用户Chrome环境

Selenium每次打开Chrome浏览器时&#xff0c;每次都是一个初始的全新环境&#xff0c;有时候&#xff0c;我们需要一些当前用户的一些设置和插件等&#xff0c;便可以通过ChromeOptions参数&#xff0c;通过指定用户数据目录--user-data-dir来设置成真实用户目录来实现。 浏览…

【剑指offer】学习计划day2

目录 一. 前言 二. 从尾到头打印链表 a.题目 b.题解分析 c.AC代码 二. 反转链表 a.题目 b.题解分析 c.AC代码 三. 复杂链表的复制 a.题目 b.题解分析 c.AC代码 一. 前言 本系列是针对Leetcode中剑指offer学习计划的记录与思路讲解。详情查看以下链接&#xff1a; 剑指of…

KF-GINS开源代码讲解直播课PPT和学习资源

KF-GINS开源代码讲解直播课PPT和学习资源 文章目录 KF-GINS开源代码讲解直播课PPT和学习资源KF-GINS 组合导航算法原理KF-GINS 代码设计KF-GINS 代码实现KF-GINS 常见问题KF-GINS 扩展直播的部分问题 武汉大学i2Nav团队开源的基于卡尔曼滤波的GNSS/INS组合导航系统&#xff08;…

【UmiJS项目】react-monaco-editor代码编辑器的安装与使用

一、git地址 monaco-editorreact-monaco-editor 二、安装 yarn add monaco-editor yarn add react-monaco-editor yarn add monaco-editor-webpack-plugin注意&#xff1a; monaco-editor 和 monaco-editor-webpack-plugin 需要按照以下对应版本来安装 本人使用的版本如下&a…

西门子PLC加减速时间的算法

1、新建工艺对象&#xff0c;在“动态”中可以设置最大转速&#xff08;30.0&#xff09;和启动/停止转速&#xff08;2.0&#xff09;以及加减速时间&#xff08;也可以计算得出&#xff09;。 加速度的计算方法为&#xff1a;&#xff08;最大转速-启动/停止速度&#xff09;…

ChatGPT、Midjourney不香了吗,New Bing 已向全球个人开放

文章目录 1. 前言2. 教程3. 开始 Bing AI 以上图片均由Bing AI生成。&#xff08;后文给出第一幅图的关键字&#xff09; 本文没有任何广告&#xff0c;放心食用&#xff0c;并且手把手教你怎么配置new bing&#xff0c;有需要的耐心看完哦&#xff0c;不懂的可私信我~ 1. 前…

Yarn安装及配置一件启停

Yarn安装及配置一件启停 数据、程序、运算资源&#xff08;内存、CPU)三者组在一起&#xff0c;才能完成数据的计算处理过程。在单机环境下&#xff0c;三者之间协调配合不是太大问题。为了应对海量数据的处理场景&#xff0c;Hadoop软件出现并提供了分布式处理思想。但是在分…

数据结构——双向链表(保姆级教程,包学包会)

1.双向链表的概念 双向链表就是带头双向循环链表 我们在学完单链表之后&#xff0c;就感觉这个非常简单了&#xff0c;他的主要表现就是拥有头节点&#xff0c;链表永不为空&#xff0c;不需要二级指针&#xff1b;可以通过一个节点找到上一个或者下一个节点&#xff1b;头尾…

MySQL基础-事务详解

本文主要介绍MySQL事务 文章目录 前言事务定义事务四大特性&#xff08;ACID&#xff09; 事务操作事务并发问题事务隔离级别 前言 参考链接&#xff1a; 链接1链接2 事务定义 事务是一组操作的集合&#xff0c;他是一个不可分割的工作单位&#xff0c;事务会把所有的操作作…

微服务入门SpringCloud

一、微服务的组成 注册中心&#xff1a;记录每个微服务调用地址、ip 配置中心&#xff1a;管理每个服务的配置 服务网关&#xff1a;身份校验&#xff0c; 分布式缓存&#xff1a;提升访问数据库的速度。 分布式搜索&#xff1a;海量缓存 消息队列&#xff1a;异步消息&#x…

【C++】还new不出对象?看看C++怎么做~(C++内存管理)

&#x1f9d1;‍&#x1f393;个人主页&#xff1a;简 料 &#x1f3c6;所属专栏&#xff1a;C &#x1f3c6;个人社区&#xff1a;越努力越幸运社区 &#x1f3c6;简 介&#xff1a;简料简料&#xff0c;简单有料~在校大学生一枚&#xff0c;专注C/C/GO的干货分…

Redis---订阅和发布

目录 消息系统命令 消息系统 ​ 发布/订阅&#xff0c;即 pub/sub&#xff0c;是一种消息通信模式&#xff1a;发布者也称为消息生产者&#xff0c;生产和发送消息到存储系统&#xff1b;订阅者也称为消息消费者&#xff0c;从存储系统接收和消费消息。这个存储系统可以是文件系…

安全多方计算:安全定义

参考文献&#xff1a;《密码协议》课程 PPT 文章目录 UM & AM安全定义编译器 Semi-honest & Malicious安全定义半诚实模型恶意模型 编译器Input-CommitmentAugmented Coin-TossingAuthenticated Computation编译器框架 UM & AM 安全定义 异步网络下的多方协议&am…

关于 Kafka 分区程序的关键细节

Apache Kafka 是当今事件流的事实标准。Kafka 如此成功的部分原因是它能够处理大量数据&#xff0c;每秒吞吐量达到数百万条记录&#xff0c;这在生产环境中并非闻所未闻。Kafka设计的一部分使这成为可能&#xff0c;那就是分区。 Kafka 使用分区将数据负载分散到集群中的代理…

UFT描述性编程及综合练习

1、录制登录操作改描述性编程。 登录的用户名、密码在global表中给出。有2组&#xff1a;自己的学号/mercury&#xff0c;自己的学号/123456。将登录的本地对象库清空。 要求&#xff1a; 分别采用直接描述性编程和Description描述性编程实现2组数据登录测试&#xff0c;用repo…