From 1a2bef3ec8dedfb14c292b74839df510a041bebf Mon Sep 17 00:00:00 2001 From: Dragos Carp Date: Sun, 9 Mar 2014 14:06:50 +0100 Subject: [PATCH 1/5] Added dub support --- cmake-d/CMakeLists.txt | 1 + cmake-d/UseDub.cmake | 65 ++++++++++++++++++++++++++ cmake-d/UseDub/DubToCMake.d | 93 +++++++++++++++++++++++++++++++++++++ cmake-d/UseDub/DubUrl.d | 91 ++++++++++++++++++++++++++++++++++++ tests/dub/CMakeLists.txt | 7 +++ 5 files changed, 257 insertions(+) create mode 100644 cmake-d/UseDub.cmake create mode 100644 cmake-d/UseDub/DubToCMake.d create mode 100644 cmake-d/UseDub/DubUrl.d create mode 100644 tests/dub/CMakeLists.txt diff --git a/cmake-d/CMakeLists.txt b/cmake-d/CMakeLists.txt index d66d895..1ffd2ec 100644 --- a/cmake-d/CMakeLists.txt +++ b/cmake-d/CMakeLists.txt @@ -22,6 +22,7 @@ SET (MOD_SRCS FindGDCPath.cmake UseDDoc.cmake UseDDeps.cmake + UseDUB.cmake dependencies.cmake UseDUnittest.cmake FindPhobos.cmake diff --git a/cmake-d/UseDub.cmake b/cmake-d/UseDub.cmake new file mode 100644 index 0000000..aa085bf --- /dev/null +++ b/cmake-d/UseDub.cmake @@ -0,0 +1,65 @@ +# This modules add functions for downloading and building dub dependencies. +# This code sets the following variables and functions: +# +# DUB_DIRECTORY = the full path to Dub pacakges +# +# DubProject_Add( [version]) +# +#============================================================================ +# Copyright (c) 2014 Dragos Carp +# +# All rights reserved. +# +# See LICENSE for details. +# + +set(DUB_DIRECTORY ${CMAKE_BINARY_DIR}/UseDub CACHE PATH "Dub packages direcotry") + +set(DUB_REGISTRY "http://code.dlang.org/packages") +file(MAKE_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp) + +if(NOT CMAKE_D_COMPILER) + message(FATAL_ERROR "UseDub needs a D compiler or use it in a D project.") +endif(NOT CMAKE_D_COMPILER) + +#compile json parsers +if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl OR 1) + find_file(DUB_GET_PACKAGE_URL_D_SRC "DubUrl.d" + PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH + PATH_SUFFIXES "UseDub") + execute_process(COMMAND ${CMAKE_D_COMPILER} ${DUB_GET_PACKAGE_URL_D_SRC} + WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp) + unset(DUB_GET_PACKAGE_URL_D_SRC CACHE) +endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl OR 1) +if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake OR 1) + find_file(DUB_PACKAGE_TO_CMAKE_D_SRC "DubToCMake.d" + PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH + PATH_SUFFIXES "UseDub") + execute_process(COMMAND ${CMAKE_D_COMPILER} ${DUB_PACKAGE_TO_CMAKE_D_SRC} + WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp) + unset(DUB_PACKAGE_TO_CMAKE_D_SRC CACHE) +endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake OR 1) + +include(ExternalProject) + +function(DubProject_Add name) + if(NOT EXISTS ${DUB_DIRECTORY}/${name}.json) + file(DOWNLOAD ${DUB_REGISTRY}/${name}.json ${DUB_DIRECTORY}/${name}.json) + endif(NOT EXISTS ${DUB_DIRECTORY}/${name}.json) + + if(${ARGC} GREATER 1) + execute_process(COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubUrl -p ${name}.json -t ${ARGN} + WORKING_DIRECTORY ${DUB_DIRECTORY}) + else(${ARGC} GREATER 1) + execute_process(COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubUrl -p ${name}.json + WORKING_DIRECTORY ${DUB_DIRECTORY}) + endif(${ARGC} GREATER 1) + + include(${DUB_DIRECTORY}/${name}.cmake) + + ExternalProject_Add(${name} + DOWNLOAD_DIR ${DUB_DIRECTORY}/${name} + URL ${DUB_PACKAGE_URL} + PATCH_COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubToCMake -p package.json + CMAKE_CACHE_ARGS -DCMAKE_MODULE_PATH:PATH=${CMAKE_MODULE_PATH}) +endfunction() diff --git a/cmake-d/UseDub/DubToCMake.d b/cmake-d/UseDub/DubToCMake.d new file mode 100644 index 0000000..5478851 --- /dev/null +++ b/cmake-d/UseDub/DubToCMake.d @@ -0,0 +1,93 @@ +import std.file; +import std.getopt; +import std.json; +import std.stdio; +import std.string; + +int main(string[] args) +{ + string dubFile = "dub.json"; + string cmakeFile = "CMakeLists.txt"; + + getopt(args, + "package|p", &dubFile, + "output|o", &cmakeFile); + + if (!exists(dubFile)) + { + stderr.writefln("Cannot find file: '%s'", dubFile); + return -1; + } + + string json = readText(dubFile); + JSONValue root = parseJSON(json); + + string cmake = q"< +cmake_minimum_required(VERSION 2.8) + +project(%1$s D) + +find_file(APP_MAIN_FILE + NAMES app.d main.d %1$s/main.d %1$s/app.d + PATHS source src NO_DEFAULT_PATH) + +file(GLOB_RECURSE SRC_FILES source/*.d src/*.d) +if(APP_MAIN_FILE) + list(REMOVE_ITEM SRC_FILES ${APP_MAIN_FILE}) +endif(APP_MAIN_FILE) +>".format(root["name"].str); + + switch ("targetType" in root.object ? root["targetType"].str : "autodetect") + { + case "autodetect": + cmake ~= q"< +if(APP_MAIN_FILE) + add_executable(%1$s ${SRC_FILES} ${APP_MAIN_FILE}) +else(APP_MAIN_FILE) + add_library(%1$s ${SRC_FILES}) +endif(APP_MAIN_FILE) +>".format(root["targetName"].str); + break; + case "none": + break; + case "executable": + cmake ~= q"< +add_executable(%s ${SRC_FILES} ${APP_MAIN_FILE}) +>".format(root["targetName"].str); + break; + case "library": + cmake ~= q"< +add_library(%s ${SRC_FILES}) +>".format(root["targetName"].str); + break; + case "sourceLibrary": + break; + case "staticLibrary": + cmake ~= q"< +add_library(%s STATIC ${SRC_FILES}) +>".format(root["targetName"].str); + break; + case "dynamicLibrary": + cmake ~= q"< +add_library(%s SHARED ${SRC_FILES}) +>".format(root["targetName"].str); + break; + default: + assert(false, "Unknown targetType"); + break; + } + + if ("dependencies" in root.object) + { + cmake ~= "\ninclude(UseDub)\n"; + foreach (dependency, version_; root["dependencies"].object) + { + cmake ~= "DubProject_Add(%s %s)\n".format(dependency, version_.str); + } + } + + + std.file.write(cmakeFile, cmake); + + return 0; +} diff --git a/cmake-d/UseDub/DubUrl.d b/cmake-d/UseDub/DubUrl.d new file mode 100644 index 0000000..5ee55d3 --- /dev/null +++ b/cmake-d/UseDub/DubUrl.d @@ -0,0 +1,91 @@ +import std.algorithm; +import std.array; +import std.file; +import std.getopt; +import std.json; +import std.stdio; +import std.string; + +int main(string[] args) +{ + string registryFile = ""; + string packageVersion = ""; + bool listVersions; + string outputPath = "."; + + getopt(args, + "package|p", ®istryFile, + "tag|t", &packageVersion, + "list|l", &listVersions, + "output|o", &outputPath); + + if (registryFile.empty) + { + stderr.writeln("Package registry file (.json) need to be specified."); + return -1; + } + + if (!exists(registryFile) && !registryFile.endsWith(".json")) + registryFile ~= ".json"; + + if (!exists(registryFile)) + { + stderr.writefln("Package registry file '%s' not found.", registryFile); + return -1; + } + + string json = readText(registryFile); + JSONValue node; + JSONValue root = parseJSON(json); + + if (packageVersion.empty) + { + node = root["versions"][0]; + } + else + { + auto range = root["versions"].array.find!"a[\"version\"].str == b"(packageVersion); + if (!range.empty) + { + node = range[0]; + } + else + { + stderr.writefln("No version tagged '%s' found.", packageVersion); + return -1; + } + } + + if (registryFile.endsWith(".json")) + { + registryFile = registryFile[0..$-5]; + } + + if (listVersions) + { + writefln("Package '%s'", registryFile); + + foreach(n; root["versions"].array) + { + writefln(" %s => %s", n["version"].str, n["downloadUrl"].str); + } + } + + packageVersion = node["version"].str; + auto packageUrl = node["downloadUrl"].str; + auto packageName = root["name"].str; + + if (!outputPath.isDir) + { + stderr.writefln("Output path '%s' need to be a directory.", outputPath); + return -1; + } + + string output = "set(DUB_PACKAGE_NAME, \"%s\")\n".format(packageName) ~ + "set(DUB_PACKAGE_VERSION \"%s\")\n".format(packageVersion) ~ + "set(DUB_PACKAGE_URL \"%s\")\n".format(packageUrl); + + std.file.write(outputPath ~ "/" ~ packageName ~ ".cmake", output); + + return 0; +} diff --git a/tests/dub/CMakeLists.txt b/tests/dub/CMakeLists.txt new file mode 100644 index 0000000..73f742a --- /dev/null +++ b/tests/dub/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.8) + +project(DubTest D) + +include(UseDub) + +DubProject_Add(derelict-sdl2 ~2.0.0) From d313ac0ce12cf7f6feee582c75772d9f27c25b84 Mon Sep 17 00:00:00 2001 From: Dragos Carp Date: Tue, 1 Apr 2014 03:29:48 +0200 Subject: [PATCH 2/5] added semver.d --- cmake-d/UseDub/DubUrl.d | 48 ++++ cmake-d/UseDub/semver.d | 606 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 654 insertions(+) create mode 100644 cmake-d/UseDub/semver.d diff --git a/cmake-d/UseDub/DubUrl.d b/cmake-d/UseDub/DubUrl.d index 5ee55d3..b2f4d40 100644 --- a/cmake-d/UseDub/DubUrl.d +++ b/cmake-d/UseDub/DubUrl.d @@ -6,6 +6,54 @@ import std.json; import std.stdio; import std.string; + +struct Version +{ + uint major; + uint minor; + uint patch; + + this(string ) +} + +/** + * Finds the best match of $(D range) in $(D choices) versions list. + * + * Params: + * range = Match criteria. + * choices = Versions list it is matched against. + * + * Returns: + * Best match in $(D choices) or empty string if no match is found. + * + * See_Also: + * $(WEB https://github.com/npm/npm/blob/master/doc/misc/semver.md#ranges Ranges definition) + */ +string matchVersion(string range, string[] choices) +{ + foreach (ref choice; choices) + { + choice.skipOver('~'); + } + + if (range.skipOver('~')) + { + foreach (choice; choices) + { + if (choice.startsWith(range)) + return choice; + } + return ""; + } + + return ""; +} + +unittest +{ + +} + int main(string[] args) { string registryFile = ""; diff --git a/cmake-d/UseDub/semver.d b/cmake-d/UseDub/semver.d new file mode 100644 index 0000000..e994f03 --- /dev/null +++ b/cmake-d/UseDub/semver.d @@ -0,0 +1,606 @@ +import std.algorithm; +import std.array; +import std.conv; +import std.range; +import std.regex; +import std.stdio; +import std.string; + +enum ReleaseType +{ + MAJOR, + MINOR, + PATCH, + PRERELEASE, +}; + +struct SemVer +{ + uint[3] ids; + string[] prerelease; + string[] build; + + bool isValid; + + @disable this(); + + this(string semVer) + { + isValid = false; + if (semVer.empty) + return; + if (!semVer.skipOver('v')) + semVer.skipOver('='); + + auto re = regex(`^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([a-zA-Z\d-.]+))?(?:\+([a-zA-Z\d-.]+))?$`); + auto m = semVer.matchAll(re); + if (m.empty) + return; + + foreach (i, ref id; ids) + { + if (!m.captures[i+1].empty) + id = m.captures[i+1].to!uint; + } + + if (!m.captures[4].empty) + { + prerelease = m.captures[4].splitter('.').array; + if (prerelease.any!empty) + return; + } + + if (!m.captures[5].empty) + { + build = m.captures[5].splitter('.').array; + if (build.any!empty) + return; + } + + isValid = true; + } + + string toString() const + { + if (!isValid) + return ""; + + string semVer = "%(%s.%)".format(ids); + if (!prerelease.empty) + semVer ~= "-" ~ "%-(%s.%)".format(prerelease); + if (!build.empty) + semVer ~= "+" ~ "%-(%s.%)".format(build); + return semVer; + } + + @property bool valid() const + { + return isValid; + } + + SemVer inc(ReleaseType releaseType) const + in + { + assert(this.valid); + } + out(result) + { + assert(result.valid); + } + body + { + SemVer result = "0"; + foreach (i; 0..releaseType) + result.ids[i] = this.ids[i]; + if (releaseType != ReleaseType.PRERELEASE) + result.ids[releaseType] = this.ids[releaseType]+1; + return result; + } + + SemVer appendPrerelease0() + { + if (prerelease.empty) + prerelease ~= "0"; + return this; + } + + unittest + { + assert(SemVer("1.2.3").inc(ReleaseType.MAJOR) == SemVer("2.0.0")); + assert(SemVer("1.2.3").inc(ReleaseType.MINOR) == SemVer("1.3.0")); + assert(SemVer("1.2.3-alpha").inc(ReleaseType.MINOR) == SemVer("1.3.0")); + assert(SemVer("1.2.3").inc(ReleaseType.PATCH) == SemVer("1.2.4")); + assert(SemVer("1.2.3-alpha").inc(ReleaseType.PATCH) == SemVer("1.2.4")); + assert(SemVer("1.2.3").inc(ReleaseType.PRERELEASE) == SemVer("1.2.3")); + assert(SemVer("1.2.3-alpha").inc(ReleaseType.PRERELEASE) == SemVer("1.2.3")); + } + + int opCmp(ref const SemVer v) const + in + { + assert(this.valid); + assert(v.valid); + } + body + { + foreach (i; 0..ids.length) + { + if (ids[i] != v.ids[i]) + return ids[i] < v.ids[i] ? -1 : 1; + } + + if (!prerelease.empty && v.prerelease.empty) + return -1; + if (prerelease.empty && !v.prerelease.empty) + return 1; + + foreach (a, b; lockstep(prerelease, v.prerelease)) + { + if (a.isNumeric && b.isNumeric) + { + if (a.to!uint != b.to!uint) + return a.to!uint < b.to!uint ? -1 : 1; + else + continue; + } + if (a != b) + return a < b ? -1 : 1; + } + if (prerelease.length != v.prerelease.length) + return prerelease.length < v.prerelease.length ? -1 : 1; + + return 0; + } + + int opCmp(const SemVer v) const + { + return this.opCmp(v); + } + + bool opEquals(ref const SemVer v) const + { + return this.opCmp(v) == 0; + } + + bool opEquals(const SemVer v) const + { + return this.opEquals(v); + } +} + +unittest +{ + assert(!SemVer("1.2-.alpha.32").valid); + assert(!SemVer("1.2-alpha+").valid); + assert(!SemVer("1.2-alpha_").valid); + assert(!SemVer("1.2+32.").valid); + assert(!SemVer("1.2.5.6").valid); + assert(!SemVer("").valid); + assert(SemVer("1.0.0-alpha") < SemVer("1.0.0-alpha.1")); + assert(SemVer("1.0.0-alpha.1") < SemVer("1.0.0-alpha.beta")); + assert(SemVer("1.0.0-alpha.beta") < SemVer("1.0.0-beta")); + assert(SemVer("1.0.0-beta") < SemVer("1.0.0-beta.2")); + assert(SemVer("1.0.0-beta.2") < SemVer("1.0.0-beta.11")); + assert(SemVer("1.0.0-beta.11") < SemVer("1.0.0-rc.1")); + assert(SemVer("1.0.0-rc.1") < SemVer("1.0.0")); + assert(SemVer("1.0.0-rc.1") == SemVer("1.0.0-rc.1+build.5")); +} + +struct SemVerRange +{ + struct SimpleRange + { + string op; + SemVer semVer; + + string toString() const + { + return op ~ semVer.toString; + } + } + + SimpleRange[][] ranges; + + invariant() + { + assert(ranges.all!(r => r.all!(r => ["<", "<=", "=", ">=", ">"].canFind(r.op)))); + } + + bool isValid; + + @disable this(); + + this(string semVerRange) + { + isValid = false; + auto re = regex(`(~|~>|\^|<|<=|=|>=|>)?[v]?(\d+|\*|X|x)(?:\.(\d+|\*|X|x))?(?:\.(\d+|\*|X|x))?([\S]*)`); + + ranges = [SimpleRange[].init]; + + writeln(semVerRange); + + while (!semVerRange.stripLeft.empty) + { + auto m = semVerRange.matchFirst(re); + if (m.empty) + return; + + auto operator = m.captures[1]; + auto wildcard = wildcardAt([m.captures[2], m.captures[3], m.captures[4]]); + auto expanded = expand([m.captures[2], m.captures[3], m.captures[4], m.captures[5]]); + if (expanded.empty) + return; + + auto semVer = SemVer(expanded); + if (!semVer.valid) + return; + + switch (m.captures.pre.strip) + { + case "": + break; + case "-": + if (ranges[$-1].empty || ranges[$-1][$-1].op != "=" || + operator != "" || wildcard != ReleaseType.PRERELEASE) + return; + ranges[$-1][$-1].op = ">="; + operator = "<="; + break; + case "||": + ranges ~= SimpleRange[].init; + break; + default: + return; + } + + switch (operator) + { + case "": + case "=": + final switch (wildcard) + { + case ReleaseType.MAJOR: + assert(semVer == SemVer("0.0.0")); + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + break; + case ReleaseType.MINOR: + case ReleaseType.PATCH: + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(--wildcard).appendPrerelease0); + break; + case ReleaseType.PRERELEASE: + ranges[$-1] ~= SimpleRange("=", semVer); + break; + } + break; + case "<": + case "<=": + case ">=": + case ">": + if (operator == "<" || wildcard < ReleaseType.PRERELEASE) + semVer.appendPrerelease0; + ranges[$-1] ~= SimpleRange(operator, semVer); + break; + case "~": + final switch (wildcard) + { + case ReleaseType.MAJOR: + return; + case ReleaseType.MINOR: + case ReleaseType.PATCH: + --wildcard; + break; + case ReleaseType.PRERELEASE: + --wildcard; + --wildcard; + break; + } + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(wildcard).appendPrerelease0); + break; + case "~>": + final switch (wildcard) + { + case ReleaseType.MAJOR: + return; + case ReleaseType.MINOR: + --wildcard; + break; + case ReleaseType.PATCH: + case ReleaseType.PRERELEASE: + --wildcard; + --wildcard; + break; + } + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(wildcard).appendPrerelease0); + break; + case "^": + if (wildcard == ReleaseType.MAJOR || !semVer.prerelease.empty) + return; + if (semVer.ids[ReleaseType.MAJOR] != 0) + { + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.MAJOR).appendPrerelease0); + } + else if (semVer.ids[ReleaseType.MINOR] != 0) + { + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.MINOR).appendPrerelease0); + } + else + { + ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0); + ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.PATCH).appendPrerelease0); + } + break; + default: + assert(0); + break; + } + semVerRange = m.captures.post; + } + isValid = true; + } + + private static ReleaseType wildcardAt(string[3] semVer) + { + foreach (i; ReleaseType.MAJOR..ReleaseType.PRERELEASE) + { + if (["", "*", "X", "x"].canFind(semVer[i])) + return i; + } + return ReleaseType.PRERELEASE; + } + + unittest + { + assert(wildcardAt(["*", "", ""]) == ReleaseType.MAJOR); + assert(wildcardAt(["X", "", ""]) == ReleaseType.MAJOR); + assert(wildcardAt(["1", "", ""]) == ReleaseType.MINOR); + assert(wildcardAt(["1", "x", ""]) == ReleaseType.MINOR); + assert(wildcardAt(["1", "2", ""]) == ReleaseType.PATCH); + assert(wildcardAt(["1", "2", "x"]) == ReleaseType.PATCH); + assert(wildcardAt(["1", "2", "3"]) == ReleaseType.PRERELEASE); + } + + private static string expand(string[4] semVer) + { + ReleaseType wildcard = wildcardAt(semVer[0..3]); + if (wildcard != ReleaseType.PRERELEASE) + { + if (semVer[wildcard+1..$].any!`!["", "*", "X", "x"].canFind(a)`) + return ""; + foreach (j; wildcard..ReleaseType.PRERELEASE) + semVer[j] = "0"; + } + string result = "%-(%s.%)".format(semVer[0..3]); + if (!semVer[3].empty) + result ~= semVer[3]; + return result; + } + + unittest + { + assert(expand(["*", "", "", ""]) == "0.0.0"); + assert(expand(["X", "", "", ""]) == "0.0.0"); + assert(expand(["1", "2", "3", ""]) == "1.2.3"); + assert(expand(["1", "2", "3", "-abc"]) == "1.2.3-abc"); + assert(expand(["1", "2", "", ""]) == "1.2.0"); + assert(expand(["1", "2", "", "-abc"]) == ""); + assert(expand(["1", "2", "x", ""]) == "1.2.0"); + assert(expand(["1", "", "", ""]) == "1.0.0"); + assert(expand(["1", "x", "", ""]) == "1.0.0"); + } + + string toString() const + { + if (!isValid) + return ""; + + return "%(%(%s %) || %)".format(ranges); + } + + @property bool valid() const + { + return isValid; + } + + private static bool simpleRangeSatisfiedBy(SimpleRange simpleRange, SemVer semVer) + in + { + assert(semVer.valid); + assert(["<", "<=", "=", ">=", ">"].canFind(simpleRange.op)); + assert(simpleRange.semVer.valid); + } + body + { + switch (simpleRange.op) + { + case "<": + return semVer < simpleRange.semVer; + case "<=": + return semVer <= simpleRange.semVer; + case "=": + return semVer == simpleRange.semVer; + case ">=": + return semVer >= simpleRange.semVer; + case ">": + return semVer > simpleRange.semVer; + default: + return false; + } + } + + bool satisfiedBy(SemVer semVer) + in + { + assert(semVer.valid); + assert(valid); + } + body + { + return ranges.any!(r => r.all!(s => simpleRangeSatisfiedBy(s, semVer))); + } + +} + +bool satisfies(SemVer semVer, SemVerRange semVerRange) +{ + return semVerRange.satisfiedBy(semVer); +} + +SemVer maxSatisfying(SemVer[] semVers, SemVerRange semVerRange) +in +{ + assert(semVers.all!"a.valid"); + assert(semVerRange.valid); +} +body +{ + auto found = semVers.sort.find!(a => satisfies(a, semVerRange)); + return found.empty ? SemVer("invalid") : found[0]; +} + +unittest +{ + assert(SemVerRange("1.x || >=2.5.0 || 5.0.0 - 7.2.3").valid); + assert(!SemVerRange("blerg").valid); + assert(!SemVerRange("git+https://user:password0123@github.com/foo").valid); + + assert(SemVer("1.2.3").satisfies(SemVerRange("1.x || >=2.5.0 || 5.0.0 - 7.2.3"))); + + assert(SemVer("1.2.3").satisfies(SemVerRange("1.0.0 - 2.0.0"))); + assert(SemVer("1.0.0").satisfies(SemVerRange("1.0.0"))); + assert(SemVer("0.2.4").satisfies(SemVerRange(">=*"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("*"))); + assert(SemVer("v1.2.3-foo").satisfies(SemVerRange("*"))); + assert(SemVer("1.0.0").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.0.1").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.1.0").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.0.1").satisfies(SemVerRange(">1.0.0"))); + assert(SemVer("1.1.0").satisfies(SemVerRange(">1.0.0"))); + assert(SemVer("2.0.0").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("1.9999.9999").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("0.2.9").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("1.9999.9999").satisfies(SemVerRange("<2.0.0"))); + assert(SemVer("0.2.9").satisfies(SemVerRange("<2.0.0"))); + assert(SemVer("1.0.0").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.0.1").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.1.0").satisfies(SemVerRange(">=1.0.0"))); + assert(SemVer("1.0.1").satisfies(SemVerRange(">1.0.0"))); + assert(SemVer("1.1.0").satisfies(SemVerRange(">1.0.0"))); + assert(SemVer("2.0.0").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("1.9999.9999").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("0.2.9").satisfies(SemVerRange("<=2.0.0"))); + assert(SemVer("1.9999.9999").satisfies(SemVerRange("<2.0.0"))); + assert(SemVer("0.2.9").satisfies(SemVerRange("<2.0.0"))); + assert(SemVer("v0.1.97").satisfies(SemVerRange(">=0.1.97"))); + assert(SemVer("0.1.97").satisfies(SemVerRange(">=0.1.97"))); + assert(SemVer("1.2.4").satisfies(SemVerRange("0.1.20 || 1.2.4"))); + assert(SemVer("0.0.0").satisfies(SemVerRange(">=0.2.3 || <0.0.1"))); + assert(SemVer("0.2.3").satisfies(SemVerRange(">=0.2.3 || <0.0.1"))); + assert(SemVer("0.2.4").satisfies(SemVerRange(">=0.2.3 || <0.0.1"))); + assert(SemVer("2.1.3").satisfies(SemVerRange("2.x.x"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.x"))); + assert(SemVer("2.1.3").satisfies(SemVerRange("1.2.x || 2.x"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.x || 2.x"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("x"))); + assert(SemVer("2.1.3").satisfies(SemVerRange("2.*.*"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.*"))); + assert(SemVer("2.1.3").satisfies(SemVerRange("1.2.* || 2.*"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.* || 2.*"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("*"))); + assert(SemVer("2.1.2").satisfies(SemVerRange("2"))); + assert(SemVer("2.3.1").satisfies(SemVerRange("2.3"))); + assert(SemVer("2.4.0").satisfies(SemVerRange("~2.4"))); + assert(SemVer("2.4.5").satisfies(SemVerRange("~2.4"))); + assert(SemVer("3.2.2").satisfies(SemVerRange("~>3.2.1"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~>1"))); + assert(SemVer("1.0.2").satisfies(SemVerRange("~1.0"))); + assert(SemVer("1.0.12").satisfies(SemVerRange("~1.0.3"))); + assert(SemVer("1.0.0").satisfies(SemVerRange(">=1"))); + assert(SemVer("1.1.1").satisfies(SemVerRange("<1.2"))); + assert(SemVer("1.0.0-bet").satisfies(SemVerRange("1"))); + assert(SemVer("0.5.5").satisfies(SemVerRange("~v0.5.4-pre"))); + assert(SemVer("0.5.4").satisfies(SemVerRange("~v0.5.4-pre"))); + assert(SemVer("0.7.2").satisfies(SemVerRange("=0.7.x"))); + assert(SemVer("0.7.2").satisfies(SemVerRange(">=0.7.x"))); + assert(SemVer("0.7.0-asdf").satisfies(SemVerRange("=0.7.x"))); + assert(SemVer("0.7.0-asdf").satisfies(SemVerRange(">=0.7.x"))); + assert(SemVer("0.6.2").satisfies(SemVerRange("<=0.7.x"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 >=1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 =1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 >=1.2.3 1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3 >=1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.1 1.2.3"))); + assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.3 >=1.2.1"))); + assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.3 >=1.2.1"))); + assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.1 >=1.2.3"))); + assert(SemVer("1.2.3-beta").satisfies(SemVerRange("<=1.2.3"))); + assert(SemVer("1.3.0-beta").satisfies(SemVerRange(">1.2"))); + assert(SemVer("1.2.8").satisfies(SemVerRange(">=1.2"))); + assert(SemVer("1.8.1").satisfies(SemVerRange("^1.2.3"))); + assert(SemVer("1.2.3-beta").satisfies(SemVerRange("^1.2.3"))); + assert(SemVer("0.1.2").satisfies(SemVerRange("^0.1.2"))); + assert(SemVer("0.1.2").satisfies(SemVerRange("^0.1"))); + assert(SemVer("1.4.2").satisfies(SemVerRange("^1.2"))); + assert(SemVer("1.4.2").satisfies(SemVerRange("^1.2 ^1"))); + assert(SemVer("1.2.0-pre").satisfies(SemVerRange("^1.2"))); + assert(SemVer("1.2.3-pre").satisfies(SemVerRange("^1.2.3"))); + + assert(!SemVer("2.2.3").satisfies(SemVerRange("1.0.0 - 2.0.0"))); + assert(!SemVer("1.0.1").satisfies(SemVerRange("1.0.0"))); + assert(!SemVer("0.0.0").satisfies(SemVerRange(">=1.0.0"))); + assert(!SemVer("0.0.1").satisfies(SemVerRange(">=1.0.0"))); + assert(!SemVer("0.1.0").satisfies(SemVerRange(">=1.0.0"))); + assert(!SemVer("0.0.1").satisfies(SemVerRange(">1.0.0"))); + assert(!SemVer("0.1.0").satisfies(SemVerRange(">1.0.0"))); + assert(!SemVer("3.0.0").satisfies(SemVerRange("<=2.0.0"))); + assert(!SemVer("2.9999.9999").satisfies(SemVerRange("<=2.0.0"))); + assert(!SemVer("2.2.9").satisfies(SemVerRange("<=2.0.0"))); + assert(!SemVer("2.9999.9999").satisfies(SemVerRange("<2.0.0"))); + assert(!SemVer("2.2.9").satisfies(SemVerRange("<2.0.0"))); + assert(!SemVer("v0.1.93").satisfies(SemVerRange(">=0.1.97"))); + assert(!SemVer("0.1.93").satisfies(SemVerRange(">=0.1.97"))); + assert(!SemVer("1.2.3").satisfies(SemVerRange("0.1.20 || 1.2.4"))); + assert(!SemVer("0.0.3").satisfies(SemVerRange(">=0.2.3 || <0.0.1"))); + assert(!SemVer("0.2.2").satisfies(SemVerRange(">=0.2.3 || <0.0.1"))); + assert(!SemVer("1.1.3").satisfies(SemVerRange("2.x.x"))); + assert(!SemVer("3.1.3").satisfies(SemVerRange("2.x.x"))); + assert(!SemVer("1.3.3").satisfies(SemVerRange("1.2.x"))); + assert(!SemVer("3.1.3").satisfies(SemVerRange("1.2.x || 2.x"))); + assert(!SemVer("1.1.3").satisfies(SemVerRange("1.2.x || 2.x"))); + assert(!SemVer("1.1.3").satisfies(SemVerRange("2.*.*"))); + assert(!SemVer("3.1.3").satisfies(SemVerRange("2.*.*"))); + assert(!SemVer("1.3.3").satisfies(SemVerRange("1.2.*"))); + assert(!SemVer("3.1.3").satisfies(SemVerRange("1.2.* || 2.*"))); + assert(!SemVer("1.1.3").satisfies(SemVerRange("1.2.* || 2.*"))); + assert(!SemVer("1.1.2").satisfies(SemVerRange("2"))); + assert(!SemVer("2.4.1").satisfies(SemVerRange("2.3"))); + assert(!SemVer("2.5.0").satisfies(SemVerRange("~2.4"))); + assert(!SemVer("2.3.9").satisfies(SemVerRange("~2.4"))); + assert(!SemVer("3.3.2").satisfies(SemVerRange("~>3.2.1"))); + assert(!SemVer("3.2.0").satisfies(SemVerRange("~>3.2.1"))); + assert(!SemVer("0.2.3").satisfies(SemVerRange("~1"))); + assert(!SemVer("2.2.3").satisfies(SemVerRange("~>1"))); + assert(!SemVer("1.1.0").satisfies(SemVerRange("~1.0"))); + assert(!SemVer("1.0.0").satisfies(SemVerRange("<1"))); + assert(!SemVer("1.1.1").satisfies(SemVerRange(">=1.2"))); + assert(!SemVer("2.0.0-beta").satisfies(SemVerRange("1"))); + assert(!SemVer("0.5.4-alpha").satisfies(SemVerRange("~v0.5.4-beta"))); + assert(!SemVer("1.0.0-beta").satisfies(SemVerRange("<1"))); + assert(!SemVer("0.8.2").satisfies(SemVerRange("=0.7.x"))); + assert(!SemVer("0.6.2").satisfies(SemVerRange(">=0.7.x"))); + assert(!SemVer("0.7.2").satisfies(SemVerRange("<=0.7.x"))); + assert(!SemVer("1.2.3-beta").satisfies(SemVerRange("<1.2.3"))); + assert(!SemVer("1.2.3-beta").satisfies(SemVerRange("=1.2.3"))); + assert(!SemVer("1.2.8").satisfies(SemVerRange(">1.3"))); + assert(!SemVer("2.0.0-alpha").satisfies(SemVerRange("^1.2.3"))); + assert(!SemVer("1.2.2").satisfies(SemVerRange("^1.2.3"))); + assert(!SemVer("1.1.9").satisfies(SemVerRange("^1.2"))); + assert(!SemVer("2.0.0-pre").satisfies(SemVerRange("^1.2.3"))); +} From 05d891a0eea33d7d039fa86a38f1ecea3a7e509c Mon Sep 17 00:00:00 2001 From: Dragos Carp Date: Tue, 15 Apr 2014 01:12:12 +0200 Subject: [PATCH 3/5] Integrated semver.d --- cmake-d/UseDub.cmake | 5 ++++- cmake-d/UseDub/DubUrl.d | 38 +++++++++++++++++++++++++------------- cmake-d/UseDub/semver.d | 14 ++++++++++---- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/cmake-d/UseDub.cmake b/cmake-d/UseDub.cmake index aa085bf..ea8a053 100644 --- a/cmake-d/UseDub.cmake +++ b/cmake-d/UseDub.cmake @@ -27,7 +27,10 @@ if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl OR 1) find_file(DUB_GET_PACKAGE_URL_D_SRC "DubUrl.d" PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH PATH_SUFFIXES "UseDub") - execute_process(COMMAND ${CMAKE_D_COMPILER} ${DUB_GET_PACKAGE_URL_D_SRC} + find_file(SEMVER_SRC "semver.d" + PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH + PATH_SUFFIXES "UseDub") + execute_process(COMMAND ${CMAKE_D_COMPILER} ${DUB_GET_PACKAGE_URL_D_SRC} ${SEMVER_SRC} WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp) unset(DUB_GET_PACKAGE_URL_D_SRC CACHE) endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl OR 1) diff --git a/cmake-d/UseDub/DubUrl.d b/cmake-d/UseDub/DubUrl.d index b2f4d40..6c6e839 100644 --- a/cmake-d/UseDub/DubUrl.d +++ b/cmake-d/UseDub/DubUrl.d @@ -5,16 +5,7 @@ import std.getopt; import std.json; import std.stdio; import std.string; - - -struct Version -{ - uint major; - uint minor; - uint patch; - - this(string ) -} +import semver; /** * Finds the best match of $(D range) in $(D choices) versions list. @@ -88,11 +79,15 @@ int main(string[] args) if (packageVersion.empty) { - node = root["versions"][0]; + packageVersion = "*"; } - else + + auto versionRange = SemVerRange(packageVersion); + + if (!versionRange.valid) { - auto range = root["versions"].array.find!"a[\"version\"].str == b"(packageVersion); + // try exact string match + auto range = root["versions"].array.find!`a["version"].str == b`(packageVersion); if (!range.empty) { node = range[0]; @@ -103,6 +98,23 @@ int main(string[] args) return -1; } } + else + { + auto nodes = root["versions"].array.filter!(a => SemVer(a["version"].str).valid).array; + auto maxVersion = nodes.map!(a => SemVer(a["version"].str)).array.maxSatisfying(versionRange); + + if (maxVersion.valid) + { + auto range = nodes.find!((a, b) => SemVer(a["version"].str) == b)(maxVersion); + assert(!range.empty); + node = range[0]; + } + else + { + stderr.writefln("No version '%s' found.", versionRange); + return -1; + } + } if (registryFile.endsWith(".json")) { diff --git a/cmake-d/UseDub/semver.d b/cmake-d/UseDub/semver.d index e994f03..36c648f 100644 --- a/cmake-d/UseDub/semver.d +++ b/cmake-d/UseDub/semver.d @@ -217,8 +217,6 @@ struct SemVerRange ranges = [SimpleRange[].init]; - writeln(semVerRange); - while (!semVerRange.stripLeft.empty) { auto m = semVerRange.matchFirst(re); @@ -274,10 +272,12 @@ struct SemVerRange } break; case "<": + ranges[$-1] ~= SimpleRange(operator, semVer.appendPrerelease0); + break; case "<=": case ">=": case ">": - if (operator == "<" || wildcard < ReleaseType.PRERELEASE) + if (wildcard < ReleaseType.PRERELEASE) semVer.appendPrerelease0; ranges[$-1] ~= SimpleRange(operator, semVer); break; @@ -458,7 +458,7 @@ in } body { - auto found = semVers.sort.find!(a => satisfies(a, semVerRange)); + auto found = semVers.sort!"a > b".find!(a => satisfies(a, semVerRange)); return found.empty ? SemVer("invalid") : found[0]; } @@ -522,6 +522,7 @@ unittest assert(SemVer("1.0.12").satisfies(SemVerRange("~1.0.3"))); assert(SemVer("1.0.0").satisfies(SemVerRange(">=1"))); assert(SemVer("1.1.1").satisfies(SemVerRange("<1.2"))); + assert(SemVer("1.1.9").satisfies(SemVerRange("<=1.2"))); assert(SemVer("1.0.0-bet").satisfies(SemVerRange("1"))); assert(SemVer("0.5.5").satisfies(SemVerRange("~v0.5.4-pre"))); assert(SemVer("0.5.4").satisfies(SemVerRange("~v0.5.4-pre"))); @@ -590,6 +591,7 @@ unittest assert(!SemVer("1.1.0").satisfies(SemVerRange("~1.0"))); assert(!SemVer("1.0.0").satisfies(SemVerRange("<1"))); assert(!SemVer("1.1.1").satisfies(SemVerRange(">=1.2"))); + assert(!SemVer("1.3.0").satisfies(SemVerRange("<=1.2"))); assert(!SemVer("2.0.0-beta").satisfies(SemVerRange("1"))); assert(!SemVer("0.5.4-alpha").satisfies(SemVerRange("~v0.5.4-beta"))); assert(!SemVer("1.0.0-beta").satisfies(SemVerRange("<1"))); @@ -603,4 +605,8 @@ unittest assert(!SemVer("1.2.2").satisfies(SemVerRange("^1.2.3"))); assert(!SemVer("1.1.9").satisfies(SemVerRange("^1.2"))); assert(!SemVer("2.0.0-pre").satisfies(SemVerRange("^1.2.3"))); + + auto semVers = [SemVer("0.8.0"), SemVer("1.0.0"), SemVer("1.1.0")]; + assert(semVers.maxSatisfying(SemVerRange("<=1.0.0")) == SemVer("1.0.0")); + assert(semVers.maxSatisfying(SemVerRange(">=1.0")) == SemVer("1.1.0")); } From 011defaff5697e564eb1231a3855ad151dcbe35d Mon Sep 17 00:00:00 2001 From: Dragos Carp Date: Wed, 30 Apr 2014 00:44:54 +0200 Subject: [PATCH 4/5] Compile first dependencies --- cmake-d/UseDub/DubToCMake.d | 13 +++++++------ cmake-d/UseDub/DubUrl.d | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/cmake-d/UseDub/DubToCMake.d b/cmake-d/UseDub/DubToCMake.d index 5478851..a5b3fd2 100644 --- a/cmake-d/UseDub/DubToCMake.d +++ b/cmake-d/UseDub/DubToCMake.d @@ -21,6 +21,7 @@ int main(string[] args) string json = readText(dubFile); JSONValue root = parseJSON(json); + string target = root["targetName"].str; string cmake = q"< cmake_minimum_required(VERSION 2.8) @@ -46,31 +47,31 @@ if(APP_MAIN_FILE) else(APP_MAIN_FILE) add_library(%1$s ${SRC_FILES}) endif(APP_MAIN_FILE) ->".format(root["targetName"].str); +>".format(target); break; case "none": break; case "executable": cmake ~= q"< add_executable(%s ${SRC_FILES} ${APP_MAIN_FILE}) ->".format(root["targetName"].str); +>".format(target); break; case "library": cmake ~= q"< add_library(%s ${SRC_FILES}) ->".format(root["targetName"].str); +>".format(target); break; case "sourceLibrary": break; case "staticLibrary": cmake ~= q"< add_library(%s STATIC ${SRC_FILES}) ->".format(root["targetName"].str); +>".format(target); break; case "dynamicLibrary": cmake ~= q"< add_library(%s SHARED ${SRC_FILES}) ->".format(root["targetName"].str); +>".format(target); break; default: assert(false, "Unknown targetType"); @@ -84,9 +85,9 @@ add_library(%s SHARED ${SRC_FILES}) { cmake ~= "DubProject_Add(%s %s)\n".format(dependency, version_.str); } + cmake ~= "\nadd_dependencies(%s %-(%s %))\n".format(target, root["dependencies"].object.keys); } - std.file.write(cmakeFile, cmake); return 0; diff --git a/cmake-d/UseDub/DubUrl.d b/cmake-d/UseDub/DubUrl.d index 6c6e839..2947894 100644 --- a/cmake-d/UseDub/DubUrl.d +++ b/cmake-d/UseDub/DubUrl.d @@ -94,24 +94,31 @@ int main(string[] args) } else { - stderr.writefln("No version tagged '%s' found.", packageVersion); + stderr.writefln("%s has no version tagged %s.", root["name"].str, packageVersion); return -1; } } else { - auto nodes = root["versions"].array.filter!(a => SemVer(a["version"].str).valid).array; - auto maxVersion = nodes.map!(a => SemVer(a["version"].str)).array.maxSatisfying(versionRange); + string nodeVersionString(JSONValue node) + { + auto ver = node["version"].str; + ver.skipOver('~'); + return ver; + } + + auto nodes = root["versions"].array.filter!(a => SemVer(nodeVersionString(a)).valid).array; + auto maxVersion = nodes.map!(a => SemVer(nodeVersionString(a))).array.maxSatisfying(versionRange); if (maxVersion.valid) { - auto range = nodes.find!((a, b) => SemVer(a["version"].str) == b)(maxVersion); + auto range = nodes.find!((a, b) => SemVer(nodeVersionString(a)) == b)(maxVersion); assert(!range.empty); node = range[0]; } else { - stderr.writefln("No version '%s' found.", versionRange); + stderr.writefln("%s has no version %s.", root["name"].str, versionRange); return -1; } } From e3c869b05af8902af66149165c2760dc05d71a44 Mon Sep 17 00:00:00 2001 From: Dragos Carp Date: Wed, 21 May 2014 05:14:39 -0700 Subject: [PATCH 5/5] Fixed dependencies includes --- cmake-d/UseDub.cmake | 26 ++++++++++++++++++-------- cmake-d/UseDub/DubToCMake.d | 9 +++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/cmake-d/UseDub.cmake b/cmake-d/UseDub.cmake index ea8a053..2cd3267 100644 --- a/cmake-d/UseDub.cmake +++ b/cmake-d/UseDub.cmake @@ -13,7 +13,9 @@ # See LICENSE for details. # -set(DUB_DIRECTORY ${CMAKE_BINARY_DIR}/UseDub CACHE PATH "Dub packages direcotry") +if(NOT DUB_DIRECTORY) + set(DUB_DIRECTORY ${CMAKE_BINARY_DIR}/UseDub CACHE PATH "Dub packages directory") +endif(NOT DUB_DIRECTORY) set(DUB_REGISTRY "http://code.dlang.org/packages") file(MAKE_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp) @@ -23,25 +25,26 @@ if(NOT CMAKE_D_COMPILER) endif(NOT CMAKE_D_COMPILER) #compile json parsers -if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl OR 1) +if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl) find_file(DUB_GET_PACKAGE_URL_D_SRC "DubUrl.d" PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH PATH_SUFFIXES "UseDub") find_file(SEMVER_SRC "semver.d" PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH PATH_SUFFIXES "UseDub") - execute_process(COMMAND ${CMAKE_D_COMPILER} ${DUB_GET_PACKAGE_URL_D_SRC} ${SEMVER_SRC} + get_filename_component(SEMVER_PATH ${SEMVER_SRC} PATH) + execute_process(COMMAND ${CMAKE_D_COMPILER} -I${SEMVER_PATH} ${DUB_GET_PACKAGE_URL_D_SRC} ${SEMVER_SRC} WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp) unset(DUB_GET_PACKAGE_URL_D_SRC CACHE) -endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl OR 1) -if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake OR 1) +endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl) +if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake) find_file(DUB_PACKAGE_TO_CMAKE_D_SRC "DubToCMake.d" PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH PATH_SUFFIXES "UseDub") execute_process(COMMAND ${CMAKE_D_COMPILER} ${DUB_PACKAGE_TO_CMAKE_D_SRC} WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp) unset(DUB_PACKAGE_TO_CMAKE_D_SRC CACHE) -endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake OR 1) +endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake) include(ExternalProject) @@ -61,8 +64,15 @@ function(DubProject_Add name) include(${DUB_DIRECTORY}/${name}.cmake) ExternalProject_Add(${name} - DOWNLOAD_DIR ${DUB_DIRECTORY}/${name} + DOWNLOAD_DIR ${DUB_DIRECTORY}/archive/${name} + SOURCE_DIR ${DUB_DIRECTORY}/source/${name} URL ${DUB_PACKAGE_URL} PATCH_COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubToCMake -p package.json - CMAKE_CACHE_ARGS -DCMAKE_MODULE_PATH:PATH=${CMAKE_MODULE_PATH}) + INSTALL_DIR ${DUB_DIRECTORY}/export + CMAKE_CACHE_ARGS + -DCMAKE_MODULE_PATH:PATH=${CMAKE_MODULE_PATH} + -DCMAKE_INSTALL_PREFIX:PATH= + -DDUB_DIRECTORY:PATH=${DUB_DIRECTORY}) + + include_directories(${DUB_DIRECTORY}/source/${name}/source ${DUB_DIRECTORY}/source/${name}/src) endfunction() diff --git a/cmake-d/UseDub/DubToCMake.d b/cmake-d/UseDub/DubToCMake.d index a5b3fd2..d232f08 100644 --- a/cmake-d/UseDub/DubToCMake.d +++ b/cmake-d/UseDub/DubToCMake.d @@ -36,6 +36,8 @@ file(GLOB_RECURSE SRC_FILES source/*.d src/*.d) if(APP_MAIN_FILE) list(REMOVE_ITEM SRC_FILES ${APP_MAIN_FILE}) endif(APP_MAIN_FILE) + +include_directories(source src) >".format(root["name"].str); switch ("targetType" in root.object ? root["targetType"].str : "autodetect") @@ -78,6 +80,13 @@ add_library(%s SHARED ${SRC_FILES}) break; } + cmake ~= q"< +install(TARGETS %s + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) +>".format(target); + if ("dependencies" in root.object) { cmake ~= "\ninclude(UseDub)\n";