I am facing an issue where changes to definitions in C++ headers don't cause the Swift code that uses them to recompile when building with CMake using Ninja.
Should CMake/Ninja be able to detect changes to definitions in C++ headers used in Swift and recompile when necessary? What can be done to make the example below work so that changes take effect when doing incremental builds?
Example
include/module.modulemap
module Foo {
header "Foo.hpp"
}
include/Foo.hpp
#pragma once
inline int hpp() {
return 1; // <--
}
int cpp();
So for C/C++, Ninja reads the dependency file emitted by clang and adds it to Ninja's internal dependency graph so that when it sees that file change, it implicitly knows which targets to rebuild. It only accepts one dependency file per target though.
The Swift driver emits one dependency file per frontend invocation, so in most cases, there are multiple dependency files for a Swift target. This isn't fed into Ninja, so Ninja doesn't know about the dependency. This isn't really something that CMake knows about either since it's the driver discovering the dependency.
Hand-writing a quick deps file and feeding it into Ninja seems to support this. Please file a bug report on the Driver asking for single dep-file output per invocation and I can wire that into CMake pretty easily once we have that. Thanks.
What does frontend invocation mean exactly? If I pass 2 Swift files in one swiftc invocation, does it count as 2 frontend invocations?
Each Swift file produces 1 object file and 1 dependency file, but as multiple Swift files are passed within a single swiftc invocation, they are treated as parts of the same Ninja target?
So Ninja needs a single dependency file (*.d) that has the combined dependencies of all the Swift files included in the swiftc invocation? And there isn't an option in swiftc to generate that file yet?
Thanks for the clarification! I can file an issue tomorrow on the swift-driver repository if someone hasn't already done so by then.
Out of curiosity, how are projects that make use of Swift C++ interoperability with CMake handling this issue currently? I feel like this could cause some major problems during development, and I find it odd that it hasn't been resolved yet. I assume that the fix will take some time to appear in official releases of Swift and CMake, so I wonder what would be the best solution to keep the headers in check in the meantime?
Yeah, I don't know when it will land. If you notice it, you can probably touch one of the Swift sources in the target importing the C/C++ header. Ninja will see that the Swift source is dirty and rebuild that target.
If you're feeling adventurous, you could scoop up the generated *.swift.o.d for the target, merge them, and feed that into Ninja. Ninja will consume that file unless you pass -d keepdepfile. The hand-crafted deps file won't stay in sync with the Swift source or the module maps, so if you add an import or modify the module map that the target is importing, you'll need to update it to reflect the dependencies.