diff --git a/changelog/pre-post-run-commands.dd b/changelog/pre-post-run-commands.dd new file mode 100644 index 0000000..a9fc6b9 --- /dev/null +++ b/changelog/pre-post-run-commands.dd @@ -0,0 +1,6 @@ +Pre/Post run commands added + +DUB now supports commands preRunCommands which are executed before the target run +and postRunCommands which are executed after the target run. +Environment variable DUB_TARGET_EXIT_STATUS contains the target executable call status +and is available in postRunCommands. \ No newline at end of file diff --git a/source/dub/compilers/buildsettings.d b/source/dub/compilers/buildsettings.d index 939a1f1..0ed9aae 100644 --- a/source/dub/compilers/buildsettings.d +++ b/source/dub/compilers/buildsettings.d @@ -41,6 +41,8 @@ string[] postGenerateCommands; string[] preBuildCommands; string[] postBuildCommands; + string[] preRunCommands; + string[] postRunCommands; @byName BuildRequirements requirements; @byName BuildOptions options; @@ -77,6 +79,8 @@ addPostGenerateCommands(bs.postGenerateCommands); addPreBuildCommands(bs.preBuildCommands); addPostBuildCommands(bs.postBuildCommands); + addPreRunCommands(bs.preRunCommands); + addPostRunCommands(bs.postRunCommands); } void addDFlags(in string[] value...) { dflags ~= value; } @@ -100,6 +104,8 @@ void addPostGenerateCommands(in string[] value...) { add(postGenerateCommands, value, false); } void addPreBuildCommands(in string[] value...) { add(preBuildCommands, value, false); } void addPostBuildCommands(in string[] value...) { add(postBuildCommands, value, false); } + void addPreRunCommands(in string[] value...) { add(preRunCommands, value, false); } + void addPostRunCommands(in string[] value...) { add(postRunCommands, value, false); } void addRequirements(in BuildRequirement[] value...) { foreach (v; value) this.requirements |= v; } void addRequirements(in BuildRequirements value) { this.requirements |= value; } void addOptions(in BuildOption[] value...) { foreach (v; value) this.options |= v; } diff --git a/source/dub/description.d b/source/dub/description.d index c9c347c..d38181a 100644 --- a/source/dub/description.d +++ b/source/dub/description.d @@ -93,6 +93,8 @@ string[] postGenerateCommands; /// commands executed after creating the description string[] preBuildCommands; /// Commands to execute prior to every build string[] postBuildCommands; /// Commands to execute after every build + string[] preRunCommands; /// Commands to execute prior to every run + string[] postRunCommands; /// Commands to execute after every run @byName BuildRequirement[] buildRequirements; @byName BuildOption[] options; SourceFileDescription[] files; /// A list of all source/import files possibly used by the package diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 1895e3b..68ed57b 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -529,19 +529,42 @@ 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(" ")); if (settings.runCallback) { auto res = execute(exe_path_string ~ run_args); 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 result = prg_pid.wait(); + settings.targetExitStatus = result; + runPostRunCommands(m_project.rootPackage, m_project, settings, buildsettings); enforce(result == 0, "Program exited with code "~to!string(result)); } } else enforce(false, "Target is a library. Skipping execution."); } + private void runPreRunCommands(in Package pack, in Project proj, in GeneratorSettings settings, + in BuildSettings buildsettings) + { + if (buildsettings.preRunCommands.length) { + logInfo("Running pre-run commands..."); + runBuildCommands(buildsettings.preRunCommands, pack, proj, settings, buildsettings); + } + } + + private void runPostRunCommands(in Package pack, in Project proj, in GeneratorSettings settings, + in BuildSettings buildsettings) + { + if (buildsettings.postRunCommands.length) { + logInfo("Running post-run commands..."); + runBuildCommands(buildsettings.postRunCommands, pack, proj, settings, buildsettings); + } + } + private void cleanupTemporaries() { foreach_reverse (f; m_temporaryFiles) { diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index 34352ba..8c6736e 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -439,6 +439,7 @@ string buildType; BuildSettings buildSettings; BuildMode buildMode = BuildMode.separate; + int targetExitStatus; bool combined; // compile all in one go instead of each dependency separately @@ -642,6 +643,7 @@ env["DUB_TARGET_TYPE"] = to!string(build_settings.targetType); env["DUB_TARGET_PATH"] = build_settings.targetPath; env["DUB_TARGET_NAME"] = build_settings.targetName; + env["DUB_TARGET_EXIT_STATUS"] = settings.targetExitStatus.text; env["DUB_WORKING_DIRECTORY"] = build_settings.workingDirectory; env["DUB_MAIN_SOURCE_FILE"] = build_settings.mainSourceFile; diff --git a/source/dub/project.d b/source/dub/project.d index d01fe41..2add6fd 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -991,6 +991,8 @@ case "post-generate-commands": return listBuildSetting!"postGenerateCommands"(args); case "pre-build-commands": return listBuildSetting!"preBuildCommands"(args); case "post-build-commands": return listBuildSetting!"postBuildCommands"(args); + case "pre-run-commands": return listBuildSetting!"preRunCommands"(args); + case "post-run-commands": return listBuildSetting!"postRunCommands"(args); case "requirements": return listBuildSetting!"requirements"(args); case "options": return listBuildSetting!"options"(args); @@ -1155,6 +1157,8 @@ dst.addPostGenerateCommands(processVars(project, pack, gsettings, settings.postGenerateCommands)); dst.addPreBuildCommands(processVars(project, pack, gsettings, settings.preBuildCommands)); dst.addPostBuildCommands(processVars(project, pack, gsettings, settings.postBuildCommands)); + dst.addPreRunCommands(processVars(project, pack, gsettings, settings.preRunCommands)); + dst.addPostRunCommands(processVars(project, pack, gsettings, settings.postRunCommands)); dst.addRequirements(settings.requirements); dst.addOptions(settings.options); diff --git a/source/dub/recipe/json.d b/source/dub/recipe/json.d index a254e89..1078945 100644 --- a/source/dub/recipe/json.d +++ b/source/dub/recipe/json.d @@ -220,6 +220,8 @@ case "postGenerateCommands": bs.postGenerateCommands[suffix] = deserializeJson!(string[])(value); break; case "preBuildCommands": bs.preBuildCommands[suffix] = deserializeJson!(string[])(value); break; case "postBuildCommands": bs.postBuildCommands[suffix] = deserializeJson!(string[])(value); break; + case "preRunCommands": bs.preRunCommands[suffix] = deserializeJson!(string[])(value); break; + case "postRunCommands": bs.postRunCommands[suffix] = deserializeJson!(string[])(value); break; case "buildRequirements": BuildRequirements reqs; foreach (req; deserializeJson!(string[])(value)) @@ -267,6 +269,8 @@ foreach (suffix, arr; bs.postGenerateCommands) ret["postGenerateCommands"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.preBuildCommands) ret["preBuildCommands"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.postBuildCommands) ret["postBuildCommands"~suffix] = serializeToJson(arr); + foreach (suffix, arr; bs.preRunCommands) ret["preRunCommands"~suffix] = serializeToJson(arr); + foreach (suffix, arr; bs.postRunCommands) ret["postRunCommands"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.buildRequirements) { string[] val; foreach (i; [EnumMembers!BuildRequirement]) diff --git a/source/dub/recipe/packagerecipe.d b/source/dub/recipe/packagerecipe.d index 7775bdb..7282bc6 100644 --- a/source/dub/recipe/packagerecipe.d +++ b/source/dub/recipe/packagerecipe.d @@ -157,6 +157,8 @@ string[][string] postGenerateCommands; string[][string] preBuildCommands; string[][string] postBuildCommands; + string[][string] preRunCommands; + string[][string] postRunCommands; BuildRequirements[string] buildRequirements; BuildOptions[string] buildOptions; @@ -238,6 +240,8 @@ getPlatformSetting!("postGenerateCommands", "addPostGenerateCommands")(dst, platform); getPlatformSetting!("preBuildCommands", "addPreBuildCommands")(dst, platform); getPlatformSetting!("postBuildCommands", "addPostBuildCommands")(dst, platform); + getPlatformSetting!("preRunCommands", "addPreRunCommands")(dst, platform); + getPlatformSetting!("postRunCommands", "addPostRunCommands")(dst, platform); getPlatformSetting!("buildRequirements", "addRequirements")(dst, platform); getPlatformSetting!("buildOptions", "addOptions")(dst, platform); } diff --git a/source/dub/recipe/sdl.d b/source/dub/recipe/sdl.d index 33dc59d..8d606ce 100644 --- a/source/dub/recipe/sdl.d +++ b/source/dub/recipe/sdl.d @@ -156,6 +156,8 @@ case "postGenerateCommands": setting.parsePlatformStringArray(bs.postGenerateCommands); break; case "preBuildCommands": setting.parsePlatformStringArray(bs.preBuildCommands); break; case "postBuildCommands": setting.parsePlatformStringArray(bs.postBuildCommands); break; + case "preRunCommands": setting.parsePlatformStringArray(bs.preRunCommands); break; + case "postRunCommands": setting.parsePlatformStringArray(bs.postRunCommands); break; case "buildRequirements": setting.parsePlatformEnumArray!BuildRequirement(bs.buildRequirements); break; case "buildOptions": setting.parsePlatformEnumArray!BuildOption(bs.buildOptions); break; } @@ -257,6 +259,8 @@ foreach (suffix, arr; bs.postGenerateCommands) adda("postGenerateCommands", suffix, arr); foreach (suffix, arr; bs.preBuildCommands) adda("preBuildCommands", suffix, arr); foreach (suffix, arr; bs.postBuildCommands) adda("postBuildCommands", suffix, arr); + foreach (suffix, arr; bs.preRunCommands) adda("preRunCommands", suffix, arr); + foreach (suffix, arr; bs.postRunCommands) adda("postRunCommands", suffix, arr); foreach (suffix, bits; bs.buildRequirements) adda("buildRequirements", suffix, toNameArray!BuildRequirement(bits)); foreach (suffix, bits; bs.buildOptions) adda("buildOptions", suffix, toNameArray!BuildOption(bits)); return ret; @@ -400,6 +404,10 @@ preBuildCommands "preb3" postBuildCommands "postb1" "postb2" postBuildCommands "postb3" +preRunCommands "prer1" "prer2" +preRunCommands "prer3" +postRunCommands "postr1" "postr2" +postRunCommands "postr3" dflags "df1" "df2" dflags "df3" lflags "lf1" "lf2" @@ -466,6 +474,8 @@ assert(rec.buildSettings.postGenerateCommands == ["": ["postg1", "postg2", "postg3"]]); assert(rec.buildSettings.preBuildCommands == ["": ["preb1", "preb2", "preb3"]]); assert(rec.buildSettings.postBuildCommands == ["": ["postb1", "postb2", "postb3"]]); + assert(rec.buildSettings.preRunCommands == ["": ["prer1", "prer2", "prer3"]]); + assert(rec.buildSettings.postRunCommands == ["": ["postr1", "postr2", "postr3"]]); assert(rec.buildSettings.dflags == ["": ["df1", "df2", "df3"]]); assert(rec.buildSettings.lflags == ["": ["lf1", "lf2", "lf3"]]); } diff --git a/test/issue1396-pre-post-run-commands.sh b/test/issue1396-pre-post-run-commands.sh new file mode 100755 index 0000000..fdb797e --- /dev/null +++ b/test/issue1396-pre-post-run-commands.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +. $(dirname "${BASH_SOURCE[0]}")/common.sh +cd ${CURR_DIR}/issue1396-pre-post-run-commands +rm -rf .dub +rm -rf test.txt +"$DUB" + +if ! grep -c -e "pre-run" test.txt; then + die $LINENO 'pre run not executed.' +fi + +if ! grep -c -e "post-run-0" test.txt; then + die $LINENO 'post run not executed.' +fi diff --git a/test/issue1396-pre-post-run-commands/.no_build b/test/issue1396-pre-post-run-commands/.no_build new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue1396-pre-post-run-commands/.no_build diff --git a/test/issue1396-pre-post-run-commands/dub.sdl b/test/issue1396-pre-post-run-commands/dub.sdl new file mode 100644 index 0000000..aaad878 --- /dev/null +++ b/test/issue1396-pre-post-run-commands/dub.sdl @@ -0,0 +1,3 @@ +name "test" +preRunCommands "echo pre-run >> test.txt" +postRunCommands "./post-run.sh" \ No newline at end of file diff --git a/test/issue1396-pre-post-run-commands/post-run.sh b/test/issue1396-pre-post-run-commands/post-run.sh new file mode 100755 index 0000000..7b98010 --- /dev/null +++ b/test/issue1396-pre-post-run-commands/post-run.sh @@ -0,0 +1 @@ +echo post-run-$DUB_TARGET_EXIT_STATUS >> test.txt \ No newline at end of file diff --git a/test/issue1396-pre-post-run-commands/source/app.d b/test/issue1396-pre-post-run-commands/source/app.d new file mode 100644 index 0000000..ab73b3a --- /dev/null +++ b/test/issue1396-pre-post-run-commands/source/app.d @@ -0,0 +1 @@ +void main() {}