nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{ lowPrio, newScope, pkgs, lib, stdenv, stdenvNoCC, cmake, ninja
2, gccForLibs, preLibcCrossHeaders
3, libxml2, python3, 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# LLVM release information; specify one of these but not both:
20, gitRelease ? null
21 # i.e.:
22 # {
23 # version = /* i.e. "15.0.0" */;
24 # rev = /* commit SHA */;
25 # rev-version = /* human readable version; i.e. "unstable-2022-26-07" */;
26 # sha256 = /* checksum for this release, can omit if specifying your own `monorepoSrc` */;
27 # }
28, officialRelease ? { version = "15.0.7"; sha256 = "sha256-wjuZQyXQ/jsmvy6y1aksCcEDXGBjuhpgngF3XQJ/T4s="; }
29 # i.e.:
30 # {
31 # version = /* i.e. "15.0.0" */;
32 # candidate = /* optional; if specified, should be: "rcN" */
33 # sha256 = /* checksum for this release, can omit if specifying your own `monorepoSrc` */;
34 # }
35# By default, we'll try to fetch a release from `github:llvm/llvm-project`
36# corresponding to the `gitRelease` or `officialRelease` specified.
37#
38# You can provide your own LLVM source by specifying this arg but then it's up
39# to you to make sure that the LLVM repo given matches the release configuration
40# specified.
41, monorepoSrc ? null
42}:
43
44assert let
45 int = a: if a then 1 else 0;
46 xor = a: b: ((builtins.bitXor (int a) (int b)) == 1);
47in
48 lib.assertMsg
49 (xor
50 (gitRelease != null)
51 (officialRelease != null))
52 ("must specify `gitRelease` or `officialRelease`" +
53 (lib.optionalString (gitRelease != null) " — not both"));
54let
55 monorepoSrc' = monorepoSrc;
56in let
57 releaseInfo = if gitRelease != null then rec {
58 original = gitRelease;
59 release_version = original.version;
60 version = gitRelease.rev-version;
61 } else rec {
62 original = officialRelease;
63 release_version = original.version;
64 version = if original ? candidate then
65 "${release_version}-${original.candidate}"
66 else
67 release_version;
68 };
69
70 monorepoSrc = if monorepoSrc' != null then
71 monorepoSrc'
72 else let
73 sha256 = releaseInfo.original.sha256;
74 rev = if gitRelease != null then
75 gitRelease.rev
76 else
77 "llvmorg-${releaseInfo.version}";
78 in fetchFromGitHub {
79 owner = "llvm";
80 repo = "llvm-project";
81 inherit rev sha256;
82 };
83
84 inherit (releaseInfo) release_version version;
85
86 llvm_meta = {
87 license = lib.licenses.ncsa;
88 maintainers = lib.teams.llvm.members;
89
90 # See llvm/cmake/config-ix.cmake.
91 platforms =
92 lib.platforms.aarch64 ++
93 lib.platforms.arm ++
94 lib.platforms.m68k ++
95 lib.platforms.mips ++
96 lib.platforms.power ++
97 lib.platforms.riscv ++
98 lib.platforms.s390x ++
99 lib.platforms.wasi ++
100 lib.platforms.x86;
101 };
102
103 tools = lib.makeExtensible (tools: let
104 callPackage = newScope (tools // { inherit stdenv cmake ninja libxml2 python3 release_version version monorepoSrc buildLlvmTools; });
105 mkExtraBuildCommands0 = cc: ''
106 rsrc="$out/resource-root"
107 mkdir "$rsrc"
108 ln -s "${cc.lib}/lib/clang/${release_version}/include" "$rsrc"
109 echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags
110 '';
111 mkExtraBuildCommands = cc: mkExtraBuildCommands0 cc + ''
112 ln -s "${targetLlvmLibraries.compiler-rt.out}/lib" "$rsrc/lib"
113 ln -s "${targetLlvmLibraries.compiler-rt.out}/share" "$rsrc/share"
114 '';
115
116 bintoolsNoLibc' =
117 if bootBintoolsNoLibc == null
118 then tools.bintoolsNoLibc
119 else bootBintoolsNoLibc;
120 bintools' =
121 if bootBintools == null
122 then tools.bintools
123 else bootBintools;
124
125 in {
126
127 libllvm = callPackage ./llvm {
128 inherit llvm_meta;
129 };
130
131 # `llvm` historically had the binaries. When choosing an output explicitly,
132 # we need to reintroduce `outputSpecified` to get the expected behavior e.g. of lib.get*
133 llvm = tools.libllvm;
134
135 libclang = callPackage ./clang {
136 inherit llvm_meta;
137 };
138
139 clang-unwrapped = tools.libclang;
140
141 llvm-manpages = lowPrio (tools.libllvm.override {
142 enableManpages = true;
143 python3 = pkgs.python3; # don't use python-boot
144 });
145
146 clang-manpages = lowPrio (tools.libclang.override {
147 enableManpages = true;
148 python3 = pkgs.python3; # don't use python-boot
149 });
150
151 lldb-manpages = lowPrio (tools.lldb.override {
152 enableManpages = true;
153 python3 = pkgs.python3; # don't use python-boot
154 });
155
156 # pick clang appropriate for package set we are targeting
157 clang =
158 /**/ if stdenv.targetPlatform.libc == null then tools.clangNoLibc
159 else if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
160 else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
161 else tools.libcxxClang;
162
163 libstdcxxClang = wrapCCWith rec {
164 cc = tools.clang-unwrapped;
165 # libstdcxx is taken from gcc in an ad-hoc way in cc-wrapper.
166 libcxx = null;
167 extraPackages = [
168 targetLlvmLibraries.compiler-rt
169 ];
170 extraBuildCommands = mkExtraBuildCommands cc;
171 };
172
173 libcxxClang = wrapCCWith rec {
174 cc = tools.clang-unwrapped;
175 libcxx = targetLlvmLibraries.libcxx;
176 extraPackages = [
177 libcxx.cxxabi
178 targetLlvmLibraries.compiler-rt
179 ];
180 extraBuildCommands = mkExtraBuildCommands cc;
181 };
182
183 lld = callPackage ./lld {
184 inherit llvm_meta;
185 };
186
187 lldb = callPackage ./lldb {
188 inherit llvm_meta;
189 inherit (darwin) libobjc bootstrap_cmds;
190 inherit (darwin.apple_sdk.libs) xpc;
191 inherit (darwin.apple_sdk.frameworks) Foundation Carbon Cocoa;
192 };
193
194 # Below, is the LLVM bootstrapping logic. It handles building a
195 # fully LLVM toolchain from scratch. No GCC toolchain should be
196 # pulled in. As a consequence, it is very quick to build different
197 # targets provided by LLVM and we can also build for what GCC
198 # doesn’t support like LLVM. Probably we should move to some other
199 # file.
200
201 bintools-unwrapped = callPackage ./bintools {};
202
203 bintoolsNoLibc = wrapBintoolsWith {
204 bintools = tools.bintools-unwrapped;
205 libc = preLibcCrossHeaders;
206 };
207
208 bintools = wrapBintoolsWith {
209 bintools = tools.bintools-unwrapped;
210 };
211
212 clangUseLLVM = wrapCCWith rec {
213 cc = tools.clang-unwrapped;
214 libcxx = targetLlvmLibraries.libcxx;
215 bintools = bintools';
216 extraPackages = [
217 libcxx.cxxabi
218 targetLlvmLibraries.compiler-rt
219 ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
220 targetLlvmLibraries.libunwind
221 ];
222 extraBuildCommands = mkExtraBuildCommands cc;
223 nixSupport.cc-cflags =
224 [ "-rtlib=compiler-rt"
225 "-Wno-unused-command-line-argument"
226 "-B${targetLlvmLibraries.compiler-rt}/lib"
227 ]
228 ++ lib.optional (!stdenv.targetPlatform.isWasm) "--unwindlib=libunwind"
229 ++ lib.optional
230 (!stdenv.targetPlatform.isWasm && stdenv.targetPlatform.useLLVM or false)
231 "-lunwind"
232 ++ lib.optional stdenv.targetPlatform.isWasm "-fno-exceptions";
233 };
234
235 clangNoLibcxx = wrapCCWith rec {
236 cc = tools.clang-unwrapped;
237 libcxx = null;
238 bintools = bintools';
239 extraPackages = [
240 targetLlvmLibraries.compiler-rt
241 ];
242 extraBuildCommands = mkExtraBuildCommands cc;
243 nixSupport.cc-cflags = [
244 "-rtlib=compiler-rt"
245 "-B${targetLlvmLibraries.compiler-rt}/lib"
246 "-nostdlib++"
247 ];
248 };
249
250 clangNoLibc = wrapCCWith rec {
251 cc = tools.clang-unwrapped;
252 libcxx = null;
253 bintools = bintoolsNoLibc';
254 extraPackages = [
255 targetLlvmLibraries.compiler-rt
256 ];
257 extraBuildCommands = mkExtraBuildCommands cc;
258 nixSupport.cc-cflags = [
259 "-rtlib=compiler-rt"
260 "-B${targetLlvmLibraries.compiler-rt}/lib"
261 ];
262 };
263
264 clangNoCompilerRt = wrapCCWith rec {
265 cc = tools.clang-unwrapped;
266 libcxx = null;
267 bintools = bintoolsNoLibc';
268 extraPackages = [ ];
269 extraBuildCommands = mkExtraBuildCommands0 cc;
270 nixSupport.cc-cflags = [ "-nostartfiles" ];
271 };
272
273 clangNoCompilerRtWithLibc = wrapCCWith rec {
274 cc = tools.clang-unwrapped;
275 libcxx = null;
276 bintools = bintools';
277 extraPackages = [ ];
278 extraBuildCommands = mkExtraBuildCommands0 cc;
279 };
280
281 });
282
283 libraries = lib.makeExtensible (libraries: let
284 callPackage = newScope (libraries // buildLlvmTools // { inherit stdenv cmake ninja libxml2 python3 release_version version monorepoSrc; });
285 in {
286
287 compiler-rt-libc = callPackage ./compiler-rt {
288 inherit llvm_meta;
289 stdenv = if stdenv.hostPlatform.useLLVM or false
290 then overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc
291 else stdenv;
292 };
293
294 compiler-rt-no-libc = callPackage ./compiler-rt {
295 inherit llvm_meta;
296 stdenv = if stdenv.hostPlatform.useLLVM or false
297 then overrideCC stdenv buildLlvmTools.clangNoCompilerRt
298 else stdenv;
299 };
300
301 # N.B. condition is safe because without useLLVM both are the same.
302 compiler-rt = if stdenv.hostPlatform.isAndroid
303 then libraries.compiler-rt-libc
304 else libraries.compiler-rt-no-libc;
305
306 stdenv = overrideCC stdenv buildLlvmTools.clang;
307
308 libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;
309
310 libcxxabi = let
311 # CMake will "require" a compiler capable of compiling C++ programs
312 # cxx-header's build does not actually use one so it doesn't really matter
313 # what stdenv we use here, as long as CMake is happy.
314 cxx-headers = callPackage ./libcxx {
315 inherit llvm_meta;
316 # Note that if we use the regular stdenv here we'll get cycle errors
317 # when attempting to use this compiler in the stdenv.
318 #
319 # The final stdenv pulls `cxx-headers` from the package set where
320 # hostPlatform *is* the target platform which means that `stdenv` at
321 # that point attempts to use this toolchain.
322 #
323 # So, we use `stdenv_` (the stdenv containing `clang` from this package
324 # set, defined below) to sidestep this issue.
325 #
326 # Because we only use `cxx-headers` in `libcxxabi` (which depends on the
327 # clang stdenv _anyways_), this is okay.
328 stdenv = stdenv_;
329 headersOnly = true;
330 };
331
332 # `libcxxabi` *doesn't* need a compiler with a working C++ stdlib but it
333 # *does* need a relatively modern C++ compiler (see:
334 # https://releases.llvm.org/15.0.0/projects/libcxx/docs/index.html#platform-and-compiler-support).
335 #
336 # So, we use the clang from this LLVM package set, like libc++
337 # "boostrapping builds" do:
338 # https://releases.llvm.org/15.0.0/projects/libcxx/docs/BuildingLibcxx.html#bootstrapping-build
339 #
340 # We cannot use `clangNoLibcxx` because that contains `compiler-rt` which,
341 # on macOS, depends on `libcxxabi`, thus forming a cycle.
342 stdenv_ = overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc;
343 in callPackage ./libcxxabi {
344 stdenv = stdenv_;
345 inherit llvm_meta cxx-headers;
346 };
347
348 # Like `libcxxabi` above, `libcxx` requires a fairly modern C++ compiler,
349 # so: we use the clang from this LLVM package set instead of the regular
350 # stdenv's compiler.
351 libcxx = callPackage ./libcxx {
352 inherit llvm_meta;
353 stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx;
354 };
355
356 libunwind = callPackage ./libunwind {
357 inherit llvm_meta;
358 stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx;
359 };
360
361 openmp = callPackage ./openmp {
362 inherit llvm_meta targetLlvm;
363 };
364 });
365
366in { inherit tools libraries release_version; } // libraries // tools