当前位置:网站首页 > 云服务教程 > 正文

cmake教程详解(cmake使用教程)



1.初学者可以从头开始看起,详细学习。

2.本文也可用于有一定基础的读者,根据目录按需获取内容即可。


CMake 是一个开源、跨平台的构建系统,主要用于软件的构建、测试和打包。
CMake 使用平台无关的配置文件 CMakeLists.txt 来控制软件的编译过程,并生成适用
于不同编译器环境的项目文件。


CMake 使用#进行行注释, 它可以放在任何位置。

当我们执行 cmake . 指令之后源文件所在的目录会多一些文件。这样会导致整个项目目录看起来很混乱,不太容易管理和维护。这其实被称为 内部构建。

但 CMake 强烈推荐的做法是 外部构建
此时我们可以把生成的这些与项目源码无关的文件统一放到一个对应的目录里边,比
如将这个目录命名为 build,这就叫做 外部构建。

 
  

假如我们的项目中存在多个源文件,并且这些源文件需要被反复使用, 每次都直接将
它们的名字写出来确实是很麻烦,此时我们就可以定义一个变量,将文件名对应的字
符串存储起来,在 cmake 里定义变量需要使用 set 指令。

 
  

C++标准对应
有一宏叫做 CMAKE_CXX_STANDARD

方式一:

 
  

方式二:

 
  

在 CMake 中指定可执行程序输出的路径,也对应一个宏,叫做
EXECUTABLE_OUTPUT_PATH,它的值也是可以通过 set 命令进行设置。

 
  

如果此处指定可执行程序生成路径的时候使用的是相对路径 https://blog.csdn.net/m0_/article/details/xxx/xxx,那么这个路径
中的 https://blog.csdn.net/m0_/article/details/ 对应的就是 makefile 文件所在的那个目录

如果一个项目里边的源文件很多,在编写 CMakeLists.txt 文件的时候不可能将项目目
录的各个文件一一罗列出来,这样太麻烦了。所以在 CMake 中为我们提供了搜索文件
的命令:

1.aux_source_directory

 
  

2.file 

 
  
 
  

在编译项目源文件的时候,很多时候都需要将源文件对应的头文件路径指定出来,这
样才能保证在编译过程中编译器能够找到这些头文件,并顺利通过编译。在 CMake 中
设置头文件路径也很简单,通过命令 include_directories 就可以搞定了。

 
  

1.生成动态库

 
  

2.生成静态库

 
  

1.在 cmake 中链接动态库

 
  

target:指定要加载动态库文件的名字
  ○ 该文件可能是一个源文件
  ○ 该文件可能是一个动态库文件
  ○ 该文件可能是一个可执行文件


PRIVATE|PUBLIC|INTERFACE:动态库的访问权限,默认为 PUBLIC
  ○ 如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,
一般无需指定,使用默认的 PUBLIC 即可
  ○ 动态库的链接具有传递性,如果动态库 A 链接了动态库 B、 C;动态库 D 链
接了动态库 A;此时动态库 D 相当于也链接了动态库 B、 C,并可以使用动态库 B、
C 中定义的方法。 




PRIVATE|PUBLIC|INTERFACE 的区别
  ○ PUBLIC:在 public 后面的库会被 Link 到前面的 target 中,并且里面的符号
也会被导出,提供给第三方使用
  ○ PRIVATE:在 private 后面的库仅被 link 到前面的 target 中,并且终结掉,第
三方不能感知你调了啥库
  ○ INTERFACE:在 interface 后面引入的库不会被链接到前面的 target 中,只
会导出符号





动态库的链接和静态库是完全不同的
  • 静态库会在生成可执行程序的链接阶段被打包到可执行程序中,所以可执行程序
启动,静态库就被加载到内存中了。
  • 动态库在生成可执行程序的链接阶段不会被打包到可执行程序中,当可执行程序
被启动并且调用了动态库中的函数的时候,动态库才会被加载到内存。
因此,在 cmake 中指定要链接的动态库的时候,应该将命令写到生成了可执行文件之
后:





 
  

 有些时候,当我们去链接第三方的动态库的时候, 如果不指定链接路径,会报错找不
到动态库
。此时,我们在生成可执行程序之前,通过命令指定出要链接的动态库的位

 
  

2.在 cmake 中,链接静态库

 
  

1.安装可执行文件和库

 
  

• 参数中的 TARGETS 后面跟的就是我们通过 ADD_EXECUTABLE 或者
ADD_LIBRARY 定义的目标文件, 可能是可执行⼆进制、动态库、 静态库。
• 目标类型也就相对应的有三种, ARCHIVE 特指静态库, LIBRARY 特指动态库,
RUNTIME 特指可执行目 标⼆进制。
• DESTINATION 定义了安装的路径,如果路径以/开头,那么指的是绝对路径,这
时候 CMAKE_INSTALL_PREFIX 其实就无效了。如果你希望使用
CMAKE_INSTALL_PREFIX 来 定义安装路径,就要写成相对路径,即不要以/开头,那
么安装后的路径就是 ${CMAKE_INSTALL_PREFIX}/...






 
  

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


1. 可以使用-D 选项指定 CMAKE_INSTALL_PREFIX 参数, 如 cmake .. -
DCMAKE_INSTALL_PREFIX =/usr
2. 如果没有定义 CMAKE_INSTALL_PREFIX 会安装到什么地方? 可以尝试一
下, cmake ..;make;make install,你会发现 CMAKE_INSTALL_PREFIX 的默认定
义 是/usr/local



所以当我们使用源码安装第三方库时如果不希望安装到/usr/local 路径下,可以手动指定安装路径

2.安装普通文件

 
  

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

权限:OWNER_READ,OWNER_WRITE,OWNER_EXECUTE,GROUP_READ,GROUP_WRITE,GROUP_EXECUTE,WORLD_READ,WORLD_WRITE,WORLD_EXECUTE,SETUID和SETGID

3.安装非目标文件的可执行程序

 
  

在 CMake 中可以使用命令打印消息,该命令的名字为 message。

 
  

第一个参数通常不设置, 表示重要消息。
• STATUS : 非重要消息
• WARNING: CMake 警告, 会继续执行
• AUTHOR_WARNING: CMake 警告 (dev), 会继续执行
• SEND_ERROR: CMake 错误, 继续执行,但是会跳过生成的步骤
• FATAL_ERROR: CMake 错误, 终止所有处理过程




 
  

在 CMake 中我们也可以使用 add_definitions 来定义宏。

宏 功能 PROJECT_SOURCE_DI
R 使用 cmake 命令后紧跟的目录,一般是工程的根目录 PROJECT_BINARY_DIR 执行 cmake 命令的目录 CMAKE_CURRENT_SOURCE_DIR 当前处理的 CMakeLists.txt 所在的路径 CMAKE_CURRENT_BINARY_DIR target 编译目录 EXECUTABLE_OUTPUT_PATH 重新定义目标⼆进制可执行文件的存放位置 LIBRARY_OUTPUT_PATH 重新定义目标链接库文件的存放位置 PROJECT_NAME 返回通过 PROJECT 指令定义的项目名称 CMAKE_BINARY_DIR 项目实际构建路径,假设在 build 目录进行的构建,那
么得到的就是这个目录的路径

如果项目很大,或者项目中有很多的源码目录,在通过 CMake 管理项目的时候如果只
使用一个 CMakeLists.txt,那么这个文件相对会比较复杂,有一种化繁为简的方式就
给每个源码目录都添加一个 CMakeLists.txt 文件(头文件目录不需要),这样每个文
件都不会太复杂,而且更灵活,更容易维护。


嵌套的 CMake 是一个树状结构,最顶层的 CMakeLists.txt 是根节点,其次都是子节

。因此,我们需要了解一些关于 CMakeLists.txt 文件变量作用域的一些信息:
  • 根节点 CMakeLists.txt 中的变量全局有效
  • 父节点 CMakeLists.txt 中的变量可以在子节点中使用
  • 子节点 CMakeLists.txt 中的变量只能在当前节点中使用
我们还需要知道在 CMake 中父子节点之间的关系是如何建立的,这里需要用到一个
CMake 命令:




 
  

  • source_dir:指定了 CMakeLists.txt 源文件和代码文件的位置,其实就是指定子目录 
  • binary_dir:指定了输出文件的路径,一般不需要指定,忽略即可。
  • EXCLUDE_FROM_ALL:在子路径下的目标默认不会被包含到父路径的 ALL 目标
    里,并且也会被排除在 IDE 工程文件之外。用户必须显式构建在子路径下的目标。
通过这种方式 CMakeLists.txt 文件之间的父子关系就被构建出来了



下面我们实现一个加减乘除的案例:

根目录中的 CMakeLists.txt 文件内容如下:

 
  

 src 目录中的 CMakeLists.txt 文件内容如下:

 
  

然后我们只需要执行顶层cmake即可

(1)列表定义添加数据

 
  

(2)字符串内容替换

 
  

(3)if语句

 
  

(4)循环

 
  

(5)执行外部命令

 
  

背景:现在我们有一个项目模块用到了ODB框架(ODB 通过对象 - 关系映射,将对象的操作自动转换为对应的数据库操作。开发人员只需要关注对象本身的操作,比如创建一个新的对象,修改对象的属性,然后通过 ODB 提供的简单接口将这些操作持久化到数据库中),

此项目我们定义了student,class类,需要执行odb命令将其转换成对应的数据库表。

项目层级:

顶层cmake: 

 
  

test2目录下的子cmake文件:

 
  

首先我们在顶层cmake文件的同级目录下创建build目录,并进入build目录

执行命令 cmake .. 

观察此时build目录生成了一些临时文件 

 

执行 make 

 

我们可以看到成功在build/test2目录下生成了 一系列ODB命令生成的文件。

由于我们是嵌套cmake,所以cmake时在build目录下生成 了一个test2目录,

当我们执行make指令时 build目录下的test2目录是我们的ODB命令执行的路径

所以我们的ODB命令生成的相关文件在build/test2目录下。

(build对应顶层cmake文件,build/test2对应子cmake文件)

最后执行make install

我们在顶层cmake文件中的最后设置了:

 set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR})

对应为执行cmake命令所在路径

我们在子cmake文件中设置了:

INSTALL(TARGETS main RUNTIME DESTINATION bin)

所以最后我们生成了名为main的可执行文件在 build/bin目录下


感谢阅读,欢迎补充,指正,批评。

到此这篇cmake教程详解(cmake使用教程)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 程序员代码教程(程序员专用代码)2025-07-27 22:00:06
  • autohotkey教程(autohotkey中文教程下载)2025-07-27 22:00:06
  • MSVCP140.dll下载(msvcp140.dll下载教程)2025-07-27 22:00:06
  • ad20软件使用教程安装(ad20使用教程下载)2025-07-27 22:00:06
  • ewm系统的不足(ewm系统操作教程)2025-07-27 22:00:06
  • xmouse官网(xmouse设置教程)2025-07-27 22:00:06
  • 2258xt开卡详细教程(2259xt开卡教程)2025-07-27 22:00:06
  • ad19铺铜教程(ad18铺铜教程)2025-07-27 22:00:06
  • Ubuntu镜像下载地址(ubuntu官网镜像下载教程)2025-07-27 22:00:06
  • u盘制作系统盘教程图解(u盘制作系统步骤)2025-07-27 22:00:06
  • 全屏图片