| | /** |
---|
| | 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; |
---|
| | } |
---|
| | |
---|
| | |