Move BuildPlatform to dub.platform and improve docs.
1 parent d489e3a commit 1fd4e134a20f5b3a47dace1ec4e43590b1961f44
@Sönke Ludwig Sönke Ludwig authored on 11 Mar 2016
Showing 2 changed files
View
78
source/dub/compilers/compiler.d
*/
module dub.compilers.compiler;
 
public import dub.compilers.buildsettings;
public import dub.platform : BuildPlatform, matchesSpecification;
 
import dub.compilers.dmd;
import dub.compilers.gdc;
import dub.compilers.ldc;
throw new Exception(format("%s failed with exit code %s. This may indicate that the process has run out of memory.",
args[0], status));
}
enforce(status == 0, format("%s failed with exit code %s.", args[0], status));
}
}
 
 
/// Represents a platform a package can be build upon.
struct BuildPlatform {
/// e.g. ["posix", "windows"]
string[] platform;
/// e.g. ["x86", "x86_64"]
string[] architecture;
/// Canonical compiler name e.g. "dmd"
string compiler;
/// Compiler binary name e.g. "ldmd2"
string compilerBinary;
/// Compiled frontend version (e.g. 2065)
int frontendVersion;
 
enum any = BuildPlatform(null, null, null, null, -1);
 
/// Build platforms can be specified via a string specification.
///
/// Specifications are build upon the following scheme, where each component
/// is optional (indicated by []), but the order is obligatory.
/// "[-platform][-architecture][-compiler]"
///
/// So the following strings are valid specifications:
/// "-windows-x86-dmd"
/// "-dmd"
/// "-arm"
/// "-arm-dmd"
/// "-windows-dmd"
///
/// Params:
/// specification = The specification being matched. It must be the empty string or start with a dash.
///
/// Returns:
/// true if the given specification matches this BuildPlatform, false otherwise. (The empty string matches)
///
bool matchesSpecification(const(char)[] specification)
const {
import std.string : format;
 
if (specification.empty) return true;
if (this == any) return true;
 
auto splitted=specification.splitter('-');
assert(!splitted.empty, "No valid platform specification! The leading hyphen is required!");
splitted.popFront(); // Drop leading empty match.
enforce(!splitted.empty, format("Platform specification, if present, must not be empty: \"%s\"", specification));
if (platform.canFind(splitted.front)) {
splitted.popFront();
if(splitted.empty)
return true;
}
if (architecture.canFind(splitted.front)) {
splitted.popFront();
if(splitted.empty)
return true;
}
if (compiler == splitted.front) {
splitted.popFront();
enforce(splitted.empty, "No valid specification! The compiler has to be the last element!");
return true;
}
return false;
}
unittest {
auto platform=BuildPlatform(["posix", "linux"], ["x86_64"], "dmd");
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"));
}
}
 
 
scope (failure) {
fil.close();
}
 
// NOTE: This must be kept in sync with the dub.platform module
fil.write(q{
module dub_platform_probe;
 
template toString(int v) { enum toString = v.stringof; }
View
145
source/dub/platform.d
/**
Determines the strings to identify the current build platform.
 
Copyright: © 2012 rejectedsoftware e.K.
Build platform identification and speficiation matching.
 
This module is useful for determining the build platform for a certain
machine and compiler invocation. Example applications include classifying
CI slave machines.
 
It also contains means to match build platforms against a platform
specification string as used in package reciptes.
 
Copyright: © 2012-2016 rejectedsoftware e.K.
License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
Authors: Sönke Ludwig
*/
module dub.platform;
 
import std.array;
 
 
/** Determines the full build platform used for the current build.
 
Note that the `BuildPlatform.compilerBinary` field will be left empty.
 
See_Also: `determinePlatform`, `determineArchitecture`, `determineCompiler`
*/
BuildPlatform determineBuildPlatform()
{
BuildPlatform ret;
ret.platform = determinePlatform();
ret.architecture = determineArchitecture();
ret.compiler = determineCompiler();
ret.frontendVersion = __VERSION__;
return ret;
}
 
 
/** Returns a list of platform identifiers that apply to the current
build.
 
Example results are `["windows"]` or `["posix", "osx"]`. The identifiers
correspond to the compiler defined version constants built into the
language, except that they are converted to lower case.
 
See_Also: `determineBuildPlatform`
*/
string[] determinePlatform()
{
auto ret = appender!(string[])();
version(Windows) ret.put("windows");
version(MinGW) ret.put("mingw");
return ret.data;
}
 
/** Returns a list of architecture identifiers that apply to the current
build.
 
Example results are `["x86_64"]` or `["arm", "arm_softfloat"]`. The
identifiers correspond to the compiler defined version constants built into
the language, except that they are converted to lower case.
 
See_Also: `determineBuildPlatform`
*/
string[] determineArchitecture()
{
auto ret = appender!(string[])();
version(X86) ret.put("x86");
version(Alpha_HardFP) ret.put("alpha_hardfp");
return ret.data;
}
 
/** Determines the canonical compiler name used for the current build.
 
The possible values currently are "dmd", "gdc", "ldc2" or "sdc". If an
unknown compiler is used, this function will return an empty string.
 
See_Also: `determineBuildPlatform`
*/
string determineCompiler()
{
version(DigitalMars) return "dmd";
else version(GNU) return "gdc";
else version(SDC) return "sdc";
else return null;
}
 
/** Matches a platform specification string against a build platform.
 
Specifications are build upon the following scheme, where each component
is optional (indicated by []), but the order is obligatory:
"[-platform][-architecture][-compiler]"
 
So the following strings are valid specifications: `"-windows-x86-dmd"`,
`"-dmd"`, `"-arm"`, `"-arm-dmd"`, `"-windows-dmd"`
Params:
platform = The build platform to match agains the platform specification
specification = The specification being matched. It must either be an
empty string or start with a dash.
 
Returns:
`true` if the given specification matches the build platform, `false`
otherwise. Using an empty string as the platform specification will
always result in a match.
*/
bool matchesSpecification(in BuildPlatform platform, const(char)[] specification)
{
import std.string : format;
import std.algorithm : canFind, splitter;
import std.exception : enforce;
 
if (specification.empty) return true;
if (platform == BuildPlatform.any) return true;
 
auto splitted = specification.splitter('-');
assert(!splitted.empty, "No valid platform specification! The leading hyphen is required!");
splitted.popFront(); // Drop leading empty match.
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!");
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"));
}
 
/// Represents a platform a package can be build upon.
struct BuildPlatform {
/// Special constant used to denote matching any build platform.
enum any = BuildPlatform(null, null, null, null, -1);
 
/// Platform identifiers, e.g. ["posix", "windows"]
string[] platform;
/// CPU architecture identifiers, e.g. ["x86", "x86_64"]
string[] architecture;
/// Canonical compiler name e.g. "dmd"
string compiler;
/// Compiler binary name e.g. "ldmd2"
string compilerBinary;
/// Compiled frontend version (e.g. `2067` for frontend versions 2.067.x)
int frontendVersion;
}