mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
nix: Add FHS wrappers for venv binaries (ruff, pyrefly) on NixOS (#40860)
On NixOS, dynamically linked binaries from the Python venv (installed via uv/pip) cannot run directly because they expect standard Linux library paths that don't exist on NixOS. This commit adds FHS wrappers that allow these binaries to run in an FHS-compatible environment at runtime, without patching them. I considered using the nixpkgs versions of ruff and pyrefly directly, or overriding their derivations to match the versions in requirements.txt. However, decided against it because: - Version mismatches between nixpkgs and requirements.txt caused type checking incompatibilities (pyrefly 0.34.0 vs 0.23.1) - Building these tools from source in nix is slow and adds significant time to nix-shell initialization (both are rust packages that take quite some time to build) Testing: just improvements to the NixOS development environment, no test needed **Before:** ``` ➜ servo (main) ✔ nix-shell ➜ servo (main) ✔ ./mach fmt Could not start dynamically linked executable: /home/dyego/coding/random/servo/.venv/bin/ruff NixOS cannot run dynamically linked executables intended for generic linux environments out of the box. For more information, see: https://nix.dev/permalink/stub-ld ➜ servo (main) ✔ ./mach test-tidy ➤ Checking config file (./servo-tidy.toml)... ➤ Checking directories for correct file extensions... Could not start dynamically linked executable: ruff NixOS cannot run dynamically linked executables intended for generic linux environments out of the box. For more information, see: https://nix.dev/permalink/stub-ld Error running mach: ['test-tidy'] The error occurred in code that was called by the mach command. This is either a bug in the called code itself or in the way that mach is calling it. You can invoke |./mach busted| to check if this issue is already on file. If it isn't, please use |./mach busted file| to report it. If |./mach busted| is misbehaving, you can also inspect the dependencies of bug 1543241. If filing a bug, please include the full output of mach, including this error message. The details of the failure are as follows: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) File "/home/dyego/coding/random/servo/python/servo/testing_commands.py", line 322, in test_tidy tidy_failed = tidy.scan(not all_files, not no_progress, github_annotations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/dyego/coding/random/servo/python/tidy/tidy.py", line 919, in scan for error in errors: File "/home/dyego/coding/random/servo/python/tidy/tidy.py", line 401, in check_ruff_lints for error in json.loads(e.output): ^^^^^^^^^^^^^^^^^^^^ File "/nix/store/2g9b898aq9kmizmhmhbdip5mixrc5wrk-python3-3.11.14/lib/python3.11/json/__init__.py", line 346, in loads return _default_decoder.decode(s) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/nix/store/2g9b898aq9kmizmhmhbdip5mixrc5wrk-python3-3.11.14/lib/python3.11/json/decoder.py", line 337, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/nix/store/2g9b898aq9kmizmhmhbdip5mixrc5wrk-python3-3.11.14/lib/python3.11/json/decoder.py", line 355, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None ➜ servo (main) ✔ ``` (note that the `JSONDecodeError` is because we're trying to parse the "NixOS cannot run dynamically linked executables intended..." string as JSON) **Now:** ``` ➜ servo (fix-nix-mach) ✔ nix-shell ➜ servo (fix-nix-mach) ✔ ./mach fmt ➜ servo (fix-nix-mach) ✔ ./mach test-tidy ➤ Checking config file (./servo-tidy.toml)... ➤ Checking directories for correct file extensions... ➤ Checking type annotations in python files ... ➤ Skipping WPT lint checks, because no relevant files changed. ➤ Running `cargo-deny` checks... ➤ Checking formatting of Rust files... ➤ Checking formatting of python files... ➤ Checking formatting of toml files... ✅ test-tidy reported no errors. ➜ servo (fix-nix-mach) ✔ ``` Signed-off-by: Dyego Aurélio <dyegoaurelio@gmail.com>
This commit is contained in:
4
mach
4
mach
@@ -37,6 +37,10 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
# On NixOS, prepend nix-provided binary paths so they take precedence over .venv/bin
|
||||
if 'SERVO_NIX_BIN_DIR' in os.environ:
|
||||
os.environ['PATH'] = os.environ['SERVO_NIX_BIN_DIR'] + os.pathsep + os.environ.get('PATH', '')
|
||||
|
||||
def main(args):
|
||||
topdir = os.path.abspath(os.path.dirname(sys.argv[0]))
|
||||
sys.path.insert(0, os.path.join(topdir, "python"))
|
||||
|
||||
@@ -147,6 +147,9 @@ def _activate_virtualenv(topdir: str) -> None:
|
||||
|
||||
script_dir = "Scripts" if _is_windows() else "bin"
|
||||
runpy.run_path(os.path.join(virtualenv_path, script_dir, "activate_this.py"))
|
||||
# On NixOS, prepend nix-provided binary paths so they take precedence over .venv/bin
|
||||
if "SERVO_NIX_BIN_DIR" in os.environ:
|
||||
os.environ["PATH"] = os.environ["SERVO_NIX_BIN_DIR"] + os.pathsep + os.environ.get("PATH", "")
|
||||
|
||||
install_virtual_env_requirements(topdir, marker_path)
|
||||
|
||||
|
||||
22
shell.nix
22
shell.nix
@@ -52,6 +52,19 @@ let
|
||||
];
|
||||
};
|
||||
androidSdk = androidComposition.androidsdk;
|
||||
|
||||
# FHS wrappers for Python tools installed via venv (e.g ruff, pyrefly)
|
||||
# These allow running dynamically linked binaries on NixOS without patching them.
|
||||
# The wrappers provide an FHS environment at runtime.
|
||||
mkVenvFhsWrapper =
|
||||
name:
|
||||
buildFHSEnv {
|
||||
inherit name;
|
||||
runScript = writeShellScript "${name}-fhs" ''
|
||||
exec "${toString ./.}/.venv/bin/${name}" "$@"
|
||||
'';
|
||||
};
|
||||
|
||||
# Required by ./mach build --android
|
||||
androidEnvironment = lib.optionalAttrs buildAndroid rec {
|
||||
ANDROID_SDK_ROOT = "${androidSdk}/libexec/android-sdk";
|
||||
@@ -190,6 +203,15 @@ stdenv.mkDerivation (androidEnvironment // {
|
||||
# get patched in a way that makes them dependent on the Nix store.
|
||||
repo_root=$(git rev-parse --show-toplevel)
|
||||
export RUSTUP_HOME=$repo_root/.rustup
|
||||
else
|
||||
# On NixOS, export FHS wrapper paths so mach can prepend them to PATH at runtime
|
||||
# This ensures the FHS-wrapped binaries take precedence over .venv/bin
|
||||
export SERVO_NIX_BIN_DIR="${
|
||||
lib.makeBinPath [
|
||||
(mkVenvFhsWrapper "ruff")
|
||||
(mkVenvFhsWrapper "pyrefly")
|
||||
]
|
||||
}"
|
||||
fi
|
||||
'';
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user