Ninja: Support setting verbosity through the environment

Created on 28 Dec 2017  ·  14Comments  ·  Source: ninja-build/ninja

Sometimes, regrettably, using the environment is the cleanest way to configure applications.

e.g. MAKEFLAGS, DISTCC_HOSTS, etc.

It would be useful if one could control ninja's verbosity through the environment.

e.g. have

VERBOSE=1 ninja

be (nearly) equivalent to

ninja -v

A nice use-case that this enables is having a single UI nob to turn on verbosity for both Ninja,
and any ninja-invoked scripts.

Most helpful comment

I don't have that directory on my linux machine, apparently.

I'm not able to find reference to it in the file-system hierarchy standard http://www.pathname.com/fhs/pub/fhs-2.3.pdf

I did find a reference to /usr/local/sbin in the FHS though, perhaps that's what you meant? Seems strange to use an "sbin" folder for this.

Presumably, /usr/local/bin is supposed to be on the PATH before /usr/bin and others.

However, that's not what you said. You said this:

In that case you can avoid the modification of PATH by renaming the ninja binary and putting the script at its place.

And that's a bad suggestion, riddled with security and ongoing maintenance problems.

Putting a script in a system-wide directory that's always included before everything else is a better way to do it than renaming the binary and plopping a script in it's place.

Nevertheless, I've yet to see an explanation of why we're not just including this in ninja itself, that was self-consistent, didn't add a bunch of overhead from calling a script and/or "everyone needs to write their own script now", and pointed to the guidelines for the ninja project as documented here on github.

All 14 comments

I think in cases like this you can make a shell script to obey your environment variables. Otherwise I can think of equivalent environments where someone wants VERBOSE=1 to control the verbosity of a program other than Ninja.

I think in cases like this you can make a shell script to obey your environment variables.

These environment variables are for ninja, so how would they be obeyed if ninja doesn't recognise them?

Additionally it's not always feasable, or reasonable, to modify the command-line of tools in scripts as there may be far too numerous. What you're suggesting is each script adopt a unique way of adjusting flags passed to the command, which is also unreasonable.

I've read the other PRs and issues associated with this situation and find none of the replies to be very well thought through. In each case it is simply assumed that the user has direct control over where and how ninja is executed or is even in a position to realistically do anything about it, especially when configuration systems generate ninja.build scripts as part of the pipeline.

These environment variables are for ninja, so how would they be obeyed if ninja doesn't recognise them?

The script would recognise them and pass e.g. -v to ninja.

So as I predicted, you expect every script, or even script-like thing to encode its own set of logic to pass options to ninja. That's not reasonable at all.

No, you only need one script to do that, which you name ninja and put it in your PATH before the real ninja exectuable.

I thought this was covered in the other numerous issue reports already? That's also not reasonable as it now starts to effect reproducibility build pipelines where environments are feasible to track. It also assumes people have the ability to do what you're suggesting (think secure PATH).

That's also not reasonable as it now starts to effect reproducibility build pipelines where environments are feasible to track.

You would have your script always there, then you can track VERBOSE just as you would if ninja itself handled it.

think secure PATH

What do you mean by that?

I'm not interested in VERBOSE, I think the other suggestions of exposing the flags via NINJAFLAGS is more appropriate as suggested in many other issues about this topic.

Again, this is an unreasonable request when you manage hundreds of packages, some of which use cmake to generate ninja build scripts. Creating an unncessary wrapper to act as dependency is overly involved when traditional systems such as make (with properly generated or written Makefiles) continue to honour not only the de facto environments such as CFLAGS, CXXFLAGS, LDFLAGS, etc. but also MAKEFLAGS where many of us would set something to the effect of -j$(nproc).

This again comes to notion of a secure path; systems like sudo and build/CI scripts will set PATH to a known good default to avoid any potential pollution of the build usually also underpinned by a clean chroot.

some of which use cmake to generate ninja build scripts.

I don't see how this changes anything?

This again comes to notion of a secure path; systems like sudo and build/CI scripts will set PATH to a known good default to avoid any potential pollution of the build usually also underpinned by a clean chroot.

In that case you can avoid the modification of PATH by renaming the ninja binary and putting the script at its place.

And around we go

In that case you can avoid the modification of PATH by renaming the ninja binary and putting the script at its place.

This is very inappropriate to suggest.

Users should never be mucking about with system level binaries.

It's not appropriate for a multi-user system for the system-level binary to be renamed and replaced with a script.

I'll say it again for the record: I maintain a bespoke buildsystem for a C++ development team, it compiles some multiple millions of lines of C++ code. It used to do a lot of things directly, but now it generates ninja files, and things are happy. So I have a few clues to rub together when I talk about this.

What I want: For the ninja binary to recognize a single environment variable that sets various defaults, including verbosity and such.

What I can accept: Ninja responds to several environment variables.

What's not acceptable: Needing to write a wrapper script.

Why that's not acceptable: When deploying on Windows, that would work fine, I suppose. But it's not acceptable on Linux, because we rely on the system's ninja package to provide functionality. So when deploying to Linux systems, your suggestion here is "Oh, just rename the system level ninja package, and replace it with a script" screams security problems, and maintenance problems. Among other things, now I've got to baby sit the system any time the ninja package gets updated by the system's package manager.

This is not a risky feature to add to the program. Ninja's job is not to protect users from themselves. If a user somehow manages to fuck it up, that's on them.

The probability of adding a feature like this to Ninja slowing Ninja down by more than a few micro seconds is so low as to be non-existent, but your proposal is that we use a wrapper script, which involves executing a script interpreter every time ninja gets launched, which is Far and away more overhead than a few string comparisons in an already executing binary.

So when deploying to Linux systems, your suggestion here is "Oh, just rename the system level ninja package, and replace it with a script" screams security problems, and maintenance problems.

No, when deploying to Linux my suggesting would be to put the script into /usr/local/bin.

I don't have that directory on my linux machine, apparently.

I'm not able to find reference to it in the file-system hierarchy standard http://www.pathname.com/fhs/pub/fhs-2.3.pdf

I did find a reference to /usr/local/sbin in the FHS though, perhaps that's what you meant? Seems strange to use an "sbin" folder for this.

Presumably, /usr/local/bin is supposed to be on the PATH before /usr/bin and others.

However, that's not what you said. You said this:

In that case you can avoid the modification of PATH by renaming the ninja binary and putting the script at its place.

And that's a bad suggestion, riddled with security and ongoing maintenance problems.

Putting a script in a system-wide directory that's always included before everything else is a better way to do it than renaming the binary and plopping a script in it's place.

Nevertheless, I've yet to see an explanation of why we're not just including this in ninja itself, that was self-consistent, didn't add a bunch of overhead from calling a script and/or "everyone needs to write their own script now", and pointed to the guidelines for the ninja project as documented here on github.

The independent Ninja build language reimplementation https://github.com/michaelforney/samurai supports this via the environment variable SAMUFLAGS. Simply use samu anywhere you'd otherwise use ninja, or install samu as your system /usr/bin/ninja (some linux distros have options to install this competing implementation as the default, or only, ninja).

Was this page helpful?
0 / 5 - 0 ratings