diff --git a/.codecov.yml b/.codecov.yml
index e2ed4ad..b012da1 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -1,14 +1,34 @@
# Documentation: https://docs.codecov.io/docs/codecov-yaml
+# Validate with: `curl --data-binary @.codecov.yml https://codecov.io/validate`
+
+codecov:
+ notify:
+ # We don't want to wait for the CodeCov report
+ # See https://github.com/codecov/support/issues/312
+ require_ci_to_pass: false
+ after_n_builds: 1 # send notifications after the first upload
+ wait_for_ci: false
+
+ bot: dlang-bot
+
+ # At Travis, the PR is merged into `master` before the testsuite is run.
+ # This allows CodeCov to adjust the resulting coverage diff, s.t. it matches
+ # with the GitHub diff.
+ # https://github.com/codecov/support/issues/363
+ # https://docs.codecov.io/v4.3.6/docs/comparing-commits
+ allow_coverage_offsets: true
coverage:
precision: 3
round: down
range: "80...100"
+ # Learn more at https://docs.codecov.io/docs/commit-status
status:
- # Learn more at https://docs.codecov.io/docs/commit-status
- project: true
- patch: true
- changes: true
+ project: off
+ changes: off
+ patch:
+ default:
+ threshold: 5
comment: false
diff --git a/.gitignore b/.gitignore
index 75e23c8..275a4b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
*.o
*.obj
+*~
.dub
.directory
@@ -13,6 +14,8 @@
/bin/__test__library-nonet__
/bin/__test__library__
/bin/dub-test-library
+/bin/libdub.a
+/bin/dub-*
# Ignore files or directories created by the test suite.
/test/custom-source-main-bug487/custom-source-main-bug487
@@ -26,6 +29,13 @@
/test/expected-issue616-output
/test/describe-project/dummy.dat
/test/describe-project/dummy-dep1.dat
+/test/*/main/main
+/test/*/*test-library
+/test/*/*test-application
+/test/*/exec-simple
# Ignore coverage files
cov/
+
+# Ignore auto-generated docs
+/docs
diff --git a/.travis.yml b/.travis.yml
index 86f505a..8ff60e6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,16 +2,25 @@
dist: trusty
sudo: false
-matrix:
+addons:
+ apt:
+ packages:
+ - libevent-dev
+
+script:
+ - ./travis-ci.sh
+
+jobs:
+ allow_failures:
+ - d: gdc
include:
- - d: dmd-nightly
+ - stage: test
+ d: dmd-2.078.0
+ env: [FRONTEND=2.078]
+ - d: dmd-2.077.1
+ env: [FRONTEND=2.077, COVERAGE=true]
+ - d: dmd-2.076.1
env: [FRONTEND=2.076]
- - d: dmd-beta
- env: [FRONTEND=2.076]
- - d: dmd
- env:
- - [FRONTEND=2.075]
- - [COVERAGE=true]
- d: dmd-2.075.1
env: [FRONTEND=2.075]
- d: dmd-2.074.1
@@ -28,12 +37,14 @@
env: [FRONTEND=2.069]
- d: dmd-2.068.2
env: [FRONTEND=2.068]
- - d: dmd-2.067.1
- env: [FRONTEND=2.067]
- - d: ldc-beta
- env: [FRONTEND=2.073]
- - d: ldc
- env: [FRONTEND=2.073]
+ - d: ldc-1.7.0
+ env: [FRONTEND=2.077]
+ - d: ldc-1.6.0
+ env: [FRONTEND=2.076]
+ - d: ldc-1.5.0
+ env: [FRONTEND=2.075]
+ - d: ldc-1.4.0
+ env: [FRONTEND=2.074]
- d: ldc-1.3.0
env: [FRONTEND=2.073]
- d: ldc-1.2.0
@@ -42,21 +53,61 @@
env: [FRONTEND=2.071]
- d: ldc-1.0.0
env: [FRONTEND=2.070]
- - d: ldc-0.17.2
- env: [FRONTEND=2.068]
- d: gdc
env: [FRONTEND=2.068]
- d: gdc-4.8.5
env: [FRONTEND=2.068]
-
- allow_failures:
- - d: gdc
-
-addons:
- apt:
- packages:
- - libevent-dev
-
-script:
- - deactivate # deactivate host compiler
- - ./travis-ci.sh
+ - stage: deploy
+ d: dmd
+ os: osx
+ script: echo "Deploying to GitHub releases ..." && ./release.sh
+ deploy:
+ - provider: releases
+ file_glob: true
+ file: bin/dub-*.tar.gz
+ skip_cleanup: true
+ api_key: $GH_REPO_TOKEN
+ on:
+ tags: true
+ - d: dmd
+ script: echo "Deploying to GitHub releases ..." && ./release.sh
+ env: [ARCH=32]
+ addons:
+ apt:
+ packages:
+ - g++-multilib
+ - libcurl4-openssl-dev:i386
+ deploy:
+ - provider: releases
+ file_glob: true
+ file: bin/dub-*.tar.gz
+ skip_cleanup: true
+ api_key: $GH_REPO_TOKEN
+ on:
+ tags: true
+ - d: dmd
+ script: echo "Deploying to GitHub releases ..." && ./release.sh
+ deploy:
+ - provider: releases
+ file_glob: true
+ file: bin/dub-*.tar.gz
+ skip_cleanup: true
+ api_key: $GH_REPO_TOKEN
+ on:
+ tags: true
+ - stage: update-latest
+ script: echo "Deploying to GitHub pages ..." && mkdir -p docs && git describe --abbrev=0 --tags > docs/LATEST
+ deploy:
+ - provider: pages
+ skip_cleanup: true
+ local_dir: docs
+ github_token: $GH_REPO_TOKEN
+ on:
+ tags: true
+stages:
+ - name: test
+ if: type = pull_request or (type = push and branch = master)
+ - name: deploy
+ if: type = push and tag =~ ^v
+ - name: update-latest
+ if: type = push and tag =~ ^v
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
new file mode 100644
index 0000000..6c520e4
--- /dev/null
+++ b/ARCHITECTURE.md
@@ -0,0 +1,26 @@
+## Architecture
+
+
+
+## Terminology
+
+
+ - Package
+ - A locally available version of a dub package, consisting of sources, binaries, and described by it's dub.sdl/json file.
+ - PackageSupplier
+ - A source to search and fetch package versions (zip bundles) from.
+ - PackageManager
+ - Responsible to manage packages (fetched or add-local packages), and overrides.
+ - PackageRecipe
+ - Abstract description of package sources, targets, configurations, and build settings.
+ - Generator
+ - Responsible for generating a build recipe (e.g. CMakeLists.txt, VS .sln) for a package, config, and build type. Direct builds (dmd, rdmd) are also implemented as generators.
+
- PackageDependency
+ - Unresolved, abstract specification of a dependency, e.g.
dependency "vibe-d" version="~>0.8.1"
.
+ - DependencyResolver
+ - Algorithm to resolve package dependencies to specific package versions (dub.selections.json), searching available package versions in package suppliers.
+ - Target
+ - A build output like a static library or executable.
+ - BuildCache
+ - Caches targets for a specific build id.
+
diff --git a/appveyor.yml b/appveyor.yml
index 5a05c13..143d03a 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -26,13 +26,10 @@
DVersion: stable
arch: x86
- DC: ldc
- DVersion: beta
- arch: x64
- - DC: ldc
DVersion: stable
arch: x64
- DC: ldc
- DVersion: 1.2.0
+ DVersion: 1.7.0
arch: x64
skip_tags: false
@@ -62,17 +59,18 @@
- ps: function ResolveLatestLDC
{
$version = $env:DVersion;
+ $arch = $env:arch;
if($version -eq "stable") {
$latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST").toString().replace("`n","").replace("`r","");
- $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-win64-msvc.zip";
+ $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z";
}elseif($version -eq "beta") {
$latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST_BETA").toString().replace("`n","").replace("`r","");
- $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-win64-msvc.zip";
+ $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z";
} else {
$latest = $version;
- $url = "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-win64-msvc.zip";
+ $url = "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-windows-$($arch).7z";
}
- $env:PATH += ";C:\ldc2-$($latest)-win64-msvc\bin";
+ $env:PATH += ";C:\ldc2-$($latest)-windows-$($arch)\bin";
$env:DC = "ldc2";
return $url;
}
diff --git a/architecture.graphmlz b/architecture.graphmlz
new file mode 100644
index 0000000..73716a1
--- /dev/null
+++ b/architecture.graphmlz
Binary files differ
diff --git a/architecture.png b/architecture.png
new file mode 100644
index 0000000..a66bff5
--- /dev/null
+++ b/architecture.png
Binary files differ
diff --git a/build-gdc.sh b/build-gdc.sh
index 1924b08..203f8c9 100755
--- a/build-gdc.sh
+++ b/build-gdc.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
set -e
if [ "$GDC" = "" ]; then
diff --git a/dub.selections.json b/dub.selections.json
index dd9a304..52e7c92 100644
--- a/dub.selections.json
+++ b/dub.selections.json
@@ -4,14 +4,15 @@
"botan": "1.12.9",
"botan-math": "1.0.3",
"diet-ng": "1.4.3",
- "eventcore": "0.8.26",
+ "eventcore": "0.8.27",
"libasync": "0.8.3",
"libev": "5.0.0+4.04",
"libevent": "2.0.2+2.0.16",
"memutils": "0.4.9",
"openssl": "1.1.6+1.0.1g",
+ "stdx-allocator": "2.77.0",
"taggedalgebraic": "0.10.8",
- "vibe-core": "1.3.0",
- "vibe-d": "0.8.3-alpha.1"
+ "vibe-core": "1.4.0-alpha.1",
+ "vibe-d": "0.8.3-alpha.3"
}
}
diff --git a/release.sh b/release.sh
new file mode 100755
index 0000000..e889a30
--- /dev/null
+++ b/release.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+set -v -e -o pipefail
+
+VERSION=$(git describe --abbrev=0 --tags)
+ARCH="${ARCH:-64}"
+
+unameOut="$(uname -s)"
+case "$unameOut" in
+ Linux*) OS=linux; ;;
+ Darwin*) OS=osx; ;;
+ *) echo "Unknown OS: $unameOut"; exit 1
+esac
+
+case "$ARCH" in
+ 64) ARCH_SUFFIX="x86_64";;
+ 32) ARCH_SUFFIX="x86";;
+ *) echo "Unknown ARCH: $ARCH"; exit 1
+esac
+
+archiveName="dub-$VERSION-$OS-$ARCH_SUFFIX.tar.gz"
+
+echo "Building $archiveName"
+DFLAGS="-release -m$ARCH" DMD="$(command -v $DMD)" ./build.sh
+tar cvfz "bin/$archiveName" -C bin dub
diff --git a/scripts/man/.gitignore b/scripts/man/.gitignore
new file mode 100644
index 0000000..2c2a370
--- /dev/null
+++ b/scripts/man/.gitignore
@@ -0,0 +1,2 @@
+*.1
+/gen_man
diff --git a/scripts/man/README.md b/scripts/man/README.md
new file mode 100644
index 0000000..1b7484a
--- /dev/null
+++ b/scripts/man/README.md
@@ -0,0 +1,13 @@
+1) Build
+--------
+
+```shell
+./gen_man.d
+```
+
+2) Preview
+----------
+
+```shell
+man -l dub.1
+```
diff --git a/scripts/man/gen_man.d b/scripts/man/gen_man.d
new file mode 100755
index 0000000..1524ea1
--- /dev/null
+++ b/scripts/man/gen_man.d
@@ -0,0 +1,187 @@
+#!/usr/bin/env dub
+/+dub.sdl:
+dependency "dub" path="../.."
++/
+
+import std.algorithm, std.conv, std.format, std.path, std.range, std.stdio;
+import dub.commandline;
+
+string italic(string w)
+{
+ return `\fI` ~ w ~ `\fR`;
+}
+
+string bold(string w)
+{
+ return `\fB` ~ w ~ `\fR`;
+}
+
+string header(string heading)
+{
+ return ".SH " ~ heading;
+}
+
+string br(string s)
+{
+ return ".BR " ~ s;
+}
+
+struct Config
+{
+ import std.datetime;
+ SysTime date;
+
+ static Config init(){
+ import std.process : environment;
+ Config config;
+ config.date = Clock.currTime;
+ auto diffable = environment.get("DIFFABLE", "0");
+ if (diffable == "1")
+ config.date = SysTime(DateTime(2018, 01, 01));
+
+ config.cwd = __FILE_FULL_PATH__.dirName;
+ return config;
+ }
+ string cwd;
+}
+
+void writeHeader(ref File manFile, string manName, const Config config)
+{
+ static immutable manHeader =
+`.TH %s 1 "%s" "The D Language Foundation" "The D Language Foundation"
+.SH NAME`;
+ manFile.writefln(manHeader, manName, config.date.toISOExtString.take(10));
+}
+
+void writeFooter(ref File manFile, string seeAlso, const Config config)
+{
+ static immutable manFooter =
+`.SH FILES
+\fIdub\&.sdl\fR, \fIdub\&.json\fR
+.SH AUTHOR
+Copyright (c) 1999-%s by The D Language Foundation
+.SH "ONLINE DOCUMENTATION"
+.UR http://code.dlang.org/docs/commandline
+.UE http://code.dlang.org/docs/commandline
+.SH "SEE ALSO"
+%s`;
+ manFile.writefln(manFooter, config.date.year, seeAlso);
+}
+
+void writeMainManFile(CommandArgs args, CommandGroup[] commands,
+ string fileName, const Config config)
+{
+ auto manFile = File(config.cwd.buildPath(fileName), "w");
+ manFile.writeHeader("DUB", config);
+ auto seeAlso = ["dmd(1)".br, "rdmd(1)"].joiner("\n").to!string;
+ scope(exit) manFile.writeFooter(seeAlso, config);
+
+ alias writeln = (m) => manFile.writeln(m);
+ writeln(`dub \- Package and build management system for D`);
+ writeln("SYNOPSIS".header);
+ writeln(`.B dub
+[\-\-version]
+[\fICOMMAND\fR]
+[\fIOPTIONS\&.\&.\&.\fR]
+[\-\- [\fIAPPLICATION ARGUMENTS\&.\&.\&.\fR]]`);
+
+ writeln("DESCRIPTION".header);
+ writeln(`Manages the DUB project in the current directory\&. DUB can serve as a build
+system and a package manager, automatically keeping track of project's
+dependencies \- both downloading them and linking them into the application.`);
+
+ writeln(".SH COMMANDS");
+ foreach (grp; commands) {
+ foreach (cmd; grp.commands) {
+ writeln(".TP");
+ writeln(cmd.name.bold);
+ writeln(cmd.helpText.joiner("\n"));
+ }
+ }
+
+ writeln("COMMON OPTIONS".header);
+ args.writeArgs(manFile);
+}
+
+string highlightArguments(string args)
+{
+ import std.regex : regex, replaceAll;
+ static immutable re = regex("<([^>]*)>");
+ static immutable reReplacement = "<%s>".format(`$1`.italic);
+ return args.replaceAll(re, reReplacement);
+}
+
+void writeArgs(CommandArgs args, ref File manFile)
+{
+ alias write = (m) => manFile.write(m);
+ foreach (arg; args.recognizedArgs)
+ {
+ auto names = arg.names.split("|");
+ assert(names.length == 1 || names.length == 2);
+ string sarg = names[0].length == 1 ? names[0] : null;
+ string larg = names[0].length > 1 ? names[0] : names.length > 1 ? names[1] : null;
+ write(".IP ");
+ if (sarg !is null) {
+ write("-%s".format(sarg));
+ if (larg !is null)
+ write(", ");
+ }
+ if (larg !is null) {
+ write("--%s".format(larg));
+ if (!arg.defaultValue.peek!bool)
+ write("=VALUE");
+ }
+ manFile.writeln;
+ manFile.writeln(arg.helpText.join("\n"));
+ }
+}
+
+void writeManFile(Command command, const Config config)
+{
+ import std.uni : toUpper;
+
+ auto args = new CommandArgs(null);
+ command.prepare(args);
+ string fileName = format("dub-%s.1", command.name);
+ auto manFile = File(config.cwd.buildPath(fileName), "w");
+ auto manName = format("DUB-%s", command.name).toUpper;
+ manFile.writeHeader(manName, config);
+ static immutable seeAlso = ["dmd(1)".br, "dub(1)"].joiner("\n").to!string;
+ scope(exit) manFile.writeFooter(seeAlso, config);
+
+ alias writeln = (m) => manFile.writeln(m);
+ writeln(`dub \- Package and build management system for D`);
+
+ writeln("SYNOPSIS".header);
+ writeln("dub %s".format(command.name).bold);
+ writeln(command.argumentsPattern.highlightArguments);
+ writeln(`OPTIONS\&.\&.\&.`.italic);
+ if (command.acceptsAppArgs)
+ {
+ writeln("[-- <%s>]".format("application arguments...".italic));
+ }
+
+ writeln("DESCRIPTION".header);
+ writeln(command.helpText.joiner("\n\n"));
+ writeln("OPTIONS".header);
+ args.writeArgs(manFile);
+}
+
+void main()
+{
+ Config config = Config.init;
+ auto commands = getCommands();
+
+ // main dub.1
+ {
+ CommonOptions options;
+ auto args = new CommandArgs(null);
+ options.prepare(args);
+ args.writeMainManFile(commands, "dub.1", config);
+ }
+
+ // options for each specific command
+ foreach (cmd; commands.map!(a => a.commands).joiner) {
+ cmd.writeManFile(config);
+ }
+}
diff --git a/scripts/rpm-package/make_installer.sh b/scripts/rpm-package/make_installer.sh
index eb2ab86..097e9c4 100755
--- a/scripts/rpm-package/make_installer.sh
+++ b/scripts/rpm-package/make_installer.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
set -e
cd ../../
DUB_PATH=`pwd`
diff --git a/source/dub/commandline.d b/source/dub/commandline.d
index 9c6702c..91b0b32 100644
--- a/source/dub/commandline.d
+++ b/source/dub/commandline.d
@@ -134,6 +134,7 @@
else if (options.verbose) loglevel = LogLevel.diagnostic;
else if (options.vquiet) loglevel = LogLevel.none;
else if (options.quiet) loglevel = LogLevel.warn;
+ else if (options.verror) loglevel = LogLevel.error;
setLogLevel(loglevel);
} catch (Throwable e) {
logError("Error processing arguments: %s", e.msg);
@@ -267,7 +268,7 @@
/** Contains and parses options common to all commands.
*/
struct CommonOptions {
- bool verbose, vverbose, quiet, vquiet;
+ bool verbose, vverbose, quiet, vquiet, verror;
bool help, annotate, bare;
string[] registry_urls;
string root_path;
@@ -292,6 +293,7 @@
args.getopt("v|verbose", &verbose, ["Print diagnostic output"]);
args.getopt("vverbose", &vverbose, ["Print debug output"]);
args.getopt("q|quiet", &quiet, ["Only print warnings and errors"]);
+ args.getopt("verror", &verror, ["Only print errors"]);
args.getopt("vquiet", &vquiet, ["Print no messages"]);
args.getopt("cache", &placementLocation, ["Puts any fetched packages in the specified location [local|system|user]."]);
}
@@ -631,6 +633,7 @@
protected void setupPackage(Dub dub, string package_name, string default_build_type = "debug")
{
if (!m_compilerName.length) m_compilerName = dub.defaultCompiler;
+ if (!m_arch.length) m_arch = dub.defaultArchitecture;
m_compiler = getCompiler(m_compilerName);
m_buildPlatform = m_compiler.determinePlatform(m_buildSettings, m_compilerName, m_arch);
m_buildSettings.addDebugVersions(m_debugVersions);
diff --git a/source/dub/compilers/buildsettings.d b/source/dub/compilers/buildsettings.d
index 9f54140..28b98be 100644
--- a/source/dub/compilers/buildsettings.d
+++ b/source/dub/compilers/buildsettings.d
@@ -10,7 +10,7 @@
import dub.internal.vibecompat.inet.path;
import std.array : array;
-import std.algorithm : filter;
+import std.algorithm : filter, any;
import std.path : globMatch;
import std.typecons : BitFlags;
@@ -108,23 +108,17 @@
void removeOptions(in BuildOptions value) { this.options &= ~value; }
private:
- // Adds vals to arr without adding duplicates.
- static void add(ref string[] arr, in string[] vals, bool no_duplicates = true)
+ static auto filterDuplicates(T)(ref string[] arr, in T vals, bool noDuplicates = true)
{
- if (!no_duplicates) {
- arr ~= vals;
- return;
- }
+ return noDuplicates
+ ? vals.filter!(filtered => !arr.any!(item => item == filtered)).array
+ : vals;
+ }
- foreach (v; vals) {
- bool found = false;
- foreach (i; 0 .. arr.length)
- if (arr[i] == v) {
- found = true;
- break;
- }
- if (!found) arr ~= v;
- }
+ // Append vals to arr without adding duplicates.
+ static void add(ref string[] arr, in string[] vals, bool noDuplicates = true)
+ {
+ arr ~= filterDuplicates(arr, vals, noDuplicates);
}
unittest
@@ -136,22 +130,10 @@
assert(ary == ["-dip1000", "-vgc", "-dip1001", "-vgc"]);
}
- static void prepend(ref string[] arr, in string[] vals, bool no_duplicates = true)
+ // Prepend arr by vals without adding duplicates.
+ static void prepend(ref string[] arr, in string[] vals, bool noDuplicates = true)
{
- if (!no_duplicates) {
- arr = vals ~ arr;
- return;
- }
-
- foreach_reverse (v; vals) {
- bool found = false;
- foreach (i; 0 .. arr.length)
- if (arr[i] == v) {
- found = true;
- break;
- }
- if (!found) arr = v ~ arr;
- }
+ arr = filterDuplicates(arr, vals, noDuplicates) ~ arr;
}
unittest
@@ -186,16 +168,27 @@
assert(ary == ["path/foo.txt", "path2/foo2.txt"]);
}
- static void removePaths(ref string[] arr, in string[] vals)
+ static bool pathMatch(string path, string pattern)
+ {
+ import std.functional : memoize;
+
+ alias nativePath = memoize!((string stringPath) => NativePath(stringPath));
+
+ return nativePath(path) == nativePath(pattern) || globMatch(path, pattern);
+ }
+
+ static void removeValuesFromArray(alias Match)(ref string[] arr, in string[] vals)
{
bool matches(string s)
{
- foreach (p; vals)
- if (NativePath(s) == NativePath(p) || globMatch(s, p))
- return true;
- return false;
+ return vals.any!(item => Match(s, item));
}
- arr = arr.filter!(s => !matches(s))().array();
+ arr = arr.filter!(s => !matches(s)).array;
+ }
+
+ static void removePaths(ref string[] arr, in string[] vals)
+ {
+ removeValuesFromArray!(pathMatch)(arr, vals);
}
unittest
@@ -211,14 +204,7 @@
static void remove(ref string[] arr, in string[] vals)
{
- bool matches(string s)
- {
- foreach (p; vals)
- if (s == p)
- return true;
- return false;
- }
- arr = arr.filter!(s => !matches(s))().array();
+ removeValuesFromArray!((a, b) => a == b)(arr, vals);
}
unittest
diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d
index f70556d..e5864b4 100644
--- a/source/dub/compilers/dmd.d
+++ b/source/dub/compilers/dmd.d
@@ -28,7 +28,7 @@
tuple(BuildOption.releaseMode, ["-release"]),
tuple(BuildOption.coverage, ["-cov"]),
tuple(BuildOption.debugInfo, ["-g"]),
- tuple(BuildOption.debugInfoC, ["-gc"]),
+ tuple(BuildOption.debugInfoC, ["-g"]),
tuple(BuildOption.alwaysStackFrame, ["-gs"]),
tuple(BuildOption.stackStomping, ["-gx"]),
tuple(BuildOption.inline, ["-inline"]),
diff --git a/source/dub/dependencyresolver.d b/source/dub/dependencyresolver.d
index f5e9dcb..1662cd3 100644
--- a/source/dub/dependencyresolver.d
+++ b/source/dub/dependencyresolver.d
@@ -11,7 +11,7 @@
import dub.internal.vibecompat.core.log;
import std.algorithm : all, canFind, filter, map, sort;
-import std.array : appender, array;
+import std.array : appender, array, join;
import std.conv : to;
import std.exception : enforce;
import std.typecons : Nullable;
@@ -54,6 +54,25 @@
}
}
+ private static struct PackageConfigs
+ {
+ static struct Depender
+ {
+ TreeNode origin;
+ TreeNodes dependency;
+ }
+
+ // all possible configurations to test for this package
+ CONFIG[] allConfigs;
+
+ // determines whether this package has any dependencies, may be
+ // different from allConfigs.length > 0 after certain configurations
+ // have been filtered out
+ bool anyConfig;
+
+ Depender[] origins;
+ }
+
CONFIG[string] resolve(TreeNode root, bool throw_on_failure = true)
{
auto root_base_pack = basePackage(root.pack);
@@ -61,8 +80,7 @@
// find all possible configurations of each possible dependency
size_t[string] package_indices;
string[size_t] package_names;
- CONFIG[][] all_configs;
- bool[] any_config;
+ PackageConfigs[] configs;
bool[string] maybe_optional_deps;
bool[TreeNode] visited;
@@ -73,38 +91,40 @@
foreach (ch; getChildren(parent)) {
auto basepack = basePackage(ch.pack);
- auto pidx = all_configs.length;
+ auto pidx = configs.length;
if (ch.depType != DependencyType.required) maybe_optional_deps[ch.pack] = true;
- CONFIG[] configs;
+ PackageConfigs config;
if (auto pi = basepack in package_indices) {
pidx = *pi;
- configs = all_configs[*pi];
+ config = configs[*pi];
} else {
- if (basepack == root_base_pack) configs = [root.config];
- else configs = getAllConfigs(basepack);
- all_configs ~= configs;
+ if (basepack == root_base_pack) config.allConfigs = [root.config];
+ else config.allConfigs = getAllConfigs(basepack);
+ configs ~= config;
package_indices[basepack] = pidx;
package_names[pidx] = basepack;
}
foreach (c; getSpecificConfigs(basepack, ch))
- if (!configs.canFind(c))
- configs = c ~ configs;
+ if (!config.allConfigs.canFind(c))
+ config.allConfigs = c ~ config.allConfigs;
- if (any_config.length <= pidx) any_config.length = pidx+1;
- if (configs.length > 0)
- any_config[pidx] = true;
+ if (config.allConfigs.length > 0)
+ config.anyConfig = true;
+
+ // store package depending on this for better error messages
+ config.origins ~= PackageConfigs.Depender(parent, ch);
// eliminate configurations from which we know that they can't satisfy
// the uniquely defined root dependencies (==version or ~branch style dependencies)
- if (parent_unique) configs = configs.filter!(c => matches(ch.configs, c)).array;
+ if (parent_unique) config.allConfigs = config.allConfigs.filter!(c => matches(ch.configs, c)).array;
- all_configs[pidx] = configs;
+ configs[pidx] = config;
- foreach (v; configs)
- findConfigsRec(TreeNode(ch.pack, v), parent_unique && configs.length == 1);
+ foreach (v; config.allConfigs)
+ findConfigsRec(TreeNode(ch.pack, v), parent_unique && config.allConfigs.length == 1);
}
}
findConfigsRec(root, true);
@@ -113,14 +133,14 @@
// this is used to properly support optional dependencies (when
// getChildren() returns no configurations for an optional dependency,
// but getAllConfigs() has already provided an existing list of configs)
- foreach (i, ref cfgs; all_configs)
- if (cfgs.length == 0 || package_names[i] in maybe_optional_deps)
- cfgs = cfgs ~ CONFIG.invalid;
+ foreach (i, ref cfgs; configs)
+ if (cfgs.allConfigs.length == 0 || package_names[i] in maybe_optional_deps)
+ cfgs.allConfigs = cfgs.allConfigs ~ CONFIG.invalid;
logDebug("Configurations used for dependency resolution:");
- foreach (n, i; package_indices) logDebug(" %s (%s%s): %s", n, i, n in maybe_optional_deps ? ", maybe optional" : ", required", all_configs[i]);
+ foreach (n, i; package_indices) logDebug(" %s (%s%s): %s", n, i, n in maybe_optional_deps ? ", maybe optional" : ", required", configs[i]);
- auto config_indices = new size_t[all_configs.length];
+ auto config_indices = new size_t[configs.length];
config_indices[] = 0;
visited = null;
@@ -142,7 +162,9 @@
// get the current config/version of the current dependency
sizediff_t childidx = package_indices[basepack];
- if (all_configs[childidx].length == 1 && all_configs[childidx][0] == CONFIG.invalid) {
+ auto child = configs[childidx];
+
+ if (child.allConfigs.length == 1 && child.allConfigs[0] == CONFIG.invalid) {
// ignore invalid optional dependencies
if (ch.depType != DependencyType.required)
continue;
@@ -154,8 +176,10 @@
logError("Dependency \"%s\" of %s contains upper case letters, but must be lower case.", ch.pack, parent.pack);
if (getAllConfigs(lp).length) logError("Did you mean \"%s\"?", lp);
}
- if (any_config[childidx])
- throw new Exception(format("Root package %s reference %s %s cannot be satisfied.", parent.pack, ch.pack, ch.configs));
+ if (child.anyConfig)
+ throw new Exception(format("Root package %s reference %s %s cannot be satisfied.\nPackages causing the conflict:\n\t%s",
+ parent.pack, ch.pack, ch.configs,
+ child.origins.map!(a => a.origin.pack ~ " depends on " ~ a.dependency.configs.to!string).join("\n\t")));
else
throw new Exception(format("Root package %s references unknown package %s", parent.pack, ch.pack));
}
@@ -166,7 +190,7 @@
maxcpi = parentidx;
}
} else {
- auto config = all_configs[childidx][config_indices[childidx]];
+ auto config = child.allConfigs[config_indices[childidx]];
auto chnode = TreeNode(ch.pack, config);
if (config == CONFIG.invalid || !matches(ch.configs, config)) {
@@ -221,10 +245,10 @@
// print out current iteration state
logDebug("Interation (ci=%s) %s", conflict_index, {
import std.array : join;
- auto cs = new string[all_configs.length];
+ auto cs = new string[configs.length];
foreach (p, i; package_indices) {
- if (all_configs[i].length)
- cs[i] = p~" "~all_configs[i][config_indices[i]].to!string~(i >= 0 && i >= conflict_index ? " (C)" : "");
+ if (configs[i].allConfigs.length)
+ cs[i] = p~" "~configs[i].allConfigs[config_indices[i]].to!string~(i >= 0 && i >= conflict_index ? " (C)" : "");
else cs[i] = p ~ " [no config]";
}
return cs.join(", ");
@@ -233,8 +257,8 @@
if (conflict_index < 0) {
CONFIG[string] ret;
foreach (p, i; package_indices)
- if (all_configs[i].length) {
- auto cfg = all_configs[i][config_indices[i]];
+ if (configs[i].allConfigs.length) {
+ auto cfg = configs[i].allConfigs[config_indices[i]];
if (cfg != CONFIG.invalid) ret[p] = cfg;
}
logDebug("Resolved dependencies before optional-purge: %s", ret.byKey.map!(k => k~" "~ret[k].to!string));
@@ -246,7 +270,7 @@
// find the next combination of configurations
foreach_reverse (pi, ref i; config_indices) {
if (pi > conflict_index) i = 0;
- else if (++i >= all_configs[pi].length) i = 0;
+ else if (++i >= configs[pi].allConfigs.length) i = 0;
else break;
}
if (config_indices.all!"a==0") {
diff --git a/source/dub/dub.d b/source/dub/dub.d
index 5b36338..47bf48b 100644
--- a/source/dub/dub.d
+++ b/source/dub/dub.d
@@ -106,6 +106,7 @@
Project m_project;
NativePath m_overrideSearchPath;
string m_defaultCompiler;
+ string m_defaultArchitecture;
}
/** The default placement location of fetched packages.
@@ -159,7 +160,7 @@
ps ~= defaultPackageSuppliers();
m_packageSuppliers = ps;
- m_packageManager = new PackageManager(m_dirs.userSettings, m_dirs.systemSettings);
+ m_packageManager = new PackageManager(m_dirs.localRepository, m_dirs.systemSettings);
updatePackageSearchPath();
}
@@ -198,12 +199,18 @@
import std.file : tempDir;
version(Windows) {
m_dirs.systemSettings = NativePath(environment.get("ProgramData")) ~ "dub/";
- m_dirs.userSettings = NativePath(environment.get("APPDATA")) ~ "dub/";
+ immutable appDataDir = environment.get("APPDATA");
+ m_dirs.userSettings = NativePath(appDataDir) ~ "dub/";
+ m_dirs.localRepository = NativePath(environment.get("LOCALAPPDATA", appDataDir)) ~ "dub";
+
+ migrateRepositoryFromRoaming(m_dirs.userSettings ~"\\packages", m_dirs.localRepository ~ "\\packages");
+
} else version(Posix){
m_dirs.systemSettings = NativePath("/var/lib/dub/");
m_dirs.userSettings = NativePath(environment.get("HOME")) ~ ".dub/";
if (!m_dirs.userSettings.absolute)
m_dirs.userSettings = NativePath(getcwd()) ~ m_dirs.userSettings;
+ m_dirs.localRepository = m_dirs.userSettings;
}
m_dirs.temp = NativePath(tempDir);
@@ -213,8 +220,28 @@
m_config = new DubConfig(jsonFromFile(m_dirs.userSettings ~ "settings.json", true), m_config);
determineDefaultCompiler();
+
+ m_defaultArchitecture = m_config.defaultArchitecture;
}
+ version(Windows)
+ private void migrateRepositoryFromRoaming(NativePath roamingDir, NativePath localDir)
+ {
+ immutable roamingDirPath = roamingDir.toNativeString();
+ if (!existsDirectory(roamingDir)) return;
+
+ immutable localDirPath = localDir.toNativeString();
+ logInfo("Detected a package cache in " ~ roamingDirPath ~ ". This will be migrated to " ~ localDirPath ~ ". Please wait...");
+ if (!existsDirectory(localDir))
+ {
+ mkdirRecurse(localDirPath);
+ }
+
+ runCommand("xcopy /s /e /y " ~ roamingDirPath ~ " " ~ localDirPath ~ " > NUL");
+ rmdirRecurse(roamingDirPath);
+ }
+
+
@property void dryRun(bool v) { m_dryRun = v; }
/** Returns the root path (usually the current working directory).
@@ -250,6 +277,13 @@
*/
@property string defaultCompiler() const { return m_defaultCompiler; }
+ /** Returns the default architecture to use for building D code.
+
+ If set, the "defaultArchitecture" field of the DUB user or system
+ configuration file will be used. Otherwise null will be returned.
+ */
+ @property string defaultArchitecture() const { return m_defaultArchitecture; }
+
/** Loads the package that resides within the configured `rootPath`.
*/
void loadPackage()
@@ -699,7 +733,7 @@
NativePath placement;
final switch (location) {
case PlacementLocation.local: placement = m_rootPath; break;
- case PlacementLocation.user: placement = m_dirs.userSettings ~ "packages/"; break;
+ case PlacementLocation.user: placement = m_dirs.localRepository ~ "packages/"; break;
case PlacementLocation.system: placement = m_dirs.systemSettings ~ "packages/"; break;
}
@@ -1568,6 +1602,7 @@
NativePath temp;
NativePath userSettings;
NativePath systemSettings;
+ NativePath localRepository;
}
private class DubConfig {
@@ -1598,4 +1633,12 @@
if (m_parentConfig) return m_parentConfig.defaultCompiler;
return null;
}
+
+ @property string defaultArchitecture()
+ const {
+ if(auto pv = "defaultArchitecture" in m_data)
+ return (*pv).get!string;
+ if (m_parentConfig) return m_parentConfig.defaultArchitecture;
+ return null;
+ }
}
diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d
index dfb0670..144276d 100644
--- a/source/dub/generators/generator.d
+++ b/source/dub/generators/generator.d
@@ -89,18 +89,20 @@
if (!settings.config.length) settings.config = m_project.getDefaultConfiguration(settings.platform);
- TargetInfo[string] targets;
string[string] configs = m_project.getPackageConfigs(settings.platform, settings.config);
+ TargetInfo[string] targets;
foreach (pack; m_project.getTopologicalPackageList(true, null, configs)) {
- BuildSettings buildsettings;
- buildsettings.processVars(m_project, pack, pack.getBuildSettings(settings.platform, configs[pack.name]), true);
- prepareGeneration(pack, m_project, settings, buildsettings);
+ BuildSettings buildSettings;
+ auto config = configs[pack.name];
+ buildSettings.processVars(m_project, pack, pack.getBuildSettings(settings.platform, config), true);
+ targets[pack.name] = TargetInfo(pack, [pack], config, buildSettings);
+
+ prepareGeneration(pack, m_project, settings, buildSettings);
}
- string[] mainfiles;
- collect(settings, m_project.rootPackage, targets, configs, mainfiles, null);
- downwardsInheritSettings(m_project.rootPackage.name, targets, targets[m_project.rootPackage.name].buildSettings);
+ string[] mainfiles = configurePackages(m_project.rootPackage, targets, settings);
+
addBuildTypeSettings(targets, settings);
foreach (ref t; targets.byValue) enforceBuildRequirements(t.buildSettings);
auto bs = &targets[m_project.rootPackage.name].buildSettings;
@@ -143,144 +145,284 @@
*/
protected void performPostGenerateActions(GeneratorSettings settings, in TargetInfo[string] targets) {}
- private BuildSettings collect(GeneratorSettings settings, Package pack, ref TargetInfo[string] targets, in string[string] configs, ref string[] main_files, string bin_pack)
+ /** Configure `rootPackage` and all of it's dependencies.
+
+ 1. Merge versions, debugVersions, and inheritable build
+ settings from dependents to their dependencies.
+
+ 2. Define version identifiers Have_dependency_xyz for all
+ direct dependencies of all packages.
+
+ 3. Merge versions, debugVersions, and inheritable build settings from
+ dependencies to their dependents, so that importer and importee are ABI
+ compatible. This also transports all Have_dependency_xyz version
+ identifiers to `rootPackage`.
+
+ Note: The upwards inheritance is done at last so that siblings do not
+ influence each other, also see https://github.com/dlang/dub/pull/1128.
+
+ Note: Targets without output are integrated into their
+ dependents and removed from `targets`.
+ */
+ private string[] configurePackages(Package rootPackage, TargetInfo[string] targets, GeneratorSettings genSettings)
{
- import std.algorithm : sort;
+ import std.algorithm : remove, sort;
+ import std.range : repeat;
+
+ // 0. do shallow configuration (not including dependencies) of all packages
+ TargetType determineTargetType(const ref TargetInfo ti)
+ {
+ TargetType tt = ti.buildSettings.targetType;
+ if (ti.pack is rootPackage) {
+ if (tt == TargetType.autodetect || tt == TargetType.library) tt = TargetType.staticLibrary;
+ } else {
+ if (tt == TargetType.autodetect || tt == TargetType.library) tt = genSettings.combined ? TargetType.sourceLibrary : TargetType.staticLibrary;
+ else if (tt == TargetType.dynamicLibrary) {
+ logWarn("Dynamic libraries are not yet supported as dependencies - building as static library.");
+ tt = TargetType.staticLibrary;
+ }
+ }
+ if (tt != TargetType.none && tt != TargetType.sourceLibrary && ti.buildSettings.sourceFiles.empty) {
+ logWarn(`Configuration '%s' of package %s contains no source files. Please add {"targetType": "none"} to its package description to avoid building it.`,
+ ti.config, ti.pack.name);
+ tt = TargetType.none;
+ }
+ return tt;
+ }
+
+ string[] mainSourceFiles;
+ bool[string] hasOutput;
+
+ foreach (ref ti; targets.byValue)
+ {
+ auto bs = &ti.buildSettings;
+ // determine the actual target type
+ bs.targetType = determineTargetType(ti);
+
+ switch (bs.targetType)
+ {
+ case TargetType.none:
+ // ignore any build settings for targetType none (only dependencies will be processed)
+ *bs = BuildSettings.init;
+ bs.targetType = TargetType.none;
+ break;
+
+ case TargetType.executable:
+ break;
+
+ case TargetType.dynamicLibrary:
+ // set -fPIC for dynamic library builds
+ ti.buildSettings.addOptions(BuildOption.pic);
+ goto default;
+
+ default:
+ // remove any mainSourceFile from non-executable builds
+ if (bs.mainSourceFile.length) {
+ bs.sourceFiles = bs.sourceFiles.remove!(f => f == bs.mainSourceFile);
+ mainSourceFiles ~= bs.mainSourceFile;
+ }
+ break;
+ }
+ bool generatesBinary = bs.targetType != TargetType.sourceLibrary && bs.targetType != TargetType.none;
+ hasOutput[ti.pack.name] = generatesBinary || ti.pack is rootPackage;
+ }
+
+ // mark packages as visited (only used during upwards propagation)
+ void[0][Package] visited;
+
+ // collect all dependencies
+ void collectDependencies(Package pack, ref TargetInfo ti, TargetInfo[string] targets, size_t level = 0)
+ {
+ // use `visited` here as pkgs cannot depend on themselves
+ if (pack in visited)
+ return;
+ // transitive dependencies must be visited multiple times, see #1350
+ immutable transitive = !hasOutput[pack.name];
+ if (!transitive)
+ visited[pack] = typeof(visited[pack]).init;
+
+ auto bs = &ti.buildSettings;
+ if (hasOutput[pack.name])
+ logDebug("%sConfiguring target %s (%s %s %s)", ' '.repeat(2 * level), pack.name, bs.targetType, bs.targetPath, bs.targetName);
+ else
+ logDebug("%sConfiguring target without output %s", ' '.repeat(2 * level), pack.name);
+
+ // get specified dependencies, e.g. vibe-d ~0.8.1
+ auto deps = pack.getDependencies(targets[pack.name].config);
+ logDebug("deps: %s -> %(%s, %)", pack.name, deps.byKey);
+ foreach (depname; deps.keys.sort())
+ {
+ auto depspec = deps[depname];
+ // get selected package for that dependency, e.g. vibe-d 0.8.2-beta.2
+ auto deppack = m_project.getDependency(depname, depspec.optional);
+ if (deppack is null) continue; // optional and not selected
+
+ // if dependency has no output
+ if (!hasOutput[depname]) {
+ // add itself
+ ti.packages ~= deppack;
+ // and it's transitive dependencies to current target
+ collectDependencies(deppack, ti, targets, level + 1);
+ continue;
+ }
+ auto depti = &targets[depname];
+ const depbs = &depti.buildSettings;
+ if (depbs.targetType == TargetType.executable)
+ continue;
+ // add to (link) dependencies
+ ti.dependencies ~= depname;
+ ti.linkDependencies ~= depname;
+
+ // recurse
+ collectDependencies(deppack, *depti, targets, level + 1);
+
+ // also recursively add all link dependencies of static libraries
+ // preserve topological sorting of dependencies for correct link order
+ if (depbs.targetType == TargetType.staticLibrary)
+ ti.linkDependencies = ti.linkDependencies.filter!(d => !depti.linkDependencies.canFind(d)).array ~ depti.linkDependencies;
+ }
+ }
+
+ collectDependencies(rootPackage, targets[rootPackage.name], targets);
+ static if (__VERSION__ > 2070)
+ visited.clear();
+ else
+ destroy(visited);
+
+ // 1. downwards inherits versions, debugVersions, and inheritable build settings
+ static void configureDependencies(in ref TargetInfo ti, TargetInfo[string] targets, size_t level = 0)
+ {
+ // do not use `visited` here as dependencies must inherit
+ // configurations from *all* of their parents
+ logDebug("%sConfigure dependencies of %s, deps:%(%s, %)", ' '.repeat(2 * level), ti.pack.name, ti.dependencies);
+ foreach (depname; ti.dependencies)
+ {
+ auto pti = &targets[depname];
+ mergeFromDependent(ti.buildSettings, pti.buildSettings);
+ configureDependencies(*pti, targets, level + 1);
+ }
+ }
+
+ configureDependencies(targets[rootPackage.name], targets);
+
+ // 2. add Have_dependency_xyz for all direct dependencies of a target
+ // (includes incorporated non-target dependencies and their dependencies)
+ foreach (ref ti; targets.byValue)
+ {
+ import std.range : chain;
+ import dub.internal.utils : stripDlangSpecialChars;
+
+ auto bs = &ti.buildSettings;
+ auto pkgnames = ti.packages.map!(p => p.name).chain(ti.dependencies);
+ bs.addVersions(pkgnames.map!(pn => "Have_" ~ stripDlangSpecialChars(pn)).array);
+ }
+
+ // 3. upwards inherit full build configurations (import paths, versions, debugVersions, ...)
+ void configureDependents(ref TargetInfo ti, TargetInfo[string] targets, size_t level = 0)
+ {
+ // use `visited` here as pkgs cannot depend on themselves
+ if (ti.pack in visited)
+ return;
+ visited[ti.pack] = typeof(visited[ti.pack]).init;
+
+ logDiagnostic("%sConfiguring dependent %s, deps:%(%s, %)", ' '.repeat(2 * level), ti.pack.name, ti.dependencies);
+ // embedded non-binary dependencies
+ foreach (deppack; ti.packages[1 .. $])
+ ti.buildSettings.add(targets[deppack.name].buildSettings);
+ // binary dependencies
+ foreach (depname; ti.dependencies)
+ {
+ auto pdepti = &targets[depname];
+ configureDependents(*pdepti, targets, level + 1);
+ mergeFromDependency(pdepti.buildSettings, ti.buildSettings);
+ }
+ }
+
+ configureDependents(targets[rootPackage.name], targets);
+ static if (__VERSION__ > 2070)
+ visited.clear();
+ else
+ destroy(visited);
+
+ // 4. override string import files in dependencies
+ static void overrideStringImports(ref TargetInfo ti, TargetInfo[string] targets, string[] overrides)
+ {
+ // do not use visited here as string imports can be overridden by *any* parent
+ //
+ // special support for overriding string imports in parent packages
+ // this is a candidate for deprecation, once an alternative approach
+ // has been found
+ if (ti.buildSettings.stringImportPaths.length) {
+ // override string import files (used for up to date checking)
+ foreach (ref f; ti.buildSettings.stringImportFiles)
+ {
+ foreach (o; overrides)
+ {
+ NativePath op;
+ if (f != o && NativePath(f).head == (op = NativePath(o)).head) {
+ logDebug("string import %s overridden by %s", f, o);
+ f = o;
+ ti.buildSettings.prependStringImportPaths(op.parentPath.toNativeString);
+ }
+ }
+ }
+ }
+ // add to overrides for recursion
+ overrides ~= ti.buildSettings.stringImportFiles;
+ // override dependencies
+ foreach (depname; ti.dependencies)
+ overrideStringImports(targets[depname], targets, overrides);
+ }
+
+ overrideStringImports(targets[rootPackage.name], targets, null);
+
+ // remove targets without output
+ foreach (name; targets.keys)
+ {
+ if (!hasOutput[name])
+ targets.remove(name);
+ }
+
+ return mainSourceFiles;
+ }
+
+ private static void mergeFromDependent(in ref BuildSettings parent, ref BuildSettings child)
+ {
+ child.addVersions(parent.versions);
+ child.addDebugVersions(parent.debugVersions);
+ child.addOptions(BuildOptions(cast(BuildOptions)parent.options & inheritedBuildOptions));
+ }
+
+ private static void mergeFromDependency(in ref BuildSettings child, ref BuildSettings parent)
+ {
import dub.compilers.utils : isLinkerFile;
- if (auto pt = pack.name in targets) return pt.buildSettings;
-
- // determine the actual target type
- auto shallowbs = pack.getBuildSettings(settings.platform, configs[pack.name]);
- TargetType tt = shallowbs.targetType;
- if (pack is m_project.rootPackage) {
- if (tt == TargetType.autodetect || tt == TargetType.library) tt = TargetType.staticLibrary;
- } else {
- if (tt == TargetType.autodetect || tt == TargetType.library) tt = settings.combined ? TargetType.sourceLibrary : TargetType.staticLibrary;
- else if (tt == TargetType.dynamicLibrary) {
- logWarn("Dynamic libraries are not yet supported as dependencies - building as static library.");
- tt = TargetType.staticLibrary;
- }
+ parent.addDFlags(child.dflags);
+ parent.addVersions(child.versions);
+ parent.addDebugVersions(child.debugVersions);
+ parent.addImportPaths(child.importPaths);
+ parent.addStringImportPaths(child.stringImportPaths);
+ // linking of static libraries is done by parent
+ if (child.targetType == TargetType.staticLibrary) {
+ parent.addLinkerFiles(child.sourceFiles.filter!isLinkerFile.array);
+ parent.addLibs(child.libs);
+ parent.addLFlags(child.lflags);
}
- if (tt != TargetType.none && tt != TargetType.sourceLibrary && shallowbs.sourceFiles.empty) {
- logWarn(`Configuration '%s' of package %s contains no source files. Please add {"targetType": "none"} to its package description to avoid building it.`,
- configs[pack.name], pack.name);
- tt = TargetType.none;
- }
-
- shallowbs.targetType = tt;
- bool generates_binary = tt != TargetType.sourceLibrary && tt != TargetType.none;
- bool is_target = generates_binary || pack is m_project.rootPackage;
-
- if (tt == TargetType.none) {
- // ignore any build settings for targetType none (only dependencies will be processed)
- shallowbs = BuildSettings.init;
- shallowbs.targetType = TargetType.none;
- }
-
- // start to build up the build settings
- BuildSettings buildsettings;
- processVars(buildsettings, m_project, pack, shallowbs, true);
-
- // remove any mainSourceFile from library builds
- if (buildsettings.targetType != TargetType.executable && buildsettings.mainSourceFile.length) {
- buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => f != buildsettings.mainSourceFile)().array;
- main_files ~= buildsettings.mainSourceFile;
- }
-
- // set pic for dynamic library builds.
- if (buildsettings.targetType == TargetType.dynamicLibrary)
- buildsettings.addOptions(BuildOption.pic);
-
- logDiagnostic("Generate target %s (%s %s %s)", pack.name, buildsettings.targetType, buildsettings.targetPath, buildsettings.targetName);
- if (is_target)
- targets[pack.name] = TargetInfo(pack, [pack], configs[pack.name], buildsettings, null);
-
- auto deps = pack.getDependencies(configs[pack.name]);
- foreach (depname; deps.keys.sort()) {
- auto depspec = deps[depname];
- auto dep = m_project.getDependency(depname, depspec.optional);
- if (!dep) continue;
-
- auto depbs = collect(settings, dep, targets, configs, main_files, is_target ? pack.name : bin_pack);
-
- if (depbs.targetType != TargetType.sourceLibrary && depbs.targetType != TargetType.none) {
- // add a reference to the target binary and remove all source files in the dependency build settings
- depbs.sourceFiles = depbs.sourceFiles.filter!(f => f.isLinkerFile()).array;
- depbs.importFiles = null;
- }
-
- buildsettings.add(depbs);
-
- if (depbs.targetType == TargetType.executable)
- continue;
-
- auto pt = (is_target ? pack.name : bin_pack) in targets;
- assert(pt !is null);
- if (auto pdt = depname in targets) {
- pt.dependencies ~= depname;
- pt.linkDependencies ~= depname;
- if (depbs.targetType == TargetType.staticLibrary)
- pt.linkDependencies = pt.linkDependencies.filter!(d => !pdt.linkDependencies.canFind(d)).array ~ pdt.linkDependencies;
- } else pt.packages ~= dep;
- }
-
- if (is_target) targets[pack.name].buildSettings = buildsettings.dup;
-
- return buildsettings;
}
- private string[] downwardsInheritSettings(string target, TargetInfo[string] targets, in BuildSettings root_settings)
- {
- import dub.internal.utils : stripDlangSpecialChars;
-
- auto ti = &targets[target];
- ti.buildSettings.addVersions(root_settings.versions);
- ti.buildSettings.addDebugVersions(root_settings.debugVersions);
- ti.buildSettings.addOptions(BuildOptions(cast(BuildOptions)root_settings.options & inheritedBuildOptions));
-
- // special support for overriding string imports in parent packages
- // this is a candidate for deprecation, once an alternative approach
- // has been found
- if (ti.buildSettings.stringImportPaths.length) {
- // override string import files (used for up to date checking)
- foreach (ref f; ti.buildSettings.stringImportFiles)
- foreach (fi; root_settings.stringImportFiles)
- if (f != fi && NativePath(f).head == NativePath(fi).head) {
- f = fi;
- }
-
- // add the string import paths (used by the compiler to find the overridden files)
- ti.buildSettings.prependStringImportPaths(root_settings.stringImportPaths);
- }
-
- string[] packs = ti.packages.map!(p => p.name).array;
- foreach (d; ti.dependencies)
- packs ~= downwardsInheritSettings(d, targets, root_settings);
-
- logDebug("%s: %s", target, packs);
-
- // Add Have_* versions *after* downwards inheritance, so that dependencies
- // are build independently of the parent packages w.r.t the other parent
- // dependencies. This enables sharing of the same package build for
- // multiple dependees.
- ti.buildSettings.addVersions(packs.map!(pn => "Have_" ~ stripDlangSpecialChars(pn)).array);
-
- return packs;
- }
-
+ // configure targets for build types such as release, or unittest-cov
private void addBuildTypeSettings(TargetInfo[string] targets, GeneratorSettings settings)
{
- foreach (ref t; targets) {
- t.buildSettings.add(settings.buildSettings);
+ foreach (ref ti; targets.byValue) {
+ ti.buildSettings.add(settings.buildSettings);
// add build type settings and convert plain DFLAGS to build options
- m_project.addBuildTypeSettings(t.buildSettings, settings.platform, settings.buildType, t.pack is m_project.rootPackage);
- settings.compiler.extractBuildOptions(t.buildSettings);
+ m_project.addBuildTypeSettings(ti.buildSettings, settings.platform, settings.buildType, ti.pack is m_project.rootPackage);
+ settings.compiler.extractBuildOptions(ti.buildSettings);
- auto tt = t.buildSettings.targetType;
- bool generates_binary = tt != TargetType.sourceLibrary && tt != TargetType.none;
- enforce (generates_binary || t.pack !is m_project.rootPackage || (t.buildSettings.options & BuildOption.syntaxOnly),
+ auto tt = ti.buildSettings.targetType;
+ bool generatesBinary = tt != TargetType.sourceLibrary && tt != TargetType.none;
+ enforce (generatesBinary || ti.pack !is m_project.rootPackage || (ti.buildSettings.options & BuildOption.syntaxOnly),
format("Main package must have a binary target type, not %s. Cannot build.", tt));
}
}
diff --git a/source/dub/generators/visuald.d b/source/dub/generators/visuald.d
index bd1fd95..87c8e51 100644
--- a/source/dub/generators/visuald.d
+++ b/source/dub/generators/visuald.d
@@ -349,6 +349,7 @@
ret.put(" 0\n");
ret.put(" 0\n");
ret.put(" 0\n");
+ ret.put(" 0\n");
ret.put(" 0\n");
ret.put(" 0\n");
ret.put(" 0\n");
diff --git a/source/dub/init.d b/source/dub/init.d
index a1caaf2..23873bc 100644
--- a/source/dub/init.d
+++ b/source/dub/init.d
@@ -69,7 +69,7 @@
foreach (fil; packageInfoFiles)
enforceDoesNotExist(fil.filename);
- auto files = ["source/", "views/", "public/", "dub.json", ".gitignore"];
+ auto files = ["source/", "views/", "public/", "dub.json"];
foreach (fil; files)
enforceDoesNotExist(fil);
@@ -87,7 +87,7 @@
}
writePackageRecipe(root_path ~ ("dub."~format.to!string), p);
- writeGitignore(root_path, p);
+ writeGitignore(root_path, p.name);
}
alias RecipeCallback = void delegate(ref PackageRecipe, ref PackageFormat);
@@ -111,7 +111,7 @@
private void initVibeDPackage(NativePath root_path, ref PackageRecipe p, scope void delegate() pre_write_callback)
{
if ("vibe-d" !in p.buildSettings.dependencies)
- p.buildSettings.dependencies["vibe-d"] = Dependency("~>0.7.30");
+ p.buildSettings.dependencies["vibe-d"] = Dependency("~>0.8.2");
p.description = "A simple vibe.d server application.";
pre_write_callback();
@@ -153,9 +153,29 @@
createDirectory(root_path ~ "deimos");
}
-private void writeGitignore(NativePath root_path, PackageRecipe p)
+/**
+ * Write the `.gitignore` file to the directory, if it does not already exists
+ *
+ * As `dub` is often used with `git`, adding a `.gitignore` is a nice touch for
+ * most users. However, this file is not mandatory for `dub` to do its job,
+ * so we do not depend on the content.
+ * One important use case we need to support is people running `dub init` on
+ * a Github-initialized repository. Those might already contain a `.gitignore`
+ * (and a README and a LICENSE), thus we should not bail out if the file already
+ * exists, just ignore it.
+ *
+ * Params:
+ * root_path = The path to the directory hosting the project
+ * pkg_name = Name of the package, to generate a list of binaries to ignore
+ */
+private void writeGitignore(NativePath root_path, const(char)[] pkg_name)
{
- write((root_path ~ ".gitignore").toNativeString(),
+ auto full_path = (root_path ~ ".gitignore").toNativeString();
+
+ if (existsFile(full_path))
+ return;
+
+ write(full_path,
q"{.dub
docs.json
__dummy.html
@@ -170,7 +190,7 @@
*.o
*.obj
*.lst
-}".format(p.name));
+}".format(pkg_name));
}
private string getUserName()
diff --git a/test/4-describe-data-1-list.sh b/test/4-describe-data-1-list.sh
index 3cfe5dc..def3899 100755
--- a/test/4-describe-data-1-list.sh
+++ b/test/4-describe-data-1-list.sh
@@ -77,11 +77,11 @@
echo >> "$expected_file"
# --data=versions
echo "someVerIdent" >> "$expected_file"
-echo "anotherVerIdent" >> "$expected_file"
echo "Have_describe_project" >> "$expected_file"
echo "Have_describe_dependency_1" >> "$expected_file"
echo "Have_describe_dependency_2" >> "$expected_file"
echo "Have_describe_dependency_3" >> "$expected_file"
+echo "anotherVerIdent" >> "$expected_file"
echo >> "$expected_file"
# --data=debug-versions
echo "someDebugVerIdent" >> "$expected_file"
diff --git a/test/4-describe-data-2-dmd.sh b/test/4-describe-data-2-dmd.sh
index d323bc5..225537a 100755
--- a/test/4-describe-data-2-dmd.sh
+++ b/test/4-describe-data-2-dmd.sh
@@ -54,11 +54,11 @@
echo -n "'$CURR_DIR/describe-dependency-1/source/dummy.d' " >> "$expected_file"
# --data=versions
echo -n "-version=someVerIdent " >> "$expected_file"
-echo -n "-version=anotherVerIdent " >> "$expected_file"
echo -n "-version=Have_describe_project " >> "$expected_file"
echo -n "-version=Have_describe_dependency_1 " >> "$expected_file"
echo -n "-version=Have_describe_dependency_2 " >> "$expected_file"
echo -n "-version=Have_describe_dependency_3 " >> "$expected_file"
+echo -n "-version=anotherVerIdent " >> "$expected_file"
# --data=debug-versions
echo -n "-debug=someDebugVerIdent " >> "$expected_file"
echo -n "-debug=anotherDebugVerIdent " >> "$expected_file"
diff --git a/test/describe-dependency-1/dependency-postGenerateCommands.sh b/test/describe-dependency-1/dependency-postGenerateCommands.sh
index 1a24852..f1f641a 100755
--- a/test/describe-dependency-1/dependency-postGenerateCommands.sh
+++ b/test/describe-dependency-1/dependency-postGenerateCommands.sh
@@ -1 +1 @@
-#!/bin/sh
+#!/usr/bin/env bash
diff --git a/test/describe-dependency-1/dependency-preGenerateCommands.sh b/test/describe-dependency-1/dependency-preGenerateCommands.sh
index 1a24852..f1f641a 100755
--- a/test/describe-dependency-1/dependency-preGenerateCommands.sh
+++ b/test/describe-dependency-1/dependency-preGenerateCommands.sh
@@ -1 +1 @@
-#!/bin/sh
+#!/usr/bin/env bash
diff --git a/test/describe-project/do-postGenerateCommands.sh b/test/describe-project/do-postGenerateCommands.sh
index 1a24852..f1f641a 100755
--- a/test/describe-project/do-postGenerateCommands.sh
+++ b/test/describe-project/do-postGenerateCommands.sh
@@ -1 +1 @@
-#!/bin/sh
+#!/usr/bin/env bash
diff --git a/test/describe-project/do-preGenerateCommands.sh b/test/describe-project/do-preGenerateCommands.sh
index 1a24852..f1f641a 100755
--- a/test/describe-project/do-preGenerateCommands.sh
+++ b/test/describe-project/do-preGenerateCommands.sh
@@ -1 +1 @@
-#!/bin/sh
+#!/usr/bin/env bash
diff --git a/test/expected-issue1037-output b/test/expected-issue1037-output
new file mode 100644
index 0000000..a5d7c55
--- /dev/null
+++ b/test/expected-issue1037-output
@@ -0,0 +1,4 @@
+Root package issue1037-better-dependency-messages reference gitcompatibledubpackage 1.0.1 cannot be satisfied.
+Packages causing the conflict:
+ issue1037-better-dependency-messages depends on 1.0.1
+ b depends on ~>1.0.2
diff --git a/test/feat663-search.sh b/test/feat663-search.sh
index ab127cb..435c8d8 100755
--- a/test/feat663-search.sh
+++ b/test/feat663-search.sh
@@ -7,6 +7,9 @@
if ${DUB} search nonexistent123456789package 2>/dev/null; then
die $LINENO '`dub search nonexistent123456789package` succeeded'
fi
-if ! OUTPUT=$(${DUB} search dub -v 2>&1) || ! { echo "$OUTPUT" | grep -q '^dub (.*)\s'; } then
+if ! OUTPUT=$(${DUB} search dub -v 2>&1); then
die $LINENO '`dub search dub` failed' "$OUTPUT"
fi
+if ! grep -q '^dub (.*)\s'<<<"$OUTPUT"; then
+ die $LINENO '`grep -q '"'"'^dub (.*)\s'"'"'` failed' "$OUTPUT"
+fi
diff --git a/test/fetchzip.sh b/test/fetchzip.sh
index b0d34d2..ce03723 100755
--- a/test/fetchzip.sh
+++ b/test/fetchzip.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
DIR=$(dirname "${BASH_SOURCE[0]}")
. "$DIR"/common.sh
diff --git a/test/interactive-remove.sh b/test/interactive-remove.sh
index f689fdd..3608a2b 100755
--- a/test/interactive-remove.sh
+++ b/test/interactive-remove.sh
@@ -7,7 +7,7 @@
if $DUB remove dub --non-interactive 2>/dev/null; then
die $LINENO 'Non-interactive remove should fail'
fi
-echo 1 | $DUB remove dub | tr --delete '\n' | grep --ignore-case 'select.*0\.9\.20.*0\.9\.21.*'
+echo 1 | $DUB remove dub | tr -d '\n' | grep --ignore-case 'select.*0\.9\.20.*0\.9\.21.*'
if [ -d $HOME/.dub/packages/dub-0.9.20/dub ]; then
die $LINENO 'Failed to remove dub-0.9.20'
fi
diff --git a/test/issue1037-better-dependency-messages.sh b/test/issue1037-better-dependency-messages.sh
new file mode 100755
index 0000000..2fe3b9f
--- /dev/null
+++ b/test/issue1037-better-dependency-messages.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+set -e -o pipefail
+
+cd ${CURR_DIR}/issue1037-better-dependency-messages
+
+temp_file=$(mktemp $(basename $0).XXXXXX)
+expected_file="$CURR_DIR/expected-issue1037-output"
+
+function cleanup {
+ rm $temp_file
+}
+
+trap cleanup EXIT
+
+$DUB upgrade 2>$temp_file && exit 1 # dub upgrade should fail
+
+if ! diff "$expected_file" "$temp_file"; then
+ die 'output not containing conflict information'
+fi
+
+exit 0
\ No newline at end of file
diff --git a/test/issue1037-better-dependency-messages/.no_build b/test/issue1037-better-dependency-messages/.no_build
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/issue1037-better-dependency-messages/.no_build
diff --git a/test/issue1037-better-dependency-messages/.no_run b/test/issue1037-better-dependency-messages/.no_run
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/issue1037-better-dependency-messages/.no_run
diff --git a/test/issue1037-better-dependency-messages/.no_test b/test/issue1037-better-dependency-messages/.no_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/issue1037-better-dependency-messages/.no_test
diff --git a/test/issue1037-better-dependency-messages/b/dub.json b/test/issue1037-better-dependency-messages/b/dub.json
new file mode 100644
index 0000000..92443ac
--- /dev/null
+++ b/test/issue1037-better-dependency-messages/b/dub.json
@@ -0,0 +1,6 @@
+{
+ "name": "b",
+ "dependencies": {
+ "gitcompatibledubpackage": "~>1.0.2"
+ }
+}
\ No newline at end of file
diff --git a/test/issue1037-better-dependency-messages/dub.json b/test/issue1037-better-dependency-messages/dub.json
new file mode 100644
index 0000000..abb7d17
--- /dev/null
+++ b/test/issue1037-better-dependency-messages/dub.json
@@ -0,0 +1,10 @@
+{
+ "name": "issue1037-better-dependency-messages",
+ "dependencies": {
+ "gitcompatibledubpackage": "1.0.1",
+ "b": {
+ "path": "b",
+ "version": "*"
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/issue1262-version-inheritance-diamond/.gitignore b/test/issue1262-version-inheritance-diamond/.gitignore
new file mode 100644
index 0000000..c09a597
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/.gitignore
@@ -0,0 +1,15 @@
+.dub
+docs.json
+__dummy.html
+docs/
+issue1262-version-inheritance-diamond
+issue1262-version-inheritance-diamond.so
+issue1262-version-inheritance-diamond.dylib
+issue1262-version-inheritance-diamond.dll
+issue1262-version-inheritance-diamond.a
+issue1262-version-inheritance-diamond.lib
+issue1262-version-inheritance-diamond-test-*
+*.exe
+*.o
+*.obj
+*.lst
diff --git a/test/issue1262-version-inheritance-diamond/.no_run b/test/issue1262-version-inheritance-diamond/.no_run
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/.no_run
diff --git a/test/issue1262-version-inheritance-diamond/.no_test b/test/issue1262-version-inheritance-diamond/.no_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/.no_test
diff --git a/test/issue1262-version-inheritance-diamond/daughter/.gitignore b/test/issue1262-version-inheritance-diamond/daughter/.gitignore
new file mode 100644
index 0000000..f190acb
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/daughter/.gitignore
@@ -0,0 +1,14 @@
+.dub
+docs.json
+__dummy.html
+docs/
+daughter.so
+daughter.dylib
+daughter.dll
+daughter.a
+daughter.lib
+daughter-test-*
+*.exe
+*.o
+*.obj
+*.lst
diff --git a/test/issue1262-version-inheritance-diamond/daughter/dub.sdl b/test/issue1262-version-inheritance-diamond/daughter/dub.sdl
new file mode 100644
index 0000000..3a0eee7
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/daughter/dub.sdl
@@ -0,0 +1,3 @@
+name "daughter"
+versions "Daughter"
+dependency "diamond" path="../diamond"
diff --git a/test/issue1262-version-inheritance-diamond/daughter/source/dummy.d b/test/issue1262-version-inheritance-diamond/daughter/source/dummy.d
new file mode 100644
index 0000000..89139c3
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/daughter/source/dummy.d
@@ -0,0 +1,6 @@
+module daughter.dummy;
+
+version (Parent) {} else static assert(0, "Expected Parent to be set");
+version (Daughter) {} else static assert(0, "Expected Daughter to be set");
+version (Son) {} else static assert(0, "Expected Son to be set");
+version (Diamond) {} else static assert(0, "Expected Diamond to be set");
diff --git a/test/issue1262-version-inheritance-diamond/diamond/.gitignore b/test/issue1262-version-inheritance-diamond/diamond/.gitignore
new file mode 100644
index 0000000..c359a73
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/diamond/.gitignore
@@ -0,0 +1,14 @@
+.dub
+docs.json
+__dummy.html
+docs/
+diamond.so
+diamond.dylib
+diamond.dll
+diamond.a
+diamond.lib
+diamond-test-*
+*.exe
+*.o
+*.obj
+*.lst
diff --git a/test/issue1262-version-inheritance-diamond/diamond/dub.sdl b/test/issue1262-version-inheritance-diamond/diamond/dub.sdl
new file mode 100644
index 0000000..85cb8a1
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/diamond/dub.sdl
@@ -0,0 +1,2 @@
+name "diamond"
+versions "Diamond"
diff --git a/test/issue1262-version-inheritance-diamond/diamond/source/dummy.d b/test/issue1262-version-inheritance-diamond/diamond/source/dummy.d
new file mode 100644
index 0000000..fb1499e
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/diamond/source/dummy.d
@@ -0,0 +1,6 @@
+module diamond.dummy;
+
+version (Parent) {} else static assert(0, "Expected Parent to be set");
+version (Daughter) {} else static assert(0, "Expected Daughter to be set");
+version (Son) {} else static assert(0, "Expected Son to be set");
+version (Diamond) {} else static assert(0, "Expected Diamond to be set");
diff --git a/test/issue1262-version-inheritance-diamond/dub.sdl b/test/issue1262-version-inheritance-diamond/dub.sdl
new file mode 100644
index 0000000..588adb8
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/dub.sdl
@@ -0,0 +1,4 @@
+name "issue1262-version-inheritance-diamond"
+versions "Parent"
+dependency "daughter" path="daughter"
+dependency "son" path="son"
diff --git a/test/issue1262-version-inheritance-diamond/son/.gitignore b/test/issue1262-version-inheritance-diamond/son/.gitignore
new file mode 100644
index 0000000..601a33b
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/son/.gitignore
@@ -0,0 +1,14 @@
+.dub
+docs.json
+__dummy.html
+docs/
+son.so
+son.dylib
+son.dll
+son.a
+son.lib
+son-test-*
+*.exe
+*.o
+*.obj
+*.lst
diff --git a/test/issue1262-version-inheritance-diamond/son/dub.sdl b/test/issue1262-version-inheritance-diamond/son/dub.sdl
new file mode 100644
index 0000000..41dc1be
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/son/dub.sdl
@@ -0,0 +1,3 @@
+name "son"
+versions "Son"
+dependency "diamond" path="../diamond"
diff --git a/test/issue1262-version-inheritance-diamond/son/source/dummy.d b/test/issue1262-version-inheritance-diamond/son/source/dummy.d
new file mode 100644
index 0000000..85841ad
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/son/source/dummy.d
@@ -0,0 +1,6 @@
+module son.dummy;
+
+version (Parent) {} else static assert(0, "Expected Parent to be set");
+version (Daughter) {} else static assert(0, "Expected Daughter to be set");
+version (Son) {} else static assert(0, "Expected Son to be set");
+version (Diamond) {} else static assert(0, "Expected Diamond to be set");
diff --git a/test/issue1262-version-inheritance-diamond/source/app.d b/test/issue1262-version-inheritance-diamond/source/app.d
new file mode 100644
index 0000000..10f0ae6
--- /dev/null
+++ b/test/issue1262-version-inheritance-diamond/source/app.d
@@ -0,0 +1,8 @@
+version (Parent) {} else static assert(0, "Expected Parent to be set");
+version (Daughter) {} else static assert(0, "Expected Daughter to be set");
+version (Son) {} else static assert(0, "Expected Son to be set");
+version (Diamond) {} else static assert(0, "Expected Diamond to be set");
+
+void main()
+{
+}
diff --git a/test/issue1262-version-inheritance/.gitignore b/test/issue1262-version-inheritance/.gitignore
new file mode 100644
index 0000000..84dca77
--- /dev/null
+++ b/test/issue1262-version-inheritance/.gitignore
@@ -0,0 +1,15 @@
+.dub
+docs.json
+__dummy.html
+docs/
+issue1262-version-inheritance
+issue1262-version-inheritance.so
+issue1262-version-inheritance.dylib
+issue1262-version-inheritance.dll
+issue1262-version-inheritance.a
+issue1262-version-inheritance.lib
+issue1262-version-inheritance-test-*
+*.exe
+*.o
+*.obj
+*.lst
diff --git a/test/issue1262-version-inheritance/.no_run b/test/issue1262-version-inheritance/.no_run
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/issue1262-version-inheritance/.no_run
diff --git a/test/issue1262-version-inheritance/.no_test b/test/issue1262-version-inheritance/.no_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/issue1262-version-inheritance/.no_test
diff --git a/test/issue1262-version-inheritance/daughter/.gitignore b/test/issue1262-version-inheritance/daughter/.gitignore
new file mode 100644
index 0000000..f190acb
--- /dev/null
+++ b/test/issue1262-version-inheritance/daughter/.gitignore
@@ -0,0 +1,14 @@
+.dub
+docs.json
+__dummy.html
+docs/
+daughter.so
+daughter.dylib
+daughter.dll
+daughter.a
+daughter.lib
+daughter-test-*
+*.exe
+*.o
+*.obj
+*.lst
diff --git a/test/issue1262-version-inheritance/daughter/dub.sdl b/test/issue1262-version-inheritance/daughter/dub.sdl
new file mode 100644
index 0000000..baa3295
--- /dev/null
+++ b/test/issue1262-version-inheritance/daughter/dub.sdl
@@ -0,0 +1,3 @@
+name "daughter"
+versions "Daughter"
+
diff --git a/test/issue1262-version-inheritance/daughter/source/dummy.d b/test/issue1262-version-inheritance/daughter/source/dummy.d
new file mode 100644
index 0000000..aad7fc8
--- /dev/null
+++ b/test/issue1262-version-inheritance/daughter/source/dummy.d
@@ -0,0 +1,5 @@
+module daughter.dummy;
+
+version (Parent) {} else static assert(0, "Expected Parent to be set");
+version (Daughter) {} else static assert(0, "Expected Daughter to be set");
+version (Son) static assert(0, "Expected Son to no be set");
diff --git a/test/issue1262-version-inheritance/dub.sdl b/test/issue1262-version-inheritance/dub.sdl
new file mode 100644
index 0000000..46568fb
--- /dev/null
+++ b/test/issue1262-version-inheritance/dub.sdl
@@ -0,0 +1,4 @@
+name "issue1262-version-inheritance"
+versions "Parent"
+dependency "daughter" path="daughter"
+dependency "son" path="son"
diff --git a/test/issue1262-version-inheritance/son/.gitignore b/test/issue1262-version-inheritance/son/.gitignore
new file mode 100644
index 0000000..601a33b
--- /dev/null
+++ b/test/issue1262-version-inheritance/son/.gitignore
@@ -0,0 +1,14 @@
+.dub
+docs.json
+__dummy.html
+docs/
+son.so
+son.dylib
+son.dll
+son.a
+son.lib
+son-test-*
+*.exe
+*.o
+*.obj
+*.lst
diff --git a/test/issue1262-version-inheritance/son/dub.sdl b/test/issue1262-version-inheritance/son/dub.sdl
new file mode 100644
index 0000000..5882548
--- /dev/null
+++ b/test/issue1262-version-inheritance/son/dub.sdl
@@ -0,0 +1,2 @@
+name "son"
+versions "Son"
diff --git a/test/issue1262-version-inheritance/son/source/dummy.d b/test/issue1262-version-inheritance/son/source/dummy.d
new file mode 100644
index 0000000..63995a1
--- /dev/null
+++ b/test/issue1262-version-inheritance/son/source/dummy.d
@@ -0,0 +1,5 @@
+module son.dummy;
+
+version (Parent) {} else static assert(0, "Expected Parent to be set");
+version (Daughter) static assert(0, "Expected Daughter to not be set");
+version (Son) {} else static assert(0, "Expected Son to be set");
diff --git a/test/issue1262-version-inheritance/source/app.d b/test/issue1262-version-inheritance/source/app.d
new file mode 100644
index 0000000..b6bb4be
--- /dev/null
+++ b/test/issue1262-version-inheritance/source/app.d
@@ -0,0 +1,7 @@
+version (Parent) {} else static assert(0, "Expected Parent to be set");
+version (Daughter) {} else static assert(0, "Expected Daughter to be set");
+version (Son) {} else static assert(0, "Expected Son to be set");
+
+void main()
+{
+}
diff --git a/test/issue1350-transitive-none-deps/.gitignore b/test/issue1350-transitive-none-deps/.gitignore
new file mode 100644
index 0000000..4571d26
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/.gitignore
@@ -0,0 +1,15 @@
+.dub
+docs.json
+__dummy.html
+docs/
+test
+test.so
+test.dylib
+test.dll
+test.a
+test.lib
+test-test-*
+*.exe
+*.o
+*.obj
+*.lst
diff --git a/test/issue1350-transitive-none-deps/.no_run b/test/issue1350-transitive-none-deps/.no_run
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/.no_run
diff --git a/test/issue1350-transitive-none-deps/.no_test b/test/issue1350-transitive-none-deps/.no_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/.no_test
diff --git a/test/issue1350-transitive-none-deps/common-dep/common.d b/test/issue1350-transitive-none-deps/common-dep/common.d
new file mode 100644
index 0000000..23cc13c
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/common-dep/common.d
@@ -0,0 +1 @@
+module common;
diff --git a/test/issue1350-transitive-none-deps/common-dep/dub.sdl b/test/issue1350-transitive-none-deps/common-dep/dub.sdl
new file mode 100644
index 0000000..e4d29b2
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/common-dep/dub.sdl
@@ -0,0 +1,4 @@
+name "common-dep"
+targetType "library"
+importPaths "."
+sourceFiles "common.d"
diff --git a/test/issue1350-transitive-none-deps/common-none/dub.sdl b/test/issue1350-transitive-none-deps/common-none/dub.sdl
new file mode 100644
index 0000000..79986cc
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/common-none/dub.sdl
@@ -0,0 +1,3 @@
+name "common-none"
+targetType "none"
+dependency "common-dep" path="../common-dep"
diff --git a/test/issue1350-transitive-none-deps/dep1/dep1.d b/test/issue1350-transitive-none-deps/dep1/dep1.d
new file mode 100644
index 0000000..6b47d60
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/dep1/dep1.d
@@ -0,0 +1,2 @@
+module dep1;
+import common;
diff --git a/test/issue1350-transitive-none-deps/dep1/dub.sdl b/test/issue1350-transitive-none-deps/dep1/dub.sdl
new file mode 100644
index 0000000..432097a
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/dep1/dub.sdl
@@ -0,0 +1,4 @@
+name "dep1"
+importPaths "."
+sourceFiles "dep1.d"
+dependency "common-none" path="../common-none"
diff --git a/test/issue1350-transitive-none-deps/dep2/dep2.d b/test/issue1350-transitive-none-deps/dep2/dep2.d
new file mode 100644
index 0000000..fbfed0d
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/dep2/dep2.d
@@ -0,0 +1,2 @@
+module dep2;
+import common;
diff --git a/test/issue1350-transitive-none-deps/dep2/dub.sdl b/test/issue1350-transitive-none-deps/dep2/dub.sdl
new file mode 100644
index 0000000..3157e08
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/dep2/dub.sdl
@@ -0,0 +1,4 @@
+name "dep2"
+importPaths "."
+sourceFiles "dep2.d"
+dependency "common-none" path="../common-none"
diff --git a/test/issue1350-transitive-none-deps/dub.sdl b/test/issue1350-transitive-none-deps/dub.sdl
new file mode 100644
index 0000000..5bcd940
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/dub.sdl
@@ -0,0 +1,5 @@
+name "test"
+targetType "executable"
+sourceFiles "test.d"
+dependency "dep1" path="dep1"
+dependency "dep2" path="dep2"
diff --git a/test/issue1350-transitive-none-deps/test.d b/test/issue1350-transitive-none-deps/test.d
new file mode 100644
index 0000000..4390778
--- /dev/null
+++ b/test/issue1350-transitive-none-deps/test.d
@@ -0,0 +1,5 @@
+module test;
+
+import dep1, dep2, common;
+
+void main() {}
diff --git a/test/issue616-describe-vs-generate-commands/do-preGenerateCommands.sh b/test/issue616-describe-vs-generate-commands/do-preGenerateCommands.sh
index 84468cd..6342d76 100755
--- a/test/issue616-describe-vs-generate-commands/do-preGenerateCommands.sh
+++ b/test/issue616-describe-vs-generate-commands/do-preGenerateCommands.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
if [ -n "${dub_issue616}" ]; then
echo 'Fail! preGenerateCommands recursion detected!' >&2
exit 0 # Don't return a non-zero error code here. This way the test gives a better diagnostic.
diff --git a/test/issue616-subpack/dub.json b/test/issue616-subpack/dub.json
index 552ddcd..31c525a 100644
--- a/test/issue616-subpack/dub.json
+++ b/test/issue616-subpack/dub.json
@@ -1,6 +1,6 @@
{
"name": "issue616-subpack",
- "targetType": "executable",
+ "targetType": "library",
"dependencies": {
"issue616-subsubpack": {
"version": "1.0",
diff --git a/test/issue616-subsubpack/dub.json b/test/issue616-subsubpack/dub.json
index e4e4b5b..207761f 100644
--- a/test/issue616-subsubpack/dub.json
+++ b/test/issue616-subsubpack/dub.json
@@ -1,4 +1,4 @@
{
"name": "issue616-subsubpack",
- "targetType": "executable"
+ "targetType": "library"
}
diff --git a/test/issue884-init-defer-file-creation.sh b/test/issue884-init-defer-file-creation.sh
index 013842c..7ffab21 100755
--- a/test/issue884-init-defer-file-creation.sh
+++ b/test/issue884-init-defer-file-creation.sh
@@ -9,8 +9,11 @@
cd ${TMPDIR}
# kill dub init during interactive mode
-${DUB} init <(while :; do sleep 1; done) &
+mkfifo in
+${DUB} init < in &
+sleep 1
kill $!
+rm in
# ensure that no files are left behind
NFILES_PLUS_ONE=`ls -la | wc -l`
diff --git a/test/run-unittest.sh b/test/run-unittest.sh
index 9cf7292..8d14e33 100755
--- a/test/run-unittest.sh
+++ b/test/run-unittest.sh
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
+set -ueo pipefail
. $(dirname "${BASH_SOURCE[0]}")/common.sh
@@ -30,10 +31,11 @@
DC_BIN=$(basename "$DC")
CURR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
+FRONTEND="${FRONTEND:-}"
for script in $(ls $CURR_DIR/*.sh); do
if [ "$script" = "$(readlink -f ${BASH_SOURCE[0]})" ] || [ "$(basename $script)" = "common.sh" ]; then continue; fi
- if [ -e $script.min_frontend ] && [ ! -z ${FRONTEND:-} -a ${FRONTEND:-} \< $(cat $script.min_frontend) ]; then continue; fi
+ if [ -e $script.min_frontend ] && [ ! -z "$FRONTEND" ] && [ ${FRONTEND} \< $(cat $script.min_frontend) ]; then continue; fi
log "Running $script..."
DUB=$DUB DC=$DC CURR_DIR="$CURR_DIR" $script || logError "Script failure."
done
diff --git a/test/single-file-sdl-default-name.sh b/test/single-file-sdl-default-name.sh
index 1c61540..ab2ba8b 100755
--- a/test/single-file-sdl-default-name.sh
+++ b/test/single-file-sdl-default-name.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
set -e
cd ${CURR_DIR}
rm -f single-file-sdl-default-name
diff --git a/travis-ci.sh b/travis-ci.sh
index 8436dcb..c7782f2 100755
--- a/travis-ci.sh
+++ b/travis-ci.sh
@@ -4,7 +4,7 @@
source ~/dlang/*/activate # activate host compiler
-if [ -z "$FRONTEND" -o "$FRONTEND" \> 2.071.z ]; then
+if [ -z "$FRONTEND" -o "$FRONTEND" \> 2.072.z ]; then
vibe_ver=$(jq -r '.versions | .["vibe-d"]' < dub.selections.json)
dub fetch vibe-d --version=$vibe_ver # get optional dependency
dub test --compiler=${DC} -c library-nonet
@@ -27,6 +27,7 @@
export FRONTEND=2.068
source $(~/dlang/install.sh gdc-4.8.5 --activate)
DUB=`pwd`/bin/dub DC=${DC} test/run-unittest.sh
+ deactivate
else
./build.sh
DUB=`pwd`/bin/dub DC=${DC} test/run-unittest.sh
@@ -41,3 +42,9 @@
if [ "$COVERAGE" = true ]; then
find . -type f -name '*.d' -exec grep -Hn "[[:blank:]]$" {} \;
fi
+
+# check that the man page generation still works (only once)
+if [ "$COVERAGE" = true ]; then
+ source $(~/dlang/install.sh dmd --activate)
+ dub --single -v scripts/man/gen_man.d
+fi