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