Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: tools/gn/ninja_action_target_writer.cc

Issue 1430043002: Support script response files in GN. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: review comment, random build fix Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/functions_target.cc ('k') | tools/gn/ninja_action_target_writer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/ninja_action_target_writer.h" 5 #include "tools/gn/ninja_action_target_writer.h"
6 6
7 #include "base/strings/string_util.h" 7 #include "base/strings/string_util.h"
8 #include "tools/gn/deps_iterator.h" 8 #include "tools/gn/deps_iterator.h"
9 #include "tools/gn/err.h" 9 #include "tools/gn/err.h"
10 #include "tools/gn/settings.h" 10 #include "tools/gn/settings.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 // there will be only one invocation so we can use a simple name. 98 // there will be only one invocation so we can use a simple name.
99 std::string target_label = target_->label().GetUserVisibleName(true); 99 std::string target_label = target_->label().GetUserVisibleName(true);
100 std::string custom_rule_name(target_label); 100 std::string custom_rule_name(target_label);
101 base::ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name); 101 base::ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
102 custom_rule_name.append("_rule"); 102 custom_rule_name.append("_rule");
103 103
104 const SubstitutionList& args = target_->action_values().args(); 104 const SubstitutionList& args = target_->action_values().args();
105 EscapeOptions args_escape_options; 105 EscapeOptions args_escape_options;
106 args_escape_options.mode = ESCAPE_NINJA_COMMAND; 106 args_escape_options.mode = ESCAPE_NINJA_COMMAND;
107 107
108 if (settings_->IsWin()) { 108 out_ << "rule " << custom_rule_name << std::endl;
109 // Send through gyp-win-tool and use a response file. 109
110 if (target_->action_values().uses_rsp_file()) {
111 // Needs a response file. The unique_name part is for action_foreach so
112 // each invocation of the rule gets a different response file. This isn't
113 // strictly necessary for regular one-shot actions, but it's easier to
114 // just always define unique_name.
110 std::string rspfile = custom_rule_name; 115 std::string rspfile = custom_rule_name;
111 if (!target_->sources().empty()) 116 if (!target_->sources().empty())
112 rspfile += ".$unique_name"; 117 rspfile += ".$unique_name";
113 rspfile += ".rsp"; 118 rspfile += ".rsp";
114
115 out_ << "rule " << custom_rule_name << std::endl;
116 out_ << " command = ";
117 path_output_.WriteFile(out_, settings_->build_settings()->python_path());
118 // TODO(brettw) this hardcodes "environment.x86" which is something that
119 // the Chrome Windows toolchain writes. We should have a way to invoke
120 // python without requiring this gyp_win_tool thing.
121 out_ << " gyp-win-tool action-wrapper environment.x86 " << rspfile
122 << std::endl;
123 out_ << " description = ACTION " << target_label << std::endl;
124 out_ << " restat = 1" << std::endl;
125 out_ << " rspfile = " << rspfile << std::endl; 119 out_ << " rspfile = " << rspfile << std::endl;
126 120
127 // The build command goes in the rsp file. 121 // Response file contents.
128 out_ << " rspfile_content = "; 122 out_ << " rspfile_content =";
129 path_output_.WriteFile(out_, settings_->build_settings()->python_path()); 123 for (const auto& arg :
130 out_ << " "; 124 target_->action_values().rsp_file_contents().list()) {
131 path_output_.WriteFile(out_, target_->action_values().script());
132 for (const auto& arg : args.list()) {
133 out_ << " "; 125 out_ << " ";
134 SubstitutionWriter::WriteWithNinjaVariables( 126 SubstitutionWriter::WriteWithNinjaVariables(
135 arg, args_escape_options, out_); 127 arg, args_escape_options, out_);
136 } 128 }
137 out_ << std::endl; 129 out_ << std::endl;
138 } else { 130 }
139 // Posix can execute Python directly. 131
140 out_ << "rule " << custom_rule_name << std::endl; 132 out_ << " command = ";
141 out_ << " command = "; 133 path_output_.WriteFile(out_, settings_->build_settings()->python_path());
142 path_output_.WriteFile(out_, settings_->build_settings()->python_path()); 134 out_ << " ";
135 path_output_.WriteFile(out_, target_->action_values().script());
136 for (const auto& arg : args.list()) {
143 out_ << " "; 137 out_ << " ";
144 path_output_.WriteFile(out_, target_->action_values().script()); 138 SubstitutionWriter::WriteWithNinjaVariables(
145 for (const auto& arg : args.list()) { 139 arg, args_escape_options, out_);
146 out_ << " ";
147 SubstitutionWriter::WriteWithNinjaVariables(
148 arg, args_escape_options, out_);
149 }
150 out_ << std::endl;
151 out_ << " description = ACTION " << target_label << std::endl;
152 out_ << " restat = 1" << std::endl;
153 } 140 }
141 out_ << std::endl;
142 out_ << " description = ACTION " << target_label << std::endl;
143 out_ << " restat = 1" << std::endl;
154 144
155 return custom_rule_name; 145 return custom_rule_name;
156 } 146 }
157 147
158 void NinjaActionTargetWriter::WriteSourceRules( 148 void NinjaActionTargetWriter::WriteSourceRules(
159 const std::string& custom_rule_name, 149 const std::string& custom_rule_name,
160 const OutputFile& input_dep, 150 const OutputFile& input_dep,
161 std::vector<OutputFile>* output_files) { 151 std::vector<OutputFile>* output_files) {
162 EscapeOptions args_escape_options; 152 EscapeOptions args_escape_options;
163 args_escape_options.mode = ESCAPE_NINJA_COMMAND; 153 args_escape_options.mode = ESCAPE_NINJA_COMMAND;
164 // We're writing the substitution values, these should not be quoted since 154 // We're writing the substitution values, these should not be quoted since
165 // they will get pasted into the real command line. 155 // they will get pasted into the real command line.
166 args_escape_options.inhibit_quoting = true; 156 args_escape_options.inhibit_quoting = true;
167 157
168 const std::vector<SubstitutionType>& args_substitutions_used =
169 target_->action_values().args().required_types();
170
171 const Target::FileList& sources = target_->sources(); 158 const Target::FileList& sources = target_->sources();
172 for (size_t i = 0; i < sources.size(); i++) { 159 for (size_t i = 0; i < sources.size(); i++) {
173 out_ << "build"; 160 out_ << "build";
174 WriteOutputFilesForBuildLine(sources[i], output_files); 161 WriteOutputFilesForBuildLine(sources[i], output_files);
175 162
176 out_ << ": " << custom_rule_name << " "; 163 out_ << ": " << custom_rule_name << " ";
177 path_output_.WriteFile(out_, sources[i]); 164 path_output_.WriteFile(out_, sources[i]);
178 if (!input_dep.value().empty()) { 165 if (!input_dep.value().empty()) {
179 // Using "|" for the dependencies forces all implicit dependencies to be 166 // Using "|" for the dependencies forces all implicit dependencies to be
180 // fully up-to-date before running the action, and will re-run this 167 // fully up-to-date before running the action, and will re-run this
181 // action if any input dependencies change. This is important because 168 // action if any input dependencies change. This is important because
182 // this action may consume the outputs of previous steps. 169 // this action may consume the outputs of previous steps.
183 out_ << " | "; 170 out_ << " | ";
184 path_output_.WriteFile(out_, input_dep); 171 path_output_.WriteFile(out_, input_dep);
185 } 172 }
186 out_ << std::endl; 173 out_ << std::endl;
187 174
188 // Windows needs a unique ID for the response file. 175 // Response files require a unique name be defined.
189 if (target_->settings()->IsWin()) 176 if (target_->action_values().uses_rsp_file())
190 out_ << " unique_name = " << i << std::endl; 177 out_ << " unique_name = " << i << std::endl;
191 178
179 // The required types is the union of the args and response file. This
180 // might theoretically duplicate a definition if the same substitution is
181 // used in both the args and the reponse file. However, this should be
182 // very unusual (normally the substitutions will go in one place or the
183 // other) and the redundant assignment won't bother Ninja.
192 SubstitutionWriter::WriteNinjaVariablesForSource( 184 SubstitutionWriter::WriteNinjaVariablesForSource(
193 settings_, sources[i], args_substitutions_used, 185 settings_, sources[i],
186 target_->action_values().args().required_types(),
187 args_escape_options, out_);
188 SubstitutionWriter::WriteNinjaVariablesForSource(
189 settings_, sources[i],
190 target_->action_values().rsp_file_contents().required_types(),
194 args_escape_options, out_); 191 args_escape_options, out_);
195 192
196 if (target_->action_values().has_depfile()) { 193 if (target_->action_values().has_depfile()) {
197 out_ << " depfile = "; 194 out_ << " depfile = ";
198 WriteDepfile(sources[i]); 195 WriteDepfile(sources[i]);
199 out_ << std::endl; 196 out_ << std::endl;
200 } 197 }
201 } 198 }
202 } 199 }
203 200
204 void NinjaActionTargetWriter::WriteOutputFilesForBuildLine( 201 void NinjaActionTargetWriter::WriteOutputFilesForBuildLine(
205 const SourceFile& source, 202 const SourceFile& source,
206 std::vector<OutputFile>* output_files) { 203 std::vector<OutputFile>* output_files) {
207 size_t first_output_index = output_files->size(); 204 size_t first_output_index = output_files->size();
208 205
209 SubstitutionWriter::ApplyListToSourceAsOutputFile( 206 SubstitutionWriter::ApplyListToSourceAsOutputFile(
210 settings_, target_->action_values().outputs(), source, output_files); 207 settings_, target_->action_values().outputs(), source, output_files);
211 208
212 for (size_t i = first_output_index; i < output_files->size(); i++) { 209 for (size_t i = first_output_index; i < output_files->size(); i++) {
213 out_ << " "; 210 out_ << " ";
214 path_output_.WriteFile(out_, (*output_files)[i]); 211 path_output_.WriteFile(out_, (*output_files)[i]);
215 } 212 }
216 } 213 }
217 214
218 void NinjaActionTargetWriter::WriteDepfile(const SourceFile& source) { 215 void NinjaActionTargetWriter::WriteDepfile(const SourceFile& source) {
219 path_output_.WriteFile(out_, 216 path_output_.WriteFile(out_,
220 SubstitutionWriter::ApplyPatternToSourceAsOutputFile( 217 SubstitutionWriter::ApplyPatternToSourceAsOutputFile(
221 settings_, target_->action_values().depfile(), source)); 218 settings_, target_->action_values().depfile(), source));
222 } 219 }
OLDNEW
« no previous file with comments | « tools/gn/functions_target.cc ('k') | tools/gn/ninja_action_target_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698