You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键说明

  1. 为什么要迁移归档逻辑?
    • Yocto的strip类会自动处理二进制符号剥离,Makefile中自行归档会绕过该流程
    • override CXXFLAGS会覆盖Yocto传入的系统级编译参数(如架构优化),导致自定义优化失效
  2. CXXFLAGS的正确用法
    • 使用CXXFLAGS +=而非override CXXFLAGS,让自定义选项追加到系统参数之后,避免冲突
  3. 归档路径处理
    • 归档时用-C ${D}切换到临时安装目录,确保归档内的路径是rootfs中的相对路径

内容的提问来源于stack exchange,提问作者Mark Taylor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 13:47:02