aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrice Arruda <48073103+patricearruda@users.noreply.github.com>2020-06-25 14:12:17 -0400
committerGitHub <noreply@github.com>2020-06-25 14:12:17 -0400
commit003cf51e9b6da48063c90cf4c6710fde103c9c4a (patch)
tree01f4e8ee74775e749b2126109db4e27130daf40e
parent7a68538a09e1e0c56f936ccf20632314e74c10c0 (diff)
parentc81028400c8efb27df6a989abd2235b909cfb7c3 (diff)
downloadplatform_build_kati-003cf51e9b6da48063c90cf4c6710fde103c9c4a.tar.gz
platform_build_kati-003cf51e9b6da48063c90cf4c6710fde103c9c4a.tar.bz2
platform_build_kati-003cf51e9b6da48063c90cf4c6710fde103c9c4a.zip
Merge pull request #198 from colincross/ninja_validations
Support validations in ninja
-rw-r--r--dep.cc47
-rw-r--r--dep.h2
-rw-r--r--flags.cc2
-rw-r--r--flags.h1
-rw-r--r--ninja.cc10
-rw-r--r--rule.h1
-rwxr-xr-xruntest.rb142
-rw-r--r--testcase/ninja_validations.sh51
8 files changed, 177 insertions, 79 deletions
diff --git a/dep.cc b/dep.cc
index a4eb2d2..3289d7a 100644
--- a/dep.cc
+++ b/dep.cc
@@ -142,6 +142,7 @@ bool IsSuffixRule(Symbol output) {
struct RuleMerger {
vector<const Rule*> rules;
vector<pair<Symbol, RuleMerger*>> implicit_outputs;
+ vector<Symbol> validations;
const Rule* primary_rule;
const RuleMerger* parent;
Symbol parent_sym;
@@ -154,6 +155,8 @@ struct RuleMerger {
implicit_outputs.push_back(make_pair(output, merger));
}
+ void AddValidation(Symbol validation) { validations.push_back(validation); }
+
void SetImplicitOutput(Symbol output, Symbol p, const RuleMerger* merger) {
if (!merger->primary_rule) {
ERROR("*** implicit output `%s' on phony target `%s'", output.c_str(),
@@ -252,6 +255,10 @@ struct RuleMerger {
FillDepNodeFromRule(output, r, n);
}
}
+
+ for (auto& validation : validations) {
+ n->actual_validations.push_back(validation);
+ }
}
};
@@ -279,7 +286,8 @@ class DepBuilder {
implicit_rules_(new RuleTrie()),
depfile_var_name_(Intern(".KATI_DEPFILE")),
implicit_outputs_var_name_(Intern(".KATI_IMPLICIT_OUTPUTS")),
- ninja_pool_var_name_(Intern(".KATI_NINJA_POOL")) {
+ ninja_pool_var_name_(Intern(".KATI_NINJA_POOL")),
+ validations_var_name_(Intern(".KATI_VALIDATIONS")) {
ScopedTimeReporter tr("make dep (populate)");
PopulateRules(rules);
// TODO?
@@ -412,17 +420,26 @@ class DepBuilder {
continue;
}
auto var = vars->Lookup(implicit_outputs_var_name_);
- if (!var->IsDefined()) {
- continue;
+ if (var->IsDefined()) {
+ string implicit_outputs;
+ var->Eval(ev_, &implicit_outputs);
+
+ for (StringPiece output : WordScanner(implicit_outputs)) {
+ Symbol sym = Intern(TrimLeadingCurdir(output));
+ rules_[sym].SetImplicitOutput(sym, p.first, &p.second);
+ p.second.AddImplicitOutput(sym, &rules_[sym]);
+ }
}
- string implicit_outputs;
- var->Eval(ev_, &implicit_outputs);
+ var = vars->Lookup(validations_var_name_);
+ if (var->IsDefined()) {
+ string validations;
+ var->Eval(ev_, &validations);
- for (StringPiece output : WordScanner(implicit_outputs)) {
- Symbol sym = Intern(TrimLeadingCurdir(output));
- rules_[sym].SetImplicitOutput(sym, p.first, &p.second);
- p.second.AddImplicitOutput(sym, &rules_[sym]);
+ for (StringPiece validation : WordScanner(validations)) {
+ Symbol sym = Intern(TrimLeadingCurdir(validation));
+ p.second.AddValidation(sym);
+ }
}
}
}
@@ -684,6 +701,7 @@ class DepBuilder {
if (name == depfile_var_name_) {
n->depfile_var = new_var;
} else if (name == implicit_outputs_var_name_) {
+ } else if (name == validations_var_name_) {
} else if (name == ninja_pool_var_name_) {
n->ninja_pool_var = new_var;
} else {
@@ -790,6 +808,16 @@ class DepBuilder {
n->order_onlys.push_back({input, c});
}
+ for (Symbol validation : n->actual_validations) {
+ if (!g_flags.use_ninja_validations) {
+ ERROR_LOC(
+ n->loc,
+ ".KATI_VALIDATIONS not allowed without --use_ninja_validations");
+ }
+ DepNode* c = BuildPlan(validation, output);
+ n->validations.push_back({validation, 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 &&
@@ -867,6 +895,7 @@ class DepBuilder {
Symbol depfile_var_name_;
Symbol implicit_outputs_var_name_;
Symbol ninja_pool_var_name_;
+ Symbol validations_var_name_;
};
void MakeDep(Evaluator* ev,
diff --git a/dep.h b/dep.h
index 963447b..3ab52ac 100644
--- a/dep.h
+++ b/dep.h
@@ -39,6 +39,7 @@ struct DepNode {
vector<Value*> cmds;
vector<NamedDepNode> deps;
vector<NamedDepNode> order_onlys;
+ vector<NamedDepNode> validations;
bool has_rule;
bool is_default_target;
bool is_phony;
@@ -46,6 +47,7 @@ struct DepNode {
vector<Symbol> implicit_outputs;
vector<Symbol> actual_inputs;
vector<Symbol> actual_order_only_inputs;
+ vector<Symbol> actual_validations;
Vars* rule_vars;
Var* depfile_var;
Var* ninja_pool_var;
diff --git a/flags.cc b/flags.cc
index bcc1b4f..329e0fd 100644
--- a/flags.cc
+++ b/flags.cc
@@ -108,6 +108,8 @@ void Flags::Parse(int argc, char** argv) {
no_ninja_prelude = true;
} else if (!strcmp(arg, "--use_ninja_phony_output")) {
use_ninja_phony_output = true;
+ } else if (!strcmp(arg, "--use_ninja_validations")) {
+ use_ninja_validations = true;
} else if (!strcmp(arg, "--werror_find_emulator")) {
werror_find_emulator = true;
} else if (!strcmp(arg, "--werror_overriding_commands")) {
diff --git a/flags.h b/flags.h
index 279e7fe..066fb38 100644
--- a/flags.h
+++ b/flags.h
@@ -44,6 +44,7 @@ struct Flags {
bool no_builtin_rules;
bool no_ninja_prelude;
bool use_ninja_phony_output;
+ bool use_ninja_validations;
bool werror_find_emulator;
bool werror_overriding_commands;
bool warn_implicit_rules;
diff --git a/ninja.cc b/ninja.cc
index f53b15b..9b6989b 100644
--- a/ninja.cc
+++ b/ninja.cc
@@ -255,6 +255,9 @@ class NinjaGenerator {
for (auto const& d : node->order_onlys) {
PopulateNinjaNode(d.second);
}
+ for (auto const& d : node->validations) {
+ PopulateNinjaNode(d.second);
+ }
}
StringPiece TranslateCommand(const char* in, string* cmd_buf) {
@@ -569,6 +572,13 @@ class NinjaGenerator {
*o << " " << EscapeBuildTarget(d.first).c_str();
}
}
+ if (!node->validations.empty()) {
+ *o << " |@";
+ for (auto const& d : node->validations) {
+ *o << " " << EscapeBuildTarget(d.first).c_str();
+ }
+ }
+
*o << "\n";
string pool;
diff --git a/rule.h b/rule.h
index b8dc4a1..237eb02 100644
--- a/rule.h
+++ b/rule.h
@@ -51,6 +51,7 @@ class Rule {
vector<Symbol> inputs;
vector<Symbol> order_only_inputs;
vector<Symbol> output_patterns;
+ vector<Symbol> validations;
bool is_double_colon;
bool is_suffix_rule;
vector<Value*> cmds;
diff --git a/runtest.rb b/runtest.rb
index a3c4197..173c66d 100755
--- a/runtest.rb
+++ b/runtest.rb
@@ -26,21 +26,21 @@ while true
test_serialization = true
ARGV.shift
elsif ARGV[0] == '-c'
- ckati = true
+ $ckati = true
ARGV.shift
ENV['KATI_VARIANT'] = 'c'
elsif ARGV[0] == '-n'
- via_ninja = true
+ $via_ninja = true
ARGV.shift
ENV['NINJA_STATUS'] = 'NINJACMD: '
elsif ARGV[0] == '-a'
gen_all_targets = true
ARGV.shift
elsif ARGV[0] == '-v'
- show_failing = true
+ $show_failing = true
ARGV.shift
elsif ARGV[0] == "-q"
- hide_passing = true
+ $hide_passing = true
ARGV.shift
else
break
@@ -76,10 +76,10 @@ def move_circular_dep(l)
circ + l
end
-expected_failures = []
-unexpected_passes = []
-failures = []
-passes = []
+$expected_failures = []
+$unexpected_passes = []
+$failures = []
+$passes = []
if !ARGV.empty?
test_files = ARGV.map do |test|
@@ -187,35 +187,67 @@ end
bash_var = ' SHELL=/bin/bash'
-run_make_test = proc do |mk|
- c = File.read(mk)
+def is_expected_failure(f)
+ c = File.read(f)
expected_failure = false
- if c =~ /\A# TODO(?:\(([-a-z|]+)\))?/
- if $1
- todos = $1.split('|')
- if todos.include?('go') && !ckati
+ if c =~ /\A(#!\/bin\/bash\n)?# TODO(?:\(([-a-z|]+)\))?/
+ if $2
+ todos = $2.split('|')
+ if todos.include?('go') && !$ckati
expected_failure = true
end
- if todos.include?('c') && ckati
+ if todos.include?('c') && $ckati
expected_failure = true
end
- if todos.include?('go-ninja') && !ckati && via_ninja
+ if todos.include?('go-ninja') && !$ckati && $via_ninja
expected_failure = true
end
- if todos.include?('c-ninja') && ckati && via_ninja
+ if todos.include?('c-ninja') && $ckati && $via_ninja
expected_failure = true
end
- if todos.include?('c-exec') && ckati && !via_ninja
+ if todos.include?('c-exec') && $ckati && !$via_ninja
expected_failure = true
end
- if todos.include?('ninja') && via_ninja
+ if todos.include?('ninja') && $via_ninja
expected_failure = true
end
else
expected_failure = true
end
end
+ return expected_failure
+end
+
+report_result = proc do |name, expected, output, expected_failure|
+ if expected != output
+ if expected_failure
+ if !$hide_passing
+ puts "#{name}: FAIL (expected)"
+ end
+ $expected_failures << name
+ else
+ puts "#{name}: FAIL"
+ $failures << name
+ end
+ if !expected_failure || $show_failing
+ puts `diff -u out.make out.kati`
+ end
+ else
+ if expected_failure
+ puts "#{name}: PASS (unexpected)"
+ $unexpected_passes << name
+ else
+ if !$hide_passing
+ puts "#{name}: PASS"
+ end
+ $passes << name
+ end
+ end
+end
+run_make_test = proc do |mk|
+ expected_failure = is_expected_failure(mk)
+ c = File.read(mk)
run_in_testdir(mk) do |name|
File.open("Makefile", 'w') do |ofile|
ofile.print(c)
@@ -235,13 +267,13 @@ run_make_test = proc do |mk|
cleanup
testcases.each do |tc|
cmd = 'make'
- if via_ninja || is_silent_test
+ if $via_ninja || is_silent_test
cmd += ' -s'
end
cmd += bash_var
cmd += " #{tc} 2>&1"
res = IO.popen(cmd, 'r:binary', &:read)
- res = normalize_make_log(res, mk, via_ninja)
+ res = normalize_make_log(res, mk, $via_ninja)
expected += "=== #{tc} ===\n" + res
expected_files = get_output_filenames
expected += "\n=== FILES ===\n#{expected_files * "\n"}\n"
@@ -251,14 +283,14 @@ run_make_test = proc do |mk|
testcases.each do |tc|
json = "#{tc.empty? ? 'test' : tc}"
cmd = "../../kati -save_json=#{json}.json -log_dir=. --use_find_emulator"
- if ckati
+ if $ckati
cmd = "../../ckati --use_find_emulator"
end
- if via_ninja
+ if $via_ninja
cmd += ' --ninja'
end
if gen_all_targets
- if !ckati || !via_ninja
+ if !$ckati || !$via_ninja
raise "-a should be used with -c -n"
end
cmd += ' --gen_all_targets'
@@ -272,7 +304,7 @@ run_make_test = proc do |mk|
end
cmd += " 2>&1"
res = IO.popen(cmd, 'r:binary', &:read)
- if via_ninja && File.exist?('build.ninja') && File.exists?('ninja.sh')
+ if $via_ninja && File.exist?('build.ninja') && File.exists?('ninja.sh')
cmd = './ninja.sh -j1 -v'
if gen_all_targets
cmd += " #{tc}"
@@ -295,30 +327,7 @@ run_make_test = proc do |mk|
exit 1
end
- if expected != output
- if expected_failure
- if !hide_passing
- puts "#{name}: FAIL (expected)"
- end
- expected_failures << name
- else
- puts "#{name}: FAIL"
- failures << name
- end
- if !expected_failure || show_failing
- puts `diff -u out.make out.kati`
- end
- else
- if expected_failure
- puts "#{name}: PASS (unexpected)"
- unexpected_passes << name
- else
- if !hide_passing
- puts "#{name}: PASS"
- end
- passes << name
- end
- end
+ report_result.call(name, expected, output, expected_failure)
if name !~ /^err_/ && test_serialization && !expected_failure
testcases.each do |tc|
@@ -343,10 +352,12 @@ end
run_shell_test = proc do |sh|
is_ninja_test = sh =~ /\/ninja_/
- if is_ninja_test && (!ckati || !via_ninja)
+ if is_ninja_test && (!$ckati || !$via_ninja)
next
end
+ expected_failure = is_expected_failure(sh)
+
run_in_testdir(sh) do |name|
cleanup
cmd = "bash ../../#{sh} make"
@@ -358,13 +369,13 @@ run_shell_test = proc do |sh|
cleanup
if is_ninja_test
- if ckati
+ if $ckati
cmd = "bash ../../#{sh} ../../ckati --ninja --regen"
else
next
end
else
- if ckati
+ if $ckati
cmd = "bash ../../#{sh} ../../ckati"
else
cmd = "bash ../../#{sh} ../../kati --use_cache -log_dir=."
@@ -382,16 +393,7 @@ run_shell_test = proc do |sh|
File.open('out.make', 'w'){|ofile|ofile.print(expected)}
File.open('out.kati', 'w'){|ofile|ofile.print(output)}
- if expected != output
- puts "#{name}: FAIL"
- puts `diff -u out.make out.kati`
- failures << name
- else
- if !hide_passing
- puts "#{name}: PASS"
- end
- passes << name
- end
+ report_result.call(name, expected, output, expected_failure)
end
end
@@ -407,31 +409,31 @@ end
puts
-if !expected_failures.empty? && !hide_passing
+if !$expected_failures.empty? && !$hide_passing
puts "=== Expected failures ==="
- expected_failures.each do |n|
+ $expected_failures.each do |n|
puts n
end
end
-if !unexpected_passes.empty?
+if !$unexpected_passes.empty?
puts "=== Unexpected passes ==="
- unexpected_passes.each do |n|
+ $unexpected_passes.each do |n|
puts n
end
end
-if !failures.empty?
+if !$failures.empty?
puts "=== Failures ==="
- failures.each do |n|
+ $failures.each do |n|
puts n
end
end
puts
-if !unexpected_passes.empty? || !failures.empty?
- puts "FAIL! (#{failures.size + unexpected_passes.size} fails #{passes.size} passes)"
+if !$unexpected_passes.empty? || !$failures.empty?
+ puts "FAIL! (#{$failures.size + $unexpected_passes.size} fails #{$passes.size} passes)"
exit 1
else
puts 'PASS!'
diff --git a/testcase/ninja_validations.sh b/testcase/ninja_validations.sh
new file mode 100644
index 0000000..cd77a01
--- /dev/null
+++ b/testcase/ninja_validations.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# TODO(ninja): enable once upstream ninja supports validations
+#
+# Copyright 2015 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
+
+mk="$@"
+
+cat <<EOF >Makefile
+all: a c
+
+a:
+ echo a
+
+b:
+ echo b
+
+a: .KATI_VALIDATIONS := b
+
+c:
+ echo c
+
+d: c
+ echo d
+
+c: .KATI_VALIDATIONS := d
+EOF
+
+all="a b c d"
+if echo "${mk}" | grep kati > /dev/null; then
+ mk="${mk} --use_ninja_validations"
+ all="a c"
+fi
+${mk} -j1 $all
+if [ -e ninja.sh ]; then
+ ./ninja.sh -j1 -w dupbuild=err $all
+fi
+