at master 13 kB view raw
1let 2 withGold = platform: platform.isElf && !platform.isRiscV && !platform.isLoongArch64; 3in 4 5{ 6 stdenv, 7 autoconf269, 8 automake, 9 libtool, 10 bison, 11 buildPackages, 12 fetchurl, 13 gettext, 14 lib, 15 noSysDirs, 16 perl, 17 runCommand, 18 zlib, 19 20 enableGold ? withGold stdenv.targetPlatform, 21 enableGoldDefault ? false, 22 enableShared ? !stdenv.hostPlatform.isStatic, 23 # WARN: Enabling all targets increases output size to a multiple. 24 withAllTargets ? false, 25}: 26 27# WARN: configure silently disables ld.gold if it's unsupported, so we need to 28# make sure that intent matches result ourselves. 29assert enableGold -> withGold stdenv.targetPlatform; 30assert enableGoldDefault -> enableGold; 31 32let 33 inherit (stdenv) buildPlatform hostPlatform targetPlatform; 34 35 version = "2.44"; 36 37 #INFO: The targetPrefix prepended to binary names to allow multiple binuntils 38 # on the PATH to both be usable. 39 targetPrefix = lib.optionalString (targetPlatform != hostPlatform) "${targetPlatform.config}-"; 40 41 # gas is disabled for some targets via noconfigdirs in configure. 42 targetHasGas = !stdenv.targetPlatform.isDarwin; 43 44 # gas isn't multi-target, even with --enable-targets=all, so we do 45 # separate builds of just gas for each target. 46 # 47 # There's no way to do this exhaustively, so feel free to add 48 # additional targets here as required. 49 allGasTargets = 50 allGasTargets' 51 ++ lib.optional ( 52 targetHasGas && !lib.elem targetPlatform.config allGasTargets' 53 ) targetPlatform.config; 54 allGasTargets' = [ 55 "aarch64-unknown-linux-gnu" 56 "alpha-unknown-linux-gnu" 57 "arm-unknown-linux-gnu" 58 "avr-unknown-linux-gnu" 59 "cris-unknown-linux-gnu" 60 "hppa-unknown-linux-gnu" 61 "i686-unknown-linux-gnu" 62 "ia64-unknown-linux-gnu" 63 "m68k-unknown-linux-gnu" 64 "mips-unknown-linux-gnu" 65 "mips64-unknown-linux-gnu" 66 "msp430-unknown-linux-gnu" 67 "powerpc-unknown-linux-gnu" 68 "powerpc64-unknown-linux-gnu" 69 "s390-unknown-linux-gnu" 70 "sparc-unknown-linux-gnu" 71 "vax-unknown-linux-gnu" 72 "x86_64-unknown-linux-gnu" 73 "xscale-unknown-linux-gnu" 74 ]; 75in 76 77stdenv.mkDerivation (finalAttrs: { 78 pname = targetPrefix + "binutils"; 79 inherit version; 80 81 src = fetchurl { 82 url = "mirror://gnu/binutils/binutils-with-gold-${version}.tar.bz2"; 83 hash = "sha256-NHM+pJXMDlDnDbTliQ3sKKxB8OFMShZeac8n+5moxMg="; 84 }; 85 86 # WARN: this package is used for bootstrapping fetchurl, and thus cannot use 87 # fetchpatch! All mutable patches (generated by GitHub or cgit) that are 88 # needed here should be included directly in Nixpkgs as files. 89 patches = [ 90 # Make binutils output deterministic by default. 91 ./deterministic.patch 92 93 # Breaks nm BSD flag detection, heeds an upstream fix: 94 # https://sourceware.org/PR29547 95 ./0001-Revert-libtool.m4-fix-the-NM-nm-over-here-B-option-w.patch 96 ./0001-Revert-libtool.m4-fix-nm-BSD-flag-detection.patch 97 98 # For some reason bfd ld doesn't search DT_RPATH when cross-compiling. It's 99 # not clear why this behavior was decided upon but it has the unfortunate 100 # consequence that the linker will fail to find transitive dependencies of 101 # shared objects when cross-compiling. Consequently, we are forced to 102 # override this behavior, forcing ld to search DT_RPATH even when 103 # cross-compiling. 104 ./always-search-rpath.patch 105 106 # Avoid `lib -> out -> lib` reference. Normally `bfd-plugins` does 107 # not need to know binutils' BINDIR at all. It's an absolute path 108 # where libraries are stored. 109 ./plugins-no-BINDIR.patch 110 111 # ld64 needs `-undefined dynamic_lookup` to link `libctf-nobfd.dylib`, but the Darwin 112 # version detection in `libtool.m4` fails to detect the Darwin version correctly. 113 ./0001-libtool.m4-update-macos-version-detection-block.patch 114 115 # Adds AVR-specific options to "size" for compatibility with Atmel's downstream distribution 116 # Patch from arch-community 117 # https://github.com/archlinux/svntogit-community/blob/c8d53dd1734df7ab15931f7fad0c9acb8386904c/trunk/avr-size.patch 118 ./avr-size.patch 119 120 ./windres-locate-gcc.patch 121 ]; 122 123 outputs = [ 124 "out" 125 "info" 126 "man" 127 "dev" 128 ] 129 # Ideally we would like to always install 'lib' into a separate 130 # target. Unfortunately cross-compiled binutils installs libraries 131 # across both `$lib/lib/` and `$out/$target/lib` with a reference 132 # from $out to $lib. Probably a binutils bug: all libraries should go 133 # to $lib as binutils does not build target libraries. Let's make our 134 # life slightly simpler by installing everything into $out for 135 # cross-binutils. 136 ++ lib.optionals (targetPlatform == hostPlatform) [ "lib" ]; 137 138 strictDeps = true; 139 depsBuildBuild = [ buildPackages.stdenv.cc ]; 140 # texinfo was removed here in https://github.com/NixOS/nixpkgs/pull/210132 141 # to reduce rebuilds during stdenv bootstrap. Please don't add it back without 142 # checking the impact there first. 143 nativeBuildInputs = [ 144 bison 145 perl 146 ] 147 ++ lib.optionals buildPlatform.isDarwin [ 148 autoconf269 149 automake 150 gettext 151 libtool 152 ]; 153 154 buildInputs = [ 155 zlib 156 gettext 157 ]; 158 159 inherit noSysDirs; 160 161 preConfigure = 162 (lib.optionalString buildPlatform.isDarwin '' 163 for i in */configure.ac; do 164 pushd "$(dirname "$i")" 165 echo "Running autoreconf in $PWD" 166 # autoreconf doesn't work, don't know why 167 # autoreconf ''${autoreconfFlags:---install --force --verbose} 168 autoconf 169 popd 170 done 171 '') 172 + '' 173 # Clear the default library search path. 174 if test "$noSysDirs" = "1"; then 175 echo 'NATIVE_LIB_DIRS=' >> ld/configure.tgt 176 fi 177 178 # Use symlinks instead of hard links to save space ("strip" in the 179 # fixup phase strips each hard link separately). 180 for i in binutils/Makefile.in gas/Makefile.in ld/Makefile.in gold/Makefile.in; do 181 sed -i "$i" -e 's|ln |ln -s |' 182 done 183 184 configureScript="$PWD/configure" 185 mkdir $NIX_BUILD_TOP/build 186 cd $NIX_BUILD_TOP/build 187 ''; 188 189 # As binutils takes part in the stdenv building, we don't want references 190 # to the bootstrap-tools libgcc (as uses to happen on arm/mips) 191 # 192 # for FreeBSD it's more complicated. With -static-libgcc, configure 193 # thinks that limits.h does not exist and the build fails for not finding 194 # LONG_MIN. The configure test itself succeeds but the compiler issues a 195 # warning about -static-libgcc being unused. 196 env.NIX_CFLAGS_COMPILE = 197 if (hostPlatform.isDarwin || hostPlatform.isFreeBSD) then 198 "-Wno-string-plus-int -Wno-deprecated-declarations" 199 else 200 "-static-libgcc"; 201 202 hardeningDisable = [ 203 "format" 204 "pie" 205 ]; 206 207 configurePlatforms = [ 208 "build" 209 "host" 210 "target" 211 ]; 212 213 configureFlags = [ 214 "--enable-64-bit-bfd" 215 "--with-system-zlib" 216 217 "--enable-deterministic-archives" 218 "--disable-werror" 219 "--enable-fix-loongson2f-nop" 220 221 # Turn on --enable-new-dtags by default to make the linker set 222 # RUNPATH instead of RPATH on binaries. This is important because 223 # RUNPATH can be overridden using LD_LIBRARY_PATH at runtime. 224 "--enable-new-dtags" 225 226 # force target prefix. Some versions of binutils will make it empty if 227 # `--host` and `--target` are too close, even if Nixpkgs thinks the 228 # platforms are different (e.g. because not all the info makes the 229 # `config`). Other versions of binutils will always prefix if `--target` is 230 # passed, even if `--host` and `--target` are the same. The easiest thing 231 # for us to do is not leave it to chance, and force the program prefix to be 232 # what we want it to be. 233 "--program-prefix=${targetPrefix}" 234 235 # Unconditionally disable: 236 # - musl target needs porting: https://sourceware.org/PR29477 237 "--disable-gprofng" 238 239 # By default binutils searches $libdir for libraries. This brings in 240 # libbfd and libopcodes into a default visibility. Drop default lib 241 # path to force users to declare their use of these libraries. 242 "--with-lib-path=:" 243 ] 244 ++ lib.optionals withAllTargets [ 245 "--enable-targets=all" 246 # gas will be built separately for each target. 247 "--disable-gas" 248 ] 249 ++ lib.optionals enableGold [ 250 "--enable-gold${lib.optionalString enableGoldDefault "=default"}" 251 "--enable-plugins" 252 ] 253 ++ ( 254 if enableShared then 255 [ 256 "--enable-shared" 257 "--disable-static" 258 ] 259 else 260 [ 261 "--disable-shared" 262 "--enable-static" 263 ] 264 ) 265 ++ (lib.optionals (stdenv.cc.bintools.isLLVM && lib.versionAtLeast stdenv.cc.bintools.version "17") 266 [ 267 # lld17+ passes `--no-undefined-version` by default and makes this a hard 268 # error; libctf.ver version script references symbols that aren't present. 269 # 270 # This is fixed upstream and can be removed with the future release of 2.43. 271 # For now we allow this with `--undefined-version`: 272 "LDFLAGS=-Wl,--undefined-version" 273 ] 274 ); 275 276 postConfigure = lib.optionalString withAllTargets '' 277 for target in ${lib.escapeShellArgs allGasTargets}; do 278 mkdir "$NIX_BUILD_TOP/build-$target" 279 env -C "$NIX_BUILD_TOP/build-$target" \ 280 "$configureScript" $configureFlags "''${configureFlagsArray[@]}" \ 281 --enable-gas --program-prefix "$target-" --target "$target" 282 done 283 ''; 284 285 makeFlags = [ 286 # As we regenerated configure build system tries hard to use 287 # texinfo to regenerate manuals. Let's avoid the dependency 288 # on texinfo in bootstrap path and keep manuals unmodified. 289 "MAKEINFO=true" 290 ]; 291 292 postBuild = lib.optionalString withAllTargets '' 293 for target in ${lib.escapeShellArgs allGasTargets}; do 294 make -C "$NIX_BUILD_TOP/build-$target" -j"$NIX_BUILD_CORES" \ 295 $makeFlags "''${makeFlagsArray[@]}" $buildFlags "''${buildFlagsArray[@]}" \ 296 TARGET-gas=as-new all-gas 297 done 298 ''; 299 300 # Fails 301 doCheck = false; 302 303 # Break dependency on pkgsBuildBuild.gcc when building a cross-binutils 304 stripDebugList = 305 if stdenv.hostPlatform != stdenv.targetPlatform then 306 "bin lib ${stdenv.hostPlatform.config}" 307 else 308 null; 309 310 # INFO: Otherwise it fails with: 311 # `./sanity.sh: line 36: $out/bin/size: not found` 312 doInstallCheck = (buildPlatform == hostPlatform) && (hostPlatform == targetPlatform); 313 314 enableParallelBuilding = true; 315 316 # For the same reason we don't split "lib" output we undo the $target/ 317 # prefix for installed headers and libraries we link: 318 # $out/$host/$target/lib/* to $out/lib/ 319 # $out/$host/$target/include/* to $dev/include/* 320 # TODO(trofi): fix installation paths upstream so we could remove this 321 # code and have "lib" output unconditionally. 322 postInstall = 323 lib.optionalString (hostPlatform.config != targetPlatform.config) '' 324 ln -s $out/${hostPlatform.config}/${targetPlatform.config}/lib/* $out/lib/ 325 ln -s $out/${hostPlatform.config}/${targetPlatform.config}/include/* $dev/include/ 326 '' 327 + lib.optionalString withAllTargets '' 328 for target in ${lib.escapeShellArgs allGasTargets}; do 329 make -C "$NIX_BUILD_TOP/build-$target/gas" -j"$NIX_BUILD_CORES" \ 330 $makeFlags "''${makeFlagsArray[@]}" $installFlags "''${installFlagsArray[@]}" \ 331 install-exec-bindir 332 done 333 '' 334 + lib.optionalString (withAllTargets && targetHasGas) '' 335 ln -s $out/bin/${stdenv.targetPlatform.config}-as $out/bin/as 336 ''; 337 338 passthru = { 339 inherit targetPrefix; 340 hasGold = enableGold; 341 isGNU = true; 342 343 # The plugin API is not a function of any targets. Expose it separately, 344 # currently only used by LLVM for enabling BFD to do LTO with LLVM bitcode. 345 # (Tar will exit with an error if there are no matches). 346 plugin-api-header = runCommand "libbfd-plugin-api-header" { } '' 347 mkdir -p $out 348 tar --directory=$out \ 349 --extract \ 350 --file=${finalAttrs.src} \ 351 --strip-components=1 \ 352 --wildcards '*'/include/plugin-api.h 353 ''; 354 }; 355 356 meta = with lib; { 357 description = "Tools for manipulating binaries (linker, assembler, etc.)"; 358 longDescription = '' 359 The GNU Binutils are a collection of binary tools. The main 360 ones are `ld' (the GNU linker) and `as' (the GNU assembler). 361 They also include the BFD (Binary File Descriptor) library, 362 `gprof', `nm', `strip', etc. 363 ''; 364 homepage = "https://www.gnu.org/software/binutils/"; 365 license = licenses.gpl3Plus; 366 maintainers = with maintainers; [ 367 ericson2314 368 lovesegfault 369 ]; 370 platforms = platforms.unix; 371 372 # INFO: Give binutils a lower priority than gcc-wrapper to prevent a 373 # collision due to the ld/as wrappers/symlinks in the latter. 374 priority = 10; 375 }; 376})