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 = "14.0.0";
22 candidate = ""; # empty or "rcN"
23 dash-candidate = lib.optionalString (candidate != "") "-${candidate}";
24 rev = "ee65938357d5fffe9e586fa155b37268b5a358ac"; # When using a Git commit
25 rev-version = "unstable-2021-08-13"; # When using a Git commit
26 version = if rev != "" then rev-version else "${release_version}${dash-candidate}";
27 targetConfig = stdenv.targetPlatform.config;
28
29 src = fetchFromGitHub {
30 owner = "llvm";
31 repo = "llvm-project";
32 rev = if rev != "" then rev else "llvmorg-${version}";
33 sha256 = "10ahc108wbg2rsp50j3mc8h018a453ykg1rivjkhizng80pyllm1";
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 src 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 clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
97
98 libstdcxxClang = wrapCCWith rec {
99 cc = tools.clang-unwrapped;
100 # libstdcxx is taken from gcc in an ad-hoc way in cc-wrapper.
101 libcxx = null;
102 extraPackages = [
103 targetLlvmLibraries.compiler-rt
104 ];
105 extraBuildCommands = mkExtraBuildCommands cc;
106 };
107
108 libcxxClang = wrapCCWith rec {
109 cc = tools.clang-unwrapped;
110 libcxx = targetLlvmLibraries.libcxx;
111 extraPackages = [
112 targetLlvmLibraries.libcxxabi
113 targetLlvmLibraries.compiler-rt
114 ];
115 extraBuildCommands = mkExtraBuildCommands cc;
116 };
117
118 lld = callPackage ./lld {
119 inherit llvm_meta;
120 };
121
122 lldb = callPackage ./lldb {
123 inherit llvm_meta;
124 inherit (darwin) libobjc bootstrap_cmds;
125 inherit (darwin.apple_sdk.libs) xpc;
126 inherit (darwin.apple_sdk.frameworks) Foundation Carbon Cocoa;
127 };
128
129 # Below, is the LLVM bootstrapping logic. It handles building a
130 # fully LLVM toolchain from scratch. No GCC toolchain should be
131 # pulled in. As a consequence, it is very quick to build different
132 # targets provided by LLVM and we can also build for what GCC
133 # doesn’t support like LLVM. Probably we should move to some other
134 # file.
135
136 bintools-unwrapped = callPackage ./bintools {};
137
138 bintoolsNoLibc = wrapBintoolsWith {
139 bintools = tools.bintools-unwrapped;
140 libc = preLibcCrossHeaders;
141 };
142
143 bintools = wrapBintoolsWith {
144 bintools = tools.bintools-unwrapped;
145 };
146
147 clangUseLLVM = wrapCCWith rec {
148 cc = tools.clang-unwrapped;
149 libcxx = targetLlvmLibraries.libcxx;
150 bintools = bintools';
151 extraPackages = [
152 targetLlvmLibraries.libcxxabi
153 targetLlvmLibraries.compiler-rt
154 ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
155 targetLlvmLibraries.libunwind
156 ];
157 extraBuildCommands = ''
158 echo "-rtlib=compiler-rt -Wno-unused-command-line-argument" >> $out/nix-support/cc-cflags
159 echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags
160 '' + lib.optionalString (!stdenv.targetPlatform.isWasm) ''
161 echo "--unwindlib=libunwind" >> $out/nix-support/cc-cflags
162 '' + lib.optionalString (!stdenv.targetPlatform.isWasm && stdenv.targetPlatform.useLLVM or false) ''
163 echo "-lunwind" >> $out/nix-support/cc-ldflags
164 '' + lib.optionalString stdenv.targetPlatform.isWasm ''
165 echo "-fno-exceptions" >> $out/nix-support/cc-cflags
166 '' + mkExtraBuildCommands cc;
167 };
168
169 clangNoLibcxx = wrapCCWith rec {
170 cc = tools.clang-unwrapped;
171 libcxx = null;
172 bintools = bintools';
173 extraPackages = [
174 targetLlvmLibraries.compiler-rt
175 ];
176 extraBuildCommands = ''
177 echo "-rtlib=compiler-rt" >> $out/nix-support/cc-cflags
178 echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags
179 echo "-nostdlib++" >> $out/nix-support/cc-cflags
180 '' + mkExtraBuildCommands cc;
181 };
182
183 clangNoLibc = wrapCCWith rec {
184 cc = tools.clang-unwrapped;
185 libcxx = null;
186 bintools = bintoolsNoLibc';
187 extraPackages = [
188 targetLlvmLibraries.compiler-rt
189 ];
190 extraBuildCommands = ''
191 echo "-rtlib=compiler-rt" >> $out/nix-support/cc-cflags
192 echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags
193 '' + mkExtraBuildCommands cc;
194 };
195
196 clangNoCompilerRt = wrapCCWith rec {
197 cc = tools.clang-unwrapped;
198 libcxx = null;
199 bintools = bintoolsNoLibc';
200 extraPackages = [ ];
201 extraBuildCommands = ''
202 echo "-nostartfiles" >> $out/nix-support/cc-cflags
203 '' + mkExtraBuildCommands0 cc;
204 };
205
206 clangNoCompilerRtWithLibc = wrapCCWith rec {
207 cc = tools.clang-unwrapped;
208 libcxx = null;
209 bintools = bintools';
210 extraPackages = [ ];
211 extraBuildCommands = mkExtraBuildCommands0 cc;
212 };
213
214 });
215
216 libraries = lib.makeExtensible (libraries: let
217 callPackage = newScope (libraries // buildLlvmTools // { inherit stdenv cmake libxml2 python3 isl release_version version src; });
218 in {
219
220 compiler-rt-libc = callPackage ./compiler-rt {
221 inherit llvm_meta;
222 stdenv = if stdenv.hostPlatform.useLLVM or false
223 then overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc
224 else stdenv;
225 };
226
227 compiler-rt-no-libc = callPackage ./compiler-rt {
228 inherit llvm_meta;
229 stdenv = if stdenv.hostPlatform.useLLVM or false
230 then overrideCC stdenv buildLlvmTools.clangNoCompilerRt
231 else stdenv;
232 };
233
234 # N.B. condition is safe because without useLLVM both are the same.
235 compiler-rt = if stdenv.hostPlatform.isAndroid
236 then libraries.compiler-rt-libc
237 else libraries.compiler-rt-no-libc;
238
239 stdenv = overrideCC stdenv buildLlvmTools.clang;
240
241 libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;
242
243 libcxx = callPackage ./libcxx {
244 inherit llvm_meta;
245 stdenv = if stdenv.hostPlatform.useLLVM or false
246 then overrideCC stdenv buildLlvmTools.clangNoLibcxx
247 else stdenv;
248 };
249
250 libcxxabi = callPackage ./libcxxabi {
251 inherit llvm_meta;
252 stdenv = if stdenv.hostPlatform.useLLVM or false
253 then overrideCC stdenv buildLlvmTools.clangNoLibcxx
254 else stdenv;
255 };
256
257 libunwind = callPackage ./libunwind {
258 inherit llvm_meta;
259 stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx;
260 };
261
262 openmp = callPackage ./openmp {
263 inherit llvm_meta;
264 };
265 });
266
267in { inherit tools libraries release_version; } // libraries // tools