nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 stdenv,
4 targetPackages,
5 fetchurl,
6 fetchpatch,
7 noSysDirs,
8 langC ? true,
9 langCC ? true,
10 langFortran ? false,
11 langAda ? false,
12 langObjC ? stdenv.targetPlatform.isDarwin,
13 langObjCpp ? stdenv.targetPlatform.isDarwin,
14 langGo ? false,
15 reproducibleBuild ? true,
16 profiledCompiler ? false,
17 langJit ? false,
18 langRust ? false,
19 cargo,
20 staticCompiler ? false,
21 enableShared ? stdenv.targetPlatform.hasSharedLibraries,
22 enableDefaultPie ? stdenv.targetPlatform.hasSharedLibraries,
23 enableLTO ? stdenv.hostPlatform.hasSharedLibraries,
24 texinfo ? null,
25 perl ? null, # optional, for texi2pod (then pod2man)
26 gmp,
27 mpfr,
28 libmpc,
29 gettext,
30 which,
31 patchelf,
32 binutils,
33 autoconf269,
34 isl ? null, # optional, for the Graphite optimization framework.
35 zlib ? null,
36 libucontext ? null,
37 gnat-bootstrap ? null,
38 enableMultilib ? false,
39 enablePlugin ? (lib.systems.equals stdenv.hostPlatform stdenv.buildPlatform), # Whether to support user-supplied plug-ins
40 name ? "gcc",
41 libcCross ? null,
42 threadsCross ? { }, # for MinGW
43 withoutTargetLibc ? stdenv.targetPlatform.libc == null,
44 flex,
45 gnused ? null,
46 buildPackages,
47 pkgsBuildTarget,
48 libxcrypt,
49 disableGdbPlugin ?
50 !enablePlugin
51 || (stdenv.targetPlatform.isAvr && stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64),
52 nukeReferences,
53 callPackage,
54 majorMinorVersion,
55 apple-sdk,
56 darwin,
57}:
58
59let
60 inherit (lib)
61 callPackageWith
62 filter
63 getBin
64 maintainers
65 makeLibraryPath
66 makeSearchPathOutput
67 mapAttrs
68 optional
69 optionalAttrs
70 optionals
71 optionalString
72 pipe
73 platforms
74 versionAtLeast
75 versions
76 ;
77
78 gccVersions = import ./versions.nix;
79 version = gccVersions.fromMajorMinor majorMinorVersion;
80
81 majorVersion = versions.major version;
82 atLeast14 = versionAtLeast version "14";
83 is14 = majorVersion == "14";
84 is13 = majorVersion == "13";
85
86 # releases have a form: MAJOR.MINOR.MICRO, like 14.2.1
87 # snapshots have a form like MAJOR.MINOR.MICRO.DATE, like 14.2.1.20250322
88 isSnapshot = lib.length (lib.splitVersion version) == 4;
89 # return snapshot date of gcc's given version:
90 # "14.2.1.20250322" -> "20250322"
91 # "14.2.0" -> ""
92 snapDate = lib.concatStrings (lib.drop 3 (lib.splitVersion version));
93 # return base version without a snapshot:
94 # "14.2.1.20250322" -> "14.2.1"
95 # "14.2.0" -> "14.2.0"
96 baseVersion = lib.concatStringsSep "." (lib.take 3 (lib.splitVersion version));
97
98 disableBootstrap = !stdenv.hostPlatform.isDarwin && !profiledCompiler;
99
100 inherit (stdenv) buildPlatform hostPlatform targetPlatform;
101 targetConfig =
102 if (!lib.systems.equals targetPlatform hostPlatform) then targetPlatform.config else null;
103
104 patches = callFile ./patches { };
105
106 # Cross-gcc settings (build == host != target)
107 crossMingw = (!lib.systems.equals targetPlatform hostPlatform) && targetPlatform.isMinGW;
108 stageNameAddon = optionalString withoutTargetLibc "-nolibc";
109 crossNameAddon = optionalString (
110 !lib.systems.equals targetPlatform hostPlatform
111 ) "${targetPlatform.config}${stageNameAddon}-";
112
113 targetPrefix = lib.optionalString (
114 !lib.systems.equals stdenv.targetPlatform stdenv.hostPlatform
115 ) "${stdenv.targetPlatform.config}-";
116
117 callFile = callPackageWith {
118 # lets
119 inherit
120 majorVersion
121 isSnapshot
122 version
123 buildPlatform
124 hostPlatform
125 targetPlatform
126 targetConfig
127 patches
128 crossMingw
129 stageNameAddon
130 crossNameAddon
131 ;
132 # inherit generated with 'nix eval --json --impure --expr "with import ./. {}; lib.attrNames (lib.functionArgs gcc${majorVersion}.cc.override)" | jq '.[]' --raw-output'
133 inherit
134 apple-sdk
135 autoconf269
136 binutils
137 buildPackages
138 cargo
139 withoutTargetLibc
140 darwin
141 disableBootstrap
142 disableGdbPlugin
143 enableDefaultPie
144 enableLTO
145 enableMultilib
146 enablePlugin
147 enableShared
148 fetchpatch
149 fetchurl
150 flex
151 gettext
152 gmp
153 gnat-bootstrap
154 gnused
155 isl
156 langAda
157 langC
158 langCC
159 langFortran
160 langGo
161 langJit
162 langObjC
163 langObjCpp
164 langRust
165 lib
166 libcCross
167 libmpc
168 libucontext
169 libxcrypt
170 mpfr
171 name
172 noSysDirs
173 nukeReferences
174 patchelf
175 perl
176 pkgsBuildTarget
177 profiledCompiler
178 reproducibleBuild
179 staticCompiler
180 stdenv
181 targetPackages
182 texinfo
183 threadsCross
184 which
185 zlib
186 ;
187 };
188
189in
190
191# Make sure we get GNU sed.
192assert stdenv.buildPlatform.isDarwin -> gnused != null;
193
194# The go frontend is written in c++
195assert langGo -> langCC;
196assert langAda -> gnat-bootstrap != null;
197
198# threadsCross is just for MinGW
199assert threadsCross != { } -> stdenv.targetPlatform.isWindows;
200
201# profiledCompiler builds inject non-determinism in one of the compilation stages.
202# If turned on, we can't provide reproducible builds anymore
203assert reproducibleBuild -> profiledCompiler == false;
204
205pipe
206 ((callFile ./common/builder.nix { }) (
207 {
208 pname = "${crossNameAddon}${name}";
209 # retain snapshot date in package version, but not in final version
210 # as the version is frequently used to construct pathnames (at least
211 # in cc-wrapper).
212 name = "${crossNameAddon}${name}-${version}";
213 version = baseVersion;
214
215 src = fetchurl {
216 url =
217 if isSnapshot then
218 "mirror://gcc/snapshots/${majorVersion}-${snapDate}/gcc-${majorVersion}-${snapDate}.tar.xz"
219 else
220 "mirror://gcc/releases/gcc-${version}/gcc-${version}.tar.xz";
221 ${if is13 then "hash" else "sha256"} = gccVersions.srcHashForVersion version;
222 };
223
224 inherit patches;
225
226 outputs = [
227 "out"
228 "man"
229 "info"
230 ]
231 ++ optional (!langJit) "lib";
232
233 setOutputFlags = false;
234
235 libc_dev = stdenv.cc.libc_dev;
236
237 hardeningDisable = [
238 "format"
239 "stackclashprotection"
240 ];
241
242 postPatch = ''
243 configureScripts=$(find . -name configure)
244 for configureScript in $configureScripts; do
245 patchShebangs $configureScript
246 done
247
248 # Make sure nixpkgs versioning match upstream one
249 # to ease version-based comparisons.
250 gcc_base_version=$(< gcc/BASE-VER)
251 if [[ ${baseVersion} != $gcc_base_version ]]; then
252 echo "Please update 'version' variable:"
253 echo " Expected: '$gcc_base_version'"
254 echo " Actual: '${version}'"
255 exit 1
256 fi
257 ''
258 # This should kill all the stdinc frameworks that gcc and friends like to
259 # insert into default search paths.
260 + optionalString hostPlatform.isDarwin ''
261 substituteInPlace gcc/config/darwin-c.cc \
262 --replace 'if (stdinc)' 'if (0)'
263
264 substituteInPlace libgcc/config/t-slibgcc-darwin \
265 --replace "-install_name @shlib_slibdir@/\$(SHLIB_INSTALL_NAME)" "-install_name ''${!outputLib}/lib/\$(SHLIB_INSTALL_NAME)"
266
267 substituteInPlace libgfortran/configure \
268 --replace "-install_name \\\$rpath/\\\$soname" "-install_name ''${!outputLib}/lib/\\\$soname"
269 ''
270 + (optionalString ((!lib.systems.equals targetPlatform hostPlatform) || stdenv.cc.libc != null)
271 # On NixOS, use the right path to the dynamic linker instead of
272 # `/lib/ld*.so'.
273 (
274 let
275 libc = if libcCross != null then libcCross else stdenv.cc.libc;
276 in
277 (
278 ''
279 echo "fixing the {GLIBC,UCLIBC,MUSL}_DYNAMIC_LINKER macros..."
280 for header in "gcc/config/"*-gnu.h "gcc/config/"*"/"*.h
281 do
282 grep -q _DYNAMIC_LINKER "$header" || continue
283 echo " fixing $header..."
284 sed -i "$header" \
285 -e 's|define[[:blank:]]*\([UCG]\+\)LIBC_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define \1LIBC_DYNAMIC_LINKER\2 "${libc.out}\3"|g' \
286 -e 's|define[[:blank:]]*MUSL_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define MUSL_DYNAMIC_LINKER\1 "${libc.out}\2"|g'
287 done
288 ''
289 + optionalString (targetPlatform.libc == "musl") ''
290 sed -i gcc/config/linux.h -e '1i#undef LOCAL_INCLUDE_DIR'
291 ''
292 )
293 )
294 )
295 + optionalString targetPlatform.isAvr ''
296 makeFlagsArray+=(
297 '-s' # workaround for hitting hydra log limit
298 'LIMITS_H_TEST=false'
299 )
300 '';
301
302 inherit
303 noSysDirs
304 staticCompiler
305 withoutTargetLibc
306 libcCross
307 crossMingw
308 ;
309
310 inherit (callFile ./common/dependencies.nix { })
311 depsBuildBuild
312 nativeBuildInputs
313 depsBuildTarget
314 buildInputs
315 depsTargetTarget
316 ;
317
318 preConfigure = (callFile ./common/pre-configure.nix { }) + ''
319 ln -sf ${libxcrypt}/include/crypt.h libsanitizer/sanitizer_common/crypt.h
320 '';
321
322 dontDisableStatic = true;
323
324 configurePlatforms = [
325 "build"
326 "host"
327 "target"
328 ];
329
330 configureFlags = callFile ./common/configure-flags.nix { inherit targetPrefix; };
331
332 inherit targetConfig;
333
334 buildFlags =
335 # we do not yet have Nix-driven profiling
336 assert profiledCompiler -> !disableBootstrap;
337 let
338 target =
339 optionalString profiledCompiler "profiled"
340 + optionalString (
341 (lib.systems.equals targetPlatform hostPlatform)
342 && (lib.systems.equals hostPlatform buildPlatform)
343 && !disableBootstrap
344 ) "bootstrap";
345 in
346 optional (target != "") target;
347
348 inherit (callFile ./common/strip-attributes.nix { })
349 stripDebugList
350 stripDebugListTarget
351 preFixup
352 ;
353
354 # https://gcc.gnu.org/PR109898
355 enableParallelInstalling = false;
356
357 env = mapAttrs (_: v: toString v) {
358
359 NIX_NO_SELF_RPATH = true;
360
361 # https://gcc.gnu.org/install/specific.html#x86-64-x-solaris210
362 ${if hostPlatform.system == "x86_64-solaris" then "CC" else null} = "gcc -m64";
363
364 # Setting $CPATH and $LIBRARY_PATH to make sure both `gcc' and `xgcc' find the
365 # library headers and binaries, regardless of the language being compiled.
366 #
367 # The LTO code doesn't find zlib, so we just add it to $CPATH and
368 # $LIBRARY_PATH in this case.
369 #
370 # Cross-compiling, we need gcc not to read ./specs in order to build the g++
371 # compiler (after the specs for the cross-gcc are created). Having
372 # LIBRARY_PATH= makes gcc read the specs from ., and the build breaks.
373
374 CPATH = optionals (lib.systems.equals targetPlatform hostPlatform) (
375 makeSearchPathOutput "dev" "include" ([ ] ++ optional (zlib != null) zlib)
376 );
377
378 LIBRARY_PATH = optionals (lib.systems.equals targetPlatform hostPlatform) (
379 makeLibraryPath (optional (zlib != null) zlib)
380 );
381
382 NIX_LDFLAGS = optionalString hostPlatform.isSunOS "-lm";
383
384 inherit (callFile ./common/extra-target-flags.nix { })
385 EXTRA_FLAGS_FOR_TARGET
386 EXTRA_LDFLAGS_FOR_TARGET
387 ;
388 };
389
390 passthru = {
391 inherit
392 langC
393 langCC
394 langObjC
395 langObjCpp
396 langAda
397 langFortran
398 langGo
399 version
400 ;
401 isGNU = true;
402 hardeningUnsupportedFlags =
403 optional (
404 !(targetPlatform.isLinux && targetPlatform.isx86_64 && targetPlatform.libc == "glibc")
405 ) "shadowstack"
406 ++ optional (!(targetPlatform.isLinux && targetPlatform.isAarch64)) "pacret"
407 ++ optionals langFortran [
408 "fortify"
409 "format"
410 ];
411 };
412
413 enableParallelBuilding = true;
414 inherit enableShared enableMultilib;
415
416 meta = {
417 inherit (callFile ./common/meta.nix { inherit targetPrefix; })
418 homepage
419 license
420 description
421 longDescription
422 platforms
423 teams
424 mainProgram
425 identifiers
426 ;
427 };
428 }
429 // optionalAttrs enableMultilib {
430 dontMoveLib64 = true;
431 }
432 ))
433 [
434 (callPackage ./common/libgcc.nix {
435 inherit
436 version
437 langC
438 langCC
439 langJit
440 targetPlatform
441 hostPlatform
442 withoutTargetLibc
443 enableShared
444 libcCross
445 ;
446 })
447 (callPackage ./common/checksum.nix { inherit langC langCC; })
448 ]