On 1/23/25 3:29 PM, Evan Martin wrote:
> On Thursday, January 23, 2025 at 9:52:23 AM UTC-8
di...@google.com wrote:
>
>
> - *No "existence" support*: A missing input file (i.e. a path that
> appears in the Ninja build graph that is not generated by a build rule) is
> an error, period.
>
> I'm not sure this is true. I believe you can use 'phony' rules to mark
> files as optional. It's in the manual here, see "dummy targets":
>
https://ninja-build.org/manual.html#_the_literal_phony_literal_rule
>
> I tried this:
>
> rule wc
> command = wc -l $in > $out
>
> build b: phony # marks b as phony
> build demo: wc a b
>
> This fails to build if the file 'a' is missing, but if you 'touch a' then
> run you'll see it executes the 'wc' command (which then fails because 'b'
> is missing).
That is not what is being asked about. Also it doesn't really work as
expected. Since b is a phony rule, wc will be rerun every time you
invoke ninja.
Going back to the original request...
> 2. *optional* config files: EFINAE: existence failure is not an error,
> but a change in existence may affect compiler flags,
The idea is that when you first run the command, it doesn't matter
whether b exists, the command runs successfully (unlike wc, it doesn't
consider the file not existing to be a problem). And if you run ninja
again, it will say everything is up to date.
If you *create* b, then now demo is stale and will be rebuilt. And then
if you delete b again, then demo is stale again and will be rebuilt again.
For a better idea of how and why this is actually supposed to operate,
consider this case. It's a contrived case and I'm not convinced it makes
sense to support, but there is at least one dependency graph runner (not
ninja, not make) that considers it vital and also thinks both make and
ninja suck for not supporting it.
Here's a build.ninja:
rule c_COMPILER
command = gcc $ARGS -MD -MQ $out -MF $DEPFILE -o $out -c $in
deps = gcc
depfile = $DEPFILE_UNQUOTED
description = Compiling C object $out
rule c_LINKER
command = gcc $ARGS -o $out $in $LINK_ARGS
description = Linking target $out
build prog: c_LINKER prog.p/prog.c.o
LINK_ARGS = -Wl,--as-needed -lmylib
build prog.p/prog.c.o: c_COMPILER ../prog.c
DEPFILE = prog.p/prog.c.o.d
DEPFILE_UNQUOTED = prog.p/prog.c.o.d
ARGS = -I. -I../
Now, prog.c exists in your source tree, and it does #include "mylib.h"
which is installed on your system in /usr/include (and -lmylib is
unsurpisingly in /usr/lib64 linked to libmylib.so.1, ABI version 1). If
you compile:
ninja prog.p/prog.c.o
You'll get an object file that is based on the header functionality
defined in /usr/include/mylib.h
Plot twist. Don't link prog yet. First, go download a new version of
"mylib", and sudo make install it into /usr/local.
*Now* go ahead and finish building your project. Your object file still
uses the types from /usr/include/mylib.h, but it links to
/usr/local/lib64/libmylib.so -> libmylib.so.2
The universe now explodes. Or at least your binary does. If you do a
clean, then recompile, the object file would use
/usr/local/include/mylib.h and all would be well.
The theory here is that a build system which supports existence checks
can take a rule like this:
build prog.p/prog.c.o: c_COMPILER ../prog.c
and declare, possibly via a depfile, that it has a header dependency
which looks like this:
prog.p/prog.c.o: /usr/include/mylib.h !/usr/local/include/mylib.h
Really, it would define a "not" rule for every possible search path
permutation of any header file it utilizes. Then if you ever create any
of those files, ninja can say "well, obviously the build is now stale,
because if I recompile I'll get something different from last time".
It is technically true that there is a difference here. In practice
that's not how people put together software (and that's why effectively
nobody uses the dependency graph runner in question). Of course, people
can come up with lots of reasons why existence checks should maybe
matter that don't have to do with changing your dependency installation
locations, but I'm not sure I'm convinced any of them are really any
better. In order for "existence checks" to be useful, you have to know
in advance you're going to create a file in a specific location in the
future...
--
Eli Schwartz