Skip to content

Commit 325ff73

Browse files
committed
make cross compile a bit easier
1 parent 5fece24 commit 325ff73

File tree

2 files changed

+310
-3
lines changed

2 files changed

+310
-3
lines changed

ldc/ldc2.conf.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ default:
3434
rpath = "@SHARED_LIBS_RPATH@";
3535
};
3636

37-
"^wasm(32|64)-":
37+
"^wasm(32|64)-.*-none":
3838
{
3939
switches = [
4040
"-defaultlib=",@WASM_DEFAULT_LDC_SWITCHES@

opend/src/opend.d

Lines changed: 309 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,172 @@ struct Commands {
6868
/// Does a debug build with the given arguments
6969
int build(string[] args) {
7070
// 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");
7272
}
7373

7474
/// Does a release build with the given arguments
7575
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+
}
77237
}
78238

79239
// publish-source which puts the dependencies together?
@@ -121,6 +281,81 @@ struct Commands {
121281
int ldc2(string[] args) {
122282
return spawnProcess([getCompilerPath("ldc2")] ~ args, null).wait;
123283
}
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);
124359
}
125360

126361
string getCompilerPath(string compiler) {
@@ -137,6 +372,12 @@ string getRuntimeLibPath() {
137372
return buildPath([dirName(thisExePath()), "../lib/"]);
138373
}
139374

375+
string getXpackPath() {
376+
import std.file, std.path;
377+
return buildPath([dirName(thisExePath()), "../xpacks/"]);
378+
}
379+
380+
140381
struct OutputExecutable {
141382
string exe;
142383
string[] args;
@@ -167,3 +408,69 @@ OutputExecutable getOutputExecutable(string[] args) {
167408
import std.path;
168409
return OutputExecutable(buildPath(".", name), args[splitter .. $]);
169410
}
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

Comments
 (0)