diff --git a/changelog/cache-generated-test-config.dd b/changelog/cache-generated-test-config.dd new file mode 100644 index 000000000..01cf12145 --- /dev/null +++ b/changelog/cache-generated-test-config.dd @@ -0,0 +1,4 @@ +Caching of generated unittest runner (dub test) + +For projects without a user-defined unittest configuration `dub test` generates a main file automatically. +This main file is now being cached and won't be regenerated won subsequent runs without file changes. \ No newline at end of file diff --git a/source/dub/dub.d b/source/dub/dub.d index c35d89e6f..69e4b69bd 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -662,6 +662,7 @@ class Dub { } // prepare the list of tested modules + string[] import_modules; foreach (file; lbuildsettings.sourceFiles) { if (file.endsWith(".d")) { @@ -679,11 +680,23 @@ class Dub { } } + NativePath mainfile; + if (settings.tempBuild) + mainfile = getTempFile("dub_test_root", ".d"); + else { + 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); + // generate main file - NativePath mainfile = getTempFile("dub_test_root", ".d"); tcinfo.sourceFiles[""] ~= mainfile.toNativeString(); tcinfo.mainSourceFile = mainfile.toNativeString(); - if (!m_dryRun) { + + if (!m_dryRun && regenerateMainFile) { auto fil = openFile(mainfile, FileMode.createTrunc); scope(exit) fil.close(); fil.write("module dub_test_root;\n"); diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 75250f4b5..523233506 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -32,6 +32,24 @@ string getObjSuffix(const scope ref BuildPlatform platform) return platform.platform.canFind("windows") ? ".obj" : ".o"; } +string computeBuildName(string config, GeneratorSettings settings, const string[][] hashing...) +{ + import std.digest; + import std.digest.md; + + MD5 hash; + hash.start(); + void addHash(in string[] strings...) { foreach (s; strings) { hash.put(cast(ubyte[])s); hash.put(0); } hash.put(0); } + foreach(strings; hashing) + addHash(strings); + auto hashstr = hash.finish().toHexString().idup; + + return format("%s-%s-%s-%s-%s_%s-%s", config, settings.buildType, + settings.platform.platform.join("."), + settings.platform.architecture.join("."), + settings.platform.compiler, settings.platform.frontendVersion, hashstr); +} + class BuildGenerator : ProjectGenerator { private { PackageManager m_packageMan; @@ -329,33 +347,23 @@ class BuildGenerator : ProjectGenerator { private string computeBuildID(string config, in BuildSettings buildsettings, GeneratorSettings settings) { - import std.digest; - import std.digest.md; - import std.bitmanip; - - MD5 hash; - hash.start(); - void addHash(in string[] strings...) { foreach (s; strings) { hash.put(cast(ubyte[])s); hash.put(0); } hash.put(0); } - void addHashI(int value) { hash.put(nativeToLittleEndian(value)); } - addHash(buildsettings.versions); - addHash(buildsettings.debugVersions); - //addHash(buildsettings.versionLevel); - //addHash(buildsettings.debugLevel); - addHash(buildsettings.dflags); - addHash(buildsettings.lflags); - addHash((cast(uint)buildsettings.options).to!string); - addHash(buildsettings.stringImportPaths); - addHash(buildsettings.importPaths); - addHash(settings.platform.architecture); - addHash(settings.platform.compilerBinary); - addHash(settings.platform.compiler); - addHashI(settings.platform.frontendVersion); - auto hashstr = hash.finish().toHexString().idup; - - return format("%s-%s-%s-%s-%s_%s-%s", config, settings.buildType, - settings.platform.platform.join("."), - settings.platform.architecture.join("."), - settings.platform.compiler, settings.platform.frontendVersion, hashstr); + const(string[])[] hashing = [ + buildsettings.versions, + buildsettings.debugVersions, + buildsettings.dflags, + buildsettings.lflags, + buildsettings.stringImportPaths, + buildsettings.importPaths, + settings.platform.architecture, + [ + (cast(uint)buildsettings.options).to!string, + settings.platform.compilerBinary, + settings.platform.compiler, + settings.platform.frontendVersion.to!string, + ], + ]; + + return computeBuildName(config, settings, hashing); } private void copyTargetFile(NativePath build_path, BuildSettings buildsettings, GeneratorSettings settings) diff --git a/test/cache-generated-test-config.sh b/test/cache-generated-test-config.sh new file mode 100755 index 000000000..9f5ca6f7a --- /dev/null +++ b/test/cache-generated-test-config.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +. $(dirname "${BASH_SOURCE[0]}")/common.sh +cd ${CURR_DIR}/cache-generated-test-config +rm -rf .dub + +${DUB} test --compiler=${DC} + +STAT="stat -c '%Y'" +[[ "$OSTYPE" == "darwin"* ]] && STAT="stat -f '%m' -t '%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/*dub_test_root.d)")" +[ -z "$MAIN_TIME" ] && die $LINENO 'no MAIN_TIME was found' + +${DUB} test --compiler=${DC} +MAIN_FILES_COUNT=$(ls .dub/code/*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/*dub_test_root.d | head -n1)")" ] && die $LINENO 'The test main file has been rebuilt' + +exit 0 \ No newline at end of file diff --git a/test/cache-generated-test-config/.no_build b/test/cache-generated-test-config/.no_build new file mode 100644 index 000000000..e69de29bb diff --git a/test/cache-generated-test-config/.no_run b/test/cache-generated-test-config/.no_run new file mode 100644 index 000000000..e69de29bb diff --git a/test/cache-generated-test-config/.no_test b/test/cache-generated-test-config/.no_test new file mode 100644 index 000000000..e69de29bb diff --git a/test/cache-generated-test-config/dub.sdl b/test/cache-generated-test-config/dub.sdl new file mode 100644 index 000000000..ccfd0a222 --- /dev/null +++ b/test/cache-generated-test-config/dub.sdl @@ -0,0 +1,3 @@ +name "cache-generated-test-config" + +targetType "staticLibrary" \ No newline at end of file diff --git a/test/cache-generated-test-config/source/test.d b/test/cache-generated-test-config/source/test.d new file mode 100644 index 000000000..c6e2276ca --- /dev/null +++ b/test/cache-generated-test-config/source/test.d @@ -0,0 +1,6 @@ +module test; + +unittest +{ + assert(true); +} \ No newline at end of file