CMake常用命令指南

前言

本博客是在 CMake 保姆级教程 文章的学习上进行的总结,把常用CMake命令总结如下。

CMake基本命令

CMake 使用 # 进行行注释,使用 #[[ ]] 形式进行块注释。

# 行注释#[[块注释
]]

以下三个命令是使用CMake构建最简单的一个项目所需要的命令。

cmake_minimum_required:指定使用的 CMake 的最低版本;

project:定义工程名称,并可指定工程的版本、工程描述等;

add_executable :将指定的源码编译生成为一个可执行程序。

cmake_minimum_required(VERSION 3.0)
project(CALC)
add_executable(app add.c div.c main.c mult.c sub.c)

指定使用的 C++ 标准,set(CMAKE_CXX_STANDARD 11)


使用 set 定义变量

在 CMake 中,变量的值始终是字符串类型,且区分大小写。

set(<variable> <value>... [PARENT_SCOPE]) 设置一个普通变量,<variable> 表示变量名,<value>... 表示一个或多个参数,例如:

# 将 add.c div.c main.c mult.c sub.c 存储到 SRC 变量中
set(SRC add.c div.c main.c mult.c sub.c)# 取变量 SRC 的值
add_executable(app ${SRC})

使用 ${<variable>} 的形式取变量的值。


指定输出路径

程序的输出可能是一个可执行文件、可能是制作的共享库,可以通过以下命令设置指定的输出路径。

# 将输出路径指定为 /xxx/xxx
set(EXECUTABLE_OUTPUT_PATH /xxx/xxx)
# or
set(RUNTIME_OUTPUT_DIRECTORY /xxx/xxx)

EXECUTABLE_OUTPUT_PATHRUNTIME_OUTPUT_DIRECTORY 是预定义的宏,当设置了 RUNTIME_OUTPUT_DIRECTORY 时,EXECUTABLE_OUTPUT_PATH 就失效了。


搜索文件

在 CMake 中,可以使用 aux_source_directory 命令或者 file 命令 搜索项目中的头文件或源文件。

aux_source_directory(<dir> <variable>)<dir> 目录下的源文件存储到 <variable> 变量中。

file 命令具有很多功能,这里介绍搜索文件的功能。

file(GLOB <variable> [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS] [<globbing-expressions>...])

file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS] [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS] [<globbing-expressions>...])

<globbing-expressions>... 搜索的表达式,可以是指定目录,指定目录下的某种文件,理解为一种正则表达式就好了;GLOB 非递归搜索;GLOB_RECURSE 递归搜索;<variable> 搜索结果保存的变量名

上面时 CMake 文档中给出的命令示例,常用的形式如下:

# 非递归搜索 /xxx/xxx 下的 *.cpp 源文件
file(GLOB SRC /xxx/xxx/*.cpp)# 递归搜索 /xxx/xxx 下的所有 *.h 头文件
file(GLOB_RECURSE HEADER /xxx/xxx/*.h)

包含头文件

指定源文件对应的头文件,include_directories(/xxx/include) ,源文件对应的头文件指定在 /xxx/include 目录下。


制作动态库和静态库

以如下示例进行实验。

.
├── CMakeLists.txt
├── build
├── include
│   └── head.h
├── main.cpp
└── src├── add.cpp├── divi.cpp├── mul.cpp└── sub.cpp

制作静态库

CMakeLists.txt 内容如下

cmake_minimum_required(VERSION 3.0)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
# 制作静态库的命令
add_library(calc STATIC ${SRC_LIST})

步骤:

  1. 首先切换到项目更目录下,即顶层 CMakeLists.txt 文件所在的目录;
  2. cd build 切换到 build 目录下,build 目录用来存放 cmake 生成的 makefile 以及其他一些文件;
  3. 执行 cmake .. 命令,即根据 CMakeLists.txt 文件生成 makefile 文件;
  4. 依然保持在 build 目录下,执行 make 命令,即运行 makefile 文件,编译项目,生成静态库,默认生成的静态库在 build 目录下。若想要指定静态库的输出路径,可以使用 set(LIBRARY_OUTPUT_PATH /xxx/xxx) 命令设置输出路径。LIBRARY_OUTPUT_PATH 宏用来指定构建的共享库的存放路径。

Linux 下生成的静态库默认是不具有执行权限的,如下所示。因此在指定静态库生成的路径时,不能使用 EXECUTABLE_OUTPUT_PATHRUNTIME_OUTPUT_DIRECTORY 宏。

$ ls -l libcalc.a 
-rw-r--r-- 1 root root 5254 Dec  3 18:04 libcalc.a

制作动态库

CMakeLists.txt 内容如下:

cmake_minimum_required(VERSION 3.0)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 生成动态库
add_library(calc SHARED ${SRC_LIST})

和制作静态库的步骤相同。


同时生成动态库和静态库

当需要同时生成动态库和静态库时,不能如下所示简单的将上述的命令拼在一起,这样会导致静态库和动态库名字相同的冲突。

cmake_minimum_required(VERSION 3.0)
project(calc)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)# 生成动态库
add_library(${PROJECT_NAME} SHARED ${SRC_LIST})
# 生成静态库
add_library(${PROJECT_NAME} STATIC ${SRC_LIST})# output:
# CMake Error at CMakeLists.txt:10 (add_library):
#   add_library cannot create target "calc" because another target with the
#   same name already exists.  The existing target is a shared library created
#   in source directory "/workspace/cppCode/demo03".  See documentation for
#   policy CMP0002 for more details.

一种解决方案是,使用 set_target_properties 命令修改最终生成的静态库和动态库的名字,如下所示。

cmake_minimum_required(VERSION 3.0)
project(calc)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)# 生成动态库
add_library(${PROJECT_NAME}_shared SHARED ${SRC_LIST})
# 生成静态库
add_library(${PROJECT_NAME}_static STATIC ${SRC_LIST})# 修改生成的动态库和静态库的名称
set_target_properties(${PROJECT_NAME}_shared PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(${PROJECT_NAME}_static PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(target1 target2 ...PROPERTIES prop1 value1prop2 value2 ...)

将目标名称 target1prop1 属性设置为 value1 ;将目标名称 target2prop2 属性设置为 value2

链接静态库和动态库

以上述制作的静态库和动态库为例,程序代码结构如下所示:

.
├── CMakeLists.txt
├── build
├── include
│   └── head.h
├── lib
│   ├── libcalc.a
│   └── libcalc.so
├── main.cpp

链接静态库

链接静态库需要的命令如下:

# 指定静态库的路径,<lib path> 表示静态库的路径
link_directories(<lib path>)# 链接静态库的命令,<static lib> 表示静态库的名称,可以是全名 libxxx.a,或掐头去尾 xxx
link_libraries(<static lib> [<static lib>...])

CMakeLists.txt 内容如下,编译通过。

cmake_minimum_required(VERSION 3.0)
project(calc)
include_directories(${PROJECT_SOURCE_DIR}/include)
# 指定静态库的路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
# 链接静态库
link_libraries(calc)
add_executable(main main.cpp)

链接动态库

链接动态库使用 target_link_libraries 命令指定动态库,和链接静态库相似,直接看 CMakeLists.txt 内容:

cmake_minimum_required(VERSION 3.0)
project(calc)
include_directories(${PROJECT_SOURCE_DIR}/include)
# 指定动态库的路径
link_directories(${PROJECT_SOURCE_DIR}/lib)add_executable(main main.cpp)# 链接动态库
target_link_libraries(main calc)

需要注意的一个点是,链接动态库的命令 target_link_libraries 需要在 add_executable 命令后面,理由很简单:如上示例所示,add_executable(main main.cpp) 只有“生成”了 main 可执行文件之后,才能去加载动态库。

CMake构建项目案例(待补充…)

参考链接:

https://cmake.org/cmake/help/latest/

https://subingwen.cn/cmake/CMake-primer/

https://subingwen.cn/cmake/CMake-advanced/

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

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

相关文章

工作几年了,你真的懂 Redis 嘛?

大家好&#xff0c;我是伍六七。一个专注于输出 AI 编程内容的在职大厂资深程序员&#xff0c;全国最大 AI 付费社群破局初创合伙人&#xff0c;关注我一起破除 35 诅咒。 Redis 基本上是大部分技术公司都会使用的缓存框架&#xff0c;但是我发现很多程序员其实并不懂 Redis。 …

【数组】-Lc15-三数之和(排序+for循环+滑动窗口)

写在前面 最近想复习一下数据结构与算法相关的内容&#xff0c;找一些题来做一做。如有更好思路&#xff0c;欢迎指正。 目录 写在前面一、场景描述二、具体步骤1.环境说明2.代码 写在后面 一、场景描述 给定一个包含 n 个整数的数组 nums&#xff0c;判断 nums 中是否存在三个…

SSM新闻发布管理系统

SSM毕设分享 序号1&#xff1a;SSM新闻发布管理系统 1 项目简介 Hi&#xff0c;各位同学好&#xff0c;这里是郑师兄&#xff01; 今天向大家分享一个毕业设计项目作品【SSM新闻发布管理系统】 师兄根据实现的难度和等级对项目进行评分(最低0分&#xff0c;满分5分) 难度系数…

三极管在数字电路中的应用

一、认识三极管 三极管拥有3个引脚&#xff0c;分别对应3个级&#xff1a;基极(Base)、发射极&#xff08;Emitter&#xff09;、集电极(Collector)&#xff0c;如下图所示&#xff1b;下图横向左侧的是基极&#xff0c;带箭头的那个引脚就是发射极&#xff0c;另一个就是集电…

【PUSDN】java中easyexcel导入导出带有图片的Excel(main方法方式)

简述 java中easyexcel导入导出带有图片的Excel&#xff08;main方法方式&#xff09;&#xff0c;web方式详见另一篇 由于电脑音频问题&#xff0c;视频暂时没有解说声音&#xff0c; 回头重新补上 前情提示 如果有任何疑问、需求、技术支持&#xff0c;欢迎点赞&#xff0…

JavaWeb-XML

1.常见的配置文件 1.1 properties 数据库的连接就使用properties文件作为配置文件&#xff0c;properties文件中的配置信息是以键值对的形式存储的。 beiluo.jdbc.urljdbc:mysql://localhost:3306/beiluo beiluo.jdbc.drivercom.mysql.cj.jdbc.Driver beiluo.jdbc.usernamer…

[dfs] 图案计数

图案计数 题目描述 一张画布里有n行*m列个格子&#xff0c;其中有的格子里有颜色填充&#xff0c;有的格子是空的没有颜色填充。现在需要你写一个程序来数出画布里边有颜色填充的格子构成了多少个图案&#xff0c;其中图案的定义为&#xff1a; 如果两个有颜色的格子边相邻或…

提权(2), Netcat反弹shell

一, 简介 Netcat&#xff08;nc&#xff09;是一款网络工具&#xff0c;也被称为“瑞士军刀”&#xff0c;可以读写TCP或UDP网络连接&#xff0c;透过使用TCP或UDP协议的网络连接去读写数据. 它被设计成一个稳定的后门工具&#xff0c;能够直接由其它程序和脚本轻松驱动。同时…

【微信小程序】英文字母不换行问题 flex布局字符超出宽度折行问题:设置了word-break: break-all;和flex: 1;冲突flex不生效问题

flex布局中英文字符超出宽度不会自动折行的问题&#xff0c;但是设置了word-break: break-all&#xff1b;前面设置的flex: 1&#xff1b;就不生效了 1.英文字母不换行问题 .view_text {word-break: break-all; }如果使用flex仅仅设置word-break: break-all&#xff1b;是会影…

【hacker送书活动第7期】Python网络爬虫入门到实战

第7期图书推荐 内容简介作者简介大咖推荐图书目录概述参与方式 内容简介 本书介绍了Python3网络爬虫的常见技术。首先介绍了网页的基础知识&#xff0c;然后介绍了urllib、Requests请求库以及XPath、Beautiful Soup等解析库&#xff0c;接着介绍了selenium对动态网站的爬取和S…

HADOOP::Fsimage和Edits解析

NameNode被格式化之后&#xff0c;将在/opt/module hadoop-3.1.3/data/tmp/dfs/name/curent目录 中产生如下文件 fsimage_ 0000000000000000000 fsimage_ 0000000000000000000.md5 seen_txid VERSION (1) Fsimage文件: HDFS文件系统元数据的一个永久性的检查点&#xff0…

HJ1 字符串最后一个单词的长度

HJ1 字符串最后一个单词的长度 牛客url 描述 计算字符串最后一个单词的长度&#xff0c;单词以空格隔开&#xff0c;字符串长度小于5000。&#xff08;注&#xff1a;字符串末尾不以空格为结尾&#xff09; 输入描述&#xff1a; 输入一行&#xff0c;代表要计算的字符串&…

判断二叉树是否为完全二叉树

具体思路&#xff1a; 将二叉树层序遍历&#xff08;节点&#xff09;插进队列中&#xff0c;遇到空时就break&#xff08;退出循环&#xff09;&#xff0c;再重新遍历一遍&#xff0c;若空的后面又再次出现数据&#xff0c;则返回false&#xff08;不是完全二叉树&#xff0…

基于Java+Swing+Mysql图书管理系统(含实训报告)

基于JavaSwingMysql图书管理系统-含实训报告 一、系统介绍二、功能展示1.用户登陆 四、其他系统实现五、获取源码 一、系统介绍 该系统实现了查看登录界面、主页界面、图书类别管理、用户借阅记录、用户图书查询、用户图书归还、用户信息修改。 运行环境&#xff1a;idea、jd…

C# Spire操作Excel数据透视表

一、概述 数据透视表&#xff08;Pivot Table&#xff09;是一种交互式的表&#xff0c;可以进行某些计算&#xff0c;如求和与计数等&#xff0c;可动态地改变透视表版面布置&#xff0c;也可以重新安排行号、列标和页字段。当改变版面布置时&#xff0c;数据透视表也会按照新…

ASP.NET-BS结构的城市酒店入住信息管理系统的设计

2 理论基础 2.1 数据库技术 数据库技术应用中&#xff0c;经常用到的基本概念有&#xff1a;数据库&#xff08;DB&#xff09;、数据库管理系统&#xff08;DBMS&#xff09;、数据库系统&#xff08;DBS&#xff09;、数据库技术及数据模型。 数据库技术是研究数据库的结构、…

基于社区电商的Redis缓存架构-库存模块缓存架构(上)

库存模块缓存架构 我们先来分析一下库存模块的业务场景&#xff0c;分为入库和出库&#xff0c;入库的话&#xff0c;在库存模块中需要添加库存&#xff0c;由于库存也是 写多读多 的场景&#xff0c;那么也是以 Redis 作为主存储&#xff0c;MySQL 作为辅助存储 出库的话&am…

AMBA 5 CHI 协议节点实例和读数据的来源

1. CHI协议节点实例 如上图所示&#xff0c;RN-F、RN-I、HN-F、SN-F、HN-I、SN-I通过内部互联总线连接起来。这里的ICN可以是CMN-700。其中SN-F和SN-I是连接主存&#xff0c;RN-F和HN-F内部都有cache。 2. CHI读数据的可能来源 如上图所示&#xff0c;CHI协议中可能的读数据来…

Win中Redis部署与配置

1.下载msi版本 下载传送门 2.双击next-->next安装安装 3.密码配置以及开机自启 在配置文件中配置相应配置进行配置密码以及端口和ip port 6379指定 Redis 监听端口&#xff0c;默认端口为 6379&#xff0c;作者在自己的一篇博文中解释了为什么选用 6379 作为默认端口&…

初识Linux:保姆级教学,让你一秒记住Linux中的常用指令!

文章目录 前言一、LInux的背景及发展史二、Linux下的基本指令1、ls指令2、pwd指令3、cd指令4、touch指令5、mkdir指令&#xff08;重要&#xff09;6、tree指令7、rmdir指令和rm指令&#xff08;重要&#xff09;8、man指令&#xff08;重要&#xff09;9、cp指令&#xff08;重…