nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 stdenv,
4 version,
5 langC,
6 langCC,
7 langJit,
8 enableShared,
9 targetPlatform,
10 hostPlatform,
11 withoutTargetLibc,
12 libcCross,
13}:
14
15assert !stdenv.targetPlatform.hasSharedLibraries -> !enableShared;
16
17drv:
18lib.pipe drv
19
20 (
21 [
22
23 (
24 pkg:
25 pkg.overrideAttrs (
26 previousAttrs:
27 lib.optionalAttrs
28 (
29 (!lib.systems.equals targetPlatform hostPlatform)
30 && (enableShared || targetPlatform.isMinGW)
31 && withoutTargetLibc
32 )
33 {
34 makeFlags = [
35 "all-gcc"
36 "all-target-libgcc"
37 ];
38 installTargets = "install-gcc install-target-libgcc";
39 }
40 )
41 )
42
43 ]
44 ++ (
45 let
46 targetPlatformSlash =
47 if lib.systems.equals hostPlatform targetPlatform then "" else "${targetPlatform.config}/";
48
49 # If we are building a cross-compiler and the target libc provided
50 # to us at build time has a libgcc, use that instead of building a
51 # new one. This avoids having two separate (but identical) libgcc
52 # outpaths in the closure of most packages, which can be confusing.
53 useLibgccFromTargetLibc = libcCross != null && libcCross ? passthru.libgcc;
54
55 enableLibGccOutput =
56 # $libgcc logic is currently hardcoded for .so
57 !stdenv.hostPlatform.isPE
58 && !stdenv.targetPlatform.isPE
59 && !langJit
60 && !stdenv.hostPlatform.isDarwin
61 && enableShared
62 && !useLibgccFromTargetLibc;
63
64 # For some reason libgcc_s.so has major-version "2" on m68k but
65 # "1" everywhere else. Might be worth changing this to "*".
66 libgcc_s-version-major = if targetPlatform.isM68k then "2" else "1";
67
68 in
69 [
70
71 (
72 pkg:
73 pkg.overrideAttrs (
74 previousAttrs:
75 lib.optionalAttrs useLibgccFromTargetLibc {
76 passthru = (previousAttrs.passthru or { }) // {
77 inherit (libcCross) libgcc;
78 };
79 }
80 )
81 )
82
83 (
84 pkg:
85 pkg.overrideAttrs (
86 previousAttrs:
87 lib.optionalAttrs ((!langC) || langJit || enableLibGccOutput) {
88 outputs = previousAttrs.outputs ++ lib.optionals enableLibGccOutput [ "libgcc" ];
89 # This is a separate phase because gcc assembles its phase scripts
90 # in bash instead of nix (we should fix that).
91 preFixupPhases =
92 (previousAttrs.preFixupPhases or [ ])
93 ++ lib.optionals ((!langC) || enableLibGccOutput) [ "preFixupLibGccPhase" ];
94 preFixupLibGccPhase =
95 # delete extra/unused builds of libgcc_s in non-langC builds
96 # (i.e. libgccjit, gnat, etc) to avoid potential confusion
97 lib.optionalString (!langC) ''
98 rm -f $out/lib/libgcc_s.so*
99 ''
100
101 # move `libgcc_s.so` into its own output, `$libgcc`
102 # We maintain $libgcc/lib/$target/ structure to make sure target
103 # strip runs over libgcc_s.so and remove debug references to headers:
104 # https://github.com/NixOS/nixpkgs/issues/316114
105 + lib.optionalString enableLibGccOutput (
106 ''
107 # move libgcc from lib to its own output (libgcc)
108 mkdir -p $libgcc/${targetPlatformSlash}lib
109 mv $lib/${targetPlatformSlash}lib/libgcc_s.so $libgcc/${targetPlatformSlash}lib/
110 mv $lib/${targetPlatformSlash}lib/libgcc_s.so.${libgcc_s-version-major} $libgcc/${targetPlatformSlash}lib/
111 ln -s $libgcc/${targetPlatformSlash}lib/libgcc_s.so $lib/${targetPlatformSlash}lib/
112 ln -s $libgcc/${targetPlatformSlash}lib/libgcc_s.so.${libgcc_s-version-major} $lib/${targetPlatformSlash}lib/
113 ''
114 + lib.optionalString (targetPlatformSlash != "") ''
115 ln -s ${targetPlatformSlash}lib $libgcc/lib
116 ''
117 #
118 # Nixpkgs ordinarily turns dynamic linking into pseudo-static linking:
119 # libraries are still loaded dynamically, exactly which copy of each
120 # library is loaded is permanently fixed at compile time (via RUNPATH).
121 # For libgcc_s we must revert to the "impure dynamic linking" style found
122 # in imperative software distributions. We must do this because
123 # `libgcc_s` calls `malloc()` and therefore has a `DT_NEEDED` for `libc`,
124 # which creates two problems:
125 #
126 # 1. A circular package dependency `glibc`<-`libgcc`<-`glibc`
127 #
128 # 2. According to the `-Wl,-rpath` flags added by Nixpkgs' `ld-wrapper`,
129 # the two versions of `glibc` in the cycle above are actually
130 # different packages. The later one is compiled by this `gcc`, but
131 # the earlier one was compiled by the compiler *that compiled* this
132 # `gcc` (usually the bootstrapFiles). In any event, the `glibc`
133 # dynamic loader won't honor that specificity without namespaced
134 # manual loads (`dlmopen()`). Once a `libc` is present in the address
135 # space of a process, that `libc` will be used to satisfy all
136 # `DT_NEEDED`s for `libc`, regardless of `RUNPATH`s.
137 #
138 # So we wipe the RUNPATH using `patchelf --set-rpath ""`. We can't use
139 # `patchelf --remove-rpath`, because at least as of patchelf 0.15.0 it
140 # will leave the old RUNPATH string in the file where the reference
141 # scanner can still find it:
142 #
143 # https://github.com/NixOS/patchelf/issues/453
144 #
145 # Note: we might be using the bootstrapFiles' copy of patchelf, so we have
146 # to keep doing it this way until both the issue is fixed *and* all the
147 # bootstrapFiles are regenerated, on every platform.
148 #
149 # This patchelfing is *not* effectively equivalent to copying
150 # `libgcc_s` into `glibc`'s outpath. There is one minor and one
151 # major difference:
152 #
153 # 1. (Minor): multiple builds of `glibc` (say, with different
154 # overrides or parameters) will all reference a single store
155 # path:
156 #
157 # /nix/store/xxx...xxx-gcc-libgcc/lib/libgcc_s.so.1
158 #
159 # This many-to-one referrer relationship will be visible in the store's
160 # dependency graph, and will be available to `nix-store -q` queries.
161 # Copying `libgcc_s` into each of its referrers would lose that
162 # information.
163 #
164 # 2. (Major): by referencing `libgcc_s.so.1`, rather than copying it, we
165 # are still able to run `nix-store -qd` on it to find out how it got
166 # built! Most importantly, we can see from that deriver which compiler
167 # was used to build it (or if it is part of the unpacked
168 # bootstrap-files). Copying `libgcc_s.so.1` from one outpath to
169 # another eliminates the ability to make these queries.
170 #
171 + ''
172 patchelf --set-rpath "" $libgcc/lib/libgcc_s.so.${libgcc_s-version-major}
173 ''
174 );
175 }
176 )
177 )
178 ]
179 )
180 )