Skip to content

Optimize the CFBox as enter V0.2.0 Stage #43

Optimize the CFBox as enter V0.2.0 Stage

Optimize the CFBox as enter V0.2.0 Stage #43

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
# ── Native build + test ───────────────────────────────────────
native:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake g++-13 ccache
- name: Restore ccache
uses: actions/cache@v4
with:
path: ~/.ccache
key: ccache-native-${{ runner.os }}-${{ github.sha }}
restore-keys: ccache-native-${{ runner.os }}-
- name: Configure (Debug)
run: cmake -B build -DCMAKE_CXX_COMPILER=g++-13 -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
env:
CCACHE_MAXSIZE: 256M
- name: Build
run: cmake --build build -j $(nproc)
- name: Unit tests
run: ctest --test-dir build --output-on-failure --verbose -j $(nproc)
- name: Integration tests
run: bash tests/integration/run_all.sh
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: native-test-results
path: build/Testing/
# ── Release build with size report ───────────────────────────
release-size:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake g++-13 ccache
- name: Restore ccache
uses: actions/cache@v4
with:
path: ~/.ccache
key: ccache-release-${{ runner.os }}-${{ github.sha }}
restore-keys: ccache-release-${{ runner.os }}-
- name: Configure (Release, -Os)
run: >
cmake -B build-release
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_CXX_COMPILER=g++-13
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
-DCFBOX_OPTIMIZE_FOR_SIZE=ON
env:
CCACHE_MAXSIZE: 256M
- name: Build
run: cmake --build build-release -j $(nproc)
- name: Measure binary size
run: |
echo "=== -Os Release (dynamic) ==="
size build-release/cfbox
strip -o /tmp/cfbox-stripped build-release/cfbox
echo "Stripped size: $(wc -c < /tmp/cfbox-stripped) bytes"
- name: Upload release binary
uses: actions/upload-artifact@v4
with:
name: cfbox-x86_64-release
path: /tmp/cfbox-stripped
# ── Cross-compilation (aarch64 + armhf) ──────────────────────
cross-compile:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- target: aarch64
toolchain: Toolchain-aarch64.cmake
compiler_pkg: gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
strip: aarch64-linux-gnu-strip
- target: armhf
toolchain: Toolchain-armhf.cmake
compiler_pkg: ""
strip: arm-none-linux-gnueabihf-strip
steps:
- uses: actions/checkout@v4
- name: Install cross-compiler (aarch64)
if: matrix.target == 'aarch64'
run: |
sudo apt-get update
sudo apt-get install -y cmake ${{ matrix.compiler_pkg }} ccache
- name: Install cross-compiler (armhf)
if: matrix.target == 'armhf'
run: |
sudo apt-get update
sudo apt-get install -y ccache
curl -L -o /tmp/arm-toolchain.tar.xz \
https://developer.arm.com/-/media/Files/downloads/gnu/15.2.rel1/binrel/arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz
sudo tar -xJf /tmp/arm-toolchain.tar.xz -C /opt
sudo ln -s /opt/arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-linux-gnueabihf /opt/arm-gnu-toolchain
echo "/opt/arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-linux-gnueabihf/bin" >> "$GITHUB_PATH"
- name: Restore ccache
uses: actions/cache@v4
with:
path: ~/.ccache
key: ccache-cross-${{ matrix.target }}-${{ github.sha }}
restore-keys: ccache-cross-${{ matrix.target }}-
- name: Cross-compile (dynamic, -Os)
run: |
cmake -B build-${{ matrix.target }} \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain/${{ matrix.toolchain }} \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCFBOX_OPTIMIZE_FOR_SIZE=ON
cmake --build build-${{ matrix.target }} -j $(nproc)
- name: Verify target binary
run: |
file build-${{ matrix.target }}/cfbox
size build-${{ matrix.target }}/cfbox
${{ matrix.strip }} -o /tmp/cfbox-${{ matrix.target }}-stripped build-${{ matrix.target }}/cfbox
echo "Stripped size: $(wc -c < /tmp/cfbox-${{ matrix.target }}-stripped) bytes"
- name: Cross-compile (static)
run: |
cmake -B build-${{ matrix.target }}-static \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain/${{ matrix.toolchain }} \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCFBOX_OPTIMIZE_FOR_SIZE=ON \
-DCFBOX_STATIC_LINK=ON
cmake --build build-${{ matrix.target }}-static -j $(nproc)
- name: Verify static binary
run: |
file build-${{ matrix.target }}-static/cfbox
size build-${{ matrix.target }}-static/cfbox
- name: Upload static binary
uses: actions/upload-artifact@v4
with:
name: cfbox-${{ matrix.target }}-static
path: build-${{ matrix.target }}-static/cfbox
# ── QEMU user-mode emulation tests ──────────────────────────────
qemu-user-test:
needs: cross-compile
runs-on: ubuntu-latest
strategy:
matrix:
target: [aarch64, armhf]
steps:
- uses: actions/checkout@v4
- name: Install QEMU user-mode
run: sudo apt-get update && sudo apt-get install -y qemu-user-static
- name: Download static binary
uses: actions/download-artifact@v4
with:
name: cfbox-${{ matrix.target }}-static
path: build-${{ matrix.target }}-static
- name: Make binary executable
run: chmod +x build-${{ matrix.target }}-static/cfbox
- name: Smoke test
run: |
if [[ "${{ matrix.target }}" == "armhf" ]]; then
QEMU_BIN=qemu-arm-static
else
QEMU_BIN=qemu-${{ matrix.target }}-static
fi
$QEMU_BIN build-${{ matrix.target }}-static/cfbox --list
$QEMU_BIN build-${{ matrix.target }}-static/cfbox echo "Hello from ${{ matrix.target }}"
- name: Integration tests under QEMU
run: |
if [[ "${{ matrix.target }}" == "armhf" ]]; then
QEMU_BIN=qemu-arm-static
else
QEMU_BIN=qemu-${{ matrix.target }}-static
fi
# Create a wrapper script so test scripts work without modification
wrapper="$(mktemp /tmp/cfbox-qemu-wrapper-XXXXXX.sh)"
echo "#!/bin/sh" > "$wrapper"
echo "exec $QEMU_BIN $(pwd)/build-${{ matrix.target }}-static/cfbox \"\$@\"" >> "$wrapper"
chmod +x "$wrapper"
CFBOX="$wrapper" bash tests/integration/run_all.sh
# ── QEMU system-mode emulation tests ─────
qemu-system-test:
needs: cross-compile
runs-on: ubuntu-latest
strategy:
matrix:
target: [aarch64, armhf]
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y qemu-system-arm qemu-user-static cpio flex bison libelf-dev
- name: Install aarch64 cross-compiler
if: matrix.target == 'aarch64'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- name: Install armhf cross-compiler
if: matrix.target == 'armhf'
run: |
curl -L -o /tmp/arm-toolchain.tar.xz \
https://developer.arm.com/-/media/Files/downloads/gnu/15.2.rel1/binrel/arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz
sudo tar -xJf /tmp/arm-toolchain.tar.xz -C /opt
sudo ln -s /opt/arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-linux-gnueabihf /opt/arm-gnu-toolchain
echo "/opt/arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-linux-gnueabihf/bin" >> "$GITHUB_PATH"
- name: Download static binary
uses: actions/download-artifact@v4
with:
name: cfbox-${{ matrix.target }}-static
path: build-${{ matrix.target }}-static
- name: Make binary executable
run: chmod +x build-${{ matrix.target }}-static/cfbox
- name: Determine kernel config
id: kernel
run: |
if [[ "${{ matrix.target }}" == "aarch64" ]]; then
echo "arch=arm64" >> "$GITHUB_OUTPUT"
echo "image=arch/arm64/boot/Image" >> "$GITHUB_OUTPUT"
echo "defconfig=allnoconfig" >> "$GITHUB_OUTPUT"
echo "cross=aarch64-linux-gnu-" >> "$GITHUB_OUTPUT"
echo "extra_config=configs/qemu-virt-aarch64.config" >> "$GITHUB_OUTPUT"
else
echo "arch=arm" >> "$GITHUB_OUTPUT"
echo "image=arch/arm/boot/zImage" >> "$GITHUB_OUTPUT"
echo "defconfig=vexpress_defconfig" >> "$GITHUB_OUTPUT"
echo "cross=arm-none-linux-gnueabihf-" >> "$GITHUB_OUTPUT"
echo "extra_config=" >> "$GITHUB_OUTPUT"
fi
- name: Restore Linux kernel cache
id: cache-kernel
uses: actions/cache/restore@v4
with:
path: |
third_party/linux/${{ steps.kernel.outputs.image }}
third_party/linux/.config
${{ matrix.target == 'armhf' && 'third_party/linux/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb' || '' }}
key: linux-kernel-${{ matrix.target }}-${{ hashFiles('third_party/linux/Makefile') }}-${{ steps.kernel.outputs.defconfig }}
- name: Build Linux kernel
if: steps.cache-kernel.outputs.cache-hit != 'true'
run: |
cd third_party/linux
make ARCH=${{ steps.kernel.outputs.arch }} CROSS_COMPILE=${{ steps.kernel.outputs.cross }} ${{ steps.kernel.outputs.defconfig }}
if [[ -n "${{ steps.kernel.outputs.extra_config }}" ]]; then
while IFS='=' read -r key val; do
[[ -z "$key" || "$key" =~ ^# ]] && continue
./scripts/config --enable "$key"
done < "${{ github.workspace }}/${{ steps.kernel.outputs.extra_config }}"
make ARCH=${{ steps.kernel.outputs.arch }} CROSS_COMPILE=${{ steps.kernel.outputs.cross }} olddefconfig
fi
make ARCH=${{ steps.kernel.outputs.arch }} CROSS_COMPILE=${{ steps.kernel.outputs.cross }} -j$(nproc)
- name: Save Linux kernel cache
if: steps.cache-kernel.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
third_party/linux/${{ steps.kernel.outputs.image }}
third_party/linux/.config
${{ matrix.target == 'armhf' && 'third_party/linux/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb' || '' }}
key: linux-kernel-${{ matrix.target }}-${{ hashFiles('third_party/linux/Makefile') }}-${{ steps.kernel.outputs.defconfig }}
- name: Build initramfs (CFBox only, no busybox)
run: |
bash scripts/build_initramfs.sh \
--arch ${{ matrix.target }} \
--cfbox build-${{ matrix.target }}-static/cfbox \
--output build/${{ matrix.target }}-initramfs.cpio
- name: Run QEMU system-mode test
run: |
bash scripts/qemu_system_test.sh \
--arch ${{ matrix.target }} \
--kernel third_party/linux/${{ steps.kernel.outputs.image }} \
--initramfs build/${{ matrix.target }}-initramfs.cpio \
--timeout 120