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_build_writer.h" | 5 #include "tools/gn/ninja_build_writer.h" |
6 | 6 |
7 #include <fstream> | 7 #include <fstream> |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
150 << " generator = 1\n" | 150 << " generator = 1\n" |
151 << " depfile = build.ninja.d\n"; | 151 << " depfile = build.ninja.d\n"; |
152 | 152 |
153 // Input build files. These go in the ".d" file. If we write them as | 153 // Input build files. These go in the ".d" file. If we write them as |
154 // dependencies in the .ninja file itself, ninja will expect the files to | 154 // dependencies in the .ninja file itself, ninja will expect the files to |
155 // exist and will error if they don't. When files are listed in a depfile, | 155 // exist and will error if they don't. When files are listed in a depfile, |
156 // missing files are ignored. | 156 // missing files are ignored. |
157 dep_out_ << "build.ninja:"; | 157 dep_out_ << "build.ninja:"; |
158 std::vector<base::FilePath> input_files; | 158 std::vector<base::FilePath> input_files; |
159 g_scheduler->input_file_manager()->GetAllPhysicalInputFileNames(&input_files); | 159 g_scheduler->input_file_manager()->GetAllPhysicalInputFileNames(&input_files); |
160 for (size_t i = 0; i < input_files.size(); i++) | 160 for (const auto& input_file : input_files) |
161 dep_out_ << " " << FilePathToUTF8(input_files[i]); | 161 dep_out_ << " " << FilePathToUTF8(input_file); |
162 | 162 |
163 // Other files read by the build. | 163 // Other files read by the build. |
164 std::vector<base::FilePath> other_files = g_scheduler->GetGenDependencies(); | 164 std::vector<base::FilePath> other_files = g_scheduler->GetGenDependencies(); |
165 for (size_t i = 0; i < other_files.size(); i++) | 165 for (const auto& other_file : other_files) |
166 dep_out_ << " " << FilePathToUTF8(other_files[i]); | 166 dep_out_ << " " << FilePathToUTF8(other_file); |
167 | 167 |
168 out_ << std::endl; | 168 out_ << std::endl; |
169 } | 169 } |
170 | 170 |
171 void NinjaBuildWriter::WriteLinkPool() { | 171 void NinjaBuildWriter::WriteLinkPool() { |
172 out_ << "pool link_pool\n" | 172 out_ << "pool link_pool\n" |
173 << " depth = " << default_toolchain_->concurrent_links() << std::endl | 173 << " depth = " << default_toolchain_->concurrent_links() << std::endl |
174 << std::endl; | 174 << std::endl; |
175 } | 175 } |
176 | 176 |
177 void NinjaBuildWriter::WriteSubninjas() { | 177 void NinjaBuildWriter::WriteSubninjas() { |
178 for (size_t i = 0; i < all_settings_.size(); i++) { | 178 for (const auto& elem : all_settings_) { |
179 out_ << "subninja "; | 179 out_ << "subninja "; |
180 path_output_.WriteFile(out_, GetNinjaFileForToolchain(all_settings_[i])); | 180 path_output_.WriteFile(out_, GetNinjaFileForToolchain(elem)); |
181 out_ << std::endl; | 181 out_ << std::endl; |
182 } | 182 } |
183 out_ << std::endl; | 183 out_ << std::endl; |
184 } | 184 } |
185 | 185 |
186 bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) { | 186 bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) { |
187 std::string all_rules; | 187 std::string all_rules; |
188 | 188 |
189 // Write phony rules for all uniquely-named targets in the default toolchain. | 189 // Write phony rules for all uniquely-named targets in the default toolchain. |
190 // Don't do other toolchains or we'll get naming conflicts, and if the name | 190 // Don't do other toolchains or we'll get naming conflicts, and if the name |
191 // isn't unique, also skip it. The exception is for the toplevel targets | 191 // isn't unique, also skip it. The exception is for the toplevel targets |
192 // which we also find. | 192 // which we also find. |
193 std::map<std::string, int> small_name_count; | 193 std::map<std::string, int> small_name_count; |
194 std::vector<const Target*> toplevel_targets; | 194 std::vector<const Target*> toplevel_targets; |
195 base::hash_set<std::string> target_files; | 195 base::hash_set<std::string> target_files; |
196 for (size_t i = 0; i < default_toolchain_targets_.size(); i++) { | 196 for (const auto& target : default_toolchain_targets_) { |
197 const Target* target = default_toolchain_targets_[i]; | |
198 const Label& label = target->label(); | 197 const Label& label = target->label(); |
199 small_name_count[label.name()]++; | 198 small_name_count[label.name()]++; |
200 | 199 |
201 // Look for targets with a name of the form | 200 // Look for targets with a name of the form |
202 // dir = "//foo/", name = "foo" | 201 // dir = "//foo/", name = "foo" |
203 // i.e. where the target name matches the top level directory. We will | 202 // i.e. where the target name matches the top level directory. We will |
204 // always write phony rules for these even if there is another target with | 203 // always write phony rules for these even if there is another target with |
205 // the same short name. | 204 // the same short name. |
206 const std::string& dir_string = label.dir().value(); | 205 const std::string& dir_string = label.dir().value(); |
207 if (dir_string.size() == label.name().size() + 3 && // Size matches. | 206 if (dir_string.size() == label.name().size() + 3 && // Size matches. |
208 dir_string[0] == '/' && dir_string[1] == '/' && // "//" at beginning. | 207 dir_string[0] == '/' && dir_string[1] == '/' && // "//" at beginning. |
209 dir_string[dir_string.size() - 1] == '/' && // "/" at end. | 208 dir_string[dir_string.size() - 1] == '/' && // "/" at end. |
210 dir_string.compare(2, label.name().size(), label.name()) == 0) | 209 dir_string.compare(2, label.name().size(), label.name()) == 0) |
211 toplevel_targets.push_back(target); | 210 toplevel_targets.push_back(target); |
212 } | 211 } |
213 | 212 |
214 for (size_t i = 0; i < default_toolchain_targets_.size(); i++) { | 213 for (const auto& target : default_toolchain_targets_) { |
215 const Target* target = default_toolchain_targets_[i]; | |
216 const Label& label = target->label(); | 214 const Label& label = target->label(); |
217 OutputFile target_file(target->dependency_output_file()); | 215 OutputFile target_file(target->dependency_output_file()); |
218 // The output files may have leading "./" so normalize those away. | 216 // The output files may have leading "./" so normalize those away. |
219 NormalizePath(&target_file.value()); | 217 NormalizePath(&target_file.value()); |
220 if (!target_files.insert(target_file.value()).second) { | 218 if (!target_files.insert(target_file.value()).second) { |
221 *err = Err(Location(), "Duplicate rules for " + target_file.value()); | 219 *err = Err(Location(), "Duplicate rules for " + target_file.value()); |
222 return false; | 220 return false; |
223 } | 221 } |
224 | 222 |
225 // Write the long name "foo/bar:baz" for the target "//foo/bar:baz". | 223 // Write the long name "foo/bar:baz" for the target "//foo/bar:baz". |
(...skipping 16 matching lines...) Expand all Loading... | |
242 if (small_name_count[label.name()] == 1) | 240 if (small_name_count[label.name()] == 1) |
243 WritePhonyRule(target, target_file, label.name()); | 241 WritePhonyRule(target, target_file, label.name()); |
244 | 242 |
245 if (!all_rules.empty()) | 243 if (!all_rules.empty()) |
246 all_rules.append(" $\n "); | 244 all_rules.append(" $\n "); |
247 all_rules.append(target_file.value()); | 245 all_rules.append(target_file.value()); |
248 } | 246 } |
249 | 247 |
250 // Pick up phony rules for the toplevel targets with non-unique names (which | 248 // Pick up phony rules for the toplevel targets with non-unique names (which |
251 // would have been skipped in the above loop). | 249 // would have been skipped in the above loop). |
252 for (size_t i = 0; i < toplevel_targets.size(); i++) { | 250 for (const auto& toplevel_target : toplevel_targets) { |
253 if (small_name_count[toplevel_targets[i]->label().name()] > 1) { | 251 if (small_name_count[toplevel_target->label().name()] > 1) { |
254 const Target* target = toplevel_targets[i]; | 252 WritePhonyRule(toplevel_target, toplevel_target->dependency_output_file(), |
255 WritePhonyRule(target, target->dependency_output_file(), | 253 toplevel_target->label().name()); |
256 target->label().name()); | |
257 } | 254 } |
258 } | 255 } |
259 | 256 |
260 // Figure out if the BUILD file wants to declare a custom "default" | 257 // Figure out if the BUILD file wants to declare a custom "default" |
261 // target (rather than building 'all' by default). By convention | 258 // target (rather than building 'all' by default). By convention |
262 // we use group("default") but it doesn't have to be a group. | 259 // we use group("default") but it doesn't have to be a group. |
263 bool default_target_exists = false; | 260 bool default_target_exists = false; |
264 for (size_t i = 0; i < default_toolchain_targets_.size(); i++) { | 261 for (const auto target : default_toolchain_targets_) { |
scottmg
2015/03/23 17:24:20
const auto&
tfarina
2015/03/25 14:14:31
Done.
| |
265 const Label& label = default_toolchain_targets_[i]->label(); | 262 const Label& label = target->label(); |
266 if (label.dir().value() == "//" && label.name() == "default") | 263 if (label.dir().value() == "//" && label.name() == "default") |
267 default_target_exists = true; | 264 default_target_exists = true; |
268 } | 265 } |
269 | 266 |
270 if (!all_rules.empty()) { | 267 if (!all_rules.empty()) { |
271 out_ << "\nbuild all: phony " << all_rules << std::endl; | 268 out_ << "\nbuild all: phony " << all_rules << std::endl; |
272 } | 269 } |
273 | 270 |
274 if (default_target_exists) { | 271 if (default_target_exists) { |
275 out_ << "default default" << std::endl; | 272 out_ << "default default" << std::endl; |
(...skipping 13 matching lines...) Expand all Loading... | |
289 EscapeOptions ninja_escape; | 286 EscapeOptions ninja_escape; |
290 ninja_escape.mode = ESCAPE_NINJA; | 287 ninja_escape.mode = ESCAPE_NINJA; |
291 | 288 |
292 // Escape for special chars Ninja will handle. | 289 // Escape for special chars Ninja will handle. |
293 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr); | 290 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr); |
294 | 291 |
295 out_ << "build " << escaped << ": phony "; | 292 out_ << "build " << escaped << ": phony "; |
296 path_output_.WriteFile(out_, target_file); | 293 path_output_.WriteFile(out_, target_file); |
297 out_ << std::endl; | 294 out_ << std::endl; |
298 } | 295 } |
OLD | NEW |