| 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/gyp_binary_target_writer.h" | 5 #include "tools/gn/gyp_binary_target_writer.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "tools/gn/builder_record.h" | 10 #include "tools/gn/builder_record.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 struct Accumulator { | 23 struct Accumulator { |
| 24 Accumulator(std::vector<T>* result_in) : result(result_in) {} | 24 Accumulator(std::vector<T>* result_in) : result(result_in) {} |
| 25 | 25 |
| 26 void operator()(const T& s, std::ostream&) const { | 26 void operator()(const T& s, std::ostream&) const { |
| 27 result->push_back(s); | 27 result->push_back(s); |
| 28 } | 28 } |
| 29 | 29 |
| 30 std::vector<T>* result; | 30 std::vector<T>* result; |
| 31 }; | 31 }; |
| 32 | 32 |
| 33 // Standalone version of GypBinaryTargetWriter::Indent for use by standalone | |
| 34 // functions. | |
| 35 std::ostream& Indent(std::ostream& out, int spaces) { | |
| 36 const char kSpaces[81] = | |
| 37 " " | |
| 38 " "; | |
| 39 CHECK(static_cast<size_t>(spaces) <= arraysize(kSpaces) - 1); | |
| 40 out.write(kSpaces, spaces); | |
| 41 return out; | |
| 42 } | |
| 43 | |
| 44 // Writes the given array values. The array should already be declared with the | 33 // Writes the given array values. The array should already be declared with the |
| 45 // opening "[" written to the output. The function will not write the | 34 // opening "[" written to the output. The function will not write the |
| 46 // terminating "]" either. | 35 // terminating "]" either. |
| 47 void WriteArrayValues(std::ostream& out, | 36 void WriteArrayValues(std::ostream& out, |
| 48 const std::vector<std::string>& values) { | 37 const std::vector<std::string>& values) { |
| 49 EscapeOptions options; | 38 EscapeOptions options; |
| 50 options.mode = ESCAPE_JSON; | 39 options.mode = ESCAPE_JSON; |
| 51 for (size_t i = 0; i < values.size(); i++) { | 40 for (size_t i = 0; i < values.size(); i++) { |
| 52 out << " '"; | 41 out << " '"; |
| 53 EscapeStringToStream(out, values[i], options); | 42 EscapeStringToStream(out, values[i], options); |
| 54 out << "',"; | 43 out << "',"; |
| 55 } | 44 } |
| 56 } | 45 } |
| 57 | 46 |
| 58 // Writes the given array with the given name. The indent should be the | |
| 59 // indenting for the name, the values will be indented 2 spaces from there. | |
| 60 // Writes nothing if there is nothing in the array. | |
| 61 void WriteNamedArray(std::ostream& out, | |
| 62 const char* name, | |
| 63 const std::vector<std::string>& values, | |
| 64 int indent) { | |
| 65 if (values.empty()) | |
| 66 return; | |
| 67 | |
| 68 EscapeOptions options; | |
| 69 options.mode = ESCAPE_JSON; | |
| 70 | |
| 71 Indent(out, indent) << "'" << name << "': ["; | |
| 72 WriteArrayValues(out, values); | |
| 73 out << " ],\n"; | |
| 74 } | |
| 75 | |
| 76 // Returns the value from the already-filled in cflags_* for the optimization | 47 // Returns the value from the already-filled in cflags_* for the optimization |
| 77 // level to set in the GYP file. Additionally, this removes the flag from the | 48 // level to set in the GYP file. Additionally, this removes the flag from the |
| 78 // given vector so we don't get duplicates. | 49 // given vector so we don't get duplicates. |
| 79 std::string GetVCOptimization(std::vector<std::string>* cflags) { | 50 std::string GetVCOptimization(std::vector<std::string>* cflags) { |
| 80 // Searches for the "/O?" option and returns the corresponding GYP value. | 51 // Searches for the "/O?" option and returns the corresponding GYP value. |
| 81 for (size_t i = 0; i < cflags->size(); i++) { | 52 for (size_t i = 0; i < cflags->size(); i++) { |
| 82 const std::string& cur = (*cflags)[i]; | 53 const std::string& cur = (*cflags)[i]; |
| 83 if (cur.size() == 3 && cur[0] == '/' && cur[1] == 'O') { | 54 if (cur.size() == 3 && cur[0] == '/' && cur[1] == 'O') { |
| 84 char level = cur[2]; | 55 char level = cur[2]; |
| 85 cflags->erase(cflags->begin() + i); // Invalidates |cur|! | 56 cflags->erase(cflags->begin() + i); // Invalidates |cur|! |
| (...skipping 17 matching lines...) Expand all Loading... |
| 103 const std::vector<T>& (ConfigValues::* getter)() const, | 74 const std::vector<T>& (ConfigValues::* getter)() const, |
| 104 std::vector<T>* result) { | 75 std::vector<T>* result) { |
| 105 for (size_t config_i = 0; config_i < configs.size(); config_i++) { | 76 for (size_t config_i = 0; config_i < configs.size(); config_i++) { |
| 106 const std::vector<T>& values = | 77 const std::vector<T>& values = |
| 107 (configs[config_i].ptr->config_values().*getter)(); | 78 (configs[config_i].ptr->config_values().*getter)(); |
| 108 for (size_t val_i = 0; val_i < values.size(); val_i++) | 79 for (size_t val_i = 0; val_i < values.size(); val_i++) |
| 109 result->push_back(values[val_i]); | 80 result->push_back(values[val_i]); |
| 110 } | 81 } |
| 111 } | 82 } |
| 112 | 83 |
| 113 const int kExtraIndent = 2; | |
| 114 | |
| 115 } // namespace | 84 } // namespace |
| 116 | 85 |
| 117 GypBinaryTargetWriter::Flags::Flags() {} | 86 GypBinaryTargetWriter::Flags::Flags() {} |
| 118 GypBinaryTargetWriter::Flags::~Flags() {} | 87 GypBinaryTargetWriter::Flags::~Flags() {} |
| 119 | 88 |
| 120 GypBinaryTargetWriter::GypBinaryTargetWriter(const TargetGroup& group, | 89 GypBinaryTargetWriter::GypBinaryTargetWriter(const TargetGroup& group, |
| 90 const SourceDir& gyp_dir, |
| 121 std::ostream& out) | 91 std::ostream& out) |
| 122 : GypTargetWriter(group.debug->item()->AsTarget(), out), | 92 : GypTargetWriter(group.debug->item()->AsTarget(), gyp_dir, out), |
| 123 group_(group) { | 93 group_(group) { |
| 124 } | 94 } |
| 125 | 95 |
| 126 GypBinaryTargetWriter::~GypBinaryTargetWriter() { | 96 GypBinaryTargetWriter::~GypBinaryTargetWriter() { |
| 127 } | 97 } |
| 128 | 98 |
| 129 void GypBinaryTargetWriter::Run() { | 99 void GypBinaryTargetWriter::Run() { |
| 130 int indent = 4; | 100 int indent = 4; |
| 131 | 101 |
| 132 Indent(indent) << "{\n"; | 102 Indent(indent) << "{\n"; |
| 133 | 103 |
| 134 WriteName(indent + kExtraIndent); | 104 WriteName(indent + kExtraIndent); |
| 135 WriteType(indent + kExtraIndent); | 105 WriteType(indent + kExtraIndent); |
| 136 | 106 |
| 137 if (target_->settings()->IsLinux()) | 107 if (target_->settings()->IsLinux()) |
| 138 WriteLinuxConfiguration(indent + kExtraIndent); | 108 WriteLinuxConfiguration(indent + kExtraIndent); |
| 139 else if (target_->settings()->IsWin()) | 109 else if (target_->settings()->IsWin()) |
| 140 WriteVCConfiguration(indent + kExtraIndent); | 110 WriteVCConfiguration(indent + kExtraIndent); |
| 141 else if (target_->settings()->IsMac()) | 111 else if (target_->settings()->IsMac()) |
| 142 WriteMacConfiguration(indent + kExtraIndent); | 112 WriteMacConfiguration(indent + kExtraIndent); |
| 143 WriteDirectDependentSettings(indent + kExtraIndent); | 113 WriteDirectDependentSettings(indent + kExtraIndent); |
| 144 WriteAllDependentSettings(indent + kExtraIndent); | 114 WriteAllDependentSettings(indent + kExtraIndent); |
| 145 | 115 |
| 146 Indent(indent) << "},\n"; | 116 Indent(indent) << "},\n"; |
| 147 } | 117 } |
| 148 | 118 |
| 149 std::ostream& GypBinaryTargetWriter::Indent(int spaces) { | |
| 150 return ::Indent(out_, spaces); | |
| 151 } | |
| 152 | |
| 153 void GypBinaryTargetWriter::WriteName(int indent) { | 119 void GypBinaryTargetWriter::WriteName(int indent) { |
| 154 std::string name = helper_.GetNameForTarget(target_); | 120 std::string name = helper_.GetNameForTarget(target_); |
| 155 Indent(indent) << "'target_name': '" << name << "',\n"; | 121 Indent(indent) << "'target_name': '" << name << "',\n"; |
| 156 | 122 |
| 157 std::string product_name; | 123 std::string product_name; |
| 158 if (target_->output_name().empty()) | 124 if (target_->output_name().empty()) |
| 159 product_name = target_->label().name(); | 125 product_name = target_->label().name(); |
| 160 else | 126 else |
| 161 product_name = name; | 127 product_name = name; |
| 162 | 128 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 Indent(indent + kExtraIndent) << "},\n"; | 240 Indent(indent + kExtraIndent) << "},\n"; |
| 275 | 241 |
| 276 Indent(indent) << "},\n"; | 242 Indent(indent) << "},\n"; |
| 277 | 243 |
| 278 WriteSources(target_, indent); | 244 WriteSources(target_, indent); |
| 279 WriteDeps(target_, indent); | 245 WriteDeps(target_, indent); |
| 280 } | 246 } |
| 281 | 247 |
| 282 void GypBinaryTargetWriter::WriteVCFlags(Flags& flags, int indent) { | 248 void GypBinaryTargetWriter::WriteVCFlags(Flags& flags, int indent) { |
| 283 // Defines and includes go outside of the msvs settings. | 249 // Defines and includes go outside of the msvs settings. |
| 284 WriteNamedArray(out_, "defines", flags.defines, indent); | 250 WriteNamedArray("defines", flags.defines, indent); |
| 285 WriteIncludeDirs(flags, indent); | 251 WriteIncludeDirs(flags, indent); |
| 286 | 252 |
| 287 // C flags. | 253 // C flags. |
| 288 Indent(indent) << "'msvs_settings': {\n"; | 254 Indent(indent) << "'msvs_settings': {\n"; |
| 289 Indent(indent + kExtraIndent) << "'VCCLCompilerTool': {\n"; | 255 Indent(indent + kExtraIndent) << "'VCCLCompilerTool': {\n"; |
| 290 | 256 |
| 291 // GYP always uses the VC optimization flag to add a /O? on Visual Studio. | 257 // GYP always uses the VC optimization flag to add a /O? on Visual Studio. |
| 292 // This can produce duplicate values. So look up the GYP value corresponding | 258 // This can produce duplicate values. So look up the GYP value corresponding |
| 293 // to the flags used, and set the same one. | 259 // to the flags used, and set the same one. |
| 294 std::string optimization = GetVCOptimization(&flags.cflags); | 260 std::string optimization = GetVCOptimization(&flags.cflags); |
| 295 WriteNamedArray(out_, "AdditionalOptions", flags.cflags, | 261 WriteNamedArray("AdditionalOptions", flags.cflags, indent + kExtraIndent * 2); |
| 296 indent + kExtraIndent * 2); | |
| 297 // TODO(brettw) cflags_c and cflags_cc! | 262 // TODO(brettw) cflags_c and cflags_cc! |
| 298 Indent(indent + kExtraIndent * 2) << "'Optimization': " | 263 Indent(indent + kExtraIndent * 2) << "'Optimization': " |
| 299 << optimization << ",\n"; | 264 << optimization << ",\n"; |
| 300 Indent(indent + kExtraIndent) << "},\n"; | 265 Indent(indent + kExtraIndent) << "},\n"; |
| 301 | 266 |
| 302 // Linker tool stuff. | 267 // Linker tool stuff. |
| 303 Indent(indent + kExtraIndent) << "'VCLinkerTool': {\n"; | 268 Indent(indent + kExtraIndent) << "'VCLinkerTool': {\n"; |
| 304 | 269 |
| 305 // ...Library dirs. | 270 // ...Library dirs. |
| 306 EscapeOptions escape_options; | 271 EscapeOptions escape_options; |
| 307 escape_options.mode = ESCAPE_JSON; | 272 escape_options.mode = ESCAPE_JSON; |
| 308 if (!flags.lib_dirs.empty()) { | 273 if (!flags.lib_dirs.empty()) { |
| 309 Indent(indent + kExtraIndent * 2) << "'AdditionalLibraryDirectories': ["; | 274 Indent(indent + kExtraIndent * 2) << "'AdditionalLibraryDirectories': ["; |
| 310 for (size_t i = 0; i < flags.lib_dirs.size(); i++) { | 275 for (size_t i = 0; i < flags.lib_dirs.size(); i++) { |
| 311 out_ << " '"; | 276 out_ << " '"; |
| 312 EscapeStringToStream(out_, | 277 EscapeStringToStream(out_, |
| 313 helper_.GetDirReference(flags.lib_dirs[i], false), | 278 helper_.GetDirReference(flags.lib_dirs[i], false), |
| 314 escape_options); | 279 escape_options); |
| 315 out_ << "',"; | 280 out_ << "',"; |
| 316 } | 281 } |
| 317 out_ << " ],\n"; | 282 out_ << " ],\n"; |
| 318 } | 283 } |
| 319 | 284 |
| 320 // ...Libraries. | 285 // ...Libraries. |
| 321 WriteNamedArray(out_, "AdditionalDependencies", flags.libs, | 286 WriteNamedArray("AdditionalDependencies", flags.libs, |
| 322 indent + kExtraIndent * 2); | 287 indent + kExtraIndent * 2); |
| 323 | 288 |
| 324 // ...LD flags. | 289 // ...LD flags. |
| 325 // TODO(brettw) EnableUAC defaults to on and needs to be set. Also | 290 // TODO(brettw) EnableUAC defaults to on and needs to be set. Also |
| 326 // UACExecutionLevel and UACUIAccess depends on that and defaults to 0/false. | 291 // UACExecutionLevel and UACUIAccess depends on that and defaults to 0/false. |
| 327 WriteNamedArray(out_, "AdditionalOptions", flags.ldflags, 14); | 292 WriteNamedArray("AdditionalOptions", flags.ldflags, 14); |
| 328 Indent(indent + kExtraIndent) << "},\n"; | 293 Indent(indent + kExtraIndent) << "},\n"; |
| 329 Indent(indent) << "},\n"; | 294 Indent(indent) << "},\n"; |
| 330 } | 295 } |
| 331 | 296 |
| 332 void GypBinaryTargetWriter::WriteMacFlags(Flags& flags, int indent) { | 297 void GypBinaryTargetWriter::WriteMacFlags(Flags& flags, int indent) { |
| 333 WriteNamedArray(out_, "defines", flags.defines, indent); | 298 WriteNamedArray("defines", flags.defines, indent); |
| 334 WriteIncludeDirs(flags, indent); | 299 WriteIncludeDirs(flags, indent); |
| 335 | 300 |
| 336 // Libraries and library directories. | 301 // Libraries and library directories. |
| 337 EscapeOptions escape_options; | 302 EscapeOptions escape_options; |
| 338 escape_options.mode = ESCAPE_JSON; | 303 escape_options.mode = ESCAPE_JSON; |
| 339 if (!flags.lib_dirs.empty()) { | 304 if (!flags.lib_dirs.empty()) { |
| 340 Indent(indent + kExtraIndent) << "'library_dirs': ["; | 305 Indent(indent + kExtraIndent) << "'library_dirs': ["; |
| 341 for (size_t i = 0; i < flags.lib_dirs.size(); i++) { | 306 for (size_t i = 0; i < flags.lib_dirs.size(); i++) { |
| 342 out_ << " '"; | 307 out_ << " '"; |
| 343 EscapeStringToStream(out_, | 308 EscapeStringToStream(out_, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 Indent(indent + kExtraIndent) << "'OTHER_CPLUSPLUSFLAGS': ["; | 340 Indent(indent + kExtraIndent) << "'OTHER_CPLUSPLUSFLAGS': ["; |
| 376 WriteArrayValues(out_, flags.cflags); | 341 WriteArrayValues(out_, flags.cflags); |
| 377 WriteArrayValues(out_, flags.cflags_cc); | 342 WriteArrayValues(out_, flags.cflags_cc); |
| 378 WriteArrayValues(out_, flags.cflags_objcc); | 343 WriteArrayValues(out_, flags.cflags_objcc); |
| 379 out_ << " ],\n"; | 344 out_ << " ],\n"; |
| 380 } | 345 } |
| 381 | 346 |
| 382 // Ld flags. Don't write these for static libraries. Otherwise, they'll be | 347 // Ld flags. Don't write these for static libraries. Otherwise, they'll be |
| 383 // passed to the library tool which doesn't expect it (the toolchain does | 348 // passed to the library tool which doesn't expect it (the toolchain does |
| 384 // not use ldflags so these are ignored in the normal build). | 349 // not use ldflags so these are ignored in the normal build). |
| 385 if (target_->output_type() != Target::STATIC_LIBRARY) { | 350 if (target_->output_type() != Target::STATIC_LIBRARY) |
| 386 WriteNamedArray(out_, "OTHER_LDFLAGS", flags.ldflags, | 351 WriteNamedArray("OTHER_LDFLAGS", flags.ldflags, indent + kExtraIndent); |
| 387 indent + kExtraIndent); | |
| 388 } | |
| 389 | 352 |
| 390 base::FilePath clang_path = | 353 base::FilePath clang_path = |
| 391 target_->settings()->build_settings()->GetFullPath(SourceFile( | 354 target_->settings()->build_settings()->GetFullPath(SourceFile( |
| 392 "//third_party/llvm-build/Release+Asserts/bin/clang")); | 355 "//third_party/llvm-build/Release+Asserts/bin/clang")); |
| 393 base::FilePath clang_pp_path = | 356 base::FilePath clang_pp_path = |
| 394 target_->settings()->build_settings()->GetFullPath(SourceFile( | 357 target_->settings()->build_settings()->GetFullPath(SourceFile( |
| 395 "//third_party/llvm-build/Release+Asserts/bin/clang++")); | 358 "//third_party/llvm-build/Release+Asserts/bin/clang++")); |
| 396 | 359 |
| 397 Indent(indent) << "'CC': '" << FilePathToUTF8(clang_path) << "',\n"; | 360 Indent(indent) << "'CC': '" << FilePathToUTF8(clang_path) << "',\n"; |
| 398 Indent(indent) << "'LDPLUSPLUS': '" | 361 Indent(indent) << "'LDPLUSPLUS': '" |
| 399 << FilePathToUTF8(clang_pp_path) << "',\n"; | 362 << FilePathToUTF8(clang_pp_path) << "',\n"; |
| 400 | 363 |
| 401 Indent(indent) << "},\n"; | 364 Indent(indent) << "},\n"; |
| 402 } | 365 } |
| 403 | 366 |
| 404 void GypBinaryTargetWriter::WriteLinuxFlagsForTarget(const Target* target, | 367 void GypBinaryTargetWriter::WriteLinuxFlagsForTarget(const Target* target, |
| 405 int indent) { | 368 int indent) { |
| 406 Flags flags(FlagsFromTarget(target)); | 369 Flags flags(FlagsFromTarget(target)); |
| 407 WriteLinuxFlags(flags, indent); | 370 WriteLinuxFlags(flags, indent); |
| 408 } | 371 } |
| 409 | 372 |
| 410 void GypBinaryTargetWriter::WriteLinuxFlags(const Flags& flags, int indent) { | 373 void GypBinaryTargetWriter::WriteLinuxFlags(const Flags& flags, int indent) { |
| 411 WriteIncludeDirs(flags, indent); | 374 WriteIncludeDirs(flags, indent); |
| 412 WriteNamedArray(out_, "defines", flags.defines, indent); | 375 WriteNamedArray("defines", flags.defines, indent); |
| 413 WriteNamedArray(out_, "cflags", flags.cflags, indent); | 376 WriteNamedArray("cflags", flags.cflags, indent); |
| 414 WriteNamedArray(out_, "cflags_c", flags.cflags_c, indent); | 377 WriteNamedArray("cflags_c", flags.cflags_c, indent); |
| 415 WriteNamedArray(out_, "cflags_cc", flags.cflags_cc, indent); | 378 WriteNamedArray("cflags_cc", flags.cflags_cc, indent); |
| 416 WriteNamedArray(out_, "cflags_objc", flags.cflags_objc, indent); | 379 WriteNamedArray("cflags_objc", flags.cflags_objc, indent); |
| 417 WriteNamedArray(out_, "cflags_objcc", flags.cflags_objcc, indent); | 380 WriteNamedArray("cflags_objcc", flags.cflags_objcc, indent); |
| 418 | 381 |
| 419 // Put libraries and library directories in with ldflags. | 382 // Put libraries and library directories in with ldflags. |
| 420 Indent(indent) << "'ldflags': ["; \ | 383 Indent(indent) << "'ldflags': ["; \ |
| 421 WriteArrayValues(out_, flags.ldflags); | 384 WriteArrayValues(out_, flags.ldflags); |
| 422 | 385 |
| 423 EscapeOptions escape_options; | 386 EscapeOptions escape_options; |
| 424 escape_options.mode = ESCAPE_JSON; | 387 escape_options.mode = ESCAPE_JSON; |
| 425 for (size_t i = 0; i < flags.lib_dirs.size(); i++) { | 388 for (size_t i = 0; i < flags.lib_dirs.size(); i++) { |
| 426 out_ << " '-L"; | 389 out_ << " '-L"; |
| 427 EscapeStringToStream(out_, | 390 EscapeStringToStream(out_, |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 EXTRACT(std::string, cflags_objc); | 529 EXTRACT(std::string, cflags_objc); |
| 567 EXTRACT(std::string, cflags_objcc); | 530 EXTRACT(std::string, cflags_objcc); |
| 568 EXTRACT(std::string, ldflags); | 531 EXTRACT(std::string, ldflags); |
| 569 EXTRACT(SourceDir, lib_dirs); | 532 EXTRACT(SourceDir, lib_dirs); |
| 570 EXTRACT(std::string, libs); | 533 EXTRACT(std::string, libs); |
| 571 | 534 |
| 572 #undef EXTRACT | 535 #undef EXTRACT |
| 573 | 536 |
| 574 return ret; | 537 return ret; |
| 575 } | 538 } |
| 539 |
| 540 void GypBinaryTargetWriter::WriteNamedArray( |
| 541 const char* name, |
| 542 const std::vector<std::string>& values, |
| 543 int indent) { |
| 544 if (values.empty()) |
| 545 return; |
| 546 |
| 547 EscapeOptions options; |
| 548 options.mode = ESCAPE_JSON; |
| 549 |
| 550 Indent(indent) << "'" << name << "': ["; |
| 551 WriteArrayValues(out_, values); |
| 552 out_ << " ],\n"; |
| 553 } |
| 554 |
| OLD | NEW |