@@ -68,12 +68,172 @@ struct Commands {
68
68
// / Does a debug build with the given arguments
69
69
int build (string [] args) {
70
70
// FIXME: pull info out of the cache to get the right libs and -i modifiers out
71
- return dmd ([" -i" ] ~ args);
71
+ return sendToCompilerDriver ([" -i" ] ~ args, " dmd " );
72
72
}
73
73
74
74
// / Does a release build with the given arguments
75
75
int publish (string [] args) {
76
- return ldmd2 ([" -i" , " -O2" ] ~ args);
76
+ return sendToCompilerDriver ([" -i" , " -O2" ] ~ args, " ldmd2" );
77
+ }
78
+
79
+ int sendToCompilerDriver (string [] args, string preferredCompiler = null ) {
80
+ // extract --target
81
+ string [] argsToKeep;
82
+ argsToKeep.reserve (args.length);
83
+
84
+ int translateTarget (string target) {
85
+ import std.string ;
86
+
87
+ string os;
88
+ string platform;
89
+ string cpu;
90
+ string detail;
91
+
92
+ foreach (part; target.toLower.split(" -" )) {
93
+ switch (part) {
94
+ case " windows" :
95
+ case " win64" :
96
+ cpu = " x86_64" ;
97
+ os = " windows" ;
98
+ detail = " msvc" ;
99
+ break ;
100
+ case " mac" :
101
+ case " macos" :
102
+ if (cpu is null )
103
+ cpu = " x86_64,aarch64" ;
104
+ os = " apple" ;
105
+ detail = " darwin" ;
106
+ break ;
107
+ case " ipad" :
108
+ case " iphone" :
109
+ if (cpu is null )
110
+ cpu = " aarch64,x86_64" ;
111
+ os = " apple" ;
112
+ detail = " ios" ;
113
+ break ;
114
+ case " android" :
115
+ if (cpu is null )
116
+ cpu = " aarch64,x86_64" ;
117
+ os = " linux" ;
118
+ detail = " android" ;
119
+ break ;
120
+ // FIXME: i should add some bsd stuff too
121
+ case " linux" :
122
+ if (cpu is null )
123
+ cpu = " x86_64" ;
124
+ os = " linux" ;
125
+ detail = " gnu" ;
126
+ break ;
127
+ case " arm" :
128
+ case " aarch64" :
129
+ cpu = " aarch64" ;
130
+ break ;
131
+ case " amd64" :
132
+ case " x86_64" :
133
+ case " intel" :
134
+ cpu = " x86_64" ;
135
+ break ;
136
+ case " wasm" :
137
+ case " webassembly" :
138
+ cpu = " wasm32" ;
139
+ if (os is null )
140
+ os = " emscripten" ;
141
+ break ;
142
+ case " musl" :
143
+ if (cpu is null )
144
+ cpu = " x86_64" ;
145
+ if (os is null )
146
+ os = " linux" ;
147
+ detail = " musl" ;
148
+ break ;
149
+ case " emscripten" :
150
+ os = " emscripten" ;
151
+ if (cpu is null ) cpu = " wasm32" ;
152
+ break ;
153
+ case " wasi" :
154
+ detail = " wasi" ;
155
+ if (cpu is null ) cpu = " wasm32" ;
156
+ break ;
157
+ case " none" :
158
+ os = " unknown" ;
159
+ detail = " none" ;
160
+ break ;
161
+ case " x86" :
162
+ import std.stdio ;
163
+ stderr.writeln(" 32 bit not supported right now by opend, contact us to ask for it. Try amd64 instead.\n " );
164
+ return 1 ;
165
+ case " win32" :
166
+ import std.stdio ;
167
+ stderr.writeln(" 32 bit not supported right now by opend, contact us to ask for it. Try win64 instead.\n " );
168
+ return 1 ;
169
+ default :
170
+ import std.stdio ;
171
+ stderr.writeln(" Unknown part " , part, " try using -mtriple instead." );
172
+ return 1 ;
173
+ }
174
+ }
175
+
176
+ string triple;
177
+ void addPart (string w) {
178
+ if (w.length) {
179
+ if (triple.length)
180
+ triple ~= " -" ;
181
+ triple ~= w;
182
+ }
183
+ }
184
+
185
+ auto comma = cpu.indexOf(" ," );
186
+ if (comma != - 1 )
187
+ cpu = cpu[0 .. comma]; // FIXME: should actually spawn two instances
188
+
189
+ addPart(cpu);
190
+ addPart(platform);
191
+ addPart(os);
192
+ addPart(detail);
193
+
194
+ argsToKeep ~= " --mtriple=" ~ triple;
195
+ if (preferredCompiler.length == 0 || preferredCompiler == " dmd" )
196
+ preferredCompiler = " ldmd2" ;
197
+
198
+ return 0 ;
199
+ }
200
+
201
+ bool nextIsTarget;
202
+ bool verbose;
203
+ import std.algorithm ;
204
+ import std.string ;
205
+ foreach (arg; args) {
206
+ if (nextIsTarget) {
207
+ nextIsTarget = false ;
208
+ if (auto err = translateTarget(arg)) return err;
209
+ } else if (arg == " --target" || arg == " -target" ) {
210
+ nextIsTarget = true ;
211
+ } else if (arg.startsWith(" --target=" )) {
212
+ if (auto err = translateTarget(arg[" --target=" .length .. $])) return err;
213
+ } else if (arg.indexOf(" -mtriple" ) != - 1 ) {
214
+ preferredCompiler = " ldmd2" ;
215
+ } else if (arg == " -v" ) {
216
+ argsToKeep ~= arg;
217
+ verbose = true ;
218
+ } else
219
+ argsToKeep ~= arg;
220
+ }
221
+ args = argsToKeep;
222
+
223
+ if (verbose) {
224
+ import std.stdio ;
225
+ stderr.writeln(preferredCompiler, " " , args);
226
+ }
227
+ switch (preferredCompiler) {
228
+ case " dmd" :
229
+ return dmd (args);
230
+ case " ldmd2" :
231
+ return ldmd2 (args);
232
+ case " ldc2" :
233
+ return ldc2 (args);
234
+ default :
235
+ goto case " ldmd2" ;
236
+ }
77
237
}
78
238
79
239
// publish-source which puts the dependencies together?
@@ -121,6 +281,81 @@ struct Commands {
121
281
int ldc2 (string [] args) {
122
282
return spawnProcess ([getCompilerPath(" ldc2" )] ~ args, null ).wait;
123
283
}
284
+
285
+ // / Installs optional components or updates to opend
286
+ int install (string [] args) {
287
+ // create the ../xpacks directory
288
+
289
+ static import std.file ;
290
+ if (! std.file.exists (getXpackPath()))
291
+ std.file.mkdir (getXpackPath());
292
+
293
+ switch (args[0 ]) {
294
+ case " update" :
295
+ // get the new update, if available, then repeat other xpack installs
296
+ return 1 ;
297
+ case " xpack-android" :
298
+ // can extract the libs from the android downloads
299
+ // you must also install the ndk
300
+ return 1 ;
301
+ case " xpack-emscripten" :
302
+ // https://github.com/opendlang/opend/releases/download/CI/opend-latest-xpack-emscripten.tar.xz
303
+ // you must also install the emsdk
304
+
305
+ downloadXpack(" xpack-emscripten" );
306
+ // phobos is compiled but puts out some warnings so gonna reenable it with -i and not link the phobos
307
+ // tbh might be a good idea to do that for other platforms too
308
+ installConfig(`
309
+ "^wasm(32|64)-.*-emscripten":
310
+ {
311
+ lib-dirs = [
312
+ "%%ldcbinarypath%%/../xpacks/opend-latest-xpack-emscripten/lib",
313
+ ];
314
+
315
+ switches = [
316
+ "-defaultlib=druntime-ldc",
317
+ "--linker=emcc",
318
+ "-i=std",
319
+ ];
320
+ };
321
+ ` );
322
+
323
+ import std.stdio ;
324
+ writeln(" Installation complete, build with `opend build -mtriple=wasm32-emscripten <other args>`" );
325
+ writeln(" You will need the emsdk. Install that separately and follow its instructions to activate it before trying to build D code because opend will use emcc to finish the link step." );
326
+ writeln(" https://emscripten.org/docs/getting_started/downloads.html" );
327
+
328
+ return 0 ;
329
+ case " xpack-win64" :
330
+ // https://github.com/opendlang/opend/releases/download/CI/opend-latest-xpack-win64.tar.xz
331
+ downloadXpack(" xpack-win64" );
332
+ installConfig(`
333
+ "x86_64-.*-windows-msvc":
334
+ {
335
+ lib-dirs = [
336
+ "%%ldcbinarypath%%/../xpacks/opend-latest-xpack-win64/lib",
337
+ ];
338
+ };
339
+ ` );
340
+
341
+ import std.stdio ;
342
+ writeln(" Installation complete, build with `opend build -mtriple=x86_64-windows-msvc <other args>`" );
343
+
344
+ return 0 ;
345
+ default :
346
+ import std.stdio ;
347
+ stderr.writeln(" Unknown thing" );
348
+ return 1 ;
349
+
350
+ // maybe should do xpack-freestanding-{amd64,aarch64}
351
+ // xpack-linux-aarch64, xpack-linux-musl
352
+ }
353
+ }
354
+ }
355
+
356
+ void installConfig (string configInfo) {
357
+ import std.file , std.path ;
358
+ std.file.append (buildPath([dirName(thisExePath()), " ../etc/ldc2.conf" ]), configInfo);
124
359
}
125
360
126
361
string getCompilerPath (string compiler) {
@@ -137,6 +372,12 @@ string getRuntimeLibPath() {
137
372
return buildPath ([dirName(thisExePath()), " ../lib/" ]);
138
373
}
139
374
375
+ string getXpackPath () {
376
+ import std.file , std.path ;
377
+ return buildPath ([dirName(thisExePath()), " ../xpacks/" ]);
378
+ }
379
+
380
+
140
381
struct OutputExecutable {
141
382
string exe;
142
383
string [] args;
@@ -167,3 +408,69 @@ OutputExecutable getOutputExecutable(string[] args) {
167
408
import std.path ;
168
409
return OutputExecutable (buildPath(" ." , name), args[splitter .. $]);
169
410
}
411
+
412
+ void downloadXpack (string which) {
413
+ import arsd.archive;
414
+
415
+ import std.net.curl ;
416
+
417
+ import core.thread.fiber ;
418
+
419
+ ubyte [] availableData;
420
+
421
+ string url = " https://github.com/opendlang/opend/releases/download/CI/opend-latest-" ~ which ~ " .tar.xz" ;
422
+ string destination = getXpackPath();
423
+
424
+ void processor () {
425
+ TarFileHeader tfh;
426
+ long size;
427
+ ubyte [512 ] tarBuffer;
428
+
429
+ import std.stdio ;
430
+ File file;
431
+ long currentFileSize;
432
+
433
+ decompressLzma(
434
+ (in ubyte [] chunk) => cast (void ) processTar(&tfh, &size, chunk,
435
+ (header, isNewFile, fileFinished, data) {
436
+ if (isNewFile) {
437
+ import std.stdio ; writeln(" inflating xpack file " , header.filename);
438
+ import std.path , std.file ;
439
+ mkdirRecurse(dirName(buildPath(destination, header.filename)));
440
+ file = File (buildPath(destination, header.filename), " wb" );
441
+ currentFileSize = header.size;
442
+ }
443
+ file.rawWrite(data);
444
+ if (fileFinished)
445
+ file.close();
446
+ }),
447
+ (ubyte [] buffer) {
448
+ try_again:
449
+ auto canUse = buffer.length < availableData.length ? buffer.length : availableData.length;
450
+ if (canUse) {
451
+ buffer[0 .. canUse] = availableData[0 .. canUse];
452
+ availableData = availableData[canUse .. $];
453
+ return buffer[0 .. canUse];
454
+ } else {
455
+ Fiber .yield();
456
+ goto try_again;
457
+ }
458
+ },
459
+ tarBuffer[]
460
+ );
461
+ }
462
+
463
+ auto fiber = new Fiber (&processor, 1 * 1024 * 1024 /* reserve 1 MB stack */ );
464
+
465
+ import std.stdio ;
466
+ writeln(" Downloading..." );
467
+
468
+ auto http = HTTP (url);
469
+ http.onReceive = (ubyte [] data) {
470
+ availableData = data;
471
+ fiber.call();
472
+ return data.length - availableData.length;
473
+ };
474
+ http.perform();
475
+
476
+ }
0 commit comments