diff --git a/.travis.yml b/.travis.yml index f131df0..cd04032 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,21 @@ language: d +dist: trusty sudo: false matrix: include: - d: dmd-nightly - env: [FRONTEND=2.074] + env: [FRONTEND=2.075] - d: dmd-beta - env: [FRONTEND=2.074] + env: [FRONTEND=2.075] - d: dmd - env: [FRONTEND=2.074] - - d: dmd-2.074.0 - env: [FRONTEND=2.074] - - d: dmd-2.073.0 env: - - [FRONTEND=2.073] + - [FRONTEND=2.074] - [COVERAGE=true] + - d: dmd-2.074.1 + env: [FRONTEND=2.074] + - d: dmd-2.073.2 + env: [FRONTEND=2.073] - d: dmd-2.072.2 env: [FRONTEND=2.072] - d: dmd-2.071.2 @@ -29,8 +30,6 @@ env: [FRONTEND=2.067] - d: dmd-2.066.1 env: [FRONTEND=2.066] - - d: dmd-2.065.0 - env: [FRONTEND=2.065] - d: ldc-beta env: [FRONTEND=2.073] - d: ldc @@ -49,11 +48,14 @@ env: [FRONTEND=2.066] - d: gdc-4.9.2 env: [FRONTEND=2.066] - - d: gdc-4.9.0 - env: [FRONTEND=2.065] allow_failures: - d: gdc +addons: + apt: + packages: + - libevent-dev + script: - ./travis-ci.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 7387e58..82f0cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ Changelog ========= +v1.5.0 - 2017- +------------------- + +- Read additional registry URLs (semicolon separated) from DUB_REGISTRY env var - [pull #1173][issue1173] + +[issue1173]: https://github.com/dlang/dub/issues/1173 + v1.4.0 - 2017- ------------------- diff --git a/build.sh b/build.sh index d5d8f55..7cd478e 100755 --- a/build.sh +++ b/build.sh @@ -56,7 +56,7 @@ MACOSX_DEPLOYMENT_TARGET=10.7 echo Running $DMD... -$DMD -ofbin/dub -w -version=DubUseCurl -Isource $* $LIBS @build-files.txt +$DMD -ofbin/dub -g -O -w -version=DubUseCurl -Isource $* $LIBS @build-files.txt bin/dub --version echo DUB has been built as bin/dub. echo diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 3fec92f..0356c00 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -496,7 +496,7 @@ while (true) { // Tries getting the name until a valid one is given. import std.regex; - auto nameRegex = regex(`^[a-z\-_]+$`); + auto nameRegex = regex(`^[a-z0-9\-_]+$`); string triedName = input("Name", p.name); if (triedName.matchFirst(nameRegex).empty) { logError("Invalid name, \""~triedName~"\", names should consist only of lowercase alphanumeric characters, - and _."); @@ -847,6 +847,7 @@ private { string m_mainFile; bool m_combined = false; + bool m_parallel = false; bool m_force = false; } @@ -885,6 +886,9 @@ args.getopt("combined", &m_combined, [ "Tries to build the whole project in a single compiler run." ]); + args.getopt("parallel", &m_parallel, [ + "Runs multiple compiler instances in parallel, if possible." + ]); args.getopt("f|force", &m_force, [ "Forces a recompilation even if the target is up to date" ]); @@ -912,6 +916,7 @@ settings.buildMode = m_buildMode; settings.buildSettings = m_buildSettings; settings.combined = m_combined; + settings.parallelBuild = m_parallel; settings.force = m_force; settings.tempBuild = m_single; settings.run = true; diff --git a/source/dub/compilers/buildsettings.d b/source/dub/compilers/buildsettings.d index beebd0f..16de290 100644 --- a/source/dub/compilers/buildsettings.d +++ b/source/dub/compilers/buildsettings.d @@ -277,9 +277,10 @@ deprecationErrors = 1<<19, /// Stop compilation upon usage of deprecated features (-de) property = 1<<20, /// DEPRECATED: Enforce property syntax (-property) profileGC = 1<<21, /// Profile runtime allocations + pic = 1<<22, /// Generate position independent code // for internal usage - _docs = 1<<22, // Write ddoc to docs - _ddox = 1<<23, // Compile docs.json + _docs = 1<<23, // Write ddoc to docs + _ddox = 1<<24 // Compile docs.json } struct BuildOptions { @@ -326,4 +327,5 @@ | BuildOption.noBoundsCheck | BuildOption.profile | BuildOption.ignoreUnknownPragmas | BuildOption.syntaxOnly | BuildOption.warnings | BuildOption.warningsAsErrors | BuildOption.ignoreDeprecations | BuildOption.deprecationWarnings - | BuildOption.deprecationErrors | BuildOption.property | BuildOption.profileGC; + | BuildOption.deprecationErrors | BuildOption.property | BuildOption.profileGC + | BuildOption.pic; diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index 0295a64..b13736e 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -20,7 +20,6 @@ import std.exception; import std.file; import std.process; -import std.random; import std.typecons; @@ -117,7 +116,7 @@ } version (Posix) { - if (settings.targetType == TargetType.dynamicLibrary) + if (settings.options & BuildOption.pic) settings.addDFlags("-fPIC"); } diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index 7a20f54..0d5d3cf 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -20,7 +20,6 @@ import std.exception; import std.file; import std.process; -import std.random; import std.typecons; @@ -119,7 +118,7 @@ settings.lflags = null; } - if (settings.targetType == TargetType.dynamicLibrary) + if (settings.options & BuildOption.pic) settings.addDFlags("-fPIC"); assert(fields & BuildSetting.dflags); diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 8953e5e..df8c2de 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -20,7 +20,6 @@ import std.exception; import std.file; import std.process; -import std.random; import std.typecons; @@ -117,7 +116,7 @@ settings.lflags = null; } - if (settings.targetType == TargetType.dynamicLibrary) + if (settings.options & BuildOption.pic) settings.addDFlags("-relocation-model=pic"); assert(fields & BuildSetting.dflags); diff --git a/source/dub/dub.d b/source/dub/dub.d index 32c84bf..f27793a 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -133,9 +133,11 @@ PackageSupplier[] ps = additional_package_suppliers; if (skip_registry < SkipPackageSuppliers.all) - ps ~= m_config.registryURLs + { + ps ~= (environment.get("DUB_REGISTRY", null).split(";") ~ m_config.registryURLs) .map!(url => cast(PackageSupplier)new RegistryPackageSupplier(URL(url))) .array; + } if (skip_registry < SkipPackageSuppliers.standard) ps ~= defaultPackageSuppliers(); @@ -145,6 +147,22 @@ updatePackageSearchPath(); } + unittest + { + scope (exit) environment.remove("DUB_REGISTRY"); + auto dub = new Dub(".", null, SkipPackageSuppliers.standard); + assert(dub.m_packageSuppliers.length == 0); + environment["DUB_REGISTRY"] = "http://example.com/"; + dub = new Dub(".", null, SkipPackageSuppliers.standard); + logInfo("%s", dub.m_packageSuppliers); + assert(dub.m_packageSuppliers.length == 1); + environment["DUB_REGISTRY"] = "http://example.com/;http://foo.com/"; + dub = new Dub(".", null, SkipPackageSuppliers.standard); + assert(dub.m_packageSuppliers.length == 2); + dub = new Dub(".", [new RegistryPackageSupplier(URL("http://bar.com/"))], SkipPackageSuppliers.standard); + assert(dub.m_packageSuppliers.length == 3); + } + /** Initializes the instance with a single package search path, without loading a package. @@ -273,6 +291,7 @@ { import dub.recipe.io : parsePackageRecipe; import std.file : mkdirRecurse, readText; + import std.path : baseName, stripExtension; path = makeAbsolute(path); @@ -295,12 +314,16 @@ recipe_content = file_content[0 .. idx].strip(); } else throw new Exception("The source file must start with a recipe comment."); + auto nidx = recipe_content.indexOf('\n'); + auto idx = recipe_content.indexOf(':'); - enforce(idx > 0, "Missing recipe file name (e.g. \"dub.sdl:\") in recipe comment"); + enforce(idx > 0 && (nidx < 0 || nidx > idx), + "The first line of the recipe comment must list the recipe file name followed by a colon (e.g. \"/+ dub.sdl:\")."); auto recipe_filename = recipe_content[0 .. idx]; recipe_content = recipe_content[idx+1 .. $]; + auto recipe_default_package_name = path.toString.baseName.stripExtension.strip; - auto recipe = parsePackageRecipe(recipe_content, recipe_filename); + auto recipe = parsePackageRecipe(recipe_content, recipe_filename, null, recipe_default_package_name); enforce(recipe.buildSettings.sourceFiles.length == 0, "Single-file packages are not allowed to specify source files."); enforce(recipe.buildSettings.sourcePaths.length == 0, "Single-file packages are not allowed to specify source paths."); enforce(recipe.buildSettings.importPaths.length == 0, "Single-file packages are not allowed to specify import paths."); diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index 7938cc7..7865d9e 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -188,6 +188,10 @@ 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); diff --git a/source/dub/internal/utils.d b/source/dub/internal/utils.d index 65b9497..799755b 100644 --- a/source/dub/internal/utils.d +++ b/source/dub/internal/utils.d @@ -276,6 +276,9 @@ auto proxy = environment.get("http_proxy", null); if (proxy.length) conn.proxy = proxy; + auto noProxy = environment.get("no_proxy", null); + if (noProxy.length) conn.handle.set(CurlOption.noproxy, noProxy); + conn.addRequestHeader("User-Agent", "dub/"~getDUBVersion()~" (std.net.curl; +https://github.com/rejectedsoftware/dub)"); } } diff --git a/source/dub/internal/vibecompat/inet/url.d b/source/dub/internal/vibecompat/inet/url.d index 389046e..9115c9c 100644 --- a/source/dub/internal/vibecompat/inet/url.d +++ b/source/dub/internal/vibecompat/inet/url.d @@ -107,7 +107,7 @@ } } - this.localURI = str; + this.localURI = (str == "") ? "/" : str; } /// ditto static URL parse(string url_string) @@ -277,4 +277,10 @@ assert(url.path.toString() == "/sub2/index.html", url.path.toString()); assert(url.queryString == "query", url.queryString); assert(url.anchor == "anchor", url.anchor); + + url = URL("http://localhost")~Path("packages"); + assert(url.toString() == "http://localhost/packages", url.toString()); + + url = URL("http://localhost/")~Path("packages"); + assert(url.toString() == "http://localhost/packages", url.toString()); } diff --git a/source/dub/recipe/io.d b/source/dub/recipe/io.d index 9704931..52dbefe 100644 --- a/source/dub/recipe/io.d +++ b/source/dub/recipe/io.d @@ -53,11 +53,14 @@ to determine the file format from the file extension parent_name = Optional name of the parent package (if this is a sub package) + default_package_name = Optional default package name (if no package name + is found in the recipe this value will be used) Returns: Returns the package recipe contents Throws: Throws an exception if an I/O or syntax error occurs */ -PackageRecipe parsePackageRecipe(string contents, string filename, string parent_name = null) +PackageRecipe parsePackageRecipe(string contents, string filename, string parent_name = null, + string default_package_name = null) { import std.algorithm : endsWith; import dub.internal.vibecompat.data.json; @@ -66,6 +69,8 @@ PackageRecipe ret; + ret.name = default_package_name; + if (filename.endsWith(".json")) parseJson(ret, parseJsonString(contents, filename), parent_name); else if (filename.endsWith(".sdl")) parseSDL(ret, contents, parent_name, filename); else assert(false, "readPackageRecipe called with filename with unknown extension: "~filename); diff --git a/test/1-dynLib-simple/.no_build b/test/1-dynLib-simple/.no_build deleted file mode 100644 index 72679d2..0000000 --- a/test/1-dynLib-simple/.no_build +++ /dev/null @@ -1 +0,0 @@ -Remove me when bug with dynamic libs get fixed. diff --git a/test/1-dynLib-simple/.no_build_gdc b/test/1-dynLib-simple/.no_build_gdc new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/1-dynLib-simple/.no_build_gdc diff --git a/test/1-dynLib-simple/.no_build_ldc2 b/test/1-dynLib-simple/.no_build_ldc2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/1-dynLib-simple/.no_build_ldc2 diff --git a/test/1-dynLib-simple/.no_run b/test/1-dynLib-simple/.no_run new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/1-dynLib-simple/.no_run diff --git a/test/2-dynLib-with-staticLib-dep/.no_build_gdc b/test/2-dynLib-with-staticLib-dep/.no_build_gdc new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/2-dynLib-with-staticLib-dep/.no_build_gdc diff --git a/test/2-dynLib-with-staticLib-dep/.no_build_ldc2 b/test/2-dynLib-with-staticLib-dep/.no_build_ldc2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/2-dynLib-with-staticLib-dep/.no_build_ldc2 diff --git a/test/2-dynLib-with-staticLib-dep/.no_run b/test/2-dynLib-with-staticLib-dep/.no_run new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/2-dynLib-with-staticLib-dep/.no_run diff --git a/test/2-dynLib-with-staticLib-dep/dub.json b/test/2-dynLib-with-staticLib-dep/dub.json new file mode 100644 index 0000000..f0b6043 --- /dev/null +++ b/test/2-dynLib-with-staticLib-dep/dub.json @@ -0,0 +1,7 @@ +{ + "name": "dynlib-with-staticlib-dep", + "targetType": "dynamicLibrary", + "dependencies": { + "staticlib-simple": { "path": "../1-staticLib-simple/" } + } +} diff --git a/test/2-dynLib-with-staticLib-dep/source/dynlib/app.d b/test/2-dynLib-with-staticLib-dep/source/dynlib/app.d new file mode 100644 index 0000000..9741cae --- /dev/null +++ b/test/2-dynLib-with-staticLib-dep/source/dynlib/app.d @@ -0,0 +1,8 @@ +module dynlib.app; +import std.stdio; +import staticlib.app; + +void foo() +{ + entry(); +} diff --git a/test/common.sh b/test/common.sh index f464b3c..b43c656 100644 --- a/test/common.sh +++ b/test/common.sh @@ -7,7 +7,7 @@ local line=$1 local msg=${2:-command failed} local rc=${3:-1} - >&2 echo "$SOURCE_FILE:$1 Error: $msg" + >&2 echo "[ERROR] $SOURCE_FILE:$1 $msg" exit $rc } trap 'die $LINENO' ERR diff --git a/test/issue103-single-file-package.sh b/test/issue103-single-file-package.sh index 693a926..0c23eb2 100755 --- a/test/issue103-single-file-package.sh +++ b/test/issue103-single-file-package.sh @@ -16,3 +16,8 @@ if [ -f single-file-test ]; then die $LINENO 'Shebang invocation produced binary in current directory' fi + +if ${DUB} "issue103-single-file-package-error.d" 2> /dev/null; then + echo "Invalid package comment syntax did not trigger an error." + exit 1 +fi diff --git a/test/run-unittest.sh b/test/run-unittest.sh index f04e487..312c9ea 100755 --- a/test/run-unittest.sh +++ b/test/run-unittest.sh @@ -7,7 +7,7 @@ } function logError() { - echo -e 1>&2 "\033[0;31m"$@"\033[0m" + echo -e 1>&2 "\033[0;31m[ERROR] "$@"\033[0m" any_errors=1 } @@ -20,7 +20,7 @@ export -f die if [ -z ${DUB:-} ]; then - die 'Error: Variable $DUB must be defined to run the tests.' + die 'Variable $DUB must be defined to run the tests.' fi if [ -z ${DC:-} ]; then @@ -28,6 +28,7 @@ DC=dmd fi +DC_BIN=$(basename "$DC") CURR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) for script in $(ls $CURR_DIR/*.sh); do @@ -39,8 +40,10 @@ for pack in $(ls -d $CURR_DIR/*/); do if [ -e $pack/.min_frontend ] && [ ! -z "$FRONTEND" -a "$FRONTEND" \< $(cat $pack/.min_frontend) ]; then continue; fi + # First we build the packages - if [ ! -e $pack/.no_build ]; then # For sourceLibrary + if [ ! -e $pack/.no_build ] && [ ! -e $pack/.no_build_$DC_BIN ]; then # For sourceLibrary + build=1 if [ -e $pack/.fail_build ]; then log "Building $pack, expected failure..." $DUB build --force --root=$pack --compiler=$DC 2>/dev/null && logError "Error: Failure expected, but build passed." @@ -48,16 +51,18 @@ log "Building $pack..." $DUB build --force --root=$pack --compiler=$DC || logError "Build failure." fi + else + build=0 fi - # We run the ones that are supposed to be ran - if [ ! -e $pack/.no_build ] && [ ! -e $pack/.no_run ]; then + # We run the ones that are supposed to be run + if [ $build -eq 1 ] && [ ! -e $pack/.no_run ] && [ ! -e $pack/.no_run_$DC_BIN ]; then log "Running $pack..." $DUB run --force --root=$pack --compiler=$DC || logError "Run failure." fi # Finally, the unittest part - if [ ! -e $pack/.no_build ] && [ ! -e $pack/.no_test ]; then + if [ $build -eq 1 ] && [ ! -e $pack/.no_test ] && [ ! -e $pack/.no_test_$DC_BIN ]; then log "Testing $pack..." $DUB test --force --root=$pack --compiler=$DC || logError "Test failure." fi diff --git a/test/single-file-sdl-default-name.d b/test/single-file-sdl-default-name.d new file mode 100644 index 0000000..e7e7bef --- /dev/null +++ b/test/single-file-sdl-default-name.d @@ -0,0 +1,10 @@ +/++dub.sdl: +dependency "sourcelib-simple" path="1-sourceLib-simple" ++/ +module single; + +void main(string[] args) +{ + import sourcelib.app; + entry(); +} diff --git a/test/single-file-sdl-default-name.sh b/test/single-file-sdl-default-name.sh new file mode 100755 index 0000000..1c61540 --- /dev/null +++ b/test/single-file-sdl-default-name.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -e +cd ${CURR_DIR} +rm -f single-file-sdl-default-name + +${DUB} run --single single-file-sdl-default-name.d --compiler=${DC} +if [ ! -f single-file-sdl-default-name ]; then + echo "Normal invocation did not produce a binary in the current directory" + exit 1 +fi +rm single-file-sdl-default-name