Hello系列|cmake简明基础知识

嵌入式大杂烩 2022-02-07 21:30

大家好,我是LinuxZn。

Hello系列,汇总短而实用的内容。

上一篇文章中我们分享了关于make与Makefile的知识:Makefile常用基础知识梳理!。make工具有很多种:gnu make、QT的qmake、微软的MS nmake等。不同的make工具遵循不同的规范,如果我们的程序想要运行在不同地平台上,就需要根据不同地平台的make工具规范编写对应的Makefile文件。显然,这很不方便。

CMake就是一个可以解决上面这个问题的工具。

什么是cmake?

CMake 是一个跨平台的安装(编译)工具。CMakeList.txt是一个与平台无关的、用于定制编译流程的文件。CMake 靠的是 CMakeLists.txt 文件来生成Makefile文件。

CMakeLists.txt文件的编写也需要遵循一些语法规则,CMakeLists.txt文件的语法与shell脚本的语法很相似,shell编程知识可见往期文章:Hello系列 | Shell编程必备简明基础知识。

下面简单了解CMakeLists.txt简单的规则及一些示例。

cmake语法知识

1、直译模式

直译模式简单解释就是不生成Makefile的模式。这很方便我们验证一些CMakeLists.txt的语法及验证一些数学运算等。

下面通过简单实例区分直译模式与非直译模式模式的区别。

直译模式:

输入 -P参数 指定CMakeLists.txt脚本以直译模式解析。其中,message是CMakeLists.txt中用于输出信息的命令。以直译模式解析就不会生成Makefile文件,并且终端输出的信息就是我们CMakeLists.txt指定输出的内容。

非直译模式:

可见,以非直译模式解析则会生成Makefile文件,并且终端多输出了一些核查编译器相关的信息。

2、定义变量

CMakeLists.txt中只有字串和字串数组两种变量。定义变量通过 set命令 来定义,使用变量时在外面加上 ${} 符号即可。如:

# 定义变量
set(name "LinuxZn")

# 使用变量
message("My name is ${name}!")

① 注释使用符号 #

② 命令不区分大小写,即set也可以替换为SET。

3、数学运算

# EXPR 是一款表达式计算工具
# math 是用于数学运算的命令

# 设置变量a、b的值
set(a "1")
set(b "2")

# 加
math(EXPR res "${a} + ${b}")
message("a + b : ${res}")

# 减
math(EXPR res "${a} - ${b}")
message("a - b : ${res}")

# 乘
math(EXPR res "${a} * ${b}")
message("a * b : ${res}")

# 除
math(EXPR res "${a} / ${b}")
message("a / b : ${res}")

# 取余
math(EXPR res "${a} % ${b}")
message("a % b : ${res}")

4、从命令行给变量赋值

# EXPR 是一款表达式计算工具
# math 是用于数学运算的命令

# 加
math(EXPR res "${a} + ${b}")
message("a + b : ${res}")

# 减
math(EXPR res "${a} - ${b}")
message("a - b : ${res}")

# 乘
math(EXPR res "${a} * ${b}")
message("a * b : ${res}")

# 除
math(EXPR res "${a} / ${b}")
message("a / b : ${res}")

# 取余
math(EXPR res "${a} % ${b}")
message("a % b : ${res}")

-D后面跟着变量及赋值。

我们经常会在命令行配置工程为debug模式还是release模式,如:

cmake -DCMAKE_BUILD_TYPE=Debug

CMAKE_BUILD_TYPE是cmake中的一个内置变量,用于指定构建类型。

5、流程控制

(1)if

set(ARCH "x86")
if(ARCH MATCHES "x86")
message("ARCH is x86")
else()
message("ARCH is arm")
endif()

(2)while

set(a "1")
while(${a} LESS "5")
message("${a}")
math(EXPR a "${a} + 1")
endwhile()

(3)foreach

message("for 1 =========")
foreach(i RANGE 1 5)
message("${i}")
endforeach()

message("for 2 =========")
foreach(i 1 5 6 7 9 10)
message("${i}")
endforeach()

message("for 3 =========")
foreach(str Linux C Cpp Python Shell)
message("${str}")
endforeach()

6、自定义宏与函数

(1)宏

# 定义名为printf的宏 
macro(printf str)
message(${str})
endmacro()

# 使用
printf("hello macro")

(2)函数

# 定义名为printf的函数 
function(printf str)
message(${str})
endfunction()

# 使用
printf("hello function")

(3)宏与函数的区别

函数中的变量是局部的,宏中的变量是全局的,宏中的变量在外面也可以被访问到。

# 定义名为func_printf的函数 
function(func_printf str)
message(${str})
set(func_var "1111111111")
endfunction()

# 定义名为macro_printf的宏
macro(macro_printf str)
message(${str})
set(macro_var "222222222")
endmacro()

# 使用
func_printf("hello function")
message("func_var = ${func_var}")
macro_printf("hello macro")
message("macro_var = ${macro_var}")

7、查看cmake命令说明

上面列举的语法知识中,我们并未介绍所用命令的格式及使用方式。各命令详细的解释可以通过如下方式查看。

(1)查看所有cmake命令

cmake --help-command-list

(2)查看具体某个命令说明

比如,查看message命令说明:

cmake --help-command message

cmake与构建

上一节分享了cmake的一些基本语法知识。这一节我们一起来看一下cmake与构建相关的内容。

1、几个常用命令

下面列出几个常用的命令,在我们下面的例子中会用到。

(1)cmake_minimum_required

命令格式:

cmake_minimum_required(VERSION major.minor[.patch[.tweak]]
[FATAL_ERROR])

用于指定需要的 CMake 的最低版本。

使用示例:

cmake_minimum_required (VERSION 3.10)

(2)project

命令格式:

project( [LANGUAGES] [...])

用于指定项目的名称。

使用示例:

project (hello)

(3)add_executable

命令格式:

add_executable( [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...])

用于指定从一组源文件 source1 … 编译出一个可执行文件且命名为 name。

使用示例:

add_executable(hello main.c)

(4)aux_source_directory

命令格式:

aux_source_directory( )

用于将 dir 目录下的所有源文件的名字保存在变量 variable 中。

使用示例:

aux_source_directory(. DIR_SRCS)

(5)add_subdirectory

命令格式:

add_subdirectory(source_dir [binary_dir]
[EXCLUDE_FROM_ALL])

用于添加一个需要进行构建的子目录。

使用示例:

add_subdirectory(Lib)

(6)add_library

命令格式:

add_library( INTERFACE [IMPORTED [GLOBAL]])

用于指定从一组源文件中编译出一个库文件且命名为name。

使用示例:

add_library(Lib ${DIR_SRCS})

(7)target_link_libraries

命令格式:

target_link_libraries( ... ... ...)

用于指定 target 需要链接 item1 item2 …。

使用示例:

target_link_libraries(hello Lib)

(8)include_directories

命令格式:

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

用于添加头文件路径。

使用示例:

include_directories(include)

2、常用内置变量

(1)PROJECT_SOURCE_DIR

目前正在处理中的专案最上层目录,即内含 project() 指令的 CMakeLists 所在资料夹。

(2)CMAKE_BUILD_TYPE

控制构建类型,可选值为:

  • None: 编译器默认值
  • Debug: 产生除错信息
  • Release: 进行最佳化
  • RelWithDebInfo: 进行最佳化,但仍然会启用 DEBUG flag
  • MinSizeRel: 进行程式码最小化

(3)CMAKE_C_FLAGS

C编译器的编译选项。

(4)CMAKE_CXX_FLAGS

C++编译器的编译选项。

3、实例

(1)基础实例

main.c:

#include 

int main(void)
{
    printf("hello cmake\n");
    return 0;
}

CMakeLists.txt:

cmake_minimum_required (VERSION 3.10)
project (hello)
add_executable(hello main.c)

(2)多个文件、多个文件夹

上一个demo只有一个源文件,对应的CMakeLists.txt比较简单。下面看看有多个文件夹及文件的工程。

基于上面的demo,修改工程如:

main.c:

#include "hello.h"

int main(void)
{
    print_hello();
    return 0;
}

CMakeLists.txt:

cmake_minimum_required (VERSION 3.10)
project (hello)

# 添加头文件路径
include_directories(include)

# 查找src目录下的所有源文件并将名称保存到 SRC_DIR_SRCS 变量中
aux_source_directory(src SRC_DIR_SRCS)

# 查找当前目录下的所有源文件并将名称保存到 CUR_DIR_SRCS 变量中
aux_source_directory(. CUR_DIR_SRCS)

# 从SRC_DIR_SRCS与CUR_DIR_SRCS中编译出可执行文件hello
add_executable(hello
${SRC_DIR_SRCS}
${CUR_DIR_SRCS}
)

编译、运行:

cd build
cmake ..
make
./hello

(3)编译静态库

基于demo2,我们把src文件夹下的源文件编译成静态库,再由main.c调用。工程目录基本不变,需要在src下新增一个CMakeLists.txt文件,其内容如:

# 查找当前目录下的所有源文件并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)

# 生成链接库
add_library (print_hello ${DIR_LIB_SRCS})

根目录下的CMakeLists.txt修改为:

cmake_minimum_required (VERSION 3.10)
project (hello)

# 添加头文件路径
include_directories(include)

# 查找当前目录下的所有源文件并将名称保存到 CUR_DIR_SRCS 变量中
aux_source_directory(. CUR_DIR_SRCS)

# 添加 src 子目录
add_subdirectory(src)

# 从CUR_DIR_SRCS中编译出可执行文件hello
add_executable(hello
${CUR_DIR_SRCS}
)

# 添加链接库
target_link_libraries(hello print_hello)

编译、运行:

cd build
cmake ..
make
./hello

(4)编译动态库

编译动态库的方式与编译动态库的方式差不多。基于上面的demo3,只需修改src文件夹下的CMakeLists.txt为:

# 查找当前目录下的所有源文件并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)

# 生成动态库
add_library (print_hello SHARED ${DIR_LIB_SRCS})

编译、运行:

cd build
cmake ..
make
./hello

4、支持gdb调试

上面工程中根目录加上如下命令可支持gdb调试:

set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O0 -Wall")

以上就是本次的分享。如果觉得文章有用,欢迎收藏、转发!

往期推荐:

干货 | 项目乏力?nanopb助你一臂之力

长文 | 花了两天时间整理了STM32中的一些C语言知识点

分享一个有趣的库,让你学习C语言不会觉得那么枯燥

嵌入式 C | 结构体完全笔记,收藏!

实用 | 一个高性能通信库的简单使用分享

实用工具 | LVGL GUI-Guider的使用分享

基于vs2019的lvgl模拟器使用

lvgl最新版本在STM32上的移植使用

实用 | 10分钟教你搭建一个嵌入式web服务器

嵌入式开发小记,实用小知识分享

分享一款嵌入式人必备绘图工具!

干货 | protobuf-c之嵌入式平台使用

干货 | 嵌入式必备技能之Git的使用

例说嵌入式实用知识之JSON数据

C语言、嵌入式中几个非常实用的宏技巧

一个小巧、开源的信号发生器,酷!

在公众号聊天界面回复1024,可获取嵌入式资源;回复 ,可查看文章汇总。


点击阅读原文,查看更多分享。

嵌入式大杂烩 专注于嵌入式技术,包括但不限于C/C++、嵌入式、物联网、Linux等编程学习笔记,同时,内包含大量的学习资源。欢迎关注,一同交流学习,共同进步!
评论
  • 80,000人到访的国际大展上,艾迈斯欧司朗有哪些亮点?感未来,光无限。近日,在慕尼黑electronica 2024现场,ams OSRAM通过多款创新DEMO展示,以及数场前瞻洞察分享,全面展示自身融合传感器、发射器及集成电路技术,精准捕捉并呈现环境信息的卓越能力。同时,ams OSRAM通过展会期间与客户、用户等行业人士,以及媒体朋友的深度交流,向业界传达其以光电技术为笔、以创新为墨,书写智能未来的深度思考。electronica 2024electronica 2024构建了一个高度国际
    艾迈斯欧司朗 2025-01-16 20:45 187浏览
  • 一个易用且轻量化的UI可以大大提高用户的使用效率和满意度——通过快速启动、直观操作和及时反馈,帮助用户快速上手并高效完成任务;轻量化设计则可以减少资源占用,提升启动和运行速度,增强产品竞争力。LVGL(Light and Versatile Graphics Library)是一个免费开源的图形库,专为嵌入式系统设计。它以轻量级、高效和易于使用而著称,支持多种屏幕分辨率和硬件配置,并提供了丰富的GUI组件,能够帮助开发者轻松构建出美观且功能强大的用户界面。近期,飞凌嵌入式为基于NXP i.MX9
    飞凌嵌入式 2025-01-16 13:15 219浏览
  • Ubuntu20.04默认情况下为root账号自动登录,本文介绍如何取消root账号自动登录,改为通过输入账号密码登录,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!添加新账号1、使用adduser命令来添加新用户,用户名以industio为例,系统会提示设置密码以及其他信息,您可以根据需要填写或跳过,命令如下:root@id
    Industio_触觉智能 2025-01-17 14:14 84浏览
  • 电竞鼠标应用环境与客户需求电竞行业近年来发展迅速,「鼠标延迟」已成为决定游戏体验与比赛结果的关键因素。从技术角度来看,传统鼠标的延迟大约为20毫秒,入门级电竞鼠标通常为5毫秒,而高阶电竞鼠标的延迟可降低至仅2毫秒。这些差异看似微小,但在竞技激烈的游戏中,尤其在对反应和速度要求极高的场景中,每一毫秒的优化都可能带来致胜的优势。电竞比赛的普及促使玩家更加渴望降低鼠标延迟以提升竞技表现。他们希望通过精确的测试,了解不同操作系统与设定对延迟的具体影响,并寻求最佳配置方案来获得竞技优势。这样的需求推动市场
    百佳泰测试实验室 2025-01-16 15:45 310浏览
  • 日前,商务部等部门办公厅印发《手机、平板、智能手表(手环)购新补贴实施方案》明确,个人消费者购买手机、平板、智能手表(手环)3类数码产品(单件销售价格不超过6000元),可享受购新补贴。每人每类可补贴1件,每件补贴比例为减去生产、流通环节及移动运营商所有优惠后最终销售价格的15%,每件最高不超过500元。目前,京东已经做好了承接手机、平板等数码产品国补优惠的落地准备工作,未来随着各省市关于手机、平板等品类的国补开启,京东将第一时间率先上线,满足消费者的换新升级需求。为保障国补的真实有效发放,基于
    华尔街科技眼 2025-01-17 10:44 205浏览
  • 实用性高值得收藏!! (时源芯微)时源专注于EMC整改与服务,配备完整器件 TVS全称Transient Voltage Suppre,亦称TVS管、瞬态抑制二极管等,有单向和双向之分。单向TVS 一般应用于直流供电电路,双向TVS 应用于电压交变的电路。在直流电路的应用中,TVS被并联接入电路中。在电路处于正常运行状态时,TVS会保持截止状态,从而不对电路的正常工作产生任何影响。然而,一旦电路中出现异常的过电压,并且这个电压达到TVS的击穿阈值时,TVS的状态就会
    时源芯微 2025-01-16 14:23 186浏览
  • 随着消费者对汽车驾乘体验的要求不断攀升,汽车照明系统作为确保道路安全、提升驾驶体验以及实现车辆与环境交互的重要组成,日益受到业界的高度重视。近日,2024 DVN(上海)国际汽车照明研讨会圆满落幕。作为照明与传感创新的全球领导者,艾迈斯欧司朗受邀参与主题演讲,并现场展示了其多项前沿技术。本届研讨会汇聚来自全球各地400余名汽车、照明、光源及Tier 2供应商的专业人士及专家共聚一堂。在研讨会第一环节中,艾迈斯欧司朗系统解决方案工程副总裁 Joachim Reill以深厚的专业素养,主持该环节多位
    艾迈斯欧司朗 2025-01-16 20:51 146浏览
  •  光伏及击穿,都可视之为 复合的逆过程,但是,复合、光伏与击穿,不单是进程的方向相反,偏置状态也不一样,复合的工况,是正偏,光伏是零偏,击穿与漂移则是反偏,光伏的能源是外来的,而击穿消耗的是结区自身和电源的能量,漂移的载流子是 客席载流子,须借外延层才能引入,客席载流子 不受反偏PN结的空乏区阻碍,能漂不能漂,只取决于反偏PN结是否处于外延层的「射程」范围,而穿通的成因,则是因耗尽层的过度扩张,致使跟 端子、外延层或其他空乏区 碰触,当耗尽层融通,耐压 (反向阻断能力) 即告彻底丧失,
    MrCU204 2025-01-17 11:30 152浏览
  • 本文介绍瑞芯微开发板/主板Android配置APK默认开启性能模式方法,开启性能模式后,APK的CPU使用优先级会有所提高。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。源码修改修改源码根目录下文件device/rockchip/rk3562/package_performance.xml并添加以下内容,注意"+"号为添加内容,"com.tencent.mm"为AP
    Industio_触觉智能 2025-01-17 14:09 118浏览
  • 随着智慧科技的快速发展,智能显示器的生态圈应用变得越来越丰富多元,智能显示器不仅仅是传统的显示设备,透过结合人工智能(AI)和语音助理,它还可以成为家庭、办公室和商业环境中的核心互动接口。提供多元且个性化的服务,如智能家居控制、影音串流拨放、实时信息显示等,极大提升了使用体验。此外,智能家居系统的整合能力也不容小觑,透过智能装置之间的无缝连接,形成了强大的多元应用生态圈。企业也利用智能显示器进行会议展示和多方远程合作,大大提高效率和互动性。Smart Display Ecosystem示意图,作
    百佳泰测试实验室 2025-01-16 15:37 194浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 57浏览
  • 百佳泰特为您整理2025年1月各大Logo的最新规格信息,本月有更新信息的logo有HDMI、Wi-Fi、Bluetooth、DisplayHDR、ClearMR、Intel EVO。HDMI®▶ 2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新规范将支持更高的分辨率和刷新率,并提供更多高质量选项。更快的96Gbps 带宽可满足数据密集型沉浸式和虚拟应用对传输的要求,如 AR/VR/MR、空间现实和光场显示,以及各种商业应用,如大型数字标牌、医疗成像和
    百佳泰测试实验室 2025-01-16 15:41 189浏览
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 117浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦