1{ lib, stdenv, targetPackages, fetchurl, fetchpatch, fetchFromGitHub, noSysDirs
2, langC ? true, langCC ? true, langFortran ? false
3, langAda ? false
4, langObjC ? stdenv.targetPlatform.isDarwin
5, langObjCpp ? stdenv.targetPlatform.isDarwin
6, langD ? false
7, langGo ? false
8, reproducibleBuild ? true
9, profiledCompiler ? false
10, langJit ? false
11, staticCompiler ? false
12, enableShared ? stdenv.targetPlatform.hasSharedLibraries
13, enableLTO ? stdenv.hostPlatform.hasSharedLibraries
14, texinfo ? null
15, perl ? null # optional, for texi2pod (then pod2man)
16, gmp, mpfr, libmpc, gettext, which, patchelf, binutils
17, isl ? null # optional, for the Graphite optimization framework.
18, zlib ? null
19, libucontext ? null
20, gnat-bootstrap ? null
21, enableMultilib ? false
22, enablePlugin ? stdenv.hostPlatform == stdenv.buildPlatform # Whether to support user-supplied plug-ins
23, name ? "gcc"
24, libcCross ? null
25, threadsCross ? null # for MinGW
26, withoutTargetLibc ? false
27, gnused ? null
28, cloog # unused; just for compat with gcc4, as we override the parameter on some places
29, buildPackages
30, pkgsBuildTarget
31, libxcrypt
32, disableGdbPlugin ? !enablePlugin || (stdenv.targetPlatform.isAvr && stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64)
33, nukeReferences
34, callPackage
35, majorMinorVersion
36, cctools
37, darwin
38
39# only for gcc<=6.x
40, langJava ? false
41, flex
42, boehmgc ? null
43, zip ? null, unzip ? null, pkg-config ? null
44, gtk2 ? null, libart_lgpl ? null
45, libX11 ? null, libXt ? null, libSM ? null, libICE ? null, libXtst ? null
46, libXrender ? null, xorgproto ? null
47, libXrandr ? null, libXi ? null
48, x11Support ? langJava
49}:
50
51let
52 inherit (lib)
53 callPackageWith
54 filter
55 getBin
56 maintainers
57 makeLibraryPath
58 makeSearchPathOutput
59 mapAttrs
60 optional
61 optionalAttrs
62 optionals
63 optionalString
64 pipe
65 platforms
66 versionAtLeast
67 versions
68 ;
69
70 gccVersions = import ./versions.nix;
71 version = gccVersions.fromMajorMinor majorMinorVersion;
72
73 majorVersion = versions.major version;
74 atLeast14 = versionAtLeast version "14";
75 atLeast13 = versionAtLeast version "13";
76 atLeast12 = versionAtLeast version "12";
77 atLeast11 = versionAtLeast version "11";
78 atLeast10 = versionAtLeast version "10";
79 atLeast9 = versionAtLeast version "9";
80 atLeast8 = versionAtLeast version "8";
81 atLeast7 = versionAtLeast version "7";
82 atLeast6 = versionAtLeast version "6";
83 atLeast49 = versionAtLeast version "4.9";
84 is14 = majorVersion == "14";
85 is13 = majorVersion == "13";
86 is12 = majorVersion == "12";
87 is11 = majorVersion == "11";
88 is10 = majorVersion == "10";
89 is9 = majorVersion == "9";
90 is8 = majorVersion == "8";
91 is7 = majorVersion == "7";
92 is6 = majorVersion == "6";
93 is49 = majorVersion == "4" && versions.minor version == "9";
94 is48 = majorVersion == "4" && versions.minor version == "8";
95
96 disableBootstrap = atLeast11 && !stdenv.hostPlatform.isDarwin && (atLeast12 -> !profiledCompiler);
97
98 inherit (stdenv) buildPlatform hostPlatform targetPlatform;
99 targetConfig = if targetPlatform != hostPlatform then targetPlatform.config else null;
100
101 patches = callFile ./patches {};
102
103 /* Cross-gcc settings (build == host != target) */
104 crossMingw = targetPlatform != hostPlatform && targetPlatform.isMinGW;
105 stageNameAddon = optionalString withoutTargetLibc "-nolibc";
106 crossNameAddon = optionalString (targetPlatform != hostPlatform) "${targetPlatform.config}${stageNameAddon}-";
107
108 javaAwtGtk = langJava && x11Support;
109 xlibs = [
110 libX11 libXt libSM libICE libXtst libXrender libXrandr libXi
111 xorgproto
112 ];
113 callFile = callPackageWith ({
114 # lets
115 inherit
116 majorVersion
117 version
118 buildPlatform
119 hostPlatform
120 targetPlatform
121 targetConfig
122 patches
123 crossMingw
124 stageNameAddon
125 crossNameAddon
126 ;
127 # inherit generated with 'nix eval --json --impure --expr "with import ./. {}; lib.attrNames (lib.functionArgs gcc${majorVersion}.cc.override)" | jq '.[]' --raw-output'
128 inherit
129 binutils
130 buildPackages
131 cloog
132 withoutTargetLibc
133 darwin
134 disableBootstrap
135 disableGdbPlugin
136 enableLTO
137 enableMultilib
138 enablePlugin
139 enableShared
140 fetchpatch
141 fetchurl
142 gettext
143 gmp
144 gnat-bootstrap
145 gnused
146 isl
147 langAda
148 langC
149 langCC
150 langD
151 langFortran
152 langGo
153 langJit
154 langObjC
155 langObjCpp
156 lib
157 libcCross
158 libmpc
159 libucontext
160 libxcrypt
161 mpfr
162 name
163 noSysDirs
164 nukeReferences
165 patchelf
166 perl
167 pkgsBuildTarget
168 profiledCompiler
169 reproducibleBuild
170 staticCompiler
171 stdenv
172 targetPackages
173 texinfo
174 threadsCross
175 which
176 zip
177 zlib
178 ;
179 } // optionalAttrs (!atLeast7) {
180 inherit
181 boehmgc
182 flex
183 gnat-bootstrap
184 gtk2
185 langAda
186 langJava
187 libICE
188 libSM
189 libX11
190 libXi
191 libXrandr
192 libXrender
193 libXt
194 libXtst
195 libart_lgpl
196 pkg-config
197 unzip
198 x11Support
199 xorgproto
200 javaAwtGtk
201 xlibs
202 ;
203 javaEcj = fetchurl {
204 # The `$(top_srcdir)/ecj.jar' file is automatically picked up at
205 # `configure' time.
206
207 # XXX: Eventually we might want to take it from upstream.
208 url = "ftp://sourceware.org/pub/java/ecj-4.3.jar";
209 sha256 = "0jz7hvc0s6iydmhgh5h2m15yza7p2rlss2vkif30vm9y77m97qcx";
210 };
211
212 # Antlr (optional) allows the Java `gjdoc' tool to be built. We want a
213 # binary distribution here to allow the whole chain to be bootstrapped.
214 javaAntlr = fetchurl {
215 url = "https://www.antlr.org/download/antlr-4.4-complete.jar";
216 sha256 = "02lda2imivsvsis8rnzmbrbp8rh1kb8vmq4i67pqhkwz7lf8y6dz";
217 };
218 });
219
220in
221
222# We enable the isl cloog backend.
223assert !atLeast6 -> (cloog != null -> isl != null);
224
225assert langJava -> !atLeast7 && zip != null && unzip != null && zlib != null && boehmgc != null && perl != null; # for `--enable-java-home'
226
227# Make sure we get GNU sed.
228assert stdenv.buildPlatform.isDarwin -> gnused != null;
229
230# The go frontend is written in c++
231assert langGo -> langCC;
232assert (atLeast6 && !is7 && !is8) -> (langAda -> gnat-bootstrap != null);
233
234# TODO: fixup D bootstapping, probably by using gdc11 (and maybe other changes).
235# error: GDC is required to build d
236assert atLeast12 -> !langD;
237
238# threadsCross is just for MinGW
239assert threadsCross != {} -> stdenv.targetPlatform.isWindows;
240
241# profiledCompiler builds inject non-determinism in one of the compilation stages.
242# If turned on, we can't provide reproducible builds anymore
243assert reproducibleBuild -> profiledCompiler == false;
244
245# We need all these X libraries when building AWT with GTK.
246assert !atLeast7 -> (x11Support -> (filter (x: x == null) ([ gtk2 libart_lgpl ] ++ xlibs)) == []);
247
248pipe ((callFile ./common/builder.nix {}) ({
249 pname = "${crossNameAddon}${name}";
250 inherit version;
251
252 src = if is6 && stdenv.targetPlatform.isVc4 then fetchFromGitHub {
253 owner = "itszor";
254 repo = "gcc-vc4";
255 rev = "e90ff43f9671c760cf0d1dd62f569a0fb9bf8918";
256 sha256 = "0gxf66hwqk26h8f853sybphqa5ca0cva2kmrw5jsiv6139g0qnp8";
257 } else if is6 && stdenv.targetPlatform.isRedox then fetchFromGitHub {
258 owner = "redox-os";
259 repo = "gcc";
260 rev = "f360ac095028d286fc6dde4d02daed48f59813fa"; # `redox` branch
261 sha256 = "1an96h8l58pppyh3qqv90g8hgcfd9hj7igvh2gigmkxbrx94khfl";
262 } else fetchurl {
263 url = if atLeast7
264 then "mirror://gcc/releases/gcc-${version}/gcc-${version}.tar.xz"
265 else if atLeast6
266 then "mirror://gnu/gcc/gcc-${version}/gcc-${version}.tar.xz"
267 else "mirror://gnu/gcc/gcc-${version}/gcc-${version}.tar.bz2";
268 ${if is10 || is11 || is13 then "hash" else "sha256"} =
269 gccVersions.srcHashForVersion version;
270 };
271
272 inherit patches;
273
274 outputs =
275 if atLeast7
276 then [ "out" "man" "info" ] ++ optional (!langJit) "lib"
277 else if atLeast49 && (langJava || langGo || (if atLeast6 then langJit else targetPlatform.isDarwin)) then ["out" "man" "info"]
278 else [ "out" "lib" "man" "info" ];
279
280 setOutputFlags = false;
281
282 libc_dev = stdenv.cc.libc_dev;
283
284 hardeningDisable = [ "format" "pie" "stackclashprotection" ]
285 ++ optionals (is11 && langAda) [ "fortify3" ];
286
287 postPatch = optionalString atLeast7 ''
288 configureScripts=$(find . -name configure)
289 for configureScript in $configureScripts; do
290 patchShebangs $configureScript
291 done
292 ''
293 # This should kill all the stdinc frameworks that gcc and friends like to
294 # insert into default search paths.
295 + optionalString (atLeast6 && hostPlatform.isDarwin) ''
296 substituteInPlace gcc/config/darwin-c.c${optionalString atLeast12 "c"} \
297 --replace 'if (stdinc)' 'if (0)'
298
299 substituteInPlace libgcc/config/t-slibgcc-darwin \
300 --replace "-install_name @shlib_slibdir@/\$(SHLIB_INSTALL_NAME)" "-install_name ''${!outputLib}/lib/\$(SHLIB_INSTALL_NAME)"
301
302 substituteInPlace libgfortran/configure \
303 --replace "-install_name \\\$rpath/\\\$soname" "-install_name ''${!outputLib}/lib/\\\$soname"
304 ''
305 + (
306 optionalString (targetPlatform != hostPlatform || stdenv.cc.libc != null)
307 # On NixOS, use the right path to the dynamic linker instead of
308 # `/lib/ld*.so'.
309 (let
310 libc = if libcCross != null then libcCross else stdenv.cc.libc;
311 in
312 (
313 '' echo "fixing the {GLIBC,UCLIBC,MUSL}_DYNAMIC_LINKER macros..."
314 for header in "gcc/config/"*-gnu.h "gcc/config/"*"/"*.h
315 do
316 grep -q ${optionalString (!atLeast6) "LIBC"}_DYNAMIC_LINKER "$header" || continue
317 echo " fixing $header..."
318 sed -i "$header" \
319 -e 's|define[[:blank:]]*\([UCG]\+\)LIBC_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define \1LIBC_DYNAMIC_LINKER\2 "${libc.out}\3"|g' \
320 -e 's|define[[:blank:]]*MUSL_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define MUSL_DYNAMIC_LINKER\1 "${libc.out}\2"|g'
321 done
322 '' + optionalString (atLeast6 && targetPlatform.libc == "musl") ''
323 sed -i gcc/config/linux.h -e '1i#undef LOCAL_INCLUDE_DIR'
324 ''
325 )
326 ))
327 + optionalString (atLeast7 && targetPlatform.isAvr) (''
328 makeFlagsArray+=(
329 '-s' # workaround for hitting hydra log limit
330 'LIMITS_H_TEST=false'
331 )
332 '');
333
334 inherit noSysDirs staticCompiler withoutTargetLibc
335 libcCross crossMingw;
336
337 inherit (callFile ./common/dependencies.nix { }) depsBuildBuild nativeBuildInputs depsBuildTarget buildInputs depsTargetTarget;
338
339 preConfigure = (callFile ./common/pre-configure.nix { }) + optionalString atLeast10 ''
340 ln -sf ${libxcrypt}/include/crypt.h libsanitizer/sanitizer_common/crypt.h
341 '';
342
343 dontDisableStatic = true;
344
345 configurePlatforms = [ "build" "host" "target" ];
346
347 configureFlags = (callFile ./common/configure-flags.nix { })
348 ++ optional (is7 && targetPlatform.isAarch64) "--enable-fix-cortex-a53-843419"
349 ++ optional (is7 && targetPlatform.isNetBSD) "--disable-libcilkrts";
350
351 inherit targetConfig;
352
353 buildFlags =
354 # we do not yet have Nix-driven profiling
355 assert atLeast12 -> (profiledCompiler -> !disableBootstrap);
356 if atLeast11
357 then let target =
358 optionalString (profiledCompiler) "profiled" +
359 optionalString (targetPlatform == hostPlatform && hostPlatform == buildPlatform && !disableBootstrap) "bootstrap";
360 in optional (target != "") target
361 else
362 optional
363 (targetPlatform == hostPlatform && hostPlatform == buildPlatform)
364 (if profiledCompiler then "profiledbootstrap" else "bootstrap");
365
366 inherit (callFile ./common/strip-attributes.nix { })
367 stripDebugList
368 stripDebugListTarget
369 preFixup;
370
371 # https://gcc.gnu.org/PR109898
372 enableParallelInstalling = false;
373
374 env = mapAttrs (_: v: toString v) ({
375
376 NIX_NO_SELF_RPATH = true;
377
378 # https://gcc.gnu.org/install/specific.html#x86-64-x-solaris210
379 ${if hostPlatform.system == "x86_64-solaris" then "CC" else null} = "gcc -m64";
380
381 # Setting $CPATH and $LIBRARY_PATH to make sure both `gcc' and `xgcc' find the
382 # library headers and binaries, regarless of the language being compiled.
383 #
384 # Note: When building the Java AWT GTK peer, the build system doesn't honor
385 # `--with-gmp' et al., e.g., when building
386 # `libjava/classpath/native/jni/java-math/gnu_java_math_GMP.c', so we just add
387 # them to $CPATH and $LIBRARY_PATH in this case.
388 #
389 # Likewise, the LTO code doesn't find zlib.
390 #
391 # Cross-compiling, we need gcc not to read ./specs in order to build the g++
392 # compiler (after the specs for the cross-gcc are created). Having
393 # LIBRARY_PATH= makes gcc read the specs from ., and the build breaks.
394
395 CPATH = optionals (targetPlatform == hostPlatform) (makeSearchPathOutput "dev" "include" ([]
396 ++ optional (zlib != null) zlib
397 ++ optional langJava boehmgc
398 ++ optionals javaAwtGtk xlibs
399 ++ optionals javaAwtGtk [ gmp mpfr ]
400 ));
401
402 LIBRARY_PATH = optionals (targetPlatform == hostPlatform) (makeLibraryPath (
403 optional (zlib != null) zlib
404 ++ optional langJava boehmgc
405 ++ optionals javaAwtGtk xlibs
406 ++ optionals javaAwtGtk [ gmp mpfr ]
407 ));
408
409 inherit (callFile ./common/extra-target-flags.nix { })
410 EXTRA_FLAGS_FOR_TARGET
411 EXTRA_LDFLAGS_FOR_TARGET
412 ;
413 } // optionalAttrs is7 {
414 NIX_CFLAGS_COMPILE = optionalString (stdenv.cc.isClang && langFortran) "-Wno-unused-command-line-argument"
415 # Downgrade register storage class specifier errors to warnings when building a cross compiler from a clang stdenv.
416 + optionalString (stdenv.cc.isClang && targetPlatform != hostPlatform) " -Wno-register";
417 } // optionalAttrs (!is7 && !atLeast12 && stdenv.cc.isClang && targetPlatform != hostPlatform) {
418 NIX_CFLAGS_COMPILE = "-Wno-register";
419 } // optionalAttrs (!atLeast7) {
420 inherit langJava;
421 } // optionalAttrs atLeast6 {
422 NIX_LDFLAGS = optionalString hostPlatform.isSunOS "-lm";
423 });
424
425 passthru = {
426 inherit langC langCC langObjC langObjCpp langAda langFortran langGo langD langJava version;
427 isGNU = true;
428 hardeningUnsupportedFlags = optional is48 "stackprotector"
429 ++ optional (
430 (targetPlatform.isAarch64 && !atLeast9) || !atLeast8
431 ) "stackclashprotection"
432 ++ optional (!atLeast11) "zerocallusedregs"
433 ++ optionals (!atLeast12) [ "fortify3" "trivialautovarinit" ]
434 ++ optionals (langFortran) [ "fortify" "format" ];
435 };
436
437 enableParallelBuilding = true;
438 inherit enableShared enableMultilib;
439
440 meta = {
441 inherit (callFile ./common/meta.nix { })
442 homepage
443 license
444 description
445 longDescription
446 platforms
447 maintainers
448 ;
449 } // optionalAttrs (!atLeast11) {
450 badPlatforms =
451 # avr-gcc8 is maintained for the `qmk` package
452 if (is8 && targetPlatform.isAvr) then []
453 else if !(is48 || is49 || is6) then [ "aarch64-darwin" ]
454 else platforms.darwin;
455 } // optionalAttrs is10 {
456 badPlatforms = if targetPlatform != hostPlatform then [ "aarch64-darwin" ] else [ ];
457 };
458} // optionalAttrs (!atLeast10 && stdenv.targetPlatform.isDarwin) {
459 # GCC <10 requires default cctools `strip` instead of `llvm-strip` used by Darwin bintools.
460 preBuild = ''
461 makeFlagsArray+=('STRIP=${getBin cctools}/bin/${stdenv.cc.targetPrefix}strip')
462 '';
463} // optionalAttrs (!atLeast8) {
464 doCheck = false; # requires a lot of tools, causes a dependency cycle for stdenv
465} // optionalAttrs enableMultilib {
466 dontMoveLib64 = true;
467} // optionalAttrs (((is49 && !stdenv.hostPlatform.isDarwin) || is6) && langJava) {
468 postFixup = ''
469 target="$(echo "$out/libexec/gcc"/*/*/ecj*)"
470 patchelf --set-rpath "$(patchelf --print-rpath "$target"):$out/lib" "$target"
471 '';
472}
473))
474([
475 (callPackage ./common/libgcc.nix { inherit version langC langCC langJit targetPlatform hostPlatform withoutTargetLibc enableShared libcCross; })
476] ++ optionals atLeast11 [
477 (callPackage ./common/checksum.nix { inherit langC langCC; })
478])
479