初识CMake,如何编写一个CMake工程(上)

您所在的位置:网站首页 opencv使用什么语言编写 初识CMake,如何编写一个CMake工程(上)

初识CMake,如何编写一个CMake工程(上)

2023-11-04 10:58| 来源: 网络整理| 查看: 265

如何编写一个CMake工程 笔者想分享CMake工程的原因?1 接触CMake1.1 认识CMake被广泛的使用?1.2 了解CMake运行流程1.3 Make和Makefile是什么关系?1.4 CMake与CMakeLists又是什么? 2 从源码到可执行程序的流程3 一个源文件Demo13.1 第一个CMakeLists.txt 4 同一个目录多个源文件Demo24.1 aux_source_directory查找指定路径下的所有源文件 5 多个目录Demo36 根CMakeLists.txt流程7 CMake语法预设常用变量8 参考文献

初识CMake,如何编写一个CMake工程(下) https://blog.csdn.net/weixin_39956356/article/details/115260616?spm=1001.2014.3001.5501

笔者想分享CMake工程的原因? CMake的目标? 跨平台自动编译,实现代码写一份,在Windows、Linux等系统,甚至不同处理器上,如X86、ARM等。从而做到“Write once, run everywhere”CMake的影响力? 选择CMake作为整个项目的助手,无疑是一个正确的选择。比如熟知的openCV、openVINO、VTK、ITK、KDE等。笔者接触CMake已经有一段时间,恰好看到一篇好的文章,借此以入门的姿态分享所得最后会分享一些资料,代码在github可以下载,原文链接也会给出,欢迎批评指正。Github https://github.com/ve2102388688/myCmakeDemos 1 接触CMake 1.1 认识CMake被广泛的使用?

从下图可以看出,CMake现已经被广泛使用。

支持各种编译器GCC、Clang、MSVC等支持大部分平台Windows、Linux、macOS等支持底层语言C/C++等 在这里插入图片描述 1.2 了解CMake运行流程

如下图,源文件和该目录下的CMakeLists.txt在CMake作用下会生成Makefile文件,之后使用make命令进行编译、make test进行测试、make install进行安装。 CMake解决了什么问题? 显然,简化了人们编写Makefile文件的难度,对于大型应用写一个Makefile是不现实、极难维护的。 在这里插入图片描述

1.3 Make和Makefile是什么关系?

问题:当源文件比较多时,一般不适合直接通过gcc来编译代码,难道要一个一个写吗?如果修改了呢?文件移动了呢? 解决:需要一个自动化的编译工具。Make(GNU Make)是一个自动化软件,用于将源代码文件编译为可执行的二进制文件从而完成自动化编译。Make工具编译的时候需要Makefile文件提供编译规则,Makefile定义了一系列的编译规则,包括编译的先后顺序,哪些文件需要重新编译等操作。利用Make工具可以自动完成编译工作,如果修改了某几个源文件,则只重新编译这几个源文件。如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。利用这种自动编译极大地提高了开发效率,避免了不必要的重新编译。

1.4 CMake与CMakeLists又是什么?

CMake是更加抽象的跨平台的项目管理工具,CMakeLists.txt文件在CMake作用下生成Makefile文件。 这里想简要谈下CMake语法

CMakeLists.txt这个文件名不可拼错一个字符,否则编译失败内置了很多预定义变量名PROJECT_BINARY_DIR、CMAKE_C_FLAGS、CMAKE_CXX_FLAGS等内置很多API,如aux_source_directory、include_directories、project、target_link_libraries等,注意这些API名字 大小写不敏感这里一定要讲讲CMakeLists.txt工程结构,每一个目录下都应该有CMakeLists.txt!!!,根CMakeLists.txt会收集所有目录下的子CMakeLists.txt,这好像有点像Kconfig和.config意味哈 2 从源码到可执行程序的流程

为什么会分析这个问题?难道这对写CMakeLists.txt有影响? 答案是肯定的,因为CMakeLists.txt中的代码顺序是有要求的,正如编译器需要

预处理->编译->汇编->链接

上面的顺序是不可以颠倒,难道有先链接再编译??? 在这里插入图片描述

3 一个源文件Demo1

源文件是一个计算指数的函数,这里主要分析CMakeLists.txt该怎么写?不关系源文件怎么写的哈,为了节省篇幅,下面就不会再贴源文件的代码了。所有的源文件代码都在Github,自己独立写CMakeLists.txt哈。

#include #include /** * power - Calculate the power of number. * @param base: Base value. * @param exponent: Exponent value. * * @return base raised to the power exponent. */ double power(double base, int exponent) { int result = base; int i; if (exponent == 0) { return 1; } for(i = 1; i if (argc DIR_SRC})

CMake 会将当前目录所有源文件的文件名赋值给变量 DIR_SRC,再指示变量 DIR_SRC中的源文件需要编译成一个名称为 Demo 的可执行文件。

5 多个目录Demo3

工程会很复杂,一般同main.cc同级下的源文件可以用上面的方法解决。但是有多个目录呢? 这里有一个math目录,怎么告诉CMake呢?我想至少有两点

在根CMakeLists.txt中告诉有一个子目录math在math中再写一个CMakeLists.txt告诉根CMakeLists.txt需要处理我这个子目录 . ├── CMakeLists.txt ├── del.sh ├── main.cc └── math ├── CMakeLists.txt ├── MathFunctions.cc └── MathFunctions.h

第一步:add_subdirectory添加子目录,当然这要放在add_executable,这是显然的,难道能调换过来吗?请看上面的编译流程,如果把顺序整反了,还在检查拼写错误是不应该。

# 编译其他目录下的文件,如math add_subdirectory(math)

第二步: 建立子CMakeLists.txt,这时候你不应该在使用CMAKE_MINIMUM_REQUIRED、project,因为根CMakeLists.txt只有一个,子CMakeLists.txt只需要做好子目录应该做的事情,如:只需要编译math目录下的文件并生成静态库!!! 注意 这里只编译成动态、静态库哈,使用add_library(库名 源文件) 即可,不要使用add_executable哈,你要清楚你在干什么?链接一个exe?还是链接一个.lib,.dll还是.so,,a?

子CMakeLists.txt

# 将本目录下的所有文件全部编译成静态库 aux_source_directory(. MATH_DIR_SRC) add_library(mathfun ${MATH_DIR_SRC})

根CMakeLists.txt

# cmake的最低版本号,注意VERSION需要大写 cmake_minimum_required(VERSION 2.8) # 工程名 project(Demo3) # 编译其他目录下的文件,如math add_subdirectory(math) # 编译当前目录下的文件 add_executable(Demo main.cc) # 把其他目录下的静态、动态库链接进来 target_link_libraries(Demo mathfun)

这里多说一句,下面的代码编译器会做什么,我想大概是这样的

看见stdio.h、stdlib.h进行预处理,因为系统库最后只需要链接glibc中即可看见math/MathFunctions.h,先去编译MathFunctions,将其编程成库,供main链接重复第二步,其他文件…因为main函数是最后才编译的,其实也就是把其他库的函数地址拼在一起。如果找不到就会报链接失败,如ld问题,LNK2019 #include #include #include "math/MathFunctions.h" // 其他文件.....

输出的一部分 1 发现要编译target mathfun,因为add_subdirectory(math),链接成libmathfun.a供main使用 2. 编译main 3. Linking CXX executable Demo,自始至终可执行程序就一个,链接打包后就是Demo

Scanning dependencies of target mathfun [ 25%] Building CXX object math/CMakeFiles/mathfun.dir/MathFunctions.cc.o [ 50%] Linking CXX static library libmathfun.a [ 50%] Built target mathfun Scanning dependencies of target Demo [ 75%] Building CXX object CMakeFiles/Demo.dir/main.cc.o [100%] Linking CXX executable Demo [100%] Built target Demo 6 根CMakeLists.txt流程

根据编译流程,根CMakeLists.txt书写流程大致如下,接下来会逐步完善

定义一个最低的版本号 定义一个工程 ------------------------------------------ 定义配置信息,如编译选项、Debug/Release、版本号、自定义宏名、条件编译 ------------------------------------------ 添加其他子目录 添加目标exe ------------------------------------------ 添加install 添加测试test 7 CMake语法预设常用变量

这里提下CMAKE_ROOT,也就是安装路径,如/usr/share/cmake-3.10

变量含义CMAKE_MAJOR_VERSIONcmake 主版本号;CMAKE_MINOR_VERSIONcmake 次版本号;CMAKE_C_FLAGS设置 C 编译选项;CMAKE_CXX_FLAGS设置 C++ 编译选项;PROJECT_SOURCE_DIR工程的根目录;PROJECT_BINARY_DIR运行 cmake 命令的目录;CMAKE_CURRENT_SOURCE_DIR当前CMakeLists.txt 所在路径;CMAKE_CURRENT_BINARY_DIR目标文件编译目录;EXECUTABLE_OUTPUT_PATH重新定义目标二进制可执行文件的存放位置LIBRARY_OUTPUT_PATH重新定义目标链接库文件的存放位置CMAKE_ROOT/usr/share/cmake-3.10

未按待续

8 参考文献

https://mp.weixin.qq.com/s/wLJkkLTup_Uf7X8MfDYNMQ

https://mp.weixin.qq.com/s/WglXaNNDETKKu6zICRYswQ

https://mp.weixin.qq.com/s/67lPVyWUXG0SPJm4AOHmBA

在线帮助文档 https://cmake.org/cmake/help/v3.10/



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3