I'm fiddling with import libraries on Windows and wondering if anyone
has any input on a way to model them in ninja.
When building a .dll, an associated .lib is sometimes generated. This
.lib is what other targets link against to import symbols from the
.dll.
However, the linker is "clever" in emitting this .lib. Amongst other
complications, when the .dll is relinked, if the exported symbols
haven't been modified since last time, the .lib won't be touched
(timestamp not updated).
What I attempted at first was the obvious:
a.lib a.dll : a.obj
link ...
This orders the build correctly, but breaks because when the exports
don't change, a.lib will remain older than a.obj even after the rule
is run, and so the link re-runs every build.
My attempted solution was to wrap the linker invocation, and, if the
.dll was successfully linked, simply to update the timestamp of the
.lib. Unfortunately that also doesn't work because the incremental
linker detects the timestamp update as an unexpected change, and so it
causes a full (slow) relink, rather than an incremental link. ("Slow"
meaning 1m30s, rather than ~5s... so worth worrying about.)
In general, both the .dll and the .lib need to appear in the graph.
The .lib is linked by things that depend on "a", and the .dll is
referenced in post build steps.
I thought perhaps what I was looking for was order-only dependencies, as in:
a.dll : a.obj
link ...
final.exe : ... a.lib || a.dll
final-link ...
as that would seem to express the ordering correctly (I think?). But
then a.lib doesn't exist on a clean build and there's no way to
express that the .dll step will build it, so ninja errors out before
it gets a chance to create it.
So, perhaps I want a.lib to be sort of like the "modified" version of
implicit dependency that headers via depfiles use per
http://martine.github.com/ninja/manual.html#_build_dependencies ? Or
perhaps some way of specifying it as a slightly different type of
output? Or is there some other way I'm missing?
If anyone followed all of that :) and sees a solution, I would be
happy to hear it.
scott
a.dll : a.obj
link ...
final.exe : ... a.lib || a.dll
final-link ...
a.lib: phony
That is, order-only dependency on a.dll, and faking the existence of
a.lib with a phony rule.
Sanity check or wrongness-demo appreciated though!
I think what you want to do is to mark the link rule as restat,
and declare an ordinary dependency from final.exe to a.lib only.
That way, once the linker has run, ninja will consider a.lib to be
clean if it hasn't been touched by the linker. Although a.lib will
then be older than a.obj, Ninja will store some extra information in
the .ninja_log file causing a.lib to be considered clean until a.obj
or one of its dependencies is modified again.
Thanks,
--
Peter
Ah! I thought restat would only recheck the output, but then discover
it was older than the inputs, and still rebuild. But the code looks to
agree with your description. :)
Thanks!