lemonboard 发表于 2024-11-3 19:26

《Cmake构建实战》第七章之实战演练

<div class='showpostmsg'># 《Cmake构建实战》第七章之实战演练
&emsp;&emsp;今天为大家分享一下《Cmake构建实战》第七章的学习内容。读了两遍第七章,我感觉内容略多,所以我的分享就以我的实现项目开发的使用视角来分享第七章这些属性与功能应用。本次示例以计算一串字符串的CRC16为示例做讲解。
## 应用场景1:生成可执行文件
&emsp;&emsp;这是我们最简单的应用场景了。也是我们最常用的场景之一。我们首先tree一下我们的示例项目文件结构:

&emsp;&emsp;通过上面的图片我们可以看到在app文件夹里面存放着应用层的.c/.h文件,主要包含main.c和main.h及crc.c/.h文件。
&emsp;&emsp;我们首先要使用ADD_EXECUTABLE命令来明确生成的目标文件名,还有源文件,就是像gcc手动编译时要输入main.c和-o hello.exe一样。换成cmake就是下面的命令样式:
```shell
ADD_EXECUTABLE(hello main.c)
```
&emsp;&emsp;这条命令过于简单,平时我们的项目也不能仅写一个main.c就完成了。所以,我们还应用了另一个命令AUX_SOURCE_DIRECTORY。
&emsp;&emsp;对于AUX_SOURCE_DIRECTORY命令,书中作者不建议使用,他的观点是在新添加.c文件后,由于CMakeLists.txt并未更新,因此CMake并不会重新遍历,并更新makefile。这样会导致编译过程仍然是旧的文件,但我是建议这样使用。理由也简单:省事。如果出现添加新文件未编译,则编译更新的时候肯定会报缺少文件调用或函数调用。这时,直接把build文件夹清空,再执行CMake即可。
&emsp;&emsp;我把cmakelists.txt的全部内容贴上来:
```shell
cmake_minimum_required(VERSION 3.20)
message("Hello EEWORLD! Hello CMake!")

project(hellocrc)
AUX_SOURCE_DIRECTORY(./app SRC_LIST)
ADD_EXECUTABLE(${PROJECT_NAME} ${SRC_LIST})
```
&emsp;&emsp;程序运行结果也符合预期:


## 应用场景2:生成库文件
&emsp;&emsp;我们在开发过程中,除了生成项目最终可执行文件外,我们平时还会编译各种库文件:一方面,利于我们代码复用;另一方面,也对我们的代码进行一些保护。
和普通的makefile一样,CMake也可以生成静态链接库,动态链接库和内核模块。分别对应STATIC,SHARED,MODULE三个参数值 ,而对应的语句也非常简单:
```shell
add_library(crc, STATIC, crc.c)
```
&ensp;&ensp;我们就使用我们编写的CRC算法的文件来生成静态链接库,对应的cmakelists.txt如下:
```shell
cmake_minimum_required(VERSION 3.20)
message("Hello EEWORLD! Hello CMake!")

project(crc)
AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_LIBRARY(${PROJECT_NAME} STATIC ${SRC_LIST})
```
&emsp;&emsp;编译后的结果也符合预研,成功生成了libcrc.a文件


## 应用场景3:多程序融合单项目
&emsp;&emsp;类似于git项目,git命令输入后,git会去找对应的子命令,如git diff命令。在这样的应用场景下,我们确实可以在每个程序单独编写cmakelists.txt并每个文件夹再单独cmake与make。但这显然不是咱们所想要的——这效率略低嘛!
&emsp;&emsp;这种多程序融合的单项目应用项目里,要用到add_subdirectory命令。
add_subdirectory命令用于将子目录加入项目。子目录文件夹必须含有一个cmake目录程序的cmakelists.txt,即对应该文件夹的操作与管理仍然必须要有说明(否则就需要上层文件的cmakelists.txt来考虑)。
&emsp;&emsp;我们仍然以刚刚的计算CRC为例,我们将CRC计算算法的静态库加入到本项目中来,我们可以看到CRC算法的源代码,但主程序却是使用静态库来链接使用API。文档结构我们再tree一下:
```
C:.
│CMakeLists.txt
│tree.txt

├─app
│      main.c
│      main.h
│      
├─build
└─func_crc
    │CMakeLists.txt
    │crc.c
    └─ crc.h
```
&emsp;&emsp;我们编写的cmakelists.txt如下:
```shell
cmake_minimum_required(VERSION 3.20)
message("Hello EEWORLD! Hello CMake!")

project(hellocrc)
AUX_SOURCE_DIRECTORY(./app SRC_LIST)
ADD_EXECUTABLE(${PROJECT_NAME} ${SRC_LIST})
add_subdirectory(func_crc)
target_link_libraries(${PROJECT_NAME} libcrc.a)
target_include_directories(${PROJECT_NAME} PUBLIC func_crc)
target_link_directories(${PROJECT_NAME} PUBLIC func_crc)
```
&emsp;&emsp;编译后的结果也符合预研:


&emsp;&emsp;我在项目中常用的三个典型的应用场景就介绍到这里了。本章节还讲到了CMake其它属性,书中讲到的知识面非常广。把所以有的知识全部记下来也不现实,只能待我们在实际应用中不断实践,再返回书中再学习,再实践了。


</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构建实战》第七章之实战演练