编译工程之际,记录一下编译过程,免得后续遗忘,总结下来chip-tool 交叉编译涉及到的知识点:
- 需要了解如何支持交叉编译,基于GN编译框架
- 需要理解应用库如何交叉编译,理解pkg-config的使用
- meson 编译(主要是编译glib 用到)
工具链准备
应该知道,交叉编译用到的编译链接库、包含头文件路径都应该是工具链可以默认可以搜索到的路径。
可以利用下面命令查看
echo 'main(){}' | arm-buildroot-linux-gnueabi-gcc -E -v -
经过试验输出如下:
Using built-in specs.
COLLECT_GCC=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/bin/arm-buildroot-linux-gnueabi-gcc.br_real
Target: arm-buildroot-linux-gnueabi
Configured with: ./configure --prefix=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32 --sysconfdir=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/etc --enable-static --target=arm-buildroot-linux-gnueabi --with-sysroot=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot --enable-__cxa_atexit --with-gnu-ld --disable-libssp --disable-multilib --disable-decimal-float --with-gmp=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32 --with-mpc=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32 --with-mpfr=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32 --with-pkgversion='Buildroot 2019.11.1' --with-bugurl=http://bugs.buildroot.net/ --disable-libquadmath --enable-tls --enable-threads --with-isl=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32 --with-float=soft --with-abi=aapcs-linux --with-cpu=cortex-a9 --with-float=soft --with-mode=arm --enable-languages=c,c++ --with-build-time-tools=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/bin --enable-shared --disable-libgomp
Thread model: posix
gcc version 9.2.0 (Buildroot 2019.11.1)
COLLECT_GCC_OPTIONS='-Os' '-pipe' '-E' '-v' '-mcpu=cortex-a9' '-mfloat-abi=soft' '-mabi=aapcs-linux' '-marm' '-mtls-dialect=gnu' '-march=armv7-a+mp+sec'/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/libexec/gcc/arm-buildroot-linux-gnueabi/9.2.0/cc1 -E -quiet -v -isysroot /opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot - -mcpu=cortex-a9 -mfloat-abi=soft -mabi=aapcs-linux -marm -mtls-dialect=gnu -march=armv7-a+mp+sec -Os
ignoring nonexistent directory "/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot/usr/local/include"
#include "..." search starts here:
#include <...> search starts here:/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/lib/gcc/arm-buildroot-linux-gnueabi/9.2.0/include/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/lib/gcc/arm-buildroot-linux-gnueabi/9.2.0/include-fixed/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/lib/gcc/arm-buildroot-linux-gnueabi/9.2.0/../../../../arm-buildroot-linux-gnueabi/include/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot/usr/include
End of search list.
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "<stdin>"
main(){}
COMPILER_PATH=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/libexec/gcc/arm-buildroot-linux-gnueabi/9.2.0/:/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/libexec/gcc/arm-buildroot-linux-gnueabi/9.2.0/:/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/libexec/gcc/arm-buildroot-linux-gnueabi/:/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/lib/gcc/arm-buildroot-linux-gnueabi/9.2.0/:/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/lib/gcc/arm-buildroot-linux-gnueabi/:/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/lib/gcc/arm-buildroot-linux-gnueabi/9.2.0/../../../../arm-buildroot-linux-gnueabi/bin/
LIBRARY_PATH=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/lib/gcc/arm-buildroot-linux-gnueabi/9.2.0/:/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/lib/gcc/arm-buildroot-linux-gnueabi/9.2.0/../../../../arm-buildroot-linux-gnueabi/lib/:/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot/lib/:/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot/usr/lib/
COLLECT_GCC_OPTIONS='-Os' '-pipe' '-E' '-v' '-mcpu=cortex-a9' '-mfloat-abi=soft' '-mabi=aapcs-linux' '-marm' '-mtls-dialect=gnu' '-march=armv7-a+mp+sec'
通过以上打印,可以看到
#include "..." search starts here:
#include <...> search starts here:
指向了默认头文件的搜索路径,这里貌似看不到链接库路径,(为此后需要设置链接库路径埋下伏笔)
交叉编译脚本
先说下结果,编译用的是32位工具链,使用的编译命令是
./scripts/examples/gn_build_example.sh examples/chip-tool/ out/bcm6756 'target_cpu="arm" target_os="linux"'
脚本里编译大概分俩类,标准编译以及自定义编译,
diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn
index abc61ab2bf..7eb20fbbf6 100644
--- a/build/toolchain/linux/BUILD.gn
+++ b/build/toolchain/linux/BUILD.gn
@@ -49,7 +49,7 @@ gcc_toolchain("linux_x86_clang") {}gcc_toolchain("linux_arm_gcc") {1. _toolprefix = "arm-linux-gnueabihf-"2. _toolprefix = "/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/bin/arm-buildroot-linux-gnueabi-"cc = "${_toolprefix}gcc"cxx = "${_toolprefix}g++"
可以看到,这里直接修改了基于32位平台的工具链,最好的办好是自己增加一个custom 工具链,关于custom工具链支持,后续正式项目采用
交叉编译脚本解读
./scripts/examples/gn_build_example.sh examples/chip-tool/ out/bcm6756 'target_cpu="arm" target_os="linux"'
以connectedhomeip 作为主目录,编译的入口是 ./build/coinfig/BUILDCONFIG.gn,这个是GN编译框架规定的,可以参照最简单的GN编译理解,框架是一样的。
上图原文链接:https://pingzhou.site/notes/gn_101.html
比较清晰的展示目录结构,帮助理解。基本分析了下SDK的编译,因为matter协议可以理解为跨平台的应用,所以编译目录结构以及功能上进行了模块话处理,可以通过import 导入一个文件变量,类似于C语言中的include 函数,而且定义了template,类似于C语言中的函数,可以细化管理整个编译命令。
为了帮助理解编译,可以通过print() 函数打印变量值
依赖库编译
先说一下结论,主要是依赖openssl 和glib库,如果之前编译过glib库就会知道,glib库有自己的依赖,比如zlib库以及libffi库。
准备交叉编译,库安装目录:
/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot/usr/
openssl 交叉编译
1.代码clone 使用的是openssl-1.1.1l.tar.gz
2.解压、编译
./config no-asm shared --prefix=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot/usr --cross-compile-prefix=arm-buildroot-linux-gnueabi-
–prefix 指定了编译安装目录 --cross-compile-prefix 指定工具链信息
3.修改Makefile
去掉m64相关
4.make
5.sudo make install
glib库交叉编译
代码中编译使用glib2.45.1版本的是不行的,会报函数G_SOURCE_FUNC找不到
因为交叉编译的库,都应该来自于自己编译的库文件,所以我搜索了下glib2.45.1源码中是没有该函数定义的,所以找不到,之后下载了glib2.76.0,搜索后发现能找到函数定义,于是重新编译了库,后面就没再报这个错误了。
glib库2.6以上就采用了meson编译,所以需要熟悉一下meson的编译,跑一下简单历程,熟悉下用法,glib2.76.0库,有一个好处是会自己下载依赖库,不用像glib2.45.1 需要手动安装依赖
需要注意的是meson install 安装时可能会报错,提示
Meson build error "ModuleNotFoundError: No module named 'mesonbuild'"
这里是meson安装出问题了,不能用普通用户权限,必须sudo 权限下安装,卸载掉超级用户权限安装meson即可
参考链接:https://askubuntu.com/questions/1225195/meson-build-error-modulenotfounderror-no-module-named-mesonbuild
glib2.76.0编译,在源码目录里新建一个脚本build.sh,执行,会自动编译,亲测可用。最后是手动安装的sudo meson install
#!/bin/bash
set -eDEVEL=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot/usr/if [ -d _build ];then
rm -r _build
fi
mkdir _buildarch='arm-buildroot-linux-gnueabi-'
sys_root='/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot'
#创建交叉编译配置文件cross_file.txt#还可设置c_args等等类似 CFLAGS
echo "[constants]" > cross_file.txt
echo "arch = '${arch}'" >> cross_file.txt
echo "[binaries]" >> cross_file.txt
echo "c = arch + 'gcc'" >> cross_file.txt
echo "cpp = arch + 'g++'" >> cross_file.txt
echo "ar = arch + 'ar'" >> cross_file.txt
echo "ld = arch + 'ld'" >> cross_file.txt
echo "srtip = arch + 'strip'" >> cross_file.txt
echo "sys_root = '${sys_root}'" >> cross_file.txt
echo "pkg_config_libdir = '${sys_root}/usr/lib/pkgconfig'" >> cross_file.txt#编译结果可运行平台的架构
echo "[host_machine]" >> cross_file.txt
echo "system = 'linux'" >> cross_file.txt
echo "cpu_family = 'arm'" >> cross_file.txt
echo "cpu = 'armv7hl'" >> cross_file.txt
echo "endian = 'little'" >> cross_file.txt#类似于configure功能 meson configure 获取到可配置项
echo "[project options]" >> cross_file.txt
echo "prefix = '/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot/usr'" >> cross_file.txt
echo "selinux = 'disabled'" >> cross_file.txt
echo "libelf = 'disabled'" >> cross_file.txt#类似于执行configure
meson setup _build --cross-file cross_file.txt
cd _build
#编译 类似于make
ninja
cd ../
#类似于make install DESTDIR=$DEVEL
DESTDIR=$DEVEL meson install
matter交叉编译
需要设置链接库路径环境变量,新建一个set_env.sh脚本,设置环境
xing@xing-virtual-machine:~/work$ cat set_env.sh
#export PATH=$PATH::/opt/crosstools-aarch64-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/binexport PATH=$PATH:/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/bin
export PKG_CONFIG_PATH=/opt/toolchains/crosstools-arm-gcc-9.2-linux-4.19-glibc-2.30-binutils-2.32/arm-buildroot-linux-gnueabi/sysroot/usr/lib/pkgconfig
这里必须要执行,否则系统会因为找不到合适的链接目录,链接到宿主机,比如x86版本glib库,报一些变量值溢出问题
编译成功
梳理一下过程,设置环境变量,执行上面的set_env.sh,交叉编译所需库,安装好,然后执行一条脚本即可编译成功,源码SDK不需要修改
编译完,竟然有170多MB,使用strip 后,17M。这应用够大的!