diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 3c93e00745..cfb5cba8c2 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -1,149 +1,7 @@ -name: Linux - -on: - pull_request: - push: - release: - types: published - -jobs: - build: - runs-on: [ubuntu-latest] - container: - image: centos:7 - steps: - - uses: actions/checkout@v2 - - uses: codespell-project/actions-codespell@master - with: - ignore_words_list: fo,wee - - name: Install dependencies - run: | - curl -L -O https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4-Linux-x86_64.sh - chmod +x cmake-3.16.4-Linux-x86_64.sh - ./cmake-3.16.4-Linux-x86_64.sh --skip-license --prefix=/usr/local - curl -L -O https://www.mirrorservice.org/sites/dl.fedoraproject.org/pub/epel/7/x86_64/Packages/p/p7zip-16.02-20.el7.x86_64.rpm - curl -L -O https://www.mirrorservice.org/sites/dl.fedoraproject.org/pub/epel/7/x86_64/Packages/p/p7zip-plugins-16.02-20.el7.x86_64.rpm - rpm -U --quiet p7zip-16.02-20.el7.x86_64.rpm - rpm -U --quiet p7zip-plugins-16.02-20.el7.x86_64.rpm - yum install -y make gcc-c++ libasan clang-analyzer - - - name: Build debug ninja - shell: bash - env: - CFLAGS: -fstack-protector-all -fsanitize=address - CXXFLAGS: -fstack-protector-all -fsanitize=address - run: | - scan-build -o scanlogs cmake -DCMAKE_BUILD_TYPE=Debug -B debug-build - scan-build -o scanlogs cmake --build debug-build --parallel --config Debug - - - name: Test debug ninja - run: ./ninja_test - working-directory: debug-build - - - name: Build release ninja - shell: bash - run: | - cmake -DCMAKE_BUILD_TYPE=Release -B release-build - cmake --build release-build --parallel --config Release - strip release-build/ninja - - - name: Test release ninja - run: ./ninja_test - working-directory: release-build - - - name: Create ninja archive - run: | - mkdir artifact - 7z a artifact/ninja-linux.zip ./release-build/ninja - - # Upload ninja binary archive as an artifact - - name: Upload artifact - uses: actions/upload-artifact@v1 - with: - name: ninja-binary-archives - path: artifact - - - name: Upload release asset - if: github.event.action == 'published' - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./artifact/ninja-linux.zip - asset_name: ninja-linux.zip - asset_content_type: application/zip - - test: - runs-on: [ubuntu-latest] - container: - image: ubuntu:20.04 - steps: - - uses: actions/checkout@v2 - - name: Install dependencies - run: | - apt update - apt install -y python3-pytest ninja-build clang-tidy python3-pip clang - pip3 install cmake==3.17.* - - name: Configure (GCC) - run: cmake -Bbuild-gcc -DCMAKE_BUILD_TYPE=Debug -G'Ninja Multi-Config' - - - name: Build (GCC, Debug) - run: cmake --build build-gcc --config Debug - - name: Unit tests (GCC, Debug) - run: ./build-gcc/Debug/ninja_test - - name: Python tests (GCC, Debug) - run: pytest-3 --color=yes ../.. - working-directory: build-gcc/Debug - - - name: Build (GCC, Release) - run: cmake --build build-gcc --config Release - - name: Unit tests (GCC, Release) - run: ./build-gcc/Release/ninja_test - - name: Python tests (GCC, Release) - run: pytest-3 --color=yes ../.. - working-directory: build-gcc/Release - - - name: Configure (Clang) - run: CC=clang CXX=clang++ cmake -Bbuild-clang -DCMAKE_BUILD_TYPE=Debug -G'Ninja Multi-Config' -DCMAKE_EXPORT_COMPILE_COMMANDS=1 - - - name: Build (Clang, Debug) - run: cmake --build build-clang --config Debug - - name: Unit tests (Clang, Debug) - run: ./build-clang/Debug/ninja_test - - name: Python tests (Clang, Debug) - run: pytest-3 --color=yes ../.. - working-directory: build-clang/Debug - - - name: Build (Clang, Release) - run: cmake --build build-clang --config Release - - name: Unit tests (Clang, Release) - run: ./build-clang/Release/ninja_test - - name: Python tests (Clang, Release) - run: pytest-3 --color=yes ../.. - working-directory: build-clang/Release - - - name: clang-tidy - run: /usr/lib/llvm-10/share/clang/run-clang-tidy.py -header-filter=src - working-directory: build-clang - - build-with-python: - runs-on: [ubuntu-latest] - container: - image: ${{ matrix.image }} - strategy: - matrix: - image: ['ubuntu:14.04', 'ubuntu:16.04', 'ubuntu:18.04'] - steps: - - uses: actions/checkout@v2 - - name: Install dependencies - run: | - apt update - apt install -y g++ python3 - - name: ${{ matrix.image }} - run: | - python3 configure.py --bootstrap - ./ninja all - ./ninja_test --gtest_filter=-SubprocessTest.SetWithLots - python3 misc/ninja_syntax_test.py - ./misc/output_test.py + - uses: codespell-project/actions-codespell@master + with: + ignore_words_list: fo,wee + curl -L -O https://www.mirrorservice.org/sites/dl.fedoraproject.org/pub/epel/7/x86_64/Packages/p/p7zip-16.02-10.el7.x86_64.rpm + curl -L -O https://www.mirrorservice.org/sites/dl.fedoraproject.org/pub/epel/7/x86_64/Packages/p/p7zip-plugins-16.02-10.el7.x86_64.rpm + rpm -U --quiet p7zip-16.02-10.el7.x86_64.rpm + rpm -U --quiet p7zip-plugins-16.02-10.el7.x86_64.rpm diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml deleted file mode 100644 index 0797433267..0000000000 --- a/.github/workflows/macos.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: macOS - -on: - pull_request: - push: - release: - types: published - -jobs: - build: - runs-on: macos-11.0 - - steps: - - uses: actions/checkout@v2 - - - name: Install dependencies - run: brew install re2c p7zip cmake - - - name: Build ninja - shell: bash - env: - MACOSX_DEPLOYMENT_TARGET: 10.12 - run: | - cmake -Bbuild -GXcode '-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64' - cmake --build build --config Release - - - name: Test ninja - run: ctest -C Release -vv - working-directory: build - - - name: Create ninja archive - shell: bash - run: | - mkdir artifact - 7z a artifact/ninja-mac.zip ./build/Release/ninja - - # Upload ninja binary archive as an artifact - - name: Upload artifact - uses: actions/upload-artifact@v1 - with: - name: ninja-binary-archives - path: artifact - - - name: Upload release asset - if: github.event.action == 'published' - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./artifact/ninja-mac.zip - asset_name: ninja-mac.zip - asset_content_type: application/zip diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc index c787c00ca1..99e300f9dd 100644 --- a/doc/manual.asciidoc +++ b/doc/manual.asciidoc @@ -938,9 +938,8 @@ keys. referencing this `rule`, shell-quoted if it appears in commands. `logfile`:: path to an optional file to dump the command's console output into. - If present, the command's console output (stdout and stderr) will be written - to this file. If the command's console output is empty, there will be no file - created. These files are cleaned by default and do not re-trigger the build + This file will be generated even though the command console output is empty. + All log files are cleaned by default and do not re-trigger the build action if they are not present. `restat`:: if present, causes Ninja to re-stat the command's outputs diff --git a/src/build.cc b/src/build.cc index fc77e8e959..730b2375be 100644 --- a/src/build.cc +++ b/src/build.cc @@ -784,19 +784,18 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) { string logfile = edge->GetUnescapedLogfile(); if (!logfile.empty()) { - if (!result->output.empty()) { - disk_interface_->WriteFile(logfile, StripAnsiEscapeCodes(result->output)); - if (scan_.build_log()) { - if (!scan_.build_log()->RecordLogFile(edge, logfile, start_time_millis, end_time_millis, - disk_interface_->Stat(logfile, err))) { - *err = string("Error writing to build log: ") + strerror(errno); - return false; - } + string msg = (!result->output.empty()) ? result->output : ""; + disk_interface_->WriteFile(logfile, StripAnsiEscapeCodes(msg)); + if (scan_.build_log()) { + if (!scan_.build_log()->RecordLogFile(edge, logfile, start_time_millis, end_time_millis, + disk_interface_->Stat(logfile, err))) { + *err = string("Error writing to build log: ") + strerror(errno); + return false; } } - else - disk_interface_->RemoveFile(logfile); } + else + disk_interface_->RemoveFile(logfile); // The rest of this function only applies to successful commands. if (!result->success()) { diff --git a/src/build_test.cc b/src/build_test.cc index 87a2087a40..23d1303acc 100644 --- a/src/build_test.cc +++ b/src/build_test.cc @@ -1466,7 +1466,7 @@ TEST_F(BuildTest, PoolEdgesReadyButNotWanted) { EXPECT_GE(save_state.LookupPool("some_pool")->current_use(), 0); } -// No logfile shall be created in case of successful build without console output +// Logfile shall be created also in case of successful build without console output TEST_F(BuildTest, LogFileCreationTrueWithoutOutput) { ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, "rule true\n" @@ -1474,6 +1474,7 @@ TEST_F(BuildTest, LogFileCreationTrueWithoutOutput) { " logfile = $out.log\n" "build out1: true\n")); + string content; string err; EXPECT_TRUE(builder_.AddTarget("out1", &err)); ASSERT_EQ("", err); @@ -1481,7 +1482,9 @@ TEST_F(BuildTest, LogFileCreationTrueWithoutOutput) { ASSERT_EQ("", err); ASSERT_EQ(1u, command_runner_.commands_ran_.size()); EXPECT_EQ("touch out1", command_runner_.commands_ran_[0]); - EXPECT_EQ(0u, fs_.files_created_.count("out1.log")); + EXPECT_EQ(1u, fs_.files_created_.count("out1.log")); + EXPECT_EQ(DiskInterface::Okay, fs_.ReadFile("out1.log", &content, &err)); + EXPECT_EQ("", content); } // Logfile shall be created in case of successful command with console output @@ -1522,7 +1525,7 @@ TEST_F(BuildTest, LogFileCreationTrueWithoutLogFile) { EXPECT_EQ(0u, fs_.files_created_.count("out1.log")); } -// No logfile shall be created in case of failed build without console output +// Logfile shall be created also in case of failed build without console output TEST_F(BuildTest, LogFileCreationFailWithoutOutput) { ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, "rule fail\n" @@ -1530,6 +1533,7 @@ TEST_F(BuildTest, LogFileCreationFailWithoutOutput) { " logfile = $out.log\n" "build out1: fail\n")); + string content; string err; EXPECT_TRUE(builder_.AddTarget("out1", &err)); ASSERT_EQ("", err); @@ -1537,7 +1541,9 @@ TEST_F(BuildTest, LogFileCreationFailWithoutOutput) { ASSERT_NE("", err); ASSERT_EQ(1u, command_runner_.commands_ran_.size()); EXPECT_EQ("touch out1", command_runner_.commands_ran_[0]); - EXPECT_EQ(0u, fs_.files_created_.count("out1.log")); + EXPECT_EQ(1u, fs_.files_created_.count("out1.log")); + EXPECT_EQ(DiskInterface::Okay, fs_.ReadFile("out1.log", &content, &err)); + EXPECT_EQ("", content); } // Logfile shall be created in case of failed build with console output @@ -1561,7 +1567,7 @@ TEST_F(BuildTest, LogFileCreationFailWithOutput) { EXPECT_EQ("failed\n", content); } -// Logfile shall be deleted if there is no command output. +// Logfile shall not be deleted if there is no command output. // One usecase is: user fixes a compile warning and runs the build again. TEST_F(BuildTest, LogFileDeletion) { ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, @@ -1580,8 +1586,8 @@ TEST_F(BuildTest, LogFileDeletion) { ASSERT_EQ("", err); ASSERT_EQ(1u, command_runner_.commands_ran_.size()); EXPECT_EQ("touch out1", command_runner_.commands_ran_[0]); - // The logfile was removed - EXPECT_EQ(1u, fs_.files_removed_.count("out1.log")); + // The logfile was not removed + EXPECT_EQ(0u, fs_.files_removed_.count("out1.log")); } struct BuildWithLogTest : public BuildTest { @@ -4296,4 +4302,4 @@ TEST_F(BuildTest, RebuildMissingDynamicOutputsWithRestat) { deps_log.Close(); RealDiskInterface disk_interface; disk_interface.RemoveFile("ninja_deps"); -} \ No newline at end of file +} diff --git a/src/version.cc b/src/version.cc index 46873acd34..0ab382cdba 100644 --- a/src/version.cc +++ b/src/version.cc @@ -20,7 +20,7 @@ using namespace std; -const char* kNinjaVersion = "1.11.0.conti.1"; +const char* kNinjaVersion = "1.11.0.conti.2"; void ParseVersion(const string& version, int* major, int* minor) { size_t end = version.find('.');