-
Notifications
You must be signed in to change notification settings - Fork 235
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
Allow NIX_* environment variables to be passed to rustc #466
Conversation
This is, IMO, not the right place to put this. It is far too tied to the specifics of the Nixpkgs/Rust toolchain you are using (nixpkgs? rust-overlay? mozilla's overlay? your own custom binaries? and what git versions are those?) and may become fragile if the version of Buck2's prelude and Besides all of that, nobody at Meta uses Nix for anything like this, so it will inevitably bitrot and nobody there will be able to maintain it. They won't be in a position to fix or migrate it or know when to add or remove things, or understand why and now those options may break (or help enforce!) hermeticity. It is probably something better attached to the actual toolchain definition, i.e. That's just one possible fix, though. I'm not even sure that's the best one. Really, in an ideal world, |
Yeah I am not attached to this solution at all. Something like |
I can think of three ways to go:
Now you have produced a rustc that captures the environment variables, so even if the Rust toolchain omits them, users get it back. That said, option 2 seems simple and effective? Although I'd be curious what the Rust rule authors think, e.g. @zertosh @davidbarsky |
I think that solution 3 actually leads to a more complete solution 4 which should be the real way for people to use Nix for Buck2: there should, instead of a
There are two complications:
This would mean that you do not need direnv or any other tool like I haven't really needed this myself (yet), but maybe I can try to get a working |
Is it likely that some people would want the whole Nix hermetic toolchain (which should certainly be available) and some other Nix users would want to just use direnv? If so, is doing both the proper toolchain and a hack to let NIX_ variables through worthwhile? |
As a preface, I'm on a 9 hour flight, so the amount of oxygen I have to think isn't particularly high, nor have I had a decent amount for minute. Anyways:
|
There is a The problem is with remote execution. The hermetic seal is drawn outside buck-out. Making nix-based toolchains = symlinking to /nix/store, but if you try to use such a symlink ( The I think that's the only idea that's not insane for anyone who doesn't have 10,000 developers to throw at the problem. There are 3 main alternatives, and all of them sound like pretty big undertakings.
Using a docker image with the required nix dependencies in it seems doable and doesn't require deploying and administering a bunch of servers. At least it's possible to have consistent versions and bust caches when they change. I have an improved version of I think it will also need symlinks, even dangling ones, to be preserved in buck2's |
OK, so this seems a complicated issue. It would be great to make some progress on it.
In the meantime, is some variant of whitelist all |
Update to patch required after change in facebook/buck2-prelude@9e1cfaf resulted in a merge conflict (trivial to resolve but there nonetheless). References: #2266 References: facebook/buck2#466 Signed-off-by: Fletcher Nichol <[email protected]>
The genrule approach can't work with system_rust_toolchain as-is, because it doesn't allow configuring non-working conceptYou need to use some kind of nix command to capture the environment, because the NIX_ env vars are huge (multiple kilobytes each) and quite unwieldy to paste into a genrule. # root BUCK file
genrule(
name = "nix-rustc-script",
srcs = glob([ "**/*.nix" ]) + ["flake.lock"],
bash = """
(
echo '#!/usr/bin/env bash';
nix develop . --command bash -c set \
| grep '^PATH=\|^NIX_\|^PKG_CONFIG_\|^LD_' \
| sed 's/^/export /';
echo 'exec rustc \"$@\"';
) > $OUT
chmod +x $OUT
""",
out = "rustc.sh",
)
command_alias(
name = "nix-rustc",
exe = ":nix-rustc-script",
visibility = ["toolchains//..."],
) Given that, it would be nicer to say to Nix folks (a core audience for buck) that there's a flag you can set to make it work. I would add a hack via:
|
I would not be surprised if things break, but I also know I'm not doing standard stuff. There's a small group of nix users that I'll ask at work about this, but I have the sudden, sinking feeling that I might have the most expertise on interactions between the buck rules, |
@facebook-github-bot has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
Yes, that approach is also what we have arrived at. For the cxx (nix) toolchain we create a wrapper like this: cxx = pkgs.stdenv.mkDerivation
{
name = "buck2-cxx";
dontUnpack = true;
dontCheck = true;
nativeBuildInputs = [ pkgs.makeWrapper ];
buildPhase = ''
function capture_env() {
# variables to export, all variables with names beginning with one of these are exported
local -ar vars=(
NIX_CC_WRAPPER_TARGET_HOST_
NIX_CFLAGS_COMPILE
NIX_DONT_SET_RPATH
NIX_ENFORCE_NO_NATIVE
NIX_HARDENING_ENABLE
NIX_IGNORE_LD_THROUGH_GCC
NIX_LDFLAGS
NIX_NO_SELF_RPATH
)
for prefix in "''${vars[@]}"; do
for v in $( eval 'echo "''${!'"$prefix"'@}"' ); do
echo "--set"
echo "$v"
echo "''${!v}"
done
done
}
mkdir -p "$out/bin"
for tool in ar nm objcopy ranlib strip; do
ln -st "$out/bin" "$NIX_CC/bin/$tool"
done
mapfile -t < <(capture_env)
makeWrapper "$NIX_CC/bin/$CC" "$out/bin/cc" "''${MAPFILE[@]}"
makeWrapper "$NIX_CC/bin/$CXX" "$out/bin/c++" "''${MAPFILE[@]}"
'';
}; So instead of fixing every script of the prelude that might call a nix based C/C+ compiler, capture the environment variables on the nix side and configure that as a cxx toolchain. You could also do that as part of a nix-shell / direnv setup of course. (I haven't tried this with rustc, I am assuming the rust toolchain depends on the cxx toolchain and uses whatever tools are configured) |
Summary: Otherwise if you are running buck2, and by extension rustc, from within nix any C(++) builds will fail. All credit to fnichol who pointed me to [this fix in their prelude](https://github.com/systeminit/si/blob/main/prelude/rust/tools/rustc_action.py#L262). Let me know if this fix is better applied somewhere else. X-link: facebook/buck2#466 Reviewed By: dtolnay Differential Revision: D66988964 Pulled By: IanChilds fbshipit-source-id: 09752aac79527993a10bb79523179ca2d4ff6d97
@IanChilds merged this pull request in df9cf09. |
Otherwise if you are running buck2, and by extension rustc, from within nix any C(++) builds will fail.
All credit to @fnichol who pointed me to this fix in their prelude.
Let me know if this fix is better applied somewhere else.