lemonboard 发表于 2024-10-11 01:46

《Cmake构建实战》第二章之你好,CMake!

<div class='showpostmsg'># 《Cmake构建实战》第二章之你好!CMake
在上一篇中,我们搭建完成了windows环境的C/C++编译开发环境。本章我们尝试进入CMake的世界。
在开始之前,先讲一下为什么要选择CMake。主要还是因为CMake的跨平台的特性!CMake软件在不同系统环境下,已经为我们处理好了makefile的适配,这也让我有更多的精力去关注程序开发,代码编写。
在本书中,作者还罗列了其它的优势,如由开源社区维护,强大的脚本语言,向后兼容等。我在这里不展开详细说明了。总之,选择了,自己顺手了,便是优秀的工具了。
## Hello CMake
我们在上一个帖子已经安装了CMake程序,所以,今天我们先编写一个小的示例来验证一下CMake环境。我们的示例程序使用CMake语法中的message命令,输出文本的命令。
```shell
cmake_minimum_required(VERSION 3.20)
message("Hello EEWORLD! Hello CMake!")

project(helloworld)
AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(${PROJECT_NAME} ${SRC_LIST})
```
书中是使用的是脚本实现,我是使用CMakeLists.txt来实现。这样的主要原因,还是简单,直接,省时,省力。结果如下图所示:

以上,我们就验证了CMake安装及成功运行的示例。下面,我们再深入CMake语法。
## CMake程序
阅读本书时,我才注意到CMake有两种类型,分别为CMakeLists.txt(目录结构类型)和.cmake(脚本程序和模块程序)。为了便于后面的理解,我在这里摘录一下上述三种文件的定义解释:

- 目录结构CMakeLists.txt

项目顶层目录下的CMakeLists.txt,CMake会根据此文件构建目录结构,作为构建对应源程序时的工作目录和二进制输出目录。

- 脚本(< script >.cmake)

指定-P参数运行CMake命令行工具,可以执行脚本类型的CMake程序。

- 模块(< module >.cmake)

CMake的目录程序和脚本程序均可通过include命令引用CMake模块程序。CMake模块是主要代码复用单元。
## CMake命令参数
CMake程序由命令调用构成,类似于我们C语言的函数调用。如果是类似函数调用,那么CMake的命令调用也会有命令参数传入。命令参数五共有以下三种类型:

- 引号参数

用引号包裹在内的参数,而且CMake规定必须为双引号。这里注意一下,双引号是包含换行。如果取消换行,需要使用连字符'\'(反斜杠)。

- 非引号参数

指未被引号包裹的参数。这种参数不能包含任何空白符。注意:非引号参数不作为(书上使用“不总是”)整体参数传递命令,而是将其作为列表中的每一个元素都会作为一个单独的参数传递。

- 括号参数

CMake的括号参数会作为一个整体传递给命令。它不处理文本中的任何特殊字符,变量引用语法,直接保留原始文本。
## CMake变量
### 预定义变量
CMAKE_BINARY_DIR
构建树的顶层目录。这是项目()命令的工作目录。
CMAKE_SOURCE_DIR
当前处理的 CMakeLists.txt 文件所在的目录。
PROJECT_BINARY_DIR
与 CMAKE_BINARY_DIR 相同,但是以项目(project)名称为基础。
PROJECT_SOURCE_DIR
与 CMAKE_SOURCE_DIR 相同,但是以项目(project)名称为基础。
CMAKE_CURRENT_SOURCE_DIR
当前处理的 CMakeLists.txt 文件所在的目录。
CMAKE_CURRENT_BINARY_DIR
如果使用了 ${PROJECT_NAME}_BINARY_DIR ,它会指向构建目录。
CMAKE_MODULE_PATH
用于查找的自定义模块的路径。
CMAKE_SYSTEM_NAME
目标系统平台名称。
CMAKE_SYSTEM_VERSION
目标系统版本。
CMAKE_SYSTEM_PROCESSOR
目标系统的处理器架构。
CMAKE_C_COMPILER
用于编译 C 源文件的编译器。
CMAKE_CXX_COMPILER
用于编译 C++ 源文件的编译器。
BUILD_SHARED_LIBS
控制默认的库构建方式。如果未设置,默认构建静态库。
CMAKE_BUILD_TYPE
构建类型(Debug, Release, RelWithDebInfo, MinSizeRel)。
CMAKE_INSTALL_PREFIX
构建系统的默认安装目录。
CMAKE_LIBRARY_OUTPUT_DIRECTORY
构建的库文件输出目录。
CMAKE_ARCHIVE_OUTPUT_DIRECTORY
构建静态库文件的输出目录。
CMAKE_RUNTIME_OUTPUT_DIRECTORY
构建可执行文件的输出目录。
CMAKE_POLICY_DEFAULT_CMP0091
控制 CMake 的 CMP0091 策略。
CMAKE_EXE_LINKER_FLAGS
设置链接器标志,用于构建可执行文件。
CMAKE_MODULE_LINKER_FLAGS
设置链接器标志,用于模块构建。
CMAKE_SHARED_LINKER_FLAGS
设置链接器标志,用于构建共享库。
CMAKE_STATIC_LINKER_FLAGS
设置链接器标志,用于构建静态库。
CMAKE_C_FLAGS
设置 C 编译器标志。
CMAKE_CXX_FLAGS
设置 C++ 编译器标志。
CMAKE_C_FLAGS_DEBUG
设置 C 编译器的调试编译标志。
CMAKE_CXX_FLAGS_DEBUG
设置 C++ 编译器的调试编译标志。
CMAKE_C_FLAGS_RELEASE
设置 C 编译器的发布编译标志。
CMAKE_CXX_FLAGS_RELEASE
设置 C++ 编译器的发布编译标志。
### 定义变量
CMake也是使用变量做为存储数据的基本单元。set命令用于定义或赋值一个普通变量,缓存变量或环境变量。

- 定义普通变量

- 定义缓存变量

- 定义环境变量

我觉得这里的内容有点书面与学术提高了。书中还使用了函数调用来讲解,CMake是用于简化我编写makefile的,而不是增加我的复杂度的。所以,使用一个set命令足矣。
## CMake列表
- 定义列表变量

其实,这个就是set命令的参数扩展,即将单个值写成多个值。
```shell
set(a main.c bsp.c)
```
- 特殊的分号

分号在上面谈到的变量中,作为分隔元素使用了。但如果有转义的反斜杠时,这个分号不会用作分隔符。还有,当一个分号前面存在未闭合的方括号时,其也不会当作元素的分隔符。这个特殊的分号平时很少使用,这里也不再展开说明了。
考虑到我们的项目暂不需要支持复杂的控制结构。于是,第三章先学习到这里,我们先往下继续走,如后期有精力,再回头学习。


## 参考
1.CMake预定义变量,https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                               
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>
页: [1]
查看完整版本: 《Cmake构建实战》第二章之你好,CMake!