- 2024-11-04
-
发表了主题帖:
《CMake构建实战》CMake 构建目标和属性
# CMake 构建目标和属性
## 二进制构建目标
在构建过程中被构建的可执行文件、库文件或目标文件都可以作为二进制构建目标。
### 可执行文件目标
```cmake
add_executable(
[WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
[源文件...])
```
该命令会创建一个可执行文件类型的构建目标,其中第一个参数是必选参数,且应当在项目中唯一。
创建一个小工程实践一下。创建`008`文件夹
创建`CMakeLists.txt`
```cmake
cmake_minimum_required(VERSION 3.20)
project(myProgram)
add_executable(myProgram main.c)
add_executable(myProgramExcludedFromAll
EXCLUDE_FROM_ALL
main.c)
```
创建`main.c`
```c
#include
int main() {
printf("hello world\n");
return 0;
}
```
执行命令
```bash
bruce@ubuntu:~/Documents/study/cmake/008$ touch CMakeLists.txt
bruce@ubuntu:~/Documents/study/cmake/008$ vi CMakeLists.txt
bruce@ubuntu:~/Documents/study/cmake/008$ vi main.c
bruce@ubuntu:~/Documents/study/cmake/008$ mkdir build
bruce@ubuntu:~/Documents/study/cmake/008$ cd build/
bruce@ubuntu:~/Documents/study/cmake/008/build$ cmake ..
-- The C compiler identification is GNU 13.2.0
-- The CXX compiler identification is GNU 13.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/bruce/Documents/study/cmake/008/build
bruce@ubuntu:~/Documents/study/cmake/008/build$ make
[ 50%] Building C object CMakeFiles/myProgram.dir/main.c.o
[100%] Linking C executable myProgram
[100%] Built target myProgram
bruce@ubuntu:~/Documents/study/cmake/008/build$ ./myProgram
hello world
```
### 一般库目标
一般库目标包括静态库目标、动态库目标和模块库目标。
```cmake
add_library(
[EXCLUDED_FROM_ALL]
[...])
```
该命令会创建一个一般库类型的构建目标,其中参数是必选项,且应在项目中唯一。
参数有以下三个取值。
* STATIC
* SHARED
* MODULE
实践,创建`009`文件夹
创建 `CMakeLists.txt`
```cmake
cmake_minimum_required(VERSION 3.20)
project(mylib)
add_library(mylib lib.c)
```
创建`lib.c`
```c
int add(int a, int b) { return a+b; }
```
操作过程如下
```bash
bruce@ubuntu:~/Documents/study/cmake/009$ vi CMakeLists.txt
bruce@ubuntu:~/Documents/study/cmake/009$ ls
CMakeLists.txt
bruce@ubuntu:~/Documents/study/cmake/009$ touch lib.c
bruce@ubuntu:~/Documents/study/cmake/009$ vi lib.c
bruce@ubuntu:~/Documents/study/cmake/009$ ls
CMakeLists.txt lib.c
bruce@ubuntu:~/Documents/study/cmake/009$ mkdir build
bruce@ubuntu:~/Documents/study/cmake/009$ cd build/
bruce@ubuntu:~/Documents/study/cmake/009/build$ cmake ..
-- The C compiler identification is GNU 13.2.0
-- The CXX compiler identification is GNU 13.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/bruce/Documents/study/cmake/009/build
bruce@ubuntu:~/Documents/study/cmake/009/build$ make
[ 50%] Building C object CMakeFiles/mylib.dir/lib.c.o
[100%] Linking C static library libmylib.a
[100%] Built target mylib
bruce@ubuntu:~/Documents/study/cmake/009/build$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake libmylib.a Makefile
bruce@ubuntu:~/Documents/study/cmake/009/build$
```
可以看到最后生成了 `libmylib.a`
可以看到不定义`BUILD_SHARED_LIBS`变量时,默认构建静态库。接下来试验定义`BUILD_SHARED_LIBS`
```bash
bruce@ubuntu:~/Documents/study/cmake/009/build$ cmake -DBUILD_SHARED_LIBS=ON ..
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/bruce/Documents/study/cmake/009/build
bruce@ubuntu:~/Documents/study/cmake/009/build$ cmake --build .
[ 50%] Building C object CMakeFiles/mylib.dir/lib.c.o
[100%] Linking C shared library libmylib.so
[100%] Built target mylib
bruce@ubuntu:~/Documents/study/cmake/009/build$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake libmylib.a libmylib.so Makefile
bruce@ubuntu:~/Documents/study/cmake/009/build$
```
定义了`BUILD_SHARED_LIBS`后生成了`libmylib.so`动态库。
-
回复了主题帖:
《CMake构建实战》CMake常用命令
秦天qintian0303 发表于 2024-11-2 23:08
CMake提供了math命令用于计算数学表达式,写法有什么不同吗
我感觉平时使用CMake几乎用不到,可能是方便一些特殊场景吧
- 2024-11-02
-
发表了主题帖:
《CMake构建实战》CMake常用命令
# CMake 常用命令
CMake提供了很多命令,这些命令能够帮助我们在CMake程序中实现各种功能,包括对数值、字符串、列表、文件、路径的操作,生成文件、输出日志、指令命令行程序、引用模块、实现元编程、辅助调试等。
## 数值操作命令:math
CMake提供了math命令用于计算数学表达式。尽管这不如表达式语法那样简单直接,但鉴于构建过程中涉及数值计算的需求少之又少,使用math命令也算是在保持CMake语法单一性的前提下较为简单实用的一种方式了。
创建1.cmake
```cmake
cmake_minimum_required(VERSION 3.20)
math(EXPR a 10*10 OUTPUT_FORMAT DECIMAL)
message("a=${a}")
```
测试
```bash
$ cmake -P 1.cmake
a=100
```
## 字符串操作命令:string
### 搜索和替换
语法
```cmake
string(FIND [REVERSE])
```
新建 `2.cmake`,搜索子字符串`a`
```cmake
string(FIND aba a res)
message("${res}")
```
从aba字符串搜索a,如果找到,返回字符串a所在的位置,上面的例子应该返回0,测试一下
```bash
$ cmake -P 2.cmake
0
```
### 替换字符串
语法
```cmake
string(REPLACE )
```
新建 `3.cmake`
```cmake
string(REPLACE a b res aba)
message("${res}")
```
将aba字符串中的a全部替换为b,上面的例子应该返回`bbb`,测试一下
```bash
$ cmake -P 3.cmake
bbb
```
### 取字符串长度
语法
```cmake
string(LENGTH )
```
新建 `4.cmake`
```cmake
string(LENGTH aba res)
message("${res}")
```
计算字符串`aba`的长度,保存到`res`变量中,测试一下
```bash
$ cmake -P 4.cmake
3
```
## 列表操作指令list
### 列表长度
```cmake
list(LENGTH )
```
新建 `5.cmake`
```cmake
set(x a b c)
list(LENGTH x res )
message("${res}")
```
计算列表`x`的长度,保存到`res`变量中,测试一下
```bash
$ cmake -P 5.cmake
3
```
### 列表元素操作
```cmake
list(APPEND [...])
```
在 `5.cmake` 基础上修改
```cmake
set(x a b c)
list(LENGTH x res )
message("${res}")
list(APPEND x d e f g)
message("${x}")
```
在列表`x`后面追加 `d e f g` 四个元素,测试结果如下
```bash
$ cmake -P 5.cmake
3
a;b;c;d;e;f;g
```
- 2024-10-31
-
回复了主题帖:
【2024 DigiKey创意大赛】基于Linux系统的远程实时语音对讲系统
-
发表了主题帖:
【2024 DigiKey创意大赛】基于Linux系统的远程实时语音对讲系统
本帖最后由 小麦克 于 2024-10-31 09:28 编辑
# 基于Linux系统的远程实时语音对讲系统
## 一、作品简介
本系统基于NXP最新的iMX93芯片和配套的Linux 6.6.23操作系统,旨在实现高效、实时的远程语音对讲功能。系统利用PJSIP协议栈,通过以太网进行语音数据的实时传输,以确保低延迟和高质量的语音通话体验。
在硬件方面,系统主要采用以太网LAN8841芯片负责网络连接,LAN8841具有出色的网络性能和稳定性。同时,语音芯片VK419则承担着语音信号的处理功能,支持高质量的音频编解码,为用户提供清晰、自然的语音交流效果。
尽管NXP IMX93配套的Linux系统并未支持LAN8841和VK419芯片,但我通过手动移植驱动程序并进行调试,实现了对这两种芯片的成功支持。这个过程中让我深入学习了嵌入式驱动开发相关技能,为后面的开发打下了坚实的基础。
该远程语音对讲系统广泛应用于家庭、办公室以及各种远程通信场所,具备良好的扩展性和适应性,满足不同场景下的语音交互需求。
实物图如下:核心板使用的是正点原子的
## 二、系统框图
以上框图画的比较全面,由于时间原因,本次参赛只做了其中语音对讲部分。
本系统的设计思路旨在结合高性能硬件与灵活的软件架构,以实现一个可靠、高效的远程实时语音对讲解决方案。具体设计思路如下:
### 1. 硬件选择与集成
IMX93芯片:选择NXP IMX93芯片作为系统的核心处理器,利用其强大的处理能力和丰富的外设接口,以支持复杂的语音处理和网络通信。
LAN8841以太网芯片:为了实现稳定的网络连接,选择LAN8841以太网芯片。该芯片的高效性和稳定性确保了数据传输的实时性。
VK419语音芯片:使用VK419语音芯片作为音频处理单元,实现语音信号的高质量编解码和处理。
### 2. 软件架构设计
操作系统:基于Linux的开放性和灵活性,使系统能够更好地支持各种网络和音频处理需求。
驱动移植:为了支持LAN8841和VK419芯片,手动移植必要的驱动程序,并针对特定硬件进行调试,确保其在Linux环境下的稳定运行。
通信协议:采用PJSIP作为协议栈,利用其成熟的SIP协议特性实现音频数据的实时传输和管理,从而保证低延迟的语音通话体验。
### 3. 功能模块设计
语音处理模块:负责音频的采集、编码、解码和播放,确保用户之间的语音交流清晰、流畅。
网络通信模块:负责数据包的交换和管理,实现跨网络区域的实时连接。
## 三、各部分功能说明
### 1. 硬件设计
以太网LAN8841原理图设计
音频芯片AK4619原理图设计
iMX93启动配置和调试串口
### 2. 软件设计
u-boot和Linux内核在NXP官方6.6.23基础上进行修改。
文件系统使用Buildroot构建,选择添加了libpjsip2.14等包。
应用层采用C++编写。
源代码都打包上传了,这里就不单独拷贝了。
## 四、作品源码
源码已上传到网站
PCB:https://download.eeworld.com.cn/detail/%E5%B0%8F%E9%BA%A6%E5%85%8B/634854
Linux:https://download.eeworld.com.cn/detail/%E5%B0%8F%E9%BA%A6%E5%85%8B/634853
Buildroot:https://download.eeworld.com.cn/detail/%E5%B0%8F%E9%BA%A6%E5%85%8B/634852
## 五、作品功能演示视频
[localvideo]4e676134f3f1a688cbf0f7fab941ea8e[/localvideo]
## 六、项目总结
本项目旨在开发一套基于NXP IMX93芯片和Linux操作系统的远程实时语音对讲系统。通过系统集成和技术创新,成功实现了语音通信解决方案。
### 1. 项目目标与实现
本项目的核心目标是设计一款能够在网络环境中实现实时语音对讲的系统。项目实施过程中,考虑了以下几个方面:
硬件选择:通过选用IMX93芯片作为核心处理单元,结合LAN8841以太网芯片和VK419语音芯片,实现了系统的性能和功能需求。
驱动移植与调试:由于NXP IMX93的Linux系统原生不支持LAN8841和VK419,我们手动移植了驱动程序,并经过细致调试,使其在Linux环境中的稳定运行成为可能。
软件架构:采用灵活的PJSIP协议栈处理语音数据,以确保低延迟和高质量的通话体验,构建了系统的核心功能模块。
### 2. 未来展望
虽然本项目已成功完成系统设计与实现,但仍有进一步优化与扩展的机会:
功能扩展:未来可以考虑增加更多的功能,如视频对讲、录音回放等,提升用户的使用体验。
性能优化:在今后的版本中,持续关注系统性能,特别是在多用户同时使用的情况下,优化网络负载与语音质量。
## 七、结语
基于Linux系统的远程实时语音对讲系统项目的成功实施,期待后续能在此基础上,继续深化技术应用与创新。
-
上传了资料:
imx93 pcb
-
上传了资料:
imx93-linux-kernel
-
上传了资料:
imx93-audio-buildroot
- 2024-10-25
-
发表了主题帖:
《CMake构建实战》CMake实践-交叉编译APP
## CMake实践-交叉编译APP
之前在这篇[帖子](https://bbs.eeworld.com.cn/thread-1291655-1-1.html)写过使用buildroot生成的sdk开发包开发应用程序。在这个基础上来实践CMake交叉编译。
这里以编译引用`pjsip`库的应用程序为例,通过`buildroot`编译会自动生成 `libpjproject.pc`
测试一下。在工具链目录搜索`libpjproject.pc`,这个文件后面的CMake会用到。
```bash
$ find -name "libpjproject.pc"
./aarch64-buildroot-linux-gnu/sysroot/usr/lib/pkgconfig/libpjproject.pc
```
CMake开发环境
```bash
# 生效buildroot
source ~/Documents/aarch64-buildroot-linux-gnu_sdk-buildroot/environment-setup
```
创建`CMakeLists.txt`
```cmake
cmake_minimum_required(VERSION 3.10)
project(PJSUA2App)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(PkgConfig REQUIRED)
pkg_check_modules(PJSIP REQUIRED libpjproject)
add_definitions(-DPJ_AUTOCONF=1)
add_executable(pjsua2_app pjsip-call.cpp)
target_link_libraries(pjsua2_app ${PJSIP_LIBRARIES})
```
通过`libpjproject` 找到 `pjsip` 相关的库
### 测试例子
新建如下目录结构
```bash
$ tree
.
├── build
├── CMakeLists.txt
└── pjsip-call.cpp
2 directories, 3 files
```
pjsip-call.cpp文件
```c++
#include
#include
#include
#define THIS_FILE "pjsua2_demo.cpp"
using namespace pj;
class MyEndpoint : public Endpoint
{
public:
MyEndpoint() : Endpoint() {};
virtual pj_status_t onCredAuth(OnCredAuthParam &prm)
{
PJ_UNUSED_ARG(prm);
std::cout
- 2024-10-13
-
回复了主题帖:
《CMake构建实战》CMake 变量
Jacktang 发表于 2024-10-13 08:37
CMake 变量和其他编程语言没有什么特色啊
个人感觉CMake变量比较随意,和其他编程语言还是有较大区别,需要熟悉之后才能应用
-
发表了主题帖:
《CMake构建实战》CMake 变量
# CMake 变量
继续学习《CMake构建实战》第3章 变量
同大多数编程语言一样,CMake中的变量也是存储数据的基本单元,但CMake变量都是文本型的,在使用时会被一些命令解释成数值、列表等。
## 变量分类
普通变量:大多数变量都是普通变量,它们具有特定的作用域
缓存变量:能够被缓存起来的变量,会被持久化到缓存文件`CMakeCache.txt`。例如第一次配置时会检测编译器路径,然后将其作为缓存变量持久化,避免每次执行都重新进行检测。
环境变量:操作系统中的环境变量,对CMake进程具有全局的作用域。
### 预定义变量
CMake中有许多预定义的普通变量和环境变量,他们一般以“CMAKE_”开头,例如:
`CMAKE_CURRENT_LIST_DIR` 表示当前运行中的CMake程序所在目录的绝对路径
`CMAKE_SYSTEM_NAME` 表示CMake构建的目标操作系统名称。
创建 1.cmake
```cmake
message("OS: ${CMAKE_HOST_SYSTEM_NAME}")
```
执行
```bash
$ cmake -P 1.cmake
OS: Linux
```
## 条件语法
CMake中几乎一切都是命令,条件语法名义上是“语法”,但其充其量是命令中的某种特定的参数形式。
### 常量、变量
真值常量:ON,YES,TRUE,Y,或非零数值
假值常量:0,OFF,NO,FALSE,N,IGNORE,空字符串,NOTFOUND
创建2.cmake
```cmake
cmake_minimum_required(VERSION 3.20)
if(ABC)
else()
message("ABC不是一个已定义的变量")
endif()
set(a "XYZ")
set(b "0")
set(c "a-NOTFOUND")
if(a)
message("a是一个变量,其值非假值常量,因此为真")
endif()
if(b)
else()
message("b是一个变量,其值假值常量,因此为假")
endif()
if(c)
else()
message("c是一个变量,其值假值常量,因此为假")
endif()
```
运行结果
```bash
$ cmake -P 2.cmake
ABC不是一个已定义的变量
a是一个变量,其值非假值常量,因此为真
b是一个变量,其值假值常量,因此为假
c是一个变量,其值假值常量,因此为假
```
### 逻辑运算
条件语法中可以包含与(AND)、或(OR)、非(NOT)三种逻辑运算。
创建`3.cmake`
```cmake
cmake_minimum_required(VERSION 3.20)
if(NOT OFF)
message("NOT OFF为真")
endif()
if(ON AND YES)
message("ON AND YES为真")
endif()
```
执行结果
```bash
$ cmake -P 3.cmake
NOT OFF为真
ON AND YES为真
```
- 2024-09-24
-
发表了主题帖:
【2024 DigiKey创意大赛】物料开箱
本帖最后由 小麦克 于 2024-9-25 08:13 编辑
# 【2024 DigiKey创意大赛】物料开箱
这次申请了两块开发板,STM32F411和ESP32-C6,其他都是凑单的芯片。
准备使用AD画一块集成了正点原子iMX93核心板的DEMO开发板,AD是边学边干,进度比较慢。
等板子出来后需要调试LAN8841和VK4619芯片的Linux驱动,然后准备做一款实时语音对讲应用。希望不要半途而废,加油!
全家福
ESP32-C6
STM32F411
ALL
AD学习中...
-
加入了学习《【Follow me第二季第2期】+开发板硬件介绍和实现任务一 LED灯闪烁和串口打印》,观看 【Follow me第二季第2期】+通过外部SHT40温湿度传感器,上传温湿度到HA
- 2024-09-14
-
回复了主题帖:
《CMake构建实战》CMake构建初探
-
发表了主题帖:
《CMake构建实战》CMake构建初探
# CMake构建初探
《CMake构建实战》第3章,第4章详细讲解了CMake这门语言,由于之前有过一点点CMake开发经验。先跳到第六章 `CMake构建初探` 来试试,有不懂的再回头找对应的知识点学习。否则真怕第三第四章没看完就把书扔一边了~
## CMake项目生命周期
### 配置阶段和生成阶段
CMake本身并不实际调用编译器和链接器,而是根据整个构建流程,生成Makefile或者其他构建工具的配置文件。
常用的构建系统生成器 `Unix Makefiles` `Ninja` 等
```bash
The following generators are available on this platform (* marks default):
Green Hills MULTI = Generates Green Hills MULTI files
(experimental, work-in-progress).
* Unix Makefiles = Generates standard UNIX makefiles.
Ninja = Generates build.ninja files.
Ninja Multi-Config = Generates build-.ninja files.
Watcom WMake = Generates Watcom WMake makefiles.
```
### 实例
下面通过一个静态库实例来演示CMake的配置和生成阶段。
新建`mylib`文件夹,创建`CMakeLists.txt` 和 `lib.c`
```bash
tree
.
└── mylib
├── CMakeLists.txt
└── lib.c
2 directories, 2 files
```
`CMakeLists.txt `
```cmake
cmake_minimum_required(VERSION 3.20)
project(mylib VERSION 1.0.0)
add_library(mylib STATIC lib.c)
install(TARGETS mylib)
set(CPACK_PACKAGE_NAME "mylib")
include(CPack)
```
`lib.c`
```c
int add(int a, int b) {
return a + b;
}
```
测试,新建`build`文件夹,用来存放生成的文件,防止污染源代码目录。进入`build`目录执行 `cmake ..`
```bash
mkdir build
cd build
cmake ..
-- The C compiler identification is GNU 13.2.0
-- The CXX compiler identification is GNU 13.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.3s)
-- Generating done (0.0s)
-- Build files have been written to: /home/bruce/Documents/study/cmake/6/001/mylib/build
```
执行成功后就生成了我们需要的Makefile文件,其实从这个角度讲,`CMake`就是帮助我们生成Makefile的工具,这样我们就不需要手动写复杂的`Makefile` 文件了。
下一步执行make即可生成最终目标文件
```bash
$ make
[ 50%] Building C object CMakeFiles/mylib.dir/lib.c.o
[100%] Linking C static library libmylib.a
[100%] Built target mylib
```
### 安装打包发布阶段
其实大部分情况下,上面的步骤已经完成日常开发了。CMake还能够打包发布,将需要的二进制文件打包,以便分发。这里不作过多介绍,需要时再详细了解。
- 2024-09-13
-
回复了主题帖:
《CMake构建实战》 - 引入CMake
-
发表了主题帖:
《CMake构建实战》 - 引入CMake
# CMake引入
### 为什么使用CMake
从之前的介绍中可知Linux平台中的Makefile和Windows不能做到很好的兼容。而CMake很好的解决了跨平台问题。CMake能做到一次编写,到处编译
CMake是高效的,写CMakeLists.txt比写Makefile高效,能帮助开发者将精力都放在写代码上
CMake是强大的,支持在同一项目中使用多种开发环境和编译器,支持多种编程语言,适合团队开发,几乎是构建C和C++项目的业界标准工具
### 安装CMake
在Ubuntu中安装,我安装的版本是`3.28.3`
```bash
bruce@ubuntu:~$ sudo apt install cmake
bruce@ubuntu:~$ cmake --version
cmake version 3.28.3
CMake suite maintained and supported by Kitware (kitware.com/cmake).
```
### 基础语法
`CMakeLists.txt` 项目顶层目录下的CMake入口文件
`.cmake` 指定`-P`参数执行脚本类型的CMake程序,这种CMake程序不会配置生成任何构建系统
`.cmake` 模块,通过`include`等命令引用模块程序
CMake程序几乎完全由命令调用构成,命令不区分大小写,一般使用小写
新建 `005`,创建`cmake.cmake`
```cmake
message(hello, CMake!)
```
执行
```bash
bruce@ubuntu:~/Documents/study/cmake/005$ cmake -P cmake.cmake
hello,CMake!
```
#### 命令参数
* 引号参数(quoted argument)
* 非引号参数(unquoted argument)
* 括号参数(bracket argument)
##### 引号参数(quoted argument)
```cmake
message("CMake
您好!")
```
```bash
bruce@ubuntu:~/Documents/study/cmake/005$ cmake -P 1.cmake
CMake
您好!
```
可以看到双引号`""`包裹的参数会原样的显示出来
##### 非引号参数(unquoted argument)
```cmake
message("x;y;z")
message(x y z)
message(x;y;z)
```
执行`cmake -P 2.cmake`
```bash
bruce@ubuntu:~/Documents/study/cmake/005$ cmake -P 2.cmake
x;y;z
xyz
xyz
```
##### 变量引用(variable reference)
创建`3.cmake`
```cmake
set(var_a 您好)
set(var_b a)
message(${var_${var_b}})
```
执行 `cmake -P 3.cmake`
```bash
bruce@ubuntu:~/Documents/study/cmake/005$ cmake -P 3.cmake
您好
```
- 2024-09-09
-
回复了主题帖:
《CMake构建实战》 - 构建之旅
13620203064 发表于 2024-9-6 17:20
有没有pdf文档,或者电子书的内容,发个链接。
上面内容的pdf文档,没有这本书的电子版
- 2024-09-06
-
发表了主题帖:
《CMake构建实战》 - 构建之旅
# 构建之旅
收到《CMake构建实战》有两天了,开始学习。
平时工作中也零零散散接触到CMake开发,比如QT6开始推荐使用CMake的方式进行构建。也做了几个QT CMake相关项目,但是项目模板都是工具自动生成的,项目改动不大。对CMake内部原理似懂非懂,遇到问题也不知道如何下手。
非常感谢论坛能给我提供这个机会,后面我会和坛友们一起学习,一起进步。
### 构建之旅
第一章先从构建基础讲起,让我们了解构建原理。书中对Windows和Linux分别做了讲解,但是原理差不多。由于我最近在学习Linux,比较熟悉Linux开发环境,后面都在Linux环境下进行测试,Windows和macOS环境了解即可。
#### 一、静态库
静态库(static library),也称静态链接库(statically-linked library)。在静态库中包含了所有目标文件,还有一些符号索引。在我们程序链接静态库时,会将需要的函数、变量等目标代码会全部拷贝到我们的程序中,发布程序时不再需要带上这些静态库。好处是程序运行时没有依赖问题,坏处是我们的程序体积会变大。
按照书上的示例,新建下面几个文件
```bash
bruce@ubuntu:~/Documents/study/cmake/001$ tree
.
├── a.c
├── b.c
├── libab.h
├── main.c
└── Makefile
1 directory, 5 files
```
为了方便测试,`Makefile`中添加了`clean`目标
```makefile
main: main.o libab.a
gcc main.o -o main -L. -lab
main.o: main.c
gcc -c main.c -o main.o
libab.a: a.o b.o
ar rcs libab.a a.o b.o
a.o: a.c
gcc -c a.c -o a.o
b.o: b.c
gcc -c b.c -o b.o
.PHONY: clean
clean:
rm -rf *.o *.a main
```
测试,可以看到生成了静态库文件`libab.a`
```bash
bruce@ubuntu:~/Documents/study/cmake/001$ make
gcc -c main.c -o main.o
gcc -c a.c -o a.o
gcc -c b.c -o b.o
ar rcs libab.a a.o b.o
gcc main.o -o main -L. -lab
bruce@ubuntu:~/Documents/study/cmake/001$ tree
.
├── a.c
├── a.o
├── b.c
├── b.o
├── libab.a
├── libab.h
├── main
├── main.c
├── main.o
└── Makefile
1 directory, 10 files
bruce@ubuntu:~/Documents/study/cmake/001$ ls -alh
总计 60K
drwxrwxr-x 2 bruce bruce 4.0K Sep 6 11:33 .
drwxrwxr-x 3 bruce bruce 4.0K Sep 6 11:30 ..
-rw-rw-r-- 1 bruce bruce 54 Sep 6 11:12 a.c
-rw-rw-r-- 1 bruce bruce 1.5K Sep 6 11:33 a.o
-rw-rw-r-- 1 bruce bruce 54 Sep 6 11:13 b.c
-rw-rw-r-- 1 bruce bruce 1.5K Sep 6 11:33 b.o
-rw-rw-r-- 1 bruce bruce 3.1K Sep 6 11:33 libab.a
-rw-rw-r-- 1 bruce bruce 81 Sep 6 11:15 libab.h
-rwxrwxr-x 1 bruce bruce 16K Sep 6 11:33 main
-rw-rw-r-- 1 bruce bruce 82 Sep 6 11:16 main.c
-rw-rw-r-- 1 bruce bruce 1.4K Sep 6 11:33 main.o
-rw-rw-r-- 1 bruce bruce 236 Sep 6 11:28 Makefile
bruce@ubuntu:~/Documents/study/cmake/001$ ./main
a
b
bruce@ubuntu:~/Documents/study/cmake/001$
```
将main单独拷贝到其他目录也能执行,不需要带上`libab.a`
#### 二、动态库
动态库(dynamic library),也称动态链接库(Dynamically-Linked Library, DLL)或共享库(shared library)。与静态库不同,动态库的目标代码在程序转载时或运行时被动态链接。
好处是和程序解耦,可以单独更新,我们的应用程序体积不会增大。坏处是随着时间的推移,应用程序可能和动态库出现不兼容的情况,这种情况对最终目标客户是个灾难。
拷贝之前的001文件夹为002,修改`Makefile`
```bash
main: main.o libab.so
gcc main.o -o main -L. '-Wl,-R$$ORIGIN' -lab
main.o: main.c
gcc -c main.c -o main.o
libab.so: a.o b.o
gcc -shared a.o b.o -o libab.so
a.o: a.c
gcc -c a.c -o a.o
b.o: b.c
gcc -c b.c -o b.o
.PHONY: clean
clean:
rm -rf *.o *.so main
```
主要改动了`libab.so`生成方法:`gcc -shared a.o b.o -o libab.so`
注意,生成`main`需要添加 `'-Wl,-R$$ORIGIN'`,否则会出现错误 `./main: error while loading shared libraries: libab.so: cannot open shared object file: No such file or directory`
#### 三、引用第三方库
C和C++编程的一大优势是丰富的生态,让我们站在巨人的肩膀上。学习一下引用第三方 `Boost` 库。
下载boost库,解压到`~/boost`
```bash
cd ~
wget https://archives.boost.io/release/1.86.0/source/boost_1_86_0.tar.gz
tar -xf boost_1_86_0.tar.gz boost
```
创建`main.cpp`和`Makefile`,编译测试
```bash
bruce@ubuntu:~/Documents/study/cmake/003$ tree
.
├── main
├── main.cpp
└── Makefile
1 directory, 3 files
bruce@ubuntu:~/Documents/study/cmake/003$ cat Makefile
main: main.cpp
g++ main.cpp -I ~/boost -o main
clean:
rm main
bruce@ubuntu:~/Documents/study/cmake/003$ cat main.cpp
#include
#include
using namespace std;
using namespace boost;
int main(void) {
string str = " hello world!";
cout
- 2024-08-31
-
回复了主题帖:
读书入围名单: 《CMake构建实战:项目开发卷》
个人信息无误,确认可以完成阅读分享计划