From 52649de2c56b63f42bc59513d51286531c595b44 Mon Sep 17 00:00:00 2001 From: zero9178 Date: Wed, 20 May 2020 14:38:36 +0200 Subject: bugfix: Process escaped colon in GCC depfiles. (#1774) * Added ability to parse escaped colons in GCC Dep files enabling ninja to parse dep files of GCC 10 on Windows * Added generated depfile_parser.cc * Addressed formatting * Added extra tests with real world examples of paths produced by both GCC 10 and Clang and GCC pre 10. Adjusted one test so it doesn't fail * Adjusted regular expression to not match \: if the character following the : is either EOF or whitespace * Fixed typo in regex (should be 0x20 for space not 0xa) * Changed regular expression form using lookahead to instead matching a separate expression. This was needed as re2c pre version 1.17 is broken when using lookaheads. Also added tests for \: followed by whitespace * Addressed formatting * Forgot a missing std:: * Fixed formatting for spaces after , as well as respecting column width --- src/depfile_parser.cc | 87 +++++++++++++++++++++++++++++++++------------- src/depfile_parser.in.cc | 23 ++++++++++++ src/depfile_parser_test.cc | 35 +++++++++++++++++++ 3 files changed, 121 insertions(+), 24 deletions(-) diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc index 90d4a8a..0b7dce1 100644 --- a/src/depfile_parser.cc +++ b/src/depfile_parser.cc @@ -1,4 +1,4 @@ -/* Generated by re2c 1.1.1 */ +/* Generated by re2c 1.3 */ // Copyright 2011 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -166,22 +166,23 @@ yy12: goto yy5; yy13: yych = *(yymarker = ++in); - if (yych <= 0x1F) { + if (yych <= ' ') { if (yych <= '\n') { if (yych <= 0x00) goto yy5; if (yych <= '\t') goto yy16; goto yy17; } else { if (yych == '\r') goto yy19; - goto yy16; + if (yych <= 0x1F) goto yy16; + goto yy21; } } else { - if (yych <= '#') { - if (yych <= ' ') goto yy21; - if (yych <= '"') goto yy16; - goto yy23; + if (yych <= '9') { + if (yych == '#') goto yy23; + goto yy16; } else { - if (yych == '\\') goto yy25; + if (yych <= ':') goto yy25; + if (yych == '\\') goto yy27; goto yy16; } } @@ -231,26 +232,63 @@ yy23: } yy25: yych = *++in; - if (yych <= 0x1F) { + if (yych <= '\f') { + if (yych <= 0x00) goto yy28; + if (yych <= 0x08) goto yy26; + if (yych <= '\n') goto yy28; + } else { + if (yych <= '\r') goto yy28; + if (yych == ' ') goto yy28; + } +yy26: + { + // De-escape colon sign, but preserve other leading backslashes. + // Regular expression uses lookahead to make sure that no whitespace + // nor EOF follows. In that case it'd be the : at the end of a target + int len = (int)(in - start); + if (len > 2 && out < start) + memset(out, '\\', len - 2); + out += len - 2; + *out++ = ':'; + continue; + } +yy27: + yych = *++in; + if (yych <= ' ') { if (yych <= '\n') { if (yych <= 0x00) goto yy11; if (yych <= '\t') goto yy16; goto yy11; } else { if (yych == '\r') goto yy11; - goto yy16; + if (yych <= 0x1F) goto yy16; + goto yy30; } } else { - if (yych <= '#') { - if (yych <= ' ') goto yy26; - if (yych <= '"') goto yy16; - goto yy23; + if (yych <= '9') { + if (yych == '#') goto yy23; + goto yy16; } else { - if (yych == '\\') goto yy28; + if (yych <= ':') goto yy25; + if (yych == '\\') goto yy32; goto yy16; } } -yy26: +yy28: + ++in; + { + // Backslash followed by : and whitespace. + // It is therefore normal text and not an escaped colon + int len = (int)(in - start - 1); + // Need to shift it over if we're overwriting backslashes. + if (out < start) + memmove(out, start, len); + out += len; + if (*(in - 1) == '\n') + have_newline = true; + break; + } +yy30: ++in; { // 2N backslashes plus space -> 2N backslashes, end of filename. @@ -260,24 +298,25 @@ yy26: out += len - 1; break; } -yy28: +yy32: yych = *++in; - if (yych <= 0x1F) { + if (yych <= ' ') { if (yych <= '\n') { if (yych <= 0x00) goto yy11; if (yych <= '\t') goto yy16; goto yy11; } else { if (yych == '\r') goto yy11; - goto yy16; + if (yych <= 0x1F) goto yy16; + goto yy21; } } else { - if (yych <= '#') { - if (yych <= ' ') goto yy21; - if (yych <= '"') goto yy16; - goto yy23; + if (yych <= '9') { + if (yych == '#') goto yy23; + goto yy16; } else { - if (yych == '\\') goto yy25; + if (yych <= ':') goto yy25; + if (yych == '\\') goto yy27; goto yy16; } } diff --git a/src/depfile_parser.in.cc b/src/depfile_parser.in.cc index b32b942..95b4346 100644 --- a/src/depfile_parser.in.cc +++ b/src/depfile_parser.in.cc @@ -103,6 +103,29 @@ bool DepfileParser::Parse(string* content, string* err) { *out++ = '#'; continue; } + '\\'+ ':' [\x00\x20\r\n\t] { + // Backslash followed by : and whitespace. + // It is therefore normal text and not an escaped colon + int len = (int)(in - start - 1); + // Need to shift it over if we're overwriting backslashes. + if (out < start) + memmove(out, start, len); + out += len; + if (*(in - 1) == '\n') + have_newline = true; + break; + } + '\\'+ ':' { + // De-escape colon sign, but preserve other leading backslashes. + // Regular expression uses lookahead to make sure that no whitespace + // nor EOF follows. In that case it'd be the : at the end of a target + int len = (int)(in - start); + if (len > 2 && out < start) + memset(out, '\\', len - 2); + out += len - 2; + *out++ = ':'; + continue; + } '$$' { // De-escape dollar character. *out++ = '$'; diff --git a/src/depfile_parser_test.cc b/src/depfile_parser_test.cc index bf1a0bc..8e2cd25 100644 --- a/src/depfile_parser_test.cc +++ b/src/depfile_parser_test.cc @@ -142,6 +142,41 @@ TEST_F(DepfileParserTest, Escapes) { ASSERT_EQ(0u, parser_.ins_.size()); } +TEST_F(DepfileParserTest, EscapedColons) +{ + std::string err; + // Tests for correct parsing of depfiles produced on Windows + // by both Clang, GCC pre 10 and GCC 10 + EXPECT_TRUE(Parse( +"c\\:\\gcc\\x86_64-w64-mingw32\\include\\stddef.o: \\\n" +" c:\\gcc\\x86_64-w64-mingw32\\include\\stddef.h \n", + &err)); + ASSERT_EQ("", err); + ASSERT_EQ(1u, parser_.outs_.size()); + EXPECT_EQ("c:\\gcc\\x86_64-w64-mingw32\\include\\stddef.o", + parser_.outs_[0].AsString()); + ASSERT_EQ(1u, parser_.ins_.size()); + EXPECT_EQ("c:\\gcc\\x86_64-w64-mingw32\\include\\stddef.h", + parser_.ins_[0].AsString()); +} + +TEST_F(DepfileParserTest, EscapedTargetColon) +{ + std::string err; + EXPECT_TRUE(Parse( +"foo1\\: x\n" +"foo1\\:\n" +"foo1\\:\r\n" +"foo1\\:\t\n" +"foo1\\:", + &err)); + ASSERT_EQ("", err); + ASSERT_EQ(1u, parser_.outs_.size()); + EXPECT_EQ("foo1\\", parser_.outs_[0].AsString()); + ASSERT_EQ(1u, parser_.ins_.size()); + EXPECT_EQ("x", parser_.ins_[0].AsString()); +} + TEST_F(DepfileParserTest, SpecialChars) { // See filenames like istreambuf.iterator_op!= in // https://github.com/google/libcxx/tree/master/test/iterators/stream.iterators/istreambuf.iterator/ -- cgit v0.12 From cc79afbc0510b7320d35fb481f0f200dec92cb43 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Mon, 18 May 2020 12:46:18 +0200 Subject: Delay actually opening log files until the first write, fix #1724 Calling DepsLog/BuildLog::OpenForWrite will now only save the file path. The actual opening of the file (moved to OpenForWriteIfNeeded) happens right before the first write attempt. This is needed so that the files aren't held open when the generator runs (i.e. RebuildManifest) as it may call tools like recompact which won't be able to open the file on Windows. The disadvantage is that now the error reporting happens at a later time and will be reported as a failed write, not a failed open. --- src/build_log.cc | 51 ++++++++++++++++++++++++--------------- src/build_log.h | 8 +++++++ src/deps_log.cc | 72 ++++++++++++++++++++++++++++++++++---------------------- src/deps_log.h | 5 ++++ 4 files changed, 89 insertions(+), 47 deletions(-) diff --git a/src/build_log.cc b/src/build_log.cc index 98543b6..e5f179c 100644 --- a/src/build_log.cc +++ b/src/build_log.cc @@ -23,6 +23,7 @@ #include "build_log.h" #include "disk_interface.h" +#include #include #include #include @@ -132,25 +133,9 @@ bool BuildLog::OpenForWrite(const string& path, const BuildLogUser& user, return false; } - log_file_ = fopen(path.c_str(), "ab"); - if (!log_file_) { - *err = strerror(errno); - return false; - } - setvbuf(log_file_, NULL, _IOLBF, BUFSIZ); - SetCloseOnExec(fileno(log_file_)); - - // Opening a file in append mode doesn't set the file pointer to the file's - // end on Windows. Do that explicitly. - fseek(log_file_, 0, SEEK_END); - - if (ftell(log_file_) == 0) { - if (fprintf(log_file_, kFileSignature, kCurrentVersion) < 0) { - *err = strerror(errno); - return false; - } - } - + assert(!log_file_); + log_file_path_ = path; // we don't actually open the file right now, but will + // do so on the first write attempt return true; } @@ -174,6 +159,9 @@ bool BuildLog::RecordCommand(Edge* edge, int start_time, int end_time, log_entry->end_time = end_time; log_entry->mtime = mtime; + if (!OpenForWriteIfNeeded()) { + return false; + } if (log_file_) { if (!WriteEntry(log_file_, *log_entry)) return false; @@ -186,11 +174,36 @@ bool BuildLog::RecordCommand(Edge* edge, int start_time, int end_time, } void BuildLog::Close() { + OpenForWriteIfNeeded(); // create the file even if nothing has been recorded if (log_file_) fclose(log_file_); log_file_ = NULL; } +bool BuildLog::OpenForWriteIfNeeded() { + if (log_file_path_.empty()) { + return true; + } + log_file_ = fopen(log_file_path_.c_str(), "ab"); + if (!log_file_) { + return false; + } + setvbuf(log_file_, NULL, _IOLBF, BUFSIZ); + SetCloseOnExec(fileno(log_file_)); + + // Opening a file in append mode doesn't set the file pointer to the file's + // end on Windows. Do that explicitly. + fseek(log_file_, 0, SEEK_END); + + if (ftell(log_file_) == 0) { + if (fprintf(log_file_, kFileSignature, kCurrentVersion) < 0) { + return false; + } + } + log_file_path_.clear(); + return true; +} + struct LineReader { explicit LineReader(FILE* file) : file_(file), buf_end_(buf_), line_start_(buf_), line_end_(NULL) { diff --git a/src/build_log.h b/src/build_log.h index ebe0530..6d060d1 100644 --- a/src/build_log.h +++ b/src/build_log.h @@ -45,7 +45,10 @@ struct BuildLog { BuildLog(); ~BuildLog(); + /// Prepares writing to the log file without actually opening it - that will + /// happen when/if it's needed bool OpenForWrite(const string& path, const BuildLogUser& user, string* err); + bool RecordCommand(Edge* edge, int start_time, int end_time, TimeStamp mtime = 0); void Close(); @@ -91,8 +94,13 @@ struct BuildLog { const Entries& entries() const { return entries_; } private: + /// Should be called before using log_file_. When false is returned, errno + /// will be set. + bool OpenForWriteIfNeeded(); + Entries entries_; FILE* log_file_; + std::string log_file_path_; bool needs_recompaction_; }; diff --git a/src/deps_log.cc b/src/deps_log.cc index cf55194..db8f071 100644 --- a/src/deps_log.cc +++ b/src/deps_log.cc @@ -49,34 +49,9 @@ bool DepsLog::OpenForWrite(const string& path, string* err) { return false; } - file_ = fopen(path.c_str(), "ab"); - if (!file_) { - *err = strerror(errno); - return false; - } - // Set the buffer size to this and flush the file buffer after every record - // to make sure records aren't written partially. - setvbuf(file_, NULL, _IOFBF, kMaxRecordSize + 1); - SetCloseOnExec(fileno(file_)); - - // Opening a file in append mode doesn't set the file pointer to the file's - // end on Windows. Do that explicitly. - fseek(file_, 0, SEEK_END); - - if (ftell(file_) == 0) { - if (fwrite(kFileSignature, sizeof(kFileSignature) - 1, 1, file_) < 1) { - *err = strerror(errno); - return false; - } - if (fwrite(&kCurrentVersion, 4, 1, file_) < 1) { - *err = strerror(errno); - return false; - } - } - if (fflush(file_) != 0) { - *err = strerror(errno); - return false; - } + assert(!file_); + file_path_ = path; // we don't actually open the file right now, but will do + // so on the first write attempt return true; } @@ -132,6 +107,10 @@ bool DepsLog::RecordDeps(Node* node, TimeStamp mtime, errno = ERANGE; return false; } + + if (!OpenForWriteIfNeeded()) { + return false; + } size |= 0x80000000; // Deps record: set high bit. if (fwrite(&size, 4, 1, file_) < 1) return false; @@ -162,6 +141,7 @@ bool DepsLog::RecordDeps(Node* node, TimeStamp mtime, } void DepsLog::Close() { + OpenForWriteIfNeeded(); // create the file even if nothing has been recorded if (file_) fclose(file_); file_ = NULL; @@ -396,6 +376,10 @@ bool DepsLog::RecordId(Node* node) { errno = ERANGE; return false; } + + if (!OpenForWriteIfNeeded()) { + return false; + } if (fwrite(&size, 4, 1, file_) < 1) return false; if (fwrite(node->path().data(), path_size, 1, file_) < 1) { @@ -416,3 +400,35 @@ bool DepsLog::RecordId(Node* node) { return true; } + +bool DepsLog::OpenForWriteIfNeeded() { + if (file_path_.empty()) { + return true; + } + file_ = fopen(file_path_.c_str(), "ab"); + if (!file_) { + return false; + } + // Set the buffer size to this and flush the file buffer after every record + // to make sure records aren't written partially. + setvbuf(file_, NULL, _IOFBF, kMaxRecordSize + 1); + SetCloseOnExec(fileno(file_)); + + // Opening a file in append mode doesn't set the file pointer to the file's + // end on Windows. Do that explicitly. + fseek(file_, 0, SEEK_END); + + if (ftell(file_) == 0) { + if (fwrite(kFileSignature, sizeof(kFileSignature) - 1, 1, file_) < 1) { + return false; + } + if (fwrite(&kCurrentVersion, 4, 1, file_) < 1) { + return false; + } + } + if (fflush(file_) != 0) { + return false; + } + file_path_.clear(); + return true; +} diff --git a/src/deps_log.h b/src/deps_log.h index e7974a1..c4ada8b 100644 --- a/src/deps_log.h +++ b/src/deps_log.h @@ -110,8 +110,13 @@ struct DepsLog { // Write a node name record, assigning it an id. bool RecordId(Node* node); + /// Should be called before using file_. When false is returned, errno will + /// be set. + bool OpenForWriteIfNeeded(); + bool needs_recompaction_; FILE* file_; + std::string file_path_; /// Maps id -> Node. vector nodes_; -- cgit v0.12 From ea9f736100ec5db72526c286c0e8c9e626b2a908 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Mon, 25 May 2020 10:58:34 +0200 Subject: Add missing Apache license header, fix #1781 --- misc/ninja_syntax.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/misc/ninja_syntax.py b/misc/ninja_syntax.py index ebe6490..ab5c0d4 100644 --- a/misc/ninja_syntax.py +++ b/misc/ninja_syntax.py @@ -1,5 +1,19 @@ #!/usr/bin/python +# Copyright 2011 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. + """Python module for generating .ninja files. Note that this is emphatically not a required piece of Ninja; it's -- cgit v0.12 From a32a2087b65e9e858fbd1450555108bfda95adfb Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 4 Jun 2020 00:46:43 -0700 Subject: [clang-tidy] remove pointless c_str() (#1785) Found with readability-redundant-string-cstr Signed-off-by: Rosen Penev --- src/disk_interface_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disk_interface_test.cc b/src/disk_interface_test.cc index bac515d..866d1d6 100644 --- a/src/disk_interface_test.cc +++ b/src/disk_interface_test.cc @@ -190,7 +190,7 @@ TEST_F(DiskInterfaceTest, ReadFile) { TEST_F(DiskInterfaceTest, MakeDirs) { string path = "path/with/double//slash/"; - EXPECT_TRUE(disk_.MakeDirs(path.c_str())); + EXPECT_TRUE(disk_.MakeDirs(path)); FILE* f = fopen((path + "a_file").c_str(), "w"); EXPECT_TRUE(f); EXPECT_EQ(0, fclose(f)); -- cgit v0.12 From be6c7afcd1eb87b150a285043520d46d23674070 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 4 Jun 2020 00:47:37 -0700 Subject: [clang-tidy] check empty instead of size (#1784) Found with readability-container-size-empty Signed-off-by: Rosen Penev --- src/build.cc | 2 +- src/build_test.cc | 2 +- src/deps_log.cc | 2 +- src/string_piece_util.cc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/build.cc b/src/build.cc index cd8df4e..a16593b 100644 --- a/src/build.cc +++ b/src/build.cc @@ -1033,7 +1033,7 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) { } if (!deps_type.empty() && !config_.dry_run) { - assert(edge->outputs_.size() >= 1 && "should have been rejected by parser"); + assert(!edge->outputs_.empty() && "should have been rejected by parser"); for (std::vector::const_iterator o = edge->outputs_.begin(); o != edge->outputs_.end(); ++o) { TimeStamp deps_mtime = disk_interface_->Stat((*o)->path(), err); diff --git a/src/build_test.cc b/src/build_test.cc index 426e825..12c3383 100644 --- a/src/build_test.cc +++ b/src/build_test.cc @@ -672,7 +672,7 @@ bool FakeCommandRunner::WaitForCommand(Result* result) { bool verify_active_edge_found = false; for (vector::iterator i = active_edges_.begin(); i != active_edges_.end(); ++i) { - if ((*i)->outputs_.size() >= 1 && + if (!(*i)->outputs_.empty() && (*i)->outputs_[0]->path() == verify_active_edge) { verify_active_edge_found = true; } diff --git a/src/deps_log.cc b/src/deps_log.cc index cf55194..59a1956 100644 --- a/src/deps_log.cc +++ b/src/deps_log.cc @@ -399,7 +399,7 @@ bool DepsLog::RecordId(Node* node) { if (fwrite(&size, 4, 1, file_) < 1) return false; if (fwrite(node->path().data(), path_size, 1, file_) < 1) { - assert(node->path().size() > 0); + assert(!node->path().empty()); return false; } if (padding && fwrite("\0\0", padding, 1, file_) < 1) diff --git a/src/string_piece_util.cc b/src/string_piece_util.cc index 8e1ecfd..69513f5 100644 --- a/src/string_piece_util.cc +++ b/src/string_piece_util.cc @@ -39,7 +39,7 @@ vector SplitStringPiece(StringPiece input, char sep) { } string JoinStringPiece(const vector& list, char sep) { - if (list.size() == 0){ + if (list.empty()) { return ""; } -- cgit v0.12 From 76ea0462a37b9b5a7dd483416346ee7749b7bdc1 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Mon, 15 Jun 2020 09:19:40 +0200 Subject: GitHub Actions: Run ninja_test directly (Windows) --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index d961582..4ac7fd1 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -23,7 +23,7 @@ jobs: cmake --build build --parallel --config Release - name: Test ninja - run: ctest -vv + run: ./ninja_test working-directory: build - name: Create ninja archive -- cgit v0.12 From 86d30f775dd643e03c2667a9232b2f439ef4b4da Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Mon, 15 Jun 2020 09:26:20 +0200 Subject: GitHub Actions: PowerShell requires \ instead of / --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 4ac7fd1..0ab2a70 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -23,7 +23,7 @@ jobs: cmake --build build --parallel --config Release - name: Test ninja - run: ./ninja_test + run: .\ninja_test.exe working-directory: build - name: Create ninja archive -- cgit v0.12 From 8948ec2de60249deb756e02cf3c742f62f12aafe Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Mon, 15 Jun 2020 09:33:53 +0200 Subject: GitHub Actions: Switch to MSVC's subdirectory --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 0ab2a70..04fc2f6 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -24,7 +24,7 @@ jobs: - name: Test ninja run: .\ninja_test.exe - working-directory: build + working-directory: build/Release - name: Create ninja archive shell: bash -- cgit v0.12 From 7e678b5d4d35bb497d42860c089bcf9468942bcc Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 2 Jun 2020 18:05:38 -0700 Subject: [clang-tidy] remove redundant member init Found with readability-redundant-member-init Signed-off-by: Rosen Penev --- src/build.cc | 9 +++------ src/clean.cc | 2 -- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/build.cc b/src/build.cc index a16593b..a32bdda 100644 --- a/src/build.cc +++ b/src/build.cc @@ -77,12 +77,9 @@ bool DryRunCommandRunner::WaitForCommand(Result* result) { } // namespace BuildStatus::BuildStatus(const BuildConfig& config) - : config_(config), - start_time_millis_(GetTimeMillis()), - started_edges_(0), finished_edges_(0), total_edges_(0), - progress_status_format_(NULL), - overall_rate_(), current_rate_(config.parallelism) { - + : config_(config), start_time_millis_(GetTimeMillis()), started_edges_(0), + finished_edges_(0), total_edges_(0), progress_status_format_(NULL), + current_rate_(config.parallelism) { // Don't do anything fancy in verbose mode. if (config_.verbosity != BuildConfig::NORMAL) printer_.set_smart_terminal(false); diff --git a/src/clean.cc b/src/clean.cc index ec6e7d7..55d7277 100644 --- a/src/clean.cc +++ b/src/clean.cc @@ -28,8 +28,6 @@ Cleaner::Cleaner(State* state, : state_(state), config_(config), dyndep_loader_(state, disk_interface), - removed_(), - cleaned_(), cleaned_files_count_(0), disk_interface_(disk_interface), status_(0) { -- cgit v0.12 From 0ab46c5918b7fdcbd0846f4c6284646015accd64 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 2 Jun 2020 18:28:20 -0700 Subject: [clang-tidy] fix small false positive else if has to be on the same line it seems. Found with readability-misleading-indentation Signed-off-by: Rosen Penev --- src/build.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/build.cc b/src/build.cc index a16593b..ecb35a4 100644 --- a/src/build.cc +++ b/src/build.cc @@ -1067,8 +1067,7 @@ bool Builder::ExtractDeps(CommandRunner::Result* result, // complexity in IncludesNormalize::Relativize. deps_nodes->push_back(state_->GetNode(*i, ~0u)); } - } else - if (deps_type == "gcc") { + } else if (deps_type == "gcc") { string depfile = result->edge->GetUnescapedDepfile(); if (depfile.empty()) { *err = string("edge with deps=gcc but no depfile makes no sense"); -- cgit v0.12 From 580f57fe7745fcbbb5d0c4cd446ecf8001a20b62 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sun, 21 Jun 2020 18:32:02 -0400 Subject: Include unistd.h in disk_interface.cc stat() needs unistd.h in addition to sys/stat.h and sys/types.h per POSIX. At least one (hobby) OS does need unistd.h, so add an include for it. --- src/disk_interface.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/disk_interface.cc b/src/disk_interface.cc index dc297c4..594bc51 100644 --- a/src/disk_interface.cc +++ b/src/disk_interface.cc @@ -26,6 +26,8 @@ #include #include #include // _mkdir +#else +#include #endif #include "metrics.h" -- cgit v0.12 From b1914048285d627027ccd5df801c7d43ede0c060 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sun, 21 Jun 2020 18:37:46 -0400 Subject: Include sys/select.h in subprocess-posix.cc pselect() is in sys/select.h in "newer" (2001) versions of posix, so add an include for it. While here, only include poll.h if USE_PPOLL is defined. --- src/subprocess-posix.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/subprocess-posix.cc b/src/subprocess-posix.cc index fc5543e..74785d1 100644 --- a/src/subprocess-posix.cc +++ b/src/subprocess-posix.cc @@ -18,13 +18,18 @@ #include #include #include -#include #include #include #include #include #include +#if defined(USE_PPOLL) +#include +#else +#include +#endif + extern char** environ; #include "util.h" -- cgit v0.12 From 6c5e886aacd98766fe43539c2c8ae7f3ca2af2aa Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Sun, 5 Jul 2020 16:57:33 +0300 Subject: Fix typos --- doc/manual.asciidoc | 4 ++-- src/build.cc | 2 +- src/ninja.cc | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc index 9976ce4..e1ae083 100644 --- a/doc/manual.asciidoc +++ b/doc/manual.asciidoc @@ -899,7 +899,7 @@ set environment variables. On Windows, commands are strings, so Ninja passes the `command` string directly to `CreateProcess`. (In the common case of simply executing a compiler this means there is less overhead.) Consequently the -quoting rules are deterimined by the called program, which on Windows +quoting rules are determined by the called program, which on Windows are usually provided by the C library. If you need shell interpretation of the command (such as the use of `&&` to chain multiple commands), make the command execute the Windows shell by @@ -935,7 +935,7 @@ There are three types of build dependencies which are subtly different. 1. _Explicit dependencies_, as listed in a build line. These are available as the `$in` variable in the rule. Changes in these files - cause the output to be rebuilt; if these file are missing and + cause the output to be rebuilt; if these files are missing and Ninja doesn't know how to build them, the build is aborted. + This is the standard form of dependency to be used e.g. for the diff --git a/src/build.cc b/src/build.cc index a16593b..db28e65 100644 --- a/src/build.cc +++ b/src/build.cc @@ -183,7 +183,7 @@ void BuildStatus::BuildLoadDyndeps() { // it considers a portion of the graph to be out of date. Normally // this is done before the build starts, but our caller is about to // load a dyndep file during the build. Doing so may generate more - // exlanation lines (via fprintf directly to stderr), but in an + // explanation lines (via fprintf directly to stderr), but in an // interactive console the cursor is currently at the end of a status // line. Start a new line so that the first explanation does not // append to the status line. After the explanations are done a diff --git a/src/ninja.cc b/src/ninja.cc index 1429639..00e3a5c 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -91,7 +91,7 @@ struct NinjaMain : public BuildLogUser { /// Loaded state (rules, nodes). State state_; - /// Functions for accesssing the disk. + /// Functions for accessing the disk. RealDiskInterface disk_interface_; /// The build directory, used for storing the build log etc. @@ -1050,7 +1050,7 @@ bool DebugEnable(const string& name) { } } -/// Set a warning flag. Returns false if Ninja should exit instead of +/// Set a warning flag. Returns false if Ninja should exit instead of /// continuing. bool WarningEnable(const string& name, Options* options) { if (name == "list") { -- cgit v0.12 From 086a9b2f8833fd45f2119596f74f90b9f7e2cdf5 Mon Sep 17 00:00:00 2001 From: David Callu Date: Thu, 16 Jul 2020 14:06:20 +0200 Subject: cmake: use PROJECT_{SOURCE,BINARY}_DIR instead of CMAKE_{SOURCE,BINARY}_DIR CMAKE_SOURCE_DIR refer to the full path to the top level of the current CMake source tree PROJECT_SOURCE_DIR refer to the source directory of the last call to the project() command made in the current directory scope or one of its parents when ninja is use as a subproject, the build fail because of this. --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 007c662..65e42a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,9 +39,9 @@ if(RE2C) COMMAND ${RE2C} -b -i --no-generation-date -o ${OUT} ${IN} ) endfunction() - re2c(${CMAKE_SOURCE_DIR}/src/depfile_parser.in.cc ${CMAKE_BINARY_DIR}/depfile_parser.cc) - re2c(${CMAKE_SOURCE_DIR}/src/lexer.in.cc ${CMAKE_BINARY_DIR}/lexer.cc) - add_library(libninja-re2c OBJECT ${CMAKE_BINARY_DIR}/depfile_parser.cc ${CMAKE_BINARY_DIR}/lexer.cc) + re2c(${PROJECT_SOURCE_DIR}/src/depfile_parser.in.cc ${PROJECT_BINARY_DIR}/depfile_parser.cc) + re2c(${PROJECT_SOURCE_DIR}/src/lexer.in.cc ${PROJECT_BINARY_DIR}/lexer.cc) + add_library(libninja-re2c OBJECT ${PROJECT_BINARY_DIR}/depfile_parser.cc ${PROJECT_BINARY_DIR}/lexer.cc) else() message(WARNING "re2c was not found; changes to src/*.in.cc will not affect your build.") add_library(libninja-re2c OBJECT src/depfile_parser.cc src/lexer.cc) -- cgit v0.12 From 6c5fc1d4ec2cbe32b5e617895da433ee6e974ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Le=C5=9Bniak?= Date: Sat, 1 Aug 2020 17:04:14 +0200 Subject: Use c++ instead of g++ `configure.py` assumes `g++` is present on the system, which is not the case, e.g. for FreeBSD. `c++` should be used insted, which should be a link to system c++ compiler. This will be `g++` for linux, but `clang++` for FreeBSD. --- configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.py b/configure.py index 8eef7e6..48c4821 100755 --- a/configure.py +++ b/configure.py @@ -269,7 +269,7 @@ if configure_env: n.variable('configure_env', config_str + '$ ') n.newline() -CXX = configure_env.get('CXX', 'g++') +CXX = configure_env.get('CXX', 'c++') objext = '.o' if platform.is_msvc(): CXX = 'cl' -- cgit v0.12 From 9ddd3c917793bb97eb19d571429cdedf07501c03 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Tue, 18 Aug 2020 21:24:50 +0200 Subject: Mark this 1.10.1.git --- src/version.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.cc b/src/version.cc index 74e1213..9d27e87 100644 --- a/src/version.cc +++ b/src/version.cc @@ -18,7 +18,7 @@ #include "util.h" -const char* kNinjaVersion = "1.10.0.git"; +const char* kNinjaVersion = "1.10.1.git"; void ParseVersion(const string& version, int* major, int* minor) { size_t end = version.find('.'); -- cgit v0.12 From 5b80abbc729e94abb5f5776a3438ad57d480c097 Mon Sep 17 00:00:00 2001 From: Alastair Harrison Date: Thu, 27 Aug 2020 21:47:27 +0100 Subject: CMake: Add support for "browse" mode Fixes ninja-build/ninja#1822, fixes ninja-build/ninja#1853 Adds support for `ninja -t browse` to CMake builds. The platform support logic is copied from configure.py, so Windows, Solaris and AIX are treated as 'unsupported' platforms. All other platforms are assumed to be supported. As discussed in #1853, when built via CMake the `ninja` executable looks for a binary called `python` in the current path, in order to launch the "browse" mode. The behaviour differs from that of the configure.py script, which looks for a python executable that has the *same name* as the python executable that invoked the configure script. --- CMakeLists.txt | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 65e42a4..d132965 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,18 @@ else() endif() target_include_directories(libninja-re2c PRIVATE src) +# --- Check for 'browse' mode support +set(unsupported_browse_platforms + "Windows" + "SunOS" + "AIX" +) +if(${CMAKE_SYSTEM_NAME} IN_LIST unsupported_browse_platforms) + set(platform_supports_ninja_browse FALSE) +else() + set(platform_supports_ninja_browse TRUE) +endif() + # Core source files all build into ninja library. add_library(libninja OBJECT src/build_log.cc @@ -96,6 +108,32 @@ endif() add_executable(ninja src/ninja.cc) target_link_libraries(ninja PRIVATE libninja libninja-re2c) +# Adds browse mode into the ninja binary if it's supported by the host platform. +if(platform_supports_ninja_browse) + # Inlines src/browse.py into the browse_py.h header, so that it can be included + # by src/browse.cc + add_custom_command( + OUTPUT build/browse_py.h + MAIN_DEPENDENCY src/browse.py + DEPENDS src/inline.sh + COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/build + COMMAND src/inline.sh kBrowsePy + < src/browse.py + > ${CMAKE_BINARY_DIR}/build/browse_py.h + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + VERBATIM + ) + + target_compile_definitions(ninja PRIVATE NINJA_HAVE_BROWSE) + target_sources(ninja PRIVATE src/browse.cc) + set_source_files_properties(src/browse.cc + PROPERTIES + OBJECT_DEPENDS "${CMAKE_BINARY_DIR}/build/browse_py.h" + INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}" + COMPILE_DEFINITIONS NINJA_PYTHON="python" + ) +endif() + # Tests all build into ninja_test executable. add_executable(ninja_test src/build_log_test.cc -- cgit v0.12 From 67f960be1be8099ea1727af8d3361d38274b2bd1 Mon Sep 17 00:00:00 2001 From: Alastair Harrison Date: Fri, 28 Aug 2020 11:53:58 +0100 Subject: Improve error handling in inline.sh Previously the script would generate some output and return a zero error code, even if the calls to `od` or `sed` failed. This change ensures that: - If `od` or `sed` fail then the script will fail. - Output will only be written on success. --- src/inline.sh | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/inline.sh b/src/inline.sh index b64e8ca..5092fa2 100755 --- a/src/inline.sh +++ b/src/inline.sh @@ -19,7 +19,14 @@ # stdin and writes stdout. varname="$1" -echo "const char $varname[] =" -od -t x1 -A n -v | sed -e 's|^[\t ]\{0,\}$||g; s|[\t ]\{1,\}| |g; s| \{1,\}$||g; s| |\\x|g; s|^|"|; s|$|"|' -echo ";" +# 'od' and 'sed' may not be available on all platforms, and may not support the +# flags used here. We must ensure that the script exits with a non-zero exit +# code in those cases. +byte_vals=$(od -t x1 -A n -v) || exit 1 +escaped_byte_vals=$(echo "${byte_vals}" \ + | sed -e 's|^[\t ]\{0,\}$||g; s|[\t ]\{1,\}| |g; s| \{1,\}$||g; s| |\\x|g; s|^|"|; s|$|"|') \ + || exit 1 + +# Only write output once we have successfully generated the required data +printf "const char %s[] = \n%s;" "${varname}" "${escaped_byte_vals}" -- cgit v0.12 From 0b5f5ba91020668856f87f079a61380198540bd7 Mon Sep 17 00:00:00 2001 From: Alastair Harrison Date: Fri, 28 Aug 2020 11:58:43 +0100 Subject: CMake: Add platform checks for browse mode support Browse mode requires a number of POSIX features to be available. This commit adds configure-time checks that the 'unistd.h' header is available and that the `inline.sh` script executes successfully. If the checks pass then browse mode is enabled. --- CMakeLists.txt | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d132965..b0c0911 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.15) + +include(CheckIncludeFileCXX) + project(ninja) # --- optional link-time optimization @@ -49,16 +52,28 @@ endif() target_include_directories(libninja-re2c PRIVATE src) # --- Check for 'browse' mode support -set(unsupported_browse_platforms - "Windows" - "SunOS" - "AIX" -) -if(${CMAKE_SYSTEM_NAME} IN_LIST unsupported_browse_platforms) - set(platform_supports_ninja_browse FALSE) -else() - set(platform_supports_ninja_browse TRUE) -endif() +function(check_platform_supports_browse_mode RESULT) + # Make sure the inline.sh script works on this platform. + # It uses the shell commands such as 'od', which may not be available. + execute_process( + COMMAND sh -c "echo 'TEST' | src/inline.sh var" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE inline_result + OUTPUT_QUIET + ERROR_QUIET + ) + if(NOT inline_result EQUAL "0") + # The inline script failed, so browse mode is not supported. + set(${RESULT} "0" PARENT_SCOPE) + return() + endif() + + # Now check availability of the unistd header + check_include_file_cxx(unistd.h PLATFORM_HAS_UNISTD_HEADER) + set(${RESULT} "${PLATFORM_HAS_UNISTD_HEADER}" PARENT_SCOPE) +endfunction() + +check_platform_supports_browse_mode(platform_supports_ninja_browse) # Core source files all build into ninja library. add_library(libninja OBJECT -- cgit v0.12 From 54959b0f2c4950d97d94c03810b3b5185be0d69e Mon Sep 17 00:00:00 2001 From: David Callu Date: Mon, 14 Sep 2020 12:39:13 +0200 Subject: cmake: add BUILD_TESTING option (ON by default) (#1839) option provided by cmake's Module CTest enable_testing() is call by this Module --- CMakeLists.txt | 80 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b0c0911..8e6bdd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,45 +149,47 @@ if(platform_supports_ninja_browse) ) endif() -# Tests all build into ninja_test executable. -add_executable(ninja_test - src/build_log_test.cc - src/build_test.cc - src/clean_test.cc - src/clparser_test.cc - src/depfile_parser_test.cc - src/deps_log_test.cc - src/disk_interface_test.cc - src/dyndep_parser_test.cc - src/edit_distance_test.cc - src/graph_test.cc - src/lexer_test.cc - src/manifest_parser_test.cc - src/ninja_test.cc - src/state_test.cc - src/string_piece_util_test.cc - src/subprocess_test.cc - src/test.cc - src/util_test.cc -) -if(WIN32) - target_sources(ninja_test PRIVATE src/includes_normalize_test.cc src/msvc_helper_test.cc) +include(CTest) +if(BUILD_TESTING) + # Tests all build into ninja_test executable. + add_executable(ninja_test + src/build_log_test.cc + src/build_test.cc + src/clean_test.cc + src/clparser_test.cc + src/depfile_parser_test.cc + src/deps_log_test.cc + src/disk_interface_test.cc + src/dyndep_parser_test.cc + src/edit_distance_test.cc + src/graph_test.cc + src/lexer_test.cc + src/manifest_parser_test.cc + src/ninja_test.cc + src/state_test.cc + src/string_piece_util_test.cc + src/subprocess_test.cc + src/test.cc + src/util_test.cc + ) + if(WIN32) + target_sources(ninja_test PRIVATE src/includes_normalize_test.cc src/msvc_helper_test.cc) + endif() + target_link_libraries(ninja_test PRIVATE libninja libninja-re2c) + + foreach(perftest + build_log_perftest + canon_perftest + clparser_perftest + depfile_parser_perftest + hash_collision_bench + manifest_parser_perftest + ) + add_executable(${perftest} src/${perftest}.cc) + target_link_libraries(${perftest} PRIVATE libninja libninja-re2c) + endforeach() + + add_test(NinjaTest ninja_test) endif() -target_link_libraries(ninja_test PRIVATE libninja libninja-re2c) - -foreach(perftest - build_log_perftest - canon_perftest - clparser_perftest - depfile_parser_perftest - hash_collision_bench - manifest_parser_perftest -) - add_executable(${perftest} src/${perftest}.cc) - target_link_libraries(${perftest} PRIVATE libninja libninja-re2c) -endforeach() - -enable_testing() -add_test(NinjaTest ninja_test) install(TARGETS ninja DESTINATION bin) -- cgit v0.12