Skip to content

Commit

Permalink
Add a flag to remain persistent.
Browse files Browse the repository at this point in the history
Large projects (e.g. Android, with its 1GB+ ninjafiles) can take
multiple seconds to parse ninjafiles, leading to a very painful
edit-compile-test cycle. Add a flag that causes ninja to remain
persistent and run a build upon receiving input to stdin, speeding up
a no-op incremental build of a directory in Android from 10 seconds to
under 200 milliseconds.
  • Loading branch information
jmgao committed Feb 21, 2018
1 parent e234a7b commit 78adfff
Showing 1 changed file with 38 additions and 2 deletions.
40 changes: 38 additions & 2 deletions src/ninja.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ struct Options {

/// Whether phony cycles should warn or print an error.
bool phony_cycle_should_err;

/// Whether to remain persistent.
bool persistent;
};

/// The Ninja main() loads up a series of data structures; various tools need
Expand Down Expand Up @@ -210,6 +213,7 @@ void Usage(const BuildConfig& config) {
" -k N keep going until N jobs fail [default=1]\n"
" -l N do not start new jobs if the load average is greater than N\n"
" -n dry run (don't run commands but act like they succeeded)\n"
" -p persist and rebuild upon receiving a line of input on stdin\n"
" -v show all command lines while building\n"
"\n"
" -d MODE enable debugging (use '-d list' to list modes)\n"
Expand Down Expand Up @@ -1047,7 +1051,7 @@ int ReadFlags(int* argc, char*** argv,

int opt;
while (!options->tool &&
(opt = getopt_long(*argc, *argv, "d:f:j:k:l:nt:vw:C:h", kLongOptions,
(opt = getopt_long(*argc, *argv, "d:f:j:k:l:nt:vw:C:ph", kLongOptions,
NULL)) != -1) {
switch (opt) {
case 'd':
Expand Down Expand Up @@ -1103,6 +1107,9 @@ int ReadFlags(int* argc, char*** argv,
case 'C':
options->working_dir = optarg;
break;
case 'p':
options->persistent = true;
break;
case OPT_VERSION:
printf("%s\n", kNinjaVersion);
return 0;
Expand All @@ -1118,6 +1125,19 @@ int ReadFlags(int* argc, char*** argv,
return -1;
}

static void WaitForInput(const BuildConfig& config) {
static char* buf = NULL;
static size_t len = 0;

if (config.verbosity == BuildConfig::VERBOSE) {
fprintf(stderr, "ninja waiting for input...\n");
}
ssize_t rc = getline(&buf, &len, stdin);
if (rc < 0) {
exit(0);
}
}

int real_main(int argc, char** argv) {
BuildConfig config;
Options options = {};
Expand Down Expand Up @@ -1194,7 +1214,23 @@ int real_main(int argc, char** argv) {
return 1;
}

int result = ninja.RunBuild(argc, argv);
int result = 0;
do {
Stopwatch stopwatch;

if (options.persistent) {
WaitForInput(config);
stopwatch.Restart();
}

result = ninja.RunBuild(argc, argv);
if (options.persistent) {
fprintf(stderr, "build %s in %0.3f seconds\n",
result == 0 ? "succeeded" : "failed", stopwatch.Elapsed());
ninja.state_.Reset();
}
} while (options.persistent);

if (g_metrics)
ninja.DumpMetrics();
return result;
Expand Down

0 comments on commit 78adfff

Please sign in to comment.