Skip to content

Commit

Permalink
Ninja reruns reggae when file contents changed
Browse files Browse the repository at this point in the history
  • Loading branch information
atilaneves committed Sep 7, 2023
1 parent 7485274 commit 8471eaf
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 102 deletions.
2 changes: 1 addition & 1 deletion dub.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"tests/projects/dub/source/main.d",
"tests/projects/dub_prebuild/source/lemain.d",
"tests/projects/implicits/main.d",
"tests/projects/phony_proj/main.d",
"tests/projects/phony_proj/src/main.d",
"tests/projects/export_proj/hello.d",
"tests/projects/dub_postbuild/source/app.d",
"tests/projects/dub_postbuild/reggaefile.d",
Expand Down
62 changes: 58 additions & 4 deletions payload/reggae/backend/ninja.d
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,20 @@ struct Ninja {

//includes rerunning reggae
const(NinjaEntry)[] allBuildEntries() @safe {
immutable files = flattenEntriesInBuildLine(_options.reggaeFileDependencies);
import std.array: join;
import std.algorithm: sort, uniq;

const files =
flattenEntriesInBuildLine(_options.reggaeFileDependencies)
~ " " ~ _dlangSrcDirs.sort.uniq.join(" ")
;
auto paramLines = _options.oldNinja ? [] : ["pool = console"];

const(NinjaEntry)[] rerunEntries() {
// if exporting the build system, don't include rerunning reggae
return _options.export_ ? [] : [NinjaEntry("build build.ninja: _rerun | " ~ files,
paramLines)];
return _options.export_
? []
: [NinjaEntry("build build.ninja: _rerun | " ~ files, paramLines)];
}

const defaultOutputs = _build.defaultTargetsOutputs(_projectPath);
Expand Down Expand Up @@ -90,10 +97,14 @@ private:
string _projectPath;
const(Options) _options;
int _counter = 1;
// we keep a list of directories with sources here to add them as
// dependencies for a reggae rerun
string[] _dlangSrcDirs;

void defaultRule(Target target) @safe {
import std.algorithm: canFind, map;
import std.algorithm: canFind, map, startsWith;
import std.array: join, replace;
import std.path: extension;

static string flattenShellArgs(in string[] args) {
static string quoteArgIfNeeded(string a) {
Expand All @@ -120,6 +131,45 @@ private:
const buildLine = buildLine(target, ruleName, /*includeImplicitInputs=*/true);

buildEntries ~= NinjaEntry(buildLine, paramLines);
maybeAddDirDependencies(target, ruleName);
}

// For D source code, add the directories that contain them to the
// dependencies for rerunning reggae so it picks up new files.
private void maybeAddDirDependencies(in Target target, in string ruleName) @safe pure {
import std.algorithm: startsWith, filter, map, sort, uniq, joiner, canFind;
import std.path: extension, dirName;
import std.array: array;
import std.format: format;

if(!ruleName.startsWith("_dcompile"))
return;

const outputs = target.expandOutputs(_projectPath);

static bool isDlangSrcFile(in Target t) {
return t.rawOutputs.length == 1
&& t.dependencyTargets.length == 0
&& t.rawOutputs[0].extension == ".d";
}

auto dlangSrcs = target
.dependencyTargets
.filter!isDlangSrcFile;

if(dlangSrcs.empty)
return;

auto dlangDirs = dlangSrcs
.map!(t => t.expandOutputs(_projectPath)[0])
.map!dirName;

_dlangSrcDirs ~= dlangDirs
// otherwise ninja will emit this as 2 or more dependencies
.filter!(d => !d.canFind(" "))
.array;

return;
}

void phonyRule(Target target) @safe {
Expand Down Expand Up @@ -373,6 +423,10 @@ private:
private string[] targetDependencies(in Target target) @safe pure const {
return target.dependenciesInProjectPath(_projectPath);
}

private string dirSentinelFileName(in Target target) @safe pure const {
return target.expandOutputs(_projectPath)[0] ~ ".files.txt";
}
}


Expand Down
17 changes: 13 additions & 4 deletions tests/it/runtime/dependencies.d
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ version(DigitalMars) {
"reggaefile.d",
q{
import reggae;
import constants;
import other.constants;
alias exe = executable!(ExeName(exeName), Sources!("source"));
mixin build!exe;
}
);
writeFile("constants.d", q{enum exeName = "foo"; void lefoo() { }});
writeFile("other/constants.d", q{enum exeName = "foo"; void lefoo() { }});
writeFile("source/main.d", "void main() { }");

runReggae("-b", backend);
Expand All @@ -33,8 +33,17 @@ version(DigitalMars) {
// been identified as an implicit dependency of the reggaefile.
// If things actually worked, we'd assert that there's now a file named
// `bar`.
writeFile("constants.d", q{enum exeName = "bar"; void lefoo() { }});
auto lines = mixin(backend).shouldFailToExecute;
writeFile("other/constants.d", q{enum exeName = "bar"; void lefoo() { }});
mixin(backend).shouldFailToExecute.shouldContain("reggae");

runReggae("-b", backend); // but this should be fine
mixin(backend).shouldExecuteOk; // it's rerun, so ninja succeeds

static if(backend == "ninja") {
// test that adding a file triggers a rerun
writeFile("source/foo.d");
mixin(backend).shouldFailToExecute.shouldContain("reggae");
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/projects/phony_proj/reggaefile.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module phony_proj.reggaefile;
import reggae;
import reggae.path: buildPath;

alias app = scriptlike!(App(SourceFileName("main.d"), BinaryFileName("app" ~ exeExt)));
alias app = scriptlike!(App(SourceFileName("src/main.d"), BinaryFileName("app" ~ exeExt)));
alias doit = phony!("doit", buildPath("./app"), app);

mixin build!(app, optional!(doit));
File renamed without changes.
91 changes: 0 additions & 91 deletions tests/ut/drules.d

This file was deleted.

1 change: 0 additions & 1 deletion tests/ut_main.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ mixin runTestsMain!(
"tests.ut.options",
"tests.ut.serialisation",
"tests.ut.realistic_build",
"tests.ut.drules",
"tests.ut.backend.binary",
"tests.ut.backend.ninja",
"tests.ut.backend.make",
Expand Down

0 comments on commit 8471eaf

Please sign in to comment.