1{
2 lowPrio,
3 newScope,
4 pkgs,
5 targetPackages,
6 lib,
7 stdenv,
8 libxcrypt,
9 substitute,
10 replaceVars,
11 fetchFromGitHub,
12 fetchpatch,
13 fetchpatch2,
14 overrideCC,
15 wrapCCWith,
16 wrapBintoolsWith,
17 buildPackages,
18 buildLlvmTools, # tools, but from the previous stage, for cross
19 targetLlvmLibraries, # libraries, but from the next stage, for cross
20 targetLlvm,
21 # This is the default binutils, but with *this* version of LLD rather
22 # than the default LLVM version's, if LLD is the choice. We use these for
23 # the `useLLVM` bootstrapping below.
24 bootBintoolsNoLibc ? if stdenv.targetPlatform.linker == "lld" then null else pkgs.bintoolsNoLibc,
25 bootBintools ? if stdenv.targetPlatform.linker == "lld" then null else pkgs.bintools,
26 darwin,
27 gitRelease ? null,
28 officialRelease ? null,
29 monorepoSrc ? null,
30 version ? null,
31 patchesFn ? lib.id,
32 # Allows passthrough to packages via newScope. This makes it possible to
33 # do `(llvmPackages.override { <someLlvmDependency> = bar; }).clang` and get
34 # an llvmPackages whose packages are overridden in an internally consistent way.
35 ...
36}@args:
37
38assert lib.assertMsg (lib.xor (gitRelease != null) (officialRelease != null)) (
39 "must specify `gitRelease` or `officialRelease`"
40 + (lib.optionalString (gitRelease != null) " — not both")
41);
42
43let
44 monorepoSrc' = monorepoSrc;
45
46 metadata = rec {
47 # Import releaseInfo separately to avoid infinite recursion
48 inherit
49 (import ./common-let.nix {
50 inherit (args)
51 lib
52 gitRelease
53 officialRelease
54 version
55 ;
56 })
57 releaseInfo
58 ;
59 inherit (releaseInfo) release_version version;
60 inherit
61 (import ./common-let.nix {
62 inherit
63 lib
64 fetchFromGitHub
65 release_version
66 gitRelease
67 officialRelease
68 monorepoSrc'
69 version
70 ;
71 })
72 llvm_meta
73 monorepoSrc
74 ;
75 src = monorepoSrc;
76 versionDir =
77 (builtins.toString ../.)
78 + "/${if (gitRelease != null) then "git" else lib.versions.major release_version}";
79 getVersionFile =
80 p:
81 builtins.path {
82 name = builtins.baseNameOf p;
83 path =
84 let
85 patches = args.patchesFn (import ./patches.nix);
86
87 constraints = patches."${p}" or null;
88 matchConstraint =
89 {
90 before ? null,
91 after ? null,
92 path,
93 }:
94 let
95 check = fn: value: if value == null then true else fn release_version value;
96 matchBefore = check lib.versionOlder before;
97 matchAfter = check lib.versionAtLeast after;
98 in
99 matchBefore && matchAfter;
100
101 patchDir =
102 toString
103 (
104 if constraints == null then
105 { path = metadata.versionDir; }
106 else
107 (lib.findFirst matchConstraint { path = metadata.versionDir; } constraints)
108 ).path;
109 in
110 "${patchDir}/${p}";
111 };
112 };
113
114 tools = lib.makeExtensible (
115 tools:
116 let
117 callPackage = newScope (tools // args // metadata);
118 clangVersion =
119 if (lib.versionOlder metadata.release_version "16") then
120 metadata.release_version
121 else
122 lib.versions.major metadata.release_version;
123 mkExtraBuildCommands0 =
124 cc:
125 ''
126 rsrc="$out/resource-root"
127 mkdir "$rsrc"
128 echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags
129 ''
130 # clang standard c headers are incompatible with FreeBSD so we have to put them in -idirafter instead of -resource-dir
131 # see https://github.com/freebsd/freebsd-src/commit/f382bac49b1378da3c2dd66bf721beaa16b5d471
132 + (
133 if stdenv.targetPlatform.isFreeBSD then
134 ''
135 echo "-idirafter ${lib.getLib cc}/lib/clang/${clangVersion}/include" >> $out/nix-support/cc-cflags
136 ''
137 else
138 ''
139 ln -s "${lib.getLib cc}/lib/clang/${clangVersion}/include" "$rsrc"
140 ''
141 );
142 mkExtraBuildCommandsBasicRt =
143 cc:
144 mkExtraBuildCommands0 cc
145 + ''
146 ln -s "${targetLlvmLibraries.compiler-rt-no-libc.out}/lib" "$rsrc/lib"
147 '';
148 mkExtraBuildCommands =
149 cc:
150 mkExtraBuildCommands0 cc
151 + ''
152 ln -s "${targetLlvmLibraries.compiler-rt.out}/lib" "$rsrc/lib"
153 ln -s "${targetLlvmLibraries.compiler-rt.out}/share" "$rsrc/share"
154 '';
155
156 bintoolsNoLibc' = if bootBintoolsNoLibc == null then tools.bintoolsNoLibc else bootBintoolsNoLibc;
157 bintools' = if bootBintools == null then tools.bintools else bootBintools;
158 in
159 {
160 libllvm = callPackage ./llvm {
161 };
162
163 # `llvm` historically had the binaries. When choosing an output explicitly,
164 # we need to reintroduce `outputSpecified` to get the expected behavior e.g. of lib.get*
165 llvm = tools.libllvm;
166
167 tblgen = callPackage ./tblgen.nix {
168 patches =
169 builtins.filter
170 # Crude method to drop polly patches if present, they're not needed for tblgen.
171 (p: (!lib.hasInfix "-polly" p))
172 tools.libllvm.patches;
173 clangPatches = [
174 # Would take tools.libclang.patches, but this introduces a cycle due
175 # to replacements depending on the llvm outpath (e.g. the LLVMgold patch).
176 # So take the only patch known to be necessary.
177 (metadata.getVersionFile "clang/gnu-install-dirs.patch")
178 ]
179 ++
180 lib.optional (stdenv.isAarch64 && lib.versions.major metadata.release_version == "17")
181 # Fixes llvm17 tblgen builds on aarch64.
182 # https://github.com/llvm/llvm-project/issues/106521#issuecomment-2337175680
183 (metadata.getVersionFile "clang/aarch64-tblgen.patch");
184 };
185
186 libclang = callPackage ./clang {
187 };
188
189 clang-unwrapped = tools.libclang;
190
191 llvm-manpages = lowPrio (
192 tools.libllvm.override {
193 enableManpages = true;
194 python3 = pkgs.python3; # don't use python-boot
195 }
196 );
197
198 clang-manpages = lowPrio (
199 tools.libclang.override {
200 enableManpages = true;
201 python3 = pkgs.python3; # don't use python-boot
202 }
203 );
204
205 # Wrapper for standalone command line utilities
206 clang-tools = callPackage ./clang-tools { };
207
208 # pick clang appropriate for package set we are targeting
209 clang =
210 if stdenv.targetPlatform.libc == null then
211 tools.clangNoLibc
212 else if stdenv.targetPlatform.useLLVM or false then
213 tools.clangUseLLVM
214 else if (pkgs.targetPackages.stdenv or args.stdenv).cc.isGNU then
215 tools.libstdcxxClang
216 else
217 tools.libcxxClang;
218
219 libstdcxxClang = wrapCCWith rec {
220 cc = tools.clang-unwrapped;
221 # libstdcxx is taken from gcc in an ad-hoc way in cc-wrapper.
222 libcxx = null;
223 extraPackages = [ targetLlvmLibraries.compiler-rt ];
224 extraBuildCommands = mkExtraBuildCommands cc;
225 };
226
227 libcxxClang = wrapCCWith rec {
228 cc = tools.clang-unwrapped;
229 libcxx = targetLlvmLibraries.libcxx;
230 extraPackages = [ targetLlvmLibraries.compiler-rt ];
231 extraBuildCommands = mkExtraBuildCommands cc;
232 };
233
234 lld = callPackage ./lld {
235 };
236
237 lldbPlugins = lib.makeExtensible (
238 lldbPlugins:
239 let
240 callPackage = newScope (lldbPlugins // tools // args // metadata);
241 in
242 lib.recurseIntoAttrs { llef = callPackage ./lldb-plugins/llef.nix { }; }
243 );
244
245 lldb = callPackage ./lldb (
246 {
247 }
248 // lib.optionalAttrs (lib.versions.major metadata.release_version == "16") {
249 src = callPackage (
250 { runCommand }:
251 runCommand "lldb-src-${metadata.version}" { } ''
252 mkdir -p "$out"
253 cp -r ${monorepoSrc}/cmake "$out"
254 cp -r ${monorepoSrc}/lldb "$out"
255 ''
256 ) { };
257 }
258 );
259
260 # Below, is the LLVM bootstrapping logic. It handles building a
261 # fully LLVM toolchain from scratch. No GCC toolchain should be
262 # pulled in. As a consequence, it is very quick to build different
263 # targets provided by LLVM and we can also build for what GCC
264 # doesn’t support like LLVM. Probably we should move to some other
265 # file.
266
267 bintools-unwrapped = callPackage ./bintools.nix { };
268
269 bintoolsNoLibc = wrapBintoolsWith {
270 bintools = tools.bintools-unwrapped;
271 libc = targetPackages.preLibcHeaders;
272 };
273
274 bintools = wrapBintoolsWith { bintools = tools.bintools-unwrapped; };
275
276 clangUseLLVM = wrapCCWith (
277 rec {
278 cc = tools.clang-unwrapped;
279 libcxx = targetLlvmLibraries.libcxx;
280 bintools = bintools';
281 extraPackages = [
282 targetLlvmLibraries.compiler-rt
283 ]
284 ++ lib.optionals (!stdenv.targetPlatform.isWasm && !stdenv.targetPlatform.isFreeBSD) [
285 targetLlvmLibraries.libunwind
286 ];
287 extraBuildCommands =
288 lib.optionalString (lib.versions.major metadata.release_version == "13") (
289 ''
290 echo "-rtlib=compiler-rt -Wno-unused-command-line-argument" >> $out/nix-support/cc-cflags
291 echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags
292 ''
293 + lib.optionalString (!stdenv.targetPlatform.isWasm) ''
294 echo "--unwindlib=libunwind" >> $out/nix-support/cc-cflags
295 echo "-L${targetLlvmLibraries.libunwind}/lib" >> $out/nix-support/cc-ldflags
296 ''
297 + lib.optionalString (!stdenv.targetPlatform.isWasm && stdenv.targetPlatform.useLLVM or false) ''
298 echo "-lunwind" >> $out/nix-support/cc-ldflags
299 ''
300 + lib.optionalString stdenv.targetPlatform.isWasm ''
301 echo "-fno-exceptions" >> $out/nix-support/cc-cflags
302 ''
303 )
304 + mkExtraBuildCommands cc;
305 }
306 // lib.optionalAttrs (lib.versionAtLeast metadata.release_version "14") {
307 nixSupport.cc-cflags = [
308 "-rtlib=compiler-rt"
309 "-Wno-unused-command-line-argument"
310 "-B${targetLlvmLibraries.compiler-rt}/lib"
311 ]
312 ++ lib.optional (
313 !stdenv.targetPlatform.isWasm && !stdenv.targetPlatform.isFreeBSD
314 ) "--unwindlib=libunwind"
315 ++ lib.optional (
316 !stdenv.targetPlatform.isWasm
317 && !stdenv.targetPlatform.isFreeBSD
318 && stdenv.targetPlatform.useLLVM or false
319 ) "-lunwind"
320 ++ lib.optional stdenv.targetPlatform.isWasm "-fno-exceptions";
321 nixSupport.cc-ldflags = lib.optionals (
322 !stdenv.targetPlatform.isWasm && !stdenv.targetPlatform.isFreeBSD
323 ) [ "-L${targetLlvmLibraries.libunwind}/lib" ];
324 }
325 );
326
327 clangWithLibcAndBasicRtAndLibcxx = wrapCCWith (
328 rec {
329 cc = tools.clang-unwrapped;
330 libcxx = targetLlvmLibraries.libcxx;
331 bintools = bintools';
332 extraPackages = [
333 targetLlvmLibraries.compiler-rt-no-libc
334 ]
335 ++
336 lib.optionals
337 (
338 !stdenv.targetPlatform.isWasm && !stdenv.targetPlatform.isFreeBSD && !stdenv.targetPlatform.isDarwin
339 )
340 [
341 targetLlvmLibraries.libunwind
342 ];
343 extraBuildCommands =
344 lib.optionalString (lib.versions.major metadata.release_version == "13") (
345 ''
346 echo "-rtlib=compiler-rt -Wno-unused-command-line-argument" >> $out/nix-support/cc-cflags
347 echo "-B${targetLlvmLibraries.compiler-rt-no-libc}/lib" >> $out/nix-support/cc-cflags
348 ''
349 + lib.optionalString (!stdenv.targetPlatform.isWasm && !stdenv.targetPlatform.isDarwin) ''
350 echo "--unwindlib=libunwind" >> $out/nix-support/cc-cflags
351 echo "-L${targetLlvmLibraries.libunwind}/lib" >> $out/nix-support/cc-ldflags
352 ''
353 + lib.optionalString (!stdenv.targetPlatform.isWasm && stdenv.targetPlatform.useLLVM or false) ''
354 echo "-lunwind" >> $out/nix-support/cc-ldflags
355 ''
356 + lib.optionalString stdenv.targetPlatform.isWasm ''
357 echo "-fno-exceptions" >> $out/nix-support/cc-cflags
358 ''
359 )
360 + mkExtraBuildCommandsBasicRt cc;
361 }
362 // lib.optionalAttrs (lib.versionAtLeast metadata.release_version "14") {
363 nixSupport.cc-cflags = [
364 "-rtlib=compiler-rt"
365 "-Wno-unused-command-line-argument"
366 "-B${targetLlvmLibraries.compiler-rt-no-libc}/lib"
367 ]
368 ++ lib.optional (
369 !stdenv.targetPlatform.isWasm && !stdenv.targetPlatform.isFreeBSD && !stdenv.targetPlatform.isDarwin
370 ) "--unwindlib=libunwind"
371 ++ lib.optional (
372 !stdenv.targetPlatform.isWasm
373 && !stdenv.targetPlatform.isFreeBSD
374 && stdenv.targetPlatform.useLLVM or false
375 ) "-lunwind"
376 ++ lib.optional stdenv.targetPlatform.isWasm "-fno-exceptions";
377 nixSupport.cc-ldflags = lib.optionals (
378 !stdenv.targetPlatform.isWasm && !stdenv.targetPlatform.isFreeBSD && !stdenv.targetPlatform.isDarwin
379 ) [ "-L${targetLlvmLibraries.libunwind}/lib" ];
380 }
381 );
382
383 clangWithLibcAndBasicRt = wrapCCWith (
384 rec {
385 cc = tools.clang-unwrapped;
386 libcxx = null;
387 bintools = bintools';
388 extraPackages = [ targetLlvmLibraries.compiler-rt-no-libc ];
389 extraBuildCommands =
390 lib.optionalString (lib.versions.major metadata.release_version == "13") ''
391 echo "-rtlib=compiler-rt" >> $out/nix-support/cc-cflags
392 echo "-B${targetLlvmLibraries.compiler-rt-no-libc}/lib" >> $out/nix-support/cc-cflags
393 echo "-nostdlib++" >> $out/nix-support/cc-cflags
394 ''
395 + mkExtraBuildCommandsBasicRt cc;
396 }
397 // lib.optionalAttrs (lib.versionAtLeast metadata.release_version "14") {
398 nixSupport.cc-cflags = [
399 "-rtlib=compiler-rt"
400 "-B${targetLlvmLibraries.compiler-rt-no-libc}/lib"
401 "-nostdlib++"
402 ]
403 ++ lib.optional (
404 lib.versionAtLeast metadata.release_version "15" && stdenv.targetPlatform.isWasm
405 ) "-fno-exceptions";
406 }
407 );
408
409 clangNoLibcWithBasicRt = wrapCCWith (
410 rec {
411 cc = tools.clang-unwrapped;
412 libcxx = null;
413 bintools = bintoolsNoLibc';
414 extraPackages = [ targetLlvmLibraries.compiler-rt-no-libc ];
415 extraBuildCommands =
416 lib.optionalString (lib.versions.major metadata.release_version == "13") ''
417 echo "-rtlib=compiler-rt" >> $out/nix-support/cc-cflags
418 echo "-B${targetLlvmLibraries.compiler-rt-no-libc}/lib" >> $out/nix-support/cc-cflags
419 ''
420 + mkExtraBuildCommandsBasicRt cc;
421 }
422 // lib.optionalAttrs (lib.versionAtLeast metadata.release_version "14") {
423 nixSupport.cc-cflags = [
424 "-rtlib=compiler-rt"
425 "-B${targetLlvmLibraries.compiler-rt-no-libc}/lib"
426 ]
427 ++ lib.optional (
428 lib.versionAtLeast metadata.release_version "15" && stdenv.targetPlatform.isWasm
429 ) "-fno-exceptions";
430 }
431 );
432
433 clangNoLibcNoRt = wrapCCWith (
434 rec {
435 cc = tools.clang-unwrapped;
436 libcxx = null;
437 bintools = bintoolsNoLibc';
438 extraPackages = [ ];
439 # "-nostartfiles" used to be needed for pkgsLLVM, causes problems so don't include it.
440 extraBuildCommands = mkExtraBuildCommands0 cc;
441 }
442 // lib.optionalAttrs (lib.versionAtLeast metadata.release_version "14") {
443 # "-nostartfiles" used to be needed for pkgsLLVM, causes problems so don't include it.
444 nixSupport.cc-cflags = lib.optional (
445 lib.versionAtLeast metadata.release_version "15" && stdenv.targetPlatform.isWasm
446 ) "-fno-exceptions";
447 }
448 );
449
450 # This is an "oddly ordered" bootstrap just for Darwin. Probably
451 # don't want it otherwise.
452 clangNoCompilerRtWithLibc =
453 wrapCCWith rec {
454 cc = tools.clang-unwrapped;
455 libcxx = null;
456 bintools = bintools';
457 extraPackages = [ ];
458 extraBuildCommands = mkExtraBuildCommands0 cc;
459 }
460 // lib.optionalAttrs (
461 lib.versionAtLeast metadata.release_version "15" && stdenv.targetPlatform.isWasm
462 ) { nixSupport.cc-cflags = [ "-fno-exceptions" ]; };
463
464 # Aliases
465 clangNoCompilerRt = tools.clangNoLibcNoRt;
466 clangNoLibc = tools.clangNoLibcWithBasicRt;
467 clangNoLibcxx = tools.clangWithLibcAndBasicRt;
468 }
469 // lib.optionalAttrs (lib.versionAtLeast metadata.release_version "15") {
470 # TODO: pre-15: lldb/docs/index.rst:155:toctree contains reference to nonexisting document 'design/structureddataplugins'
471 lldb-manpages = lowPrio (
472 tools.lldb.override {
473 enableManpages = true;
474 python3 = pkgs.python3; # don't use python-boot
475 }
476 );
477 }
478 // lib.optionalAttrs (lib.versionAtLeast metadata.release_version "16") {
479 mlir = callPackage ./mlir { };
480 }
481 // lib.optionalAttrs (lib.versionAtLeast metadata.release_version "19") {
482 bolt = callPackage ./bolt {
483 };
484 }
485 //
486 lib.optionalAttrs
487 (lib.versionAtLeast metadata.release_version "16" && lib.versionOlder metadata.release_version "20")
488 {
489 libclc = callPackage ./libclc { };
490 }
491 );
492
493 libraries = lib.makeExtensible (
494 libraries:
495 let
496 callPackage = newScope (
497 libraries
498 // buildLlvmTools
499 // args
500 // metadata
501 # Previously monorepoSrc was erroneously not being passed through.
502 // lib.optionalAttrs (lib.versionOlder metadata.release_version "14") { monorepoSrc = null; } # Preserve a bug during #307211, TODO: remove; causes llvm 13 rebuild.
503 );
504 in
505 (
506 {
507 compiler-rt-libc = callPackage ./compiler-rt (
508 let
509 # temp rename to avoid infinite recursion
510 stdenv =
511 # Darwin needs to use a bootstrap stdenv to avoid an infinite recursion when cross-compiling.
512 if args.stdenv.hostPlatform.isDarwin then
513 overrideCC darwin.bootstrapStdenv buildLlvmTools.clangWithLibcAndBasicRtAndLibcxx
514 else if args.stdenv.hostPlatform.useLLVM or false then
515 overrideCC args.stdenv buildLlvmTools.clangWithLibcAndBasicRtAndLibcxx
516 else
517 args.stdenv;
518 in
519 {
520 inherit stdenv;
521 }
522 // lib.optionalAttrs (stdenv.hostPlatform.useLLVM or false) {
523 libxcrypt = (libxcrypt.override { inherit stdenv; }).overrideAttrs (old: {
524 configureFlags = old.configureFlags ++ [ "--disable-symvers" ];
525 });
526 }
527 );
528
529 compiler-rt-no-libc = callPackage ./compiler-rt {
530 doFakeLibgcc = stdenv.hostPlatform.useLLVM or false;
531 stdenv =
532 # Darwin needs to use a bootstrap stdenv to avoid an infinite recursion when cross-compiling.
533 if stdenv.hostPlatform.isDarwin then
534 overrideCC darwin.bootstrapStdenv buildLlvmTools.clangNoLibcNoRt
535 else
536 overrideCC stdenv buildLlvmTools.clangNoLibcNoRt;
537 };
538
539 compiler-rt =
540 if
541 stdenv.hostPlatform.libc == null
542 # Building the with-libc compiler-rt and WASM doesn't yet work,
543 # because wasilibc doesn't provide some expected things. See
544 # compiler-rt's file for further details.
545 || stdenv.hostPlatform.isWasm
546 # Failing `#include <term.h>` in
547 # `lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp`
548 # sanitizers, not sure where to get it.
549 || stdenv.hostPlatform.isFreeBSD
550 then
551 libraries.compiler-rt-no-libc
552 else
553 libraries.compiler-rt-libc;
554
555 stdenv = overrideCC stdenv buildLlvmTools.clang;
556
557 libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;
558
559 libcxx = callPackage ./libcxx (
560 {
561 stdenv =
562 if stdenv.hostPlatform.isDarwin then
563 overrideCC darwin.bootstrapStdenv buildLlvmTools.clangWithLibcAndBasicRt
564 else
565 overrideCC stdenv buildLlvmTools.clangWithLibcAndBasicRt;
566 }
567 // lib.optionalAttrs (lib.versionOlder metadata.release_version "14") {
568 # TODO: remove this, causes LLVM 13 packages rebuild.
569 inherit (metadata) monorepoSrc; # Preserve bug during #307211 refactor.
570 }
571 );
572
573 libunwind = callPackage ./libunwind {
574 stdenv = overrideCC stdenv buildLlvmTools.clangWithLibcAndBasicRt;
575 };
576
577 openmp = callPackage ./openmp {
578 };
579 }
580 // lib.optionalAttrs (lib.versionAtLeast metadata.release_version "20") {
581 libc-overlay = callPackage ./libc {
582 isFullBuild = false;
583 # Use clang due to "gnu::naked" not working on aarch64.
584 # Issue: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77882
585 stdenv = overrideCC stdenv buildLlvmTools.clang;
586 };
587
588 libc-full = callPackage ./libc {
589 isFullBuild = true;
590 # Use clang due to "gnu::naked" not working on aarch64.
591 # Issue: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77882
592 stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcNoRt;
593 cmake =
594 if stdenv.targetPlatform.libc == "llvm" then buildPackages.cmakeMinimal else buildPackages.cmake;
595 python3 =
596 if stdenv.targetPlatform.libc == "llvm" then
597 buildPackages.python3Minimal
598 else
599 buildPackages.python3;
600 };
601
602 libc = if stdenv.targetPlatform.libc == "llvm" then libraries.libc-full else libraries.libc-overlay;
603 }
604 )
605 );
606
607 noExtend = extensible: lib.attrsets.removeAttrs extensible [ "extend" ];
608in
609{
610 inherit tools libraries;
611 inherit (metadata) release_version;
612}
613// (noExtend libraries)
614// (noExtend tools)