diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e6490ae..e66a488 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ matrix: # Latest stable version, update at will os: [ macOS-10.15, ubuntu-18.04, windows-2019 ] - dc: [ dmd-2.093.1, ldc-1.23.0, dmd-master, ldc-master ] + dc: [ dmd-latest, ldc-latest, dmd-master, ldc-master ] runs-on: ${{ matrix.os }} steps: @@ -61,10 +61,10 @@ env: COVERAGE: false # The value doesn't matter as long as it's > 2.087 - FRONTEND: 2.093.0 + FRONTEND: 2.095.0 run: | dub build --compiler=${{ env.DC }} - dub run --compiler=${{ env.DC }} --single test/issue_2051_running_unittests_from_dub_single_file_packages_fails.d + dub run --compiler=${{ env.DC }} --single test/issue2051_running_unittests_from_dub_single_file_packages_fails.d ./scripts/ci/travis.sh - name: '[Windows] Test' @@ -74,4 +74,4 @@ run: | dub build --compiler=${{ env.DC }} dub test --compiler=${{ env.DC }} - dub run --compiler=${{ env.DC }} --single test\issue_2051_running_unittests_from_dub_single_file_packages_fails.d + dub run --compiler=${{ env.DC }} --single test\issue2051_running_unittests_from_dub_single_file_packages_fails.d diff --git a/.gitignore b/.gitignore index bc0b97f..06b77b4 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ /test/*/*test-library /test/*/*test-application /test/*/exec-simple +/test/issue1474/ext/fortytwo.d # Ignore coverage files cov/ @@ -41,3 +42,7 @@ # Ignore auto-generated docs /docs scripts/man/dub*.1.gz + +# Ignore generated files for examples +/examples/generated-sources/generated-sources +/examples/generated-sources/source/test.d diff --git a/changelog/dmd-linker-dflags.dd b/changelog/dmd-linker-dflags.dd new file mode 100644 index 0000000..3628792 --- /dev/null +++ b/changelog/dmd-linker-dflags.dd @@ -0,0 +1,3 @@ +More 'linker dflags' with DMD + +`-betterC`, `-L…` and `-Xcc=…` `dflags` are now used for linking too. \ No newline at end of file diff --git a/changelog/visuald-copyfiles.dd b/changelog/visuald-copyfiles.dd new file mode 100644 index 0000000..72c8058 --- /dev/null +++ b/changelog/visuald-copyfiles.dd @@ -0,0 +1,5 @@ +copyFiles can now be used in VisualD projects. + +Files that are needed for the application to run can be specified in the `copyFiles` build option, +which causes these files to be copied to the target path. The dub generator for VisualD now replicates +this behaviour, so that this kind of applications can be successfully debugged in Visual Studio. diff --git a/dub.sdl b/dub.sdl index 91894bc..a6bb5d5 100644 --- a/dub.sdl +++ b/dub.sdl @@ -22,13 +22,13 @@ } configuration "library-nonet" { - dependency "vibe-d:http" version=">=0.7.30 <0.10.0" optional=true + dependency "vibe-d:http" version=">=0.9.0 <0.10.0" optional=true targetType "library" excludedSourceFiles "source/app.d" } configuration "dynamic-library-nonet" { - dependency "vibe-d:http" version=">=0.7.30 <0.10.0" optional=true + dependency "vibe-d:http" version=">=0.9.0 <0.10.0" optional=true targetType "dynamicLibrary" excludedSourceFiles "source/app.d" } diff --git a/scripts/ci/travis.sh b/scripts/ci/travis.sh index 8c12c10..067d848 100755 --- a/scripts/ci/travis.sh +++ b/scripts/ci/travis.sh @@ -28,6 +28,7 @@ bash codecov.sh else ./build.d + DUB=`pwd`/bin/dub DC=${DC} dub --single ./test/run-unittest.d DUB=`pwd`/bin/dub DC=${DC} test/run-unittest.sh fi diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 04f5d69..bebdd43 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -14,7 +14,7 @@ import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; -import dub.internal.vibecompat.inet.url; +import dub.internal.vibecompat.inet.path; import dub.package_; import dub.packagemanager; import dub.packagesuppliers; @@ -990,7 +990,7 @@ protected void setupVersionPackage(Dub dub, string str_package_info, string default_build_type = "debug") { - PackageAndVersion package_info = splitPackageName(str_package_info); + PackageAndVersion package_info = splitPackageName(str_package_info); setupPackage(dub, package_info.name, default_build_type, package_info.version_); } @@ -1391,6 +1391,7 @@ settings.tempBuild = m_single; settings.run = true; settings.runArgs = app_args; + settings.single = m_single; dub.testProject(settings, m_buildConfig, NativePath(m_mainFile)); return 0; diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index 2eb8a9a..80331c5 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -8,21 +8,16 @@ module dub.compilers.compiler; public import dub.compilers.buildsettings; -public import dub.dependency : Dependency; +deprecated("Please `import dub.dependency : Dependency` instead") public import dub.dependency : Dependency; public import dub.platform : BuildPlatform, matchesSpecification; -import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; -import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; -import dub.recipe.packagerecipe : ToolchainRequirements; import std.algorithm; import std.array; -import std.conv; import std.exception; import std.process; -import std.typecons : Flag; /** Returns a compiler handler for a given binary name. diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index 6f55ee0..1782831 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -12,14 +12,11 @@ import dub.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; -import dub.recipe.packagerecipe : ToolchainRequirements; import std.algorithm; import std.array; -import std.conv; import std.exception; import std.file; -import std.process; import std.typecons; // Determines whether the specified process is running under WOW64 or an Intel64 of x64 processor. @@ -333,7 +330,13 @@ if (platform.platform.canFind("linux")) args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order by DMD args ~= lflagsToDFlags(settings.lflags); - args ~= settings.dflags.filter!(f => isLinkerDFlag(f)).array; + if (platform.compiler == "ldc") { + // ldmd2: support the full LDC-specific list + extra "-m32mscoff", a superset of the DMD list + import dub.compilers.ldc : LDCCompiler; + args ~= settings.dflags.filter!(f => f == "-m32mscoff" || LDCCompiler.isLinkerDFlag(f)).array; + } else { + args ~= settings.dflags.filter!(f => isLinkerDFlag(f)).array; + } auto res_file = getTempFile("dub-build", ".lnk"); std.file.write(res_file.toNativeString(), escapeArgs(args).join("\n")); @@ -352,14 +355,15 @@ return args.map!(s => s.canFind(' ') ? "\""~s~"\"" : s); } - private static bool isLinkerDFlag(string arg) + static bool isLinkerDFlag(string arg) { switch (arg) { - default: - if (arg.startsWith("-defaultlib=")) return true; - return false; - case "-g", "-gc", "-m32", "-m64", "-shared", "-lib", "-m32mscoff": + case "-g", "-gc", "-m32", "-m64", "-shared", "-lib", "-m32mscoff", "-betterC": return true; + default: + return arg.startsWith("-L") + || arg.startsWith("-Xcc=") + || arg.startsWith("-defaultlib="); } } } diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index cec2dbc..f615cbb 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -12,11 +12,9 @@ import dub.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; -import dub.recipe.packagerecipe : ToolchainRequirements; import std.algorithm; import std.array; -import std.conv; import std.exception; import std.file; import std.process; diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 2fbe362..c4ba3ec 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -12,14 +12,11 @@ import dub.internal.utils; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; -import dub.recipe.packagerecipe : ToolchainRequirements; import std.algorithm; import std.array; -import std.conv; import std.exception; import std.file; -import std.process; import std.typecons; @@ -271,7 +268,7 @@ return args.map!(s => s.canFind(' ') ? "\""~s~"\"" : s); } - private static bool isLinkerDFlag(string arg) + static bool isLinkerDFlag(string arg) { if (arg.length > 2 && arg.startsWith("--")) arg = arg[1 .. $]; // normalize to 1 leading hyphen diff --git a/source/dub/dependency.d b/source/dub/dependency.d index c9b1515..f41c458 100644 --- a/source/dub/dependency.d +++ b/source/dub/dependency.d @@ -11,17 +11,14 @@ import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; -import dub.internal.vibecompat.inet.url; +import dub.internal.vibecompat.inet.path; import dub.package_; import dub.semver; import std.algorithm; import std.array; import std.exception; -import std.regex; import std.string; -import std.typecons; -static import std.compiler; /** Encapsulates the name of a package along with its dependency specification. diff --git a/source/dub/dependencyresolver.d b/source/dub/dependencyresolver.d index eb4462c..8ec82cc 100644 --- a/source/dub/dependencyresolver.d +++ b/source/dub/dependencyresolver.d @@ -14,8 +14,7 @@ import std.array : appender, array, join; import std.conv : to; import std.exception : enforce; -import std.typecons : Nullable; -import std.string : format, indexOf, lastIndexOf; +import std.string : format, lastIndexOf; /** Resolves dependency graph with multiple configurations per package. diff --git a/source/dub/dub.d b/source/dub/dub.d index e88ece2..c11737b 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -660,13 +660,15 @@ // prepare the list of tested modules string[] import_modules; + if (settings.single) + lbuildsettings.importPaths ~= NativePath(mainfil).parentPath.toNativeString; foreach (file; lbuildsettings.sourceFiles) { if (file.endsWith(".d")) { auto fname = NativePath(file).head.name; NativePath msf = NativePath(mainfil); if (msf.absolute) msf = msf.relativeTo(m_project.rootPackage.path); - if (NativePath(file).relativeTo(m_project.rootPackage.path) == msf) { + if (!settings.single && NativePath(file).relativeTo(m_project.rootPackage.path) == msf) { logWarn("Excluding main source file %s from test.", mainfil); tcinfo.excludedSourceFiles[""] ~= mainfil; continue; @@ -686,7 +688,7 @@ import dub.generators.build : computeBuildName; mainfile = m_project.rootPackage.path ~ format(".dub/code/%s_dub_test_root.d", computeBuildName(test_config, settings, import_modules)); } - + mkdirRecurse(mainfile.parentPath.toNativeString()); bool regenerateMainFile = settings.force || !existsFile(mainfile); @@ -1379,7 +1381,6 @@ { import std.file : thisExePath; import std.path : buildPath, dirName, expandTilde, isAbsolute, isDirSeparator; - import std.process : environment; import std.range : front; // Env takes precedence diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 649fbe0..3f13ddb 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -528,29 +528,19 @@ if (buildsettings.workingDirectory.length) { runcwd = NativePath(buildsettings.workingDirectory); if (!runcwd.absolute) runcwd = cwd ~ runcwd; - logDiagnostic("Switching to %s", runcwd.toNativeString()); - chdir(runcwd.toNativeString()); } - scope(exit) chdir(cwd.toNativeString()); if (!exe_file_path.absolute) exe_file_path = cwd ~ exe_file_path; - auto exe_path_string = exe_file_path.relativeTo(runcwd).toNativeString(); - version (Posix) { - if (!exe_path_string.startsWith(".") && !exe_path_string.startsWith("/")) - exe_path_string = "./" ~ exe_path_string; - } - version (Windows) { - if (!exe_path_string.startsWith(".") && (exe_path_string.length < 2 || exe_path_string[1] != ':')) - exe_path_string = ".\\" ~ exe_path_string; - } runPreRunCommands(m_project.rootPackage, m_project, settings, buildsettings); - logInfo("Running %s %s", exe_path_string, run_args.join(" ")); + logInfo("Running %s %s", exe_file_path.relativeTo(runcwd), run_args.join(" ")); if (settings.runCallback) { - auto res = execute(exe_path_string ~ run_args); + auto res = execute([ exe_file_path.toNativeString() ] ~ run_args, + null, Config.none, size_t.max, runcwd.toNativeString()); settings.runCallback(res.status, res.output); settings.targetExitStatus = res.status; runPostRunCommands(m_project.rootPackage, m_project, settings, buildsettings); } else { - auto prg_pid = spawnProcess(exe_path_string ~ run_args); + auto prg_pid = spawnProcess([ exe_file_path.toNativeString() ] ~ run_args, + null, Config.none, runcwd.toNativeString()); auto result = prg_pid.wait(); settings.targetExitStatus = result; runPostRunCommands(m_project.rootPackage, m_project, settings, buildsettings); diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index 9ab99e7..3eeb807 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -20,8 +20,7 @@ import dub.project; import std.algorithm : map, filter, canFind, balancedParens; -import std.array : array; -import std.array; +import std.array : array, appender, join; import std.exception; import std.file; import std.string; @@ -120,7 +119,10 @@ buildsettings.processVars(m_project, pack, pack.getBuildSettings(settings.platform, configs[pack.name]), settings, true); bool generate_binary = !(buildsettings.options & BuildOption.syntaxOnly); auto bs = &targets[m_project.rootPackage.name].buildSettings; - auto targetPath = (m_tempTargetExecutablePath.empty) ? NativePath(bs.targetPath) : m_tempTargetExecutablePath; + auto targetPath = !m_tempTargetExecutablePath.empty ? m_tempTargetExecutablePath : + !bs.targetPath.empty ? NativePath(bs.targetPath) : + NativePath(buildsettings.targetPath); + finalizeGeneration(pack, m_project, settings, buildsettings, targetPath, generate_binary); } @@ -670,6 +672,62 @@ /** + Calls delegates on files and directories in the given path that match any globs. +*/ +void findFilesMatchingGlobs(in NativePath path, in string[] globList, void delegate(string file) addFile, void delegate(string dir) addDir) +{ + import std.path : globMatch; + + string[] globs; + foreach (f; globList) + { + if (f.canFind("*", "?") || + (f.canFind("{") && f.balancedParens('{', '}')) || + (f.canFind("[") && f.balancedParens('[', ']'))) + { + globs ~= f; + } + else + { + if (f.isDir) + addDir(f); + else + addFile(f); + } + } + if (globs.length) // Search all files for glob matches + foreach (f; dirEntries(path.toNativeString(), SpanMode.breadth)) + foreach (glob; globs) + if (f.name().globMatch(glob)) + { + if (f.isDir) + addDir(f); + else + addFile(f); + break; + } +} + + +/** + Calls delegates on files in the given path that match any globs. + + If a directory matches a glob, the delegate is called on all existing files inside it recursively + in depth-first pre-order. +*/ +void findFilesMatchingGlobs(in NativePath path, in string[] globList, void delegate(string file) addFile) +{ + void addDir(string dir) + { + foreach (f; dirEntries(dir, SpanMode.breadth)) + addFile(f); + } + + findFilesMatchingGlobs(path, globList, addFile, &addDir); +} + + +/** Runs pre-build commands and performs other required setup before project files are generated. */ private void prepareGeneration(in Package pack, in Project proj, in GeneratorSettings settings, @@ -687,8 +745,6 @@ private void finalizeGeneration(in Package pack, in Project proj, in GeneratorSettings settings, in BuildSettings buildsettings, NativePath target_path, bool generate_binary) { - import std.path : globMatch; - if (buildsettings.postGenerateCommands.length && !isRecursiveInvocation(pack.name)) { logInfo("Running post-generate commands for %s...", pack.name); runBuildCommands(buildsettings.postGenerateCommands, pack, proj, settings, buildsettings); @@ -744,40 +800,7 @@ } catch(Exception e) logWarn("Failed to copy %s to %s: %s", src.toNativeString(), dst.toNativeString(), e.msg); } logInfo("Copying files for %s...", pack.name); - string[] globs; - foreach (f; buildsettings.copyFiles) - { - if (f.canFind("*", "?") || - (f.canFind("{") && f.balancedParens('{', '}')) || - (f.canFind("[") && f.balancedParens('[', ']'))) - { - globs ~= f; - } - else - { - if (f.isDir) - tryCopyDir(f); - else - tryCopyFile(f); - } - } - if (globs.length) // Search all files for glob matches - { - foreach (f; dirEntries(pack.path.toNativeString(), SpanMode.breadth)) - { - foreach (glob; globs) - { - if (f.name().globMatch(glob)) - { - if (f.isDir) - tryCopyDir(f); - else - tryCopyFile(f); - break; - } - } - } - } + findFilesMatchingGlobs(pack.path, buildsettings.copyFiles, &tryCopyFile, &tryCopyDir); } } diff --git a/source/dub/generators/sublimetext.d b/source/dub/generators/sublimetext.d index 1bf2187..aaf5cf0 100644 --- a/source/dub/generators/sublimetext.d +++ b/source/dub/generators/sublimetext.d @@ -17,11 +17,7 @@ import std.algorithm; import std.array; -import std.compiler; import std.file; -import std.path; -import std.range; -import std.string; class SublimeTextGenerator : ProjectGenerator { diff --git a/source/dub/generators/visuald.d b/source/dub/generators/visuald.d index 17ec093..6db18ab 100644 --- a/source/dub/generators/visuald.d +++ b/source/dub/generators/visuald.d @@ -156,7 +156,8 @@ auto ret = appender!(char[])(); - auto project_file_dir = m_project.rootPackage.path ~ projFileName(packname).parentPath; + auto root_package_path = m_project.rootPackage.path; + auto project_file_dir = root_package_path ~ projFileName(packname).parentPath; ret.put("\n"); ret.formattedWrite(" %s\n", guid(packname)); @@ -168,36 +169,38 @@ // Add all files auto files = targets[packname].buildSettings; SourceFile[string] sourceFiles; - void addSourceFile(NativePath file_path, NativePath structure_path, bool build) + void addSourceFile(NativePath file_path, NativePath structure_path, SourceFile.Action action) { auto key = file_path.toString(); auto sf = sourceFiles.get(key, SourceFile.init); sf.filePath = file_path; - if (!sf.build) { - sf.build = build; + if (sf.action == SourceFile.Action.none) { + sf.action = action; sf.structurePath = structure_path; } sourceFiles[key] = sf; } - void addFile(string s, bool build) { + void addFile(string s, SourceFile.Action action) { auto sp = NativePath(s); assert(sp.absolute, format("Source path in %s expected to be absolute: %s", packname, s)); //if( !sp.absolute ) sp = pack.path ~ sp; - addSourceFile(sp.relativeTo(project_file_dir), determineStructurePath(sp, targets[packname]), build); + addSourceFile(sp.relativeTo(project_file_dir), determineStructurePath(sp, targets[packname]), action); } foreach (p; targets[packname].packages) if (!p.recipePath.empty) - addFile(p.recipePath.toNativeString(), false); + addFile(p.recipePath.toNativeString(), SourceFile.Action.none); if (files.targetType == TargetType.staticLibrary) - foreach(s; files.sourceFiles.filter!(s => !isLinkerFile(settings.platform, s))) addFile(s, true); + foreach(s; files.sourceFiles.filter!(s => !isLinkerFile(settings.platform, s))) addFile(s, SourceFile.Action.build); else - foreach(s; files.sourceFiles.filter!(s => !s.endsWith(".lib"))) addFile(s, true); + foreach(s; files.sourceFiles.filter!(s => !s.endsWith(".lib"))) addFile(s, SourceFile.Action.build); - foreach(s; files.importFiles) addFile(s, false); - foreach(s; files.stringImportFiles) addFile(s, false); + foreach(s; files.importFiles) addFile(s, SourceFile.Action.none); + foreach(s; files.stringImportFiles) addFile(s, SourceFile.Action.none); + findFilesMatchingGlobs(root_package_path, files.copyFiles, s => addFile(s, SourceFile.Action.copy)); + findFilesMatchingGlobs(root_package_path, files.extraDependencyFiles, s => addFile(s, SourceFile.Action.none)); // Create folders and files ret.formattedWrite(" ", getPackageFileName(packname)); @@ -220,7 +223,18 @@ ret.formattedWrite("\n ", cur[same + idx].name); lastFolder = cur; } - ret.formattedWrite("\n ", source.build ? "" : "tool=\"None\" ", source.filePath.toNativeString()); + final switch (source.action) with (SourceFile.Action) + { + case none: + ret.formattedWrite("\n ", source.filePath.toNativeString()); + break; + case build: + ret.formattedWrite("\n ", source.filePath.toNativeString()); + break; + case copy: + ret.formattedWrite("\n ", source.filePath.toNativeString()); + break; + } } // Finalize all open folders foreach(unused; 0..lastFolder.length) @@ -256,6 +270,9 @@ return ret; } + if (buildsettings.targetType == TargetType.none) + return; + foreach(architecture; settings.platform.architecture) { auto arch = architecture.vsArchitecture; ret.formattedWrite(" \n", to!string(type), arch); @@ -457,9 +474,10 @@ private struct SourceFile { NativePath structurePath; NativePath filePath; - bool build; + enum Action { none, build, copy }; + Action action = Action.none; - size_t toHash() const nothrow @trusted { return structurePath.toHash() ^ filePath.toHash() ^ (build * 0x1f3e7b2c); } + size_t toHash() const nothrow @trusted { return structurePath.toHash() ^ filePath.toHash() ^ (action * 0x1f3e7b2c); } int opCmp(ref const SourceFile rhs) const { return sortOrder(this, rhs); } // "a < b" for folder structures (deepest folder first, else lexical) private final static int sortOrder(ref const SourceFile a, ref const SourceFile b) { diff --git a/source/dub/init.d b/source/dub/init.d index a1fb3d9..876b791 100644 --- a/source/dub/init.d +++ b/source/dub/init.d @@ -128,7 +128,11 @@ auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["::1", "127.0.0.1"]; - listenHTTP(settings, &hello); + auto listener = listenHTTP(settings, &hello); + scope (exit) + { + listener.stopListening(); + } logInfo("Please open http://127.0.0.1:8080/ in your browser."); runApplication(); diff --git a/source/dub/internal/sdlang/lexer.d b/source/dub/internal/sdlang/lexer.d index dd99719..3eb44a8 100644 --- a/source/dub/internal/sdlang/lexer.d +++ b/source/dub/internal/sdlang/lexer.d @@ -17,7 +17,6 @@ import std.typecons; import std.uni; import std.utf; -import std.variant; import dub.internal.sdlang.exception; import dub.internal.sdlang.symbol; diff --git a/source/dub/internal/sdlang/parser.d b/source/dub/internal/sdlang/parser.d index 023dffc..24bb16e 100644 --- a/source/dub/internal/sdlang/parser.d +++ b/source/dub/internal/sdlang/parser.d @@ -7,6 +7,7 @@ else: import std.file; +import std.variant : Algebraic; import dub.internal.libInputVisitor; @@ -118,7 +119,7 @@ } /// The element of the InputRange returned by pullParseFile and pullParseSource: -alias ParserEvent = std.variant.Algebraic!( +alias ParserEvent = Algebraic!( FileStartEvent, FileEndEvent, TagStartEvent, diff --git a/source/dub/internal/vibecompat/inet/path.d b/source/dub/internal/vibecompat/inet/path.d index c25878a..0872b14 100644 --- a/source/dub/internal/vibecompat/inet/path.d +++ b/source/dub/internal/vibecompat/inet/path.d @@ -8,7 +8,6 @@ module dub.internal.vibecompat.inet.path; version (Have_vibe_core) public import vibe.core.path; -else version (Have_vibe_d_core) public import vibe.inet.path; else: import std.algorithm; diff --git a/source/dub/internal/vibecompat/inet/url.d b/source/dub/internal/vibecompat/inet/url.d index eb302e5..34b2ec7 100644 --- a/source/dub/internal/vibecompat/inet/url.d +++ b/source/dub/internal/vibecompat/inet/url.d @@ -9,7 +9,7 @@ public import dub.internal.vibecompat.inet.path; -version (Have_vibe_d_core) public import vibe.inet.url; +version (Have_vibe_d_inet) public import vibe.inet.url; else: import std.algorithm; diff --git a/source/dub/package_.d b/source/dub/package_.d index 98c295b..bbcf973 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -19,7 +19,7 @@ import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; -import dub.internal.vibecompat.inet.url; +import dub.internal.vibecompat.inet.path; import std.algorithm; import std.array; diff --git a/source/dub/project.d b/source/dub/project.d index 2f96a8e..d406421 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -14,7 +14,7 @@ import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; -import dub.internal.vibecompat.inet.url; +import dub.internal.vibecompat.inet.path; import dub.package_; import dub.packagemanager; import dub.generators.generator; @@ -653,7 +653,7 @@ if (shallow && pkg !is m_rootPackage) psettings.sourceFiles = null; processVars(dst, this, pkg, psettings, gsettings); - if (psettings.importPaths.empty) + if (!gsettings.single && psettings.importPaths.empty) logWarn(`Package %s (configuration "%s") defines no import paths, use {"importPaths": [...]} or the default package directory structure to fix this.`, pkg.name, configs[pkg.name]); if (psettings.mainSourceFile.empty && pkg is m_rootPackage && psettings.targetType == TargetType.executable) logWarn(`Executable configuration "%s" of package %s defines no main source file, this may cause certain build modes to fail. Add an explicit "mainSourceFile" to the package description to fix this.`, configs[pkg.name], pkg.name); diff --git a/source/dub/recipe/packagerecipe.d b/source/dub/recipe/packagerecipe.d index f03a943..a7a3522 100644 --- a/source/dub/recipe/packagerecipe.d +++ b/source/dub/recipe/packagerecipe.d @@ -13,7 +13,7 @@ import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; -import dub.internal.vibecompat.inet.url; +import dub.internal.vibecompat.inet.path; import std.algorithm : findSplit, sort; import std.array : join, split; diff --git a/source/dub/semver.d b/source/dub/semver.d index e4c0143..68978d8 100644 --- a/source/dub/semver.d +++ b/source/dub/semver.d @@ -15,7 +15,6 @@ */ module dub.semver; -import std.range; import std.string; import std.algorithm : max; import std.conv; diff --git a/test/issue1053-extra-files-visuald.sh b/test/issue1053-extra-files-visuald.sh new file mode 100755 index 0000000..4c8d979 --- /dev/null +++ b/test/issue1053-extra-files-visuald.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +. $(dirname "${BASH_SOURCE[0]}")/common.sh +cd "${CURR_DIR}/issue1053-extra-files-visuald" || die "Could not cd." + +"$DUB" generate visuald + +if [ `grep -c -e "saturate.vert" .dub/extra_files.visualdproj` -ne 1 ]; then + die $LINENO 'Regression of issue #1053.' +fi + +if [ `grep -c -e "warp.geom" .dub/extra_files.visualdproj` -ne 1 ]; then + die $LINENO 'Regression of issue #1053.' +fi + +if [ `grep -c -e "LICENSE.txt" .dub/extra_files.visualdproj` -ne 1 ]; then + die $LINENO 'Regression of issue #1053.' +fi + +if [ `grep -c -e "README.txt" .dub/extra_files.visualdproj` -ne 1 ]; then + die $LINENO 'Regression of issue #1053.' +fi + +if [ `grep -e "README.txt" .dub/extra_files.visualdproj | grep -c -e 'copy /Y $(InputPath) $(TargetDir)'` -ne 1 ]; then + die $LINENO 'Copying of copyFiles seems broken for visuald.' +fi diff --git a/test/issue1053-extra-files-visuald/dub.json b/test/issue1053-extra-files-visuald/dub.json new file mode 100644 index 0000000..a24bc8d --- /dev/null +++ b/test/issue1053-extra-files-visuald/dub.json @@ -0,0 +1,11 @@ +{ + "name": "extra_files", + "targetType": "executable", + "extraDependencyFiles": [ + "shaders/*" + ], + "copyFiles": [ + "text/LICENSE.txt", + "text/README.txt" + ] +} diff --git a/test/issue1053-extra-files-visuald/shaders/saturate.vert b/test/issue1053-extra-files-visuald/shaders/saturate.vert new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue1053-extra-files-visuald/shaders/saturate.vert diff --git a/test/issue1053-extra-files-visuald/shaders/warp.geom b/test/issue1053-extra-files-visuald/shaders/warp.geom new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue1053-extra-files-visuald/shaders/warp.geom diff --git a/test/issue1053-extra-files-visuald/source/app.d b/test/issue1053-extra-files-visuald/source/app.d new file mode 100644 index 0000000..ab73b3a --- /dev/null +++ b/test/issue1053-extra-files-visuald/source/app.d @@ -0,0 +1 @@ +void main() {} diff --git a/test/issue1053-extra-files-visuald/text/LICENSE.txt b/test/issue1053-extra-files-visuald/text/LICENSE.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue1053-extra-files-visuald/text/LICENSE.txt diff --git a/test/issue1053-extra-files-visuald/text/README.txt b/test/issue1053-extra-files-visuald/text/README.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue1053-extra-files-visuald/text/README.txt diff --git a/test/issue2051_running_unittests_from_dub_single_file_packages_fails.d b/test/issue2051_running_unittests_from_dub_single_file_packages_fails.d new file mode 100644 index 0000000..2327db3 --- /dev/null +++ b/test/issue2051_running_unittests_from_dub_single_file_packages_fails.d @@ -0,0 +1,99 @@ +/+ dub.sdl: + name "issue2051_running_unittests_from_dub_single_file_packages_fails" + +/ + +import std.algorithm : any; +import std.conv : text; +import std.file : tempDir; +import std.stdio : File, writeln; +import std.string : lineSplitter; +import std.path : buildPath; +import std.process : environment, executeShell; + +auto executeCommand(string command) +{ + import std.exception : enforce; + + auto dub = executeShell(command); + writeln("--- dub output:"); + foreach(line; dub.output.lineSplitter) + writeln("\t", line); + writeln("--- end of dub output"); + + return dub.status; +} + +int main() +{ + auto dub = environment.get("DUB"); + if (!dub.length) + dub = buildPath(".", "bin", "dub"); + + string filename; + // check if the single file package with dependency compiles and runs + { + filename = tempDir.buildPath("issue2051_success.d"); + auto f = File(filename, "w"); + f.write( +`#!/usr/bin/env dub +/+ dub.sdl: + name "issue2051" + dependency "taggedalgebraic" version="~>0.11.0" ++/ + +version(unittest) {} +else void main() +{ +} + +unittest +{ + import taggedalgebraic; + + static union Base { + int i; + string str; + } + + auto dummy = TaggedAlgebraic!Base(1721); + assert(dummy == 1721); +} +` ); + } + + const rc1 = text(dub, " test --single ", filename).executeCommand; + if (rc1) + writeln("\nError. Unittests failed."); + else + writeln("\nOk. Unittest passed."); + + // Check if dub `test` command runs unittests for single file package + { + filename = tempDir.buildPath("issue2051_fail.d"); + auto f = File(filename, "w"); + f.write( +`#!/usr/bin/env dub +/+ dub.sdl: + name "issue2051" ++/ + +version(unittest) {} +else void main() +{ +} + +unittest +{ + assert(0); +} +` ); + } + + const rc2 = text(dub, " test --single ", filename).executeCommand; + if (rc2) + writeln("\nOk. Unittests failed."); + else + writeln("\nError. Unittest passed."); + + return rc1 | !rc2; +} \ No newline at end of file diff --git a/test/issue2085-target-none-visuald.sh b/test/issue2085-target-none-visuald.sh new file mode 100755 index 0000000..8012f5a --- /dev/null +++ b/test/issue2085-target-none-visuald.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +. $(dirname "${BASH_SOURCE[0]}")/common.sh +cd "${CURR_DIR}/issue2085-target-none-visuald" || die "Could not cd." + +"$DUB" generate visuald + +if grep -c -e \"\" .dub/root.visualdproj; then + die $LINENO 'Regression of issue #2085.' +fi diff --git a/test/issue2085-target-none-visuald/.no_build b/test/issue2085-target-none-visuald/.no_build new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue2085-target-none-visuald/.no_build diff --git a/test/issue2085-target-none-visuald/.no_run b/test/issue2085-target-none-visuald/.no_run new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue2085-target-none-visuald/.no_run diff --git a/test/issue2085-target-none-visuald/dub.json b/test/issue2085-target-none-visuald/dub.json new file mode 100644 index 0000000..70862f5 --- /dev/null +++ b/test/issue2085-target-none-visuald/dub.json @@ -0,0 +1,10 @@ +{ + "name": "root", + "targetType": "none", + "dependencies": { + "root:sub": "*" + }, + "subPackages": [ + "sub" + ] +} diff --git a/test/issue2085-target-none-visuald/sub/dub.json b/test/issue2085-target-none-visuald/sub/dub.json new file mode 100644 index 0000000..fd8a432 --- /dev/null +++ b/test/issue2085-target-none-visuald/sub/dub.json @@ -0,0 +1,5 @@ +{ + "name": "sub", + "targetType": "executable", + "targetName": "sub" +} diff --git a/test/issue2085-target-none-visuald/sub/source/app.d b/test/issue2085-target-none-visuald/sub/source/app.d new file mode 100644 index 0000000..ab73b3a --- /dev/null +++ b/test/issue2085-target-none-visuald/sub/source/app.d @@ -0,0 +1 @@ +void main() {} diff --git a/test/issue2086-copyfiles-subpackage-targetpath.sh b/test/issue2086-copyfiles-subpackage-targetpath.sh new file mode 100755 index 0000000..9502f8c --- /dev/null +++ b/test/issue2086-copyfiles-subpackage-targetpath.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +. $(dirname "${BASH_SOURCE[0]}")/common.sh +cd "${CURR_DIR}/issue2086-copyfiles-subpackage-targetpath" || die "Could not cd." + +rm -f "sub/to_be_deployed.txt" + +"$DUB" build +./sub/sub diff --git a/test/issue2086-copyfiles-subpackage-targetpath/.no_run b/test/issue2086-copyfiles-subpackage-targetpath/.no_run new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue2086-copyfiles-subpackage-targetpath/.no_run diff --git a/test/issue2086-copyfiles-subpackage-targetpath/dub.json b/test/issue2086-copyfiles-subpackage-targetpath/dub.json new file mode 100644 index 0000000..70862f5 --- /dev/null +++ b/test/issue2086-copyfiles-subpackage-targetpath/dub.json @@ -0,0 +1,10 @@ +{ + "name": "root", + "targetType": "none", + "dependencies": { + "root:sub": "*" + }, + "subPackages": [ + "sub" + ] +} diff --git a/test/issue2086-copyfiles-subpackage-targetpath/sub/dub.json b/test/issue2086-copyfiles-subpackage-targetpath/sub/dub.json new file mode 100644 index 0000000..76bfce6 --- /dev/null +++ b/test/issue2086-copyfiles-subpackage-targetpath/sub/dub.json @@ -0,0 +1,8 @@ +{ + "name": "sub", + "targetType": "executable", + "targetName": "sub", + "copyFiles": [ + "files/*" + ] +} diff --git a/test/issue2086-copyfiles-subpackage-targetpath/sub/files/to_be_deployed.txt b/test/issue2086-copyfiles-subpackage-targetpath/sub/files/to_be_deployed.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue2086-copyfiles-subpackage-targetpath/sub/files/to_be_deployed.txt diff --git a/test/issue2086-copyfiles-subpackage-targetpath/sub/source/app.d b/test/issue2086-copyfiles-subpackage-targetpath/sub/source/app.d new file mode 100644 index 0000000..9dc16f9 --- /dev/null +++ b/test/issue2086-copyfiles-subpackage-targetpath/sub/source/app.d @@ -0,0 +1,9 @@ +import std.exception: enforce; +import std.file: exists, thisExePath; +import std.path: dirName, buildPath; + +void main() +{ + string filePath = buildPath(thisExePath.dirName, "to_be_deployed.txt"); + enforce(filePath.exists); +} diff --git a/test/issue_2051_running_unittests_from_dub_single_file_packages_fails.d b/test/issue_2051_running_unittests_from_dub_single_file_packages_fails.d deleted file mode 100644 index 08a45ad..0000000 --- a/test/issue_2051_running_unittests_from_dub_single_file_packages_fails.d +++ /dev/null @@ -1,76 +0,0 @@ -/+ dub.sdl: - name "issue_2051_running_unittests_from_dub_single_file_packages_fails" - +/ - -import std.algorithm : any; -import std.conv : text; -import std.file : tempDir; -import std.stdio : File, writeln; -import std.string : lineSplitter; -import std.path : buildPath; -import std.process : environment, executeShell; - -auto executeCommand(string command) -{ - import std.exception : enforce; - - auto dub = executeShell(command); - writeln("--- dub output:"); - foreach(line; dub.output.lineSplitter) - writeln("\t", line); - writeln("--- end of dub output"); - - enforce(dub.status == 0, "couldn't build the project, see above"); - - return dub.output; -} - -/// check dub output to determine rebuild has not been triggered -auto checkUnittestsResult(string output) -{ - if (output.lineSplitter.any!(a=> a == "All unit tests have been run successfully.")) - { - writeln("\nOk. Unittest passed."); - return 0; - } - else - { - writeln("\nError. Unittests failed."); - return 1; - } -} - -int main() -{ - auto dub = environment.get("DUB"); - if (!dub.length) - dub = buildPath(".", "bin", "dub"); - - string filename; - // create test_project - { - filename = tempDir.buildPath("issue_2051.d"); - auto f = File(filename, "w"); - f.write( -`#!/usr/bin/env dub -/+ dub.sdl: - name "issue2051" -+/ - -version(unittest) {} -else void main() -{ -} - -unittest -{ - auto input = [1721]; - assert(input[0] == 1721); -} -` ); - } - - return text(dub, " test --single ", filename) - .executeCommand - .checkUnittestsResult; -} \ No newline at end of file diff --git a/test/run-unittest.d b/test/run-unittest.d new file mode 100644 index 0000000..5575743 --- /dev/null +++ b/test/run-unittest.d @@ -0,0 +1,111 @@ +#!/usr/bin/env dub +/+dub.sdl: + name: run_unittest + targetName: run-unittest ++/ +module run_unittest; + +/// Name of the log file +enum logFile = "test.log"; + +/// has true if some test fails +bool any_errors = false; + +/// prints (non error) message to standard output and log file +void log(Args...)(Args args) + if (Args.length) +{ + import std.conv : text; + import std.stdio : File, stdout; + + const str = text("[INFO] ", args); + version(Windows) stdout.writeln(str); + else stdout.writeln("\033[0;33m", str, "\033[0m"); + stdout.flush; + File(logFile, "a").writeln(str); +} + +/// prints error message to standard error stream and log file +/// and set any_errors var to true value to indicate that some +/// test fails +void logError(Args...)(Args args) +{ + import std.conv : text; + import std.stdio : File, stderr; + + const str = text("[ERROR] ", args); + version(Windows) stderr.writeln(str); + else stderr.writeln("\033[0;31m", str, "\033[0m"); + stderr.flush; + File(logFile, "a").writeln(str); + any_errors = true; +} + +int main(string[] args) +{ + import std.algorithm : among; + import std.file : dirEntries, DirEntry, exists, getcwd, readText, SpanMode; + import std.format : format; + import std.stdio : File, writeln; + import std.path : absolutePath, buildNormalizedPath, baseName, dirName; + import std.process : environment, spawnProcess, wait; + + //** if [ -z ${DUB:-} ]; then + //** die $LINENO 'Variable $DUB must be defined to run the tests.' + //** fi + auto dub = environment.get("DUB", ""); + writeln("DUB: ", dub); + if (dub == "") + { + logError(`Environment variable "DUB" must be defined to run the tests.`); + return 1; + } + + //** if [ -z ${DC:-} ]; then + //** log '$DC not defined, assuming dmd...' + //** DC=dmd + //** fi + auto dc = environment.get("DC", ""); + if (dc == "") + { + log(`Environment variable "DC" not defined, assuming dmd...`); + dc = "dmd"; + } + + // Clear log file + { + File(logFile, "w"); + } + + //** DC_BIN=$(basename "$DC") + //** CURR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + //** FRONTEND="${FRONTEND:-}" + const dc_bin = baseName(dc); + const curr_dir = args[0].absolutePath.dirName.buildNormalizedPath; + const frontend = environment.get("FRONTEND", ""); + + //** if [ "$#" -gt 0 ]; then FILTER=$1; else FILTER=".*"; fi + auto filter = (args.length > 1) ? args[1] : "*"; + + version(linux) + { + //** for script in $(ls $CURR_DIR/*.sh); do + //** if [[ ! "$script" =~ $FILTER ]]; then continue; fi + //** if [ "$script" = "$(gnureadlink ${BASH_SOURCE[0]})" ] || [ "$(basename $script)" = "common.sh" ]; 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 + foreach(DirEntry script; dirEntries(curr_dir, (args.length > 1) ? args[1] : "*.sh", SpanMode.shallow)) + { + if (baseName(script.name).among("run-unittest.sh", "common.sh")) continue; + const min_frontend = script.name ~ ".min_frontend"; + if (exists(min_frontend) && frontend.length && frontend < min_frontend.readText) continue; + log("Running " ~ script ~ "..."); + if (spawnProcess(script.name, ["DUB":dub, "DC":dc, "CURR_DIR":curr_dir]).wait) + logError("Script failure."); + } + } + + return any_errors; +} diff --git a/test/run-unittest.sh b/test/run-unittest.sh index 943f8ef..a7c3427 100755 --- a/test/run-unittest.sh +++ b/test/run-unittest.sh @@ -39,14 +39,6 @@ if [ "$#" -gt 0 ]; then FILTER=$1; else FILTER=".*"; fi -for script in $(ls $CURR_DIR/*.sh); do - if [[ ! "$script" =~ $FILTER ]]; then continue; fi - if [ "$script" = "$(gnureadlink ${BASH_SOURCE[0]})" ] || [ "$(basename $script)" = "common.sh" ]; 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 - for pack in $(ls -d $CURR_DIR/*/); do if [[ ! "$pack" =~ $FILTER ]]; then continue; fi if [ -e $pack/.min_frontend ] && [ ! -z "$FRONTEND" -a "$FRONTEND" \< $(cat $pack/.min_frontend) ]; then continue; fi