SPS · log · files · refs · tags · releases · people · languages · GitHub · commit
eeb6e68
Load target libraries when just-built modules are imported.
Parents
Stat
PACKAGE-MAINTAINER.md | 12 ++++++++++++ bin/mkiso | 15 ++++++++++++++- bin/mkpkg | 43 ++++++++++++++++++++++++++++++++++++++++--- bin/setup | 23 ++++++++++++++++++++--- lib/mkiso/seed-bins | 2 ++ tests/test_build.sh | 42 +++++++++++++++++++++++++++++++++++++++++- tests/test_mkiso.sh | 8 ++++++++ tests/test_setup.sh | 6 ++++++ 8 files changed, 143 insertions(+), 8 deletions(-)
Diff
diff --git a/PACKAGE-MAINTAINER.md b/PACKAGE-MAINTAINER.md
index 5cccaaa..ffbfd77 100644
--- a/PACKAGE-MAINTAINER.md
+++ b/PACKAGE-MAINTAINER.md
@@ -138,6 +138,7 @@ The phase environment provides:
| `SRC` | Downloaded/copied sources and support trees |
| `PKG` | Package staging root |
| `MAKEJOBS` | Positive parallel-job count |
+| `SPS_TARGET_LIBRARY_PATH` | Target `lib64`/`lib` dirs when `SPS_ROOT` is not `/` |
Typical build-system records look like:
@@ -166,6 +167,17 @@ Use the upstream project's intended build system and supported options. Build
commands run on the host; `mkpkg` is not a chroot and cannot prevent a bad
command from modifying paths outside `$PKG`.
+When `SPS_ROOT` is a mounted disk (live `setup`), `mkpkg` puts that root on
+`LD_LIBRARY_PATH` so a just-built interpreter can import its own extensions
+against libraries already unpacked into the target. CPython's
+`check_extension_modules` will otherwise load the live disc's older
+`libsqlite3`, rename `_sqlite3` to `_sqlite3_failed`, and then `make install`
+dies on `sharedinstall`. Host `gcc`, `python3`, `meson`, and `git` wrappers
+restore the previous `LD_LIBRARY_PATH` so those tools do not load a
+half-installed libc from the disk. Shared libraries belong in `lib64` on
+this architecture; pass `--libdir=/usr/lib64` (or Meson's `--libdir=lib64`)
+instead of relying on Autoconf's `/usr/lib` default.
+
## Local files and patches
A real `files/` directory is copied to `$SRC/files`; a real `patches/` directory
diff --git a/bin/mkiso b/bin/mkiso
index 63c3de0..4a3c4d8 100755
--- a/bin/mkiso
+++ b/bin/mkiso
@@ -804,6 +804,19 @@ mkiso_verify_live()
fi
fi
+ if [ -e /usr/sbin/efibootmgr ] || [ -L /usr/sbin/efibootmgr ] ||
+ [ -e /usr/bin/efibootmgr ] || [ -L /usr/bin/efibootmgr ]
+ then
+ if [ ! -e "$mkiso_live/usr/sbin/efibootmgr" ] &&
+ [ ! -L "$mkiso_live/usr/sbin/efibootmgr" ] &&
+ [ ! -e "$mkiso_live/usr/bin/efibootmgr" ] &&
+ [ ! -L "$mkiso_live/usr/bin/efibootmgr" ]
+ then
+ sps_die "$SPS_EX_PACKAGE" \
+ "seeded live image is missing efibootmgr"
+ fi
+ fi
+
mkiso_verify_compiler
mkiso_verify_plasma
mkiso_verify_setup_catalog
@@ -1608,7 +1621,7 @@ fi
printf '%s: copying disk tools for setup\n' "$sps_prog" >&2
for mkiso_cmd in lsblk blkid sfdisk cfdisk fdisk wipefs mkfs.ext4 mke2fs \
mkfs.vfat mkswap partprobe udevadm udevd grub-install grub-mkconfig \
- dhcpcd
+ efibootmgr dhcpcd
do
mkiso_copy_host_cmd "$mkiso_cmd" || :
done
diff --git a/bin/mkpkg b/bin/mkpkg
index 477b5cd..031106f 100755
--- a/bin/mkpkg
+++ b/bin/mkpkg
@@ -713,6 +713,17 @@ shell_quote()
printf "'%s'" "$(printf '%s' "$1" | sed "s/'/'\\\\''/g")"
}
+# Host tools must load the live disc's libraries, not SPS_ROOT. CPython's
+# `make` imports just-built _sqlite3.so against the sqlite on the target;
+# that needs LD_LIBRARY_PATH. gcc loading a half-installed libc from the
+# disk would abort the compiler. Restore the caller's LD_LIBRARY_PATH.
+write_host_ld_restore()
+{
+ printf '%s\n' 'LD_LIBRARY_PATH=$SPS_HOST_LD_LIBRARY_PATH'
+ printf '%s\n' 'export LD_LIBRARY_PATH'
+ printf '%s\n' '[ -n "$LD_LIBRARY_PATH" ] || unset LD_LIBRARY_PATH'
+}
+
# gcc on PATH must inject -L/-isystem itself. Autoconf often runs `gcc`
# without LDFLAGS, which is how alsa-utils printed "No linkable libasound
# was found" after alsa-lib was already in SPS_ROOT.
@@ -723,6 +734,7 @@ write_cc_wrapper()
[ -n "$real_cc" ] && [ -x "$real_cc" ] || return 0
{
printf '%s\n' '#!/bin/sh'
+ write_host_ld_restore
printf 'exec %s -isystem %s -L%s -L%s -L%s -L%s -Wl,-rpath-link,%s -Wl,-rpath-link,%s "$@"\n' \
"$(shell_quote "$real_cc")" \
"$(shell_quote "$target_inc")" \
@@ -736,6 +748,19 @@ write_cc_wrapper()
chmod 755 "$wrapper_path"
}
+write_host_tool_wrapper()
+{
+ wrapper_path=$1
+ real_tool=$2
+ [ -n "$real_tool" ] && [ -x "$real_tool" ] || return 0
+ {
+ printf '%s\n' '#!/bin/sh'
+ write_host_ld_restore
+ printf 'exec %s "$@"\n' "$(shell_quote "$real_tool")"
+ } >"$wrapper_path"
+ chmod 755 "$wrapper_path"
+}
+
# A controlled build root runs each phase with the root's /usr/bin and /bin
# ahead of the host PATH and exposes the root as $SYSROOT. Recipes building a
# staged toolchain use this to ensure their compiler, linker, and headers are
@@ -764,8 +789,11 @@ fi
# target, not only live /usr. Exporting LDFLAGS is not enough: autoconf
# AC_CHECK_LIB often invokes `gcc conftest.c -lasound` with a cleared
# environment. Wrappers named gcc/g++ on PATH inject -L/-isystem instead.
-# Do not set LD_LIBRARY_PATH to the target; that makes host gcc load a
-# half-installed libc from the disk.
+# CPython then *runs* the new _sqlite3.so (check_extension_modules) and
+# renames it to _sqlite3_failed if the loader picked the live disc's
+# older libsqlite3. LD_LIBRARY_PATH must include SPS_ROOT for that
+# import. Host gcc/python3/meson/git wrappers restore the previous
+# LD_LIBRARY_PATH so they do not load a half-installed libc from the disk.
if [ -n "${SPS_ROOT:-}" ] && [ "$SPS_ROOT" != / ]; then
target_root=$SPS_ROOT
target_inc=$target_root/usr/include
@@ -794,7 +822,11 @@ if [ -n "${SPS_ROOT:-}" ] && [ "$SPS_ROOT" != / ]; then
C_INCLUDE_PATH=$target_inc${C_INCLUDE_PATH:+:$C_INCLUDE_PATH}
CPLUS_INCLUDE_PATH=$target_inc${CPLUS_INCLUDE_PATH:+:$CPLUS_INCLUDE_PATH}
LIBRARY_PATH=$target_libpath${LIBRARY_PATH:+:$LIBRARY_PATH}
- export CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH LIBRARY_PATH
+ SPS_HOST_LD_LIBRARY_PATH=${LD_LIBRARY_PATH-}
+ SPS_TARGET_LIBRARY_PATH=$target_libpath
+ LD_LIBRARY_PATH=$target_libpath${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
+ export CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH LIBRARY_PATH \
+ SPS_HOST_LD_LIBRARY_PATH SPS_TARGET_LIBRARY_PATH LD_LIBRARY_PATH
CPPFLAGS="$target_cflags${CPPFLAGS:+ $CPPFLAGS}"
CFLAGS="$target_cflags${CFLAGS:+ $CFLAGS}"
@@ -839,6 +871,11 @@ if [ -n "${SPS_ROOT:-}" ] && [ "$SPS_ROOT" != / ]; then
CXX=$build_dir/run/g++
export CXX
fi
+ for host_tool in python3 python meson cmake git curl wget perl; do
+ host_tool_path=$(PATH=$host_path command -v "$host_tool" 2>/dev/null) ||
+ host_tool_path=
+ write_host_tool_wrapper "$build_dir/run/$host_tool" "$host_tool_path"
+ done
# Autoconf sources CONFIG_SITE before AC_CHECK_LIB. AM_PATH_ALSA
# (alsa-utils) only adds -L when --with-alsa-prefix is set; this
diff --git a/bin/setup b/bin/setup
index 2d0f4fe..3574b6e 100755
--- a/bin/setup
+++ b/bin/setup
@@ -2162,10 +2162,27 @@ if [ "$setup_install_bootloader" -eq 1 ]; then
"--install-bootloader requires --disk; refusing to guess. See /root/sps-bootloader.txt"
printf '%s: grub-install %s (explicit)\n' "$sps_prog" "$setup_disk" >&2
if [ -d "$setup_root/boot/efi" ]; then
- grub-install --target=x86_64-efi --efi-directory="$setup_root/boot/efi" \
- --bootloader-id=SPS --boot-directory="$setup_root/boot" \
+ # Firmware fallback path: \EFI\BOOT\BOOTX64.EFI. This does not
+ # need efibootmgr or working NVRAM, which QEMU often lacks.
+ printf '%s: grub-install EFI removable (EFI/BOOT/BOOTX64.EFI)\n' \
+ "$sps_prog" >&2
+ grub-install --target=x86_64-efi \
+ --efi-directory="$setup_root/boot/efi" \
+ --boot-directory="$setup_root/boot" \
+ --removable --no-nvram \
"$setup_disk" ||
- setup_fail "$SPS_EX_BUILD" "grub-install (EFI) failed"
+ setup_fail "$SPS_EX_BUILD" "grub-install (EFI removable) failed"
+ if command -v efibootmgr >/dev/null 2>&1; then
+ printf '%s: grub-install EFI Boot#### via efibootmgr\n' \
+ "$sps_prog" >&2
+ grub-install --target=x86_64-efi \
+ --efi-directory="$setup_root/boot/efi" \
+ --bootloader-id=SPS \
+ --boot-directory="$setup_root/boot" \
+ "$setup_disk" ||
+ printf '%s: efibootmgr NVRAM update failed; EFI/BOOT/BOOTX64.EFI is in place\n' \
+ "$sps_prog" >&2
+ fi
else
grub-install --target=i386-pc --boot-directory="$setup_root/boot" \
"$setup_disk" ||
diff --git a/lib/mkiso/seed-bins b/lib/mkiso/seed-bins
index 9697f5f..41d7747 100644
--- a/lib/mkiso/seed-bins
+++ b/lib/mkiso/seed-bins
@@ -121,6 +121,8 @@
/usr/bin/patch
/usr/bin/diff
/usr/sbin/grub-install
+/usr/sbin/efibootmgr
+/usr/bin/efibootmgr
/usr/bin/grub-mkconfig
/usr/sbin/grub-mkconfig
/usr/bin/grub-probe
diff --git a/tests/test_build.sh b/tests/test_build.sh
index 6ae05cb..55b3ccb 100755
--- a/tests/test_build.sh
+++ b/tests/test_build.sh
@@ -261,8 +261,10 @@ description Confirms PATH gcc injects SPS_ROOT -L even without LDFLAGS
configure unset LDFLAGS CFLAGS CPPFLAGS LIBRARY_PATH
configure printf '%s\n' '#include <spsprobe.h>' 'int main(void){return sps_probe_lib();}' >"$WORK/probe.c"
configure gcc "$WORK/probe.c" -lspsprobe -o "$WORK/probe"
-install mkdir -p "$PKG/usr/bin"
+configure sed -n '1,20p' "$CC" >"$WORK/ccwrap"
+install mkdir -p "$PKG/usr/bin" "$PKG/usr/share/target-cc-wrapper-probe"
install cp "$WORK/probe" "$PKG/usr/bin/target-cc-wrapper-probe"
+install cp "$WORK/ccwrap" "$PKG/usr/share/target-cc-wrapper-probe/gcc"
install chmod 755 "$PKG/usr/bin/target-cc-wrapper-probe"
EOF
wrap_artifact=$(run_mkpkg --no-download --output "$tmp/wrap-out" \
@@ -272,6 +274,44 @@ EOF
tar -xf "$wrap_artifact" -C "$tmp/wrap-extract"
[ -x "$tmp/wrap-extract/usr/bin/target-cc-wrapper-probe" ] ||
fail "wrapper probe binary was not staged"
+ grep -q SPS_HOST_LD_LIBRARY_PATH \
+ "$tmp/wrap-extract/usr/share/target-cc-wrapper-probe/gcc" ||
+ fail "gcc wrapper must restore the host LD_LIBRARY_PATH"
+
+ # CPython's check_extension_modules *runs* _sqlite3.so. Linking is
+ # not enough: the loader must find the sqlite in SPS_ROOT, not the
+ # live disc. Host gcc must not see that LD_LIBRARY_PATH.
+ mkdir -p "$tmp/run-recipe" "$tmp/run-out"
+ cat >"$tmp/run-recipe/recipe" <<'EOF'
+name target-runtime-lib-probe
+version 1.0
+release 1
+arch any
+description Confirms just-built binaries load libraries from SPS_ROOT
+configure printf '%s\n' "$LD_LIBRARY_PATH" >"$WORK/ldpath"
+configure printf '%s\n' "$SPS_TARGET_LIBRARY_PATH" >"$WORK/targetld"
+configure printf '%s\n' '#include <spsprobe.h>' 'int main(void){return sps_probe_lib();}' >"$WORK/probe.c"
+configure gcc "$WORK/probe.c" -lspsprobe -o "$WORK/probe"
+configure "$WORK/probe"
+install mkdir -p "$PKG/usr/share/target-runtime-lib-probe" "$PKG/usr/bin"
+install cp "$WORK/ldpath" "$WORK/targetld" "$PKG/usr/share/target-runtime-lib-probe/"
+install cp "$WORK/probe" "$PKG/usr/bin/target-runtime-lib-probe"
+install chmod 755 "$PKG/usr/bin/target-runtime-lib-probe"
+EOF
+ run_artifact=$(run_mkpkg --no-download --output "$tmp/run-out" \
+ "$tmp/run-recipe/recipe") ||
+ fail "target-root runtime library probe failed (just-built binaries must load SPS_ROOT libs)"
+ mkdir "$tmp/run-extract"
+ tar -xf "$run_artifact" -C "$tmp/run-extract"
+ case "$(cat "$tmp/run-extract/usr/share/target-runtime-lib-probe/ldpath")" in
+ "$tmp/root/usr/lib64:"*) : ;;
+ *) fail "LD_LIBRARY_PATH did not start with the target libdir" ;;
+ esac
+ assert_equal "$tmp/root/usr/lib64:$tmp/root/usr/lib:$tmp/root/lib64:$tmp/root/lib" \
+ "$(cat "$tmp/run-extract/usr/share/target-runtime-lib-probe/targetld")" \
+ "SPS_TARGET_LIBRARY_PATH was not the target libdirs"
+ [ -x "$tmp/run-extract/usr/bin/target-runtime-lib-probe" ] ||
+ fail "runtime probe binary was not staged"
fi
printf '%s\n' 'test_build: ok'
diff --git a/tests/test_mkiso.sh b/tests/test_mkiso.sh
index d058c2a..4047d3f 100755
--- a/tests/test_mkiso.sh
+++ b/tests/test_mkiso.sh
@@ -241,6 +241,10 @@ grep -q 'copying disk tools for setup' "$mkiso" ||
fail 'mkiso must copy partition tools by command name'
grep -q grub-install "$mkiso" ||
fail 'mkiso must copy grub-install by command name for setup'
+grep -q efibootmgr "$mkiso" ||
+ fail 'mkiso must copy efibootmgr by command name for EFI NVRAM'
+grep -q /usr/sbin/efibootmgr "$project_dir/lib/mkiso/seed-bins" ||
+ fail 'seed-bins must list efibootmgr'
grep -q 'system-local.conf' "$mkiso" ||
fail 'mkiso must bake a live D-Bus system-local.conf'
grep -q '<user>root</user>' "$project_dir/lib/mkiso/live-plasma" ||
@@ -349,6 +353,10 @@ grep -q 'using .* for headers, libraries, and pkg-config' "$project_dir/bin/mkpk
fail 'mkpkg must compile against SPS_ROOT so setup can link target libs'
grep -q write_cc_wrapper "$project_dir/bin/mkpkg" ||
fail 'mkpkg must wrap gcc so autoconf finds libraries in SPS_ROOT'
+grep -q SPS_HOST_LD_LIBRARY_PATH "$project_dir/bin/mkpkg" ||
+ fail 'mkpkg must keep host gcc from loading SPS_ROOT via LD_LIBRARY_PATH'
+grep -q SPS_TARGET_LIBRARY_PATH "$project_dir/bin/mkpkg" ||
+ fail 'mkpkg must put SPS_ROOT on LD_LIBRARY_PATH for just-built test programs'
grep -q CONFIG_SITE "$project_dir/bin/mkpkg" ||
fail 'mkpkg must export CONFIG_SITE so autoconf sees SPS_ROOT LDFLAGS'
grep -q 'sps_say "unpacking' "$project_dir/bin/pkin" ||
diff --git a/tests/test_setup.sh b/tests/test_setup.sh
index d3528e8..b1b3bca 100755
--- a/tests/test_setup.sh
+++ b/tests/test_setup.sh
@@ -281,6 +281,12 @@ st=$?
set -e
[ "$st" -eq 2 ] || fail "--install-bootloader without --disk returned $st"
contains "$(cat "$tmp/err")" '--disk'
+grep -q -- '--removable' "$setup" ||
+ fail 'EFI grub-install must write EFI/BOOT/BOOTX64.EFI'
+grep -q -- '--no-nvram' "$setup" ||
+ fail 'EFI removable grub-install must not require firmware NVRAM'
+grep -q efibootmgr "$setup" ||
+ fail 'EFI grub-install must use efibootmgr when it is on PATH'
set +e
"$setup" --non-interactive --no-update --target "$tmp/noformat" \