From e9bf06ab3fabba069e6f5d84e0c318bc642b6967 Mon Sep 17 00:00:00 2001 From: Mathias Lang Date: Tue, 19 Dec 2023 19:15:51 +0100 Subject: [PATCH] Move data part of dub.platform to dub.data We want to separate the data part, which is exposed to the PackageRecipe, from the actual platform check code, which is used when building. --- build-files.txt | 1 + source/dub/compilers/compiler.d | 2 +- source/dub/data/platform.d | 128 ++++++++++++++++++++++++++++++++ source/dub/platform.d | 117 +---------------------------- 4 files changed, 131 insertions(+), 117 deletions(-) create mode 100644 source/dub/data/platform.d diff --git a/build-files.txt b/build-files.txt index 3a9ec14d1..182d0171c 100644 --- a/build-files.txt +++ b/build-files.txt @@ -6,6 +6,7 @@ source/dub/compilers/dmd.d source/dub/compilers/gdc.d source/dub/compilers/ldc.d source/dub/compilers/utils.d +source/dub/data/platform.d source/dub/data/settings.d source/dub/dependency.d source/dub/dependencyresolver.d diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index e98de64fc..6a0014ece 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -9,7 +9,7 @@ module dub.compilers.compiler; public import dub.compilers.buildsettings; deprecated("Please `import dub.dependency : Dependency` instead") public import dub.dependency : Dependency; -public import dub.platform : BuildPlatform, matchesSpecification; +public import dub.data.platform : BuildPlatform, matchesSpecification; import dub.internal.vibecompat.inet.path; import dub.internal.vibecompat.core.file; diff --git a/source/dub/data/platform.d b/source/dub/data/platform.d new file mode 100644 index 000000000..fb0870e70 --- /dev/null +++ b/source/dub/data/platform.d @@ -0,0 +1,128 @@ +/******************************************************************************* + + Represent a target platform + + Platform informations can be embedded in recipe, such that some settings + only target a certain platform (e.g. sourceFiles, lflags, etc...). + The struct in this module represent that information, structured. + +*******************************************************************************/ + +module dub.data.platform; + +/// 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; + /// Compiler version e.g. "1.11.0" + string compilerVersion; + /// Frontend version string from frontendVersion + /// e.g: 2067 => "2.067" + 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"); + } + + /// Checks to see if platform field contains windows + 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); + } +} + +/** 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 against 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.range : empty; + 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")); + + // Before PR#2279, a leading '-' was required + assert(platform.matchesSpecification("-x86_64")); +} diff --git a/source/dub/platform.d b/source/dub/platform.d index 6ee31b2e8..833061a98 100644 --- a/source/dub/platform.d +++ b/source/dub/platform.d @@ -15,6 +15,7 @@ module dub.platform; import std.array; +public import dub.data.platform; // archCheck, compilerCheck, and platformCheck are used below and in // generatePlatformProbeFile, so they've been extracted into these strings @@ -166,119 +167,3 @@ string determineCompiler() { mixin(compilerCheck); } - -/** 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 against 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 : 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")); - - // Before PR#2279, a leading '-' was required - assert(platform.matchesSpecification("-x86_64")); -} - -/// 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; - /// Compiler version e.g. "1.11.0" - string compilerVersion; - /// Frontend version string from frontendVersion - /// e.g: 2067 => "2.067" - 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"); - } - - /// Checks to see if platform field contains windows - 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); - } -}