diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f03c3599c..3c25ab4bdc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,7 @@ add_library(libninja OBJECT src/parser.cc src/state.cc src/string_piece_util.cc + src/tokenpool-gnu-make.cc src/util.cc src/version.cc ) @@ -104,12 +105,16 @@ if(WIN32) src/msvc_helper-win32.cc src/msvc_helper_main-win32.cc src/getopt.c + src/tokenpool-gnu-make-win32.cc ) if(MSVC) target_sources(libninja PRIVATE src/minidump-win32.cc) endif() else() - 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() @@ -182,6 +187,7 @@ if(BUILD_TESTING) src/string_piece_util_test.cc src/subprocess_test.cc src/test.cc + src/tokenpool_test.cc src/util_test.cc ) if(WIN32) diff --git a/src/build.cc b/src/build.cc index b4157239e4..41414423fd 100644 --- a/src/build.cc +++ b/src/build.cc @@ -684,7 +684,7 @@ struct RealCommandRunner : public CommandRunner { // copy of config_.max_load_average; can be modified by TokenPool setup double max_load_average_; SubprocessSet subprocs_; - TokenPool *tokens_; + TokenPool* tokens_; map subproc_to_edge_; }; diff --git a/src/build_test.cc b/src/build_test.cc index 98508dc40d..80b9c4f2ac 100644 --- a/src/build_test.cc +++ b/src/build_test.cc @@ -3461,16 +3461,6 @@ void BuildTokenTest::EnqueueBooleans(vector& booleans, int count, va_list } } -TEST_F(BuildTokenTest, CompleteNoWork) { - // plan should not execute anything - string err; - - EXPECT_TRUE(builder_.Build(&err)); - EXPECT_EQ("", err); - - EXPECT_EQ(0u, token_command_runner_.commands_ran_.size()); -} - TEST_F(BuildTokenTest, DoNotAquireToken) { // plan should execute one command string err; diff --git a/src/subprocess-posix.cc b/src/subprocess-posix.cc index 74451b0be2..31839276c4 100644 --- a/src/subprocess-posix.cc +++ b/src/subprocess-posix.cc @@ -250,7 +250,7 @@ Subprocess *SubprocessSet::Add(const string& command, bool use_console) { } #ifdef USE_PPOLL -bool SubprocessSet::DoWork(struct TokenPool* tokens) { +bool SubprocessSet::DoWork(TokenPool* tokens) { vector fds; nfds_t nfds = 0; @@ -315,7 +315,7 @@ bool SubprocessSet::DoWork(struct TokenPool* tokens) { } #else // !defined(USE_PPOLL) -bool SubprocessSet::DoWork(struct TokenPool* tokens) { +bool SubprocessSet::DoWork(TokenPool* tokens) { fd_set set; int nfds = 0; FD_ZERO(&set); diff --git a/src/subprocess-win32.cc b/src/subprocess-win32.cc index ce3e2c20a4..2926e9a221 100644 --- a/src/subprocess-win32.cc +++ b/src/subprocess-win32.cc @@ -252,7 +252,7 @@ Subprocess *SubprocessSet::Add(const string& command, bool use_console) { return subprocess; } -bool SubprocessSet::DoWork(struct TokenPool* tokens) { +bool SubprocessSet::DoWork(TokenPool* tokens) { DWORD bytes_read; Subprocess* subproc; OVERLAPPED* overlapped; diff --git a/src/subprocess.h b/src/subprocess.h index 9ea67ea477..1ec78171e8 100644 --- a/src/subprocess.h +++ b/src/subprocess.h @@ -86,7 +86,7 @@ struct SubprocessSet { ~SubprocessSet(); Subprocess* Add(const std::string& command, bool use_console = false); - bool DoWork(struct TokenPool* tokens); + bool DoWork(TokenPool* tokens); Subprocess* NextFinished(); void Clear(); diff --git a/src/subprocess_test.cc b/src/subprocess_test.cc index f625963462..eddc110d41 100644 --- a/src/subprocess_test.cc +++ b/src/subprocess_test.cc @@ -35,7 +35,7 @@ const char* kSimpleCommand = "cmd /c dir \\"; const char* kSimpleCommand = "ls /"; #endif -struct TokenPoolTest : public TokenPool { +struct TestTokenPool : public TokenPool { bool Acquire() { return false; } void Reserve() {} void Release() {} @@ -58,7 +58,7 @@ struct TokenPoolTest : public TokenPool { struct SubprocessTest : public testing::Test { SubprocessSet subprocs_; - TokenPoolTest tokens_; + TestTokenPool tokens_; }; } // anonymous namespace @@ -73,7 +73,7 @@ TEST_F(SubprocessTest, BadCommandStderr) { // Pretend we discovered that stderr was ready for writing. subprocs_.DoWork(NULL); } - ASSERT_EQ(false, subprocs_.IsTokenAvailable()); + ASSERT_FALSE(subprocs_.IsTokenAvailable()); EXPECT_EQ(ExitFailure, subproc->Finish()); EXPECT_NE("", subproc->GetOutput()); @@ -89,7 +89,7 @@ TEST_F(SubprocessTest, NoSuchCommand) { // Pretend we discovered that stderr was ready for writing. subprocs_.DoWork(NULL); } - ASSERT_EQ(false, subprocs_.IsTokenAvailable()); + ASSERT_FALSE(subprocs_.IsTokenAvailable()); EXPECT_EQ(ExitFailure, subproc->Finish()); EXPECT_NE("", subproc->GetOutput()); @@ -109,7 +109,7 @@ TEST_F(SubprocessTest, InterruptChild) { while (!subproc->Done()) { subprocs_.DoWork(NULL); } - ASSERT_EQ(false, subprocs_.IsTokenAvailable()); + ASSERT_FALSE(subprocs_.IsTokenAvailable()); EXPECT_EQ(ExitInterrupted, subproc->Finish()); } @@ -135,7 +135,7 @@ TEST_F(SubprocessTest, InterruptChildWithSigTerm) { while (!subproc->Done()) { subprocs_.DoWork(NULL); } - ASSERT_EQ(false, subprocs_.IsTokenAvailable()); + ASSERT_FALSE(subprocs_.IsTokenAvailable()); EXPECT_EQ(ExitInterrupted, subproc->Finish()); } @@ -161,7 +161,7 @@ TEST_F(SubprocessTest, InterruptChildWithSigHup) { while (!subproc->Done()) { subprocs_.DoWork(NULL); } - ASSERT_EQ(false, subprocs_.IsTokenAvailable()); + ASSERT_FALSE(subprocs_.IsTokenAvailable()); EXPECT_EQ(ExitInterrupted, subproc->Finish()); } @@ -190,7 +190,7 @@ TEST_F(SubprocessTest, Console) { while (!subproc->Done()) { subprocs_.DoWork(NULL); } - ASSERT_EQ(false, subprocs_.IsTokenAvailable()); + ASSERT_FALSE(subprocs_.IsTokenAvailable()); EXPECT_EQ(ExitSuccess, subproc->Finish()); } @@ -206,7 +206,7 @@ TEST_F(SubprocessTest, SetWithSingle) { while (!subproc->Done()) { subprocs_.DoWork(NULL); } - ASSERT_EQ(false, subprocs_.IsTokenAvailable()); + ASSERT_FALSE(subprocs_.IsTokenAvailable()); ASSERT_EQ(ExitSuccess, subproc->Finish()); ASSERT_NE("", subproc->GetOutput()); @@ -243,7 +243,7 @@ TEST_F(SubprocessTest, SetWithMulti) { ASSERT_GT(subprocs_.running_.size(), 0u); subprocs_.DoWork(NULL); } - ASSERT_EQ(false, subprocs_.IsTokenAvailable()); + ASSERT_FALSE(subprocs_.IsTokenAvailable()); ASSERT_EQ(0u, subprocs_.running_.size()); ASSERT_EQ(3u, subprocs_.finished_.size()); @@ -278,7 +278,7 @@ TEST_F(SubprocessTest, SetWithLots) { subprocs_.ResetTokenAvailable(); while (!subprocs_.running_.empty()) subprocs_.DoWork(NULL); - ASSERT_EQ(false, subprocs_.IsTokenAvailable()); + ASSERT_FALSE(subprocs_.IsTokenAvailable()); for (size_t i = 0; i < procs.size(); ++i) { ASSERT_EQ(ExitSuccess, procs[i]->Finish()); ASSERT_NE("", procs[i]->GetOutput()); @@ -298,7 +298,7 @@ TEST_F(SubprocessTest, ReadStdin) { while (!subproc->Done()) { subprocs_.DoWork(NULL); } - ASSERT_EQ(false, subprocs_.IsTokenAvailable()); + ASSERT_FALSE(subprocs_.IsTokenAvailable()); ASSERT_EQ(ExitSuccess, subproc->Finish()); ASSERT_EQ(1u, subprocs_.finished_.size()); } diff --git a/src/tokenpool-gnu-make-posix.cc b/src/tokenpool-gnu-make-posix.cc index 70d84bfff7..8447070849 100644 --- a/src/tokenpool-gnu-make-posix.cc +++ b/src/tokenpool-gnu-make-posix.cc @@ -32,8 +32,8 @@ struct GNUmakeTokenPoolPosix : public GNUmakeTokenPool { virtual int GetMonitorFd(); - virtual const char *GetEnv(const char *name) { return getenv(name); }; - virtual bool ParseAuth(const char *jobserver); + virtual const char* GetEnv(const char* name) { return getenv(name); }; + virtual bool ParseAuth(const char* jobserver); virtual bool AcquireToken(); virtual bool ReturnToken(); @@ -82,14 +82,13 @@ bool GNUmakeTokenPoolPosix::SetAlarmHandler() { act.sa_handler = CloseDupRfd; if (sigaction(SIGALRM, &act, &old_act_) < 0) { perror("sigaction:"); - return(false); - } else { - restore_ = true; - return(true); + return false; } + restore_ = true; + return true; } -bool GNUmakeTokenPoolPosix::ParseAuth(const char *jobserver) { +bool GNUmakeTokenPoolPosix::ParseAuth(const char* jobserver) { int rfd = -1; int wfd = -1; if ((sscanf(jobserver, "%*[^=]=%d,%d", &rfd, &wfd) == 2) && @@ -195,9 +194,9 @@ bool GNUmakeTokenPoolPosix::ReturnToken() { } int GNUmakeTokenPoolPosix::GetMonitorFd() { - return(rfd_); + return rfd_; } -struct TokenPool *TokenPool::Get() { +TokenPool* TokenPool::Get() { return new GNUmakeTokenPoolPosix; } diff --git a/src/tokenpool-gnu-make-win32.cc b/src/tokenpool-gnu-make-win32.cc index 2719f2c1fc..b2bb52fadb 100644 --- a/src/tokenpool-gnu-make-win32.cc +++ b/src/tokenpool-gnu-make-win32.cc @@ -14,7 +14,8 @@ #include "tokenpool-gnu-make.h" -// always include first to make sure other headers do the correct thing... +// Always include this first. +// Otherwise the other system headers don't work correctly under Win32 #include #include @@ -32,8 +33,8 @@ struct GNUmakeTokenPoolWin32 : public GNUmakeTokenPool { virtual void WaitForTokenAvailability(HANDLE ioport); virtual bool TokenIsAvailable(ULONG_PTR key); - virtual const char *GetEnv(const char *name); - virtual bool ParseAuth(const char *jobserver); + virtual const char* GetEnv(const char* name); + virtual bool ParseAuth(const char* jobserver); virtual bool AcquireToken(); virtual bool ReturnToken(); @@ -98,19 +99,19 @@ GNUmakeTokenPoolWin32::~GNUmakeTokenPoolWin32() { } } -const char *GNUmakeTokenPoolWin32::GetEnv(const char *name) { +const char* GNUmakeTokenPoolWin32::GetEnv(const char* name) { // getenv() does not work correctly together with tokenpool_tests.cc static char buffer[MAX_PATH + 1]; - if (GetEnvironmentVariable("MAKEFLAGS", buffer, sizeof(buffer)) == 0) + if (GetEnvironmentVariable(name, buffer, sizeof(buffer)) == 0) return NULL; - return(buffer); + return buffer; } -bool GNUmakeTokenPoolWin32::ParseAuth(const char *jobserver) { +bool GNUmakeTokenPoolWin32::ParseAuth(const char* jobserver) { // match "--jobserver-auth=gmake_semaphore_..." - const char *start = strchr(jobserver, '='); + const char* start = strchr(jobserver, '='); if (start) { - const char *end = start; + const char* end = start; unsigned int len; char c, *auth; @@ -119,14 +120,15 @@ bool GNUmakeTokenPoolWin32::ParseAuth(const char *jobserver) { break; len = end - start; // includes string terminator in count - if ((len > 1) && ((auth = (char *)malloc(len)) != NULL)) { + if ((len > 1) && ((auth = (char*)malloc(len)) != NULL)) { strncpy(auth, start + 1, len - 1); auth[len - 1] = '\0'; - if ((semaphore_jobserver_ = OpenSemaphore(SEMAPHORE_ALL_ACCESS, /* Semaphore access setting */ - FALSE, /* Child processes DON'T inherit */ - auth /* Semaphore name */ - )) != NULL) { + if ((semaphore_jobserver_ = + OpenSemaphore(SEMAPHORE_ALL_ACCESS, /* Semaphore access setting */ + FALSE, /* Child processes DON'T inherit */ + auth /* Semaphore name */ + )) != NULL) { free(auth); return true; } @@ -171,7 +173,7 @@ DWORD GNUmakeTokenPoolWin32::SemaphoreThread() { } DWORD WINAPI GNUmakeTokenPoolWin32::SemaphoreThreadWrapper(LPVOID param) { - GNUmakeTokenPoolWin32 *This = (GNUmakeTokenPoolWin32 *) param; + GNUmakeTokenPoolWin32* This = (GNUmakeTokenPoolWin32*) param; return This->SemaphoreThread(); } @@ -216,7 +218,7 @@ void GNUmakeTokenPoolWin32::WaitForTokenAvailability(HANDLE ioport) { bool GNUmakeTokenPoolWin32::TokenIsAvailable(ULONG_PTR key) { // alert child thread to break wait on token semaphore - QueueUserAPC(&NoopAPCFunc, child_, (ULONG_PTR)NULL); + QueueUserAPC((PAPCFUNC)&NoopAPCFunc, child_, (ULONG_PTR)NULL); // return true when GetQueuedCompletionStatus() returned our key return key == (ULONG_PTR) this; @@ -232,6 +234,6 @@ void GNUmakeTokenPoolWin32::WaitForObject(HANDLE object) { Win32Fatal("WaitForSingleObject"); } -struct TokenPool *TokenPool::Get() { +TokenPool* TokenPool::Get() { return new GNUmakeTokenPoolWin32; } diff --git a/src/tokenpool-gnu-make.cc b/src/tokenpool-gnu-make.cc index 92ff611721..60e0552924 100644 --- a/src/tokenpool-gnu-make.cc +++ b/src/tokenpool-gnu-make.cc @@ -31,36 +31,37 @@ GNUmakeTokenPool::~GNUmakeTokenPool() { bool GNUmakeTokenPool::Setup(bool ignore, bool verbose, double& max_load_average) { - const char *value = GetEnv("MAKEFLAGS"); - if (value) { - // GNU make <= 4.1 - const char *jobserver = strstr(value, "--jobserver-fds="); + const char* value = GetEnv("MAKEFLAGS"); + if (!value) + return false; + + // GNU make <= 4.1 + const char* jobserver = strstr(value, "--jobserver-fds="); + if (!jobserver) // GNU make => 4.2 - if (!jobserver) - jobserver = strstr(value, "--jobserver-auth="); - if (jobserver) { - LinePrinter printer; - - if (ignore) { - printer.PrintOnNewLine("ninja: warning: -jN forced on command line; ignoring GNU make jobserver.\n"); - } else { - if (ParseAuth(jobserver)) { - const char *l_arg = strstr(value, " -l"); - int load_limit = -1; - - if (verbose) { - printer.PrintOnNewLine("ninja: using GNU make jobserver.\n"); - } - - // translate GNU make -lN to ninja -lN - if (l_arg && - (sscanf(l_arg + 3, "%d ", &load_limit) == 1) && - (load_limit > 0)) { - max_load_average = load_limit; - } - - return true; + jobserver = strstr(value, "--jobserver-auth="); + if (jobserver) { + LinePrinter printer; + + if (ignore) { + printer.PrintOnNewLine("ninja: warning: -jN forced on command line; ignoring GNU make jobserver.\n"); + } else { + if (ParseAuth(jobserver)) { + const char* l_arg = strstr(value, " -l"); + int load_limit = -1; + + if (verbose) { + printer.PrintOnNewLine("ninja: using GNU make jobserver.\n"); + } + + // translate GNU make -lN to ninja -lN + if (l_arg && + (sscanf(l_arg + 3, "%d ", &load_limit) == 1) && + (load_limit > 0)) { + max_load_average = load_limit; } + + return true; } } } @@ -76,10 +77,10 @@ bool GNUmakeTokenPool::Acquire() { // token acquired available_++; return true; - } else { - // no token available - return false; } + + // no token available + return false; } void GNUmakeTokenPool::Reserve() { diff --git a/src/tokenpool-gnu-make.h b/src/tokenpool-gnu-make.h index d3852088e2..c94cca5e2d 100644 --- a/src/tokenpool-gnu-make.h +++ b/src/tokenpool-gnu-make.h @@ -17,7 +17,7 @@ // interface to GNU make token pool struct GNUmakeTokenPool : public TokenPool { GNUmakeTokenPool(); - virtual ~GNUmakeTokenPool(); + ~GNUmakeTokenPool(); // token pool implementation virtual bool Acquire(); @@ -27,8 +27,8 @@ struct GNUmakeTokenPool : public TokenPool { virtual bool Setup(bool ignore, bool verbose, double& max_load_average); // platform specific implementation - virtual const char *GetEnv(const char *name) = 0; - virtual bool ParseAuth(const char *jobserver) = 0; + virtual const char* GetEnv(const char* name) = 0; + virtual bool ParseAuth(const char* jobserver) = 0; virtual bool AcquireToken() = 0; virtual bool ReturnToken() = 0; diff --git a/src/tokenpool-none.cc b/src/tokenpool-none.cc deleted file mode 100644 index 613d16882d..0000000000 --- a/src/tokenpool-none.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016-2018 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "tokenpool.h" - -#include - -// No-op TokenPool implementation -struct TokenPool *TokenPool::Get() { - return NULL; -} diff --git a/src/tokenpool.h b/src/tokenpool.h index 1be8e1d5ce..931c22754d 100644 --- a/src/tokenpool.h +++ b/src/tokenpool.h @@ -38,5 +38,5 @@ struct TokenPool { #endif // returns NULL if token pool is not available - static struct TokenPool *Get(); + static TokenPool* Get(); }; diff --git a/src/tokenpool_test.cc b/src/tokenpool_test.cc index 8d4fd7d33a..1bc1c84c00 100644 --- a/src/tokenpool_test.cc +++ b/src/tokenpool_test.cc @@ -43,10 +43,10 @@ const double kLoadAverageDefault = -1.23456789; struct TokenPoolTest : public testing::Test { double load_avg_; - TokenPool *tokens_; + TokenPool* tokens_; char buf_[1024]; #ifdef _WIN32 - const char *semaphore_name_; + const char* semaphore_name_; HANDLE semaphore_; #else int fds_[2]; @@ -65,7 +65,7 @@ struct TokenPoolTest : public testing::Test { ASSERT_TRUE(false); } - void CreatePool(const char *format, bool ignore_jobserver = false) { + void CreatePool(const char* format, bool ignore_jobserver = false) { if (format) { sprintf(buf_, format, #ifdef _WIN32