| 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 |