nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{ lib
2, stdenv
3, langC
4, langCC
5, langJit
6}:
7
8let
9 enableLibGccOutput =
10 (with stdenv; targetPlatform == hostPlatform) &&
11 !langJit &&
12 !stdenv.hostPlatform.isDarwin &&
13 !stdenv.hostPlatform.isStatic;
14in
15(pkg: pkg.overrideAttrs (previousAttrs: lib.optionalAttrs ((!langC) || langJit || enableLibGccOutput) {
16 outputs = previousAttrs.outputs ++ lib.optionals enableLibGccOutput [ "libgcc" ];
17 # This is a separate phase because gcc assembles its phase scripts
18 # in bash instead of nix (we should fix that).
19 preFixupPhases = (previousAttrs.preFixupPhases or []) ++ lib.optionals ((!langC) || enableLibGccOutput) [ "preFixupLibGccPhase" ];
20 preFixupLibGccPhase =
21 # delete extra/unused builds of libgcc_s in non-langC builds
22 # (i.e. libgccjit, gnat, etc) to avoid potential confusion
23 lib.optionalString (!langC) ''
24 rm -f $out/lib/libgcc_s.so*
25 ''
26
27 # TODO(amjoseph): remove the `libgcc_s.so` symlinks below and replace them
28 # with a `-L${gccForLibs.libgcc}/lib` in cc-wrapper's
29 # `$out/nix-support/cc-flags`. See also:
30 # - https://github.com/NixOS/nixpkgs/pull/209870#discussion_r1130614895
31 # - https://github.com/NixOS/nixpkgs/pull/209870#discussion_r1130635982
32 # - https://github.com/NixOS/nixpkgs/commit/404155c6acfa59456aebe6156b22fe385e7dec6f
33 #
34 # move `libgcc_s.so` into its own output, `$libgcc`
35 + lib.optionalString enableLibGccOutput (''
36 # move libgcc from lib to its own output (libgcc)
37 mkdir -p $libgcc/lib
38 mv $lib/lib/libgcc_s.so $libgcc/lib/
39 mv $lib/lib/libgcc_s.so.1 $libgcc/lib/
40 ln -s $libgcc/lib/libgcc_s.so $lib/lib/
41 ln -s $libgcc/lib/libgcc_s.so.1 $lib/lib/
42 ''
43 #
44 # Nixpkgs ordinarily turns dynamic linking into pseudo-static linking:
45 # libraries are still loaded dynamically, exactly which copy of each
46 # library is loaded is permanently fixed at compile time (via RUNPATH).
47 # For libgcc_s we must revert to the "impure dynamic linking" style found
48 # in imperative software distributions. We must do this because
49 # `libgcc_s` calls `malloc()` and therefore has a `DT_NEEDED` for `libc`,
50 # which creates two problems:
51 #
52 # 1. A circular package dependency `glibc`<-`libgcc`<-`glibc`
53 #
54 # 2. According to the `-Wl,-rpath` flags added by Nixpkgs' `ld-wrapper`,
55 # the two versions of `glibc` in the cycle above are actually
56 # different packages. The later one is compiled by this `gcc`, but
57 # the earlier one was compiled by the compiler *that compiled* this
58 # `gcc` (usually the bootstrapFiles). In any event, the `glibc`
59 # dynamic loader won't honor that specificity without namespaced
60 # manual loads (`dlmopen()`). Once a `libc` is present in the address
61 # space of a process, that `libc` will be used to satisfy all
62 # `DT_NEEDED`s for `libc`, regardless of `RUNPATH`s.
63 #
64 # So we wipe the RUNPATH using `patchelf --set-rpath ""`. We can't use
65 # `patchelf --remove-rpath`, because at least as of patchelf 0.15.0 it
66 # will leave the old RUNPATH string in the file where the reference
67 # scanner can still find it:
68 #
69 # https://github.com/NixOS/patchelf/issues/453
70 #
71 # Note: we might be using the bootstrapFiles' copy of patchelf, so we have
72 # to keep doing it this way until both the issue is fixed *and* all the
73 # bootstrapFiles are regenerated, on every platform.
74 #
75 # This patchelfing is *not* effectively equivalent to copying
76 # `libgcc_s` into `glibc`'s outpath. There is one minor and one
77 # major difference:
78 #
79 # 1. (Minor): multiple builds of `glibc` (say, with different
80 # overrides or parameters) will all reference a single store
81 # path:
82 #
83 # /nix/store/xxx...xxx-gcc-libgcc/lib/libgcc_s.so.1
84 #
85 # This many-to-one referrer relationship will be visible in the store's
86 # dependency graph, and will be available to `nix-store -q` queries.
87 # Copying `libgcc_s` into each of its referrers would lose that
88 # information.
89 #
90 # 2. (Major): by referencing `libgcc_s.so.1`, rather than copying it, we
91 # are still able to run `nix-store -qd` on it to find out how it got
92 # built! Most importantly, we can see from that deriver which compiler
93 # was used to build it (or if it is part of the unpacked
94 # bootstrap-files). Copying `libgcc_s.so.1` from one outpath to
95 # another eliminates the ability to make these queries.
96 #
97 + ''
98 patchelf --set-rpath "" $libgcc/lib/libgcc_s.so.1
99 '');
100}))