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

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

Issue 23606031: GN: Use build directory for CD for scripts (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 months 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 | Annotate | Revision Log
« no previous file with comments | « tools/gn/ninja_script_target_writer.h ('k') | tools/gn/scope_per_file_provider.h » ('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_script_target_writer.h" 5 #include "tools/gn/ninja_script_target_writer.h"
6 6
7 #include "base/strings/string_util.h" 7 #include "base/strings/string_util.h"
8 #include "tools/gn/err.h" 8 #include "tools/gn/err.h"
9 #include "tools/gn/file_template.h" 9 #include "tools/gn/file_template.h"
10 #include "tools/gn/string_utils.h" 10 #include "tools/gn/string_utils.h"
11 #include "tools/gn/target.h" 11 #include "tools/gn/target.h"
12 12
13 NinjaScriptTargetWriter::NinjaScriptTargetWriter(const Target* target, 13 NinjaScriptTargetWriter::NinjaScriptTargetWriter(const Target* target,
14 std::ostream& out) 14 std::ostream& out)
15 : NinjaTargetWriter(target, out) { 15 : NinjaTargetWriter(target, out) {
16 } 16 }
17 17
18 NinjaScriptTargetWriter::~NinjaScriptTargetWriter() { 18 NinjaScriptTargetWriter::~NinjaScriptTargetWriter() {
19 } 19 }
20 20
21 void NinjaScriptTargetWriter::Run() { 21 void NinjaScriptTargetWriter::Run() {
22 WriteEnvironment(); 22 WriteEnvironment();
23 23
24 // Run the script from the dir of the BUILD file. This has no trailing 24 std::string custom_rule_name = WriteRuleDefinition();
25 // slash.
26 const SourceDir& script_cd = target_->label().dir();
27 std::string script_cd_to_root = InvertDir(script_cd);
28 if (script_cd_to_root.empty()) {
29 script_cd_to_root = ".";
30 } else {
31 // Remove trailing slash.
32 DCHECK(script_cd_to_root[script_cd_to_root.size() - 1] == '/');
33 script_cd_to_root.resize(script_cd_to_root.size() - 1);
34 }
35
36 // Compute the relative script file name. The script string should start with
37 // 2 slashes, and we trim 1.
38 DCHECK(target_->script_values().script().is_source_absolute());
39 std::string script_relative_to_cd = script_cd_to_root;
40 const std::string& script_string = target_->script_values().script().value();
41 script_relative_to_cd.append(&script_string[1], script_string.size() - 1);
42
43 std::string custom_rule_name = WriteRuleDefinition(script_relative_to_cd);
44 std::string implicit_deps = GetSourcesImplicitDeps(); 25 std::string implicit_deps = GetSourcesImplicitDeps();
45 26
46 // Collects all output files for writing below. 27 // Collects all output files for writing below.
47 std::vector<OutputFile> output_files; 28 std::vector<OutputFile> output_files;
48 29
49 if (has_sources()) { 30 if (has_sources()) {
50 // Write separate rules for each input source file. 31 // Write separate rules for each input source file.
51 WriteSourceRules(custom_rule_name, implicit_deps, script_cd, 32 WriteSourceRules(custom_rule_name, implicit_deps, &output_files);
52 script_cd_to_root, &output_files);
53 } else { 33 } else {
54 // No sources, write a rule that invokes the script once with the 34 // No sources, write a rule that invokes the script once with the
55 // outputs as outputs, and the data as inputs. 35 // outputs as outputs, and the data as inputs.
56 out_ << "build"; 36 out_ << "build";
57 const Target::FileList& outputs = target_->script_values().outputs(); 37 const Target::FileList& outputs = target_->script_values().outputs();
58 for (size_t i = 0; i < outputs.size(); i++) { 38 for (size_t i = 0; i < outputs.size(); i++) {
59 OutputFile output_path( 39 OutputFile output_path(
60 RemovePrefix(outputs[i].value(), 40 RemovePrefix(outputs[i].value(),
61 settings_->build_settings()->build_dir().value())); 41 settings_->build_settings()->build_dir().value()));
62 output_files.push_back(output_path); 42 output_files.push_back(output_path);
63 out_ << " "; 43 out_ << " ";
64 path_output_.WriteFile(out_, output_path); 44 path_output_.WriteFile(out_, output_path);
65 } 45 }
66 out_ << ": " << custom_rule_name << implicit_deps << std::endl; 46 out_ << ": " << custom_rule_name << implicit_deps << std::endl;
67 } 47 }
68 out_ << std::endl; 48 out_ << std::endl;
69 49
70 WriteStamp(output_files); 50 WriteStamp(output_files);
71 } 51 }
72 52
73 std::string NinjaScriptTargetWriter::WriteRuleDefinition( 53 std::string NinjaScriptTargetWriter::WriteRuleDefinition() {
74 const std::string& script_relative_to_cd) {
75 // Make a unique name for this rule. 54 // Make a unique name for this rule.
55 //
56 // Use a unique name for the response file when there are multiple build
57 // steps so that they don't stomp on each other. When there are no sources,
58 // there will be only one invocation so we can use a simple name.
76 std::string target_label = target_->label().GetUserVisibleName(true); 59 std::string target_label = target_->label().GetUserVisibleName(true);
77 std::string custom_rule_name(target_label); 60 std::string custom_rule_name(target_label);
78 ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name); 61 ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
79 custom_rule_name.append("_rule"); 62 custom_rule_name.append("_rule");
80 63
81 // Use a unique name for the response file when there are multiple build
82 // steps so that they don't stomp on each other. When there are no sources,
83 // there will be only one invocation so we can use a simple name.
84
85 if (settings_->IsWin()) { 64 if (settings_->IsWin()) {
86 // Send through gyp-win-tool and use a response file. 65 // Send through gyp-win-tool and use a response file.
87 std::string rspfile = custom_rule_name; 66 std::string rspfile = custom_rule_name;
88 if (has_sources()) 67 if (has_sources())
89 rspfile += ".$unique_name"; 68 rspfile += ".$unique_name";
90 rspfile += ".rsp"; 69 rspfile += ".rsp";
91 70
92 out_ << "rule " << custom_rule_name << std::endl; 71 out_ << "rule " << custom_rule_name << std::endl;
93 out_ << " command = $pythonpath gyp-win-tool action-wrapper $arch " 72 out_ << " command = $pythonpath gyp-win-tool action-wrapper $arch "
94 << rspfile << " "; 73 << rspfile << std::endl;
95 path_output_.WriteDir(out_, target_->label().dir(),
96 PathOutput::DIR_NO_LAST_SLASH);
97 out_ << std::endl;
98 out_ << " description = CUSTOM " << target_label << std::endl; 74 out_ << " description = CUSTOM " << target_label << std::endl;
99 out_ << " restat = 1" << std::endl; 75 out_ << " restat = 1" << std::endl;
100 out_ << " rspfile = " << rspfile << std::endl; 76 out_ << " rspfile = " << rspfile << std::endl;
101 77
102 // The build command goes in the rsp file. 78 // The build command goes in the rsp file.
103 out_ << " rspfile_content = $pythonpath " << script_relative_to_cd; 79 out_ << " rspfile_content = $pythonpath ";
80 path_output_.WriteFile(out_, target_->script_values().script());
104 for (size_t i = 0; i < target_->script_values().args().size(); i++) { 81 for (size_t i = 0; i < target_->script_values().args().size(); i++) {
105 const std::string& arg = target_->script_values().args()[i]; 82 const std::string& arg = target_->script_values().args()[i];
106 out_ << " "; 83 out_ << " ";
107 WriteArg(arg); 84 WriteArg(arg);
108 } 85 }
109 } else { 86 } else {
110 // Posix can execute Python directly. 87 // Posix can execute Python directly.
111 out_ << "rule " << custom_rule_name << std::endl; 88 out_ << "rule " << custom_rule_name << std::endl;
112 out_ << " command = cd "; 89 out_ << " command = cd ";
113 path_output_.WriteDir(out_, target_->label().dir(), 90 path_output_.WriteDir(out_, target_->label().dir(),
114 PathOutput::DIR_NO_LAST_SLASH); 91 PathOutput::DIR_NO_LAST_SLASH);
115 out_ << "; $pythonpath " << script_relative_to_cd; 92 out_ << "; $pythonpath ";
93 path_output_.WriteFile(out_, target_->script_values().script());
116 for (size_t i = 0; i < target_->script_values().args().size(); i++) { 94 for (size_t i = 0; i < target_->script_values().args().size(); i++) {
117 const std::string& arg = target_->script_values().args()[i]; 95 const std::string& arg = target_->script_values().args()[i];
118 out_ << " "; 96 out_ << " ";
119 WriteArg(arg); 97 WriteArg(arg);
120 } 98 }
121 out_ << std::endl; 99 out_ << std::endl;
122 out_ << " description = CUSTOM " << target_label << std::endl; 100 out_ << " description = CUSTOM " << target_label << std::endl;
123 out_ << " restat = 1" << std::endl; 101 out_ << " restat = 1" << std::endl;
124 } 102 }
125 103
(...skipping 12 matching lines...) Expand all
138 ReplaceSubstringsAfterOffset(&output_str, 0, FileTemplate::kSource, 116 ReplaceSubstringsAfterOffset(&output_str, 0, FileTemplate::kSource,
139 "${source}"); 117 "${source}");
140 ReplaceSubstringsAfterOffset(&output_str, 0, FileTemplate::kSourceNamePart, 118 ReplaceSubstringsAfterOffset(&output_str, 0, FileTemplate::kSourceNamePart,
141 "${source_name_part}"); 119 "${source_name_part}");
142 out_ << output_str; 120 out_ << output_str;
143 } 121 }
144 122
145 void NinjaScriptTargetWriter::WriteSourceRules( 123 void NinjaScriptTargetWriter::WriteSourceRules(
146 const std::string& custom_rule_name, 124 const std::string& custom_rule_name,
147 const std::string& implicit_deps, 125 const std::string& implicit_deps,
148 const SourceDir& script_cd,
149 const std::string& script_cd_to_root,
150 std::vector<OutputFile>* output_files) { 126 std::vector<OutputFile>* output_files) {
151 // Construct the template for generating the output files from each source. 127 // Construct the template for generating the output files from each source.
152 const Target::FileList& outputs = target_->script_values().outputs(); 128 const Target::FileList& outputs = target_->script_values().outputs();
153 std::vector<std::string> output_template_args; 129 std::vector<std::string> output_template_args;
154 for (size_t i = 0; i < outputs.size(); i++) { 130 for (size_t i = 0; i < outputs.size(); i++) {
155 // All outputs should be in the output dir. 131 // All outputs should be in the output dir.
156 output_template_args.push_back( 132 output_template_args.push_back(
157 RemovePrefix(outputs[i].value(), 133 RemovePrefix(outputs[i].value(),
158 settings_->build_settings()->build_dir().value())); 134 settings_->build_settings()->build_dir().value()));
159 } 135 }
160 FileTemplate output_template(output_template_args); 136 FileTemplate output_template(output_template_args);
161 137
162 // Prevent re-allocating each time by initializing outside the loop. 138 // Prevent re-allocating each time by initializing outside the loop.
163 std::vector<std::string> output_template_result; 139 std::vector<std::string> output_template_result;
164 140
165 // Path output formatter for wrigin source paths passed to the script.
166 PathOutput script_source_path_output(script_cd, ESCAPE_SHELL, true);
167
168 const Target::FileList& sources = target_->sources(); 141 const Target::FileList& sources = target_->sources();
169 for (size_t i = 0; i < sources.size(); i++) { 142 for (size_t i = 0; i < sources.size(); i++) {
170 // Write outputs for this source file computed by the template. 143 // Write outputs for this source file computed by the template.
171 out_ << "build"; 144 out_ << "build";
172 output_template.ApplyString(sources[i].value(), &output_template_result); 145 output_template.ApplyString(sources[i].value(), &output_template_result);
173 for (size_t out_i = 0; out_i < output_template_result.size(); out_i++) { 146 for (size_t out_i = 0; out_i < output_template_result.size(); out_i++) {
174 OutputFile output_path(output_template_result[out_i]); 147 OutputFile output_path(output_template_result[out_i]);
175 output_files->push_back(output_path); 148 output_files->push_back(output_path);
176 out_ << " "; 149 out_ << " ";
177 path_output_.WriteFile(out_, output_path); 150 path_output_.WriteFile(out_, output_path);
178 } 151 }
179 152
180 out_ << ": " << custom_rule_name; 153 out_ << ": " << custom_rule_name;
181 path_output_.WriteFile(out_, sources[i]); 154 path_output_.WriteFile(out_, sources[i]);
182 out_ << implicit_deps << std::endl; 155 out_ << implicit_deps << std::endl;
183 156
184 out_ << " unique_name = " << i << std::endl; 157 out_ << " unique_name = " << i << std::endl;
185 158
186 // The source file here should be relative to the script directory since 159 // The source file here should be relative to the script directory since
187 // this is the variable passed to the script. Here we slightly abuse the 160 // this is the variable passed to the script. Here we slightly abuse the
188 // OutputFile object by putting a non-output-relative path in it to signal 161 // OutputFile object by putting a non-output-relative path in it to signal
189 // that the PathWriter should not prepend directories. 162 // that the PathWriter should not prepend directories.
190 out_ << " source = "; 163 out_ << " source = ";
191 script_source_path_output.WriteFile(out_, sources[i]); 164 path_output_.WriteFile(out_, sources[i]);
192 out_ << std::endl; 165 out_ << std::endl;
193 166
194 out_ << " source_name_part = " 167 out_ << " source_name_part = "
195 << FindFilenameNoExtension(&sources[i].value()).as_string() 168 << FindFilenameNoExtension(&sources[i].value()).as_string()
196 << std::endl; 169 << std::endl;
197 } 170 }
198 } 171 }
199 172
200 void NinjaScriptTargetWriter::WriteStamp( 173 void NinjaScriptTargetWriter::WriteStamp(
201 const std::vector<OutputFile>& output_files) { 174 const std::vector<OutputFile>& output_files) {
202 out_ << "build "; 175 out_ << "build ";
203 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_)); 176 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_));
204 out_ << ": " 177 out_ << ": "
205 << helper_.GetRulePrefix(target_->settings()->toolchain()) 178 << helper_.GetRulePrefix(target_->settings()->toolchain())
206 << "stamp"; 179 << "stamp";
207 for (size_t i = 0; i < output_files.size(); i++) { 180 for (size_t i = 0; i < output_files.size(); i++) {
208 out_ << " "; 181 out_ << " ";
209 path_output_.WriteFile(out_, output_files[i]); 182 path_output_.WriteFile(out_, output_files[i]);
210 } 183 }
211 out_ << std::endl; 184 out_ << std::endl;
212 } 185 }
OLDNEW
« no previous file with comments | « tools/gn/ninja_script_target_writer.h ('k') | tools/gn/scope_per_file_provider.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698