1{ lowPrio, newScope, pkgs, lib, stdenv, cmake
2, gccForLibs, preLibcCrossHeaders
3, libxml2, python3, isl, fetchFromGitHub, overrideCC, wrapCCWith, wrapBintoolsWith
4, buildLlvmTools # tools, but from the previous stage, for cross
5, targetLlvmLibraries # libraries, but from the next stage, for cross
6, targetLlvm
7# This is the default binutils, but with *this* version of LLD rather
8# than the default LLVM version's, if LLD is the choice. We use these for
9# the `useLLVM` bootstrapping below.
10, bootBintoolsNoLibc ?
11 if stdenv.targetPlatform.linker == "lld"
12 then null
13 else pkgs.bintoolsNoLibc
14, bootBintools ?
15 if stdenv.targetPlatform.linker == "lld"
16 then null
17 else pkgs.bintools
18, darwin
19}:
20
21let
22 release_version = "13.0.1";
23 candidate = ""; # empty or "rcN"
24 dash-candidate = lib.optionalString (candidate != "") "-${candidate}";
25 rev = ""; # When using a Git commit
26 rev-version = ""; # When using a Git commit
27 version = if rev != "" then rev-version else "${release_version}${dash-candidate}";
28 targetConfig = stdenv.targetPlatform.config;
29
30 src = fetchFromGitHub {
31 owner = "llvm";
32 repo = "llvm-project";
33 rev = if rev != "" then rev else "llvmorg-${version}";
34 sha256 = "06dv6h5dmvzdxbif2s8njki6h32796v368dyb5945x8gjj72xh7k";
35 };
36
37 llvm_meta = {
38 license = lib.licenses.ncsa;
39 maintainers = lib.teams.llvm.members;
40
41 # See llvm/cmake/config-ix.cmake.
42 platforms =
43 lib.platforms.aarch64 ++
44 lib.platforms.arm ++
45 lib.platforms.mips ++
46 lib.platforms.power ++
47 lib.platforms.riscv ++
48 lib.platforms.s390x ++
49 lib.platforms.wasi ++
50 lib.platforms.x86;
51 };
52
53 tools = lib.makeExtensible (tools: let
54 callPackage = newScope (tools // { inherit stdenv cmake libxml2 python3 isl release_version version src buildLlvmTools; });
55 mkExtraBuildCommands0 = cc: ''
56 rsrc="$out/resource-root"
57 mkdir "$rsrc"
58 ln -s "${cc.lib}/lib/clang/${release_version}/include" "$rsrc"
59 echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags
60 '';
61 mkExtraBuildCommands = cc: mkExtraBuildCommands0 cc + ''
62 ln -s "${targetLlvmLibraries.compiler-rt.out}/lib" "$rsrc/lib"
63 ln -s "${targetLlvmLibraries.compiler-rt.out}/share" "$rsrc/share"
64 '';
65
66 bintoolsNoLibc' =
67 if bootBintoolsNoLibc == null
68 then tools.bintoolsNoLibc
69 else bootBintoolsNoLibc;
70 bintools' =
71 if bootBintools == null
72 then tools.bintools
73 else bootBintools;
74
75 in {
76
77 libllvm = callPackage ./llvm {
78 inherit llvm_meta;
79 };
80
81 # `llvm` historically had the binaries. When choosing an output explicitly,
82 # we need to reintroduce `outputSpecified` to get the expected behavior e.g. of lib.get*
83 llvm = tools.libllvm;
84
85 libclang = callPackage ./clang {
86 inherit llvm_meta;
87 };
88
89 clang-unwrapped = tools.libclang;
90
91 llvm-manpages = lowPrio (tools.libllvm.override {
92 enableManpages = true;
93 python3 = pkgs.python3; # don't use python-boot
94 });
95
96 clang-manpages = lowPrio (tools.libclang.override {
97 enableManpages = true;
98 python3 = pkgs.python3; # don't use python-boot
99 });
100
101 # TODO: lldb/docs/index.rst:155:toctree contains reference to nonexisting document 'design/structureddataplugins'
102 # lldb-manpages = lowPrio (tools.lldb.override {
103 # enableManpages = true;
104 # python3 = pkgs.python3; # don't use python-boot
105 # });
106
107 # pick clang appropriate for package set we are targeting
108 clang =
109 /**/ if stdenv.targetPlatform.libc == null then tools.clangNoLibc
110 else if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
111 else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
112 else tools.libcxxClang;
113
114 libstdcxxClang = wrapCCWith rec {
115 cc = tools.clang-unwrapped;
116 # libstdcxx is taken from gcc in an ad-hoc way in cc-wrapper.
117 libcxx = null;
118 extraPackages = [
119 targetLlvmLibraries.compiler-rt
120 ];
121 extraBuildCommands = mkExtraBuildCommands cc;
122 };
123
124 libcxxClang = wrapCCWith rec {
125 cc = tools.clang-unwrapped;
126 libcxx = targetLlvmLibraries.libcxx;
127 extraPackages = [
128 libcxx.cxxabi
129 targetLlvmLibraries.compiler-rt
130 ];
131 extraBuildCommands = mkExtraBuildCommands cc;
132 };
133
134 lld = callPackage ./lld {
135 inherit llvm_meta;
136 };
137
138 lldb = callPackage ../common/lldb.nix {
139 patches =
140 let
141 resourceDirPatch = callPackage
142 ({ substituteAll, libclang }: substituteAll
143 {
144 src = ./lldb/resource-dir.patch;
145 clangLibDir = "${libclang.lib}/lib";
146 })
147 { };
148 in
149 [
150 ./lldb/procfs.patch
151 resourceDirPatch
152 ./lldb/gnu-install-dirs.patch
153 ]
154 # This is a stopgap solution if/until the macOS SDK used for x86_64 is
155 # updated.
156 #
157 # The older 10.12 SDK used on x86_64 as of this writing has a `mach/machine.h`
158 # header that does not define `CPU_SUBTYPE_ARM64E` so we replace the one use
159 # of this preprocessor symbol in `lldb` with its expansion.
160 #
161 # See here for some context:
162 # https://github.com/NixOS/nixpkgs/pull/194634#issuecomment-1272129132
163 ++ lib.optional (
164 stdenv.targetPlatform.isDarwin
165 && !stdenv.targetPlatform.isAarch64
166 && (lib.versionOlder darwin.apple_sdk.sdk.version "11.0")
167 ) ./lldb/cpu_subtype_arm64e_replacement.patch;
168 inherit llvm_meta;
169 };
170
171 # Below, is the LLVM bootstrapping logic. It handles building a
172 # fully LLVM toolchain from scratch. No GCC toolchain should be
173 # pulled in. As a consequence, it is very quick to build different
174 # targets provided by LLVM and we can also build for what GCC
175 # doesn’t support like LLVM. Probably we should move to some other
176 # file.
177
178 bintools-unwrapped = callPackage ../common/bintools.nix { };
179
180 bintoolsNoLibc = wrapBintoolsWith {
181 bintools = tools.bintools-unwrapped;
182 libc = preLibcCrossHeaders;
183 };
184
185 bintools = wrapBintoolsWith {
186 bintools = tools.bintools-unwrapped;
187 };
188
189 clangUseLLVM = wrapCCWith rec {
190 cc = tools.clang-unwrapped;
191 libcxx = targetLlvmLibraries.libcxx;
192 bintools = bintools';
193 extraPackages = [
194 libcxx.cxxabi
195 targetLlvmLibraries.compiler-rt
196 ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
197 targetLlvmLibraries.libunwind
198 ];
199 extraBuildCommands = ''
200 echo "-rtlib=compiler-rt -Wno-unused-command-line-argument" >> $out/nix-support/cc-cflags
201 echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags
202 '' + lib.optionalString (!stdenv.targetPlatform.isWasm) ''
203 echo "--unwindlib=libunwind" >> $out/nix-support/cc-cflags
204 '' + lib.optionalString (!stdenv.targetPlatform.isWasm && stdenv.targetPlatform.useLLVM or false) ''
205 echo "-lunwind" >> $out/nix-support/cc-ldflags
206 '' + lib.optionalString stdenv.targetPlatform.isWasm ''
207 echo "-fno-exceptions" >> $out/nix-support/cc-cflags
208 '' + mkExtraBuildCommands cc;
209 };
210
211 clangNoLibcxx = wrapCCWith rec {
212 cc = tools.clang-unwrapped;
213 libcxx = null;
214 bintools = bintools';
215 extraPackages = [
216 targetLlvmLibraries.compiler-rt
217 ];
218 extraBuildCommands = ''
219 echo "-rtlib=compiler-rt" >> $out/nix-support/cc-cflags
220 echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags
221 echo "-nostdlib++" >> $out/nix-support/cc-cflags
222 '' + mkExtraBuildCommands cc;
223 };
224
225 clangNoLibc = wrapCCWith rec {
226 cc = tools.clang-unwrapped;
227 libcxx = null;
228 bintools = bintoolsNoLibc';
229 extraPackages = [
230 targetLlvmLibraries.compiler-rt
231 ];
232 extraBuildCommands = ''
233 echo "-rtlib=compiler-rt" >> $out/nix-support/cc-cflags
234 echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags
235 '' + mkExtraBuildCommands cc;
236 };
237
238 clangNoCompilerRt = wrapCCWith rec {
239 cc = tools.clang-unwrapped;
240 libcxx = null;
241 bintools = bintoolsNoLibc';
242 extraPackages = [ ];
243 extraBuildCommands = ''
244 echo "-nostartfiles" >> $out/nix-support/cc-cflags
245 '' + mkExtraBuildCommands0 cc;
246 };
247
248 clangNoCompilerRtWithLibc = wrapCCWith rec {
249 cc = tools.clang-unwrapped;
250 libcxx = null;
251 bintools = bintools';
252 extraPackages = [ ];
253 extraBuildCommands = mkExtraBuildCommands0 cc;
254 };
255
256 });
257
258 libraries = lib.makeExtensible (libraries: let
259 callPackage = newScope (libraries // buildLlvmTools // { inherit stdenv cmake libxml2 python3 isl release_version version src; });
260 in {
261
262 compiler-rt-libc = callPackage ./compiler-rt {
263 inherit llvm_meta;
264 stdenv = if stdenv.hostPlatform.useLLVM or false
265 then overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc
266 else stdenv;
267 };
268
269 compiler-rt-no-libc = callPackage ./compiler-rt {
270 inherit llvm_meta;
271 stdenv = if stdenv.hostPlatform.useLLVM or false
272 then overrideCC stdenv buildLlvmTools.clangNoCompilerRt
273 else stdenv;
274 };
275
276 # N.B. condition is safe because without useLLVM both are the same.
277 compiler-rt = if stdenv.hostPlatform.isAndroid
278 then libraries.compiler-rt-libc
279 else libraries.compiler-rt-no-libc;
280
281 stdenv = overrideCC stdenv buildLlvmTools.clang;
282
283 libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;
284
285 libcxx = callPackage ./libcxx {
286 inherit llvm_meta;
287 stdenv = if stdenv.hostPlatform.useLLVM or false
288 then overrideCC stdenv buildLlvmTools.clangNoLibcxx
289 else (
290 # libcxx >= 13 does not build on gcc9
291 if stdenv.cc.isGNU && lib.versionOlder stdenv.cc.version "10"
292 then pkgs.gcc10Stdenv
293 else stdenv
294 );
295 };
296
297 libcxxabi = let
298 stdenv_ = if stdenv.hostPlatform.useLLVM or false
299 then overrideCC stdenv buildLlvmTools.clangNoLibcxx
300 else stdenv;
301 cxx-headers = callPackage ./libcxx {
302 inherit llvm_meta;
303 stdenv = stdenv_;
304 headersOnly = true;
305 };
306 in callPackage ./libcxxabi {
307 stdenv = stdenv_;
308 inherit llvm_meta cxx-headers;
309 };
310
311 libunwind = callPackage ./libunwind {
312 inherit llvm_meta;
313 stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx;
314 };
315
316 openmp = callPackage ./openmp {
317 inherit llvm_meta targetLlvm;
318 };
319 });
320 noExtend = extensible: lib.attrsets.removeAttrs extensible [ "extend" ];
321
322in { inherit tools libraries release_version; } // (noExtend libraries) // (noExtend tools)