tools/ninja: update to 1.12.1
Update to the most recent stable release, including a new job scheduler and bug fixes. Backport a patch to assist in reworking jobserver support. The original patch for jobserver support requires reworking due to the function CanRunMore() and its usage being significantly changed, including the return becoming an integer instead of a boolean. AcquireToken() must now be used in CanRunMore() in order to quantify how much the job searching loop is able to run at any time, and in order to do so CanRunMore() cannot be a constant function anymore. Added: - 010-backport-gtest.patch Manually Adjust: - 100-make_jobserver_support.patch Signed-off-by: Michael Pratt <mcpratt@pm.me> Link: https://github.com/openwrt/openwrt/pull/16693 Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
df303c7ef4
commit
ac483e1c2a
|
@ -1,12 +1,12 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=ninja
|
PKG_NAME:=ninja
|
||||||
PKG_VERSION:=1.11.1
|
PKG_VERSION:=1.12.1
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://codeload.github.com/ninja-build/ninja/tar.gz/v$(PKG_VERSION)?
|
PKG_SOURCE_URL:=https://codeload.github.com/ninja-build/ninja/tar.gz/v$(PKG_VERSION)?
|
||||||
PKG_HASH:=31747ae633213f1eda3842686f83c2aa1412e0f5691d1c14dbbcc67fe7400cea
|
PKG_HASH:=821bdff48a3f683bc4bb3b6f0b5fe7b2d647cf65d52aeb63328c91a6c6df285a
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/host-build.mk
|
include $(INCLUDE_DIR)/host-build.mk
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
From afcd4a146fb82843f6ff695f89504ce4ca65ddfd Mon Sep 17 00:00:00 2001
|
||||||
|
From: David 'Digit' Turner <digit+github@google.com>
|
||||||
|
Date: Sun, 12 May 2024 23:45:28 +0200
|
||||||
|
Subject: [PATCH] configure.py: Support --gtest-source-dir to build tests.
|
||||||
|
|
||||||
|
Allow the Ninja build plan generated by configure.py to
|
||||||
|
build `ninja_test` by compiling GoogleTest from source if
|
||||||
|
the path to the library if passed through the new option
|
||||||
|
`--gtest-source-dir` or the GTEST_SOURCE_DIR environment
|
||||||
|
variable.
|
||||||
|
|
||||||
|
For simplicity, probing for an installed version of the
|
||||||
|
library, and linking to it, is not supported (use the
|
||||||
|
CMake build for this).
|
||||||
|
|
||||||
|
This also removes the obsolete `--gtest-dir` option.
|
||||||
|
|
||||||
|
+ Update README.md
|
||||||
|
|
||||||
|
Fixes #2447
|
||||||
|
---
|
||||||
|
README.md | 13 ++++++++
|
||||||
|
configure.py | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||||
|
2 files changed, 95 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/README.md
|
||||||
|
+++ b/README.md
|
||||||
|
@@ -34,6 +34,19 @@ via CMake. For more details see
|
||||||
|
This will generate the `ninja` binary and a `build.ninja` file you can now use
|
||||||
|
to build Ninja with itself.
|
||||||
|
|
||||||
|
+If you have a GoogleTest source directory, you can build the tests
|
||||||
|
+by passing its path with `--gtest-source-dir=PATH` option, or the
|
||||||
|
+`GTEST_SOURCE_DIR` environment variable, e.g.:
|
||||||
|
+
|
||||||
|
+```
|
||||||
|
+./configure.py --bootstrap --gtest-source-dir=/path/to/googletest
|
||||||
|
+./ninja all # build ninja_test and other auxiliary binaries
|
||||||
|
+./ninja_test` # run the unit-test suite.
|
||||||
|
+```
|
||||||
|
+
|
||||||
|
+Use the CMake build below if you want to use a preinstalled binary
|
||||||
|
+version of the library.
|
||||||
|
+
|
||||||
|
### CMake
|
||||||
|
|
||||||
|
```
|
||||||
|
--- a/configure.py
|
||||||
|
+++ b/configure.py
|
||||||
|
@@ -213,7 +213,10 @@ parser.add_option('--debug', action='sto
|
||||||
|
parser.add_option('--profile', metavar='TYPE',
|
||||||
|
choices=profilers,
|
||||||
|
help='enable profiling (' + '/'.join(profilers) + ')',)
|
||||||
|
-parser.add_option('--with-gtest', metavar='PATH', help='ignored')
|
||||||
|
+parser.add_option('--gtest-source-dir', metavar='PATH',
|
||||||
|
+ help='Path to GoogleTest source directory. If not provided ' +
|
||||||
|
+ 'GTEST_SOURCE_DIR will be probed in the environment. ' +
|
||||||
|
+ 'Tests will not be built without a value.')
|
||||||
|
parser.add_option('--with-python', metavar='EXE',
|
||||||
|
help='use EXE as the Python interpreter',
|
||||||
|
default=os.path.basename(sys.executable))
|
||||||
|
@@ -425,6 +428,7 @@ n.variable('cflags', ' '.join(shell_esca
|
||||||
|
if 'LDFLAGS' in configure_env:
|
||||||
|
ldflags.append(configure_env['LDFLAGS'])
|
||||||
|
n.variable('ldflags', ' '.join(shell_escape(flag) for flag in ldflags))
|
||||||
|
+
|
||||||
|
n.newline()
|
||||||
|
|
||||||
|
if platform.is_msvc():
|
||||||
|
@@ -582,6 +586,83 @@ if options.bootstrap:
|
||||||
|
# build.ninja file.
|
||||||
|
n = ninja_writer
|
||||||
|
|
||||||
|
+# Build the ninja_test executable only if the GTest source directory
|
||||||
|
+# is provided explicitly. Either from the environment with GTEST_SOURCE_DIR
|
||||||
|
+# or with the --gtest-source-dir command-line option.
|
||||||
|
+#
|
||||||
|
+# Do not try to look for an installed binary version, and link against it
|
||||||
|
+# because doing so properly is platform-specific (use the CMake build for
|
||||||
|
+# this).
|
||||||
|
+if options.gtest_source_dir:
|
||||||
|
+ gtest_src_dir = options.gtest_source_dir
|
||||||
|
+else:
|
||||||
|
+ gtest_src_dir = os.environ.get('GTEST_SOURCE_DIR')
|
||||||
|
+
|
||||||
|
+if gtest_src_dir:
|
||||||
|
+ # Verify GoogleTest source directory, and add its include directory
|
||||||
|
+ # to the global include search path (even for non-test sources) to
|
||||||
|
+ # keep the build plan generation simple.
|
||||||
|
+ gtest_all_cc = os.path.join(gtest_src_dir, 'googletest', 'src', 'gtest-all.cc')
|
||||||
|
+ if not os.path.exists(gtest_all_cc):
|
||||||
|
+ print('ERROR: Missing GoogleTest source file: %s' % gtest_all_cc)
|
||||||
|
+ sys.exit(1)
|
||||||
|
+
|
||||||
|
+ n.comment('Tests all build into ninja_test executable.')
|
||||||
|
+
|
||||||
|
+ # Test-specific version of cflags, must include the GoogleTest
|
||||||
|
+ # include directory. Also GoogleTest can only build with a C++14 compiler.
|
||||||
|
+ test_cflags = [f.replace('std=c++11', 'std=c++14') for f in cflags]
|
||||||
|
+ test_cflags.append('-I' + os.path.join(gtest_src_dir, 'googletest', 'include'))
|
||||||
|
+
|
||||||
|
+ test_variables = [('cflags', test_cflags)]
|
||||||
|
+ if platform.is_msvc():
|
||||||
|
+ test_variables += [('pdb', 'ninja_test.pdb')]
|
||||||
|
+
|
||||||
|
+ test_names = [
|
||||||
|
+ 'build_log_test',
|
||||||
|
+ 'build_test',
|
||||||
|
+ 'clean_test',
|
||||||
|
+ 'clparser_test',
|
||||||
|
+ 'depfile_parser_test',
|
||||||
|
+ 'deps_log_test',
|
||||||
|
+ 'disk_interface_test',
|
||||||
|
+ 'dyndep_parser_test',
|
||||||
|
+ 'edit_distance_test',
|
||||||
|
+ 'graph_test',
|
||||||
|
+ 'json_test',
|
||||||
|
+ 'lexer_test',
|
||||||
|
+ 'manifest_parser_test',
|
||||||
|
+ 'ninja_test',
|
||||||
|
+ 'state_test',
|
||||||
|
+ 'string_piece_util_test',
|
||||||
|
+ 'subprocess_test',
|
||||||
|
+ 'test',
|
||||||
|
+ 'util_test',
|
||||||
|
+ ]
|
||||||
|
+ if platform.is_windows():
|
||||||
|
+ test_names += [
|
||||||
|
+ 'includes_normalize_test',
|
||||||
|
+ 'msvc_helper_test',
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
+ objs = []
|
||||||
|
+ for name in test_names:
|
||||||
|
+ objs += cxx(name, variables=test_variables)
|
||||||
|
+
|
||||||
|
+ # Build GTest as a monolithic source file.
|
||||||
|
+ # This requires one extra include search path, so replace the
|
||||||
|
+ # value of 'cflags' in our list.
|
||||||
|
+ gtest_all_variables = test_variables[1:] + [
|
||||||
|
+ ('cflags', test_cflags + ['-I' + os.path.join(gtest_src_dir, 'googletest') ]),
|
||||||
|
+ ]
|
||||||
|
+ # Do not use cxx() directly to ensure the object file is under $builddir.
|
||||||
|
+ objs += n.build(built('gtest_all' + objext), 'cxx', gtest_all_cc, variables=gtest_all_variables)
|
||||||
|
+
|
||||||
|
+ ninja_test = n.build(binary('ninja_test'), 'link', objs, implicit=ninja_lib,
|
||||||
|
+ variables=[('libs', libs)])
|
||||||
|
+ n.newline()
|
||||||
|
+ all_targets += ninja_test
|
||||||
|
+
|
||||||
|
n.comment('Ancillary executables.')
|
||||||
|
|
||||||
|
if platform.is_aix() and '-maix64' not in ldflags:
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/configure.py
|
--- a/configure.py
|
||||||
+++ b/configure.py
|
+++ b/configure.py
|
||||||
@@ -201,6 +201,8 @@ parser = OptionParser()
|
@@ -198,6 +198,8 @@ parser = OptionParser()
|
||||||
profilers = ['gmon', 'pprof']
|
profilers = ['gmon', 'pprof']
|
||||||
parser.add_option('--bootstrap', action='store_true',
|
parser.add_option('--bootstrap', action='store_true',
|
||||||
help='bootstrap a ninja binary from nothing')
|
help='bootstrap a ninja binary from nothing')
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
parser.add_option('--verbose', action='store_true',
|
parser.add_option('--verbose', action='store_true',
|
||||||
help='enable verbose build')
|
help='enable verbose build')
|
||||||
parser.add_option('--platform',
|
parser.add_option('--platform',
|
||||||
@@ -693,7 +695,11 @@ n.build('all', 'phony', all_targets)
|
@@ -756,7 +758,11 @@ n.build('all', 'phony', all_targets)
|
||||||
n.close()
|
n.close()
|
||||||
print('wrote %s.' % BUILD_FILENAME)
|
print('wrote %s.' % BUILD_FILENAME)
|
||||||
|
|
||||||
|
|
|
@ -18,22 +18,9 @@ Documentation for GNU make jobserver
|
||||||
|
|
||||||
http://make.mad-scientist.net/papers/jobserver-implementation/
|
http://make.mad-scientist.net/papers/jobserver-implementation/
|
||||||
|
|
||||||
Fixes https://github.com/ninja-build/ninja/issues/1139
|
|
||||||
---
|
|
||||||
configure.py | 2 +
|
|
||||||
src/build.cc | 63 ++++++++----
|
|
||||||
src/build.h | 3 +
|
|
||||||
src/tokenpool-gnu-make.cc | 211 ++++++++++++++++++++++++++++++++++++++
|
|
||||||
src/tokenpool-none.cc | 27 +++++
|
|
||||||
src/tokenpool.h | 26 +++++
|
|
||||||
6 files changed, 310 insertions(+), 22 deletions(-)
|
|
||||||
create mode 100644 src/tokenpool-gnu-make.cc
|
|
||||||
create mode 100644 src/tokenpool-none.cc
|
|
||||||
create mode 100644 src/tokenpool.h
|
|
||||||
|
|
||||||
--- a/configure.py
|
--- a/configure.py
|
||||||
+++ b/configure.py
|
+++ b/configure.py
|
||||||
@@ -519,11 +519,13 @@ for name in ['build',
|
@@ -543,11 +543,13 @@ for name in ['build',
|
||||||
'state',
|
'state',
|
||||||
'status',
|
'status',
|
||||||
'string_piece_util',
|
'string_piece_util',
|
||||||
|
@ -47,7 +34,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
'includes_normalize-win32',
|
'includes_normalize-win32',
|
||||||
'msvc_helper-win32',
|
'msvc_helper-win32',
|
||||||
'msvc_helper_main-win32']:
|
'msvc_helper_main-win32']:
|
||||||
@@ -532,7 +534,9 @@ if platform.is_windows():
|
@@ -556,7 +558,9 @@ if platform.is_windows():
|
||||||
objs += cxx('minidump-win32', variables=cxxvariables)
|
objs += cxx('minidump-win32', variables=cxxvariables)
|
||||||
objs += cc('getopt')
|
objs += cc('getopt')
|
||||||
else:
|
else:
|
||||||
|
@ -58,17 +45,17 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
if platform.is_aix():
|
if platform.is_aix():
|
||||||
objs += cc('getopt')
|
objs += cc('getopt')
|
||||||
if platform.is_msvc():
|
if platform.is_msvc():
|
||||||
@@ -590,6 +594,7 @@ for name in ['build_log_test',
|
@@ -639,6 +643,7 @@ if gtest_src_dir:
|
||||||
'string_piece_util_test',
|
'string_piece_util_test',
|
||||||
'subprocess_test',
|
'subprocess_test',
|
||||||
'test',
|
'test',
|
||||||
+ 'tokenpool_test',
|
+ 'tokenpool_test',
|
||||||
'util_test']:
|
'util_test',
|
||||||
objs += cxx(name, variables=cxxvariables)
|
]
|
||||||
if platform.is_windows():
|
if platform.is_windows():
|
||||||
--- a/src/build.cc
|
--- a/src/build.cc
|
||||||
+++ b/src/build.cc
|
+++ b/src/build.cc
|
||||||
@@ -35,6 +35,7 @@
|
@@ -39,6 +39,7 @@
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "subprocess.h"
|
#include "subprocess.h"
|
||||||
|
@ -76,10 +63,12 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -47,8 +48,9 @@ struct DryRunCommandRunner : public Comm
|
@@ -50,24 +51,29 @@ struct DryRunCommandRunner : public Comm
|
||||||
|
virtual ~DryRunCommandRunner() {}
|
||||||
|
|
||||||
// Overridden from CommandRunner:
|
// Overridden from CommandRunner:
|
||||||
virtual bool CanRunMore() const;
|
- virtual size_t CanRunMore() const;
|
||||||
|
+ virtual size_t CanRunMore();
|
||||||
+ virtual bool AcquireToken();
|
+ virtual bool AcquireToken();
|
||||||
virtual bool StartCommand(Edge* edge);
|
virtual bool StartCommand(Edge* edge);
|
||||||
- virtual bool WaitForCommand(Result* result);
|
- virtual bool WaitForCommand(Result* result);
|
||||||
|
@ -87,8 +76,11 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
|
|
||||||
private:
|
private:
|
||||||
queue<Edge*> finished_;
|
queue<Edge*> finished_;
|
||||||
@@ -58,12 +60,16 @@ bool DryRunCommandRunner::CanRunMore() c
|
};
|
||||||
return true;
|
|
||||||
|
-size_t DryRunCommandRunner::CanRunMore() const {
|
||||||
|
+size_t DryRunCommandRunner::CanRunMore() {
|
||||||
|
return SIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
+bool DryRunCommandRunner::AcquireToken() {
|
+bool DryRunCommandRunner::AcquireToken() {
|
||||||
|
@ -105,24 +97,25 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
if (finished_.empty())
|
if (finished_.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -149,7 +155,7 @@ void Plan::EdgeWanted(const Edge* edge)
|
@@ -160,7 +166,7 @@ void Plan::EdgeWanted(const Edge* edge)
|
||||||
}
|
}
|
||||||
|
|
||||||
Edge* Plan::FindWork() {
|
Edge* Plan::FindWork() {
|
||||||
- if (ready_.empty())
|
- if (ready_.empty())
|
||||||
+ if (!more_ready())
|
+ if (!more_ready())
|
||||||
return NULL;
|
return NULL;
|
||||||
EdgeSet::iterator e = ready_.begin();
|
|
||||||
Edge* edge = *e;
|
Edge* work = ready_.top();
|
||||||
@@ -448,19 +454,39 @@ void Plan::Dump() const {
|
@@ -595,19 +601,39 @@ void Plan::Dump() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RealCommandRunner : public CommandRunner {
|
struct RealCommandRunner : public CommandRunner {
|
||||||
- explicit RealCommandRunner(const BuildConfig& config) : config_(config) {}
|
- explicit RealCommandRunner(const BuildConfig& config) : config_(config) {}
|
||||||
- virtual ~RealCommandRunner() {}
|
- virtual ~RealCommandRunner() {}
|
||||||
|
- virtual size_t CanRunMore() const;
|
||||||
+ explicit RealCommandRunner(const BuildConfig& config);
|
+ explicit RealCommandRunner(const BuildConfig& config);
|
||||||
+ virtual ~RealCommandRunner();
|
+ virtual ~RealCommandRunner();
|
||||||
virtual bool CanRunMore() const;
|
+ virtual size_t CanRunMore();
|
||||||
+ virtual bool AcquireToken();
|
+ virtual bool AcquireToken();
|
||||||
virtual bool StartCommand(Edge* edge);
|
virtual bool StartCommand(Edge* edge);
|
||||||
- virtual bool WaitForCommand(Result* result);
|
- virtual bool WaitForCommand(Result* result);
|
||||||
|
@ -157,7 +150,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
vector<Edge*> RealCommandRunner::GetActiveEdges() {
|
vector<Edge*> RealCommandRunner::GetActiveEdges() {
|
||||||
vector<Edge*> edges;
|
vector<Edge*> edges;
|
||||||
for (map<const Subprocess*, Edge*>::iterator e = subproc_to_edge_.begin();
|
for (map<const Subprocess*, Edge*>::iterator e = subproc_to_edge_.begin();
|
||||||
@@ -471,14 +497,23 @@ vector<Edge*> RealCommandRunner::GetActi
|
@@ -618,9 +644,11 @@ vector<Edge*> RealCommandRunner::GetActi
|
||||||
|
|
||||||
void RealCommandRunner::Abort() {
|
void RealCommandRunner::Abort() {
|
||||||
subprocs_.Clear();
|
subprocs_.Clear();
|
||||||
|
@ -165,28 +158,35 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
+ tokens_->Clear();
|
+ tokens_->Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RealCommandRunner::CanRunMore() const {
|
-size_t RealCommandRunner::CanRunMore() const {
|
||||||
- size_t subproc_number =
|
+size_t RealCommandRunner::CanRunMore() {
|
||||||
- subprocs_.running_.size() + subprocs_.finished_.size();
|
size_t subproc_number =
|
||||||
- return (int)subproc_number < config_.parallelism
|
subprocs_.running_.size() + subprocs_.finished_.size();
|
||||||
- && ((subprocs_.running_.empty() || config_.max_load_average <= 0.0f)
|
|
||||||
- || GetLoadAverage() < config_.max_load_average);
|
@@ -635,6 +663,13 @@ size_t RealCommandRunner::CanRunMore() c
|
||||||
+ bool parallelism_limit_not_reached =
|
if (capacity < 0)
|
||||||
+ tokens_ || // ignore config_.parallelism
|
capacity = 0;
|
||||||
+ ((int) (subprocs_.running_.size() +
|
|
||||||
+ subprocs_.finished_.size()) < config_.parallelism);
|
+ if (tokens_) {
|
||||||
+ return parallelism_limit_not_reached
|
+ if (AcquireToken())
|
||||||
+ && (subprocs_.running_.empty() ||
|
+ return SIZE_MAX;
|
||||||
+ (max_load_average_ <= 0.0f ||
|
+ else
|
||||||
+ GetLoadAverage() < max_load_average_));
|
+ capacity = 0;
|
||||||
+}
|
+ }
|
||||||
+
|
+
|
||||||
+bool RealCommandRunner::AcquireToken() {
|
if (capacity == 0 && subprocs_.running_.empty())
|
||||||
+ return (!tokens_ || tokens_->Acquire());
|
// Ensure that we make progress.
|
||||||
|
capacity = 1;
|
||||||
|
@@ -642,24 +677,42 @@ size_t RealCommandRunner::CanRunMore() c
|
||||||
|
return capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+bool RealCommandRunner::AcquireToken() {
|
||||||
|
+ return (!tokens_ || tokens_->Acquire());
|
||||||
|
+}
|
||||||
|
+
|
||||||
bool RealCommandRunner::StartCommand(Edge* edge) {
|
bool RealCommandRunner::StartCommand(Edge* edge) {
|
||||||
@@ -486,19 +521,33 @@ bool RealCommandRunner::StartCommand(Edg
|
string command = edge->EvaluateCommand();
|
||||||
Subprocess* subproc = subprocs_.Add(command, edge->use_console());
|
Subprocess* subproc = subprocs_.Add(command, edge->use_console());
|
||||||
if (!subproc)
|
if (!subproc)
|
||||||
return false;
|
return false;
|
||||||
|
@ -223,61 +223,17 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
result->status = subproc->Finish();
|
result->status = subproc->Finish();
|
||||||
result->output = subproc->GetOutput();
|
result->output = subproc->GetOutput();
|
||||||
|
|
||||||
@@ -620,38 +669,43 @@ bool Builder::Build(string* err) {
|
@@ -790,7 +843,8 @@ bool Builder::Build(string* err) {
|
||||||
// command runner.
|
|
||||||
// Second, we attempt to wait for / reap the next finished command.
|
// Second, we attempt to wait for / reap the next finished command.
|
||||||
while (plan_.more_to_do()) {
|
while (plan_.more_to_do()) {
|
||||||
- // See if we can start any more commands.
|
// See if we can start any more commands.
|
||||||
- if (failures_allowed && command_runner_->CanRunMore()) {
|
- if (failures_allowed) {
|
||||||
- if (Edge* edge = plan_.FindWork()) {
|
+ bool can_run_more = failures_allowed && plan_.more_ready();
|
||||||
- if (edge->GetBindingBool("generator")) {
|
+ if (can_run_more) {
|
||||||
+ // See if we can start any more commands...
|
size_t capacity = command_runner_->CanRunMore();
|
||||||
+ bool can_run_more =
|
while (capacity > 0) {
|
||||||
+ failures_allowed &&
|
Edge* edge = plan_.FindWork();
|
||||||
+ plan_.more_ready() &&
|
@@ -833,7 +887,7 @@ bool Builder::Build(string* err) {
|
||||||
+ command_runner_->CanRunMore();
|
|
||||||
+
|
|
||||||
+ // ... but we also need a token to do that.
|
|
||||||
+ if (can_run_more && command_runner_->AcquireToken()) {
|
|
||||||
+ Edge* edge = plan_.FindWork();
|
|
||||||
+ if (edge->GetBindingBool("generator")) {
|
|
||||||
scan_.build_log()->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (!StartEdge(edge, err)) {
|
|
||||||
+ if (!StartEdge(edge, err)) {
|
|
||||||
+ Cleanup();
|
|
||||||
+ status_->BuildFinished();
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (edge->is_phony()) {
|
|
||||||
+ if (!plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, err)) {
|
|
||||||
Cleanup();
|
|
||||||
status_->BuildFinished();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
-
|
|
||||||
- if (edge->is_phony()) {
|
|
||||||
- if (!plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, err)) {
|
|
||||||
- Cleanup();
|
|
||||||
- status_->BuildFinished();
|
|
||||||
- return false;
|
|
||||||
- }
|
|
||||||
- } else {
|
|
||||||
- ++pending_commands;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- // We made some progress; go back to the main loop.
|
|
||||||
- continue;
|
|
||||||
+ } else {
|
|
||||||
+ ++pending_commands;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ // We made some progress; go back to the main loop.
|
|
||||||
+ continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if we can reap any finished commands.
|
// See if we can reap any finished commands.
|
||||||
if (pending_commands) {
|
if (pending_commands) {
|
||||||
CommandRunner::Result result;
|
CommandRunner::Result result;
|
||||||
|
@ -286,7 +242,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
result.status == ExitInterrupted) {
|
result.status == ExitInterrupted) {
|
||||||
Cleanup();
|
Cleanup();
|
||||||
status_->BuildFinished();
|
status_->BuildFinished();
|
||||||
@@ -659,6 +713,10 @@ bool Builder::Build(string* err) {
|
@@ -841,6 +895,10 @@ bool Builder::Build(string* err) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +255,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
Cleanup();
|
Cleanup();
|
||||||
--- a/src/build.h
|
--- a/src/build.h
|
||||||
+++ b/src/build.h
|
+++ b/src/build.h
|
||||||
@@ -52,6 +52,9 @@ struct Plan {
|
@@ -51,6 +51,9 @@ struct Plan {
|
||||||
/// Returns true if there's more work to be done.
|
/// Returns true if there's more work to be done.
|
||||||
bool more_to_do() const { return wanted_edges_ > 0 && command_edges_ > 0; }
|
bool more_to_do() const { return wanted_edges_ > 0 && command_edges_ > 0; }
|
||||||
|
|
||||||
|
@ -309,15 +265,17 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
/// Dumps the current state of the plan.
|
/// Dumps the current state of the plan.
|
||||||
void Dump() const;
|
void Dump() const;
|
||||||
|
|
||||||
@@ -136,6 +139,7 @@ private:
|
@@ -145,7 +148,8 @@ private:
|
||||||
|
/// RealCommandRunner is an implementation that actually runs commands.
|
||||||
struct CommandRunner {
|
struct CommandRunner {
|
||||||
virtual ~CommandRunner() {}
|
virtual ~CommandRunner() {}
|
||||||
virtual bool CanRunMore() const = 0;
|
- virtual size_t CanRunMore() const = 0;
|
||||||
|
+ virtual size_t CanRunMore() = 0;
|
||||||
+ virtual bool AcquireToken() = 0;
|
+ virtual bool AcquireToken() = 0;
|
||||||
virtual bool StartCommand(Edge* edge) = 0;
|
virtual bool StartCommand(Edge* edge) = 0;
|
||||||
|
|
||||||
/// The result of waiting for a command.
|
/// The result of waiting for a command.
|
||||||
@@ -147,7 +151,9 @@ struct CommandRunner {
|
@@ -157,7 +161,9 @@ struct CommandRunner {
|
||||||
bool success() const { return status == ExitSuccess; }
|
bool success() const { return status == ExitSuccess; }
|
||||||
};
|
};
|
||||||
/// Wait for a command to complete, or return false if interrupted.
|
/// Wait for a command to complete, or return false if interrupted.
|
||||||
|
@ -328,7 +286,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
|
|
||||||
virtual std::vector<Edge*> GetActiveEdges() { return std::vector<Edge*>(); }
|
virtual std::vector<Edge*> GetActiveEdges() { return std::vector<Edge*>(); }
|
||||||
virtual void Abort() {}
|
virtual void Abort() {}
|
||||||
@@ -155,7 +161,8 @@ struct CommandRunner {
|
@@ -165,7 +171,8 @@ struct CommandRunner {
|
||||||
|
|
||||||
/// Options (e.g. verbosity, parallelism) passed to a build.
|
/// Options (e.g. verbosity, parallelism) passed to a build.
|
||||||
struct BuildConfig {
|
struct BuildConfig {
|
||||||
|
@ -338,7 +296,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
failures_allowed(1), max_load_average(-0.0f) {}
|
failures_allowed(1), max_load_average(-0.0f) {}
|
||||||
|
|
||||||
enum Verbosity {
|
enum Verbosity {
|
||||||
@@ -167,6 +174,7 @@ struct BuildConfig {
|
@@ -177,6 +184,7 @@ struct BuildConfig {
|
||||||
Verbosity verbosity;
|
Verbosity verbosity;
|
||||||
bool dry_run;
|
bool dry_run;
|
||||||
int parallelism;
|
int parallelism;
|
||||||
|
@ -509,13 +467,15 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
+#include <stdarg.h>
|
+#include <stdarg.h>
|
||||||
|
#include <climits>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "build_log.h"
|
@@ -521,9 +522,10 @@ struct FakeCommandRunner : public Comman
|
||||||
#include "deps_log.h"
|
max_active_edges_(1), fs_(fs) {}
|
||||||
@@ -474,8 +475,9 @@ struct FakeCommandRunner : public Comman
|
|
||||||
|
|
||||||
// CommandRunner impl
|
// CommandRunner impl
|
||||||
virtual bool CanRunMore() const;
|
- virtual size_t CanRunMore() const;
|
||||||
|
+ virtual size_t CanRunMore();
|
||||||
+ virtual bool AcquireToken();
|
+ virtual bool AcquireToken();
|
||||||
virtual bool StartCommand(Edge* edge);
|
virtual bool StartCommand(Edge* edge);
|
||||||
- virtual bool WaitForCommand(Result* result);
|
- virtual bool WaitForCommand(Result* result);
|
||||||
|
@ -523,8 +483,16 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
virtual vector<Edge*> GetActiveEdges();
|
virtual vector<Edge*> GetActiveEdges();
|
||||||
virtual void Abort();
|
virtual void Abort();
|
||||||
|
|
||||||
@@ -578,6 +580,10 @@ bool FakeCommandRunner::CanRunMore() con
|
@@ -622,13 +624,17 @@ void BuildTest::RebuildTarget(const stri
|
||||||
return active_edges_.size() < max_active_edges_;
|
builder.command_runner_.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
-size_t FakeCommandRunner::CanRunMore() const {
|
||||||
|
+size_t FakeCommandRunner::CanRunMore() {
|
||||||
|
if (active_edges_.size() < max_active_edges_)
|
||||||
|
return SIZE_MAX;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
+bool FakeCommandRunner::AcquireToken() {
|
+bool FakeCommandRunner::AcquireToken() {
|
||||||
|
@ -534,7 +502,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
bool FakeCommandRunner::StartCommand(Edge* edge) {
|
bool FakeCommandRunner::StartCommand(Edge* edge) {
|
||||||
assert(active_edges_.size() < max_active_edges_);
|
assert(active_edges_.size() < max_active_edges_);
|
||||||
assert(find(active_edges_.begin(), active_edges_.end(), edge)
|
assert(find(active_edges_.begin(), active_edges_.end(), edge)
|
||||||
@@ -649,7 +655,7 @@ bool FakeCommandRunner::StartCommand(Edg
|
@@ -720,7 +726,7 @@ bool FakeCommandRunner::StartCommand(Edg
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,7 +511,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
if (active_edges_.empty())
|
if (active_edges_.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -3985,3 +3991,356 @@ TEST_F(BuildTest, ValidationWithCircular
|
@@ -4380,3 +4386,355 @@ TEST_F(BuildTest, ValidationWithCircular
|
||||||
EXPECT_FALSE(builder_.AddTarget("out", &err));
|
EXPECT_FALSE(builder_.AddTarget("out", &err));
|
||||||
EXPECT_EQ("dependency cycle: validate -> validate_in -> validate", err);
|
EXPECT_EQ("dependency cycle: validate -> validate_in -> validate", err);
|
||||||
}
|
}
|
||||||
|
@ -557,7 +525,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
+ explicit FakeTokenCommandRunner() {}
|
+ explicit FakeTokenCommandRunner() {}
|
||||||
+
|
+
|
||||||
+ // CommandRunner impl
|
+ // CommandRunner impl
|
||||||
+ virtual bool CanRunMore() const;
|
+ virtual bool CanRunMore();
|
||||||
+ virtual bool AcquireToken();
|
+ virtual bool AcquireToken();
|
||||||
+ virtual bool StartCommand(Edge* edge);
|
+ virtual bool StartCommand(Edge* edge);
|
||||||
+ virtual bool WaitForCommand(Result* result, bool more_ready);
|
+ virtual bool WaitForCommand(Result* result, bool more_ready);
|
||||||
|
@ -572,7 +540,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
+ vector<bool> wait_for_command_;
|
+ vector<bool> wait_for_command_;
|
||||||
+};
|
+};
|
||||||
+
|
+
|
||||||
+bool FakeTokenCommandRunner::CanRunMore() const {
|
+bool FakeTokenCommandRunner::CanRunMore() {
|
||||||
+ if (can_run_more_.size() == 0) {
|
+ if (can_run_more_.size() == 0) {
|
||||||
+ EXPECT_FALSE("unexpected call to CommandRunner::CanRunMore()");
|
+ EXPECT_FALSE("unexpected call to CommandRunner::CanRunMore()");
|
||||||
+ return false;
|
+ return false;
|
||||||
|
@ -580,9 +548,8 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
+
|
+
|
||||||
+ bool result = can_run_more_[0];
|
+ bool result = can_run_more_[0];
|
||||||
+
|
+
|
||||||
+ // Unfortunately CanRunMore() isn't "const" for tests
|
+ can_run_more_.erase(
|
||||||
+ const_cast<FakeTokenCommandRunner*>(this)->can_run_more_.erase(
|
+ can_run_more_.begin()
|
||||||
+ const_cast<FakeTokenCommandRunner*>(this)->can_run_more_.begin()
|
|
||||||
+ );
|
+ );
|
||||||
+
|
+
|
||||||
+ return result;
|
+ return result;
|
||||||
|
@ -1345,7 +1312,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
+}
|
+}
|
||||||
--- a/src/ninja.cc
|
--- a/src/ninja.cc
|
||||||
+++ b/src/ninja.cc
|
+++ b/src/ninja.cc
|
||||||
@@ -1447,6 +1447,7 @@ int ReadFlags(int* argc, char*** argv,
|
@@ -1466,6 +1466,7 @@ int ReadFlags(int* argc, char*** argv,
|
||||||
// We want to run N jobs in parallel. For N = 0, INT_MAX
|
// We want to run N jobs in parallel. For N = 0, INT_MAX
|
||||||
// is close enough to infinite for most sane builds.
|
// is close enough to infinite for most sane builds.
|
||||||
config->parallelism = value > 0 ? value : INT_MAX;
|
config->parallelism = value > 0 ? value : INT_MAX;
|
||||||
|
@ -2139,7 +2106,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
+};
|
+};
|
||||||
--- a/CMakeLists.txt
|
--- a/CMakeLists.txt
|
||||||
+++ b/CMakeLists.txt
|
+++ b/CMakeLists.txt
|
||||||
@@ -112,6 +112,7 @@ add_library(libninja OBJECT
|
@@ -142,6 +142,7 @@ add_library(libninja OBJECT
|
||||||
src/state.cc
|
src/state.cc
|
||||||
src/status.cc
|
src/status.cc
|
||||||
src/string_piece_util.cc
|
src/string_piece_util.cc
|
||||||
|
@ -2147,22 +2114,26 @@ Fixes https://github.com/ninja-build/ninja/issues/1139
|
||||||
src/util.cc
|
src/util.cc
|
||||||
src/version.cc
|
src/version.cc
|
||||||
)
|
)
|
||||||
@@ -123,9 +124,14 @@ if(WIN32)
|
@@ -153,13 +154,17 @@ if(WIN32)
|
||||||
src/msvc_helper_main-win32.cc
|
src/msvc_helper_main-win32.cc
|
||||||
src/getopt.c
|
src/getopt.c
|
||||||
src/minidump-win32.cc
|
src/minidump-win32.cc
|
||||||
+ src/tokenpool-gnu-make-win32.cc
|
+ src/tokenpool-gnu-make-win32.cc
|
||||||
)
|
)
|
||||||
|
# Build getopt.c, which can be compiled as either C or C++, as C++
|
||||||
|
# so that build environments which lack a C compiler, but have a C++
|
||||||
|
# compiler may build ninja.
|
||||||
|
set_source_files_properties(src/getopt.c PROPERTIES LANGUAGE CXX)
|
||||||
else()
|
else()
|
||||||
target_sources(libninja PRIVATE src/subprocess-posix.cc)
|
- target_sources(libninja PRIVATE src/subprocess-posix.cc)
|
||||||
+ target_sources(libninja PRIVATE
|
+ target_sources(libninja PRIVATE
|
||||||
+ src/subprocess-posix.cc
|
+ src/subprocess-posix.cc
|
||||||
+ src/tokenpool-gnu-make-posix.cc
|
+ src/tokenpool-gnu-make-posix.cc
|
||||||
+ )
|
+ )
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS400" OR CMAKE_SYSTEM_NAME STREQUAL "AIX")
|
if(CMAKE_SYSTEM_NAME STREQUAL "OS400" OR CMAKE_SYSTEM_NAME STREQUAL "AIX")
|
||||||
target_sources(libninja PRIVATE src/getopt.c)
|
target_sources(libninja PRIVATE src/getopt.c)
|
||||||
endif()
|
# Build getopt.c, which can be compiled as either C or C++, as C++
|
||||||
@@ -204,6 +210,7 @@ if(BUILD_TESTING)
|
@@ -286,6 +291,7 @@ if(BUILD_TESTING)
|
||||||
src/string_piece_util_test.cc
|
src/string_piece_util_test.cc
|
||||||
src/subprocess_test.cc
|
src/subprocess_test.cc
|
||||||
src/test.cc
|
src/test.cc
|
||||||
|
|
Loading…
Reference in New Issue