From a3deb8ab5f1acedd655bcc78b605b40ac1057544 Mon Sep 17 00:00:00 2001 From: Andrei Horodniceanu Date: Sun, 6 Jul 2025 20:55:54 +0300 Subject: [PATCH] Remove $DFLAGS build type (but keep supporting the $DFLAGS variable) While it is useful and expected that dub would honor the $DFLAGS variable, it should not drop *all* flags that it adds on its own. The most egregious way this is manifesting is that: - `dub test` - runs unittests (duh) - `DFLAGS= dub test` - does not run a single test This is because dub would treat the presence (even if empty) of $DFLAGS as flags to override the current buildType. This has been changed and now $DFLAGS simply are appended to the flags derived from the buildType. If users actually want to prevent dub from passing any special flags they can do so with `dub test --build=plain` Signed-off-by: Andrei Horodniceanu --- changelog/remove-dflags-config.md | 16 ++++++++++ source/dub/commandline.d | 5 ++-- source/dub/package_.d | 4 +-- test/.gitignore | 4 +-- test/cache-generated-test-config.sh | 12 ++++---- test/dflags_dont_disable_tests.d | 9 ++++++ test/dflags_dont_disable_tests.script.d | 40 +++++++++++++++++++++++++ 7 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 changelog/remove-dflags-config.md create mode 100644 test/dflags_dont_disable_tests.d create mode 100644 test/dflags_dont_disable_tests.script.d diff --git a/changelog/remove-dflags-config.md b/changelog/remove-dflags-config.md new file mode 100644 index 0000000000..0347fab465 --- /dev/null +++ b/changelog/remove-dflags-config.md @@ -0,0 +1,16 @@ +Specifying `$DFLAGS` in the environment no longer overwrites dub-added flags + +When the `$DFLAGS` variable was present in the environment (even if +empty) Dub would stop itself from adding any flags implied by the +build type. This can lead to serious issues with `dub test` not +running unittests, like in the below example: + +``` +$ DFLAGS= dub test # this does not run any unittests +``` + +This has been changes and now, the `$DFLAGS` variable is simply +appended to the dub generated build flags. + +If you rely on the old behavior you can pass `--build=plain` to `dub`, +in addition to specifying your custom flags in `$DFLAGS`. diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 3c3efd4402..192d27518d 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -1289,7 +1289,7 @@ abstract class PackageBuildCommand : Command { { args.getopt("dest", &m_destPath, ["Base directory in which output atifacts will be placed"]); args.getopt("b|build", &this.baseSettings.buildType, [ - "Specifies the type of build to perform. Note that setting the DFLAGS environment variable will override the build type with custom flags.", + "Specifies the type of build to perform.", "Possible names:", " "~builtinBuildTypes.join(", ")~" and custom types" ]); @@ -1376,8 +1376,7 @@ abstract class PackageBuildCommand : Command { } if (this.baseSettings.buildType.length == 0) { - if (environment.get("DFLAGS") !is null) this.baseSettings.buildType = "$DFLAGS"; - else this.baseSettings.buildType = default_build_type; + this.baseSettings.buildType = default_build_type; } if (!m_nodeps) { diff --git a/source/dub/package_.d b/source/dub/package_.d index 38568c85e5..bd08e48b44 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -57,8 +57,7 @@ deprecated("Open an issue if this is needed") /// Returns the default package recile file name. @property string defaultPackageFilename() { return packageInfoFiles[0].filename; } -/// All built-in build type names except for the special `$DFLAGS` build type. -/// Has the default build type (`debug`) as first index. +/// The default build type (`debug`) is first static immutable string[] builtinBuildTypes = [ "debug", "plain", @@ -423,7 +422,6 @@ class Package { } else { with(BuildOption) switch (build_type) { default: throw new Exception(format("Unknown build type for %s: '%s'", this.name, build_type)); - case "$DFLAGS": break; case "plain": break; case "debug": settings.addOptions(debugMode, debugInfo); break; case "release": settings.addOptions(releaseMode, optimize, inline); break; diff --git a/test/.gitignore b/test/.gitignore index cfe8d612fc..ed28bc5749 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -33,8 +33,8 @@ expected-issue616-output describe-project/dummy.dat describe-project/dummy-dep1.dat */main/main -*/*test-library -*/*test-application +**test-library +**test-application */exec-simple issue1474/ext/fortytwo.d issue2452/ext/fortytwo.d diff --git a/test/cache-generated-test-config.sh b/test/cache-generated-test-config.sh index b3e17210a6..0c579a1308 100755 --- a/test/cache-generated-test-config.sh +++ b/test/cache-generated-test-config.sh @@ -31,15 +31,15 @@ STAT="stat -c '%Y'" EXECUTABLE_TIME="$(${STAT} cache-generated-test-config-test-library)" [ -z "$EXECUTABLE_TIME" ] && die $LINENO 'no EXECUTABLE_TIME was found' -MAIN_TIME="$(${STAT} "$(ls $DUB_CODE_CACHE_PATH/*-\$DFLAGS-*/dub_test_root.d)")" +MAIN_TIME="$(${STAT} "$(ls $DUB_CODE_CACHE_PATH/*/dub_test_root.d)")" [ -z "$MAIN_TIME" ] && die $LINENO 'no MAIN_TIME was found' DFLAGS="" ${DUB} test --compiler=${DC} -MAIN_FILES_COUNT=$(ls $DUB_CODE_CACHE_PATH/*-\$DFLAGS-*/dub_test_root.d | wc -l) +MAIN_FILES_COUNT=$(ls $DUB_CODE_CACHE_PATH/*/dub_test_root.d | wc -l) [ $MAIN_FILES_COUNT -ne 1 ] && die $LINENO 'DUB generated more then one main file' [ "$EXECUTABLE_TIME" != "$(${STAT} cache-generated-test-config-test-library)" ] && die $LINENO 'The executable has been rebuilt' -[ "$MAIN_TIME" != "$(${STAT} "$(ls $DUB_CODE_CACHE_PATH/*-\$DFLAGS-*/dub_test_root.d | head -n1)")" ] && die $LINENO 'The test main file has been rebuilt' +[ "$MAIN_TIME" != "$(${STAT} "$(ls $DUB_CODE_CACHE_PATH/*/dub_test_root.d | head -n1)")" ] && die $LINENO 'The test main file has been rebuilt' ## test with DFLAGS environment variable DFLAGS="-g" ${DUB} test --compiler=${DC} @@ -49,15 +49,15 @@ STAT="stat -c '%Y'" EXECUTABLE_TIME="$(${STAT} cache-generated-test-config-test-library)" [ -z "$EXECUTABLE_TIME" ] && die $LINENO 'no EXECUTABLE_TIME was found' -MAIN_TIME="$(${STAT} "$(ls $DUB_CODE_CACHE_PATH/*-\$DFLAGS-*/dub_test_root.d)")" +MAIN_TIME="$(${STAT} "$(ls $DUB_CODE_CACHE_PATH/*/dub_test_root.d)")" [ -z "$MAIN_TIME" ] && die $LINENO 'no MAIN_TIME was found' DFLAGS="-g" ${DUB} test --compiler=${DC} -MAIN_FILES_COUNT=$(ls $DUB_CODE_CACHE_PATH/*-\$DFLAGS-*/dub_test_root.d | wc -l) +MAIN_FILES_COUNT=$(ls $DUB_CODE_CACHE_PATH/*/dub_test_root.d | wc -l) [ $MAIN_FILES_COUNT -ne 1 ] && die $LINENO 'DUB generated more then one main file' [ "$EXECUTABLE_TIME" != "$(${STAT} cache-generated-test-config-test-library)" ] && die $LINENO 'The executable has been rebuilt' -[ "$MAIN_TIME" != "$(${STAT} "$(ls $DUB_CODE_CACHE_PATH/*-\$DFLAGS-*/dub_test_root.d | head -n1)")" ] && die $LINENO 'The test main file has been rebuilt' +[ "$MAIN_TIME" != "$(${STAT} "$(ls $DUB_CODE_CACHE_PATH/*/dub_test_root.d | head -n1)")" ] && die $LINENO 'The test main file has been rebuilt' diff --git a/test/dflags_dont_disable_tests.d b/test/dflags_dont_disable_tests.d new file mode 100644 index 0000000000..700d80ff68 --- /dev/null +++ b/test/dflags_dont_disable_tests.d @@ -0,0 +1,9 @@ +/+ dub.json: { + name: "dflags_dont_disable_tests" + } ++/ + +unittest { + import core.stdc.stdio; + puts("IM_A_UNITTEST"); +} diff --git a/test/dflags_dont_disable_tests.script.d b/test/dflags_dont_disable_tests.script.d new file mode 100644 index 0000000000..458b0c1df9 --- /dev/null +++ b/test/dflags_dont_disable_tests.script.d @@ -0,0 +1,40 @@ +/+ dub.json: { + "name": "dflags_dont_disable_tests_script" +} +/ + +module main; + +int main() +{ + import std.process; + import std.path; + import std.stdio; + import std.algorithm; + + const dir = __FILE_FULL_PATH__.dirName(); + const testFile = dir.buildPath("dflags_dont_disable_tests.d"); + const dub = environment.get("DUB"); + auto env = environment.toAA(); + // An unobtrusive flag, supported by all compilers + env["DFLAGS"] = "-g"; + + const result = execute([dub, "test", "--single", testFile], env); + + if (result.status != 0) { + stderr.writeln("Dub failed with exit code: ", result.status); + stderr.writeln("Dub output:"); + stderr.writeln(result.output); + stderr.writeln(); + return 1; + } + + if (!result.output.canFind("IM_A_UNITTEST")) { + stderr.writeln("unittest flags not passed with custom $DFLAGS"); + stderr.writeln("Dub output:"); + stderr.writeln(result.output); + stderr.writeln(); + return 1; + } + + return 0; +}