Splux Linux

source-based Linux using SPS

SPS · log · files · refs · tags · releases · people · languages · GitHub · commit

e2b9369


mkiso: seed a working Meson instead of a setuptools stub.

Date
Commite2b936914ee5aa084554486b53c24d5ee5d55861
GitHubmirror

Parents

Stat

 PACKAGE-MAINTAINER.md |   5 +-
 bin/mkiso             | 150 +++++++++++++++++++++++++++++++++++++++++++++++++-
 bin/setup             |  14 +++++
 man/mkiso.1           |   9 ++-
 tests/test_mkiso.sh   |  18 ++++++
 tests/test_setup.sh   |   2 +
 6 files changed, 194 insertions(+), 4 deletions(-)

Diff

diff --git a/PACKAGE-MAINTAINER.md b/PACKAGE-MAINTAINER.md
index 4bbd677..5cccaaa 100644
--- a/PACKAGE-MAINTAINER.md
+++ b/PACKAGE-MAINTAINER.md
@@ -154,11 +154,14 @@ install DESTDIR="$PKG" cmake --install build
 ```
 
 ```text
-configure meson setup build --prefix=/usr --buildtype=release
+configure meson setup build --prefix=/usr --libdir=lib64 --buildtype=release
 build meson compile -C build -j "$MAKEJOBS"
 install DESTDIR="$PKG" meson install -C build
 ```
 
+Meson feature options take `enabled`, `disabled`, or `auto`, not `true`/`false`.
+Passing `-Dpython=false` to libxml2 2.15 is a meson error, not a compiler error.
+
 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`.
diff --git a/bin/mkiso b/bin/mkiso
index 17c28ae..8729df6 100755
--- a/bin/mkiso
+++ b/bin/mkiso
@@ -24,7 +24,10 @@
 # this host does not ship, so the image is built with grub-mkimage and
 # xorriso.
 #
-# Seed toolchain (--no-seed to skip): gcc, headers, cmake, ninja, python.
+# Seed toolchain (--no-seed to skip): gcc, headers, cmake, ninja, python
+# stdlib, Meson (mesonbuild), Perl library. Host /usr/bin/meson is a
+# setuptools wrapper; mesonbuild lives under site-packages, not next
+# to the Python stdlib, so copying python3.12 is not enough.
 # Pass --core/--extra so the live image can build packages without cloning
 # the recipe repos. --with-go copies the official Go tree; gccgo on PATH
 # is too old for the Go recipes in extra.
@@ -324,6 +327,121 @@ mkiso_copy_gcc_deps()
 	done
 }
 
+# Python's stdlib is under lib64; Meson is a pure-Python package under
+# /usr/lib/pythonX.Y/site-packages. Copying the interpreter and
+# lib64/pythonX.Y is not enough: that tree's site-packages is PyQt and
+# friends, not mesonbuild. The setuptools /usr/bin/meson then dies with
+# ModuleNotFoundError, which looks like a Python error at the first
+# meson recipe (often libxml2).
+mkiso_python_version()
+{
+	python3 -c 'import sys; print("%d.%d" % sys.version_info[:2])' \
+		2>/dev/null || printf '%s\n' 3.12
+}
+
+mkiso_copy_python_stdlib()
+{
+	mkiso_pyver=$(mkiso_python_version)
+	for mkiso_pylib in /usr/lib64/python$mkiso_pyver \
+		/usr/lib/python$mkiso_pyver
+	do
+		[ -d "$mkiso_pylib" ] || continue
+		printf '%s: copying Python %s stdlib from %s\n' \
+			"$sps_prog" "$mkiso_pyver" "$mkiso_pylib" >&2
+		for mkiso_pyent in "$mkiso_pylib"/*; do
+			[ -e "$mkiso_pyent" ] || continue
+			mkiso_pybase=${mkiso_pyent##*/}
+			case $mkiso_pybase in
+				test|idlelib|ensurepip|turtledemo|site-packages)
+					continue
+					;;
+			esac
+			mkiso_copy_path "$mkiso_pyent"
+		done
+		if [ -d "$mkiso_pylib/lib-dynload" ]; then
+			for mkiso_pyso in "$mkiso_pylib/lib-dynload"/*.so \
+				"$mkiso_pylib/lib-dynload"/*.so.*
+			do
+				[ -e "$mkiso_pyso" ] || continue
+				mkiso_copy_libs "$mkiso_pyso"
+			done
+		fi
+	done
+}
+
+# Install Meson as meson.py next to mesonbuild so it does not need
+# importlib.metadata or a setuptools egg-info (the host /usr/bin/meson
+# does). Same layout the meson recipe ships.
+mkiso_install_meson()
+{
+	mkiso_mod=
+	mkiso_mod=$(python3 -c 'import mesonbuild, os; print(os.path.dirname(mesonbuild.__file__))' \
+		2>/dev/null) || mkiso_mod=
+	if [ -z "$mkiso_mod" ] || [ ! -d "$mkiso_mod" ]; then
+		for mkiso_cand in \
+			/usr/lib/python*/site-packages/mesonbuild \
+			/usr/lib64/python*/site-packages/mesonbuild
+		do
+			[ -d "$mkiso_cand" ] || continue
+			mkiso_mod=$mkiso_cand
+			break
+		done
+	fi
+	[ -n "$mkiso_mod" ] && [ -d "$mkiso_mod" ] || return 0
+	printf '%s: copying Meson from %s\n' "$sps_prog" "$mkiso_mod" >&2
+	mkdir -p "$mkiso_live/usr/share/meson" "$mkiso_live/usr/bin"
+	rm -rf "$mkiso_live/usr/share/meson/mesonbuild"
+	cp -a --reflink=auto "$mkiso_mod" \
+		"$mkiso_live/usr/share/meson/mesonbuild" 2>/dev/null ||
+		cp -a "$mkiso_mod" "$mkiso_live/usr/share/meson/mesonbuild" 2>/dev/null ||
+		cp -R "$mkiso_mod" "$mkiso_live/usr/share/meson/mesonbuild"
+	cat >"$mkiso_live/usr/share/meson/meson.py" <<'EOF'
+#!/usr/bin/python3
+import sys
+from pathlib import Path
+meson_exe = Path(sys.argv[0]).resolve()
+if (meson_exe.parent / 'mesonbuild').is_dir():
+    sys.path.insert(0, str(meson_exe.parent))
+from mesonbuild import mesonmain
+if __name__ == '__main__':
+    sys.exit(mesonmain.main())
+EOF
+	chmod 755 "$mkiso_live/usr/share/meson/meson.py"
+	rm -f "$mkiso_live/usr/bin/meson"
+	ln -s ../share/meson/meson.py "$mkiso_live/usr/bin/meson"
+}
+
+mkiso_copy_cmake_data()
+{
+	printf '%s: copying CMake modules\n' "$sps_prog" >&2
+	for mkiso_cmake in /usr/share/cmake /usr/share/cmake-*
+	do
+		[ -e "$mkiso_cmake" ] || continue
+		mkiso_copy_path "$mkiso_cmake"
+	done
+}
+
+mkiso_copy_perl_lib()
+{
+	printf '%s: copying Perl library\n' "$sps_prog" >&2
+	for mkiso_perl in /usr/lib64/perl5 /usr/lib/perl5 \
+		/usr/share/perl5 /usr/share/perl
+	do
+		[ -e "$mkiso_perl" ] || continue
+		mkiso_copy_path "$mkiso_perl"
+	done
+}
+
+# Host /usr/include is copied so gcc can compile against libc. Optional
+# third-party headers on that tree make configure detect libraries the
+# disc does not ship (alsa-utils vs samplerate.h) or compile a recipe
+# against a different upstream version (host libxml2 vs the tarball).
+mkiso_prune_seed_headers()
+{
+	rm -f "$mkiso_live/usr/include/samplerate.h"
+	rm -rf "$mkiso_live/usr/include/libxml2"
+}
+
 mkiso_copy_mesa_deps()
 {
 	printf '%s: resolving Mesa DRI/GBM libraries\n' "$sps_prog" >&2
@@ -755,6 +873,30 @@ mkiso_verify_compiler()
 	elif [ -e /usr/bin/ld ]; then
 		mkiso_verify_elf_in_live /usr/bin/ld
 	fi
+	# Meson is a Python program. The host driver is a setuptools
+	# wrapper; without mesonbuild and encodings, the first meson
+	# recipe dies with a traceback (libxml2's -Dpython= option is a
+	# second, separate failure).
+	if [ -e /usr/bin/meson ] || [ -L /usr/bin/meson ]; then
+		if [ ! -e "$mkiso_live/usr/share/meson/mesonbuild/mesonmain.py" ]
+		then
+			sps_die "$SPS_EX_PACKAGE" \
+				"seeded meson is missing mesonbuild"
+		fi
+		if [ ! -e "$mkiso_live/usr/bin/meson" ] &&
+			[ ! -L "$mkiso_live/usr/bin/meson" ]
+		then
+			sps_die "$SPS_EX_PACKAGE" \
+				"seeded meson wrapper is missing"
+		fi
+		mkiso_pyver=$(mkiso_python_version)
+		if [ ! -e "$mkiso_live/usr/lib64/python$mkiso_pyver/encodings/__init__.py" ] &&
+			[ ! -e "$mkiso_live/usr/lib/python$mkiso_pyver/encodings/__init__.py" ]
+		then
+			sps_die "$SPS_EX_PACKAGE" \
+				"seeded python is missing the encodings stdlib module"
+		fi
+	fi
 }
 
 mkiso_verify_plasma()
@@ -1486,6 +1628,7 @@ if [ "$mkiso_copy_seed" -eq 1 ] && [ -f "$mkiso_libdir/seed-bins" ]; then
 	mkiso_copy_path /usr/lib64/gcc
 	mkiso_copy_path /usr/lib/gcc
 	mkiso_copy_path /usr/include
+	mkiso_prune_seed_headers
 	# gcc and ld without glibc startfiles fail the first autoconf check
 	# with "C compiler cannot create executables". Runtime libc.so.6 is
 	# not enough; the linker needs crt1.o and the libc.so script.
@@ -1530,7 +1673,10 @@ if [ "$mkiso_copy_seed" -eq 1 ] && [ -f "$mkiso_libdir/seed-bins" ]; then
 	do
 		mkiso_copy_host_cmd "$mkiso_cmd" || :
 	done
-	mkiso_copy_path /usr/lib64/python3.12
+	mkiso_copy_python_stdlib
+	mkiso_install_meson
+	mkiso_copy_cmake_data
+	mkiso_copy_perl_lib
 	mkiso_copy_path /usr/share/terminfo
 	mkiso_copy_path /usr/share/zoneinfo
 	mkiso_copy_path /etc/ssl
diff --git a/bin/setup b/bin/setup
index b920e2a..c18e038 100755
--- a/bin/setup
+++ b/bin/setup
@@ -1999,6 +1999,20 @@ if command -v gcc >/dev/null 2>&1; then
 	fi
 	rm -f "$setup_cc_out"
 fi
+# Meson recipes (libxml2 is the first for many desktop graphs) fail with
+# a Python traceback when mesonbuild is missing, or with a meson error
+# about option "python" when the recipe passes -Dpython=false.
+if command -v meson >/dev/null 2>&1; then
+	setup_meson_dir=${SPS_BUILD:-$setup_root/var/tmp/sps}
+	mkdir -p "$setup_meson_dir" ||
+		setup_fail "$SPS_EX_PERMISSION" "cannot create $setup_meson_dir"
+	setup_meson_log=$setup_meson_dir/sps-meson-probe.log
+	if ! meson --version >"$setup_meson_log" 2>&1; then
+		printf '%s: live meson cannot run\n' "$sps_prog" >&2
+		cat "$setup_meson_log" >&2
+		setup_fail "$SPS_EX_BUILD" "live meson cannot run"
+	fi
+fi
 # sget treats requested names as explicit world roots.
 # shellcheck disable=SC2086
 sget install $setup_pkgs ||
diff --git a/man/mkiso.1 b/man/mkiso.1
index 4bec931..e6b7240 100644
--- a/man/mkiso.1
+++ b/man/mkiso.1
@@ -40,7 +40,14 @@ writes the live root only, for tests and inspection.
 .PP
 Host compiler tools can be copied into the image so
 .B setup
-can build packages from the bundled recipes. Pass
+can build packages from the bundled recipes. The seed includes gcc,
+the Python stdlib, Meson as
+.B meson.py
+next to
+.BR mesonbuild ,
+CMake modules, and the Perl library. Host
+.B /usr/bin/meson
+is a setuptools wrapper and is replaced. Pass
 .B --no-seed
 to omit them.
 .SH OPTIONS
diff --git a/tests/test_mkiso.sh b/tests/test_mkiso.sh
index 7ed048c..73067f3 100755
--- a/tests/test_mkiso.sh
+++ b/tests/test_mkiso.sh
@@ -235,6 +235,8 @@ grep -q '/tmp/.X11-unix' "$layout/etc/sps/live-plasma" ||
 	fail 'live-plasma must create /tmp/.X11-unix for Xwayland'
 grep -q 'live gcc cannot create executables' "$project_dir/bin/setup" ||
 	fail 'setup must probe live gcc before the first package build'
+grep -q 'live meson cannot run' "$project_dir/bin/setup" ||
+	fail 'setup must probe live meson before the first meson package'
 grep -q 'copying disk tools for setup' "$mkiso" ||
 	fail 'mkiso must copy partition tools by command name'
 grep -q grub-install "$mkiso" ||
@@ -276,6 +278,22 @@ grep -q /usr/bin/msgfmt "$project_dir/lib/mkiso/seed-bins" ||
 	fail 'seeded ISO must include msgfmt for alsa-utils translations'
 grep -q /usr/bin/xgettext "$project_dir/lib/mkiso/seed-bins" ||
 	fail 'seeded ISO must include xgettext with the gettext tools'
+grep -q mkiso_install_meson "$mkiso" ||
+	fail 'seeded ISO must install mesonbuild next to meson.py'
+grep -q mkiso_copy_python_stdlib "$mkiso" ||
+	fail 'seeded ISO must copy the Python stdlib without host site-packages'
+grep -q 'seeded meson is missing mesonbuild' "$mkiso" ||
+	fail 'mkiso must refuse a disc whose meson cannot import mesonbuild'
+grep -q encodings "$mkiso" ||
+	fail 'mkiso must verify the Python encodings module landed'
+grep -q mkiso_copy_cmake_data "$mkiso" ||
+	fail 'seeded ISO must copy CMake modules'
+grep -q mkiso_copy_perl_lib "$mkiso" ||
+	fail 'seeded ISO must copy the Perl library for autoconf'
+grep -q mkiso_prune_seed_headers "$mkiso" ||
+	fail 'mkiso must drop host samplerate.h and libxml2 headers'
+grep -q samplerate.h "$mkiso" ||
+	fail 'mkiso must prune host samplerate.h from seeded includes'
 grep -q '/etc/file' "$mkiso" ||
 	fail 'mkiso must copy /etc/file magic used by this host file(1)'
 grep -q kactivitymanagerd "$project_dir/lib/mkiso/plasma-bins" ||
diff --git a/tests/test_setup.sh b/tests/test_setup.sh
index a7d8607..760aeaa 100755
--- a/tests/test_setup.sh
+++ b/tests/test_setup.sh
@@ -295,6 +295,8 @@ grep -q 'remount,rw,exec' "$project_dir/lib/setup/partition.sh" ||
 	fail 'setup must remount the target exec so autoconf can run conftest'
 grep -q 'live gcc cannot create executables' "$setup" ||
 	fail 'setup must probe live gcc before sget install'
+grep -q 'live meson cannot run' "$setup" ||
+	fail 'setup must probe live meson before sget install'
 
 plan=$("$setup" --plan --target /mnt --profile plasma-desktop --init systemd \
 	--disable qol-cli --disable power --disable firmware)