diff --git a/tools/ninja/Makefile b/tools/ninja/Makefile index 7d6b623925b..d79f3c5d5df 100644 --- a/tools/ninja/Makefile +++ b/tools/ninja/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ninja -PKG_VERSION:=1.11.1 +PKG_VERSION:=1.12.1 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz 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 diff --git a/tools/ninja/patches/001-backport-gtest.patch b/tools/ninja/patches/001-backport-gtest.patch new file mode 100644 index 00000000000..1440f29ef06 --- /dev/null +++ b/tools/ninja/patches/001-backport-gtest.patch @@ -0,0 +1,153 @@ +From afcd4a146fb82843f6ff695f89504ce4ca65ddfd Mon Sep 17 00:00:00 2001 +From: David 'Digit' Turner +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: diff --git a/tools/ninja/patches/010-bootstrap-configure-only.patch b/tools/ninja/patches/010-bootstrap-configure-only.patch index 61ee5a0cd67..4785ac654eb 100644 --- a/tools/ninja/patches/010-bootstrap-configure-only.patch +++ b/tools/ninja/patches/010-bootstrap-configure-only.patch @@ -1,6 +1,6 @@ --- a/configure.py +++ b/configure.py -@@ -201,6 +201,8 @@ parser = OptionParser() +@@ -198,6 +198,8 @@ parser = OptionParser() profilers = ['gmon', 'pprof'] parser.add_option('--bootstrap', action='store_true', help='bootstrap a ninja binary from nothing') @@ -9,7 +9,7 @@ parser.add_option('--verbose', action='store_true', help='enable verbose build') 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() print('wrote %s.' % BUILD_FILENAME) diff --git a/tools/ninja/patches/100-make_jobserver_support.patch b/tools/ninja/patches/100-make_jobserver_support.patch index 26d6f9714cd..82ecf0222ef 100644 --- a/tools/ninja/patches/100-make_jobserver_support.patch +++ b/tools/ninja/patches/100-make_jobserver_support.patch @@ -18,22 +18,9 @@ Documentation for GNU make jobserver 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 +++ b/configure.py -@@ -519,11 +519,13 @@ for name in ['build', +@@ -543,11 +543,13 @@ for name in ['build', 'state', 'status', 'string_piece_util', @@ -47,7 +34,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 'includes_normalize-win32', 'msvc_helper-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 += cc('getopt') else: @@ -58,17 +45,17 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 if platform.is_aix(): objs += cc('getopt') if platform.is_msvc(): -@@ -590,6 +594,7 @@ for name in ['build_log_test', - 'string_piece_util_test', - 'subprocess_test', - 'test', -+ 'tokenpool_test', - 'util_test']: - objs += cxx(name, variables=cxxvariables) - if platform.is_windows(): +@@ -639,6 +643,7 @@ if gtest_src_dir: + 'string_piece_util_test', + 'subprocess_test', + 'test', ++ 'tokenpool_test', + 'util_test', + ] + if platform.is_windows(): --- a/src/build.cc +++ b/src/build.cc -@@ -35,6 +35,7 @@ +@@ -39,6 +39,7 @@ #include "state.h" #include "status.h" #include "subprocess.h" @@ -76,10 +63,12 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 #include "util.h" using namespace std; -@@ -47,8 +48,9 @@ struct DryRunCommandRunner : public Comm +@@ -50,24 +51,29 @@ struct DryRunCommandRunner : public Comm + virtual ~DryRunCommandRunner() {} // Overridden from CommandRunner: - virtual bool CanRunMore() const; +- virtual size_t CanRunMore() const; ++ virtual size_t CanRunMore(); + virtual bool AcquireToken(); virtual bool StartCommand(Edge* edge); - virtual bool WaitForCommand(Result* result); @@ -87,8 +76,11 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 private: queue 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() { @@ -105,24 +97,25 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 if (finished_.empty()) 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() { - if (ready_.empty()) + if (!more_ready()) return NULL; - EdgeSet::iterator e = ready_.begin(); - Edge* edge = *e; -@@ -448,19 +454,39 @@ void Plan::Dump() const { + + Edge* work = ready_.top(); +@@ -595,19 +601,39 @@ void Plan::Dump() const { } struct RealCommandRunner : public CommandRunner { - explicit RealCommandRunner(const BuildConfig& config) : config_(config) {} - virtual ~RealCommandRunner() {} +- virtual size_t CanRunMore() const; + explicit RealCommandRunner(const BuildConfig& config); + virtual ~RealCommandRunner(); - virtual bool CanRunMore() const; ++ virtual size_t CanRunMore(); + virtual bool AcquireToken(); virtual bool StartCommand(Edge* edge); - virtual bool WaitForCommand(Result* result); @@ -157,7 +150,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 vector RealCommandRunner::GetActiveEdges() { vector edges; for (map::iterator e = subproc_to_edge_.begin(); -@@ -471,14 +497,23 @@ vector RealCommandRunner::GetActi +@@ -618,9 +644,11 @@ vector RealCommandRunner::GetActi void RealCommandRunner::Abort() { subprocs_.Clear(); @@ -165,28 +158,35 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 + tokens_->Clear(); } - bool RealCommandRunner::CanRunMore() const { -- size_t subproc_number = -- subprocs_.running_.size() + subprocs_.finished_.size(); -- return (int)subproc_number < config_.parallelism -- && ((subprocs_.running_.empty() || config_.max_load_average <= 0.0f) -- || GetLoadAverage() < config_.max_load_average); -+ bool parallelism_limit_not_reached = -+ tokens_ || // ignore config_.parallelism -+ ((int) (subprocs_.running_.size() + -+ subprocs_.finished_.size()) < config_.parallelism); -+ return parallelism_limit_not_reached -+ && (subprocs_.running_.empty() || -+ (max_load_average_ <= 0.0f || -+ GetLoadAverage() < max_load_average_)); -+} +-size_t RealCommandRunner::CanRunMore() const { ++size_t RealCommandRunner::CanRunMore() { + size_t subproc_number = + subprocs_.running_.size() + subprocs_.finished_.size(); + +@@ -635,6 +663,13 @@ size_t RealCommandRunner::CanRunMore() c + if (capacity < 0) + capacity = 0; + ++ if (tokens_) { ++ if (AcquireToken()) ++ return SIZE_MAX; ++ else ++ capacity = 0; ++ } + -+bool RealCommandRunner::AcquireToken() { -+ return (!tokens_ || tokens_->Acquire()); + if (capacity == 0 && subprocs_.running_.empty()) + // 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) { -@@ -486,19 +521,33 @@ bool RealCommandRunner::StartCommand(Edg + string command = edge->EvaluateCommand(); Subprocess* subproc = subprocs_.Add(command, edge->use_console()); if (!subproc) return false; @@ -223,61 +223,17 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 result->status = subproc->Finish(); result->output = subproc->GetOutput(); -@@ -620,38 +669,43 @@ bool Builder::Build(string* err) { - // command runner. +@@ -790,7 +843,8 @@ bool Builder::Build(string* err) { // Second, we attempt to wait for / reap the next finished command. while (plan_.more_to_do()) { -- // See if we can start any more commands. -- if (failures_allowed && command_runner_->CanRunMore()) { -- if (Edge* edge = plan_.FindWork()) { -- if (edge->GetBindingBool("generator")) { -+ // See if we can start any more commands... -+ bool can_run_more = -+ failures_allowed && -+ plan_.more_ready() && -+ 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 start any more commands. +- if (failures_allowed) { ++ bool can_run_more = failures_allowed && plan_.more_ready(); ++ if (can_run_more) { + size_t capacity = command_runner_->CanRunMore(); + while (capacity > 0) { + Edge* edge = plan_.FindWork(); +@@ -833,7 +887,7 @@ bool Builder::Build(string* err) { // See if we can reap any finished commands. if (pending_commands) { CommandRunner::Result result; @@ -286,7 +242,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 result.status == ExitInterrupted) { Cleanup(); status_->BuildFinished(); -@@ -659,6 +713,10 @@ bool Builder::Build(string* err) { +@@ -841,6 +895,10 @@ bool Builder::Build(string* err) { return false; } @@ -299,7 +255,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 Cleanup(); --- a/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. 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. void Dump() const; -@@ -136,6 +139,7 @@ private: +@@ -145,7 +148,8 @@ private: + /// RealCommandRunner is an implementation that actually runs commands. struct 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 StartCommand(Edge* edge) = 0; /// 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; } }; /// 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 GetActiveEdges() { return std::vector(); } virtual void Abort() {} -@@ -155,7 +161,8 @@ struct CommandRunner { +@@ -165,7 +171,8 @@ struct CommandRunner { /// Options (e.g. verbosity, parallelism) passed to a build. struct BuildConfig { @@ -338,7 +296,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 failures_allowed(1), max_load_average(-0.0f) {} enum Verbosity { -@@ -167,6 +174,7 @@ struct BuildConfig { +@@ -177,6 +184,7 @@ struct BuildConfig { Verbosity verbosity; bool dry_run; int parallelism; @@ -509,13 +467,15 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 #include +#include + #include + #include - #include "build_log.h" - #include "deps_log.h" -@@ -474,8 +475,9 @@ struct FakeCommandRunner : public Comman +@@ -521,9 +522,10 @@ struct FakeCommandRunner : public Comman + max_active_edges_(1), fs_(fs) {} // CommandRunner impl - virtual bool CanRunMore() const; +- virtual size_t CanRunMore() const; ++ virtual size_t CanRunMore(); + virtual bool AcquireToken(); virtual bool StartCommand(Edge* edge); - virtual bool WaitForCommand(Result* result); @@ -523,8 +483,16 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 virtual vector GetActiveEdges(); virtual void Abort(); -@@ -578,6 +580,10 @@ bool FakeCommandRunner::CanRunMore() con - return active_edges_.size() < max_active_edges_; +@@ -622,13 +624,17 @@ void BuildTest::RebuildTarget(const stri + 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() { @@ -534,7 +502,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 bool FakeCommandRunner::StartCommand(Edge* edge) { assert(active_edges_.size() < max_active_edges_); 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; } @@ -543,7 +511,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 if (active_edges_.empty()) 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_EQ("dependency cycle: validate -> validate_in -> validate", err); } @@ -557,7 +525,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 + explicit FakeTokenCommandRunner() {} + + // CommandRunner impl -+ virtual bool CanRunMore() const; ++ virtual bool CanRunMore(); + virtual bool AcquireToken(); + virtual bool StartCommand(Edge* edge); + virtual bool WaitForCommand(Result* result, bool more_ready); @@ -572,7 +540,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 + vector wait_for_command_; +}; + -+bool FakeTokenCommandRunner::CanRunMore() const { ++bool FakeTokenCommandRunner::CanRunMore() { + if (can_run_more_.size() == 0) { + EXPECT_FALSE("unexpected call to CommandRunner::CanRunMore()"); + return false; @@ -580,9 +548,8 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 + + bool result = can_run_more_[0]; + -+ // Unfortunately CanRunMore() isn't "const" for tests -+ const_cast(this)->can_run_more_.erase( -+ const_cast(this)->can_run_more_.begin() ++ can_run_more_.erase( ++ can_run_more_.begin() + ); + + return result; @@ -1345,7 +1312,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 +} --- a/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 // is close enough to infinite for most sane builds. config->parallelism = value > 0 ? value : INT_MAX; @@ -2139,7 +2106,7 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 +}; --- a/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/status.cc src/string_piece_util.cc @@ -2147,22 +2114,26 @@ Fixes https://github.com/ninja-build/ninja/issues/1139 src/util.cc src/version.cc ) -@@ -123,9 +124,14 @@ if(WIN32) +@@ -153,13 +154,17 @@ if(WIN32) src/msvc_helper_main-win32.cc src/getopt.c src/minidump-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() - target_sources(libninja PRIVATE src/subprocess-posix.cc) +- target_sources(libninja PRIVATE src/subprocess-posix.cc) + target_sources(libninja PRIVATE + src/subprocess-posix.cc + src/tokenpool-gnu-make-posix.cc + ) if(CMAKE_SYSTEM_NAME STREQUAL "OS400" OR CMAKE_SYSTEM_NAME STREQUAL "AIX") target_sources(libninja PRIVATE src/getopt.c) - endif() -@@ -204,6 +210,7 @@ if(BUILD_TESTING) + # Build getopt.c, which can be compiled as either C or C++, as C++ +@@ -286,6 +291,7 @@ if(BUILD_TESTING) src/string_piece_util_test.cc src/subprocess_test.cc src/test.cc