Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package dub for openSUSE:Factory checked in at 2026-11-03 17:59:17 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/dub (Old) and /work/SRC/openSUSE:Factory/.dub.new.1257 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "dub" Tue Nov 3 17:59:17 2026 rev:30 rq:1394639 version:1.43.0 Changes: -------- --- /work/SRC/openSUSE:Factory/dub/dub.changes 2026-08-15 22:42:06.613720792 +0200 +++ /work/SRC/openSUSE:Factory/.dub.new.1257/dub.changes 2026-11-03 18:03:38.495683516 +0100 @@ -1,0 +2,12 @@ +Sun Nov 1 16:22:51 UTC 2026 - Andrea Manzini <[email protected]> + +- Update to 1.43.0: + * Added `dub generate ninja` command introducing Ninja build + backend. + * Fixed `--conf` options not being passed to LDC's linker + step. + * Fixed Windows response file quoting for paths with trailing + backslashes. + * Repacked source tarball to unbundle prebuilt Windows DLLs. + +------------------------------------------------------------------- Old: ---- dub-1.42.0.tar.gz New: ---- dub-1.43.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ dub.spec ++++++ --- /var/tmp/diff_new_pack.T1eLvG/_old 2026-11-03 18:03:40.021747398 +0100 +++ /var/tmp/diff_new_pack.T1eLvG/_new 2026-11-03 18:03:40.025747566 +0100 @@ -23,13 +23,14 @@ %bcond_with dcompiler_dmd %endif Name: dub -Version: 1.42.0 +Version: 1.43.0 Release: 0 Summary: Package manager and meta build tool for the D programming language License: MIT -Group: Development/Languages/Other URL: https://code.dlang.org -Source: https://github.com/dlang/dub/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz +# Upstream tarball bundles Windows DLLs in bin/ (libcurl.dll, libeay32.dll, ssleay32.dll) +# Repacked without bin/*.dll from https://github.com/dlang/dub/archive/v%%{version}.tar.gz +Source: %{name}-%{version}.tar.gz BuildRequires: pkgconfig BuildRequires: pkgconfig(libcurl) %if %{with dcompiler_dmd} ++++++ dub-1.42.0.tar.gz -> dub-1.43.0.tar.gz ++++++ Binary files old/dub-1.42.0/bin/libcurl.dll and new/dub-1.43.0/bin/libcurl.dll differ Binary files old/dub-1.42.0/bin/libeay32.dll and new/dub-1.43.0/bin/libeay32.dll differ Binary files old/dub-1.42.0/bin/ssleay32.dll and new/dub-1.43.0/bin/ssleay32.dll differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/build-files.txt new/dub-1.43.0/build-files.txt --- old/dub-1.42.0/build-files.txt 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/build-files.txt 2026-10-31 17:11:00.000000000 +0100 @@ -13,6 +13,7 @@ source/dub/dub.d source/dub/generators/build.d source/dub/generators/cmake.d +source/dub/generators/ninja.d source/dub/generators/generator.d source/dub/generators/sublimetext.d source/dub/generators/targetdescription.d diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/changelog/dustmite-timeout.dd new/dub-1.43.0/changelog/dustmite-timeout.dd --- old/dub-1.42.0/changelog/dustmite-timeout.dd 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/changelog/dustmite-timeout.dd 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +0,0 @@ -Added `--timeout` option to `dub dustmite` command. - -Adds a timeout (in seconds) for each oracle invocation, preventing -the dustmite process from hanging indefinitely when the test command -does not terminate. Requires the `timeout` command to be available -(coreutils on Linux/macOS). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/changelog/ldc-conf.dd new/dub-1.43.0/changelog/ldc-conf.dd --- old/dub-1.42.0/changelog/ldc-conf.dd 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/changelog/ldc-conf.dd 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,9 @@ +Fixed `--conf` options not being passed to LDC's linker step. + +Packages can now use `--conf` as a dflag to modify LDC's linker +behavior for a package. + +Example: +------- +dflags "--conf=$KON_PACKAGE_DIR/55-wasm-wasi.conf" platform="wasm32" +------- \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/changelog/ninja-generator.dd new/dub-1.43.0/changelog/ninja-generator.dd --- old/dub-1.42.0/changelog/ninja-generator.dd 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/changelog/ninja-generator.dd 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,5 @@ +Added `dub generate ninja` command. + +Introduces a Ninja build backend for DUB. Running `dub generate ninja` +produces a `build.ninja` file with compile and link rules for all source +files in the project, using the correct flag syntax for DMD, LDC, and GDC. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/changelog/windows-response-file-escape.dd new/dub-1.43.0/changelog/windows-response-file-escape.dd --- old/dub-1.42.0/changelog/windows-response-file-escape.dd 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/changelog/windows-response-file-escape.dd 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,8 @@ +Fix Windows response file quoting for paths with trailing backslashes + +When dub writes spaced compiler flags into `@` response files, a trailing +directory separator before the closing quote could escape that quote under +DMD/LDC response expansion. This broke ldc2 builds for users whose dub cache +paths contain spaces (regression since import paths gained trailing slashes). + +Related: ldc-developers/ldc#5134 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/scripts/zsh-completion/_dub new/dub-1.43.0/scripts/zsh-completion/_dub --- old/dub-1.42.0/scripts/zsh-completion/_dub 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/scripts/zsh-completion/_dub 2026-10-31 17:11:00.000000000 +0100 @@ -151,7 +151,7 @@ '(-c --config)'{-c,--config=}'[Builds the specified configuration]:package configuration: ' \ '*--override-config=[ Uses the specified configuration for a certain dependency]:dependency/config: ' \ '--compiler=[Specifies the compiler binary to use (can be a path)]:compiler:(dmd gdc ldc gdmd ldmd)' \ - '(-a --arch)'{-a,--arch=}'[Force a different architecture (e.g. x86 or x86_64)]:architecture: ' \ + '(-a --arch)'{-a,--arch=}'[Force a different architecture (e.g. x86, x86_64 or aarch64)]:architecture: ' \ '(-d --debug)*'{-d,--debug=}'[Define the specified debug version identifier when building]:Debug version: ' \ '--d-version=[Define the specified version identifier when building]:Version identifier: ' \ '--nodeps[Do not resolve missing dependencies before building]' \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/commandline.d new/dub-1.43.0/source/dub/commandline.d --- old/dub-1.42.0/source/dub/commandline.d 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/source/dub/commandline.d 2026-10-31 17:11:00.000000000 +0100 @@ -11,15 +11,15 @@ import dub.dependency; import dub.dub; import dub.generators.generator; +import dub.internal.logging; +import dub.internal.utils : getClosestMatch, getDUBVersion, getTempFile; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; -import dub.internal.logging; import dub.package_; import dub.packagemanager; import dub.packagesuppliers; import dub.project; -import dub.internal.utils : getDUBVersion, getClosestMatch, getTempFile; import dub.internal.dyaml.stdsumtype; @@ -1308,7 +1308,7 @@ " "~["dmd", "gdc", "ldc", "gdmd", "ldmd"].join(", ") ]); args.getopt("a|arch", &m_arch, [ - "Force a different architecture (e.g. x86 or x86_64)" + "Force a different architecture (e.g. x86, x86_64 or aarch64)" ]); args.getopt("d|debug", &m_debugVersions, [ "Define the specified `debug` version identifier when building - can be used multiple times" @@ -1453,6 +1453,7 @@ "visuald - VisualD project files", "sublimetext - SublimeText project file", "cmake - CMake build scripts", + "ninja - Ninja build files", "build - Builds the package directly", "", "An optional package name can be given to generate a different package than the root/CWD package." diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/compilers/buildsettings.d new/dub-1.43.0/source/dub/compilers/buildsettings.d --- old/dub-1.42.0/source/dub/compilers/buildsettings.d 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/source/dub/compilers/buildsettings.d 2026-10-31 17:11:00.000000000 +0100 @@ -649,6 +649,74 @@ } /** + ABI-critical dflags that must be propagated downwards to all dependencies. + + These are raw compiler flags (not covered by `BuildOption`) that affect + calling conventions, instruction-set selection, or runtime behaviour in + ways that must be consistent across every compilation unit in the + dependency graph; otherwise the resulting binaries suffer from silent ABI + mismatches or linker errors. + + See_Also: $(LINK2 https://github.com/dlang/dub/issues/3080) +*/ +private immutable abiCriticalPrefixes = [ + // LDC + "-mattr=", + "-mcpu=", + "-mtriple=", + "-checkaction=", + // DMD / LDC (-boundscheck=off is also extracted as a BuildOption, + // but -boundscheck=safeonly and -boundscheck=on stay as raw dflags) + "-boundscheck=", + // LDC – sanitizer instrumentation must be consistent + "-fsanitize=", + // GDC (GCC-style) + "-march=", + "-mfpu=", + "-mfloat-abi=", +]; + +/// Returns only the ABI-critical flags from `dflags`. +const(string)[] filterABICriticalFlags(const string[] dflags) +{ + import std.algorithm.iteration : filter; + import std.algorithm.searching : startsWith; + + return dflags.filter!(f => abiCriticalPrefixes.any!(p => f.startsWith(p))).array; +} + +unittest +{ + auto flags = ["-mattr=+avx", "-w", "-g", "-mcpu=haswell", "-O2", + "-checkaction=halt", "-mtriple=x86_64-linux-gnu"]; + auto critical = filterABICriticalFlags(flags); + assert(critical == ["-mattr=+avx", "-mcpu=haswell", + "-checkaction=halt", "-mtriple=x86_64-linux-gnu"]); +} + +unittest +{ + // No ABI-critical flags → empty result + assert(filterABICriticalFlags(["-w", "-g", "-O2"]).length == 0); +} + +unittest +{ + // GDC flags + auto flags = ["-march=native", "-mfpu=neon", "-mfloat-abi=hard", "-v"]; + auto critical = filterABICriticalFlags(flags); + assert(critical == ["-march=native", "-mfpu=neon", "-mfloat-abi=hard"]); +} + +unittest +{ + // -boundscheck= variants and -fsanitize= + auto flags = ["-boundscheck=safeonly", "-O2", "-fsanitize=address", "-w"]; + auto critical = filterABICriticalFlags(flags); + assert(critical == ["-boundscheck=safeonly", "-fsanitize=address"]); +} + +/** All build options that will be inherited upwards in the dependency graph Build options in this category fulfill one of the following properties: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/compilers/dmd.d new/dub-1.43.0/source/dub/compilers/dmd.d --- old/dub-1.42.0/source/dub/compilers/dmd.d 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/source/dub/compilers/dmd.d 2026-10-31 17:11:00.000000000 +0100 @@ -9,10 +9,10 @@ import dub.compilers.compiler; import dub.compilers.utils; +import dub.internal.logging; import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.inet.path; -import dub.internal.logging; import std.algorithm; import std.array; @@ -23,7 +23,7 @@ version (Windows) private Nullable!bool isWow64() { // See also: https://docs.microsoft.com/de-de/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo - import core.sys.windows.windows : GetNativeSystemInfo, SYSTEM_INFO, PROCESSOR_ARCHITECTURE_AMD64; + import core.sys.windows.windows : GetNativeSystemInfo, PROCESSOR_ARCHITECTURE_AMD64, SYSTEM_INFO; static Nullable!bool result; @@ -128,6 +128,7 @@ { // Set basic arch flags for the probe - might be revised based on the exact value + compiler version string[] arch_flags; + // keep the platform arguments below updated with dub-docs! (docs/dub-reference/platform_specifications.md) switch (arch_override) { default: throw new UnsupportedArchitectureException(arch_override); case "": @@ -420,7 +421,7 @@ private auto escapeArgs(in string[] args) { - return args.map!(s => s.canFind(' ') ? "\""~s~"\"" : s); + return args.map!(escapeResponseFileArg); } static bool isLinkerDFlag(string arg) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/compilers/gdc.d new/dub-1.43.0/source/dub/compilers/gdc.d --- old/dub-1.42.0/source/dub/compilers/gdc.d 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/source/dub/compilers/gdc.d 2026-10-31 17:11:00.000000000 +0100 @@ -9,10 +9,10 @@ import dub.compilers.compiler; import dub.compilers.utils; +import dub.internal.logging; import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.inet.path; -import dub.internal.logging; import std.algorithm; import std.array; @@ -68,6 +68,7 @@ BuildPlatform determinePlatform(ref BuildSettings settings, string compiler_binary, string arch_override) { string[] arch_flags; + // keep the platform arguments below updated with dub-docs! (docs/dub-reference/platform_specifications.md) switch (arch_override) { default: throw new UnsupportedArchitectureException(arch_override); case "": break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/compilers/ldc.d new/dub-1.43.0/source/dub/compilers/ldc.d --- old/dub-1.42.0/source/dub/compilers/ldc.d 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/source/dub/compilers/ldc.d 2026-10-31 17:11:00.000000000 +0100 @@ -9,10 +9,10 @@ import dub.compilers.compiler; import dub.compilers.utils; +import dub.internal.logging; import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.inet.path; -import dub.internal.logging; import std.algorithm; import std.array; @@ -80,6 +80,7 @@ { string[] arch_flags; bool arch_override_is_triple = false; + // keep the platform arguments below updated with dub-docs! (docs/dub-reference/platform_specifications.md) switch (arch_override) { case "": break; case "x86": arch_flags = ["-march=x86"]; break; @@ -335,7 +336,7 @@ private auto escapeArgs(in string[] args) { - return args.map!(s => s.canFind(' ') ? "\""~s~"\"" : s); + return args.map!(escapeResponseFileArg); } static bool isLinkerDFlag(string arg) @@ -359,7 +360,8 @@ || arg.startsWith("-linker=") || arg.startsWith("-march=") || arg.startsWith("-mscrtlib=") - || arg.startsWith("-mtriple="); + || arg.startsWith("-mtriple=") + || arg.startsWith("-conf="); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/compilers/utils.d new/dub-1.43.0/source/dub/compilers/utils.d --- old/dub-1.42.0/source/dub/compilers/utils.d 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/source/dub/compilers/utils.d 2026-10-31 17:11:00.000000000 +0100 @@ -13,6 +13,8 @@ import dub.internal.logging; import std.algorithm : canFind, endsWith, filter; +import std.array : array; +import std.range : repeat; /** Alters the build options to comply with the specified build requirements. @@ -72,6 +74,46 @@ assert(!isLinkerFile(p, "test.d")); } +/** + Formats one command-line argument for a compiler response file. + + DMD and LDC treat a backslash immediately before a closing double quote as + escaping that quote when expanding `@` files. Spaced arguments are wrapped in + quotes; trailing backslashes in the payload must be doubled so the closing + quote ends the argument (see Phobos `responseExpandFrom`, LDC + `driver/response.cpp`). +*/ +string escapeResponseFileArg(string s) +{ + if (!s.canFind(' ')) + return s; + + size_t trailingBackslashes; + for (trailingBackslashes = 0; + trailingBackslashes < s.length && s[$ - 1 - trailingBackslashes] == '\\'; + trailingBackslashes++) { } + + if (trailingBackslashes) + s ~= '\\'.repeat(trailingBackslashes).array; + + return '"' ~ s ~ '"'; +} + +unittest { + // No spaces: leave the argument untouched (including trailing backslashes). + assert(escapeResponseFileArg(`C:\nospace`) == `C:\nospace`); + assert(escapeResponseFileArg(`C:\trail\\`) == `C:\trail\\`); + + enum spaced = `C:\dir with spaces\file.d`; + assert(escapeResponseFileArg(spaced) == `"` ~ spaced ~ `"`); + + // Trailing directory separators must be doubled inside the quotes so the + // closing quote is not escaped by response-file expansion. + assert(escapeResponseFileArg(`-IC:\Users\Has Space\src\`) == + `"-IC:\Users\Has Space\src\\"`); + assert(escapeResponseFileArg(`C:\dir with spaces\trail\\`) == + `"C:\dir with spaces\trail\\\\"`); +} /** Adds a default DT_SONAME (ELF) / 'install name' (Mach-O) when linking a dynamic library. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/generators/generator.d new/dub-1.43.0/source/dub/generators/generator.d --- old/dub-1.42.0/source/dub/generators/generator.d 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/source/dub/generators/generator.d 2026-10-31 17:11:00.000000000 +0100 @@ -9,6 +9,7 @@ import dub.compilers.compiler; import dub.generators.cmake; +import dub.generators.ninja; import dub.generators.build; import dub.generators.sublimetext; import dub.generators.visuald; @@ -742,6 +743,10 @@ child.addVersions(parent.versions); child.addDebugVersions(parent.debugVersions); child.addOptions(Flags!BuildOption(parent.options & inheritedBuildOptions)); + // Propagate ABI-critical dflags (e.g. -mattr=+avx) so that all + // dependencies are compiled with a consistent instruction set / + // calling convention. See https://github.com/dlang/dub/issues/3080 + child.addDFlags(filterABICriticalFlags(parent.dflags)); } private static void mergeFromDependency(const scope ref BuildSettings child, ref BuildSettings parent, const scope ref BuildPlatform platform) @@ -950,6 +955,9 @@ case "cmake": logDebug("Creating CMake generator."); return new CMakeGenerator(project); + case "ninja": + logDebug("Creating Ninja generator."); + return new NinjaGenerator(project); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/generators/ninja.d new/dub-1.43.0/source/dub/generators/ninja.d --- old/dub-1.42.0/source/dub/generators/ninja.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/source/dub/generators/ninja.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,165 @@ +/** + Generator for Ninja build scripts + + License: Subject to the terms of the MIT license + Authors: Hariprakash V +*/ +module dub.generators.ninja; + +import dub.compilers.compiler; +import dub.generators.generator; +import dub.project; +import dub.internal.vibecompat.inet.path; + +import std.algorithm : map, startsWith; +import std.array : join, replace; +import std.path : stripExtension; +import std.stdio : File; +import std.file : exists, thisExePath; + +class NinjaGenerator : ProjectGenerator +{ + this(Project project) + { + super(project); + } + + override void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets) + { + auto f = File("build.ninja", "w"); + scope(exit) f.close(); + + immutable compiler = settings.platform.compilerBinary; + immutable cname = settings.platform.compiler; + + f.writeln("# Generated by DUB ninja generator"); + f.writeln(); + f.writeln("ar = ar"); + f.writeln(); + f.writeln("rule dc"); + f.writeln(" command = ", compiler, " $flags -c $in -of=$out -makedeps=$out.dep"); + f.writeln(" depfile = $out.dep"); + f.writeln(" deps = gcc"); + f.writeln(" description = Compiling $in"); + f.writeln(); + f.writeln("rule link"); + f.writeln(" command = ", compiler, " $in $lflags -of=$out"); + f.writeln(" description = Linking $out"); + f.writeln(); + f.writeln("rule ar"); + f.writeln(" command = $ar rcs $out $in"); + f.writeln(" description = Archiving $out"); + f.writeln(); + + const recipePath = m_project.rootPackage.recipePath.toNativeString(); + auto selectionsPath = (m_project.rootPackage.path ~ "dub.selections.json").toNativeString(); + + f.writeln("rule regen"); + f.writeln(" command = ", thisExePath(), " generate ninja"); + f.writeln(" generator = 1"); + f.writeln(" description = Regenerating build.ninja"); + f.writeln(); + + string[] regenInputs = [recipePath]; + if (exists(selectionsPath)) + regenInputs ~= selectionsPath; + + f.writeln("build build.ninja: regen ", regenInputs.map!(p => escapeNinjaPath(p)).join(" ")); + f.writeln(); + + foreach (name, info; targets) + { + auto bs = info.buildSettings; + + auto importFlags = bs.importPaths.map!(p => "-I" ~ escapeNinjaPath(p)).join(" "); + auto strImportFlags = bs.stringImportPaths.map!(p => "-J" ~ escapeNinjaPath(p)).join(" "); + auto versionFlags = bs.versions.map!(v => versionFlag(cname) ~ v).join(" "); + auto debugFlags = bs.debugVersions.map!(v => debugFlag(cname) ~ v).join(" "); + auto extraFlags = bs.dflags.join(" "); + + string[] parts; + if (importFlags.length) parts ~= importFlags; + if (strImportFlags.length) parts ~= strImportFlags; + if (versionFlags.length) parts ~= versionFlags; + if (debugFlags.length) parts ~= debugFlags; + if (extraFlags.length) parts ~= extraFlags; + auto flags = parts.join(" "); + + auto lflags = bs.lflags.map!(f => escapeNinjaPath(f)).join(" "); + + string[] objs; + foreach (src; bs.sourceFiles) + { + auto obj = objName(src); + f.writeln("build ", obj, ": dc ", escapeNinjaPath(src)); + if (flags.length) + f.writeln(" flags = ", flags); + objs ~= obj; + } + f.writeln(); + + string[] depLibs; + foreach (dep; info.linkDependencies) + { + if (dep in targets) + depLibs ~= libName(targets[dep].buildSettings.targetName, sanitizeName(dep)); + } + + auto outBin = bs.targetName.length ? bs.targetName : sanitizeName(name); + + if (bs.targetType == TargetType.staticLibrary || + bs.targetType == TargetType.library) + { + f.writeln("build ", outBin ~ ".a", ": ar ", objs.join(" ")); + } + else + { + auto linkInputs = (objs ~ depLibs).join(" "); + f.writeln("build ", outBin, ": link ", linkInputs); + if (lflags.length) + f.writeln(" lflags = ", lflags); + f.writeln(); + f.writeln("default ", outBin); + } + f.writeln(); + } + } + + private static string escapeNinjaPath(string path) + { + return path.replace(":", "$:").replace(" ", "$ "); + } + + private static string objName(string src) + { + return stripExtension(src) + .replace("/", "_") + .replace("\\", "_") + .replace(":", "_") ~ ".o"; + } + + private static string libName(string targetName, string fallback) + { + auto base = targetName.length ? targetName : fallback; + return base ~ ".a"; + } + + private static string versionFlag(string cname) + { + if (cname.startsWith("ldc")) return "--d-version="; + if (cname.startsWith("gdc")) return "-fversion="; + return "-version="; + } + + private static string debugFlag(string cname) + { + if (cname.startsWith("ldc")) return "--d-debug="; + if (cname.startsWith("gdc")) return "-fdebug="; + return "-debug="; + } + private static string sanitizeName(string name) + { + return name.replace(":", "_").replace("/", "_"); + } + +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/generators/visuald.d new/dub-1.43.0/source/dub/generators/visuald.d --- old/dub-1.42.0/source/dub/generators/visuald.d 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/source/dub/generators/visuald.d 2026-10-31 17:11:00.000000000 +0100 @@ -307,7 +307,26 @@ ret.formattedWrite(" <imppath>%s</imppath>\n", combinedImports); ret.formattedWrite(" <fileImppath>%s</fileImppath>\n", stringImports); - ret.formattedWrite(" <program>%s</program>\n", "$(DMDInstallDir)windows\\bin\\dmd.exe"); // FIXME: use the actually selected compiler! + ret.formattedWrite(" <program>%s</program>\n", settings.compiler.name); + string program; + + final switch (settings.compiler.name) + { + case "ldc": + case "ldc2": + program = "$(LDCInstallDir)bin\\ldc2.exe"; + break; + + case "gdc": + program = "$(GDCInstallDir)bin\\gdc.exe"; + break; + + case "dmd": + program = "$(DMDInstallDir)windows\\bin\\dmd.exe"; + break; + } + + ret.formattedWrite(" <program>%s</program>\n", program); ret.formattedWrite(" <additionalOptions>%s</additionalOptions>\n", getSettings!"dflags"().join(" ")); // Add version identifiers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/internal/utils.d new/dub-1.43.0/source/dub/internal/utils.d --- old/dub-1.42.0/source/dub/internal/utils.d 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/source/dub/internal/utils.d 2026-10-31 17:11:00.000000000 +0100 @@ -138,7 +138,7 @@ void atomicWriteJsonFile(NativePath path, Json json) { import std.random : uniform; - auto tmppath = path.parentPath ~ format("%s.%s.tmp", path.head, uniform(0, int.max)); + auto tmppath = path.parentPath ~ format("%s.%s.tmp", path.head.name, uniform(0, int.max)); auto app = appender!string(); app.writePrettyJsonString(json); writeFile(tmppath, app.data); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/source/dub/version_.d new/dub-1.43.0/source/dub/version_.d --- old/dub-1.42.0/source/dub/version_.d 2026-08-05 17:14:37.000000000 +0200 +++ new/dub-1.43.0/source/dub/version_.d 2026-10-31 17:11:00.000000000 +0100 @@ -1,2 +1,2 @@ module dub.version_; -enum dubVersion = "v1.42.0"; +enum dubVersion = "v1.43.0"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/issue3080-abi-dflags/.gitignore new/dub-1.43.0/test/issue3080-abi-dflags/.gitignore --- old/dub-1.42.0/test/issue3080-abi-dflags/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/issue3080-abi-dflags/.gitignore 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,2 @@ +issue3080 +libdep.a diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/issue3080-abi-dflags/dep/dub.json new/dub-1.43.0/test/issue3080-abi-dflags/dep/dub.json --- old/dub-1.42.0/test/issue3080-abi-dflags/dep/dub.json 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/issue3080-abi-dflags/dep/dub.json 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,4 @@ +{ + "name": "dep", + "targetType": "library" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/issue3080-abi-dflags/dep/source/dep.d new/dub-1.43.0/test/issue3080-abi-dflags/dep/source/dep.d --- old/dub-1.42.0/test/issue3080-abi-dflags/dep/source/dep.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/issue3080-abi-dflags/dep/source/dep.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,5 @@ +module dep; + +void greet() +{ +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/issue3080-abi-dflags/dub.json new/dub-1.43.0/test/issue3080-abi-dflags/dub.json --- old/dub-1.42.0/test/issue3080-abi-dflags/dub.json 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/issue3080-abi-dflags/dub.json 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,8 @@ +{ + "name": "issue3080", + "targetType": "executable", + "dependencies": { + "dep": { "path": "dep" } + }, + "dflags": ["-checkaction=halt"] +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/issue3080-abi-dflags/source/app.d new/dub-1.43.0/test/issue3080-abi-dflags/source/app.d --- old/dub-1.42.0/test/issue3080-abi-dflags/source/app.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/issue3080-abi-dflags/source/app.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,6 @@ +import dep; + +void main() +{ + greet(); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/issue3080-abi-dflags.sh new/dub-1.43.0/test/issue3080-abi-dflags.sh --- old/dub-1.42.0/test/issue3080-abi-dflags.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/issue3080-abi-dflags.sh 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# Test for https://github.com/dlang/dub/issues/3080 +# Verify that ABI-critical dflags from the root package are propagated +# to dependency compilations. + +set -e + +. $(dirname "${BASH_SOURCE[0]}")/common.sh + +cd ${CURR_DIR}/issue3080-abi-dflags + +# -checkaction is supported by DMD and LDC but not GDC +DC_BIN=$(basename "$DC") +if [ "$DC_BIN" = "gdc" ]; then + echo "Skipping -checkaction propagation test for GDC." + exit 0 +fi + +# Build with verbose output so we can see the compiler invocations +OUTPUT=$($DUB build --force --compiler=${DC} -v 2>&1) + +# The root dub.json sets dflags: ["-checkaction=halt"]. +# Verify that the dependency "dep" is also compiled with this flag. +# In verbose output, the dep compilation line looks like: +# ldc2 ... dep/source/dep.d -checkaction=halt ... +# Count how many compiler invocation lines contain -checkaction=halt. +COUNT=$(echo "$OUTPUT" | grep -c '\-checkaction=halt' || true) +if [ "$COUNT" -ge 2 ]; then + echo "PASS: -checkaction=halt propagated to dependency ($COUNT occurrences)." +else + echo "FAIL: -checkaction=halt was not propagated to dependency (found $COUNT times)." + echo "Verbose output:" + echo "$OUTPUT" + exit 1 +fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-ar.sh new/dub-1.43.0/test/ninja-ar.sh --- old/dub-1.42.0/test/ninja-ar.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-ar.sh 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +. $(dirname "${BASH_SOURCE[0]}")/common.sh + +cd "$CURR_DIR"/ninja-static-lib + +if ! $DUB generate ninja --compiler=$DC 2>&1; then + die $LINENO 'dub generate ninja failed!' +fi + +ninja -t clean +if ! ninja 2>&1; then + die $LINENO 'ninja build failed!' +fi + +if [ ! -f ninja-static-lib.a ]; then + die $LINENO 'static library was not produced!' +fi + +$DC -c consumer.d -of=consumer.o +$DC consumer.o ninja-static-lib.a -of=consumer_test + +output=$(./consumer_test) +if [ "$output" != "5" ]; then + die $LINENO "expected 5 from linked archive, got '$output'" +fi + +rm -f consumer.o consumer_test +ninja -t clean +rm -f build.ninja diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-generator/dub.json new/dub-1.43.0/test/ninja-generator/dub.json --- old/dub-1.42.0/test/ninja-generator/dub.json 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-generator/dub.json 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,4 @@ +{ + "name": "ninja-generator", + "targetType": "executable" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-generator/source/app.d new/dub-1.43.0/test/ninja-generator/source/app.d --- old/dub-1.42.0/test/ninja-generator/source/app.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-generator/source/app.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1 @@ +void main() {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-generator-sdl/dub.sdl new/dub-1.43.0/test/ninja-generator-sdl/dub.sdl --- old/dub-1.42.0/test/ninja-generator-sdl/dub.sdl 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-generator-sdl/dub.sdl 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,2 @@ +name "ninja-generator-sdl" +targetType "executable" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-generator-sdl/source/app.d new/dub-1.43.0/test/ninja-generator-sdl/source/app.d --- old/dub-1.42.0/test/ninja-generator-sdl/source/app.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-generator-sdl/source/app.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1 @@ +void main() {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-generator.script.d new/dub-1.43.0/test/ninja-generator.script.d --- old/dub-1.42.0/test/ninja-generator.script.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-generator.script.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,86 @@ +/+ dub.sdl: + name "ninja-generator-regen" + dependency "common" path="./common" + +/ + +module ninja_generator_regen; + +import std.process : environment, execute, Config; +import std.path : buildPath, dirName; +import std.file : readText, remove, mkdirRecurse, rmdirRecurse, write; +import std.algorithm : canFind; +import core.thread : Thread; +import core.time : seconds; + +import common; + +bool regenUpdatesImportPath(string projDir, string recipePath, string origRecipe, string newRecipe) +{ + const buildNinjaPath = buildPath(projDir, "build.ninja"); + const importDir = buildPath(projDir, "extra-imports"); + + mkdirRecurse(importDir); + scope(exit) rmdirRecurse(importDir); + + Thread.sleep(1.seconds); + write(recipePath, newRecipe); + scope(exit) write(recipePath, origRecipe); + + const result = execute(["ninja"], null, Config.none, size_t.max, projDir); + if (result.status != 0 || !result.output.canFind("Regenerating build.ninja")) + return false; + + return readText(buildNinjaPath).canFind("extra-imports"); +} + +int main() +{ + const dub = environment.get("DUB", buildPath(__FILE_FULL_PATH__.dirName.dirName, "bin", "dub")); + const dc = environment.get("DC", "dmd"); + const curr_dir = environment.get("CURR_DIR", buildPath(__FILE_FULL_PATH__.dirName)); + const projDir = buildPath(curr_dir, "ninja-generator"); + + if (execute([dub, "generate", "ninja", "--compiler", dc], null, Config.none, size_t.max, projDir).status) + die("dub generate ninja failed"); + + execute(["ninja", "-t", "clean"], null, Config.none, size_t.max, projDir); + if (execute(["ninja"], null, Config.none, size_t.max, projDir).status) + die("initial ninja build failed"); + + const jsonRecipePath = buildPath(projDir, "dub.json"); + const origJson = readText(jsonRecipePath); + const newJson = `{ + "name": "ninja-generator", + "targetType": "executable", + "importPaths": ["extra-imports"] +}`; + + if (!regenUpdatesImportPath(projDir, jsonRecipePath, origJson, newJson)) + die("build.ninja was not actually regenerated with the new import path after touching dub.json"); + + const sdlProjDir = buildPath(curr_dir, "ninja-generator-sdl"); + + if (execute([dub, "generate", "ninja", "--compiler", dc], null, Config.none, size_t.max, sdlProjDir).status) + die("dub generate ninja failed for dub.sdl project"); + + const sdlBuildNinja = buildPath(sdlProjDir, "build.ninja"); + if (!readText(sdlBuildNinja).canFind("regen") || !readText(sdlBuildNinja).canFind("dub.sdl")) + die("build.ninja regen edge missing dub.sdl dependency"); + + execute(["ninja", "-t", "clean"], null, Config.none, size_t.max, sdlProjDir); + if (execute(["ninja"], null, Config.none, size_t.max, sdlProjDir).status) + die("initial ninja build failed for dub.sdl project"); + + const sdlRecipePath = buildPath(sdlProjDir, "dub.sdl"); + const origSdl = readText(sdlRecipePath); + const newSdl = "name \"ninja-generator-sdl\"\ntargetType \"executable\"\nimportPaths \"extra-imports\"\n"; + + if (!regenUpdatesImportPath(sdlProjDir, sdlRecipePath, origSdl, newSdl)) + die("build.ninja was not actually regenerated with the new import path after touching dub.sdl"); + + execute(["ninja", "-t", "clean"], null, Config.none, size_t.max, sdlProjDir); + remove(sdlBuildNinja); + + log("PASS"); + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-generator.sh new/dub-1.43.0/test/ninja-generator.sh --- old/dub-1.42.0/test/ninja-generator.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-generator.sh 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +. $(dirname "${BASH_SOURCE[0]}")/common.sh + +cd "$CURR_DIR"/ninja-generator + +if ! $DUB generate ninja --compiler=$DC 2>&1; then + die $LINENO 'dub generate ninja failed!' +fi + +if [ ! -f build.ninja ]; then + die $LINENO 'build.ninja was not generated!' +fi + +if ! grep -q "rule dc" build.ninja; then + die $LINENO 'build.ninja missing dc rule!' +fi + +if ! grep -q "rule link" build.ninja; then + die $LINENO 'build.ninja missing link rule!' +fi + +rm -f build.ninja diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-makedeps/dub.json new/dub-1.43.0/test/ninja-makedeps/dub.json --- old/dub-1.42.0/test/ninja-makedeps/dub.json 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-makedeps/dub.json 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,4 @@ +{ + "name": "ninja-makedeps", + "targetType": "executable" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-makedeps/source/app.d new/dub-1.43.0/test/ninja-makedeps/source/app.d --- old/dub-1.42.0/test/ninja-makedeps/source/app.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-makedeps/source/app.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,2 @@ +import helper; +void main() { helperFunc(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-makedeps/source/helper.d new/dub-1.43.0/test/ninja-makedeps/source/helper.d --- old/dub-1.42.0/test/ninja-makedeps/source/helper.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-makedeps/source/helper.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1 @@ +void helperFunc() {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-makedeps.script.d new/dub-1.43.0/test/ninja-makedeps.script.d --- old/dub-1.42.0/test/ninja-makedeps.script.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-makedeps.script.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,73 @@ +/+ dub.sdl: + name "ninja-makedeps-regen" + dependency "common" path="./common" + +/ + +module ninja_makedeps_regen; + +import std.process : environment, execute, Config; +import std.path : buildPath, dirName; +import std.file : readText, write, timeLastModified, exists; +import std.algorithm : canFind; +import core.thread : Thread; +import core.time : seconds; + +import common; + +int main() +{ + const dub = environment.get("DUB", buildPath(__FILE_FULL_PATH__.dirName.dirName, "bin", "dub")); + const dc = environment.get("DC", "dmd"); + const curr_dir = environment.get("CURR_DIR", buildPath(__FILE_FULL_PATH__.dirName)); + const projDir = buildPath(curr_dir, "ninja-makedeps"); + + if (execute([dub, "generate", "ninja", "--compiler", dc], null, Config.none, size_t.max, projDir).status) + die("dub generate ninja failed"); + + const buildNinjaPath = buildPath(projDir, "build.ninja"); + if (!readText(buildNinjaPath).canFind("-makedeps")) + die("build.ninja missing -makedeps flag on dc rule"); + if (!readText(buildNinjaPath).canFind("depfile =")) + die("build.ninja missing depfile directive on dc rule"); + + execute(["ninja", "-t", "clean"], null, Config.none, size_t.max, projDir); + if (execute(["ninja"], null, Config.none, size_t.max, projDir).status) + die("initial ninja build failed"); + + // Locate the actual app.o produced, since the generator encodes the full + // source path into the object filename. + import std.file : dirEntries, SpanMode; + string findObj(string moduleName) + { + foreach (entry; dirEntries(projDir, SpanMode.shallow)) + if (entry.name.canFind("_" ~ moduleName ~ ".o")) + return entry.name; + return ""; + } + + const objPath = findObj("app"); + if (!objPath.length || !exists(objPath)) + die("could not locate app.o after initial build"); + + const mtimeBefore = timeLastModified(objPath); + + const helperPath = buildPath(projDir, "source", "helper.d"); + const origHelper = readText(helperPath); + + Thread.sleep(1.seconds); + write(helperPath, origHelper ~ "\n// touched\n"); + scope(exit) write(helperPath, origHelper); + + if (execute(["ninja"], null, Config.none, size_t.max, projDir).status) + die("rebuild after touching helper.d failed"); + + const mtimeAfter = timeLastModified(objPath); + + if (mtimeAfter <= mtimeBefore) + die("app.o was not recompiled after helper.d changed -- depfile is not tracking transitive imports"); + + execute(["ninja", "-t", "clean"], null, Config.none, size_t.max, projDir); + + log("PASS"); + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-static-lib/consumer.d new/dub-1.43.0/test/ninja-static-lib/consumer.d --- old/dub-1.42.0/test/ninja-static-lib/consumer.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-static-lib/consumer.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,3 @@ +import std.stdio; +extern(C) int add(int a, int b); +void main() { write(add(2, 3)); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-static-lib/dub.json new/dub-1.43.0/test/ninja-static-lib/dub.json --- old/dub-1.42.0/test/ninja-static-lib/dub.json 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-static-lib/dub.json 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,4 @@ +{ + "name": "ninja-static-lib", + "targetType": "staticLibrary" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-static-lib/source/lib.d new/dub-1.43.0/test/ninja-static-lib/source/lib.d --- old/dub-1.42.0/test/ninja-static-lib/source/lib.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-static-lib/source/lib.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1 @@ +extern(C) int add(int a, int b) { return a + b; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-subpackage/dub.json new/dub-1.43.0/test/ninja-subpackage/dub.json --- old/dub-1.42.0/test/ninja-subpackage/dub.json 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-subpackage/dub.json 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,14 @@ +{ + "name": "ninja-subpackage", + "targetType": "executable", + "dependencies": { + "ninja-subpackage:mylib": "*" + }, + "subPackages": [ + { + "name": "mylib", + "targetType": "staticLibrary", + "sourcePaths": ["lib/source"] + } + ] +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-subpackage/lib/source/lib.d new/dub-1.43.0/test/ninja-subpackage/lib/source/lib.d --- old/dub-1.42.0/test/ninja-subpackage/lib/source/lib.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-subpackage/lib/source/lib.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1 @@ +extern(C) int add(int a, int b) { return a + b; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-subpackage/source/app.d new/dub-1.43.0/test/ninja-subpackage/source/app.d --- old/dub-1.42.0/test/ninja-subpackage/source/app.d 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-subpackage/source/app.d 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,2 @@ +extern(C) int add(int a, int b); +void main() { assert(add(1, 2) == 3); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dub-1.42.0/test/ninja-subpackage.sh new/dub-1.43.0/test/ninja-subpackage.sh --- old/dub-1.42.0/test/ninja-subpackage.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/dub-1.43.0/test/ninja-subpackage.sh 2026-10-31 17:11:00.000000000 +0100 @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +. $(dirname "${BASH_SOURCE[0]}")/common.sh + +cd "$CURR_DIR"/ninja-subpackage + +if ! $DUB generate ninja --compiler=$DC 2>&1; then + die $LINENO 'dub generate ninja failed!' +fi + +if ! grep -q "rule ar" build.ninja; then + die $LINENO 'build.ninja missing ar rule!' +fi + +if ! grep -q "\.a" build.ninja; then + die $LINENO 'build.ninja missing static library build edge!' +fi + +ninja -t clean +if ! ninja 2>&1; then + die $LINENO 'ninja build failed!' +fi + +if ! ./ninja-subpackage 2>&1; then + die $LINENO 'linked executable failed to run!' +fi + +ninja -t clean +rm -f build.ninja
