It could be a new tool named 'autoclean' or a new option to the 'clean' tool.
--
You received this message because you are subscribed to the Google Groups "ninja-build" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ninja-build...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Hi Avinash,here are a few points that make me somewhat skeptical about this feature:* It only cleans up files that ninja has in its .ninja_log as far as I understand – if you have a build edge that as far as ninja knowns only writes a stamp file but that also creates a bunch of .h files as a side effect, they won't be cleaned up by this feature.
* Many projects have one bot that does continuous full builds (which removes the output directory and deletes all files not known to source control), which already mostly handles this (and other) issues.
* Keeping unused lines in .ninja_log around slows down ninja (https://github.com/martine/ninja/issues/661). I think we might want to garbage-collect these lines somehow eventually, for build performance, which would be much harder to do if this autoclean feature was implemented.
Could this be done in the generator program?It seems like the natural place to perform this removal of "abandoned outputs" is in the generator program, rather than repeatedly checking per-build.Or to phrase it another way: in what scenario would an "autoclean" be triggered that is *not* immediately after a build.ninja regeneration?-- Sean Silva
The generator doesn't usually know about the set of outputs it built previously, so I don't think this can be solved without help from ninja.
I think a hybrid approach would be best:- Add an 'autoclean' tool to ninja which garbage collects the log file *and* deletes the output files on disk- After build generation, the generator manually runs autocleanIn theory the only time the outputs change is when the generator runs.However, this still fails to address the stamp file problem, where the stamp file is deleted and the stale .h is left on disk. If it solves the common case for .pb.h files, it might be worth it.
Hi Everyone, thanks for the good discussion. I think there are a lot of good ideas here, and implementing in the generator is nifty, but ...I still find there to be several issues with externalizing RAO, as compared to my patch. Please consider:#1: If RAO is implemented in the generator, and occurs *after* build.ninja is written out, there is a race condition with CTRL+C. If I CTRL+C the build immediately after build.ninja is written, but before RAO executes, then on the next incremental build, ninja would consider build.ninja up-to-date, and RAO will be skipped. This effectively fails to solve my abandoned headers problem.#2: If the generator implements RAO, it's not removing abandoned output entries from the build log.#3: If the generator implements RAO *before* build.ninja is written out, race-condition averted. But now the generator must explicitly track all of its own outputs. Not a fun problem to have if the generator isn't globally tracking everything already.#4: Making RAO the generator's responsibility means having to re-implement N times. It may be OK for my own personal generator (pynja). But at my workplace we use CMake, and I'm not interested in figuring out how to implement RAO in the CMake code [even ignoring the other issues]. (yes, there is an element of human stubborn-ness here, but I don't like having to modify the whole world whenever possible :-) )#5: I could work-around all of the above issues by writing a shell script to the effect of: ninja; separate-rao-tool; ninja . This would give me the correct result and be race-free. However, in the worst case it would be grossly inefficient.Imagine I modify a common.h and rename a generated header in the same change, but don't change my #include statements. The script would fully build (successfully) on the first ninja, since abandoned headers are still on disk; this could take minutes. Then after RAO, I discover the whole build fails.In contrast, the proposed patch discovers the build error as quickly as possible.Also, I'm not averse to adding an extra commandline option to control enablement of this feature; just need to pick name + defaults. I tend to think most builds would benefit from this, and no correct build would fail from it, so I lean towards 'RAO enabled by default'.
I know of a build somewhere that basically does:1. Write a build.ninja2. Run ninja3. Write different build.ninja in same place, with different output paths4. Run ninjaIf this is on by default, 4 would delete the build products from 2, right?
- If multiple X.ninja files produce the same output, I think you could end up in perma-dirty situations when alternating builds between them. So I'm not sure this is a valid case to consider.
I know of a build somewhere that basically does:1. Write a build.ninja2. Run ninja3. Write different build.ninja in same place, with different output paths4. Run ninjaIf this is on by default, 4 would delete the build products from 2, right?Great point! Seems like this would happen because the .ninja_log etc. are shared across all *.ninja files in that directory.So, my solution would be to give each X.ninja a separate .ninja_log-X, .ninja_deps-X, and [new in patch] .ninja_regen-X.
- If all X.ninja files control non-overlapping sets of outputs, then the above problem is resolved.
- If multiple X.ninja files produce the same output, I think you could end up in perma-dirty situations when alternating builds between them. So I'm not sure this is a valid case to consider.
I updated my branch/patch with this, if you're curious to see.Also, I'd be curious to know which build system does this; I'd guess there are interesting optimizations around this.
Minor side point: Incidentally, this change would also allow multiple .ninja files in one directory to safely be built concurrently. Currently, appending to .ninja_log uses append-writes via fwrite (using FILE*), but those are buffered within the process and not guaranteed to be atomic. You could change to using [linux] open(O_APPEND) + write or [windows] CreateFile(FILE_APPEND_DATA) + WriteFile to fix this when building on a local file system; all bets still off on a network FS.
It's a variant of an existing android ndk build script: https://github.com/awong-dev/ndk/blob/master/build/tools/build-cxx-stl.sh This is called repeatedly, and it overwrites build.ninja each time.
Maxim: In your case, each build.<platform>.ninja produces unique output files per <platform> right? That should be all good with RAO.