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# This is the default binutils, but with *this* version of LLD rather
7# than the default LLVM verion's, if LLD is the choice. We use these for
8# the `useLLVM` bootstrapping below.
9, bootBintoolsNoLibc ?
10 if stdenv.targetPlatform.linker == "lld"
11 then null
12 else pkgs.bintoolsNoLibc
13, bootBintools ?
14 if stdenv.targetPlatform.linker == "lld"
15 then null
16 else pkgs.bintools
17, darwin
18}:
19
20let
21 release_version = "15.0.0";
22 candidate = ""; # empty or "rcN"
23 dash-candidate = lib.optionalString (candidate != "") "-${candidate}";
24 rev = "a5640968f2f7485b2aa4919f5fa68fd8f23e2d1f"; # When using a Git commit
25 rev-version = "unstable-2022-26-07"; # When using a Git commit
26 version = if rev != "" then rev-version else "${release_version}${dash-candidate}";
27 targetConfig = stdenv.targetPlatform.config;
28
29 monorepoSrc = fetchFromGitHub {
30 owner = "llvm";
31 repo = "llvm-project";
32 rev = if rev != "" then rev else "llvmorg-${version}";
33 sha256 = "1sh5xihdfdn2hp7ds3lkaq1bfrl4alj36gl1aidmhlw65p5rdvl7";
34 };
35
36 llvm_meta = {
37 license = lib.licenses.ncsa;
38 maintainers = with lib.maintainers; [ lovek323 raskin dtzWill primeos ];
39 platforms = lib.platforms.all;
40 };
41
42 tools = lib.makeExtensible (tools: let
43 callPackage = newScope (tools // { inherit stdenv cmake libxml2 python3 isl release_version version monorepoSrc buildLlvmTools; });
44 mkExtraBuildCommands0 = cc: ''
45 rsrc="$out/resource-root"
46 mkdir "$rsrc"
47 ln -s "${cc.lib}/lib/clang/${release_version}/include" "$rsrc"
48 echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags
49 '';
50 mkExtraBuildCommands = cc: mkExtraBuildCommands0 cc + ''
51 ln -s "${targetLlvmLibraries.compiler-rt.out}/lib" "$rsrc/lib"
52 ln -s "${targetLlvmLibraries.compiler-rt.out}/share" "$rsrc/share"
53 '';
54
55 bintoolsNoLibc' =
56 if bootBintoolsNoLibc == null
57 then tools.bintoolsNoLibc
58 else bootBintoolsNoLibc;
59 bintools' =
60 if bootBintools == null
61 then tools.bintools
62 else bootBintools;
63
64 in {
65
66 libllvm = callPackage ./llvm {
67 inherit llvm_meta;
68 };
69
70 # `llvm` historically had the binaries. When choosing an output explicitly,
71 # we need to reintroduce `outputSpecified` to get the expected behavior e.g. of lib.get*
72 llvm = tools.libllvm.out // { outputSpecified = false; };
73
74 libclang = callPackage ./clang {
75 inherit llvm_meta;
76 };
77
78 clang-unwrapped = tools.libclang.out // { outputSpecified = false; };
79
80 llvm-manpages = lowPrio (tools.libllvm.override {
81 enableManpages = true;
82 python3 = pkgs.python3; # don't use python-boot
83 });
84
85 clang-manpages = lowPrio (tools.libclang.override {
86 enableManpages = true;
87 python3 = pkgs.python3; # don't use python-boot
88 });
89
90 # TODO: lldb/docs/index.rst:155:toctree contains reference to nonexisting document 'design/structureddataplugins'
91 # lldb-manpages = lowPrio (tools.lldb.override {
92 # enableManpages = true;
93 # python3 = pkgs.python3; # don't use python-boot
94 # });
95
96 # pick clang appropriate for package set we are targeting
97 clang =
98 /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
99 else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
100 else tools.libcxxClang;
101
102 libstdcxxClang = wrapCCWith rec {
103 cc = tools.clang-unwrapped;
104 # libstdcxx is taken from gcc in an ad-hoc way in cc-wrapper.
105 libcxx = null;
106 extraPackages = [
107 targetLlvmLibraries.compiler-rt
108 ];
109 extraBuildCommands = mkExtraBuildCommands cc;
110 };
111
112 libcxxClang = wrapCCWith rec {
113 cc = tools.clang-unwrapped;
114 libcxx = targetLlvmLibraries.libcxx;
115 extraPackages = [
116 targetLlvmLibraries.libcxxabi
117 targetLlvmLibraries.compiler-rt
118 ];
119 extraBuildCommands = mkExtraBuildCommands cc;
120 };
121
122 lld = callPackage ./lld {
123 inherit llvm_meta;
124 };
125
126 lldb = callPackage ./lldb {
127 inherit llvm_meta;
128 inherit (darwin) libobjc bootstrap_cmds;
129 inherit (darwin.apple_sdk.libs) xpc;
130 inherit (darwin.apple_sdk.frameworks) Foundation Carbon Cocoa;
131 };
132
133 # Below, is the LLVM bootstrapping logic. It handles building a
134 # fully LLVM toolchain from scratch. No GCC toolchain should be
135 # pulled in. As a consequence, it is very quick to build different
136 # targets provided by LLVM and we can also build for what GCC
137 # doesn’t support like LLVM. Probably we should move to some other
138 # file.
139
140 bintools-unwrapped = callPackage ./bintools {};
141
142 bintoolsNoLibc = wrapBintoolsWith {
143 bintools = tools.bintools-unwrapped;
144 libc = preLibcCrossHeaders;
145 };
146
147 bintools = wrapBintoolsWith {
148 bintools = tools.bintools-unwrapped;
149 };
150
151 clangUseLLVM = wrapCCWith rec {
152 cc = tools.clang-unwrapped;
153 libcxx = targetLlvmLibraries.libcxx;
154 bintools = bintools';
155 extraPackages = [
156 targetLlvmLibraries.libcxxabi
157 targetLlvmLibraries.compiler-rt
158 ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
159 targetLlvmLibraries.libunwind
160 ];
161 extraBuildCommands = mkExtraBuildCommands cc;
162 nixSupport.cc-cflags =
163 [ "-rtlib=compiler-rt"
164 "-Wno-unused-command-line-argument"
165 "-B${targetLlvmLibraries.compiler-rt}/lib"
166 ]
167 ++ lib.optional (!stdenv.targetPlatform.isWasm) "--unwindlib=libunwind"
168 ++ lib.optional
169 (!stdenv.targetPlatform.isWasm && !stdenv.targetPlatform.isFreeBSD && stdenv.targetPlatform.useLLVM or false)
170 "-lunwind"
171 ++ lib.optional stdenv.targetPlatform.isWasm "-fno-exceptions";
172 };
173
174 clangNoLibcxx = wrapCCWith rec {
175 cc = tools.clang-unwrapped;
176 libcxx = null;
177 bintools = bintools';
178 extraPackages = [
179 targetLlvmLibraries.compiler-rt
180 ];
181 extraBuildCommands = mkExtraBuildCommands cc;
182 nixSupport.cc-cflags = [
183 "-rtlib=compiler-rt"
184 "-B${targetLlvmLibraries.compiler-rt}/lib"
185 "-nostdlib++"
186 ];
187 };
188
189 clangNoLibc = wrapCCWith rec {
190 cc = tools.clang-unwrapped;
191 libcxx = null;
192 bintools = bintoolsNoLibc';
193 extraPackages = [
194 targetLlvmLibraries.compiler-rt
195 ];
196 extraBuildCommands = mkExtraBuildCommands cc;
197 nixSupport.cc-cflags = [
198 "-rtlib=compiler-rt"
199 "-B${targetLlvmLibraries.compiler-rt}/lib"
200 ];
201 };
202
203 clangNoCompilerRt = wrapCCWith rec {
204 cc = tools.clang-unwrapped;
205 libcxx = null;
206 bintools = bintoolsNoLibc';
207 extraPackages = [ ];
208 extraBuildCommands = mkExtraBuildCommands0 cc;
209 nixSupport.cc-cflags = [ "-nostartfiles" ];
210 };
211
212 clangNoCompilerRtWithLibc = wrapCCWith rec {
213 cc = tools.clang-unwrapped;
214 libcxx = null;
215 bintools = bintools';
216 extraPackages = [ ];
217 extraBuildCommands = mkExtraBuildCommands0 cc;
218 };
219
220 });
221
222 libraries = lib.makeExtensible (libraries: let
223 callPackage = newScope (libraries // buildLlvmTools // { inherit stdenv cmake libxml2 python3 isl release_version version monorepoSrc; });
224 in {
225
226 compiler-rt-libc = callPackage ./compiler-rt {
227 inherit llvm_meta;
228 stdenv = if stdenv.hostPlatform.useLLVM or false
229 then overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc
230 else stdenv;
231 };
232
233 compiler-rt-no-libc = callPackage ./compiler-rt {
234 inherit llvm_meta;
235 stdenv = if stdenv.hostPlatform.useLLVM or false
236 then overrideCC stdenv buildLlvmTools.clangNoCompilerRt
237 else stdenv;
238 };
239
240 # N.B. condition is safe because without useLLVM both are the same.
241 compiler-rt = if stdenv.hostPlatform.isAndroid
242 then libraries.compiler-rt-libc
243 else libraries.compiler-rt-no-libc;
244
245 stdenv = overrideCC stdenv buildLlvmTools.clang;
246
247 libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;
248
249 libcxx = callPackage ./libcxx {
250 inherit llvm_meta;
251 stdenv = if stdenv.hostPlatform.useLLVM or false
252 then overrideCC stdenv buildLlvmTools.clangNoLibcxx
253 else stdenv;
254 };
255
256 libcxxabi = let
257 stdenv_ = if stdenv.hostPlatform.useLLVM or false
258 then overrideCC stdenv buildLlvmTools.clangNoLibcxx
259 else stdenv;
260 cxx-headers = callPackage ./libcxx {
261 inherit llvm_meta;
262 stdenv = stdenv_;
263 headersOnly = true;
264 };
265 in callPackage ./libcxxabi {
266 stdenv = stdenv_;
267 inherit llvm_meta cxx-headers;
268 };
269
270 libunwind = callPackage ./libunwind {
271 inherit llvm_meta;
272 stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx;
273 };
274
275 openmp = callPackage ./openmp {
276 inherit llvm_meta;
277 };
278 });
279
280in { inherit tools libraries release_version; } // libraries // tools