@@ -17,53 +17,203 @@ jobs:
1717 edriver :
1818 name : " Build and test edriver / ${{ matrix.arch }}"
1919 runs-on : ${{ matrix.runner }}
20+ container :
21+ image : ${{ matrix.container }}
2022 strategy :
2123 fail-fast : false
2224 matrix :
2325 include :
2426 - arch : x86_64
2527 runner : ubuntu-latest
2628 target : x86_64-unknown-linux-musl
29+ # Ubuntu + musl-gcc + vendored-libelf (--without-zstd).
30+ # elfutils ./configure needs argp/fts/obstack, which are absent from
31+ # musl libc. We pre-build them (argp-standalone, musl-fts,
32+ # musl-obstack) using musl-gcc and install to /usr/lib/x86_64-linux-musl
33+ # before running `cargo build`, so configure finds them.
34+ container : ubuntu:24.04
35+ cc : musl-gcc
36+ lib_path : " "
37+ extra_cflags : " -idirafter /usr/include -idirafter /usr/include/x86_64-linux-gnu"
38+ cargo_extra_features : " ,vendored-libelf"
39+ rustflags : " -C target-feature=+crt-static"
2740 - arch : aarch64
2841 runner : ubuntu-24.04-arm
2942 target : aarch64-unknown-linux-musl
43+ # Same approach as x86_64. ubuntu:24.04 on arm64 supports JS
44+ # actions; Alpine ARM64 does not (no Node.js ARM64 in Alpine).
45+ container : ubuntu:24.04
46+ cc : musl-gcc
47+ lib_path : " "
48+ # -mno-outline-atomics: GCC 13 on aarch64 defaults to
49+ # -moutline-atomics, emitting __aarch64_ldadd4/8_acq_rel etc.
50+ # These live in libatomic, not musl libc, causing undefined-reference
51+ # link errors. Disabling outline atomics uses inline LL/SC
52+ # sequences instead, which musl supports natively.
53+ extra_cflags : " -idirafter /usr/include -idirafter /usr/include/aarch64-linux-gnu -mno-outline-atomics"
54+ cargo_extra_features : " ,vendored-libelf"
55+ rustflags : " -C target-feature=+crt-static"
3056 steps :
31- - name : " Git checkout"
57+ - name : Install build dependencies
58+ env :
59+ DEBIAN_FRONTEND : noninteractive
60+ run : |
61+ apt-get update -qq
62+ apt-get install -y --no-install-recommends \
63+ bash curl git ca-certificates \
64+ build-essential linux-headers-generic \
65+ clang llvm \
66+ libelf-dev zlib1g-dev \
67+ musl-tools musl-dev \
68+ protobuf-compiler \
69+ pkg-config \
70+ autoconf automake libtool autopoint gettext flex bison gawk
71+
72+ - name : Git checkout
3273 uses : actions/checkout@v4
3374 with :
34- submodules : true
75+ submodules : false # libbpf submodule cloned explicitly below
76+
77+ - name : Clone libbpf submodule
78+ # The submodule is pinned to v1.1.0 (2023); a shallow clone of that
79+ # old commit is unreliable. Clone at the v1.2.2 tag instead, which
80+ # matches the intended version recorded in .gitmodules (tags = v1.2.2).
81+ run : |
82+ git clone --depth=1 --branch v1.2.2 \
83+ https://github.com/libbpf/libbpf.git plugins/libs/libbpf
3584
3685 - name : Install Rust toolchain
3786 uses : dtolnay/rust-toolchain@stable
3887 with :
3988 targets : ${{ matrix.target }}
89+ components : rustfmt
4090
41- - name : Cache cargo registry & build
91+ - name : Cache cargo registry
4292 uses : actions/cache@v4
4393 with :
4494 path : |
4595 ~/.cargo/registry
4696 ~/.cargo/git
47- plugins/edriver/target
48- key : ${{ runner.os }}-${{ matrix.arch }}-cargo-edriver-${{ hashFiles('plugins/edriver/Cargo.lock') }}
49- restore-keys : ${{ runner.os }}-${{ matrix.arch }}-cargo-edriver-
97+ key : ${{ matrix.arch }}-cargo-edriver-v10-${{ hashFiles('plugins/edriver/Cargo.lock') }}
98+ restore-keys : ${{ matrix.arch }}-cargo-edriver-v10-
5099
51- - name : Install build dependencies
100+ # elfutils ./configure (invoked by libbpf-sys vendored-libelf build.rs)
101+ # runs with CC=musl-gcc. musl libc lacks argp_parse, fts_close, and
102+ # _obstack_free, causing configure to abort. We pre-build the three
103+ # void-linux musl-compat shims (identical to Alpine's argp-standalone,
104+ # musl-fts-dev, musl-obstack-dev packages) and install the .a + headers
105+ # into musl-gcc's default sysroot search path so configure finds them.
106+ - name : Build musl compat libs (argp / fts / obstack)
52107 run : |
53- sudo apt-get update -qq
54- sudo apt-get install -y --no-install-recommends build-essential pkgconf libelf-dev libzstd-dev musl-tools llvm-14 clang-14 protobuf-compiler
55- for tool in clang llc llvm-strip
56- do
57- sudo rm -f /usr/bin/$tool
58- sudo ln -s /usr/bin/${tool}-14 /usr/bin/$tool
59- done
108+ set -eux
109+ ARCH=$(uname -m) # x86_64 or aarch64
110+ MUSL_LIB=/usr/lib/${ARCH}-linux-musl
111+ MUSL_INC=/usr/include/${ARCH}-linux-musl
112+
113+ # 1. argp-standalone – provides argp_parse
114+ # NOTE: Makefile.am uses noinst_LIBRARIES so `make install` does NOT
115+ # install libargp.a. We build and copy manually.
116+ git clone --depth=1 https://github.com/ericonr/argp-standalone /tmp/argp-standalone
117+ cd /tmp/argp-standalone
118+ autoreconf -fiv
119+ CC=musl-gcc ./configure --prefix=/usr
120+ make -j$(nproc)
121+ cp libargp.a ${MUSL_LIB}/
122+ cp argp.h ${MUSL_INC}/
123+
124+ # 2. musl-fts – provides fts_close (NetBSD implementation)
125+ git clone --depth=1 https://github.com/void-linux/musl-fts /tmp/musl-fts
126+ cd /tmp/musl-fts
127+ ./bootstrap.sh
128+ CC=musl-gcc ./configure --enable-static --disable-shared \
129+ --prefix=/usr --libdir=${MUSL_LIB} --includedir=${MUSL_INC}
130+ make -j$(nproc) && make install
131+
132+ # 3. musl-obstack – provides _obstack_free (from gcc libiberty)
133+ git clone --depth=1 https://github.com/void-linux/musl-obstack /tmp/musl-obstack
134+ cd /tmp/musl-obstack
135+ ./bootstrap.sh
136+ CC=musl-gcc ./configure --enable-static --disable-shared \
137+ --prefix=/usr --libdir=${MUSL_LIB} --includedir=${MUSL_INC}
138+ make -j$(nproc) && make install
139+
140+ # Verify all three libs landed in the musl sysroot
141+ ls -la ${MUSL_LIB}/libargp.a ${MUSL_LIB}/libfts.a ${MUSL_LIB}/libobstack.a
142+
143+ - name : Verify toolchain
144+ run : |
145+ which protoc && protoc --version
146+ which clang && clang --version | head -1
147+ musl-gcc --version | head -1
148+
149+ - name : Build libbpf headers
150+ # Build libbpf.a separately so failures here are easily diagnosed.
151+ # Then touch the fake-target file so `make build` skips the rebuild.
152+ run : |
153+ cd plugins/edriver
154+ LIBBPF_LOG=/tmp/libbpf-build.log
155+ echo "clang: $(clang --version | head -1)"
156+ if ! CC=clang CFLAGS=-fPIC make \
157+ -C ../libs/libbpf/src \
158+ BUILD_STATIC_ONLY=1 \
159+ DESTDIR=$(pwd)/src/bpf/headers/libbpf/ \
160+ OBJDIR=$(pwd)/src/bpf/headers/libbpf/obj \
161+ INCLUDEDIR= LIBDIR= UAPIDIR= prefix= libdir= \
162+ install install_uapi_headers > "$LIBBPF_LOG" 2>&1; then
163+ echo "=== libbpf build failed, last 60 lines ==="
164+ tail -60 "$LIBBPF_LOG"
165+ grep -E "error:|fatal error:|undefined" "$LIBBPF_LOG" | head -20 \
166+ | while IFS= read -r line; do echo "::error::libbpf: $line"; done
167+ exit 2
168+ fi
169+ install -m 0640 ./src/bpf/headers/libbpf/bpf/*.h ./src/bpf/headers/
170+ mkdir -p headers/libbpf
171+ # Use a far-future mtime so make considers this target always up-to-date.
172+ touch -d "2030-01-01" headers/libbpf/libbpf.a
60173
61174 - name : Build
62- run : cd plugins/edriver && make build
175+ run : |
176+ export PROTOC=$(which protoc)
177+ BUILD_LOG=/tmp/edriver-build.log
178+ if ! ( cd plugins/edriver && make build ) > "$BUILD_LOG" 2>&1; then
179+ echo "=== Build failed, last 200 lines ==="
180+ tail -200 "$BUILD_LOG"
181+ echo "## Build failure" >> "$GITHUB_STEP_SUMMARY"
182+ echo '```' >> "$GITHUB_STEP_SUMMARY"
183+ tail -200 "$BUILD_LOG" >> "$GITHUB_STEP_SUMMARY"
184+ echo '```' >> "$GITHUB_STEP_SUMMARY"
185+ # Emit key error lines as annotations (readable via check-runs API)
186+ grep -E "error:|panicked at|make: \*\*\*|error\[|undefined reference" "$BUILD_LOG" \
187+ | grep -v "^warning" | head -20 \
188+ | while IFS= read -r line; do
189+ echo "::error::$line"
190+ done
191+ exit 2
192+ fi
63193 env :
64194 PLATFORM : ${{ matrix.arch }}
195+ LIBBPF_SYS_LIBRARY_PATH : ${{ matrix.lib_path }}
196+ # Use -idirafter (not -I) so musl sysroot headers keep priority;
197+ # linux/bpf.h etc. are still found via /usr/include as last resort.
198+ LIBBPF_SYS_EXTRA_CFLAGS : ${{ matrix.extra_cflags }}
199+ CC_x86_64_unknown_linux_musl : ${{ matrix.cc }}
200+ CC_aarch64_unknown_linux_musl : ${{ matrix.cc }}
201+ CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER : ${{ matrix.cc }}
202+ CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER : ${{ matrix.cc }}
203+ RUSTFLAGS : ${{ matrix.rustflags }}
204+ CARGO_EXTRA_FEATURES : ${{ matrix.cargo_extra_features }}
65205
66206 - name : Test
67- run : cd plugins/edriver && make test
207+ run : |
208+ export PROTOC=$(which protoc)
209+ cd plugins/edriver && make test
68210 env :
69211 PLATFORM : ${{ matrix.arch }}
212+ LIBBPF_SYS_LIBRARY_PATH : ${{ matrix.lib_path }}
213+ LIBBPF_SYS_EXTRA_CFLAGS : ${{ matrix.extra_cflags }}
214+ CC_x86_64_unknown_linux_musl : ${{ matrix.cc }}
215+ CC_aarch64_unknown_linux_musl : ${{ matrix.cc }}
216+ CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER : ${{ matrix.cc }}
217+ CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER : ${{ matrix.cc }}
218+ RUSTFLAGS : ${{ matrix.rustflags }}
219+ CARGO_EXTRA_FEATURES : ${{ matrix.cargo_extra_features }}
0 commit comments