Yocto自定义安装步骤问题:归档应用至rootfs的编译优化与剥离异常
Yocto将应用打包为tar.gz并安装到rootfs的问题解决
目标
我希望将应用及其配置文件打包为tar.gz归档文件,并将该归档文件安装到rootfs镜像中,而非直接安装编译后的文件。
背景
我在Yocto中有几个自定义层,应用基于Makefile构建和安装均正常。其中一个应用,我不想直接将编译后的二进制文件及关联文件安装到rootfs,而是要先归档为package.tar.gz再安装到rootfs。
遇到的问题
- 归档内的二进制文件带有调试信息(
-g参数) - 未按预期优化,实际未使用任何自定义
CXXFLAGS - 二进制文件未被剥离(strip)
同时有疑问:是否应该修改层的*.bb文件,重载install或package步骤,而非在应用Makefile中实现归档逻辑?具体该如何操作?
应用Makefile原配置
Program := myApp # We are creating an archive installation. # We create a temporary directory where we # assemble the required files prior to creating the # delivered archive file. prepDir := /tmp/$(Program) RELEASE_OPTIMIZATION = -Os DEBUG_OPTIMIZATION = -g INCLUDE_DIRS = \ ./\ ../Logger/source STATIC_LIBS = \ ../Logger/source/liblogger.a LDFLAGS += -pthread LDPATH += -L./ LIBS += -lssl -lcrypto all: $(Program) INC = $(foreach dir, $(INCLUDE_DIRS),-I$(dir)) STATIC_LINK = $(foreach lib, $(STATIC_LIBS),$(lib)) OPT = $(RELEASE_OPTIMIZATION) COMMON_FLAGS = -std=c++11 -Wall -Wextra -Werror -pedantic $(OPT) $(INC) override CXXFLAGS += $(COMMON_FLAGS) $(Program): main.o liblogger.a $(CXX) $(LDFLAGS) main.o $(STATIC_LINK) -o $(Program) $(LDPATH) $(LIBS) # Main main.o: main.cpp $(CXX) $(CXXFLAGS) -c main.cpp # Logger Library liblogger.a: $(MAKE) -C ../Logger/source $(PASS_DEBUG) install: $(Program) install -d $(prepDir)/usr/bin install -d $(prepDir)/etc/myApp/conf install -m 555 $(Program) $(prepDir)/usr/bin/ install -m 555 ../conf/myApp.conf $(prepDir)/etc/myApp/conf/ install -d $(DESTDIR)$(PREFIX)/home/root tar -czf $(DESTDIR)$(PREFIX)/home/root/$(Program).tar.gz -C $(prepDir) . rm -rf $(prepDir) # remove object files and executable when user executes "make clean" .PHONY: clean debug setdebugflag PASS_DEBUG = setdebugflag: $(eval OPT = $(DEBUG_OPTIMIZATION)) $(eval PASS_DEBUG = debug) debug: setdebugflag $(Program) clean: rm -f *.o $(Program) $(MAKE) -C ../Logger/source clean
层配方文件(*.bb)原配置
SUMMARY = "My Application Software" DESCRIPTION = "Device Software for My Products" LICENSE_PATH += "${LAYERDIR}/ec_licenses" LICENSE = "ECNF-1.0" LIC_FILES_CHKSUM = "file://ECNF-1.0;md5=80812384516565fef4dff4e7fdf7d55c" DEPENDS = "openssl" SRC_URI = "gitsm://git@git.mysite.com:/projects/myapp.git;protocol=ssh;branch=master" SRCREV_default = "ef0fbe4561238416e4b423a19694b79357c69b95" S = "${WORKDIR}/git/source" FILES_${PN} += "/home/root/myApp.tar.gz" do_install() { oe_runmake install PREFIX=${D} }
验证信息
- 提取rootfs中的归档文件检查后,确认其他层应用二进制已被剥离,但该归档内的文件仍带调试符号
- 尝试添加
inherit pkgconfig无效果 - 通过以下命令验证归档内二进制未被剥离:
file usr/bin/myApp objdump -x usr/bin/myApp | grep debug readelf -wl /usr/bin/myApp
解决方案
核心思路
将归档逻辑从Makefile移到BitBake配方中,让Yocto原生的编译优化、符号剥离机制正常生效。Makefile仅负责常规的编译和临时目录安装,归档操作由BitBake的do_install阶段完成。
步骤1:修改应用Makefile,移除归档逻辑
恢复标准的install流程,将文件安装到DESTDIR指定的临时路径,不要自行做tar归档:
Program := myApp RELEASE_OPTIMIZATION = -Os DEBUG_OPTIMIZATION = -g INCLUDE_DIRS = \ ./\ ../Logger/source STATIC_LIBS = \ ../Logger/source/liblogger.a LDFLAGS += -pthread LDPATH += -L./ LIBS += -lssl -lcrypto all: $(Program) INC = $(foreach dir, $(INCLUDE_DIRS),-I$(dir)) STATIC_LINK = $(foreach lib, $(STATIC_LIBS),$(lib)) OPT = $(RELEASE_OPTIMIZATION) COMMON_FLAGS = -std=c++11 -Wall -Wextra -Werror -pedantic $(OPT) $(INC) # 不要用override,避免覆盖Yocto传入的系统级CXXFLAGS CXXFLAGS += $(COMMON_FLAGS) $(Program): main.o liblogger.a $(CXX) $(LDFLAGS) main.o $(STATIC_LINK) -o $(Program) $(LDPATH) $(LIBS) main.o: main.cpp $(CXX) $(CXXFLAGS) -c main.cpp liblogger.a: $(MAKE) -C ../Logger/source $(PASS_DEBUG) # 标准install目标,安装到DESTDIR路径 install: $(Program) install -d $(DESTDIR)/usr/bin install -d $(DESTDIR)/etc/myApp/conf install -m 555 $(Program) $(DESTDIR)/usr/bin/ install -m 555 ../conf/myApp.conf $(DESTDIR)/etc/myApp/conf/ .PHONY: clean debug setdebugflag PASS_DEBUG = setdebugflag: $(eval OPT = $(DEBUG_OPTIMIZATION)) $(eval PASS_DEBUG = debug) debug: setdebugflag $(Program) clean: rm -f *.o $(Program) $(MAKE) -C ../Logger/source clean
步骤2:修改BitBake配方,实现归档并适配Yocto机制
重载do_install步骤,先完成常规安装,再将文件归档到目标路径,同时确保Yocto的优化、剥离机制生效:
SUMMARY = "My Application Software" DESCRIPTION = "Device Software for My Products" LICENSE_PATH += "${LAYERDIR}/ec_licenses" LICENSE = "ECNF-1.0" LIC_FILES_CHKSUM = "file://ECNF-1.0;md5=80812384516565fef4dff4e7fdf7d55c" DEPENDS = "openssl" SRC_URI = "gitsm://git@git.mysite.com:/projects/myapp.git;protocol=ssh;branch=master" SRCREV_default = "ef0fbe4561238416e4b423a19694b79357c69b95" S = "${WORKDIR}/git/source" # 继承strip类,自动处理二进制符号剥离 inherit strip # 指定归档文件在rootfs中的路径 ARCHIVE_PATH = "${D}/home/root/myApp.tar.gz" FILES_${PN} += "/home/root/myApp.tar.gz" do_install() { # 1. 执行常规install,将文件安装到临时目录${D} oe_runmake install DESTDIR=${D} # 2. 将${D}下的usr和etc目录内容归档 tar -czf ${ARCHIVE_PATH} -C ${D} usr etc # 3. 删除临时目录下的原始文件,只保留归档包 rm -rf ${D}/usr ${D}/etc } # 确保Yocto的编译参数与自定义参数合并生效 EXTRA_OEMAKE = 'CXXFLAGS="${CXXFLAGS}"'
步骤3:验证问题解决
构建完成后,提取rootfs中的myApp.tar.gz,用以下命令验证:
# 检查二进制是否被剥离 file usr/bin/myApp # 检查是否残留调试符号 objdump -x usr/bin/myApp | grep debug # 确认优化参数生效 readelf -a usr/bin/myApp | grep -i optimize
关键说明
- 为什么要迁移归档逻辑?
- Yocto的
strip类会自动处理二进制符号剥离,Makefile中自行归档会绕过该流程 override CXXFLAGS会覆盖Yocto传入的系统级编译参数(如架构优化),导致自定义优化失效
- Yocto的
- CXXFLAGS的正确用法
- 使用
CXXFLAGS +=而非override CXXFLAGS,让自定义选项追加到系统参数之后,避免冲突
- 使用
- 归档路径处理
- 归档时用
-C ${D}切换到临时安装目录,确保归档内的路径是rootfs中的相对路径
- 归档时用
内容的提问来源于stack exchange,提问作者Mark Taylor
相关产品推荐
相关产品推荐

