Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for environment variable NINJA_FLAGS #1399

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion doc/manual.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ you don't need to pass `-j`.)
Environment variables
~~~~~~~~~~~~~~~~~~~~~

Ninja supports one environment variable to control its behavior:
Ninja supports two environment variables to control its behavior:
`NINJA_STATUS`, the progress status printed before the rule being run.

Several placeholders are available:
Expand All @@ -212,6 +212,16 @@ The default progress status is `"[%f/%t] "` (note the trailing space
to separate from the build rule). Another example of possible progress status
could be `"[%u/%r/%f] "`.

`NINJA_FLAGS`, flags to be set before the command line arguments are parsed.

The value of the variable is parsed like command line arguments. You can for
instance use less cores than available (-j), or limit the parallelism based
on the system load (-l). For instance, on a build server used by multiple
users, you may want to set `NINJA_FLAGS=-l 1` on the system level, so that
the server never gets overloaded by parallel ninja builds. Command line
parameters override the flags set with NINJA_FLAGS.


Extra tools
~~~~~~~~~~~

Expand Down
72 changes: 68 additions & 4 deletions src/ninja.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1034,9 +1034,8 @@ int ExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {

/// Parse argv for command-line options.
/// Returns an exit code, or -1 if Ninja should continue.
int ReadFlags(int* argc, char*** argv,
int ReadFlagsFromArray(int* argc, char*** argv,
Options* options, BuildConfig* config) {
config->parallelism = GuessParallelism();

enum { OPT_VERSION = 1 };
const option kLongOptions[] = {
Expand All @@ -1045,6 +1044,7 @@ int ReadFlags(int* argc, char*** argv,
{ NULL, 0, NULL, 0 }
};

optind = 1;
int opt;
while (!options->tool &&
(opt = getopt_long(*argc, *argv, "d:f:j:k:l:nt:vw:C:h", kLongOptions,
Expand Down Expand Up @@ -1118,15 +1118,79 @@ int ReadFlags(int* argc, char*** argv,
return -1;
}

int ReadFlagsFromCommandLine(int* argc, char*** argv,
Options* options, BuildConfig* config) {
int exit_code = ReadFlagsFromArray(argc, argv, options, config);
if ( exit_code == -1 ) {
*argv += optind;
*argc -= optind;
}
return exit_code;
}

int ReadFlagsFromEnv(Options* options, BuildConfig* config) {
char *str = getenv("NINJA_FLAGS");
if (str == NULL || strlen(str) == 0 )
return -1;

char *str_copy = (char *)malloc(strlen(str)+1);
char **argv = (char **)calloc(strlen(str), sizeof(char *));
int argc = 0, i = 0;
bool in_arg = false;

argv[argc++] = (char *)""; // fake argv[0] (command) for getopt
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

travis is failing because

src/ninja.cc:1141:16: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
   argv[argc++] = ""; // fake argv[0] (command) for getopt
                ^

(click the red x to get to that: https://travis-ci.org/ninja-build/ninja/builds/354768286?utm_source=github_status&utm_medium=notification)


while(str[i] != 0) {
switch(str[i]) {
case ' ':
case '\t':
str_copy[i] = 0; // replace separators by 0 in the copy
in_arg = false;
break;
default:
str_copy[i] = str[i];
if (in_arg) {
break;
}
else {
argv[argc++] = &(str_copy[i]);
in_arg = true;
break;
}
}
i++;
}
char **argv_copy = argv; // ReadFlagsFromArray modifies argv, so create a copy
int exit_code = ReadFlagsFromArray(&argc, &argv_copy, options, config);

free(argv);
free(str_copy);

return exit_code;
}

int ReadConfig(int* argc, char*** argv, Options* options, BuildConfig* config) {
// Default values:
config->parallelism = GuessParallelism();
options->input_file = "build.ninja";

// Read config from the environment:
int exit_code = ReadFlagsFromEnv(options, config);
if (exit_code >= 0)
return exit_code;

// Read config from the command line:
return ReadFlagsFromCommandLine(argc, argv, options, config);;
}

int real_main(int argc, char** argv) {
BuildConfig config;
Options options = {};
options.input_file = "build.ninja";

setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
const char* ninja_command = argv[0];

int exit_code = ReadFlags(&argc, &argv, &options, &config);
int exit_code = ReadConfig(&argc, &argv, &options, &config);
if (exit_code >= 0)
return exit_code;

Expand Down