- 2024-11-15
-
回复了主题帖:
CW32L010学习笔记
QFN20 是不是太小巧可爱了啊
- 2024-11-10
-
回复了主题帖:
编译出错的问题
还是找一台老电脑吧!
感觉处理兼容性的问题会相当的多
- 2024-11-08
-
回复了主题帖:
免费申请测评:KTC3500 DC/DC评估板
DC-DC 看上去不错嘛
- 2024-11-06
-
回复了主题帖:
NXP LPC1114资料
我读研的时候就是这块开发板。
当时还是周立功在推呢
- 2024-11-03
-
发表了主题帖:
《Cmake构建实战》第七章之实战演练
# 《Cmake构建实战》第七章之实战演练
今天为大家分享一下《Cmake构建实战》第七章的学习内容。读了两遍第七章,我感觉内容略多,所以我的分享就以我的实现项目开发的使用视角来分享第七章这些属性与功能应用。本次示例以计算一串字符串的CRC16为示例做讲解。
## 应用场景1:生成可执行文件
这是我们最简单的应用场景了。也是我们最常用的场景之一。我们首先tree一下我们的示例项目文件结构:
通过上面的图片我们可以看到在app文件夹里面存放着应用层的.c/.h文件,主要包含main.c和main.h及crc.c/.h文件。
我们首先要使用ADD_EXECUTABLE命令来明确生成的目标文件名,还有源文件,就是像gcc手动编译时要输入main.c和-o hello.exe一样。换成cmake就是下面的命令样式:
```shell
ADD_EXECUTABLE(hello main.c)
```
这条命令过于简单,平时我们的项目也不能仅写一个main.c就完成了。所以,我们还应用了另一个命令AUX_SOURCE_DIRECTORY。
对于AUX_SOURCE_DIRECTORY命令,书中作者不建议使用,他的观点是在新添加.c文件后,由于CMakeLists.txt并未更新,因此CMake并不会重新遍历,并更新makefile。这样会导致编译过程仍然是旧的文件,但我是建议这样使用。理由也简单:省事。如果出现添加新文件未编译,则编译更新的时候肯定会报缺少文件调用或函数调用。这时,直接把build文件夹清空,再执行CMake即可。
我把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})
```
程序运行结果也符合预期:
## 应用场景2:生成库文件
我们在开发过程中,除了生成项目最终可执行文件外,我们平时还会编译各种库文件:一方面,利于我们代码复用;另一方面,也对我们的代码进行一些保护。
和普通的makefile一样,CMake也可以生成静态链接库,动态链接库和内核模块。分别对应STATIC,SHARED,MODULE三个参数值 ,而对应的语句也非常简单:
```shell
add_library(crc, STATIC, crc.c)
```
我们就使用我们编写的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})
```
编译后的结果也符合预研,成功生成了libcrc.a文件
## 应用场景3:多程序融合单项目
类似于git项目,git命令输入后,git会去找对应的子命令,如git diff命令。在这样的应用场景下,我们确实可以在每个程序单独编写cmakelists.txt并每个文件夹再单独cmake与make。但这显然不是咱们所想要的——这效率略低嘛!
这种多程序融合的单项目应用项目里,要用到add_subdirectory命令。
add_subdirectory命令用于将子目录加入项目。子目录文件夹必须含有一个cmake目录程序的cmakelists.txt,即对应该文件夹的操作与管理仍然必须要有说明(否则就需要上层文件的cmakelists.txt来考虑)。
我们仍然以刚刚的计算CRC为例,我们将CRC计算算法的静态库加入到本项目中来,我们可以看到CRC算法的源代码,但主程序却是使用静态库来链接使用API。文档结构我们再tree一下:
```
C:.
│ CMakeLists.txt
│ tree.txt
│
├─app
│ main.c
│ main.h
│
├─build
└─func_crc
│ CMakeLists.txt
│ crc.c
└─ crc.h
```
我们编写的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)
```
编译后的结果也符合预研:
我在项目中常用的三个典型的应用场景就介绍到这里了。本章节还讲到了CMake其它属性,书中讲到的知识面非常广。把所以有的知识全部记下来也不现实,只能待我们在实际应用中不断实践,再返回书中再学习,再实践了。
- 2024-10-20
-
回复了主题帖:
卡尔曼滤波原理的学习
有时间借本卡尔曼滤波的书来看看
- 2024-10-19
-
发表了主题帖:
《Cmake构建实战》第六章之CMake项目构建
本帖最后由 lemonboard 于 2024-10-19 17:19 编辑
# 《Cmake构建实战》第六章之CMake项目构建
## 引言
在学习本章之前,我一直以为CMak它就是生成一下makefile文件而已。没有想到CMake居然还负责到这个阶段。看来网上获取的知识终究只是碎片,而成系统,成体系,还是要多读书,读好书!
## CMake项目的生命周期
读到这章时,也发现了自己好久没有关注自己项目的软件生命周期的概念了。CMake在构建项目过程中的6个阶段:配置阶段、生成阶段、构建阶段、安装阶段、打包阶段和程序包安装阶段。
### 前三个阶段
在我的项目中,我经常使用的是前三个阶段,我也就重点分享配置阶段、生成阶段和构建阶段。首先,上张这三个阶段的关系框图:
图:CMake的配置、生成和构建阶段关系框图
阅读本章后,对于CMake的配置和生成阶段才有明确的界限。CMake也是采取“二段式”实现方案。先执行CMak目录程序CMakeLists.txt,完成项目的配置阶段,确定项目构建目标的依赖关系,构建需求等,与选用的具体构建系统的特殊化配置无关,即上图所示中的CMake持久化缓存和CMakeFiles。至少,我是真没有仔细研究过这些中间文件的内容。
之后的生成阶段,CMake再根据具体的目标构建系统(如我们当前的makefile)的要求生成出符合具体构建系统要求格式的具体配置。
貌似现在这种“二段式“的实现方式很流行。反正我在我未来的项目中吼采用了这种设计架构方案。
接下来,我们做一个动手实现,打印一段字符串。
我使用了VScode,并安装了CMake套件插件,所以在输入CMake关键字时有补全提示,特别方便。大家也可尝试一下!
在执行完成CMake后,CMake程序便为我们生成好了makefile文件,再执行一下make命令,gcc也就为我们生成了hello.exe文件。
使用CMake是不是特别方便!
### 后三个阶段
对我平时使用的嵌入式程序开发来说,由于我不存在安装、分发的过程,所以后三个阶段基本用不上。这里也就简单说说这三个阶段:安装阶段、打包阶段和程序包安装阶段。
CMake使用cmake --install命令来安装CMake项目。
```shell
cmake --install . --prefix ../install
```
CMake项目的构建目录,即当前目录".",应为第一个参数;"--prefix"参数用于指定安装目录前缀,即CMake项目安装位置的根目录。
CPack命令会打包当前的构建目录中的CMake项目。
而程序包安装阶段,其实并不属于CMake的内容。
本章节的剩余内容讲了CMake GUI的操作,也没有看出来有多方便来。接下来又讲了CMake内置的命令行工具,看了看,也没有发现有啥方便的地方。
好了!本次分享就到这里吧!下次我们将分享CMake在构建项目时的各种配置与属性的编写。欢迎大家关注EEWORLD,关注我。
- 2024-10-15
-
回复了主题帖:
gd32f407vet6的串口硬件只支持8和位数据位,怎样让串口的数据位是5位,6位,7位呢
刚刚看了一下此款芯片的reference,其仅支持Uart的8位或9位模式。
如果想支持其它模式,您需要重新选型了。
- 2024-10-11
-
回复了主题帖:
VGA显示器如何连接主机HDMI接口
您这是发了个啥啊!?
是广告,还是广告啊!
-
发表了主题帖:
《Cmake构建实战》第二章之你好,CMake!
# 《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
- 2024-10-09
-
回复了主题帖:
总感觉不痛快,想找点刺激
同样的感觉。有点不想干了
- 2024-10-05
-
回复了主题帖:
《Cmake构建实战》第一章之本地环境搭建
breeze_i 发表于 2024-9-29 09:38
大佬,能分享一下这本书的配套资源吗?
复制收文件盘口令,打开最新版百度网盘即可分享文件给我#LrLMZmn ...
这是啥啊
-
回复了主题帖:
《Cmake构建实战》第一章之本地环境搭建
freebsder 发表于 2024-9-29 14:31
clion和visual studio都直接支持cmake呀
嗯嗯,现在CMake的支持程度非常高。
我看我爱人的Android Studio也是使用cmake来编译项目了
-
回复了主题帖:
“春困秋乏”如何在深秋养生?
补肾呗
- 2024-09-28
-
回复了主题帖:
【2024 DigiKey 创意大赛】串口、TTL和485数据分析工具+物料开箱
这大屏,看着是真好啊
- 2024-09-25
-
发表了主题帖:
《Cmake构建实战》第一章之本地环境搭建
本帖最后由 lemonboard 于 2024-9-25 23:22 编辑
# 《Cmake构建实战》第一章之本地环境搭建
作为一名嵌入式工程师,已经工作多年。开始几年仅做MCU的项目开发,从8位AVR单片机到现在火的不要不要的STM32,我都是使用商用的编译器来做主编译器,如Keil,IAR。对于编译过程,我也仅仅是点点鼠标,或者按一下“F7”快捷键。
情况变化是在最近的项目,涉及到了嵌入式Linux应用程序开发,要使用GCC与Makefile来实现编译。由于水平有限,仅仅使用公司前辈编写好的makefile文件来完成项目,虽然几次努力试图掌握makefile的语法,但终觉不得其法,未得其精髓。一翻探究与调研,决定放弃makefile的深入学习,转而学习CMake,毕竟CMake的语法与编写行数要显著少于makefile。我觉得这也算是跟上技术潮流吧!正好遇上咱们论坛发起CMake的学习活动,故一边看书学习,一边练习分享!欢迎大家批评指正,共同学习进步!
我在阅读完成第一章后,与作者遇到的学习困难点不约而同。所以,我也首先搭建我的实验环境,为后面动手操作提供基础,也只有动手操作后才印象深嘛——“纸上得来终觉浅,绝知此事要躬行。”
我使用windows 10专业版,VScode编辑器,GCC与CMake等工具。具体版本如下图所示:
我们先编写一个简单的文件做测试,即使用命令行的方式通过GCC来编译一个hello.c的源文件的应用程序。
```c
#include
#include
int main(int argc, char const *argv[])
{
printf("hello eeworld\r\n");
return 0;
}
```
然后运行命令。
```shell
gcc hello.c -o hello.exe
```
开发测试的硬件环境我们搭建完成,接下来,我们就尝试使用gcc来编译我们的项目工程了。
对于单个文件的简单程序来说,直接使用命令行的方式肯定是足够的。但对于常见的应用程序,肯定不止1个文件这么少。这时肯定就需要编写编译规则了。
我们继续阅读第二章,《《Cmake构建实战》第一章之入门CMake》,欢迎大家锁定EEWORLD,关注我。
# Hint:
1. 在安装完成MinGW后,需要手动修改MinGW-make.exe为make.exe
2. 添加gcc的bin文件夹到系统path
-
回复了主题帖:
电瓶车铅电池要怎么充电才能获得最长的使用寿命
不必太在意。电池本身也是消耗品。
差不多更换就是了
- 2024-09-13
-
回复了主题帖:
在 LCD1602 上显示大字体数字的micropython驱动
别说,还挺好看的啊
- 2024-08-31
-
回复了主题帖:
读书入围名单: 《CMake构建实战:项目开发卷》
个人信息无误,确认可以完成阅读分享计划
- 2024-08-26
-
回复了主题帖:
新能源汽车之“BMS电池管理系统”的功能
文中是不是为了写BMS,而夸大了BMS的作用啊