在初学单片机的时候,大家往往学习使用的都是高度集成的自动化IDE,老一点的Keil、IAR,新一点的STM32CubeIDE、GD32Embeded builder之类的;原厂的工程师往往帮大家在这些开发工具中裁剪内置了最适合自家芯片的编译器(ARM Clang等等)和动态语法检查工具,极大降低了芯片固件的开发难度。

         但随着芯片国产化、定制化浪潮的袭来,工作的时候我们接触到的一些芯片,可能没有稳定可靠的官方IDE使用;尤其是接触过嵌入式Linux开发的同学更容易体会到这一点,老教程里面开发Linux源码的工具五花八门,source insight、VScode甚至Vim都有(bushi。本质上,编辑代码用记事本都可以,但是C\C++的编译、汇编、链接以及最后构建工程的步骤中会引入各种复杂的软件配置问题。比如我们在VScode里面给芯片的IIC接口封装了大量操作底层寄存器的API(芯片原厂的工作)在源文件IIC.c当中,我们可以在终端中用gcc-arm-none-eabi这类的编译器(CubeIDE实际上就是Ecplise加上它和其他组件制作出来的,细心的同学可能在编译输出窗口中早就发现了)编译成目标文件IIC.o用来组建bin文件。但是如果我们之后修改了main.c,是否还需要整体重新编译?如果我们又在main.c里面添加了usart.h,该怎么管理文件包含路径?在keil中以及有工程师帮我们以UI形式封装成了IDE里面的控件,在VScode、CLion中又该怎么办呢?其实这些问题背后都可以有一个通解,那就是我们具体要介绍的工具CMake。

         CMake是个一个开源的跨平台自动化建构系统,用来管理软件建置的程序,并不依赖于某特定编译器,并可支持多层目录、多个应用程序与多个函数库。 它用配置文件控制建构过程(build process)的方式和Unixmake相似,只是CMake的配置文件取名为CMakeLists.txt。CMake并不直接建构出最终的软件,而是产生标准的建构档(如Unix的Makefile或Windows Visual C++的projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是CMake和SCons等其他类似系统的区别之处。 CMake配置文件(CMakeLists.txt)可设置源代码或目标程序库的路径、产生适配器(wrapper)、还可以用任意的顺序建构可执行文件。CMake支持in-place建构(二进档和源代码在同一个目录树中)和out-of-place建构(二进档在别的目录里),因此可以很容易从同一个源代码目录树中建构出多个二进档。CMake也支持静态与动态程序库的建构。

      “CMake”这个名字是“Cross platform Make”的缩写。虽然名字中含有“make”,但是CMake和Unix上常见的make系统是分开的,而且更为高阶。它可与原生建置环境结合使用,例如:make、ninja、苹果公司Xcode微软Microsoft Visual Studio

       下面我以CubeMX自动生成的CMakelist为案例,给大家示范一些最基本的CMake用法,更深层次的,我也还在学(doge。

(1)在CubeMX中选择工具链为CMake;

(2)用VScdoe打开整个文件夹可以看到CMakelist以及在架构下了;

(3)新建一个Lib库,并且分立成多层,Lib/OLED/Src和Lib/OLED/Inc;

(4)最常用的两个函数,设置目标源文件路径和目标头文件路径;

# Add sources to executable 
target_sources(${CMAKE_PROJECT_NAME} PRIVATE
    # Add user sources here
    Lib/OLED/Src/OLED.c
)

# Add include paths
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
    # Add user defined include paths
    Lib/OLED/Inc
)

(5)也可以将所有的源文件以通配符配置到一个变量中使用,不过CMake官方不建议这么做,因为这样可能导致生成的Makefile\Ninja监控不到文件的变化,

file(GLOB_RECURSE LIB_SOURCE "Lib/*C")

以上是最最最基本的使用,仅能保证你编译通过一些CMakelists比较“干净”的工程,但真上过班的都知道公司仓库里pull下来的东西绝大部分都是屎山,因此我们不妨把CubeMX帮我们生成的整篇都学习了解一下,以后日积月累逐步加深对编译器的了解。

第一句代码规定了CMake的最小版本号,即3.22版本。

强制使用C11标准,并且开启编译器的扩展功能。

将构建类型定义为Debug。

设定工程名称变量。

包含工具链文件:

这个文件设置了大量编译参数:

 set函数是最常用的,可以用来设定一系列参数,比如编译器为arm,定义变量等。

¥{}可以使用变量的值。

回到CMakelists,project创建了函数,message打印了项目编译类型信息。

查找链接文件的路径,某些库是闭源的,无法获取源文件,而是提供.a或者.so的链接文件。

上面两个文件由CubeMX管理,所以请尽量修改根目录下的CMakelists文件。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐