Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to override stdenv? #70

Closed
burdiyan opened this issue Jan 24, 2022 · 11 comments · Fixed by #177
Closed

How to override stdenv? #70

burdiyan opened this issue Jan 24, 2022 · 11 comments · Fixed by #177
Labels
question Further information is requested

Comments

@burdiyan
Copy link

I wonder if it's possible to override stdenv when using this overlay?

The problem I'm having has to do with the fact that this overlay uses propagated buildInputs in various places to propagate cc from stdenv. In the project I'm working on I use different cc, but I'm not able to override cc for this overlay no matter what I try, and it override my own cc version in my nix-shell, and everywhere else I depend on rust from this overlay.

Is there any way to override stdenv here?

@oxalica oxalica added the question Further information is requested label Jan 30, 2022
@oxalica
Copy link
Owner

oxalica commented Apr 8, 2022

The CC is used by rustc as a linker. You could set cargo configurations to overide it. The default name (gcc on Linux) seems to be fixed in rustc and is hard to patch.

@bjornfor
Copy link

Before I saw this issue, I made a wrapper derivation to work around the stdenv propagation. I haven't hit an issue yet (but who knows, is this unsafe?).

  # Create a wrapper that only exposes $pkg/bin. This prevents pulling in
  # development deps, like python interpreter + $PYTHONPATH, when adding
  # packages to a nix-shell. This is especially important when packages
  # are combined from different nixpkgs versions.
  mkBinOnlyWrapper = pkg:
    pkgs.runCommand "${pkg.pname}-${pkg.version}-bin" { inherit (pkg) meta; } ''
      mkdir -p "$out/bin"
      for bin in "${pkgs.lib.getBin pkg}/bin/"*; do
          ln -s "$bin" "$out/bin/"
      done
    '';

And then using it like this:

  nativeBuildInputs = [
    ...
    # Use mkBinOnlyWrapper to avoid propagating stdenv.cc, so we can
    # customize the stdenv with mkShell.override { stdenv = ...; }
    (mkBinOnlyWrapper rust-bin.stable."1.60.0".default)
  ];

@burdiyan
Copy link
Author

I solved this by adding another level of indirection too :)

I re-exported rust from this overlay into my own overlay, replacing the propagated dependencies like so:

rust-stable = (super.rust-bin.stable.latest.default.overrideAttrs (oldAttrs: {
    propagatedBuildInputs = [];
    depsHostHostPropagated = [];
    depsTargetTargetPropagated = [];
  }));

@steveej
Copy link

steveej commented Dec 19, 2022

@burdiyan would be great to see a full example of how that snippet fits into overriding stdenv for a rust derivation. in my case i'm trying to get buildRustPackage to use clang v14 on linux and darwin, so far something's always overriding what i'm trying to do.

@burdiyan
Copy link
Author

@steveej I'm using Nix purely for nix-shell with direnv. So I'm not actually using it for building my own derivation. So, by using the overlay snipped I posted I at least get it rust-overlay to not override the cc from the stdenv, and it seems to work for me. Actually, what I'm doing on macOS is to overwrite the cc to use the one from the system. I have an impure-cc derivation that symlinks system paths to the Nix store, and I use that as my C toolchain. It's good enough for my development environment purposes.

@steveej
Copy link

steveej commented Dec 19, 2022

thanks @burdiyan. is the final effect that cargo build will use CC from your system? do you also change something in the project's Cargo.toml? i'm asking because i see this happening in nixpkgs's build-support/rust/hook.

@burdiyan
Copy link
Author

@steveej yes, the final effect is that in my development shell the CC is exposed from my impure-cc thing, which is also what cargo build ends up using (I guess, otherwise it would pick up my system-wide toolchain, which is what I want anyway :))

@maxammann
Copy link

maxammann commented Jan 23, 2025

Hm I'm failing at applying the solution introduced with #177. I can't create a dev shell that does not override the Apple clang.

This is what I'm currently trying:

rust-bin = rust-overlay.lib.mkRustBin {  } (pkgs // { stdenv = pkgs.stdenvNoCC; });

When I add that to my packages, the path to clang changes.

Note that I don't want to recompile Rust with a different version of clang, but I want to have the system clang still available in my dev shell.

@oxalica
Copy link
Owner

oxalica commented Jan 25, 2025

Note that I don't want to recompile Rust with a different version of clang, but I want to have the system clang still available in my dev shell.

Then you don't want to "override stdenv", which means exactly the former result. (Though it may not always work because we download binaries)
If you want to prefer another compiler in dev shell, explicit write it in mkShell { nativeBuildInputs = [ rust-bin.xxx clang ]; }. I can't remember the preference order in the list, swap them if it does not work. I'm sure it is deterministic and one drv is always preferred than others.

@iniw
Copy link

iniw commented Jan 28, 2025

I'm trying to use the mkRustBin solution in the following flake:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
    flake-utils.url = "github:numtide/flake-utils";
    rust-overlay = {
      url = "github:oxalica/rust-overlay";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs =
    {
      self,
      nixpkgs,
      rust-overlay,
      flake-utils,
    }:
    flake-utils.lib.eachDefaultSystem (
      system:
      let
        pkgs = import nixpkgs { inherit system; };
        llvm = pkgs.llvmPackages_19;

        rust-bin = rust-overlay.lib.mkRustBin { } (pkgs // { stdenv = llvm.libcxxStdenv; });
        rust-toolchain = rust-bin.stable.latest.default.override {
          extensions = [
            "rust-analyzer"
            "rust-src"
          ];
        };
      in
      {
        devShells.default =
          with pkgs;
          mkShell.override { stdenv = llvm.libcxxStdenv; } {
            nativeBuildInputs = [
              # rust
              rust-toolchain

              # c++
              cmake
              ninja
              (llvm.clang-tools.override { enableLibcxx = true; })
            ];
          };
      }
    );
}

But no matter what I try it doesn't work. It always overrides $CC with clang 16.0.6 (the default for MacOS shells).

Removing rust-toolchain from nativeBuildInputs correctly gives me clang 19.1.6 on $CC.

It's perhaps worth noting that the issue doesn't occur on NixOS.

@maxammann
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants