- 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构建实战:项目开发卷》
个人信息无误,确认可以完成阅读分享计划
- 2024-08-28
-
回复了主题帖:
【米尔 NXP i.MX93 开发板评测】搭建QT交叉编译环境
Jacktang 发表于 2024-8-28 07:27
i.MX93没有GPU,不支持opengl,开发的时候有点不方便的
和定位有关,工业应用。普通的QT UI应用没问题的,适配了DRM,也能高清显示,最高可达1080p60,一般场景足够了。
- 2024-08-27
-
发表了主题帖:
【米尔 NXP i.MX93 开发板评测】搭建QT交叉编译环境
本帖最后由 小麦克 于 2024-8-27 10:14 编辑
## QT交叉编译环境
需要提前安装好cmake和ninja
```bash
sudo apt install cmake
sudo apt install ninja-build
```
## 基于Yocto编译环境
关于Yocto环境,米尔专门提供了一篇教程《MYD-LMX9X+QT开发指南.pdf》,里面写的很详细了,我这里就不重复了,有两个地方需要注意一下。
### Sysroot配置问题
教程中的`Sysroot`有点问题,应该为 `/opt/fsl-imx-xwayland/6.1-mickledore/sysroots/armv8a-poky-linux` 而不是 `/opt/fsl-imx-xwayland/6.1-mickledore/sysroots/x86_64-pokysdk-linux`
### CMake构建失败
上面配置都成功了,开始创建QT应用,如果使用`qmake`方式构建应用一切正常。但是如果使用`CMake`方式构建,配置阶段为提示错误:`To use a cross-compiled Qt, please set the QT_HOST_PATH cache variable to the location of your host Qt installation.`
解决方法:需要在`CMakeLists.txt` 中设置 `QT_HOST_PATH`为主机QT的gcc目录,我安装的目录是 `/home/bruce/Qt/6.5.3/gcc_64`
```cmake
set(QT_HOST_PATH /home/bruce/Qt/6.5.3/gcc_64)
```
重新配置后成功了
编译上传测试程序到开发板测试。
## buildroot环境
由于我们之前的根文件系统都是基于`buildroot`,下面来看看怎么在`buildroot`构建的系统上面配置QT的交叉编译环境。
### 构建SDK
确保配置的`buildroot`构建成功,能成功打包成文件系统。下面是我的配置文件(基于当前最新的buildroot仓库-2024-08-27)
```bash
BR2_aarch64=y
BR2_cortex_a55=y
BR2_ARM_FPU_VFPV4D16=y
BR2_KERNEL_HEADERS_6_1=y
BR2_PACKAGE_GLIBC_UTILS=y
BR2_TOOLCHAIN_BUILDROOT_CXX=y
BR2_PACKAGE_HOST_GDB=y
BR2_ENABLE_DEBUG=y
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_MDEV=y
BR2_ROOTFS_MERGED_USR=y
BR2_SYSTEM_DHCP="eth0"
BR2_SYSTEM_DEFAULT_PATH="/bin:/sbin:/usr/bin:/usr/sbin"
BR2_ENABLE_LOCALE_WHITELIST="en_US.UTF-8"
BR2_GENERATE_LOCALE="en_US.UTF-8"
BR2_SYSTEM_ENABLE_NLS=y
BR2_TARGET_TZ_INFO=y
BR2_PACKAGE_ALSA_UTILS=y
BR2_PACKAGE_ALSA_UTILS_ALSACONF=y
BR2_PACKAGE_ALSA_UTILS_ACONNECT=y
BR2_PACKAGE_ALSA_UTILS_ALSALOOP=y
BR2_PACKAGE_ALSA_UTILS_ALSAUCM=y
BR2_PACKAGE_ALSA_UTILS_ALSATPLG=y
BR2_PACKAGE_ALSA_UTILS_AMIDI=y
BR2_PACKAGE_ALSA_UTILS_AMIXER=y
BR2_PACKAGE_ALSA_UTILS_APLAY=y
BR2_PACKAGE_ALSA_UTILS_APLAYMIDI=y
BR2_PACKAGE_ALSA_UTILS_ARECORDMIDI=y
BR2_PACKAGE_ALSA_UTILS_ASEQDUMP=y
BR2_PACKAGE_ALSA_UTILS_ASEQNET=y
BR2_PACKAGE_ALSA_UTILS_BAT=y
BR2_PACKAGE_ALSA_UTILS_IECSET=y
BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y
BR2_PACKAGE_FFMPEG_GPL=y
BR2_PACKAGE_FFMPEG_NONFREE=y
BR2_PACKAGE_FFMPEG_FFPLAY=y
BR2_PACKAGE_FFMPEG_FFPROBE=y
BR2_PACKAGE_FFMPEG_POSTPROC=y
BR2_PACKAGE_FLAC=y
BR2_PACKAGE_GSTREAMER1=y
BR2_PACKAGE_GSTREAMER1_CHECK=y
BR2_PACKAGE_GST1_PLUGINS_BASE_PLUGIN_APP=y
BR2_PACKAGE_GST1_PLUGINS_BAYER2RGB_NEON=y
BR2_PACKAGE_GST1_PLUGINS_GOOD=y
BR2_PACKAGE_GST1_PLUGINS_BAD=y
BR2_PACKAGE_GST1_LIBAV=y
BR2_PACKAGE_GDB=y
BR2_PACKAGE_GDB_SERVER=y
BR2_PACKAGE_GDB_DEBUGGER=y
BR2_PACKAGE_GDB_TUI=y
BR2_PACKAGE_BINUTILS=y
BR2_PACKAGE_BINUTILS_TARGET=y
BR2_PACKAGE_LIBTOOL=y
BR2_PACKAGE_MAKE=y
BR2_PACKAGE_PKGCONF=y
BR2_PACKAGE_TREE=y
BR2_PACKAGE_MMC_UTILS=y
BR2_PACKAGE_BITSTREAM_VERA=y
BR2_PACKAGE_CANTARELL=y
BR2_PACKAGE_DEJAVU=y
BR2_PACKAGE_FONT_AWESOME=y
BR2_PACKAGE_GHOSTSCRIPT_FONTS=y
BR2_PACKAGE_INCONSOLATA=y
BR2_PACKAGE_LIBERATION=y
BR2_PACKAGE_WQY_ZENHEI=y
BR2_PACKAGE_DIRECTFB=y
BR2_PACKAGE_SDL=y
BR2_PACKAGE_SDL_GFX=y
BR2_PACKAGE_SDL_IMAGE=y
BR2_PACKAGE_SDL_IMAGE_GIF=y
BR2_PACKAGE_SDL_IMAGE_JPEG=y
BR2_PACKAGE_SDL_IMAGE_LBM=y
BR2_PACKAGE_SDL_IMAGE_PCX=y
BR2_PACKAGE_SDL_IMAGE_PNG=y
BR2_PACKAGE_SDL_IMAGE_PNM=y
BR2_PACKAGE_SDL_IMAGE_TARGA=y
BR2_PACKAGE_SDL_IMAGE_TIFF=y
BR2_PACKAGE_SDL_IMAGE_WEBP=y
BR2_PACKAGE_SDL_IMAGE_XCF=y
BR2_PACKAGE_SDL_IMAGE_XPM=y
BR2_PACKAGE_SDL_IMAGE_XV=y
BR2_PACKAGE_SDL_MIXER=y
BR2_PACKAGE_SDL_MIXER_MIDI_TIMIDITY=y
BR2_PACKAGE_SDL_NET=y
BR2_PACKAGE_SDL_TTF=y
BR2_PACKAGE_QT6=y
BR2_PACKAGE_QT6BASE_CONCURRENT=y
BR2_PACKAGE_QT6BASE_DBUS=y
BR2_PACKAGE_QT6BASE_VULKAN=y
BR2_PACKAGE_QT6BASE_FONTCONFIG=y
BR2_PACKAGE_QT6BASE_HARFBUZZ=y
BR2_PACKAGE_QT6BASE_GIF=y
BR2_PACKAGE_QT6BASE_JPEG=y
BR2_PACKAGE_QT6BASE_PNG=y
BR2_PACKAGE_QT6BASE_WIDGETS=y
BR2_PACKAGE_QT6BASE_PRINTSUPPORT=y
BR2_PACKAGE_QT6BASE_SYSLOG=y
BR2_PACKAGE_QT6BASE_TEST=y
BR2_PACKAGE_QT6BASE_TSLIB=y
BR2_PACKAGE_QT6CORE5COMPAT=y
BR2_PACKAGE_QT6SERIALBUS=y
BR2_PACKAGE_QT6SVG=y
BR2_PACKAGE_EVEMU=y
BR2_PACKAGE_EVTEST=y
BR2_PACKAGE_KBD=y
BR2_PACKAGE_SYSSTAT=y
BR2_PACKAGE_LIBG7221=y
BR2_PACKAGE_LIBGSM=y
BR2_PACKAGE_LIBILBC=y
BR2_PACKAGE_LIBSAMPLERATE=y
BR2_PACKAGE_OPENCORE_AMR=y
BR2_PACKAGE_PORTAUDIO=y
BR2_PACKAGE_WEBRTC_AUDIO_PROCESSING=y
BR2_PACKAGE_SQLITE_ENABLE_COLUMN_METADATA=y
BR2_PACKAGE_IMLIB2=y
BR2_PACKAGE_IMLIB2_JPEG=y
BR2_PACKAGE_IMLIB2_PNG=y
BR2_PACKAGE_IMLIB2_GIF=y
BR2_PACKAGE_IMLIB2_TIFF=y
BR2_PACKAGE_IMLIB2_ID3=y
BR2_PACKAGE_LIBJPEG=y
BR2_PACKAGE_LIBDRM_INSTALL_TESTS=y
BR2_PACKAGE_LIBFREEIMAGE=y
BR2_PACKAGE_LIBVA=y
BR2_PACKAGE_WAYLAND=y
BR2_PACKAGE_WAYLAND_UTILS=y
BR2_PACKAGE_LIBAIO=y
BR2_PACKAGE_LIBV4L=y
BR2_PACKAGE_LIBV4L_UTILS=y
BR2_PACKAGE_LIBOPENH264=y
BR2_PACKAGE_LIBYUV=y
BR2_PACKAGE_X264=y
BR2_PACKAGE_X264_CLI=y
BR2_PACKAGE_LIBPJSIP=y
BR2_PACKAGE_LIBRSYNC=y
BR2_PACKAGE_LIBUPNP=y
BR2_PACKAGE_LIBCAP=y
BR2_PACKAGE_FMT=y
BR2_PACKAGE_PCRE2_32=y
BR2_PACKAGE_DHCPCD=y
BR2_PACKAGE_FREESWITCH=y
BR2_PACKAGE_FREESWITCH_MOD_BCG729=y
BR2_PACKAGE_OPENSSH=y
BR2_PACKAGE_TCPDUMP=y
BR2_PACKAGE_VSFTPD=y
BR2_PACKAGE_ZSH=y
BR2_PACKAGE_KMOD=y
BR2_PACKAGE_UTIL_LINUX_LIBFDISK=y
BR2_PACKAGE_UTIL_LINUX_AGETTY=y
BR2_PACKAGE_UTIL_LINUX_FSCK=y
BR2_PACKAGE_UTIL_LINUX_HWCLOCK=y
BR2_PACKAGE_UTIL_LINUX_KILL=y
BR2_PACKAGE_UTIL_LINUX_LSFD=y
BR2_PACKAGE_UTIL_LINUX_MORE=y
BR2_PACKAGE_UTIL_LINUX_MOUNT=y
BR2_PACKAGE_UTIL_LINUX_SULOGIN=y
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_SIZE="512M"
BR2_TARGET_ROOTFS_TAR_GZIP=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
```
构建SDK,构建成功后,在`output/images`文件夹下会生成 `aarch64-buildroot-linux-gnu_sdk-buildroot.tar.gz`SDK,这个SDK可以拷贝到其他电脑或者其他目录,进行应用开发。
```bash
make sdk
```
我这里拷贝到`/home/bruce/Documents`文件夹下,解压,重定位
```bash
# 解压
tar -xf aarch64-buildroot-linux-gnu_sdk-buildroot.tar.gz
# 重定位(只需要执行一次)
cd aarch64-buildroot-linux-gnu_sdk-buildroot/
./relocate-sdk.sh
```
生成新的QT配置,C和C++编译器配置
QT Versions配置,有红色的错误,不用管。
Devices配置
上面都配置好后,最后配置一下Kits,添加一个imx93的配置项。注意`Sysroot`的位置
新建一个CMake QT测试程序,配置为`imx93`,编译,成功!
如果不使用`Qt Creator`,`buildroot`还为我们准备了`environment-setup`脚本,需要交叉编译的时候直接`source`一下,一切就准备就绪了。看下面的示例
```bash
source ~/Documents/aarch64-buildroot-linux-gnu_sdk-buildroot/environment-setup
# 进入qt app目录编译
bruce@ubuntu:~/Documents/qt/qt-apps/test-app/build$ cmake ..
-- The CXX compiler identification is GNU 13.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /home/bruce/Documents/aarch64-buildroot-linux-gnu_sdk-buildroot/bin/aarch64-buildroot-linux-gnu-g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Performing Test HAVE_STDATOMIC
-- Performing Test HAVE_STDATOMIC - Success
-- Found WrapAtomic: TRUE
-- Configuring done (1.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/bruce/Documents/qt/qt-apps/test-app/build
bruce@ubuntu:~/Documents/qt/qt-apps/test-app/build$ make
[ 0%] Built target test-app_autogen_timestamp_deps
[ 16%] Automatic MOC and UIC for target test-app
[ 16%] Built target test-app_autogen
[ 33%] Building CXX object CMakeFiles/test-app.dir/test-app_autogen/mocs_compilation.cpp.o
[ 50%] Building CXX object CMakeFiles/test-app.dir/main.cpp.o
[ 66%] Building CXX object CMakeFiles/test-app.dir/mainwindow.cpp.o
[ 83%] Linking CXX executable test-app
[100%] Built target test-app
bruce@ubuntu:~/Documents/qt/qt-apps/test-app/build$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake Makefile test-app test-app_autogen
bruce@ubuntu:~/Documents/qt/qt-apps/test-app/build$ file test-app
test-app: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 6.1.0, with debug_info, not stripped
```
可以看到生成的`test-app`就是`ARM aarch64`。
这种方式适合自动化,对项目组提交的代码进行自动编译打包或者测试。
## 树莓派
最近搞了一台8GB的树莓派5,测试下来性能还不错,前提必须上PCI-E固态硬盘,SD卡相对于固态硬盘太慢了。
因为和IMX93使用了同样的`aarch64`架构,接上显示器,用来开发原生QT更简单,不需要配置复杂的交叉编译环境。
我这里通过VNC连接到了树莓派5,安装Qt Creator IDE,编译出的程序可以直接放到开发板运行。需要注意的是i.MX93没有GPU,不支持opengl,因此开发的时候不能调用这些库。否则在开发板加载程序会失败。
## 结论
本篇将QT开发的几种方式都做了测试,欢迎大家指正补充~
- 2024-08-23
-
发表了主题帖:
【米尔 NXP i.MX93 开发板评测】嵌入式QT开发
# 嵌入式QT测试
iMX93支持`drm`。之前在IMX93上测试了一下`LVGL`,发现`LVGL`对`Linux`的优化不太好,有些场景有卡顿,LVGL还是比较适合单片机的应用场景。对比研究下来感觉还是QT更加适合嵌入式Linux UI应用。毕竟QT功能更加强大,如果QT用熟悉了,QT不仅仅可以开发UI程序,还能写一些复杂的服务。
## Linux显示子DRM
Linux DRM是Linux下比较新的显示子系统,相比之前的framebuffer功能更加强大。
配置`buildroot`,添加 test programs
查看当前`drm`驱动信息
```bash
modetest
```
测试,显示器会有彩色条纹抖动。
```bash
modetest -M imx-drm -s 35@33:720x1280 -v
```
## 事件测试
触摸屏触摸测试,从后面的说明可以看出`/dev/input/event1`为触摸屏,输入1,触摸屏幕看到有新事件。
```bash
# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: 44440000.bbnsm:pwrkey
/dev/input/event1: Goodix Capacitive TouchScreen
/dev/input/event2: gpio_keys@0
/dev/input/event3: Logitech Inc. Logi USB Headset H340 Consumer Control
/dev/input/event4: Logitech Inc. Logi USB Headset H340
Select the device event number [0-4]: 1
Input driver version is 1.0.1
Input device ID: bus 0x18 vendor 0x416 product 0x38f version 0x1060
Input device name: "Goodix Capacitive TouchScreen"
```
## QT开发
从github同步最新的buildroot编译QT6.7,配置常用的库。
这是我当前的buildroot配置信息
```bash
BR2_aarch64=y
BR2_cortex_a55=y
BR2_ARM_FPU_VFPV4D16=y
BR2_KERNEL_HEADERS_6_1=y
BR2_PACKAGE_GLIBC_UTILS=y
BR2_TOOLCHAIN_BUILDROOT_CXX=y
BR2_PACKAGE_HOST_GDB=y
BR2_ENABLE_DEBUG=y
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_MDEV=y
BR2_ROOTFS_MERGED_USR=y
BR2_SYSTEM_DHCP="eth0"
BR2_SYSTEM_DEFAULT_PATH="/bin:/sbin:/usr/bin:/usr/sbin"
BR2_ENABLE_LOCALE_WHITELIST="en_US.UTF-8"
BR2_GENERATE_LOCALE="en_US.UTF-8"
BR2_SYSTEM_ENABLE_NLS=y
BR2_TARGET_TZ_INFO=y
BR2_PACKAGE_ALSA_UTILS=y
BR2_PACKAGE_ALSA_UTILS_ALSACONF=y
BR2_PACKAGE_ALSA_UTILS_ACONNECT=y
BR2_PACKAGE_ALSA_UTILS_ALSALOOP=y
BR2_PACKAGE_ALSA_UTILS_ALSAUCM=y
BR2_PACKAGE_ALSA_UTILS_ALSATPLG=y
BR2_PACKAGE_ALSA_UTILS_AMIDI=y
BR2_PACKAGE_ALSA_UTILS_AMIXER=y
BR2_PACKAGE_ALSA_UTILS_APLAY=y
BR2_PACKAGE_ALSA_UTILS_APLAYMIDI=y
BR2_PACKAGE_ALSA_UTILS_ARECORDMIDI=y
BR2_PACKAGE_ALSA_UTILS_ASEQDUMP=y
BR2_PACKAGE_ALSA_UTILS_ASEQNET=y
BR2_PACKAGE_ALSA_UTILS_BAT=y
BR2_PACKAGE_ALSA_UTILS_IECSET=y
BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y
BR2_PACKAGE_FFMPEG_GPL=y
BR2_PACKAGE_FFMPEG_NONFREE=y
BR2_PACKAGE_FFMPEG_FFPLAY=y
BR2_PACKAGE_FFMPEG_FFPROBE=y
BR2_PACKAGE_FFMPEG_POSTPROC=y
BR2_PACKAGE_FLAC=y
BR2_PACKAGE_GSTREAMER1=y
BR2_PACKAGE_GSTREAMER1_CHECK=y
BR2_PACKAGE_GST1_PLUGINS_BASE_PLUGIN_APP=y
BR2_PACKAGE_GST1_PLUGINS_BAYER2RGB_NEON=y
BR2_PACKAGE_GST1_PLUGINS_GOOD=y
BR2_PACKAGE_GST1_PLUGINS_BAD=y
BR2_PACKAGE_GST1_LIBAV=y
BR2_PACKAGE_GDB=y
BR2_PACKAGE_GDB_SERVER=y
BR2_PACKAGE_GDB_DEBUGGER=y
BR2_PACKAGE_GDB_TUI=y
BR2_PACKAGE_BINUTILS=y
BR2_PACKAGE_BINUTILS_TARGET=y
BR2_PACKAGE_LIBTOOL=y
BR2_PACKAGE_MAKE=y
BR2_PACKAGE_PKGCONF=y
BR2_PACKAGE_TREE=y
BR2_PACKAGE_MMC_UTILS=y
BR2_PACKAGE_BITSTREAM_VERA=y
BR2_PACKAGE_CANTARELL=y
BR2_PACKAGE_DEJAVU=y
BR2_PACKAGE_FONT_AWESOME=y
BR2_PACKAGE_GHOSTSCRIPT_FONTS=y
BR2_PACKAGE_INCONSOLATA=y
BR2_PACKAGE_LIBERATION=y
BR2_PACKAGE_WQY_ZENHEI=y
BR2_PACKAGE_DIRECTFB=y
BR2_PACKAGE_SDL=y
BR2_PACKAGE_SDL_GFX=y
BR2_PACKAGE_SDL_IMAGE=y
BR2_PACKAGE_SDL_IMAGE_GIF=y
BR2_PACKAGE_SDL_IMAGE_JPEG=y
BR2_PACKAGE_SDL_IMAGE_LBM=y
BR2_PACKAGE_SDL_IMAGE_PCX=y
BR2_PACKAGE_SDL_IMAGE_PNG=y
BR2_PACKAGE_SDL_IMAGE_PNM=y
BR2_PACKAGE_SDL_IMAGE_TARGA=y
BR2_PACKAGE_SDL_IMAGE_TIFF=y
BR2_PACKAGE_SDL_IMAGE_WEBP=y
BR2_PACKAGE_SDL_IMAGE_XCF=y
BR2_PACKAGE_SDL_IMAGE_XPM=y
BR2_PACKAGE_SDL_IMAGE_XV=y
BR2_PACKAGE_SDL_MIXER=y
BR2_PACKAGE_SDL_MIXER_MIDI_TIMIDITY=y
BR2_PACKAGE_SDL_NET=y
BR2_PACKAGE_SDL_TTF=y
BR2_PACKAGE_QT6=y
BR2_PACKAGE_QT6BASE_CONCURRENT=y
BR2_PACKAGE_QT6BASE_DBUS=y
BR2_PACKAGE_QT6BASE_VULKAN=y
BR2_PACKAGE_QT6BASE_FONTCONFIG=y
BR2_PACKAGE_QT6BASE_HARFBUZZ=y
BR2_PACKAGE_QT6BASE_GIF=y
BR2_PACKAGE_QT6BASE_JPEG=y
BR2_PACKAGE_QT6BASE_PNG=y
BR2_PACKAGE_QT6BASE_WIDGETS=y
BR2_PACKAGE_QT6BASE_PRINTSUPPORT=y
BR2_PACKAGE_QT6BASE_SYSLOG=y
BR2_PACKAGE_QT6BASE_TEST=y
BR2_PACKAGE_QT6BASE_TSLIB=y
BR2_PACKAGE_QT6CORE5COMPAT=y
BR2_PACKAGE_QT6SERIALBUS=y
BR2_PACKAGE_QT6SVG=y
BR2_PACKAGE_EVEMU=y
BR2_PACKAGE_EVTEST=y
BR2_PACKAGE_KBD=y
BR2_PACKAGE_LIBG7221=y
BR2_PACKAGE_LIBGSM=y
BR2_PACKAGE_LIBILBC=y
BR2_PACKAGE_LIBSAMPLERATE=y
BR2_PACKAGE_OPENCORE_AMR=y
BR2_PACKAGE_PORTAUDIO=y
BR2_PACKAGE_WEBRTC_AUDIO_PROCESSING=y
BR2_PACKAGE_SQLITE_ENABLE_COLUMN_METADATA=y
BR2_PACKAGE_IMLIB2=y
BR2_PACKAGE_IMLIB2_JPEG=y
BR2_PACKAGE_IMLIB2_PNG=y
BR2_PACKAGE_IMLIB2_GIF=y
BR2_PACKAGE_IMLIB2_TIFF=y
BR2_PACKAGE_IMLIB2_ID3=y
BR2_PACKAGE_LIBJPEG=y
BR2_PACKAGE_LIBDRM_INSTALL_TESTS=y
BR2_PACKAGE_LIBFREEIMAGE=y
BR2_PACKAGE_LIBVA=y
BR2_PACKAGE_WAYLAND=y
BR2_PACKAGE_WAYLAND_UTILS=y
BR2_PACKAGE_LIBAIO=y
BR2_PACKAGE_LIBV4L=y
BR2_PACKAGE_LIBV4L_UTILS=y
BR2_PACKAGE_LIBOPENH264=y
BR2_PACKAGE_LIBYUV=y
BR2_PACKAGE_X264=y
BR2_PACKAGE_X264_CLI=y
BR2_PACKAGE_LIBPJSIP=y
BR2_PACKAGE_LIBUPNP=y
BR2_PACKAGE_LIBCAP=y
BR2_PACKAGE_FMT=y
BR2_PACKAGE_PCRE2_32=y
BR2_PACKAGE_DHCPCD=y
BR2_PACKAGE_FREESWITCH=y
BR2_PACKAGE_FREESWITCH_MOD_BCG729=y
BR2_PACKAGE_OPENSSH=y
BR2_PACKAGE_TCPDUMP=y
BR2_PACKAGE_VSFTPD=y
BR2_PACKAGE_ZSH=y
BR2_PACKAGE_KMOD=y
BR2_PACKAGE_UTIL_LINUX_LIBFDISK=y
BR2_PACKAGE_UTIL_LINUX_AGETTY=y
BR2_PACKAGE_UTIL_LINUX_FSCK=y
BR2_PACKAGE_UTIL_LINUX_HWCLOCK=y
BR2_PACKAGE_UTIL_LINUX_KILL=y
BR2_PACKAGE_UTIL_LINUX_LSFD=y
BR2_PACKAGE_UTIL_LINUX_MORE=y
BR2_PACKAGE_UTIL_LINUX_MOUNT=y
BR2_PACKAGE_UTIL_LINUX_SULOGIN=y
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_SIZE="512M"
BR2_TARGET_ROOTFS_TAR_GZIP=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
```
经过测试,低版本QT Creator交叉编译的QT APP应用程序可以运行在高版本库上面;但是高版本QT Creator 编译的app应用程序不能跑在低版本的QT库上面。
## 运行QT前的配置
通过上面的测试可知,触摸屏的input设备是 `/dev/input/event1`。注意我的buildroot里面配置了字体,如果不配置字体,QT应用会用方框代替字符。将下面的环境变量导入到当前终端中。
```bash
# 通过上面的evtest测试可知event1为触摸屏
export TSLIB_TSDEVICE=/dev/input/event1
export QT_QPA_FB_TSLIB=1
export QT_QPA_PLATFORM=linuxfb
export QT_QPA_FONTDIR=/usr/share/fonts
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
# QT适配高分屏
export QT_SCREEN_SCALE_FACTORS=2
```
打开程序测试,观察现象
下载QT开发工具:https://download.qt.io/archive/online_installers/
后面会写一篇上位机QT交叉编译器搭建,马上回来~
- 2024-08-16
-
发表了主题帖:
【米尔 NXP i.MX93 开发板评测】GDB调试
# GDB调试
在调试应用程序时出了问题,需要在线调试,下面看看在设备端进行GDB调试的方法。
配置`buildroot`,生成目标设备`gdb`工具,打包生成文件系统下载到设备中。
```bash
Target packages
Debugging, profiling and benchmark
```
重新编译要调试的app,添加编译参数`-g`增加调试信息。下面以`buildroot`中的`libpjsip`为例进行说明。
`buildroot`默认情况下不带调试信息,找到`libpjsip`这个包的配置文件`libpjsip.mk`增加一行`LIBPJSIP_CFLAGS += -g`
重新编译`libpjsip`
```bash
make libpjsip-dirclean
make libpjsip-rebuild
```
将需要调试的应用程序下载到开发板,使用GDB进行调试。
```bash
gdb samples/aarch64-buildroot-linux-gnu/simpleua
(gdb) set args sip:bruce@192.168.1.228
(gdb) set print pretty on
(gdb) set listsize 20
(gdb) b main
(gdb) r
Starting program: /root/pjsip-apps/bin/samples/aarch64-buildroot-linux-gnu/simpleua sip:bruce@192.168.1.228
warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.
Breakpoint 1, main (argc=2, argv=0xffffc2490e08)
at ../src/samples/simpleua.c:225
225 {
(gdb) n
```
以上步骤操作说明:
1. 使用GDB加载应用程序,`gdb samples/aarch64-buildroot-linux-gnu/simpleua`
2. 设置几个参数:`args` 给应用的参数,`print pretty on` 格式化结构体(更方便查看变量),`set listsize 20` 设置一次显示的行数(默认10行)
3. 设置断点 `b main`
4. 运行:r
5. 发现程序在mian函数第一行停住,等待进一步操作指令。
运行过程中需要打印复杂结构体,比如这里的`local_sdp`指针变量
```
(gdb) p *local_sdp.media[0]
```
所有变量都会显示出来
还可以继续深挖下去,通过这种方法能查看所有变量的值。
```bash
(gdb) p *local_sdp.media[0].attr
$9 = (pjmedia_sdp_attr *) 0xaaaac01b10c8
(gdb) p **local_sdp.media[0].attr
$10 = {
name = {
ptr = 0xffff949899f8 "rtcp",
slen = 4
},
value = {
ptr = 0xaaaac01b10e8 "4001 IN IP4 192.168.1.189",
slen = 25
}
}
(gdb)
```
经过上面的调试,终于找到应用程序API调用失败是因为缺少编码器。将`package/libpjsip/libpjsip.mk`中屏蔽的编码器都打开。再次测试`simpleua`程序呼叫成功。
- 2024-08-14
-
发表了主题帖:
【米尔 NXP i.MX93 开发板评测】buildroot交叉编译实践
本帖最后由 小麦克 于 2024-8-14 16:30 编辑
# buildroot交叉编译实践
`buildroot`用来作为嵌入式linux系统开发还是非常方便的,编译器配置为`buildroot`自动生成。
`uboot`和`linux`内核采用开发板自带的。通过`buildroot`制作`rootfs`,然后再使用`buildroot`制作交叉编译的环境。这个环境中包含了我们之前加入的库,我们开发新的app就可以交叉编译并链接。
## 编译
当前的`buildroot`配置如下(保存为myirdeconfig放到`configs`目录)
```bash
BR2_aarch64=y
BR2_cortex_a55=y
BR2_ARM_FPU_VFPV4D16=y
BR2_KERNEL_HEADERS_6_1=y
BR2_PACKAGE_GLIBC_UTILS=y
BR2_TOOLCHAIN_BUILDROOT_CXX=y
BR2_PACKAGE_HOST_GDB=y
BR2_INIT_SYSTEMD=y
BR2_SYSTEM_DHCP="eth0"
BR2_SYSTEM_DEFAULT_PATH="/bin:/sbin:/usr/bin:/usr/sbin"
BR2_PACKAGE_ALSA_UTILS=y
BR2_PACKAGE_ALSA_UTILS_ALSACONF=y
BR2_PACKAGE_ALSA_UTILS_ACONNECT=y
BR2_PACKAGE_ALSA_UTILS_ALSALOOP=y
BR2_PACKAGE_ALSA_UTILS_ALSAUCM=y
BR2_PACKAGE_ALSA_UTILS_ALSATPLG=y
BR2_PACKAGE_ALSA_UTILS_AMIDI=y
BR2_PACKAGE_ALSA_UTILS_AMIXER=y
BR2_PACKAGE_ALSA_UTILS_APLAY=y
BR2_PACKAGE_ALSA_UTILS_APLAYMIDI=y
BR2_PACKAGE_ALSA_UTILS_ARECORDMIDI=y
BR2_PACKAGE_ALSA_UTILS_ASEQDUMP=y
BR2_PACKAGE_ALSA_UTILS_ASEQNET=y
BR2_PACKAGE_ALSA_UTILS_BAT=y
BR2_PACKAGE_ALSA_UTILS_IECSET=y
BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y
BR2_PACKAGE_FFMPEG_GPL=y
BR2_PACKAGE_FFMPEG_NONFREE=y
BR2_PACKAGE_FFMPEG_FFPLAY=y
BR2_PACKAGE_FFMPEG_FFPROBE=y
BR2_PACKAGE_FFMPEG_POSTPROC=y
BR2_PACKAGE_FLAC=y
BR2_PACKAGE_GSTREAMER1=y
BR2_PACKAGE_GSTREAMER1_CHECK=y
BR2_PACKAGE_GST1_PLUGINS_BASE_PLUGIN_APP=y
BR2_PACKAGE_GST1_PLUGINS_BAYER2RGB_NEON=y
BR2_PACKAGE_GST1_PLUGINS_GOOD=y
BR2_PACKAGE_GST1_LIBAV=y
BR2_PACKAGE_VLC=y
BR2_PACKAGE_TREE=y
BR2_PACKAGE_MMC_UTILS=y
BR2_PACKAGE_LIBPJSIP=y
BR2_PACKAGE_DHCPCD=y
BR2_PACKAGE_FREESWITCH=y
BR2_PACKAGE_OPENSSH=y
BR2_PACKAGE_TCPDUMP=y
BR2_PACKAGE_VSFTPD=y
BR2_PACKAGE_UTIL_LINUX_LIBFDISK=y
BR2_PACKAGE_UTIL_LINUX_HWCLOCK=y
BR2_PACKAGE_UTIL_LINUX_KILL=y
BR2_PACKAGE_UTIL_LINUX_LSFD=y
BR2_PACKAGE_UTIL_LINUX_MORE=y
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_SIZE="256M"
BR2_TARGET_ROOTFS_TAR_GZIP=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
```
注意这里打开了 `BR2_PACKAGE_HOST_ENVIRONMENT_SETUP` ,有了这个配置会生成`output/host/environment-setup`脚本,执行`source`命令即可当前开发环境设置为交叉编译,跨平台的`cmake`也搞好了,非常的方便。
配置并编译,等待编译成功
```bash
make myirdeconfig
make
# 将当前的环境设置为交叉编译
source output/host/environment-setup
# 测试一下变量
$ echo $CC
aarch64-buildroot-linux-gnu-gcc
```
可以大概看一下`environment-setup`脚本为我们做的事情。导出了很多变量,还有`configure`和`cmake`别名
编译`cmake`工程时,交叉编译配置都省了
```bash
cat
- 2024-08-13
-
发表了主题帖:
【米尔 NXP i.MX93 开发板评测】cmake交叉编译
本帖最后由 小麦克 于 2024-8-13 15:48 编辑
# cmake交叉编译模版工程
本文通过一个简单的示例,演示如何在 CMake 工程中添加交叉编译的配置,实现编译不同硬件平台的可执行文件。
## CMake概述
CMake 是一个项目构建工具,并且是跨平台的。关于项目构建我们所熟知的还有Makefile(通过 make 命令进行项目的构建),大多是IDE软件都集成了make,比如:VS 的 nmake、linux 下的 GNU make、Qt 的 qmake等,如果自己动手写 makefile,会发现,makefile 通常依赖于当前的编译平台,而且编写 makefile 的工作量比较大,解决依赖关系时也容易出错。
而 CMake 恰好能解决上述问题, 其允许开发者指定整个工程的编译流程,在根据编译平台,自动生成本地化的Makefile和工程文件,最后用户只需make编译即可,所以可以把CMake看成一款自动生成 Makefile的工具,其编译流程如下图:
## 示例
### 目录结构
```bahs
$ tree
.
├── arm_linux_setup.cmake
├── CMakeLists.txt
└── hello.c
1 directory, 3 files
```
arm_linux_setup.cmake
这里的`aarch64-buildroot-linux-gnu-gcc`是通过`buildroot`生成的交叉编译器,其他编译器也可以用,名称有差异,记得替换
```cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(target_arch aarch64-linux-gnu)
set(CMAKE_C_COMPILER aarch64-buildroot-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-buildroot-linux-gnu-g++)
set(CMAKE_LIBRARY_ARCHITECTURE ${target_arch} CACHE STRING "" FORCE)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
```
CMakeLists.txt
```cmake
cmake_minimum_required(VERSION 3.1.3)
project(hello)
set( HELLO_SRCS hello.c)
add_executable(${PROJECT_NAME} ${HELLO_SRCS})
```
hello.c
```c
#include
int main(void)
{
printf("Hello, CMake\n");
return 0;
}
```
### 编译
在项目根目录下面新建一个`build`,放cmake生成的中间文件
```bash
mkdir build
cd build
cmake ..
# 编译成主机平台
make
# 编译成功生成x86-64平台hello
$ file hello
hello: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d55b52333ab9da5f0b106b3af84a8d4ef78f9a02, for GNU/Linux 3.2.0, not stripped
```
交叉编译
```bash
# 交叉编译
rm -rf *
cmake -DCMAKE_TOOLCHAIN_FILE=../arm_linux_setup.cmake ..
make
# 交叉编译成功生成aarch64平台hello
$ file hello
hello: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 6.1.0, not stripped
```
上传开发板执行试试~
-
回复了主题帖:
【米尔 NXP i.MX93 开发板评测】USB下载工具-UUU
-
发表了主题帖:
【米尔 NXP i.MX93 开发板评测】USB下载工具-UUU
# USB下载工具-UUU
由前面的调试可知,通过SD更新镜像比较麻烦,需要SD卡并且操作的步骤也比较多。这篇来试一下NXP的[uuu](https://github.com/nxp-imx/mfgtools.git)下载工具。
`uuu`通过USB接口可以下载`uboot`,`Image`,`dtb`,`rootfs`等等,还可以执行自定义的指令。通过自定义的脚本,非常灵活。有了这个工具,后续生产及更新都非常方便。由于使用了USB高速模式,下载速度也非常快。
在GitHub的发布页面有一个uuu.pdf文档,想了解`uuu`工作原理的可以去看看。
这个工具支持`linux`,`windows`,`macos`
## uuu配置
先来看下文件构成:
1. boot目录放了imx-uboot文件`flash.bin`(myir编译出来的文件名为`imx-boot-myd-lmx9x-sd.bin-flash_singleboot`),linux内核 `Image`,设备树`myir-imx93-11x11.dtb`
2. filesystem放打包后的文件系统,这里放的是buildroot生产的`rootfs.tar`
3. modules 放打包好的内核模块 `modules.tar.gz`
4. `fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.zst.u-boot` 是NXP提供的RAMDISK,通过uboot启动后和uuu进行交互操作
5. `imx93-emmc.uuu` 下载控制脚本文件,根据需要修改。
6. `uuu` `uuu.exe` linux和windows的可执行文件,两个系统都可以下载,方便!
`imx93-emmc.uuu` 脚本
```bash
uuu_version 1.5.163
# Please Replace below items with actually file names
# @_flash.bin | boot loader, flash.bin
# @_Image | kernel image, arm64 is Image, arm32 it is zImage, here is Image
# @_board.dtb | board dtb file, here is imx93-11x11-evk.dtb
# @_initramfs.cpio.gz.uboot | mfgtool init ramfs, here is fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.zst.u-boot
# @_rootfs.tar.zst | rootfs, here is imx-image-multimedia-imx93evk.tar.zst
# @_uTee.tar | optee image, put dummy _uTee.tar file here if platform is not MX6/MX7*
# This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ
SDP: boot -f boot/flash.bin
# This command will be run when ROM support stream mode
# i.MX8QXP, i.MX8QM
SDPS: boot -f boot/flash.bin
# SDPU will be deprecated. please use SDPV instead of SDPU
# {
SDPU: delay 1000
SDPU: write -f boot/flash.bin -offset 0x57c00
SDPU: jump
# }
# These commands will be run when use SPL and will be skipped if no spl
# if (SPL support SDPV)
# {
SDPV: delay 1000
SDPV: write -f boot/flash.bin -skipspl
SDPV: jump
# }
# use uboot burn bootloader to eMMC
# becaue difference chip, offset is difference
# you can use kernel to do that for specific boards
FB: ucmd setenv fastboot_dev mmc
FB: ucmd setenv mmcdev ${emmc_dev}
FB: flash bootloader boot/flash.bin
FB: ucmd if env exists emmc_ack; then ; else setenv emmc_ack 0; fi;
FB: ucmd setenv emmc_cmd mmc partconf ${emmc_dev} ${emmc_ack} 1 0
FB: ucmd if test "${emmc_skip_fb}" != "yes"; then run emmc_cmd; fi
FB: ucmd setenv emmc_cmd mmc bootbus ${emmc_dev} 2 0 1;
FB: ucmd if test "${emmc_skip_fb}" != "yes"; then run emmc_cmd; fi
FB: ucmd setenv fastboot_buffer ${loadaddr}
FB: download -f boot/Image
FB: ucmd setenv fastboot_buffer ${fdt_addr}
FB: download -f boot/myir-imx93-11x11.dtb
FB: ucmd setenv fastboot_buffer ${initrd_addr}
FB: download -f fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.zst.u-boot
#FB: ucmd setenv bootargs console=${console},${baudrate} earlycon=${earlycon},${baudrate}
FB: acmd ${kboot} ${loadaddr} ${initrd_addr} ${fdt_addr}
# get mmc dev number from kernel command line
# Wait for emmc
FBK: ucmd while [ ! -e /dev/mmcblk*boot0 ]; do sleep 1; echo "wait for /dev/mmcblk*boot* appear"; done;
# serach emmc device number, if your platform have more than two emmc chip, please echo dev number >/tmp/mmcdev
FBK: ucmd dev=`ls /dev/mmcblk*boot*`; dev=($dev); dev=${dev[0]}; dev=${dev#/dev/mmcblk}; dev=${dev%boot*}; echo $dev > /tmp/mmcdev;
# dd to clear the possible MBR
FBK: ucmd mmc=`cat /tmp/mmcdev`; dd if=/dev/zero of=/dev/mmcblk${mmc} bs=512 count=1
# create partition
FBK: ucmd mmc=`cat /tmp/mmcdev`; PARTSTR=$'8M,120M,0c\n,5120M,83\n,128M,83\n5416M,,83\n'; echo "$PARTSTR" | sfdisk --force /dev/mmcblk${mmc}
FBK: ucmd sync
# FAT
FBK: ucmd mmc=`cat /tmp/mmcdev`; while [ ! -e /dev/mmcblk${mmc}p1 ]; do sleep 1; done
FBK: ucmd mmc=`cat /tmp/mmcdev`; mkfs.vfat /dev/mmcblk${mmc}p1
FBK: ucmd mmc=`cat /tmp/mmcdev`; mkdir -p /mnt/fat
FBK: ucmd mmc=`cat /tmp/mmcdev`; mount -t vfat /dev/mmcblk${mmc}p1 /mnt/fat
FBK: ucp boot/Image t:/mnt/fat
FBK: ucp boot/myir-imx93-11x11.dtb t:/mnt/fat
FBK: ucp boot/myir-imx93-11x11-root.dtb t:/mnt/fat
FBK: ucmd sync
FBK: ucmd umount /mnt/fat
# ROOTFS
FBK: ucmd mmc=`cat /tmp/mmcdev`; mkfs.ext4 -F /dev/mmcblk${mmc}p2
FBK: ucmd mkdir -p /mnt/ext4
FBK: ucmd mmc=`cat /tmp/mmcdev`; mount /dev/mmcblk${mmc}p2 /mnt/ext4
FBK: acmd export EXTRACT_UNSAFE_SYMLINKS=1; tar --warning=no-timestamp -xz -C /mnt/ext4
FBK: ucp filesystem/rootfs.tar.gz t:-
FBK: ucmd sync
# PARAMETER
FBK: ucmd mmc=`cat /tmp/mmcdev`; mkfs.ext4 -F /dev/mmcblk${mmc}p3
FBK: ucmd sync
# APPFS
FBK: ucmd mmc=`cat /tmp/mmcdev`; mkfs.ext4 -F /dev/mmcblk${mmc}p4
FBK: ucmd sync
# modules
FBK: ucmd mkdir -p /mnt/ext4/lib/modules
FBK: acmd tar --warning=no-timestamp -x -C /mnt/ext4/lib/modules
FBK: ucp modules/modules.tar.gz t:-
FBK: ucmd sync
FBK: ucmd umount /mnt/ext4
FBK: DONE
```
## 下载
设置拨码开关为USB下载,执行指令,重新上电启动,即开始下载。
```bash
# Windows环境
.\uuu.exe .\imx93-emmc.uuu
# Linux环境
./uuu ./imx93-emmc.uuu
```
下载完成,设置eMMC启动,重新上电检查。
## WLAN驱动问题
上电启动后,自带的WLAN驱动好像有点问题。但是不影响使用,有时间再回头看这个问题。输入root登录系统。
- 2024-08-11
-
回复了主题帖:
【米尔 NXP i.MX93 开发板评测】IMX93视频播放性能测试
lugl4313820 发表于 2024-8-10 22:56
大佬,是不是太激动了,好象是多了一位数,或者多了一个零。
没有错,Linux和windows系统CPU占用率表示方式不一样:
Linux系统根据系统有多少个CPU核心来确定总使用率,iMX.93有两个核心,最大CPU使用率为200%
-
发表了主题帖:
【米尔 NXP i.MX93 开发板评测】RAMDISK实践
# RAMDISK实践
> 编译开发板自带的内核源码,制作一个`RAMDISK`,放到SD卡中加载测试内核;由于UBOOT功能有限,可以使用ramdisk添加更高级的维护功能,比如设备升级与工厂生产刷机。后面我们实现升级功能时会用到。
## 制作RAMDISK
使用`busybox`生成一个精简`initramdisk`
### 内核编译
参考米尔文档 《MYD-LMX9X_Linux软件开发指南.pdf》
```bash
# 配置交叉编译器
source /opt/fsl-imx-xwayland/6.1-mickledore/environment-setuparmv8a-poky-linux
cd MYD-LMX9X-Linux-L6.1.55-V1.0.0
./build-linux-zh.sh
# 选择编译线程数,等待一会儿编译成功后会生成output目录
cd output
output$ ll -h
总计 65M
drwxrwxr-x 2 bruce bruce 4.0K Aug 11 06:42 ./
drwxrwxr-x 4 bruce bruce 4.0K Aug 11 06:31 ../
-rw-rw-r-- 1 bruce bruce 34M Aug 11 06:42 Image
-rw-rw-r-- 1 bruce bruce 31M Aug 11 06:42 modules.tar.gz
-rw-rw-r-- 1 bruce bruce 45K Aug 11 06:42 myir-imx93-11x11.dtb
-rw-rw-r-- 1 bruce bruce 47K Aug 11 06:42 myir-imx93-11x11-lvds-10-1.dtb
-rw-rw-r-- 1 bruce bruce 46K Aug 11 06:42 myir-imx93-11x11-lvds.dtb
-rw-rw-r-- 1 bruce bruce 46K Aug 11 06:42 myir-imx93-11x11-RGB.dtb
-rw-rw-r-- 1 bruce bruce 45K Aug 11 06:42 myir-imx93-11x11-root.dtb
```
重新配置内核,支持`RAM block device`
```bash
# 进入内核源代码目录
cd myir-imx-linux
# 配置
make menuconfig
# 将RAM block驱动编译进内核
Device Drivers --->
Block devices --->
RAM block device support
(1) Default number of RAM disks
(65536) Default RAM disk size (kbytes)
make
# 生成我们需要的 arch/arm64/boot/Image
```
**注意:**这里不能使用`./build-linux-zh.sh`,脚本编译时会再次使用DEFCONFIG生成配置文件`.config`,会将我们设置好的配置清除掉。如果想用,可以重新拷贝一份deconfig,配置好`RAM DISK`,然后替代这里的 `DEFCONFIG="imx_v8_defconfig"`
```shell
DEFCONFIG="imx_v8_defconfig"
compile_linux(){
echo "开始配置内核"
cd ${LOACL_PATH}/${LINUX_NAME}
make ${DEFCONFIG} > /dev/null 2>&1
echo "开始编译内核"
LDFLAGS="" CC="$CC" make -j ${THREAD_NUM} > /dev/null 2>&1 &
make_pid=$!
bar_test ${make_pid}
echo "编译完成"
}
```
### update.sh
编写刷机脚本 `update.sh`,需要添加执行权限
```bash
#!/bin/sh
# eMMC device node
node=/dev/mmcblk0
# size in MB
BOOT_ROM_SIZE=8
ROOT_FS_SIZE=5120
PARAM_FS_SIZE=128
APP_FS_START=5416
mount -o remount,rw /
# wait for the SD/MMC device node ready
while [ ! -e ${node} ]
do
sleep 1
echo "wait for ${node} appear"
done
# TODO: check eMMC partitions
EMMC_PARTITIONS=("/dev/mmcblk0p1" "/dev/mmcblk0p2" "/dev/mmcblk0p3")
for PARTITION in "${EMMC_PARTITIONS[@]}"; do
if [ -e "$PARTITION" ]; then
echo "$PARTITION exist."
else
echo "$PARTITION not exist."
fi
done
# call sfdisk to create partition table
# destroy the partition table
dd if=/dev/zero of=${node} bs=1024 count=1
# p1 8M ~ 128M FAT(120MB)
# p2 128M ~ 5248M ROOTFS(5GB)
# p3 5248M ~ 5376 PARAM(128MB)
# p4 5376 ~ END APP(left)
echo ">>> sfdisk ${node}"
sfdisk --force ${node} /sys/block/mmcblk0boot0/force_ro
dd if=/mnt/flash/flash.bin of=/dev/mmcblk0boot0 conv=fsync
echo 1 > /sys/block/mmcblk0boot0/force_ro
mmc bootpart enable 1 1 /dev/mmcblk0
fi
while [ ! -e /dev/mmcblk0p1 ]
do
sleep 1
echo "waiting... /dev/mmcblk0p1"
done
# burn dtb and Image
if [ -f /mnt/flash/Image ]
then
echo ">>> copy dtb and Image -> /dev/mmcblk0p1"
mkfs.vfat /dev/mmcblk0p1
mkdir -p /tmp/kernel
mount -t vfat /dev/mmcblk0p1 /tmp/kernel
cp /mnt/flash/Image /tmp/kernel
cp /mnt/flash/imx93-11x11-atk.dtb /tmp/kernel
cp /mnt/flash/ramdisk.img.gz /tmp/kernel
sync
umount /tmp/kernel
fi
# burn rootfs
if [ -f /mnt/flash/rootfs.tar ]
then
echo ">>> burn rootfs -> /dev/mmcblk0p2"
# mkfs.ext4 -F -E nodiscard /dev/mmcblk0p2
mkfs.ext4 -F /dev/mmcblk0p2
mkdir -p /tmp/rootfs
mount -t ext4 /dev/mmcblk0p2 /tmp/rootfs
tar -xf /mnt/flash/rootfs.tar -C /tmp/rootfs
sync
umount /tmp/rootfs
fi
# parameter: 128MB
mkfs.ext4 -F -E nodiscard /dev/mmcblk0p3
# APP: using left space
mkfs.ext4 -F -E nodiscard /dev/mmcblk0p4
sync
sleep 1
echo ">>>>>>>>>>> DONE
- 2024-08-09
-
发表了主题帖:
【米尔 NXP i.MX93 开发板评测】IMX93视频播放性能测试
本帖最后由 小麦克 于 2024-8-9 18:04 编辑
# IMX93视频播放性能测试
iMX.93带两个64位Cortex-A55 CPU,主频1.7GHz,由于芯片内部没有H.264硬件编解码器,播放视频时必须依靠CPU进行软解,而H.264编解码非常耗资源。
Linux系统根据系统有多少个CPU核心来确定总使用率,iMX.93有两个核心,最大CPU使用率为200%
源视频为网上下载的4K高清视频,通过`ffmpeg`工具得到几个测试分辨率
```bash
./ffmpeg.exe -i 7121088-uhd_2160_3840_25fps.mp4 -vf scale=1080:1920 video2_1080.mp4
./ffmpeg.exe -i 7121088-uhd_2160_3840_25fps.mp4 -vf scale=720:1280 video2_720.mp4
./ffmpeg.exe -i 7121088-uhd_2160_3840_25fps.mp4 -vf scale=540:960 video2_540.mp4
```
将视频上传到开发板
播放测试
```bash
gst-play --loop video_1920.mp4
```
测试视频信息
播放1920X1080 CPU占用率
测试结果如下:
1)1920X1080分辨率视频CPU占用率160%左右
2)1280X720p分辨率适配CPU占用率74%左右
3)960X540分辨率CPU占用率45%左右
由以上分析可知,实际应用中,考虑双向视频对讲是消耗资源最高的使用场景,使用不大于720p分辨率时应该可以满足项目需求。
- 2024-08-05
-
回复了主题帖:
【米尔 NXP i.MX93 开发板评测】U-BOOT SD卡加载镜像问题
刚才使用正点原子的开发板测试了一下,测试了多遍,SD卡读取正常。使用同样的SD和程序。而且发现正点原子的SD卡读取速度明显更快。
这个问题可能需要找米尔的厂家支持一下。
- 2024-08-04
-
回复了主题帖:
【米尔 NXP i.MX93 开发板评测】U-BOOT SD卡加载镜像问题
有谁遇到过这种情况的?