From 8d21057d4946e3d7c7ec96b0c968fea932b42b20 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Fri, 19 Dec 2025 10:27:03 +0100 Subject: [PATCH] tests/functional2: use bash as builder ...and add both a static bash and busybox into the sandbox for building: $ /nix/store/fz43jxs5qfg5vldzk38y2hmrcl58qk18-busybox-1.36.1/bin/sh -c 'declare -A foo' /nix/store/fz43jxs5qfg5vldzk38y2hmrcl58qk18-busybox-1.36.1/bin/sh: declare: not found The reason is that busybox's `sh` doesn't know about `declare` which means it cannot build derivations with `__structuredAttrs = true;`. Change-Id: Ie3ca431f862fd3e59dc649582704ae739ee5834a --- meson.build | 1 + meson.options | 6 +++++- package.nix | 10 ++++++++-- tests/functional2/meson.build | 3 +++ tests/functional2/testlib/fixtures/env.py | 7 ++++++- tests/functional2/testlib/fixtures/test_env.py | 4 ++-- tests/functional2/testlib/utils.py | 4 ++-- 7 files changed, 27 insertions(+), 8 deletions(-) diff --git a/meson.build b/meson.build index 18bdc98b9..9cb181546 100644 --- a/meson.build +++ b/meson.build @@ -426,6 +426,7 @@ endif sandbox_shell = get_option('sandbox-shell') build_test_shell = get_option('build-test-shell') +build_test_env = get_option('build-test-env') # Consider it required if we're on Linux and the user explicitly specified a non-default value. sandbox_shell_required = sandbox_shell != 'busybox' and host_machine.system() == 'linux' # NOTE(Qyriad): package.nix puts busybox in buildInputs for Linux. diff --git a/meson.options b/meson.options index ce1177e63..c4077e296 100644 --- a/meson.options +++ b/meson.options @@ -24,8 +24,12 @@ option('sandbox-shell', type : 'string', value : 'busybox', description : 'path to a statically-linked shell to use as /bin/sh in sandboxes (usually busybox)', ) +option('build-test-env', type: 'string', + description : 'path to a statically-linked busybox which offers coreutils functionality' +) + option('build-test-shell', type: 'string', - description : 'path to a statically-linked shell which also offeres coreutils functionality' + description : 'path to a statically-linked bash (cannot use busybox sh because of __structuredAttrs)' ) option('pasta-path', type : 'string', value : 'pasta', diff --git a/package.nix b/package.nix index 8917cb146..4e2e59028 100644 --- a/package.nix +++ b/package.nix @@ -66,6 +66,7 @@ wrapBintoolsWith, busybox-sandbox-shell, + bash, pname ? "lix", versionSuffix ? "", @@ -296,9 +297,13 @@ stdenv.mkDerivation (finalAttrs: { # which don't actually get added to PATH. And buildInputs is correct over # nativeBuildInputs since this should be a busybox executable on the host. "-Dsandbox-shell=${lib.getExe' busybox-sandbox-shell "busybox"}" - "-Dbuild-test-shell=${pkgsStatic.busybox}/bin" + "-Dbuild-test-shell=${pkgsStatic.bash}/bin" + "-Dbuild-test-env=${pkgsStatic.busybox}/bin" "-Dpasta-path=${lib.getExe' passt-lix "pasta"}" ] + ++ lib.optionals hostPlatform.isDarwin [ + "-Dbuild-test-shell=${bash}/bin" + ] ++ lib.optionals useLld [ "-Dc_link_args=-fuse-ld=lld" "-Dcpp_link_args=-fuse-ld=lld" @@ -432,7 +437,8 @@ stdenv.mkDerivation (finalAttrs: { VERSION_SUFFIX = versionSuffix; } // lib.optionalAttrs hostPlatform.isLinux { - BUILD_TEST_SHELL = "${pkgsStatic.busybox}/bin"; + BUILD_TEST_SHELL = "${pkgsStatic.bash}/bin"; + BUILD_TEST_ENV = "${pkgsStatic.busybox}/bin"; } // lib.optionalAttrs hostPlatform.isStatic { NIX_CFLAGS_COMPILE = " -static"; diff --git a/tests/functional2/meson.build b/tests/functional2/meson.build index 4a4049121..a58558df4 100644 --- a/tests/functional2/meson.build +++ b/tests/functional2/meson.build @@ -18,6 +18,9 @@ functional2_env.set('NIX_BIN_DIR', fs.parent(nix.full_path())) if build_test_shell != '' functional2_env.set('BUILD_TEST_SHELL', build_test_shell) endif +if build_test_env != '' + functional2_env.set('BUILD_TEST_ENV', build_test_env) +endif functional2_env.set('system', host_system) test( diff --git a/tests/functional2/testlib/fixtures/env.py b/tests/functional2/testlib/fixtures/env.py index b560f28fa..35c503a7a 100644 --- a/tests/functional2/testlib/fixtures/env.py +++ b/tests/functional2/testlib/fixtures/env.py @@ -167,6 +167,7 @@ class ManagedEnv: # Things fetched from the global env build_shell = environ.get("BUILD_TEST_SHELL") global_path = environ.get("PATH") + build_env = environ.get("BUILD_TEST_ENV") # `NIX_BIN_DIR` either propagated from us or set by meson # Set to the codebase internal output if started standalone # This is where the current lix binaries are located. @@ -176,9 +177,10 @@ class ManagedEnv: lix_bin = Path(environ.get("NIX_BIN_DIR", lix_base_folder / "outputs/out/bin")) self._env = {} - self.path = _ManagedPath(build_shell) + self.path = _ManagedPath(build_env) self._tmp_path = tmp_path self.shell_dir = build_shell or "/bin" + self.build_env = build_env self.dirs = _Dirs( test_root=self._get_dir(""), @@ -193,6 +195,7 @@ class ManagedEnv: tmpdir=self._get_dir("tmp"), ) self.path.prepend(self.dirs.nix_bin_dir) + self.path.prepend(build_shell) self.init_defaults(global_path) def _get_dir(self, sub_path: str) -> Path: @@ -210,6 +213,8 @@ class ManagedEnv: "PAGER": "cat", "BUILD_TEST_SHELL": self.shell_dir, } + if self.build_env: + self._env["BUILD_TEST_ENV"] = self.build_env if platform.system() == "Darwin": # Darwin / Apple behaves differently and requires _NIX_TEST_NO_SANDBOX to be set for whatever reason self._env |= {"_NIX_TEST_NO_SANDBOX": "1"} diff --git a/tests/functional2/testlib/fixtures/test_env.py b/tests/functional2/testlib/fixtures/test_env.py index 2ea19d689..c5cf49b79 100644 --- a/tests/functional2/testlib/fixtures/test_env.py +++ b/tests/functional2/testlib/fixtures/test_env.py @@ -14,7 +14,7 @@ def test_env_inits_defaults(tmp_path: Path): assert env.get_env("GIT_CONFIG_SYSTEM") == "/dev/null" if sys.platform != "darwin": # Darwin doesn't like sandboxes so we don't have a sandbox shell here - assert "busybox" in env.get_env("SHELL") + assert "bash" in env.get_env("SHELL") else: assert "/bin/sh" in env.get_env("SHELL") assert env.get_env("PAGER") == "cat" @@ -134,7 +134,7 @@ def test_env_to_env(tmp_path: Path): "PATH", "BUILD_TEST_SHELL", "TMPDIR", - } | ({"_NIX_TEST_NO_SANDBOX"} if sys.platform == "darwin" else set()) + } | ({"_NIX_TEST_NO_SANDBOX"} if sys.platform == "darwin" else {"BUILD_TEST_ENV"}) def test_path_inits_build_shell(): diff --git a/tests/functional2/testlib/utils.py b/tests/functional2/testlib/utils.py index f1295b87e..c87373501 100644 --- a/tests/functional2/testlib/utils.py +++ b/tests/functional2/testlib/utils.py @@ -149,8 +149,8 @@ def get_global_asset(name: str) -> Fileish: { "system": environ.get("system"), # Either just the build shell or entire global path if we are darwin - "path": environ.get("BUILD_TEST_SHELL") or environ.get("PATH"), - "shell": Path(environ.get("BUILD_TEST_SHELL") or "/bin") / "sh", + "path": environ.get("BUILD_TEST_ENV") or environ.get("PATH"), + "shell": Path(environ.get("BUILD_TEST_SHELL") or "/bin") / "bash", }, ) return CopyFile(functional2_base_folder / "testlib" / "global_assets" / name)