{ lib, stdenv, targetPackages, fetchurl, fetchpatch, noSysDirs , langC ? true, langCC ? true, langFortran ? false , langAda ? false , langObjC ? stdenv.targetPlatform.isDarwin , langObjCpp ? stdenv.targetPlatform.isDarwin , langD ? false , langGo ? false , reproducibleBuild ? true , profiledCompiler ? false , langJit ? false , staticCompiler ? false , enableShared ? !stdenv.targetPlatform.isStatic , enableLTO ? !stdenv.hostPlatform.isStatic , texinfo ? null , perl ? null # optional, for texi2pod (then pod2man) , gmp, mpfr, libmpc, gettext, which, patchelf , isl ? null # optional, for the Graphite optimization framework. , zlib ? null , gnatboot ? null , enableMultilib ? false , enablePlugin ? stdenv.hostPlatform == stdenv.buildPlatform # Whether to support user-supplied plug-ins , name ? "gcc" , libcCross ? null , threadsCross ? null # for MinGW , crossStageStatic ? false , gnused ? null , cloog # unused; just for compat with gcc4, as we override the parameter on some places , buildPackages , libxcrypt }: # Make sure we get GNU sed. assert stdenv.buildPlatform.isDarwin -> gnused != null; # The go frontend is written in c++ assert langGo -> langCC; assert langAda -> gnatboot != null; # threadsCross is just for MinGW assert threadsCross != {} -> stdenv.targetPlatform.isWindows; # profiledCompiler builds inject non-determinism in one of the compilation stages. # If turned on, we can't provide reproducible builds anymore assert reproducibleBuild -> profiledCompiler == false; with lib; with builtins; let majorVersion = "10"; version = "${majorVersion}.4.0"; inherit (stdenv) buildPlatform hostPlatform targetPlatform; patches = [ ] ++ optional (targetPlatform != hostPlatform) ../libstdc++-target.patch ++ optional noSysDirs ../no-sys-dirs.patch ++ optional (noSysDirs && hostPlatform.isRiscV) ../no-sys-dirs-riscv.patch /* ++ optional (hostPlatform != buildPlatform) (fetchpatch { # XXX: Refine when this should be applied url = "https://git.busybox.net/buildroot/plain/package/gcc/${version}/0900-remove-selftests.patch?id=11271540bfe6adafbc133caf6b5b902a816f5f02"; sha256 = ""; # TODO: uncomment and check hash when available. }) */ ++ optional langAda ../gnat-cflags.patch ++ optional langD ../libphobos.patch ++ optional langFortran ../gfortran-driving.patch ++ optional (targetPlatform.libc == "musl" && targetPlatform.isPower) ../ppc-musl.patch # Obtain latest patch with ../update-mcfgthread-patches.sh ++ optional (!crossStageStatic && targetPlatform.isMinGW && threadsCross.model == "mcf") ./Added-mcf-thread-model-support-from-mcfgthread.patch ++ optional (buildPlatform.system == "aarch64-darwin" && targetPlatform != buildPlatform) (fetchpatch { url = "https://raw.githubusercontent.com/richard-vd/musl-cross-make/5e9e87f06fc3220e102c29d3413fbbffa456fcd6/patches/gcc-${version}/0008-darwin-aarch64-self-host-driver.patch"; sha256 = "sha256-XtykrPd5h/tsnjY1wGjzSOJ+AyyNLsfnjuOZ5Ryq9vA="; }); /* Cross-gcc settings (build == host != target) */ crossMingw = targetPlatform != hostPlatform && targetPlatform.libc == "msvcrt"; stageNameAddon = if crossStageStatic then "stage-static" else "stage-final"; crossNameAddon = optionalString (targetPlatform != hostPlatform) "${targetPlatform.config}-${stageNameAddon}-"; in stdenv.mkDerivation ({ pname = "${crossNameAddon}${name}"; inherit version; builder = ../builder.sh; src = fetchurl { url = "mirror://gcc/releases/gcc-${version}/gcc-${version}.tar.xz"; sha256 = "1wg4xdizkksmwi66mvv2v4pk3ja8x64m7v9gzhykzd3wrmdpsaf9"; }; inherit patches; outputs = [ "out" "man" "info" ] ++ lib.optional (!langJit) "lib"; setOutputFlags = false; NIX_NO_SELF_RPATH = true; libc_dev = stdenv.cc.libc_dev; hardeningDisable = [ "format" "pie" ]; postPatch = '' configureScripts=$(find . -name configure) for configureScript in $configureScripts; do patchShebangs $configureScript done '' # This should kill all the stdinc frameworks that gcc and friends like to # insert into default search paths. + lib.optionalString hostPlatform.isDarwin '' substituteInPlace gcc/config/darwin-c.c \ --replace 'if (stdinc)' 'if (0)' substituteInPlace libgcc/config/t-slibgcc-darwin \ --replace "-install_name @shlib_slibdir@/\$(SHLIB_INSTALL_NAME)" "-install_name ''${!outputLib}/lib/\$(SHLIB_INSTALL_NAME)" substituteInPlace libgfortran/configure \ --replace "-install_name \\\$rpath/\\\$soname" "-install_name ''${!outputLib}/lib/\\\$soname" '' + ( if targetPlatform != hostPlatform || stdenv.cc.libc != null then # On NixOS, use the right path to the dynamic linker instead of # `/lib/ld*.so'. let libc = if libcCross != null then libcCross else stdenv.cc.libc; in ( '' echo "fixing the \`GLIBC_DYNAMIC_LINKER', \`UCLIBC_DYNAMIC_LINKER', and \`MUSL_DYNAMIC_LINKER' macros..." for header in "gcc/config/"*-gnu.h "gcc/config/"*"/"*.h do grep -q _DYNAMIC_LINKER "$header" || continue echo " fixing \`$header'..." sed -i "$header" \ -e 's|define[[:blank:]]*\([UCG]\+\)LIBC_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define \1LIBC_DYNAMIC_LINKER\2 "${libc.out}\3"|g' \ -e 's|define[[:blank:]]*MUSL_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define MUSL_DYNAMIC_LINKER\1 "${libc.out}\2"|g' done '' + lib.optionalString (targetPlatform.libc == "musl") '' sed -i gcc/config/linux.h -e '1i#undef LOCAL_INCLUDE_DIR' '' ) else "") + lib.optionalString targetPlatform.isAvr '' makeFlagsArray+=( '-s' # workaround for hitting hydra log limit 'LIMITS_H_TEST=false' ) ''; inherit noSysDirs staticCompiler crossStageStatic libcCross crossMingw; depsBuildBuild = [ buildPackages.stdenv.cc ]; nativeBuildInputs = [ texinfo which gettext ] ++ (optional (perl != null) perl) ++ (optional langAda gnatboot) # The builder relies on GNU sed (for instance, Darwin's `sed' fails with # "-i may not be used with stdin"), and `stdenvNative' doesn't provide it. ++ (optional buildPlatform.isDarwin gnused) ; # For building runtime libs depsBuildTarget = ( if hostPlatform == buildPlatform then [ targetPackages.stdenv.cc.bintools # newly-built gcc will be used ] else assert targetPlatform == hostPlatform; [ # build != host == target stdenv.cc ] ) ++ optional targetPlatform.isLinux patchelf; buildInputs = [ gmp mpfr libmpc libxcrypt targetPackages.stdenv.cc.bintools # For linking code at run-time ] ++ (optional (isl != null) isl) ++ (optional (zlib != null) zlib) ; depsTargetTarget = optional (!crossStageStatic && threadsCross != {} && threadsCross.package != null) threadsCross.package; NIX_LDFLAGS = lib.optionalString hostPlatform.isSunOS "-lm -ldl"; preConfigure = (import ../common/pre-configure.nix { inherit lib; inherit version targetPlatform hostPlatform gnatboot langAda langGo langJit crossStageStatic enableMultilib; }) + '' ln -sf ${libxcrypt}/include/crypt.h libsanitizer/sanitizer_common/crypt.h ''; dontDisableStatic = true; configurePlatforms = [ "build" "host" "target" ]; configureFlags = import ../common/configure-flags.nix { inherit lib stdenv targetPackages crossStageStatic libcCross threadsCross version gmp mpfr libmpc isl enableLTO enableMultilib enablePlugin enableShared langC langD langCC langFortran langAda langGo langObjC langObjCpp langJit ; }; targetConfig = if targetPlatform != hostPlatform then targetPlatform.config else null; buildFlags = optional (targetPlatform == hostPlatform && hostPlatform == buildPlatform) (if profiledCompiler then "profiledbootstrap" else "bootstrap"); inherit (import ../common/strip-attributes.nix { inherit lib stdenv langJit; }) stripDebugList stripDebugListTarget preFixup; # https://gcc.gnu.org/install/specific.html#x86-64-x-solaris210 ${if hostPlatform.system == "x86_64-solaris" then "CC" else null} = "gcc -m64"; # Setting $CPATH and $LIBRARY_PATH to make sure both `gcc' and `xgcc' find the # library headers and binaries, regarless of the language being compiled. # # Likewise, the LTO code doesn't find zlib. # # Cross-compiling, we need gcc not to read ./specs in order to build the g++ # compiler (after the specs for the cross-gcc are created). Having # LIBRARY_PATH= makes gcc read the specs from ., and the build breaks. CPATH = optionals (targetPlatform == hostPlatform) (makeSearchPathOutput "dev" "include" ([] ++ optional (zlib != null) zlib )); LIBRARY_PATH = optionals (targetPlatform == hostPlatform) (makeLibraryPath (optional (zlib != null) zlib)); inherit (import ../common/extra-target-flags.nix { inherit lib stdenv crossStageStatic langD libcCross threadsCross; }) EXTRA_FLAGS_FOR_TARGET EXTRA_LDFLAGS_FOR_TARGET ; passthru = { inherit langC langCC langObjC langObjCpp langAda langFortran langGo langD version; isGNU = true; }; enableParallelBuilding = true; inherit enableMultilib enableShared; meta = { homepage = "https://gcc.gnu.org/"; license = lib.licenses.gpl3Plus; # runtime support libraries are typically LGPLv3+ description = "GNU Compiler Collection, version ${version}"; longDescription = '' The GNU Compiler Collection includes compiler front ends for C, C++, Objective-C, Fortran, OpenMP for C/C++/Fortran, and Ada, as well as libraries for these languages (libstdc++, libgomp,...). GCC development is a part of the GNU Project, aiming to improve the compiler used in the GNU system including the GNU/Linux variant. ''; maintainers = lib.teams.gcc.members; platforms = lib.platforms.unix; badPlatforms = [ "aarch64-darwin" ]; }; } // optionalAttrs (targetPlatform != hostPlatform && targetPlatform.libc == "msvcrt" && crossStageStatic) { makeFlags = [ "all-gcc" "all-target-libgcc" ]; installTargets = "install-gcc install-target-libgcc"; } // optionalAttrs (enableMultilib) { dontMoveLib64 = true; } )