@@ -93,17 +93,33 @@ install_deps() {
9393 echo " libelf-dev libssl-dev bc curl cpio" >&2
9494 fi
9595
96- # Ensure pyelftools is importable by the Python that will run bin2cbundle.py.
97- # The apt package may install to a different Python than the default python3.
98- if ! python3 -c " import elftools" & > /dev/null; then
99- echo " pyelftools not importable, installing via pip..."
100- python3 -m pip install --break-system-packages pyelftools 2> /dev/null || \
101- python3 -m pip install pyelftools || true
102- fi
10396}
10497
10598install_deps
10699
100+ # libkrunfw's Makefile invokes `python3` from PATH for bin2cbundle.py. A mise shim,
101+ # project venv, or other early PATH entry often shadows /usr/bin/python3 and does
102+ # not ship pyelftools even when python3-pyelftools is installed for the distro.
103+ ensure_python3_with_pyelftools_for_libkrunfw () {
104+ echo " Checking Python 3 + pyelftools (libkrunfw bin2cbundle.py)..."
105+ if python3 -c ' from elftools.elf.elffile import ELFFile' 2> /dev/null; then
106+ echo " OK ($( command -v python3) )"
107+ return 0
108+ fi
109+ if [ -x /usr/bin/python3 ] && /usr/bin/python3 -c ' from elftools.elf.elffile import ELFFile' 2> /dev/null; then
110+ export PATH=" /usr/bin:${PATH} "
111+ echo " Using /usr/bin/python3 (PATH python3 lacked pyelftools; system Python has it)."
112+ return 0
113+ fi
114+ echo " ERROR: Python 3 with pyelftools is required to build libkrunfw (kernel.c generation)." >&2
115+ echo " Install: Debian/Ubuntu: sudo apt-get install -y python3-pyelftools" >&2
116+ echo " Fedora/RHEL: sudo dnf install -y python3-pyelftools" >&2
117+ echo " pip: python3 -m pip install --user pyelftools" >&2
118+ echo " If the package is installed but this still fails, PATH may point at another python3 (mise, venv)." >&2
119+ echo " Try: PATH=/usr/bin:\$ PATH mise run vm:setup" >&2
120+ exit 1
121+ }
122+
107123# ── Setup build directory ───────────────────────────────────────────────
108124
109125mkdir -p " $BUILD_DIR "
@@ -114,6 +130,8 @@ cd "$BUILD_DIR"
114130echo " "
115131echo " ==> Building libkrunfw with custom kernel config..."
116132
133+ ensure_python3_with_pyelftools_for_libkrunfw
134+
117135if [ ! -d libkrunfw ]; then
118136 echo " Cloning libkrunfw (pinned: ${LIBKRUNFW_REF:- HEAD} )..."
119137 git clone https://github.com/containers/libkrunfw.git
@@ -221,54 +239,168 @@ make -j"$(nproc)"
221239cp libkrunfw.so* " $OUTPUT_DIR /"
222240echo " Built: $( ls " $OUTPUT_DIR " /libkrunfw.so* | xargs -n1 basename | tr ' \n' ' ' ) "
223241
224- # ── Export kernel.c for cross-platform builds ───────────────────────────
225- # kernel.c is a C source file containing the compiled Linux kernel as a byte
226- # array. It is architecture-specific (aarch64 vs x86_64) but OS-agnostic —
227- # any C compiler can turn it into a .so or .dylib. We export it so the macOS
228- # job can produce libkrunfw.dylib without rebuilding the kernel.
242+ cd " $BUILD_DIR "
229243
230- ABI_VERSION= " $( grep -oE ' ABI_VERSION\s*=\s*[0-9]+ ' Makefile | head -1 | sed ' s/[^0-9]//g ' ) "
244+ # ── Build libkrun (VMM) ─────────────────────────────────────────────────
231245
232- if [ -f kernel.c ]; then
233- cp kernel.c " $OUTPUT_DIR /kernel.c"
234- echo " ${ABI_VERSION} " > " $OUTPUT_DIR /ABI_VERSION"
235- echo " Exported kernel.c ($( du -sh kernel.c | cut -f1) ) and ABI_VERSION=${ABI_VERSION} "
236- else
237- echo " Warning: kernel.c not found — cross-platform builds will not work" >&2
238- fi
246+ # libkrun's Makefile invokes plain `cargo`. Ubuntu/Debian often put /usr/bin/cargo
247+ # (e.g. 1.75) ahead of mise/rustup; upstream requires edition 2024 (Cargo >= 1.85).
248+ ensure_cargo_for_libkrun () {
249+ local min_ver=" ${LIBKRUN_MIN_CARGO_VERSION:- 1.85} "
250+ local have ver_line bindir candidates_mise candidates_home
251+
252+ cargo_meets_min () {
253+ local bin=" $1 "
254+ local v
255+ [ -x " $bin " ] || return 1
256+ v=" $( " $bin " --version 2> /dev/null | awk ' {print $2}' ) "
257+ [ -n " $v " ] || return 1
258+ [ " $( printf ' %s\n' " ${min_ver} " " $v " | sort -V | head -n1) " = " ${min_ver} " ]
259+ }
260+
261+ echo " Checking Cargo (libkrun needs >= ${min_ver} , edition 2024)..."
262+ if cargo_meets_min " $( command -v cargo 2> /dev/null || true) " ; then
263+ echo " OK ($( command -v cargo) — $( cargo --version) )"
264+ return 0
265+ fi
239266
240- cd " $BUILD_DIR "
267+ candidates_mise=" "
268+ if command -v mise & > /dev/null; then
269+ if ver_line=" $( mise which cargo 2> /dev/null) " && [ -n " ${ver_line} " ]; then
270+ candidates_mise=" $( dirname " ${ver_line} " ) "
271+ fi
272+ fi
273+ candidates_home=" ${HOME} /.cargo/bin"
274+
275+ for bindir in " ${candidates_mise} " " ${candidates_home} " ; do
276+ [ -n " ${bindir} " ] || continue
277+ if cargo_meets_min " ${bindir} /cargo" ; then
278+ export PATH=" ${bindir} :${PATH} "
279+ echo " Using ${bindir} /cargo ($( " ${bindir} /cargo" --version) )"
280+ return 0
281+ fi
282+ done
241283
242- # ── Build libkrun (VMM) ─────────────────────────────────────────────────
284+ echo " ERROR: Cargo >= ${min_ver} is required to build libkrun (Rust edition 2024)." >&2
285+ echo " Current: $( command -v cargo 2> /dev/null || echo ' (no cargo in PATH)' ) $( cargo --version 2> /dev/null || true) " >&2
286+ echo " Typical fix: run vm:setup via mise from the repo so Rust stable is on PATH," >&2
287+ echo " or: rustup update stable && export PATH=\"\$ HOME/.cargo/bin:\$ PATH\" " >&2
288+ echo " Override minimum: LIBKRUN_MIN_CARGO_VERSION=…" >&2
289+ exit 1
290+ }
291+
292+ # Directory must contain libclang.so or libclang-<ver>.so (what clang-sys expects
293+ # for linking; bare .so.N sonames alone are not enough).
294+ _libclang_dir_usable () {
295+ local d=" $1 "
296+ [ -n " $d " ] && [ -d " $d " ] || return 1
297+ if [ -e " $d /libclang.so" ]; then
298+ return 0
299+ fi
300+ local f base
301+ for f in " $d " /libclang-* .so; do
302+ [ -e " $f " ] || continue
303+ base=" $( basename " $f " ) "
304+ case " $base " in
305+ * -cpp.so* ) continue ;;
306+ esac
307+ if [[ " $base " == libclang-* .so ]] && [[ " $base " != * .so.[0-9]* ]]; then
308+ return 0
309+ fi
310+ done
311+ return 1
312+ }
313+
314+ ensure_libclang_for_libkrun () {
315+ local user_libclang=" ${LIBCLANG_PATH:- } "
316+
317+ if [ -n " $user_libclang " ] && _libclang_dir_usable " $user_libclang " ; then
318+ export LIBCLANG_PATH=" $user_libclang "
319+ echo " LIBCLANG_PATH=$LIBCLANG_PATH (from environment)"
320+ return 0
321+ fi
322+
323+ if [ -n " $user_libclang " ]; then
324+ echo " Warning: LIBCLANG_PATH='$user_libclang ' has no libclang.so or libclang-*.so symlink;" >&2
325+ echo " those are required for clang-sys. Searching other system locations..." >&2
326+ fi
327+ unset LIBCLANG_PATH
328+
329+ local llvm_lib
330+ if command -v llvm-config & > /dev/null; then
331+ llvm_lib=" $( llvm-config --libdir 2> /dev/null) " || true
332+ if [ -n " ${llvm_lib} " ] && _libclang_dir_usable " $llvm_lib " ; then
333+ export LIBCLANG_PATH=" $llvm_lib "
334+ echo " LIBCLANG_PATH=$LIBCLANG_PATH (from llvm-config --libdir)"
335+ return 0
336+ fi
337+ fi
338+
339+ shopt -s nullglob
340+ local candidates=(/usr/lib/llvm-* /lib)
341+ shopt -u nullglob
342+ while IFS= read -r llvm_lib; do
343+ [ -n " $llvm_lib " ] || continue
344+ if _libclang_dir_usable " $llvm_lib " ; then
345+ export LIBCLANG_PATH=" $llvm_lib "
346+ echo " LIBCLANG_PATH=$LIBCLANG_PATH (from /usr/lib/llvm-*/lib)"
347+ return 0
348+ fi
349+ done < <( printf ' %s\n' " ${candidates[@]} " | sort -rV)
350+
351+ local multi
352+ multi=" $( gcc -print-multiarch 2> /dev/null || true) "
353+ if [ -n " $multi " ] && _libclang_dir_usable " /usr/lib/${multi} " ; then
354+ export LIBCLANG_PATH=" /usr/lib/${multi} "
355+ echo " LIBCLANG_PATH=$LIBCLANG_PATH (from gcc multiarch /usr/lib/${multi} )"
356+ return 0
357+ fi
358+
359+ if _libclang_dir_usable " /usr/lib64" ; then
360+ export LIBCLANG_PATH=" /usr/lib64"
361+ echo " LIBCLANG_PATH=$LIBCLANG_PATH (from /usr/lib64)"
362+ return 0
363+ fi
364+
365+ echo " ERROR: libclang is required to build libkrun (Rust bindgen / clang-sys) but was not found." >&2
366+ if [ -n " $user_libclang " ]; then
367+ echo " You had LIBCLANG_PATH='$user_libclang ' (ignored after search failed)." >&2
368+ fi
369+ echo " Install LLVM/Clang development packages, then re-run vm:setup:" >&2
370+ echo " Debian/Ubuntu: sudo apt-get install -y libclang-dev" >&2
371+ echo " Fedora/RHEL: sudo dnf install -y clang-devel" >&2
372+ echo " Then unset LIBCLANG_PATH or set it to a directory that contains libclang.so." >&2
373+ exit 1
374+ }
243375
244376echo " "
245377echo " ==> Building libkrun..."
246378
379+ ensure_cargo_for_libkrun
380+ ensure_libclang_for_libkrun
381+
382+ LIBKRUN_REF=" ${LIBKRUN_REF:- v1.17.4} "
383+
247384if [ ! -d libkrun ]; then
248385 echo " Cloning libkrun..."
249- git clone --depth 1 https://github.com/containers/libkrun.git
386+ git clone https://github.com/containers/libkrun.git
250387fi
251388
252389cd libkrun
253390
254- # Build with NET support for gvproxy networking and BLK support for the
255- # host-backed state disk.
256- echo " Building libkrun with NET=1 BLK=1..."
391+ if [ -n " ${LIBKRUN_REF:- } " ]; then
392+ echo " Checking out pinned ref: ${LIBKRUN_REF} "
393+ git fetch origin " ${LIBKRUN_REF} " 2> /dev/null || git fetch origin
394+ git checkout " ${LIBKRUN_REF} " 2> /dev/null || git checkout " origin/${LIBKRUN_REF} " 2> /dev/null || true
395+ fi
257396
258- # Locate libclang for clang-sys if LIBCLANG_PATH isn't already set.
259- # clang-sys looks for libclang.so or libclang-*.so; on Debian/Ubuntu the
260- # versioned file (e.g. libclang-18.so.18) lives under the LLVM lib dir.
261- if [ -z " ${LIBCLANG_PATH:- } " ]; then
262- for llvm_lib in /usr/lib/llvm-* /lib; do
263- if ls " $llvm_lib " /libclang* .so* & > /dev/null; then
264- export LIBCLANG_PATH=" $llvm_lib "
265- echo " LIBCLANG_PATH=$LIBCLANG_PATH "
266- break
267- fi
268- done
397+ if [ -f init/Makefile ] || grep -q ' init/init' Makefile 2> /dev/null; then
398+ echo " Building init/init binary..."
399+ make init/init
269400fi
270401
271- make NET=1 BLK=1 -j" $( nproc) "
402+ echo " Building libkrun with NET=1 BLK=1..."
403+ cargo build --release --features blk --features net --target-dir=" $( pwd) /target"
272404
273405# Copy output
274406cp target/release/libkrun.so " $OUTPUT_DIR /"
@@ -283,7 +415,6 @@ echo "==> Build complete!"
283415echo " Output directory: ${OUTPUT_DIR} "
284416echo " "
285417echo " Artifacts:"
286- ls -lah " $OUTPUT_DIR " /* .so* " $OUTPUT_DIR " /kernel.c " $OUTPUT_DIR " /ABI_VERSION 2> /dev/null || \
287418ls -lah " $OUTPUT_DIR " /* .so*
288419
289420echo " "
0 commit comments