about summary refs log tree commit diff
path: root/pkgs/build-support
diff options
context:
space:
mode:
authorVladimír Čunát <v@cunat.cz>2022-10-14 09:33:15 +0200
committerVladimír Čunát <v@cunat.cz>2022-10-14 09:40:48 +0200
commitd700d8e8a26427388cbe59149232ee104cf36644 (patch)
tree22473f3b8d9a2a5ca26bafb25e938e35744dadc5 /pkgs/build-support
parent283841a1ced498defb814c0404104b28052e38a9 (diff)
stdenv cc-wrapper: revert a problematic change for non-Linux
The change from 0bea4a194f71 (PR #191724) broke stdenv bootstap
on *-darwin, and I didn't want to drop the *-linux binaries
that we have already.
Diffstat (limited to 'pkgs/build-support')
-rw-r--r--pkgs/build-support/cc-wrapper/default.nix4
-rw-r--r--pkgs/build-support/cc-wrapper/setup-hook-nonlinux.sh120
2 files changed, 123 insertions, 1 deletions
diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix
index 14cd1d4313916..f199b1d7e2476 100644
--- a/pkgs/build-support/cc-wrapper/default.nix
+++ b/pkgs/build-support/cc-wrapper/default.nix
@@ -274,7 +274,9 @@ stdenv.mkDerivation {
 
   setupHooks = [
     ../setup-hooks/role.bash
-  ] ++ lib.optional (cc.langC or true) ./setup-hook.sh
+  ] ++ lib.optional (cc.langC or true)
+        # Temporary hack; see https://github.com/NixOS/nixpkgs/pull/191724#issuecomment-1278602576
+        (if stdenv.isLinux then ./setup-hook.sh else ./setup-hook-nonlinux.sh)
     ++ lib.optional (cc.langFortran or false) ./fortran-hook.sh;
 
   postFixup =
diff --git a/pkgs/build-support/cc-wrapper/setup-hook-nonlinux.sh b/pkgs/build-support/cc-wrapper/setup-hook-nonlinux.sh
new file mode 100644
index 0000000000000..6a913cc4eac72
--- /dev/null
+++ b/pkgs/build-support/cc-wrapper/setup-hook-nonlinux.sh
@@ -0,0 +1,120 @@
+# CC Wrapper hygiene
+#
+# For at least cross compilation, we need to depend on multiple cc-wrappers at
+# once---specifically up to one per sort of dependency. This follows from having
+# different tools targeting different platforms, and different flags for those
+# tools. For example:
+#
+#   # Flags for compiling (whether or not linking) C code for the...
+#   NIX_CFLAGS_COMPILE_FOR_BUILD  # ...build platform
+#   NIX_CFLAGS_COMPILE            # ...host platform
+#   NIX_CFLAGS_COMPILE_FOR_TARGET # ...target platform
+#
+# Notice that these platforms are the 3 *relative* to the package using
+# cc-wrapper, not absolute like `x86_64-pc-linux-gnu`.
+#
+# The simplest solution would be to have separate cc-wrappers per (3 intended
+# use-cases * n absolute concrete platforms). For the use-case axis, we would
+# @-splice in 'BUILD_' '' 'TARGET_' to use the write environment variables when
+# building the cc-wrapper, and likewise prefix the binaries' names so they didn't
+# clobber each other on the PATH. But the need for 3x cc-wrappers, along with
+# non-standard name prefixes, is annoying and liable to break packages' build
+# systems.
+#
+# Instead, we opt to have just one cc-wrapper per absolute platform. Matching
+# convention, the binaries' names can just be prefixed with their target
+# platform. On the other hand, that means packages will depend on not just
+# multiple cc-wrappers, but the exact same cc-wrapper derivation multiple ways.
+# That means the exact same cc-wrapper derivation must be able to avoid
+# conflicting with itself, despite the fact that `setup-hook.sh`, the `addCvars`
+# function, and `add-flags.sh` are all communicating with each other with
+# environment variables. Yuck.
+#
+# The basic strategy is:
+#
+#  - Everyone exclusively *adds information* to relative-platform-specific
+#    environment variables, like `NIX_CFLAGS_COMPILE_FOR_TARGET`, to communicate
+#    with the wrapped binaries.
+#
+#  - The wrapped binaries will exclusively *read* cc-wrapper-derivation-specific
+#    environment variables distinguished with with `suffixSalt`, like
+#    `NIX_CFLAGS_COMPILE_@suffixSalt@`.
+#
+#  - `add-flags`, beyond its old task of reading extra flags stuck inside the
+#    cc-wrapper derivation, will convert the relative-platform-specific
+#    variables to cc-wrapper-derivation-specific variables. This conversion is
+#    the only time all but one of the cc-wrapper-derivation-specific variables
+#    are set.
+#
+# This ensures the flow of information is exclusive from
+# relative-platform-specific variables to cc-wrapper-derivation-specific
+# variables. This allows us to support the general case of a many--many relation
+# between relative platforms and cc-wrapper derivations.
+#
+# For more details, read the individual files where the mechanisms used to
+# accomplish this will be individually documented.
+
+# Skip setup hook if we're neither a build-time dep, nor, temporarily, doing a
+# native compile.
+#
+# TODO(@Ericson2314): No native exception
+[[ -z ${strictDeps-} ]] || (( "$hostOffset" < 0 )) || return 0
+
+# It's fine that any other cc-wrapper will redefine this. Bash functions close
+# over no state, and there's no @-substitutions within, so any redefined
+# function is guaranteed to be exactly the same.
+ccWrapper_addCVars () {
+    # See ../setup-hooks/role.bash
+    local role_post
+    getHostRoleEnvHook
+
+    if [ -d "$1/include" ]; then
+        export NIX_CFLAGS_COMPILE${role_post}+=" -isystem $1/include"
+    fi
+
+    if [ -d "$1/Library/Frameworks" ]; then
+        export NIX_CFLAGS_COMPILE${role_post}+=" -iframework $1/Library/Frameworks"
+    fi
+}
+
+# See ../setup-hooks/role.bash
+getTargetRole
+getTargetRoleWrapper
+
+# We use the `targetOffset` to choose the right env hook to accumulate the right
+# sort of deps (those with that offset).
+addEnvHooks "$targetOffset" ccWrapper_addCVars
+
+# Note 1: these come *after* $out in the PATH (see setup.sh).
+# Note 2: phase separation makes this look useless to shellcheck.
+
+# shellcheck disable=SC2157
+if [ -n "@cc@" ]; then
+    addToSearchPath _PATH @cc@/bin
+fi
+
+# shellcheck disable=SC2157
+if [ -n "@libc_bin@" ]; then
+    addToSearchPath _PATH @libc_bin@/bin
+fi
+
+# shellcheck disable=SC2157
+if [ -n "@coreutils_bin@" ]; then
+    addToSearchPath _PATH @coreutils_bin@/bin
+fi
+
+# Export tool environment variables so various build systems use the right ones.
+
+export NIX_CC${role_post}=@out@
+
+export CC${role_post}=@named_cc@
+export CXX${role_post}=@named_cxx@
+export CC${role_post}=@named_cc@
+export CXX${role_post}=@named_cxx@
+
+# If unset, assume the default hardening flags.
+: ${NIX_HARDENING_ENABLE="fortify stackprotector pic strictoverflow format relro bindnow"}
+export NIX_HARDENING_ENABLE
+
+# No local scope in sourced file
+unset -v role_post