diff --git a/source/dub/generators/ninja.d b/source/dub/generators/ninja.d index 79b8a756b..12588239a 100644 --- a/source/dub/generators/ninja.d +++ b/source/dub/generators/ninja.d @@ -37,7 +37,9 @@ class NinjaGenerator : ProjectGenerator f.writeln("ar = ar"); f.writeln(); f.writeln("rule dc"); - f.writeln(" command = ", compiler, " $flags -c $in -of=$out"); + 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"); @@ -69,13 +71,15 @@ class NinjaGenerator : ProjectGenerator { auto bs = info.buildSettings; - auto importFlags = bs.importPaths.map!(p => "-I" ~ p).join(" "); + 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; diff --git a/test/ninja-makedeps.script.d b/test/ninja-makedeps.script.d new file mode 100644 index 000000000..737b78c8f --- /dev/null +++ b/test/ninja-makedeps.script.d @@ -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 --git a/test/ninja-makedeps/dub.json b/test/ninja-makedeps/dub.json new file mode 100644 index 000000000..7d9b84f35 --- /dev/null +++ b/test/ninja-makedeps/dub.json @@ -0,0 +1,4 @@ +{ + "name": "ninja-makedeps", + "targetType": "executable" +} diff --git a/test/ninja-makedeps/source/app.d b/test/ninja-makedeps/source/app.d new file mode 100644 index 000000000..c42ee2a33 --- /dev/null +++ b/test/ninja-makedeps/source/app.d @@ -0,0 +1,2 @@ +import helper; +void main() { helperFunc(); } diff --git a/test/ninja-makedeps/source/helper.d b/test/ninja-makedeps/source/helper.d new file mode 100644 index 000000000..d76364d35 --- /dev/null +++ b/test/ninja-makedeps/source/helper.d @@ -0,0 +1 @@ +void helperFunc() {}