Chromium Code Reviews| 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_) { |
|
scottmg
2015/03/16 16:20:51
I don't think this and the one below are correct.
tfarina
2015/03/22 19:59:54
Done.
| |
| 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_) { |
|
scottmg
2015/03/16 16:20:51
here
tfarina
2015/03/22 19:59:54
Done.
| |
| 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_) { |
| 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 |