diff options
author | LaMont Jones <lamontjones@google.com> | 2023-06-07 16:37:01 +0000 |
---|---|---|
committer | LaMont Jones <lamontjones@google.com> | 2023-06-16 16:42:56 +0000 |
commit | 48d40d7519e8d55e658183f8bc39d12c50cc2723 (patch) | |
tree | be7c0a41a0d141ec3e3a27856b17bcbe0d5c056d | |
parent | 006782243b2c2dda84fe63837e30fbf66994fe2e (diff) | |
download | kati-48d40d7519e8d55e658183f8bc39d12c50cc2723.tar.gz |
Add KATI_file_no_rerun function
The syntax is the same as $(file), but it will only be run once.
Similar to $(KATI_shell_no_rerun), we want to generate files during
kati, but not regenerate them on every invocation of kati.
Test: unit tests pass
Change-Id: I34b7972a0a9f0540da322a995c30fef2efd16145
-rw-r--r-- | src/func.cc | 29 | ||||
-rwxr-xr-x | testcase/ninja_file_no_rerun_func.sh | 60 |
2 files changed, 80 insertions, 9 deletions
diff --git a/src/func.cc b/src/func.cc index d5bca3a..912cee1 100644 --- a/src/func.cc +++ b/src/func.cc @@ -793,9 +793,10 @@ void ErrorFunc(const std::vector<Value*>& args, Evaluator* ev, std::string*) { ev->Error(StringPrintf("*** %s.", a.c_str())); } -static void FileReadFunc(Evaluator* ev, +static void FileReadFunc_(Evaluator* ev, const std::string& filename, - std::string* s) { + std::string* s, + bool rerun) { int fd = open(filename.c_str(), O_RDONLY); if (fd < 0) { if (errno == ENOENT) { @@ -833,7 +834,7 @@ static void FileReadFunc(Evaluator* ev, out.pop_back(); } - if (ShouldStoreCommandResult(filename)) { + if (rerun && ShouldStoreCommandResult(filename)) { CommandResult* cr = new CommandResult(); cr->op = CommandOp::READ; cr->cmd = filename; @@ -843,10 +844,11 @@ static void FileReadFunc(Evaluator* ev, *s += out; } -static void FileWriteFunc(Evaluator* ev, +static void FileWriteFunc_(Evaluator* ev, const std::string& filename, bool append, - std::string text) { + std::string text, + bool rerun) { FILE* f = fopen(filename.c_str(), append ? "ab" : "wb"); if (f == NULL) { ev->Error("*** fopen failed."); @@ -860,7 +862,7 @@ static void FileWriteFunc(Evaluator* ev, ev->Error("*** fclose failed."); } - if (ShouldStoreCommandResult(filename)) { + if (rerun && ShouldStoreCommandResult(filename)) { CommandResult* cr = new CommandResult(); cr->op = CommandOp::WRITE; cr->cmd = filename; @@ -870,7 +872,7 @@ static void FileWriteFunc(Evaluator* ev, } } -void FileFunc(const std::vector<Value*>& args, Evaluator* ev, std::string* s) { +void FileFunc_(const std::vector<Value*>& args, Evaluator* ev, std::string* s, bool rerun) { if (ev->avoid_io()) { ev->Error("*** $(file ...) is not supported in rules."); } @@ -891,7 +893,7 @@ void FileFunc(const std::vector<Value*>& args, Evaluator* ev, std::string* s) { ev->Error("*** invalid argument"); } - FileReadFunc(ev, std::string(filename), s); + FileReadFunc_(ev, std::string(filename), s, rerun); } else if (filename[0] == '>') { bool append = false; if (filename[1] == '>') { @@ -913,13 +915,21 @@ void FileFunc(const std::vector<Value*>& args, Evaluator* ev, std::string* s) { } } - FileWriteFunc(ev, std::string(filename), append, text); + FileWriteFunc_(ev, std::string(filename), append, text, rerun); } else { ev->Error(StringPrintf("*** Invalid file operation: %s. Stop.", std::string(filename).c_str())); } } +void FileFunc(const std::vector<Value*>& args, Evaluator* ev, std::string* s) { + FileFunc_(args, ev, s, true); +} + +void FileFuncNoRerun(const std::vector<Value*>& args, Evaluator* ev, std::string* s) { + FileFunc_(args, ev, s, false); +} + void DeprecatedVarFunc(const std::vector<Value*>& args, Evaluator* ev, std::string*) { @@ -1131,6 +1141,7 @@ static const std::unordered_map<std::string_view, FuncInfo> g_func_info_map = { ENTRY("KATI_extra_file_deps", &ExtraFileDepsFunc, 0, 0, false, false), ENTRY("KATI_shell_no_rerun", &ShellFuncNoRerun, 1, 1, false, false), ENTRY("KATI_foreach_sep", &ForeachWithSepFunc, 4, 4, false, false), + ENTRY("KATI_file_no_rerun", &FileFuncNoRerun, 2, 1, false, false), }; } // namespace diff --git a/testcase/ninja_file_no_rerun_func.sh b/testcase/ninja_file_no_rerun_func.sh new file mode 100755 index 0000000..120432a --- /dev/null +++ b/testcase/ninja_file_no_rerun_func.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# +# Copyright 2023 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. + +set -e + +log=stderr_log +mk="$@" + +echo "PASS" >testfile + +cat <<EOF > Makefile +ifdef KATI +SUPPORTS_FILE := 1 +endif +ifneq (,\$(filter 4.2%,\$(MAKE_VERSION))) +SUPPORTS_FILE := 1 +endif + +ifdef KATI + \$(KATI_file_no_rerun >testwrite,PASS) + RESULT := \$(KATI_file_no_rerun <testwrite) +else +ifdef SUPPORTS_FILE + \$(file >testwrite,PASS) + RESULT := \$(file <testwrite) +else + # Make <4 does not support \$(file ...) + \$(info Read back: PASS) + RESULT := PASS +endif +endif + +all: ;@echo \$(RESULT) +EOF + +${mk} 2> ${log} +if [ -e ninja.sh ]; then + ./ninja.sh +fi + +${mk} 2> ${log} +if [ -e ninja.sh ]; then + if grep -q regenerating ${log}; then + echo 'Should not be regenerated' + fi + ./ninja.sh +fi |