OLD | NEW |
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 Loading... |
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 } |
OLD | NEW |