Skip to content

cc-wrapper: Hygiene and set -u#27672

Merged
Ericson2314 merged 5 commits intoNixOS:stagingfrom
obsidiansystems:cc-wrapper-elegant
Aug 7, 2017
Merged

cc-wrapper: Hygiene and set -u#27672
Ericson2314 merged 5 commits intoNixOS:stagingfrom
obsidiansystems:cc-wrapper-elegant

Conversation

@Ericson2314
Copy link
Member

@Ericson2314 Ericson2314 commented Jul 26, 2017

Motivation for this change

For cross compilation, we need to have multiple cc-wrappers in use at once (usually so we can generate built-tools on the fly along with building the derivation itself). But cc-wrapper leaks a bunch of environment variables in its setup hook to be picked up by the wrapper scripts, so multiple cc-wrappers would stomp all over each other. The hack solution to that alone is simple---make sure the two cc-wrapper don't use the same identifiers, which ${infixSalt} accomplishes.

The catch is that many derivations try to mess with this process by modifying those variables. I specially modified the setup hook to pick up "unsalted" environment variables from derivation itself (or an earlier setup hook...yikes), but derivations (like glibc; see the last commit) also inject bash to modify these too. git grep 'export NIX_' can give one a scale of this. I do not yet have a general solution for how not to break these packages...

...Now I do. I do the conversion in add-flags instead. Also, normal host-platform-targetting env vars keep their existing notation, so this (at least by the standards of my recent PRs :D) is highly backwards compatible. The only semantics change I remember off-hand is that the START_HOOKs are now evaluated after add-flags.sh, but those are probably dead code---unused in nixpkgs at least.

This is best reviewed commit-by-commit, as some commits are basically seddish and bump up the diff count. Also start with #27879

[Longer term, instead of an unconditional envHook, I'd like to use pkg-config. By default, cc-wrapper will inject the appropriate pkg-config invocations, but this can be disabled per-derivation. Derivations like glibc that want to be tricky instead call it or do a deferred injection themselves.]

Things done

Please check what applies. Note that these are not hard requirements but merely serve as information for reviewers.

  • Tested using sandboxing
    (nix.useSandbox on NixOS,
    or option build-use-sandbox in nix.conf
    on non-NixOS)
  • Built stdenv on platform(s)
    • NixOS
    • macOS
    • Linux
  • Evaluated all of nixpkgs
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Fits CONTRIBUTING.md.

CC @orivej, as you have been working on this a fair amount lately.

@Ericson2314 Ericson2314 added 6.topic: cross-compilation Building packages on a different platform than they will be used on 9.needs: community feedback This needs feedback from more community members. labels Jul 26, 2017
@Ericson2314 Ericson2314 requested review from LnL7 and edolstra July 26, 2017 23:15
@Ericson2314 Ericson2314 mentioned this pull request Jul 26, 2017
13 tasks
@cstrahan
Copy link
Contributor

@Ericson2314 If I'm reading this correctly, won't this cause problems where we use e.g. NIX_LDFLAGS=$NIX_LDFLAGS:$etc_etc_etc within a phase, and ditto for within a nix-shell?

Your slurpUnsalted would, I think, only catch stuff that was defined within the derivation's environment (e.g. set directly as one of the attrs within a call to mkDerivation).

@Ericson2314
Copy link
Member Author

Ericson2314 commented Jul 27, 2017

@cstrahan Indeed that is exactly the flaw I'm worried about. I'm not sure what to do about that, considering the order of flags does matter.

Copy link
Member

@LnL7 LnL7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm probably missing something. But wouldn't the issues with setting NIX_*FLAGS during a build be solved by having the wrappers look at both the salted and unsalted versions of the environment variables?

@Ericson2314
Copy link
Member Author

@LnL7 Just saw. Well non-nativeBuildInput (which is where stdenv.cc is injected) cc-wrapper should not ignore those flags. But I think I have a solution.

  1. The setup hook will keep a "set" off the rolls the specific cc-wrapper is used in. Something like:

    if isPreNativeBuildInput; NIX_CC_WRAPPER_${salt}_ROLE+=("BUILD_"); fi
    if isNativeBuildInput; NIX_CC_WRAPPER_${salt}_ROLE+=(""); fi
    if isBuildInput; NIX_CC_WRAPPER_${salt}_ROLE+=("TARGET_"); fi
    

    N.B. These conditions will be faked with crossConfig like this PR until Make cross compilation elegant #26805

  2. The env hook (for-each-ed on each dep) will append to the role-specific, not salt-specific names (e.g. NIX_TARGET_CFLAGS_COMPILE). Since the setup hook is run for each included cc-wrapper dep, it still only works on one sort of dependency at a time (not all roles).

  3. add-flags.sh will iterate through NIX_CC_WRAPPER_${salt}_ROLE and agglomerate in non-exported camel-case names.

  4. The wrapper scripts will only use the camel-case names.

@Ericson2314 Ericson2314 force-pushed the cc-wrapper-elegant branch 4 times, most recently from 970c819 to 52f2f3a Compare August 3, 2017 22:03
@Ericson2314 Ericson2314 changed the title Quasi-hygiene for CC-wrapper Quasi-hygiene and set -u for CC-wrapper Aug 3, 2017
@Ericson2314 Ericson2314 requested a review from grahamc August 3, 2017 23:05
@Ericson2314 Ericson2314 changed the title Quasi-hygiene and set -u for CC-wrapper Hygiene and set -u for CC-wrapper Aug 3, 2017
@Ericson2314
Copy link
Member Author

OK! Rewrote this sort of as described. Probably best to review commit-by-commit as some commits are noisy but borring. set -u compliance helps demonstrate correctness (e.g. won't be forgetting to convert a env var so easily).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why SC2016?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question....

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah it used to say $hardeningDisabled or whatever

@Ericson2314 Ericson2314 changed the title Hygiene and set -u for CC-wrapper ccwrapper: Hygiene and set -u Aug 4, 2017
@Ericson2314 Ericson2314 changed the title ccwrapper: Hygiene and set -u cc-wrapper: Hygiene and set -u Aug 4, 2017
Copy link
Member

@grahamc grahamc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely palindromic PR #

Generally looks fine, but I admit to not being really familiar with stdenv and the various things we do with it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add some more info to this comment as to what it means, for future archeologists?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm you sure?

[grahamc@Morbo:~]$ declare -i n=0

[grahamc@Morbo:~]$ i+=1

[grahamc@Morbo:~]$ echo $i
1

[grahamc@Morbo:~]$ i+=1

[grahamc@Morbo:~]$ echo $i
11

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same "are you sure?"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice rename

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm not sure why we're keeping this

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know anything about gnat --- I'd figure I'd at least keep the comment up to date?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

@Ericson2314 Ericson2314 force-pushed the cc-wrapper-elegant branch 4 times, most recently from 90be90b to 8c8f87f Compare August 4, 2017 18:55
This is an ugly temp hack for cross compilation, but now we have something better on the way.

Bind `infixSalt` as an environment variable as it will be used in it.
This is basically a sed job, in preparation of the next commit. The
rules are more or less:

  - s"NIX_(.._WRAPPER_)?([a-zA-Z0-9@]*)"NIX_\1@infixSalt@_\2"g

  - except for non-cc-wrapper-specific vars like `NIX_DEBUG`
See the added comments for what exactly has been done.
Now is an opportune time to do this, as the infixSalt conversion in
`add-flags.sh` ensures that all the relevant `NIX_*` vars will be
defined even if empty.
@Ericson2314 Ericson2314 merged commit b949f30 into NixOS:staging Aug 7, 2017
@Ericson2314 Ericson2314 deleted the cc-wrapper-elegant branch August 7, 2017 07:09
@Ericson2314
Copy link
Member Author

Rebased just to get rid of merge conflict with my macOS Sierra linking hack---just a nix conflict no hashes were affected so my old builds are still valid.

@FRidh
Copy link
Member

FRidh commented Aug 7, 2017

This broke postgresql https://hydra.nixos.org/build/58192157.

@orivej
Copy link
Contributor

orivej commented Aug 7, 2017

Postgresql ./configure is broken because /nix/store/…-glibc-2.25/lib/librt.so.1 has /nix/store/…-bootstrap-glibc/lib in its RUNPATH; previously it had no RUNPATH. This may happen if NIX_DONT_SET_RPATH is not respected…

@Ericson2314
Copy link
Member Author

Very weird---https://github.com/NixOS/nixpkgs/pull/27672/files#diff-ae6d7fc8f1059168bd391972ef177c31R70 should do the trick. When developing this, a lack of respecting that up caused the Linux stdenv to fail to build at all, so the current issue must be especially subtle.

Also, I'm fine reverting this, especially as the next cross PR won't be ready for a while.

@FRidh
Copy link
Member

FRidh commented Aug 7, 2017

Some fragments from config.log.

configure:13164: result: failed
configure:13166: error:
Could not execute a simple test program.  This may be a problem
related to locating shared libraries.  Check the file 'config.log'
for the exact reason.
configure:3847: $? = 0
configure:3836: gcc -v >&5
Using built-in specs.
COLLECT_GCC=/nix/store/3vicjdaxfvcfz3nvc8wghp31n22rflq1-gcc-5.4.0/bin/gcc
COLLECT_LTO_WRAPPER=/nix/store/3vicjdaxfvcfz3nvc8wghp31n22rflq1-gcc-5.4.0/libexec/gcc/x86_64-unknown-linux-gnu/5.4.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with:
Thread model: posix
gcc version 5.4.0 (GCC)
configure:3847: $? = 0
configure:3836: gcc -V >&5
gcc: error: unrecognized command line option '-V'
gcc: fatal error: no input files
compilation terminated.
configure:3847: $? = 1
configure:3836: gcc -qversion >&5
gcc: error: unrecognized command line option '-qversion'
gcc: fatal error: no input files

That reminds me of #27940 where export LD=$CXX became necessary. I don't know what caused that.

@FRidh
Copy link
Member

FRidh commented Aug 7, 2017

@Ericson2314 if you don't think you will be able to fix this before the next staging evaluation, then I recommend reverting these changes.

@Ericson2314
Copy link
Member Author

@FRidh Found it. The problem is very silly; I slurped NIX_DONT_SET_RPATH twice so it gets defined as 1 1.

(For cross I'll eventually need to have a different monoid for these numeric env vars, but for native it suffices to just stop slurping twice.)

@Ericson2314
Copy link
Member Author

Fixed in 810fb0c

@orivej
Copy link
Contributor

orivej commented Aug 7, 2017

@Ericson2314 It seems that this pull request broke standalone gcc, ld:

$ /nix/store/…-gcc-wrapper-5.4.0/bin/gcc
/nix/store/…-gcc-wrapper-5.4.0/nix-support/add-flags.sh: line 75: NIX_x86_64_unknown_linux_gnu_CFLAGS_COMPILE: unbound variable

@Ericson2314
Copy link
Member Author

Ah, that's unfortunate. It's because in the case that no "role" is defined, none of those variables get set. We should come up with some sane defaults for that case (all empty would probably be backwards compatible).

@globin With the LLVM test failure you found, it's possible the environment has been cleaned somehow, leading to the roles being undefined.

@orivej
Copy link
Contributor

orivej commented Aug 7, 2017

It appears that LLVM tests sanitize the environment for programs they run during the test. (llvm/test/tools/llvm-symbolizer/print_context.c attempts to run

// RUN: %host_cc -O0 -g %s -o %t 2>&1
// RUN: %t 2>&1 | llvm-symbolizer -print-source-context-lines=5 -obj=%t | FileCheck %s

where %host_cc expands to /nix/store/…-gcc-wrapper-5.4.0/bin/gcc.)
Restoring support for standalone gcc will fix that.

@globin
Copy link
Member

globin commented Aug 7, 2017

Yep, working on it, give me a bit

image

@dezgeg
Copy link
Contributor

dezgeg commented Aug 8, 2017

Um, why is this infixSalt stuff needed at all, can't cc-wrapper.sh just directly use the 'role' variables like NIX_BUILD_CFLAGS_COMPILE?

@Ericson2314
Copy link
Member Author

Ericson2314 commented Aug 8, 2017

I tried to describe it in the code comment: then we can't get away with platform-tool and need something nonstandard like role-tool instead.

@dezgeg
Copy link
Contributor

dezgeg commented Aug 11, 2017

Sure, the names of the wrapped tools being after the platform triplet is fine, I just don't understand the need for the @infixSalt@ environment variables. Doesn't it just add possibilities for getting things mixed up if you happen to be cross compiling to something that is different from the native platform but maps to the same platform triplet? (E.g. ARM with some different FPU/ABI configurations or maybe baremetal stuff like http://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler%3F someone was asking on IRC)

@Ericson2314
Copy link
Member Author

@dezgeg We could use a hash of targetPlatform, or a hash of the entire cc-wrapper, instead. But unless we also likewise change the binary prefix, those two cc-wrappers will clobber each other on the PATH anyways.

I'm open to doing that or similar, though. What would you prefer?

@globin globin added this to the 17.09 milestone Aug 11, 2017
@globin globin added the 9.needs: changelog This PR needs a changelog entry label Aug 11, 2017
abbradar added a commit that referenced this pull request Oct 16, 2017
fi
# Easiest to just do this to deal with either the input or (old) output.
set +u
export ${outputVar}+="${delimiter}${!inputVar}"
Copy link
Contributor

@eddyb eddyb Jul 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to be setting the variables unconditionally, which broke #6688 (standalone clang++). I'm not sure what the exact interactions here are but nix run nixpkgs.clang can't find the C++ standard library headers and I've tracked it down to this variable assignment.

Copy link
Contributor

@eddyb eddyb Jul 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably the right fix is to use ${NIX_CXXSTDLIB_COMPILE:-@default_cxx_stdlib_compile@} instead of ${NIX_CXXSTDLIB_COMPILE-@default_cxx_stdlib_compile@}, in cc-wrapper.sh to treat the empty variable the same way as if it was uninitialized, IIRC.

EDIT: opened as #44221.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: cross-compilation Building packages on a different platform than they will be used on 9.needs: changelog This PR needs a changelog entry 9.needs: community feedback This needs feedback from more community members.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants