diff --git a/.envrc b/.envrc new file mode 100644 index 00000000000..ed519d8d962 --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +if nix flake show path:./src/tools/nix-dev-shell &> /dev/null; then + use flake path:./src/tools/nix-dev-shell +fi diff --git a/.gitignore b/.gitignore index 2e6499081a6..89c62e126b0 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,8 @@ build/ /src/tools/x/target # Created by default with `src/ci/docker/run.sh` /obj/ +# Created by nix dev shell / .envrc +src/tools/nix-dev-shell/flake.lock ## ICE reports rustc-ice-*.txt diff --git a/src/tools/nix-dev-shell/flake.nix b/src/tools/nix-dev-shell/flake.nix new file mode 100644 index 00000000000..8ab5e097427 --- /dev/null +++ b/src/tools/nix-dev-shell/flake.nix @@ -0,0 +1,33 @@ +{ + description = "rustc dev shell"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + x = import ./x { inherit pkgs; }; + in + { + devShells.default = with pkgs; mkShell { + name = "rustc-dev-shell"; + nativeBuildInputs = with pkgs; [ + binutils cmake ninja pkg-config python3 git curl cacert patchelf nix + ]; + buildInputs = with pkgs; [ + openssl glibc.out glibc.static x + ]; + # Avoid creating text files for ICEs. + RUSTC_ICE = "0"; + # Provide `libstdc++.so.6` for the self-contained lld. + LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [ + stdenv.cc.cc.lib + ]}"; + }; + } + ); +} diff --git a/src/tools/nix-dev-shell/x/default.nix b/src/tools/nix-dev-shell/x/default.nix new file mode 100644 index 00000000000..e6dfbad6f19 --- /dev/null +++ b/src/tools/nix-dev-shell/x/default.nix @@ -0,0 +1,22 @@ +{ + pkgs ? import { }, +}: +pkgs.stdenv.mkDerivation { + name = "x"; + + src = ./x.rs; + dontUnpack = true; + + nativeBuildInputs = with pkgs; [ rustc ]; + + buildPhase = '' + PYTHON=${pkgs.lib.getExe pkgs.python3} rustc -Copt-level=3 --crate-name x $src --out-dir $out/bin + ''; + + meta = with pkgs.lib; { + description = "Helper for rust-lang/rust x.py"; + homepage = "https://github.com/rust-lang/rust/blob/master/src/tools/x"; + license = licenses.mit; + mainProgram = "x"; + }; +} diff --git a/src/tools/nix-dev-shell/x/x.rs b/src/tools/nix-dev-shell/x/x.rs new file mode 100644 index 00000000000..9f83b8fd62e --- /dev/null +++ b/src/tools/nix-dev-shell/x/x.rs @@ -0,0 +1,50 @@ +// git clone https://github.com/rust-lang/rust/blob/0ea7ddcc35a2fcaa5da8a7dcfc118c9fb4a63b95/src/tools/x/src/main.rs +// patched to stop doing python probing, stop the probe, please dont, i have a python +//! Run bootstrap from any subdirectory of a rust compiler checkout. +//! +//! We prefer `exec`, to avoid adding an extra process in the process tree. +//! However, since `exec` isn't available on Windows, we indirect through +//! `exec_or_status`, which will call `exec` on unix and `status` on Windows. +//! +//! We use `powershell.exe x.ps1` on Windows, and `sh -c x` on Unix, those are +//! the ones that call `x.py`. We use `sh -c` on Unix, because it is a standard. +//! We also don't use `pwsh` on Windows, because it is not installed by default; + +use std::env; +use std::os::unix::process::CommandExt; +use std::process::{self, Command}; + +fn main() { + match env::args().skip(1).next().as_deref() { + Some("--wrapper-version") => { + println!("0.1.0"); + return; + } + _ => {} + } + let current = match env::current_dir() { + Ok(dir) => dir, + Err(err) => { + eprintln!("Failed to get current directory: {err}"); + process::exit(1); + } + }; + + for dir in current.ancestors() { + let candidate = dir.join("x.py"); + if candidate.exists() { + let mut cmd = Command::new(env!("PYTHON")); + cmd.arg(dir.join("x.py")); + cmd.args(env::args().skip(1)).current_dir(dir); + + let error = cmd.exec(); + eprintln!("Failed to invoke `{:?}`: {}", cmd, error); + } + } + + eprintln!( + "x.py not found. Please run inside of a checkout of `https://github.com/rust-lang/rust`." + ); + + process::exit(1); +}