diff options
| author | Dan Willemsen <dwillemsen@google.com> | 2020-04-27 14:42:54 -0700 |
|---|---|---|
| committer | Dan Willemsen <dwillemsen@google.com> | 2020-04-27 15:17:41 -0700 |
| commit | 7f17b188d71e3776e7ceb75a93b25ecee8c481fc (patch) | |
| tree | 45e81e8abf08472b36f3fb407e5b1779c013e219 | |
| parent | 2e4f2865461f6b02cfe1f2825ec6423df489ad97 (diff) | |
| download | platform_build_kati-7f17b188d71e3776e7ceb75a93b25ecee8c481fc.tar.gz platform_build_kati-7f17b188d71e3776e7ceb75a93b25ecee8c481fc.tar.bz2 platform_build_kati-7f17b188d71e3776e7ceb75a93b25ecee8c481fc.zip | |
Add new check for non-phony targets that have no commands
There are two related, but separate checks here:
1. --warn_real_no_cmds_or_deps: That an action has no commands or
dependencies that could create the output file. In our ninja output,
these will act similarly to _kati_always_build_ and be considered always
dirty (unless something creates the file before ninja runs, but then
there shouldn't be an action created for it, and we should consider it a
source file).
Actually trying to build these now triggers a ninja error, so this Kati
check is here to catch the issue earlier with better diagnostics.
2. --warn_real_no_cmds: That a rule has no commands, but does have a
dependency that may create the output file. Usually this means that
instead of another action, the dependency should be using
.KATI_IMPLICIT_OUTPUTS to define that it created multiple files.
Under normal circumstances, this shouldn't cause many problems, but can
in some edge cases. I'm also looking to improve our build graph so that
it can function in sandbox-like environments (remote builds, etc). One
of the additions is to remove the output file before we run the commands
that should create it, but this is one of the cases where we don't know
when an output should be created.
Change-Id: Ie330ea49bf3617aa04fa17a3c5aa4dbb6b99b983
| -rw-r--r-- | dep.cc | 47 | ||||
| -rw-r--r-- | flags.cc | 10 | ||||
| -rw-r--r-- | flags.h | 4 | ||||
| -rw-r--r-- | testcase/real_no_cmds.sh | 53 | ||||
| -rw-r--r-- | testcase/real_no_cmds_or_deps.sh | 47 |
5 files changed, 161 insertions, 0 deletions
@@ -790,6 +790,53 @@ class DepBuilder { n->order_onlys.push_back({input, c}); } + // Block on werror_writable/werror_phony_looks_real, because otherwise we + // can't rely on is_phony being valid for this check. + if (!n->is_phony && n->cmds.empty() && g_flags.werror_writable && + g_flags.werror_phony_looks_real) { + if (n->deps.empty() && n->order_onlys.empty()) { + if (g_flags.werror_real_no_cmds_or_deps) { + ERROR_LOC( + n->loc, + "*** target \"%s\" has no commands or deps that could create it", + output.c_str()); + } else if (g_flags.warn_real_no_cmds_or_deps) { + WARN_LOC(n->loc, + "warning: target \"%s\" has no commands or deps that could " + "create it", + output.c_str()); + } + } else { + if (n->actual_inputs.size() == 1) { + if (g_flags.werror_real_no_cmds) { + ERROR_LOC(n->loc, + "*** target \"%s\" has no commands. Should \"%s\" be " + "using .KATI_IMPLICIT_OUTPUTS?", + output.c_str(), n->actual_inputs[0].c_str()); + } else if (g_flags.warn_real_no_cmds) { + WARN_LOC(n->loc, + "warning: target \"%s\" has no commands. Should \"%s\" be " + "using .KATI_IMPLICIT_OUTPUTS?", + output.c_str(), n->actual_inputs[0].c_str()); + } + } else { + if (g_flags.werror_real_no_cmds) { + ERROR_LOC( + n->loc, + "*** target \"%s\" has no commands that could create output " + "file. Is a dependency missing .KATI_IMPLICIT_OUTPUTS?", + output.c_str()); + } else if (g_flags.warn_real_no_cmds) { + WARN_LOC( + n->loc, + "warning: target \"%s\" has no commands that could create " + "output file. Is a dependency missing .KATI_IMPLICIT_OUTPUTS?", + output.c_str()); + } + } + } + } + n->has_rule = true; n->is_default_target = first_rule_ == output; if (cur_rule_vars_->empty()) { @@ -134,6 +134,16 @@ void Flags::Parse(int argc, char** argv) { werror_phony_looks_real = true; } else if (!strcmp(arg, "--werror_writable")) { werror_writable = true; + } else if (!strcmp(arg, "--warn_real_no_cmds_or_deps")) { + warn_real_no_cmds_or_deps = true; + } else if (!strcmp(arg, "--werror_real_no_cmds_or_deps")) { + warn_real_no_cmds_or_deps = true; + werror_real_no_cmds_or_deps = true; + } else if (!strcmp(arg, "--warn_real_no_cmds")) { + warn_real_no_cmds = true; + } else if (!strcmp(arg, "--werror_real_no_cmds")) { + warn_real_no_cmds = true; + werror_real_no_cmds = true; } else if (ParseCommandLineOptionWithArg("-j", argv, &i, &num_jobs_str)) { num_jobs = strtol(num_jobs_str, NULL, 10); if (num_jobs <= 0) { @@ -56,6 +56,10 @@ struct Flags { bool warn_phony_looks_real; bool werror_phony_looks_real; bool werror_writable; + bool warn_real_no_cmds_or_deps; + bool werror_real_no_cmds_or_deps; + bool warn_real_no_cmds; + bool werror_real_no_cmds; const char* default_pool; const char* goma_dir; const char* ignore_dirty_pattern; diff --git a/testcase/real_no_cmds.sh b/testcase/real_no_cmds.sh new file mode 100644 index 0000000..88066d7 --- /dev/null +++ b/testcase/real_no_cmds.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# +# Copyright 2020 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 -u + +mk="$@" + +cat <<EOF > Makefile +test: out/bad.baz out/good.baz + @echo "END" +.PHONY: test + +out/bad.bar: + @echo bar >out/bad.bar + @echo baz >out/bad.baz + +out/bad.baz: out/bad.bar + +out/good.bar: .KATI_IMPLICIT_OUTPUTS := out/good.baz +out/good.bar: + @echo bar >out/good.bar + @echo baz >out/good.baz +EOF + +mkdir -p out + +if echo "${mk}" | grep -qv "kati"; then + # Make doesn't support these warnings, so write the expected output. + echo 'Makefile:9: warning: target "out/bad.baz" has no commands. Should "out/bad.bar" be using .KATI_IMPLICIT_OUTPUTS?' + echo 'END' +else + ${mk} --werror_phony_looks_real --writable=out/ --werror_writable --warn_real_no_cmds 2>&1 +fi + +if echo "${mk}" | grep -qv "kati"; then + # Make doesn't support these warnings, so write the expected output. + echo 'Makefile:9: *** target "out/bad.baz" has no commands. Should "out/bad.bar" be using .KATI_IMPLICIT_OUTPUTS?' +else + ${mk} --werror_phony_looks_real --writable=out/ --werror_writable --werror_real_no_cmds 2>&1 +fi diff --git a/testcase/real_no_cmds_or_deps.sh b/testcase/real_no_cmds_or_deps.sh new file mode 100644 index 0000000..b591803 --- /dev/null +++ b/testcase/real_no_cmds_or_deps.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# Copyright 2020 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 -u + +mk="$@" + +cat <<EOF > Makefile +test: out/bad out/good + @echo "END" +.PHONY: test + +out/bad: + +out/good: + @echo bar >out/good +EOF + +mkdir -p out + +if echo "${mk}" | grep -qv "kati"; then + # Make doesn't support these warnings, so write the expected output. + echo 'Makefile:5: warning: target "out/bad" has no commands or deps that could create it' + echo 'END' +else + ${mk} --werror_phony_looks_real --writable=out/ --werror_writable --warn_real_no_cmds_or_deps 2>&1 +fi + +if echo "${mk}" | grep -qv "kati"; then + # Make doesn't support these warnings, so write the expected output. + echo 'Makefile:5: *** target "out/bad" has no commands or deps that could create it' +else + ${mk} --werror_phony_looks_real --writable=out/ --werror_writable --werror_real_no_cmds_or_deps 2>&1 +fi |
