nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 489 lines 18 kB view raw
1{ 2 lib, 3 stdenv, 4 # LLVM version closest to ROCm fork to override 5 llvmPackages_20, 6 overrideCC, 7 lndir, 8 rocm-device-libs, 9 fetchFromGitHub, 10 runCommand, 11 symlinkJoin, 12 rdfind, 13 zstd, 14 gcc-unwrapped, 15 glibc, 16 replaceVars, 17 libffi, 18 libxml2, 19 removeReferencesTo, 20 fetchpatch, 21 # Build compilers and stdenv suitable for profiling 22 # leaving compressed line tables (-g1 -gz) unstripped 23 # TODO: Should also apply to downstream packages which use rocmClangStdenv? 24 profilableStdenv ? false, 25 # Whether to use LTO when building the ROCm toolchain 26 # Slows down this toolchain's build, for typical ROCm usecase 27 # time saved building composable_kernel and other heavy packages 28 # will outweight that. ~3-4% speedup multiplied by thousands 29 # of corehours. 30 withLto ? true, 31 # whether rocm stdenv uses libcxx (clang c++ stdlib) instead of gcc stdlibc++ 32 withLibcxx ? false, 33}: 34 35let 36 version = "7.1.1"; 37 # major version of this should be the clang version ROCm forked from 38 rocmLlvmVersion = "20.0.0-rocm"; 39 # llvmPackages_base version should match rocmLlvmVersion 40 # so libllvm's bitcode is compatible with the built toolchain 41 llvmPackages_base = llvmPackages_20; 42 llvmPackagesNoBintools = llvmPackages_base.override { 43 bootBintools = null; 44 bootBintoolsNoLibc = null; 45 }; 46 47 stdenvToBuildRocmLlvm = 48 if withLibcxx then 49 overrideCC llvmPackagesNoBintools.libcxxStdenv llvmPackagesNoBintools.clangUseLLVM 50 else 51 # oddly fuse-ld=lld fails without this override 52 overrideCC llvmPackagesNoBintools.stdenv ( 53 llvmPackagesNoBintools.libstdcxxClang.override { 54 inherit (llvmPackages_base) bintools; 55 } 56 ); 57 58 gcc-include = runCommand "gcc-include" { } '' 59 mkdir -p $out 60 ln -s ${gcc-unwrapped}/include/ $out/ 61 ln -s ${gcc-unwrapped}/lib/ $out/ 62 ''; 63 64 disallowedRefsForToolchain = [ 65 stdenv.cc 66 stdenv.cc.cc 67 stdenv.cc.bintools 68 gcc-unwrapped 69 stdenvToBuildRocmLlvm 70 stdenvToBuildRocmLlvm.cc 71 stdenvToBuildRocmLlvm.cc.cc 72 ]; 73 # A prefix for use as the GCC prefix when building rocm-toolchain 74 gcc-prefix-headers = symlinkJoin { 75 name = "gcc-prefix-headers"; 76 paths = [ 77 glibc.dev 78 gcc-unwrapped.out 79 ]; 80 disallowedRequisites = [ 81 glibc.dev 82 gcc-unwrapped.out 83 ]; 84 postBuild = '' 85 rm -rf $out/{bin,libexec,nix-support,lib64,share,etc} 86 rm $out/lib/gcc/x86_64-unknown-linux-gnu/*/plugin/include/auto-host.h 87 88 mkdir /build/tmpout 89 mv $out/* /build/tmpout 90 cp -Lr --no-preserve=mode /build/tmpout/* $out/ 91 set -x 92 versionedIncludePath="$(echo $out/include/c++/*/)" 93 mv $versionedIncludePath/* $out/include/c++/ 94 rm -rf $versionedIncludePath/ 95 ''; 96 }; 97 gcc-prefix = symlinkJoin { 98 name = "gcc-prefix"; 99 paths = [ 100 gcc-prefix-headers 101 glibc 102 gcc-unwrapped.lib 103 ]; 104 disallowedRequisites = [ 105 glibc.dev 106 gcc-unwrapped.out 107 ]; 108 postBuild = '' 109 rm -rf $out/{bin,libexec,nix-support,lib64,share,etc} 110 rm $out/lib/ld-linux-x86-64.so.2 111 ln -s $out $out/x86_64-unknown-linux-gnu 112 ''; 113 }; 114 llvmSrc = fetchFromGitHub { 115 owner = "ROCm"; 116 repo = "llvm-project"; 117 rev = "rocm-${version}"; 118 hash = "sha256-CfknIRVeR1bCKh1xzXKl3ehVp0kWT0uGrI9C1HTSKVo="; 119 }; 120 llvmMajorVersion = lib.versions.major rocmLlvmVersion; 121 # An llvmPackages (pkgs/development/compilers/llvm/) built from ROCm LLVM's source tree 122 llvmPackagesRocm = llvmPackages_base.override (_old: { 123 stdenv = stdenvToBuildRocmLlvm; 124 125 # not setting gitRelease = because that causes patch selection logic to use git patches 126 # ROCm LLVM is closer to 20 official 127 # gitRelease = {}; officialRelease = null; 128 officialRelease = { }; # Set but empty because we're overriding everything from it. 129 # this version determines which patches are applied 130 version = rocmLlvmVersion; 131 src = llvmSrc; 132 monorepoSrc = llvmSrc; 133 doCheck = false; 134 }); 135 refsToRemove = builtins.concatStringsSep " -t " [ 136 stdenvToBuildRocmLlvm 137 stdenvToBuildRocmLlvm.cc 138 stdenvToBuildRocmLlvm.cc.cc 139 stdenv.cc 140 stdenv.cc.cc 141 stdenv.cc.bintools 142 ]; 143 # Hacky way to avoid nixfmt indenting the entire scope body suggested by @emilazy 144 overrideLlvmPackagesRocm = 145 f: 146 let 147 overridenScope = llvmPackagesRocm.overrideScope (final: prev: f { inherit final prev; }); 148 in 149 { 150 inherit (overridenScope) 151 # Expose only a limited set of packages that we care about for ROCm 152 bintools 153 compiler-rt 154 compiler-rt-libc 155 clang 156 clang-unwrapped 157 libcxx 158 lld 159 llvm 160 rocm-toolchain 161 rocmClangStdenv 162 openmp 163 ; 164 }; 165 sysrootCompiler = 166 { 167 cc, 168 name, 169 paths, 170 linkPaths, 171 }: 172 let 173 linked = symlinkJoin { inherit name paths; }; 174 in 175 runCommand name 176 { 177 # If this is erroring, try why-depends --precise on the symlinkJoin of inputs to look for the problem 178 # nix why-depends --precise .#rocmPackages.llvm.rocm-toolchain.linked /store/path/its/not/allowed 179 disallowedRequisites = disallowedRefsForToolchain; 180 passthru.linked = linked; 181 linkPaths = linkPaths; 182 passAsFile = [ "linkPaths" ]; 183 # TODO(@LunNova): Try to use --sysroot with clang in its original location instead of 184 # relying on copying the binary? 185 # $clang/bin/clang++ --sysroot=$rocm-toolchain is not equivalent 186 # to a clang copied to $rocm-toolchain/bin here, have not yet figured out why 187 } 188 '' 189 mkdir -p $out/ 190 cp --reflink=auto -rL ${linked}/* $out/ 191 chmod -R +rw $out 192 mkdir -p $out/usr 193 ln -s $out/ $out/usr/local 194 # we don't need mixed 32 bit, the presence of lib64 is used by LLVM to decide it's a multilib sysroot 195 rm -rf $out/lib64 196 rm -rf $out/lib/cmake $out/lib/lib*.a 197 mkdir -p $out/lib/clang/${llvmMajorVersion}/lib/linux/ 198 ln -s $out/lib/linux/libclang_rt.* $out/lib/clang/${llvmMajorVersion}/lib/linux/ 199 200 find $out -type f -exec sed -i "s|${cc.out}|$out|g" {} + 201 find $out -type f -exec sed -i "s|${cc.dev}|$out|g" {} + 202 203 ${lib.getExe rdfind} -makesymlinks true ${ 204 builtins.concatStringsSep " " (map (x: "${x}/lib") paths) 205 } $out/ # create links *within* the sysroot to save space 206 207 for i in $(cat $linkPathsPath); do 208 ${lib.getExe lndir} -silent $i $out 209 done 210 211 echo 'export CC=clang' >> $out/nix-support/setup-hook 212 echo 'export CXX=clang++' >> $out/nix-support/setup-hook 213 ''; 214 tablegenUsage = x: !(lib.strings.hasInfix "llvm-tblgen" x); 215 llvmTargetsFlag = "-DLLVM_TARGETS_TO_BUILD=AMDGPU;${ 216 { 217 "x86_64" = "X86"; 218 "aarch64" = "AArch64"; 219 } 220 .${stdenv.targetPlatform.parsed.cpu.name} 221 or (throw "Unsupported CPU architecture: ${stdenv.targetPlatform.parsed.cpu.name}") 222 }"; 223 llvmMeta = { 224 # TODO(@LunNova): it would be nice to support aarch64 for rocmPackages 225 platforms = [ "x86_64-linux" ]; 226 }; 227 # TODO(@LunNova): Some of this might be worth supporting in llvmPackages, dropping from here 228 commonCmakeFlags = [ 229 llvmTargetsFlag 230 # Compression support is required for compressed offload kernels 231 # Set FORCE_ON so that failure to find the compression lib will be a build error 232 (lib.cmakeFeature "LLVM_ENABLE_ZSTD" "FORCE_ON") 233 # required for threaded ThinLTO to work 234 (lib.cmakeBool "LLVM_ENABLE_THREADS" true) 235 # LLVM tries to call git to embed VCS info if FORCE_VC_ aren't set 236 (lib.cmakeFeature "LLVM_FORCE_VC_REVISION" "rocm-${version}") 237 (lib.cmakeFeature "LLVM_FORCE_VC_REPOSITORY" "https://github.com/ROCm/llvm-project") 238 (lib.cmakeFeature "LLVM_VERSION_SUFFIX" "") 239 (lib.cmakeBool "LLVM_ENABLE_LIBCXX" withLibcxx) 240 (lib.cmakeFeature "CLANG_DEFAULT_CXX_STDLIB" (if withLibcxx then "libc++" else "libstdc++")) 241 (lib.cmakeFeature "CLANG_VENDOR" "nixpkgs-AMD") 242 (lib.cmakeFeature "CLANG_REPOSITORY_STRING" "https://github.com/ROCm/llvm-project/tree/rocm-${version}") 243 ] 244 ++ lib.optionals withLibcxx [ 245 (lib.cmakeFeature "CLANG_DEFAULT_RTLIB" "compiler-rt") 246 ] 247 ++ lib.optionals withLto [ 248 (lib.cmakeBool "CMAKE_INTERPROCEDURAL_OPTIMIZATION" true) 249 (lib.cmakeBool "LLVM_ENABLE_FATLTO" false) 250 ] 251 ++ lib.optionals (withLto && stdenvToBuildRocmLlvm.cc.isClang) [ 252 (lib.cmakeFeature "LLVM_ENABLE_LTO" "FULL") 253 (lib.cmakeFeature "LLVM_USE_LINKER" "lld") 254 ]; 255 256 llvmExtraCflags = lib.concatStringsSep " " ( 257 lib.optionals (stdenv.hostPlatform.system == "x86_64-linux") [ 258 # Unprincipled decision to build x86_64 ROCm clang for at least skylake and tune for zen3+ 259 # In practice building the ROCm package set with anything earlier than zen3 is annoying 260 # and earlier than skylake is implausible due to too few cores and too little RAM 261 # Speeds up composable_kernel builds by ~4% 262 # If this causes trouble in practice we can drop this. Set since 2025-03-24. 263 "-march=skylake" 264 "-mtune=znver3" 265 ] 266 ++ lib.optionals profilableStdenv [ 267 # compressed line only debug info for profiling 268 "-gz" 269 "-g1" 270 ] 271 ); 272 inherit (llvmPackagesRocm) libcxx; 273in 274overrideLlvmPackagesRocm (s: { 275 libllvm = (s.prev.libllvm.override { }).overrideAttrs (old: { 276 patches = old.patches ++ [ 277 (fetchpatch { 278 # fix compile error in tools/gold/gold-plugin.cpp 279 name = "gold-plugin-fix.patch"; 280 url = "https://github.com/llvm/llvm-project/commit/b0baa1d8bd68a2ce2f7c5f2b62333e410e9122a1.patch"; 281 hash = "sha256-yly93PvGIXOnFeDGZ2W+W6SyhdWFM6iwA+qOeaptrh0="; 282 relative = "llvm"; 283 }) 284 ./perf-increase-namestring-size.patch 285 # TODO: consider reapplying "Don't include aliases in RegisterClassInfo::IgnoreCSRForAllocOrder" 286 # it was reverted as it's a pessimization for non-GPU archs, but this compiler 287 # is used mostly for amdgpu 288 ]; 289 dontStrip = profilableStdenv; 290 hardeningDisable = [ "all" ]; 291 nativeBuildInputs = old.nativeBuildInputs ++ [ removeReferencesTo ]; 292 buildInputs = old.buildInputs ++ [ 293 zstd 294 ]; 295 preFixup = '' 296 moveToOutput "lib/lib*.a" "$dev" 297 moveToOutput "lib/cmake" "$dev" 298 sed -Ei "s|$lib/lib/(lib[^/]*)\.a|$dev/lib/\1.a|g" $dev/lib/cmake/llvm/*.cmake 299 ''; 300 env = (old.env or { }) // { 301 NIX_CFLAGS_COMPILE = "${(old.env or { }).NIX_CFLAGS_COMPILE or ""} ${llvmExtraCflags}"; 302 }; 303 cmakeFlags = (builtins.filter tablegenUsage old.cmakeFlags) ++ commonCmakeFlags; 304 # Ensure we don't leak refs to compiler that was used to bootstrap this LLVM 305 disallowedReferences = (old.disallowedReferences or [ ]) ++ disallowedRefsForToolchain; 306 postFixup = '' 307 ${old.postFixup or ""} 308 find $lib -type f -exec remove-references-to -t ${refsToRemove} {} + 309 ''; 310 meta = old.meta // llvmMeta; 311 }); 312 lld = 313 (s.prev.lld.override { 314 }).overrideAttrs 315 (old: { 316 dontStrip = profilableStdenv; 317 hardeningDisable = [ "all" ]; 318 nativeBuildInputs = old.nativeBuildInputs ++ [ 319 removeReferencesTo 320 ]; 321 buildInputs = old.buildInputs ++ [ 322 zstd 323 ]; 324 env = (old.env or { }) // { 325 NIX_CFLAGS_COMPILE = "${(old.env or { }).NIX_CFLAGS_COMPILE or ""} ${llvmExtraCflags}"; 326 }; 327 cmakeFlags = (builtins.filter tablegenUsage old.cmakeFlags) ++ commonCmakeFlags; 328 # Ensure we don't leak refs to compiler that was used to bootstrap this LLVM 329 disallowedReferences = (old.disallowedReferences or [ ]) ++ disallowedRefsForToolchain; 330 postFixup = '' 331 ${old.postFixup or ""} 332 find $lib -type f -exec remove-references-to -t ${refsToRemove} {} + 333 ''; 334 meta = old.meta // llvmMeta; 335 }); 336 clang-unwrapped = ( 337 (s.prev.clang-unwrapped.override { 338 enableClangToolsExtra = false; 339 }).overrideAttrs 340 (old: { 341 passthru = old.passthru // { 342 inherit gcc-prefix; 343 }; 344 patches = old.patches ++ [ 345 # Never add FHS include paths 346 ./clang-bodge-ignore-systemwide-incls.diff 347 # Prevents builds timing out if a single compiler invocation is very slow but 348 # per-arch jobs are completing by ensuring there's terminal output 349 ./clang-log-jobs.diff 350 ./opt-offload-compress-on-by-default.patch 351 ./perf-shorten-gcclib-include-paths.patch 352 (fetchpatch { 353 # [ClangOffloadBundler]: Add GetBundleIDsInFile to OffloadBundler 354 sha256 = "sha256-G/mzUdFfrJ2bLJgo4+mBcR6Ox7xGhWu5X+XxT4kH2c8="; 355 url = "https://github.com/GZGavinZhao/rocm-llvm-project/commit/6d296f879b0fed830c54b2a9d26240da86c8bb3a.patch"; 356 relative = "clang"; 357 }) 358 ]; 359 hardeningDisable = [ "all" ]; 360 nativeBuildInputs = old.nativeBuildInputs ++ [ 361 removeReferencesTo 362 ]; 363 buildInputs = old.buildInputs ++ [ 364 zstd 365 ]; 366 env = (old.env or { }) // { 367 NIX_CFLAGS_COMPILE = "${(old.env or { }).NIX_CFLAGS_COMPILE or ""} ${llvmExtraCflags}"; 368 }; 369 dontStrip = profilableStdenv; 370 # Ensure we don't leak refs to compiler that was used to bootstrap this LLVM 371 disallowedReferences = (old.disallowedReferences or [ ]) ++ disallowedRefsForToolchain; 372 # Enable structured attrs for separateDebugInfo, because it is required with disallowedReferences set 373 __structuredAttrs = true; 374 # https://github.com/llvm/llvm-project/blob/6976deebafa8e7de993ce159aa6b82c0e7089313/clang/cmake/caches/DistributionExample-stage2.cmake#L9-L11 375 cmakeFlags = 376 # TODO: Remove in followup, tblgen now works correctly but would rebuild 377 (builtins.filter tablegenUsage old.cmakeFlags) 378 ++ commonCmakeFlags 379 ++ lib.optionals (!withLibcxx) [ 380 # FIXME: Config file in rocm-toolchain instead of GCC_INSTALL_PREFIX? 381 # Expected to be fully removed eventually 382 "-DUSE_DEPRECATED_GCC_INSTALL_PREFIX=ON" 383 "-DGCC_INSTALL_PREFIX=${gcc-prefix}" 384 ]; 385 preFixup = '' 386 ${toString old.preFixup or ""} 387 moveToOutput "lib/lib*.a" "$dev" 388 moveToOutput "lib/cmake" "$dev" 389 mkdir -p $dev/lib/clang/ 390 ln -s $lib/lib/clang/${llvmMajorVersion} $dev/lib/clang/ 391 sed -Ei "s|$lib/lib/(lib[^/]*)\.a|$dev/lib/\1.a|g" $dev/lib/cmake/clang/*.cmake 392 ''; 393 postFixup = '' 394 ${toString old.postFixup or ""} 395 find $lib -type f -exec remove-references-to -t ${refsToRemove} {} + 396 find $dev -type f -exec remove-references-to -t ${refsToRemove} {} + 397 ''; 398 meta = old.meta // llvmMeta; 399 }) 400 ); 401 # A clang that understands standard include searching in a GNU sysroot and will put GPU libs in include path 402 # in the right order 403 # and expects its libc to be in the sysroot 404 rocm-toolchain = 405 with s.final; 406 (sysrootCompiler { 407 cc = clang-unwrapped; 408 name = "rocm-toolchain"; 409 paths = [ 410 clang-unwrapped.out 411 clang-unwrapped.lib 412 bintools.out 413 compiler-rt.out 414 openmp.out 415 openmp.dev 416 ] 417 ++ lib.optionals withLibcxx [ 418 libcxx 419 ] 420 ++ lib.optionals (!withLibcxx) [ 421 glibc 422 glibc.dev 423 ]; 424 linkPaths = [ 425 bintools.bintools.out 426 ] 427 ++ lib.optionals (!withLibcxx) [ 428 gcc-include.out 429 ]; 430 }) 431 // { 432 version = llvmMajorVersion; 433 cc = rocm-toolchain; 434 libllvm = llvm; 435 isClang = true; 436 isGNU = false; 437 }; 438 compiler-rt-libc = s.prev.compiler-rt-libc.overrideAttrs (old: { 439 patches = old.patches ++ [ 440 # fix build with glibc >= 2.42 441 (fetchpatch { 442 url = "https://github.com/llvm/llvm-project/commit/59978b21ad9c65276ee8e14f26759691b8a65763.patch"; 443 hash = "sha256-ys5SMLfO3Ay9nCX9GV5yRCQ6pLsseFu/ZY6Xd6OL4p0="; 444 relative = "compiler-rt"; 445 }) 446 ]; 447 meta = old.meta // llvmMeta; 448 }); 449 compiler-rt = s.final.compiler-rt-libc; 450 clang = s.final.rocm-toolchain; 451 452 rocmClangStdenv = with s.final; overrideCC (if withLibcxx then libcxxStdenv else stdenv) clang; 453 454 # Projects 455 openmp = 456 with s.final; 457 (llvmPackagesRocm.openmp.override { 458 llvm = llvm; 459 clang-unwrapped = clang-unwrapped; 460 }).overrideAttrs 461 (old: { 462 disallowedReferences = (old.disallowedReferences or [ ]) ++ disallowedRefsForToolchain; 463 nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ 464 removeReferencesTo 465 ]; 466 cmakeFlags = 467 old.cmakeFlags 468 ++ commonCmakeFlags 469 ++ [ 470 "-DDEVICELIBS_ROOT=${rocm-device-libs.src}" 471 # OMPD support is broken in ROCm 6.3+ Haven't investigated why. 472 "-DLIBOMP_OMPD_SUPPORT:BOOL=FALSE" 473 "-DLIBOMP_OMPD_GDB_SUPPORT:BOOL=FALSE" 474 ]; 475 buildInputs = old.buildInputs ++ [ 476 clang-unwrapped 477 zstd 478 libxml2 479 libffi 480 ]; 481 postFixup = '' 482 ${old.postFixup or ""} 483 ln -s $out/lib/libomp.so $dev/lib/libomp.so 484 ''; 485 }); 486 # AMD has a separate MLIR impl which we package under rocmPackages.rocmlir 487 # It would be an error to rely on the original mlir package from this scope 488 mlir = null; 489})