module dub.platform;
import std.array;
enum string platformCheck = q{
string[] ret;
version(Windows) ret ~= "windows";
version(linux) ret ~= "linux";
version(Posix) ret ~= "posix";
version(OSX) ret ~= ["osx", "darwin"];
version(iOS) ret ~= ["ios", "darwin"];
version(TVOS) ret ~= ["tvos", "darwin"];
version(WatchOS) ret ~= ["watchos", "darwin"];
version(FreeBSD) ret ~= "freebsd";
version(OpenBSD) ret ~= "openbsd";
version(NetBSD) ret ~= "netbsd";
version(DragonFlyBSD) ret ~= "dragonflybsd";
version(BSD) ret ~= "bsd";
version(Solaris) ret ~= "solaris";
version(AIX) ret ~= "aix";
version(Haiku) ret ~= "haiku";
version(SkyOS) ret ~= "skyos";
version(SysV3) ret ~= "sysv3";
version(SysV4) ret ~= "sysv4";
version(Hurd) ret ~= "hurd";
version(Android) ret ~= "android";
version(Cygwin) ret ~= "cygwin";
version(MinGW) ret ~= "mingw";
version(PlayStation4) ret ~= "playstation4";
version(WebAssembly) ret ~= "wasm";
version(Emscripten) ret ~= "emscripten";
return ret;
};
enum string archCheck = q{
string[] ret;
version(X86) ret ~= "x86";
version(X86) version(CRuntime_DigitalMars) ret ~= "x86_omf";
version(X86) version(CRuntime_Microsoft) ret ~= "x86_mscoff";
version(X86_64) ret ~= "x86_64";
version(ARM) ret ~= "arm";
version(AArch64) ret ~= "aarch64";
version(ARM_Thumb) ret ~= "arm_thumb";
version(ARM_SoftFloat) ret ~= "arm_softfloat";
version(ARM_HardFloat) ret ~= "arm_hardfloat";
version(PPC) ret ~= "ppc";
version(PPC_SoftFP) ret ~= "ppc_softfp";
version(PPC_HardFP) ret ~= "ppc_hardfp";
version(PPC64) ret ~= "ppc64";
version(IA64) ret ~= "ia64";
version(MIPS) ret ~= "mips";
version(MIPS32) ret ~= "mips32";
version(MIPS64) ret ~= "mips64";
version(MIPS_O32) ret ~= "mips_o32";
version(MIPS_N32) ret ~= "mips_n32";
version(MIPS_O64) ret ~= "mips_o64";
version(MIPS_N64) ret ~= "mips_n64";
version(MIPS_EABI) ret ~= "mips_eabi";
version(MIPS_NoFloat) ret ~= "mips_nofloat";
version(MIPS_SoftFloat) ret ~= "mips_softfloat";
version(MIPS_HardFloat) ret ~= "mips_hardfloat";
version(SPARC) ret ~= "sparc";
version(SPARC_V8Plus) ret ~= "sparc_v8plus";
version(SPARC_SoftFP) ret ~= "sparc_softfp";
version(SPARC_HardFP) ret ~= "sparc_hardfp";
version(SPARC64) ret ~= "sparc64";
version(S390) ret ~= "s390";
version(S390X) ret ~= "s390x";
version(HPPA) ret ~= "hppa";
version(HPPA64) ret ~= "hppa64";
version(SH) ret ~= "sh";
version(SH64) ret ~= "sh64";
version(Alpha) ret ~= "alpha";
version(Alpha_SoftFP) ret ~= "alpha_softfp";
version(Alpha_HardFP) ret ~= "alpha_hardfp";
version(LoongArch32) ret ~= "loongarch32";
version(LoongArch64) ret ~= "loongarch64";
version(LoongArch_SoftFloat) ret ~= "loongarch_softfloat";
version(LoongArch_HardFloat) ret ~= "loongarch_hardfloat";
version(WebAssembly) {
version(D_LP64) ret ~= "wasm64";
else ret ~= "wasm32";
}
return ret;
};
enum string compilerCheck = q{
version(DigitalMars) return "dmd";
else version(GNU) return "gdc";
else version(LDC) return "ldc";
else version(SDC) return "sdc";
else return null;
};
enum string compilerCheckPragmas = q{
version(DigitalMars) pragma(msg, ` "dmd"`);
else version(GNU) pragma(msg, ` "gdc"`);
else version(LDC) pragma(msg, ` "ldc"`);
else version(SDC) pragma(msg, ` "sdc"`);
};
string pragmaGen(string str) {
import std.string : replace;
return str.replace("return ret;", "").replace("string[] ret;", "").replace(`["`, `"`).replace(`", "`,`" "`).replace(`"]`, `"`).replace(`;`, "`);").replace("ret ~= ", "pragma(msg, ` ");
}
BuildPlatform determineBuildPlatform()
{
BuildPlatform ret;
ret.platform = determinePlatform();
ret.architecture = determineArchitecture();
ret.compiler = determineCompiler();
ret.frontendVersion = __VERSION__;
return ret;
}
string[] determinePlatform()
{
mixin(platformCheck);
}
string[] determineArchitecture()
{
mixin(archCheck);
}
string determineCompiler()
{
mixin(compilerCheck);
}
bool matchesSpecification(in BuildPlatform platform, const(char)[] specification)
{
import std.string : chompPrefix, format;
import std.algorithm : canFind, splitter;
import std.exception : enforce;
if (specification.empty) return true;
if (platform == BuildPlatform.any) return true;
auto splitted = specification.chompPrefix("-").splitter('-');
enforce(!splitted.empty, format("Platform specification, if present, must not be empty: \"%s\"", specification));
if (platform.platform.canFind(splitted.front)) {
splitted.popFront();
if (splitted.empty)
return true;
}
if (platform.architecture.canFind(splitted.front)) {
splitted.popFront();
if (splitted.empty)
return true;
}
if (platform.compiler == splitted.front) {
splitted.popFront();
enforce(splitted.empty, "No valid specification! The compiler has to be the last element: " ~ specification);
return true;
}
return false;
}
unittest {
auto platform = BuildPlatform(["posix", "linux"], ["x86_64"], "dmd");
assert(platform.matchesSpecification(""));
assert(platform.matchesSpecification("posix"));
assert(platform.matchesSpecification("linux"));
assert(platform.matchesSpecification("linux-dmd"));
assert(platform.matchesSpecification("linux-x86_64-dmd"));
assert(platform.matchesSpecification("x86_64"));
assert(!platform.matchesSpecification("windows"));
assert(!platform.matchesSpecification("ldc"));
assert(!platform.matchesSpecification("windows-dmd"));
assert(platform.matchesSpecification("-x86_64"));
}
struct BuildPlatform {
enum any = BuildPlatform(null, null, null, null, -1);
string[] platform;
string[] architecture;
string compiler;
string compilerBinary;
int frontendVersion;
string compilerVersion;
string frontendVersionString() const
{
import std.format : format;
const maj = frontendVersion / 1000;
const min = frontendVersion % 1000;
return format("%d.%03d", maj, min);
}
unittest
{
BuildPlatform bp;
bp.frontendVersion = 2067;
assert(bp.frontendVersionString == "2.067");
}
bool isWindows() const {
import std.algorithm : canFind;
return this.platform.canFind("windows");
}
unittest {
BuildPlatform bp;
bp.platform = ["windows"];
assert(bp.isWindows);
bp.platform = ["posix"];
assert(!bp.isWindows);
}
bool isDarwin() const {
import std.algorithm : canFind;
return this.platform.canFind("darwin");
}
unittest {
BuildPlatform bp;
bp.platform = ["osx", "darwin"];
assert(bp.isDarwin);
bp.platform = ["posix"];
assert(!bp.isDarwin);
}
}