0

Goal

I want to create a tar.gz archive of an application along with its configuration files and I want to install the archive file into the rootfs image rather than the compiled files themselves.

Background

I have a few custom layers in Yocto and my applications build and install correctly. My applications are Makefile-based.

For one of my applications, I do not want to directly install the compiled binary and associated files into the rootfs image. Instead, I want to archive these files into a package.tar.gz file and install the archive file into the rootfs.

Problem

  1. The binaries inside my archive file are compiled with debug info ('-g' flag)
  2. Are not optimized the way I want - in fact none of my CXXFLAGS are used.
  3. Are not stripped

How do I fix these problems? Should I modify the layer *.bb file and overload the install or package step instead of putting this archiving logic in my application's Makefile? How should I do this?

Application Makefile

To accomplish the archiving logic, I written the install step in my application's Makefile as follows:

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

Layer Recipe File

My application's *.bb file looks pretty simple and perhaps my declaration of do_install() is redundant:

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}
}
  • I've pulled the archive file out of the rootfs and examined the contents. I have verified that other application binaries made in other layers are stripped, however I imagine they are still compiled with debug flags and contain debugging symbols.
  • I've tried inserting inherit pkgconfig into my *.bb file - no effect
  • I've verified with the following commands the binaries in my archive are not stripped:
file usr/bin/myApp
objdump -x usr/bin/myApp | grep debug
readelf -wl /usr/bin/myApp

1 Answers1

0

I went back and forth narrowing in on a solution. Here is what I settled on:

Makefile

Reverted to original form of install:. However, this is not called in my recipe - it's just there for native installations (i.e., not Yocto):

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 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 $(DESTDIR)$(PREFIX)/usr/bin
    install -d $(DESTDIR)$(PREFIX)/etc/myApp/conf
    install -m 555 $(Program) $(DESTDIR)$(PREFIX)/usr/bin/
    install -m 555 ../conf/myApp.conf $(DESTDIR)$(PREFIX)/etc/myApp/conf/

# 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

Layer

Instead, I do the packaging in the recipe's do_install() method.

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} += "/usr/share/myApp/{PN}.tar.gz"
PREP_DIR = "/tmp/${PN}"

do_install() {
    install -d ${PREP_DIR}${bindir}
    install -d ${PREP_DIR}/etc/myApp/conf
    install -m 440 ${S}/../conf/myApp.conf ${PREP_DIR}/etc/myApp/conf 
    install -m 555 ${S}/myApp ${PREP_DIR}${bindir}/
    ${STRIP} ${PREP_DIR}${bindir}/myApp

    install -d ${D}${datadir}/myApp
    tar -czf ${PN}.tar.gz -C ${PREP_DIR} .
    install -m 440 ${PN}.tar.gz ${D}${datadir}/myApp
    rm -rf ${PREP_DIR}
}

CXXFLAGS_remove = "-g"
CXXFLAGS_remove = "-O2"
CXXFLAGS_append = " -Os"
EXTRA_OEMAKE += "'STRIP=${TARGET_PREFIX}strip'"

In the recipe, I specifically remove the '-g' debug flag along with the '-O2' optimization and re-insert '-Os', which is what I wanted. Additionally, I define a symbol that points to the cross-compiled strip tool and explicitly call it prior to archiving the files.

The resulting archive correctly contains the files and the binary is indeed stripped. Success! Not sure if this is the proper "Yocto" way to accomplish my goal, but it is working.