Swupdate的aarch64交叉编译

上一篇博客我们简单测试了swupdate的基础功能,当时使用的是buildroot进行编译的,依赖关心有buildroot进行处理了。今天我自己手动编译一些swupdate。下面记录了编译swupdate的过程。
基本过程就是下载源码,配置选项,然后进行编译。
swupdate是在github上下载的,下载地址为:

https://codeload.github.com/sbabic/swupdate/tar.gz/refs/tags/2023.05

一、依赖

libconfig是必须支持的库,下载地址如下:

http://hyperrealm.github.io/libconfig/dist/libconfig-1.7.3.tar.gz

如果选中了lua功能,需要下载和编译lua包,连接如下:

https://www.lua.org/ftp/lua-5.4.6.tar.gz

如果选中了delta功能,就拥有对delta升级能力(二进制差分)。librsync下载路径如下:

https://github.com/librsync/librsync/releases
https://codeload.github.com/zchunk/zchunk/tar.gz/refs/tags/1.3.1

如果选中了archive功能,就可以对归档文件的处理,就依赖libarchive。 libarchive库下载路径如下:

https://github.com/libarchive/libarchive/releases/tag/v3.6.2

如果选中了diskpart功能,就可以对disk分区进行操作。就依赖util-linux/misc-utils库下载地址

https://github.com/util-linux/util-linux/blob/master/misc-utils/blkid.c

如果选中了ext234功能,就可以对disk分区进行格式化操作。就依赖libext2fs库,下载地址

https://sourceforge.net/projects/e2fsprogs/

我们的设备使用的emmc所以不需要支持mtd,把mtd功能取消掉,就不用处理mtd的依赖了。如果你需要,那么你自行处理。

二、编译依赖库

2.1 lua库

lua库就是比较简单,直接使用MakefIle进行构建。那么我们就直接修改Makefile进行交叉编译。我这里使用了quilt作为patch工具,来记录修改,其实用git更好,我就是试一下quilt。下面修改记录,主要是进行交叉编译和lua.pc文件生成功能修改。

 Index: lua-5.4.6/Makefile
===================================================================
--- lua-5.4.6.orig/Makefile
+++ lua-5.4.6/Makefile
@@ -10,13 +10,14 @@ PLAT= guess
 # so take care if INSTALL_TOP is not an absolute path. See the local target.
 # You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with
 # LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h.
-INSTALL_TOP= /usr/local
+INSTALL_TOP= $(AARCH64_SYSROOT)/usr/local
 INSTALL_BIN= $(INSTALL_TOP)/bin
 INSTALL_INC= $(INSTALL_TOP)/include
 INSTALL_LIB= $(INSTALL_TOP)/lib
 INSTALL_MAN= $(INSTALL_TOP)/man/man1
 INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
 INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V
+INSTALL_PKG= $(INSTALL_TOP)/lib/pkgconfig
 
 # How to install. If your install program does not support "-p", then
 # you may have to run ranlib on the installed liblua.a.
@@ -54,8 +55,8 @@ all:	$(PLAT)
 $(PLATS) help test clean:
 	@cd src && $(MAKE) $@
 
-install: dummy
-	cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)
+install: dummy pc
+	cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) $(INSTALL_PKG)
 	cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
 	cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
 	cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
@@ -99,6 +100,20 @@ pc:
 	@echo "prefix=$(INSTALL_TOP)"
 	@echo "libdir=$(INSTALL_LIB)"
 	@echo "includedir=$(INSTALL_INC)"
+	@echo "prefix=$(INSTALL_TOP)"     > $(INSTALL_PKG)/lua.pc
+	@echo -n "libdir=$$"   >> $(INSTALL_PKG)/lua.pc
+	@echo "{prefix}/lib"   >> $(INSTALL_PKG)/lua.pc
+	@echo -n "includedir=$$" >> $(INSTALL_PKG)/lua.pc
+	@echo "{prefix}/include" >> $(INSTALL_PKG)/lua.pc
+	@echo ""                          >> $(INSTALL_PKG)/lua.pc
+	@echo "Name: lua"                 >> $(INSTALL_PKG)/lua.pc
+	@echo "Description: lua library." >> $(INSTALL_PKG)/lua.pc
+	@echo "Version: $R"                >> $(INSTALL_PKG)/lua.pc
+	@echo -n "Libs: -L$$"  >> $(INSTALL_PKG)/lua.pc
+	@echo "{libdir} -llua"  >> $(INSTALL_PKG)/lua.pc
+	@echo -n "Cflags: -I$$"  >> $(INSTALL_PKG)/lua.pc
+	@echo "{includedir}"  >> $(INSTALL_PKG)/lua.pc
+
 
 # Targets that do not create files (not all makes understand .PHONY).
 .PHONY: all $(PLATS) help test clean install uninstall local dummy echo pc
Index: lua-5.4.6/src/Makefile
===================================================================
--- lua-5.4.6.orig/src/Makefile
+++ lua-5.4.6/src/Makefile
@@ -6,13 +6,19 @@
 # Your platform. See PLATS for possible values.
 PLAT= guess
 
-CC= gcc -std=gnu99
+TOOLCHAIN-PREFIX= aarch64-linux-gnu-
+
+CC= $(TOOLCHAIN-PREFIX)gcc -std=gnu99
 CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_3 $(SYSCFLAGS) $(MYCFLAGS)
 LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
 LIBS= -lm $(SYSLIBS) $(MYLIBS)
 
-AR= ar rcu
-RANLIB= ranlib
+CFLAGS+= --sysroot=$(AARCH64_SYSROOT)
+LDFLAGS+= --sysroot=$(AARCH64_SYSROOT)
+
+
+AR= $(TOOLCHAIN-PREFIX)ar rcu
+RANLIB= $(TOOLCHAIN-PREFIX)ranlib
 RM= rm -f
 UNAME= uname

2.2 libconfig库

常规的configure编译,3步走。我这里是将系统的CC环境变量修改了的,如下:

./configure --host=aarch64  --with-sysroot=$AARCH64_SYSROOT --prefix=$AARCH64_SYSROOT/usr
make
make install

环境变量
CXX=aarch64-linux-gnu-g++
LD=aarch64-linux-gnu-ld
AARCH64_SYSROOT=/home/yp/workspace/toolchain/staging-8.3
AR=aarch64-linux-gnu-ar
NM=aarch64-linux-gnu-nm
CC=aarch64-linux-gnu-gcc

2.3 zchunk库

使用meson进行编译,交叉编译时,一定要把环境变量中的CC,AR,NM等变量unset掉。我的编译环境变量中CC=aarch64-linux-gnu-gcc时,meson setup --cross-file crosscompile.txt build-aarch64一直报错。报错如下:

zchunk-1.3.1$ meson setup --cross-file crosscompile.txt  build-aarch64
The Meson build system
Version: 0.53.2
Source dir: /home/yp/workspace/packages/zchunk-1.3.1
Build dir: /home/yp/workspace/packages/zchunk-1.3.1/build-aarch64
Build type: cross build
Project name: zck
Project version: 1.3.1
/lib/ld-linux-aarch64.so.1: No such file or directory

meson.build:1:0: ERROR: Executables created by c compiler aarch64-linux-gnu-gcc are not runnable.

A full log can be found at /home/yp/workspace/packages/zchunk-1.3.1/build-aarch64/meson-logs/meson-log.txt

当我把编译的环境变量CC,AR,NM等unset后,执行setup恢复正常。 crosscompile.txt内容如下:

[binaries]
c = 'aarch64-linux-gnu-gcc'
cpp = 'aarch64-linux-gnu-g++'
ar = 'aarch64-linux-gnu-ar'
strip = 'aarch64-linux-gnu-strip'

[host_machine]
system = 'linux'
cpu_family = 'aarch64'
cpu = 'aarch64'
endian = 'little'

[properties]
sys_root = '/home/yp/workspace/toolchain/staging-8.3'

[build_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

完整的编译流程如下:

unset CC AR CXX NM LD LDFLAGS PKG_CONFIG_PATH

配置交叉编译
meson setup --cross-file crosscompile.txt  --prefix=/your/aarch64_sysroot/usr/local build-aarch64

如果你有什么东西漏配置了,可以编译路径下执行
meson --reconfigure --prefix=/your/aarch64_sysroot/usr/local

执行编译
ninja

执行安装
ninja install

2.4 librsync库编译

是cmake进行编译,需要注意的是,我的编译中环境变量CC,AR,NM都是修改过的,已经是交叉工具链。编译脚本如下。

#!/bin/bash
rm build -rf

mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=$AARCH64_SYSROOT/usr/local ..

if [ $? -ne 0 ];then
	echo "cmake .. error"
	exit 1
fi

make

if [ $? -ne 0 ];then
	echo "make  error"
	exit 1
fi

make install

if [ $? -ne 0 ];then
	echo "make install error"
	exit 1
fi

echo "all is ok"

env命令的打印, 编译的环境变量如下:

CXX=aarch64-linux-gnu-g++
LD=aarch64-linux-gnu-ld
AARCH64_SYSROOT=/home/yp/workspace/toolchain/staging-8.3
AR=aarch64-linux-gnu-ar
NM=aarch64-linux-gnu-nm
CC=aarch64-linux-gnu-gcc

2.5 编译zlib

之前已经移植了,今天就不在移植了。

2.6 编译archive

libarchive 是一个可以创建和读取多种不同流式归档格式的程序库,包含了最流行的 tar 格式变体、一些 cpio 格式,以及所有的 BSD 和 GNU ar 变体。bsdtar 是一个使用 libarchive 的 tar 实现。
编译的环境变量如2.4。编译脚本如下:

#!/bin/bash
rm cbuild -rf

mkdir cbuild
cd cbuild

export PKG_CONFIG_PATH=$AARCH64_SYSROOT/usr/lib/pkgconfig:$AARCH64_SYSROOT/usr/local/lib/pkgconfig
export CFLAGS="--sysroot=$AARCH64_SYSROOT -I$AARCH64_SYSROOT/include -I$AARCH64_SYSROOT/usr/local/include"
export LDFLAGS="--sysroot=$AARCH64_SYSROOT -L$AARCH64_SYSROOT/usr/loacl/lib"

cmake -DCMAKE_INSTALL_PREFIX=$AARCH64_SYSROOT/usr/local ..

if [ $? -ne 0 ];then
	echo "cmake .. error"
	unset PKG_CONFIG_PATH CFLAGS LDFLAGS 
	exit 1
fi

make

if [ $? -ne 0 ];then
	echo "make  error"
	unset PKG_CONFIG_PATH CFLAGS LDFLAGS 
	exit 1
fi

make install

if [ $? -ne 0 ];then
	echo "make install error"
	unset PKG_CONFIG_PATH CFLAGS LDFLAGS 
	exit 1
fi

unset PKG_CONFIG_PATH CFLAGS LDFLAGS 
echo "all is ok"

2.6 编译 blkid fdisk uuid

blkid - command-line utility to locate/print block device attributes.

又来了一个meson编译的东西,我们模仿上面的编译流程。完整的编译流程如下:

unset CC AR CXX NM LD LDFLAGS PKG_CONFIG_PATH

配置交叉编译
meson setup --cross-file crosscompile.txt  --prefix=/your/aarch64_sysroot/usr/local build-aarch64 -Dbuild-libmount=disabled

如果你有什么东西漏配置了,可以编译路径下执行
meson --reconfigure --prefix=/your/aarch64_sysroot/usr/local

执行编译
ninja

执行安装
ninja install

编译中找不到Python.h头文件。我已经不想再去搞Python了,我们直接把对应的工具disabled掉-Dbuild-libmount=disabled,-Dbuild-plymouth-support=disabled。这些定义我是在meson.build文件中看到的。但是disbale掉还是解决不了问题。

meson --reconfigure --prefix=/your/aarch64_sysroot/usr/local -Dbuild-libmount=disabled -Dbuild-plymouth-support=disabled

配置完后是这种状态
util-linux 2.39

  components
              libblkid: enabled
               libuuid: enabled
              libmount: disabled
          libsmartcols: enabled
              libfdisk: enabled
                 uuidd: enabled
    cryptsetup support: disabled
      plymouth support: disabled

       static programs: 


然而还是没有解决问题,ninja就是要编译libmount中的东西,使用pythone。那我们就单独编译 blkid,fdisk,uuidd,然后再手动安装

ninja blkid
cp ./libblkid/libblkid.so* /home/hy/workspace/toolchain/staging-8.3/usr/local/lib -d
mkdir /home/hy/workspace/toolchain/staging-8.3/usr/local/include/blkid/ -p
cp libblkid/blkid.h /home/hy/workspace/toolchain/staging-8.3/usr/local/include/blkid/
cp ./meson-private/blkid.pc /home/hy/workspace/toolchain/staging-8.3/usr/local/lib/pkgconfig/
 

ninja fdisk
cp ./libfdisk/libfdisk.so* /home/yp/workspace/toolchain/staging-8.3/usr/local/lib -d
mkdir -p /home/yp/workspace/toolchain/staging-8.3/usr/local/include/libfdisk 
cp libfdisk/libfdisk.h /home/yp/workspace/toolchain/staging-8.3/usr/local/include/libfdisk
cp meson-private/fdisk.pc /home/yp/workspace/toolchain/staging-8.3/usr/local/lib/pkgconfig/

ninja uuidd
mkdir -p /home/hy/workspace/toolchain/staging-8.3/usr/local/include/uuid
cp ./libuuid/src/uuidd.h ./libuuid/src/uuid.h ./libuuid/src/uuidP.h /home/hy/workspace/toolchain/staging-8.3/usr/local/include/uuid
cp ./build-aarch64/libuuid/libuuid.so* /home/hy/workspace/toolchain/staging-8.3/usr/local/lib -d
cp ./build-aarch64/meson-private/uuid.pc /home/hy/workspace/toolchain/staging-8.3/usr/local/lib/pkgconfig/

但是编译报错找不到一些符号,我看了半天没有找到解决办法,改天再研究一下,后来发现在/lib/libblkid.a已经有一个旧库了,连接查找库错误了。删除旧的库即可正常编译分区相关功能。

2.7 编译ext2/3/4支持 libext2fs

常规编译三步走,如下:


mkdir build
cd build
build$ ../configure --prefix=$AARCH64_SYSROOT/usr/local --host=aarch64   --with-sysroot=$AARCH64_SYSROOT 
make

install

2.7 编译swupdate

1)设置 SWUpdate Settings → Build Options

设置工具链前缀:aarch64-linux-gnu-

设置交叉编译的sys_root: /your/aarch64_sysroot

设置LD选项:-ldl -lm (后面编译会报错,所以加上这2个库)

选中你需要的功能,然后进行make编译。当报错缺头文件时,大概率是你的库没有安装。这里举例几个错误场景。

  • 场景1,lua的函数找不到,是因为没有连接lua库,查看前面的打印,可以看出来没有找到lua.pc,认为没有lua库。但程序又选中了lua的支持。
报错:
ld: lua_interface.c:(.text.update_table+0x200): undefined reference to `lua_pushstring'

lua.pc内容:
$ cat ~/workspace/toolchain/staging-8.3/usr/local/lib/pkgconfig/lua.pc 
prefix=/home/yp/workspace/toolchain/staging-8.3/usr/local
libdir=${prefix}/lib
includedir=${prefix}/include

Name: lua
Description: lua library.
Version: 5.4.6
Libs: -L${libdir} -llua
Cflags: -I${includedir}


解决办法:
export PKG_CONFIG_PATH=/home/yp/workspace/toolchain/staging-8.3/usr/local/lib/pkgconfig/ 
  • 场景2, 其他符号找不到,缺少库连接,使用make menuconfig去添加链接库即可。我这里添加了-ldl -lm连接库。
liblua.a(loadlib.o): undefined reference to symbol 'dlsym@@GLIBC_2.17'
(.text+0x398): undefined reference to `sin'

  • 场景3,在menuconfig中增加-lcom_err,这个库随e2fsprogs-1.47.0一起编译产生。加了还报找不到com_err,我看了一下我使用的是静态库libcom_err.a,静态库很依赖编译时的路径。于是我手动调整了一下该路径的路径,就编译成功了。
    将-lcom_err 与 -lext2fs放在一个group里面。那我们怎么自动成功呢?虽然ext2fs.pc的中已经写了libext2fs依赖com_err,但是编译脚本任然没有自动将该库连接进去。看来自能手动修改Makefile.flags文件在ext2fs 后面增加com_err。好吧这样就能编译成功了
in function `ext2fs_inode_alloc_stats2':
alloc_stats.c:(.text+0xf8): undefined reference to `com_err'

手动编译成功指令
aarch64-linux-gnu-gcc -Wall -Wshadow -Wwrite-strings -Wundef -Wstrict-prototypes -Wunused -Wunused-parameter -Wunused-function -Wunused-value -Wmissing-prototypes -Wmissing-declarations -Wno-format-security -Wno-format-truncation -Wold-style-definition -finline-limit=0 -fno-builtin-strlen -fomit-frame-pointer -ffunction-sections -fdata-sections -fno-guess-branch-probability -funsigned-char -falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1 -static-libgcc -fno-unwind-tables -fno-asynchronous-unwind-tables -Os --sysroot=/home/hy/workspace/toolchain/staging-8.3 -I/home/hy/workspace/toolchain/staging-8.3/usr/local/include -ldl -lm -lcom_err -Wl,-E -o swupdate_unstripped -Wl,--sort-common -Wl,--sort-section,alignment -Wl,--gc-sections -Wl,--start-group core/built-in.o handlers/built-in.o bootloader/built-in.o suricatta/built-in.o ipc/built-in.o corelib/lib.a mongoose/lib.a parser/lib.a fs/lib.a -Wl,--end-group -Wl,--start-group -lpthread -llua -lcurl -lconfig -larchive -lcrypto -lssl -lz -lzstd -lfdisk -lblkid -lext2fs -luuid -lblkid -lrsync -lzck -lcom_err  -Wl,--end-group

最终编译出来的文件swupdate的依赖库如下,有些库是使用的静态库,如lua,ext2fs库:

swupdate-2023.05$ readelf -d swupdate

Dynamic section at offset 0x78d40 contains 35 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libcurl.so]
 0x0000000000000001 (NEEDED)             Shared library: [libarchive.so.19]
 0x0000000000000001 (NEEDED)             Shared library: [libcrypto.so.1.1]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libzstd.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [librsync.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libzck.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 
libarchive-3.6.2.tar.gz  librsync-2.3.4.tar.gz  swupdate-2023.05.tar.gz  zchunk-1.3.1.tar.gz
libconfig-1.7.3.tar.gz   lua-5.4.6.tar.gz       util-linux-2.39.tar.gz   e2fsprogs-1.47.0.tar.gz

最终我们支持了分区操作,ext文件格式操作,delta,签名,lua等功能的swupdate已经是比较全的了,另外zmq(ipc功能), uboot是没有支持的。
我们测试了一些功能正常,编译这到这里吧!!还是自动构建套件好选中就行,例如openwrt,buildroot等。如果这篇文章帮助到你,请帮忙点赞。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值