diff options
| author | Patrice Arruda <48073103+patricearruda@users.noreply.github.com> | 2020-06-25 14:12:17 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-25 14:12:17 -0400 |
| commit | 003cf51e9b6da48063c90cf4c6710fde103c9c4a (patch) | |
| tree | 01f4e8ee74775e749b2126109db4e27130daf40e | |
| parent | 7a68538a09e1e0c56f936ccf20632314e74c10c0 (diff) | |
| parent | c81028400c8efb27df6a989abd2235b909cfb7c3 (diff) | |
| download | platform_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.cc | 47 | ||||
| -rw-r--r-- | dep.h | 2 | ||||
| -rw-r--r-- | flags.cc | 2 | ||||
| -rw-r--r-- | flags.h | 1 | ||||
| -rw-r--r-- | ninja.cc | 10 | ||||
| -rw-r--r-- | rule.h | 1 | ||||
| -rwxr-xr-x | runtest.rb | 142 | ||||
| -rw-r--r-- | testcase/ninja_validations.sh | 51 |
8 files changed, 177 insertions, 79 deletions
@@ -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, @@ -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; @@ -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")) { @@ -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; @@ -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; @@ -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; @@ -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 + |
