Correct blacklist entry message
[chromium-blink-merge.git] / tools / gn / ninja_script_target_writer.cc
blobe8cdef41933fd76682700443fa4c7bcfd9a162ce
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "tools/gn/ninja_script_target_writer.h"
7 #include "base/strings/string_util.h"
8 #include "tools/gn/err.h"
9 #include "tools/gn/file_template.h"
10 #include "tools/gn/string_utils.h"
11 #include "tools/gn/target.h"
13 NinjaScriptTargetWriter::NinjaScriptTargetWriter(const Target* target,
14 const Toolchain* toolchain,
15 std::ostream& out)
16 : NinjaTargetWriter(target, toolchain, out),
17 path_output_no_escaping_(
18 target->settings()->build_settings()->build_dir(),
19 ESCAPE_NONE, false) {
22 NinjaScriptTargetWriter::~NinjaScriptTargetWriter() {
25 void NinjaScriptTargetWriter::Run() {
26 FileTemplate args_template(target_->script_values().args());
27 std::string custom_rule_name = WriteRuleDefinition(args_template);
28 std::string implicit_deps = GetSourcesImplicitDeps();
30 // Collects all output files for writing below.
31 std::vector<OutputFile> output_files;
33 if (has_sources()) {
34 // Write separate build lines for each input source file.
35 WriteSourceRules(custom_rule_name, implicit_deps, args_template,
36 &output_files);
37 } else {
38 // No sources, write a rule that invokes the script once with the
39 // outputs as outputs, and the data as inputs.
40 out_ << "build";
41 const Target::FileList& outputs = target_->script_values().outputs();
42 for (size_t i = 0; i < outputs.size(); i++) {
43 OutputFile output_path(
44 RemovePrefix(outputs[i].value(),
45 settings_->build_settings()->build_dir().value()));
46 output_files.push_back(output_path);
47 out_ << " ";
48 path_output_.WriteFile(out_, output_path);
50 out_ << ": " << custom_rule_name << implicit_deps << std::endl;
52 out_ << std::endl;
54 WriteStamp(output_files);
57 std::string NinjaScriptTargetWriter::WriteRuleDefinition(
58 const FileTemplate& args_template) {
59 // Make a unique name for this rule.
61 // Use a unique name for the response file when there are multiple build
62 // steps so that they don't stomp on each other. When there are no sources,
63 // there will be only one invocation so we can use a simple name.
64 std::string target_label = target_->label().GetUserVisibleName(true);
65 std::string custom_rule_name(target_label);
66 ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
67 custom_rule_name.append("_rule");
69 if (settings_->IsWin()) {
70 // Send through gyp-win-tool and use a response file.
71 std::string rspfile = custom_rule_name;
72 if (has_sources())
73 rspfile += ".$unique_name";
74 rspfile += ".rsp";
76 out_ << "rule " << custom_rule_name << std::endl;
77 out_ << " command = ";
78 path_output_.WriteFile(out_, settings_->build_settings()->python_path());
79 // TODO(brettw) this hardcodes "environment.x86" which is something that
80 // the Chrome Windows toolchain writes. We should have a way to invoke
81 // python without requiring this gyp_win_tool thing.
82 out_ << " gyp-win-tool action-wrapper environment.x86 " << rspfile
83 << std::endl;
84 out_ << " description = CUSTOM " << target_label << std::endl;
85 out_ << " restat = 1" << std::endl;
86 out_ << " rspfile = " << rspfile << std::endl;
88 // The build command goes in the rsp file.
89 out_ << " rspfile_content = ";
90 path_output_.WriteFile(out_, settings_->build_settings()->python_path());
91 out_ << " ";
92 path_output_.WriteFile(out_, target_->script_values().script());
93 args_template.WriteWithNinjaExpansions(out_);
94 out_ << std::endl;
95 } else {
96 // Posix can execute Python directly.
97 out_ << "rule " << custom_rule_name << std::endl;
98 out_ << " command = ";
99 path_output_.WriteFile(out_, settings_->build_settings()->python_path());
100 out_ << " ";
101 path_output_.WriteFile(out_, target_->script_values().script());
102 args_template.WriteWithNinjaExpansions(out_);
103 out_ << std::endl;
104 out_ << " description = CUSTOM " << target_label << std::endl;
105 out_ << " restat = 1" << std::endl;
108 out_ << std::endl;
109 return custom_rule_name;
112 void NinjaScriptTargetWriter::WriteArgsSubstitutions(
113 const SourceFile& source,
114 const FileTemplate& args_template) {
115 std::ostringstream source_file_stream;
116 path_output_no_escaping_.WriteFile(source_file_stream, source);
118 EscapeOptions template_escape_options;
119 template_escape_options.mode = ESCAPE_NINJA_SHELL;
120 template_escape_options.inhibit_quoting = true;
122 args_template.WriteNinjaVariablesForSubstitution(
123 out_, source_file_stream.str(), template_escape_options);
126 void NinjaScriptTargetWriter::WriteSourceRules(
127 const std::string& custom_rule_name,
128 const std::string& implicit_deps,
129 const FileTemplate& args_template,
130 std::vector<OutputFile>* output_files) {
131 FileTemplate output_template(GetOutputTemplate());
133 const Target::FileList& sources = target_->sources();
134 for (size_t i = 0; i < sources.size(); i++) {
135 out_ << "build";
136 WriteOutputFilesForBuildLine(output_template, sources[i], output_files);
138 out_ << ": " << custom_rule_name << " ";
139 path_output_.WriteFile(out_, sources[i]);
140 out_ << implicit_deps << std::endl;
142 // Windows needs a unique ID for the response file.
143 if (target_->settings()->IsWin())
144 out_ << " unique_name = " << i << std::endl;
146 if (args_template.has_substitutions())
147 WriteArgsSubstitutions(sources[i], args_template);
151 void NinjaScriptTargetWriter::WriteStamp(
152 const std::vector<OutputFile>& output_files) {
153 out_ << "build ";
154 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_));
155 out_ << ": "
156 << helper_.GetRulePrefix(target_->settings())
157 << "stamp";
158 for (size_t i = 0; i < output_files.size(); i++) {
159 out_ << " ";
160 path_output_.WriteFile(out_, output_files[i]);
162 out_ << std::endl;
165 void NinjaScriptTargetWriter::WriteOutputFilesForBuildLine(
166 const FileTemplate& output_template,
167 const SourceFile& source,
168 std::vector<OutputFile>* output_files) {
169 std::vector<std::string> output_template_result;
170 output_template.ApplyString(source.value(), &output_template_result);
171 for (size_t out_i = 0; out_i < output_template_result.size(); out_i++) {
172 OutputFile output_path(output_template_result[out_i]);
173 output_files->push_back(output_path);
174 out_ << " ";
175 path_output_.WriteFile(out_, output_path);