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

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

Issue 206813002: Remove GN GYP generator. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 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/gyp_binary_target_writer.h ('k') | tools/gn/gyp_binary_target_writer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "tools/gn/gyp_binary_target_writer.h"
6
7 #include <set>
8
9 #include "base/logging.h"
10 #include "base/strings/string_util.h"
11 #include "tools/gn/builder_record.h"
12 #include "tools/gn/config_values_extractors.h"
13 #include "tools/gn/err.h"
14 #include "tools/gn/escape.h"
15 #include "tools/gn/filesystem_utils.h"
16 #include "tools/gn/settings.h"
17 #include "tools/gn/target.h"
18
19 namespace {
20
21 // This functor is used to capture the output of RecursiveTargetConfigToStream
22 // in an vector.
23 template<typename T>
24 struct Accumulator {
25 Accumulator(std::vector<T>* result_in) : result(result_in) {}
26
27 void operator()(const T& s, std::ostream&) const {
28 result->push_back(s);
29 }
30
31 std::vector<T>* result;
32 };
33
34 // Writes the given array values. The array should already be declared with the
35 // opening "[" written to the output. The function will not write the
36 // terminating "]" either.
37 void WriteArrayValues(std::ostream& out,
38 const std::vector<std::string>& values) {
39 EscapeOptions options;
40 options.mode = ESCAPE_JSON;
41 for (size_t i = 0; i < values.size(); i++) {
42 out << " '";
43 EscapeStringToStream(out, values[i], options);
44 out << "',";
45 }
46 }
47
48 // Returns the value from the already-filled in cflags_* for the optimization
49 // level to set in the GYP file. Additionally, this removes the flag from the
50 // given vector so we don't get duplicates.
51 std::string GetVCOptimization(std::vector<std::string>* cflags) {
52 // Searches for the "/O?" option and returns the corresponding GYP value.
53 for (size_t i = 0; i < cflags->size(); i++) {
54 const std::string& cur = (*cflags)[i];
55 if (cur.size() == 3 && cur[0] == '/' && cur[1] == 'O') {
56 char level = cur[2];
57 cflags->erase(cflags->begin() + i); // Invalidates |cur|!
58 switch (level) {
59 case 'd': return "'0'";
60 case '1': return "'1'";
61 case '2': return "'2'";
62 case 'x': return "'3'";
63 default: return "'2'";
64 }
65 }
66 }
67 return "'2'"; // Default value.
68 }
69
70 // Returns the value from the already-filled in cflags for the processor
71 // architecture to set in the GYP file. Additionally, this removes the flag
72 // from the given vector so we don't get duplicates.
73 std::string GetMacArch(std::vector<std::string>* cflags) {
74 // Searches for the "-arch" option and returns the corresponding GYP value.
75 for (size_t i = 0; i < cflags->size(); i++) {
76 const std::string& cur = (*cflags)[i];
77 if (cur == "-arch") {
78 // This is the first part of a list with ["-arch", "i386"], return the
79 // following item, and delete both of them.
80 if (i < cflags->size() - 1) {
81 std::string ret = (*cflags)[i + 1];
82 cflags->erase(cflags->begin() + i, cflags->begin() + i + 2);
83 return ret;
84 }
85 } else if (StartsWithASCII(cur, "-arch ", true)) {
86 // The arch was passed as one GN string value, e.g. "-arch i386". Return
87 // the stuff following the space and delete the item.
88 std::string ret = cur.substr(6);
89 cflags->erase(cflags->begin() + i);
90 return ret;
91 }
92 }
93 return std::string();
94 }
95
96 // Searches for -miphoneos-version-min, returns the resulting value, and
97 // removes it from the list. Returns the empty string if it's not found.
98 std::string GetIPhoneVersionMin(std::vector<std::string>* cflags) {
99 // Searches for the "-arch" option and returns the corresponding GYP value.
100 const char prefix[] = "-miphoneos-version-min=";
101 for (size_t i = 0; i < cflags->size(); i++) {
102 const std::string& cur = (*cflags)[i];
103 if (StartsWithASCII(cur, prefix, true)) {
104 std::string result = cur.substr(arraysize(prefix) - 1);
105 cflags->erase(cflags->begin() + i);
106 return result;
107 }
108 }
109 return std::string();
110 }
111
112 // Finds all values from the given getter from all configs in the given list,
113 // and adds them to the given result vector.
114 template<typename T>
115 void FillConfigListValues(
116 const LabelConfigVector& configs,
117 const std::vector<T>& (ConfigValues::* getter)() const,
118 std::vector<T>* result) {
119 for (size_t config_i = 0; config_i < configs.size(); config_i++) {
120 const std::vector<T>& values =
121 (configs[config_i].ptr->config_values().*getter)();
122 for (size_t val_i = 0; val_i < values.size(); val_i++)
123 result->push_back(values[val_i]);
124 }
125 }
126
127 bool IsClang(const Target* target) {
128 const Value* is_clang =
129 target->settings()->base_config()->GetValue("is_clang");
130 return is_clang && is_clang->type() == Value::BOOLEAN &&
131 is_clang->boolean_value();
132 }
133
134 bool IsIOS(const Target* target) {
135 const Value* is_ios = target->settings()->base_config()->GetValue("is_ios");
136 return is_ios && is_ios->type() == Value::BOOLEAN && is_ios->boolean_value();
137 }
138
139 // Returns true if the current target is an iOS simulator build.
140 bool IsIOSSimulator(const std::vector<std::string>& cflags) {
141 // Search for the sysroot flag. We expect one flag to be the
142 // switch, and the following one to be the value.
143 const char sysroot[] = "-isysroot";
144 for (size_t i = 0; i < cflags.size(); i++) {
145 const std::string& cur = cflags[i];
146 if (cur == sysroot) {
147 if (i == cflags.size() - 1)
148 return false; // No following value.
149
150 // The argument is a file path, we check the prefix of the file name.
151 base::FilePath path(UTF8ToFilePath(cflags[i + 1]));
152 std::string path_file_part = FilePathToUTF8(path.BaseName());
153 return StartsWithASCII(path_file_part, "iphonesimulator", false);
154 }
155 }
156 return false;
157 }
158
159 } // namespace
160
161 GypBinaryTargetWriter::Flags::Flags() {}
162 GypBinaryTargetWriter::Flags::~Flags() {}
163
164 GypBinaryTargetWriter::GypBinaryTargetWriter(const TargetGroup& group,
165 const Toolchain* debug_toolchain,
166 const SourceDir& gyp_dir,
167 std::ostream& out)
168 : GypTargetWriter(group.get()->item()->AsTarget(), debug_toolchain,
169 gyp_dir, out),
170 group_(group) {
171 }
172
173 GypBinaryTargetWriter::~GypBinaryTargetWriter() {
174 }
175
176 void GypBinaryTargetWriter::Run() {
177 int indent = 4;
178
179 Indent(indent) << "{\n";
180
181 WriteName(indent + kExtraIndent);
182 WriteType(indent + kExtraIndent);
183
184 if (target_->settings()->IsLinux())
185 WriteLinuxConfiguration(indent + kExtraIndent);
186 else if (target_->settings()->IsWin())
187 WriteVCConfiguration(indent + kExtraIndent);
188 else if (target_->settings()->IsMac())
189 WriteMacConfiguration(indent + kExtraIndent);
190 WriteDirectDependentSettings(indent + kExtraIndent);
191 WriteAllDependentSettings(indent + kExtraIndent);
192
193 Indent(indent) << "},\n";
194 }
195
196 void GypBinaryTargetWriter::WriteName(int indent) {
197 std::string name = helper_.GetNameForTarget(target_);
198 Indent(indent) << "'target_name': '" << name << "',\n";
199
200 std::string product_name;
201 if (target_->output_name().empty())
202 product_name = target_->label().name();
203 else
204 product_name = name;
205
206 // TODO(brettw) GN knows not to prefix targets starting with "lib" with
207 // another "lib" on Linux, but GYP doesn't. We need to rename applicable
208 // targets here.
209
210 Indent(indent) << "'product_name': '" << product_name << "',\n";
211
212 std::string product_extension = target_->output_extension();
213 if (!product_extension.empty())
214 Indent(indent) << "'product_extension': '" << product_extension << "',\n";
215 }
216
217 void GypBinaryTargetWriter::WriteType(int indent) {
218 Indent(indent) << "'type': ";
219 switch (target_->output_type()) {
220 case Target::EXECUTABLE:
221 out_ << "'executable',\n";
222 break;
223 case Target::STATIC_LIBRARY:
224 out_ << "'static_library',\n";
225 break;
226 case Target::SHARED_LIBRARY:
227 out_ << "'shared_library',\n";
228 break;
229 case Target::SOURCE_SET:
230 out_ << "'static_library',\n"; // TODO(brettw) fixme.
231 break;
232 default:
233 NOTREACHED();
234 }
235
236 if (target_->hard_dep())
237 Indent(indent) << "'hard_dependency': 1,\n";
238
239 // Write out the toolsets depending on whether there is a host build. If no
240 // toolset is specified, GYP assumes a target build.
241 if (group_.debug && group_.host_debug)
242 Indent(indent) << "'toolsets': ['target', 'host'],\n";
243 else if (group_.host_debug)
244 Indent(indent) << "'toolsets': ['host'],\n";
245 }
246
247 void GypBinaryTargetWriter::WriteVCConfiguration(int indent) {
248 Indent(indent) << "'configurations': {\n";
249
250 Indent(indent + kExtraIndent) << "'Debug': {\n";
251 Indent(indent + kExtraIndent * 2) <<
252 "'msvs_configuration_platform': 'Win32',\n";
253 Flags debug_flags(FlagsFromTarget(group_.debug->item()->AsTarget()));
254 WriteVCFlags(debug_flags, indent + kExtraIndent * 2);
255 Indent(indent + kExtraIndent) << "},\n";
256
257 Indent(indent + kExtraIndent) << "'Release': {\n";
258 Indent(indent + kExtraIndent * 2) <<
259 "'msvs_configuration_platform': 'Win32',\n";
260 Flags release_flags(FlagsFromTarget(group_.release->item()->AsTarget()));
261 WriteVCFlags(release_flags, indent + kExtraIndent * 2);
262 Indent(indent + kExtraIndent) << "},\n";
263
264 // Note that we always need Debug_x64 and Release_x64 defined or GYP will get
265 // confused, but we ca leave them empty if there's no 64-bit target.
266 Indent(indent + kExtraIndent) << "'Debug_x64': {\n";
267 if (group_.debug64) {
268 Indent(indent + kExtraIndent * 2) <<
269 "'msvs_configuration_platform': 'x64',\n";
270 Flags flags(FlagsFromTarget(group_.debug64->item()->AsTarget()));
271 WriteVCFlags(flags, indent + kExtraIndent * 2);
272 }
273 Indent(indent + kExtraIndent) << "},\n";
274
275 Indent(indent + kExtraIndent) << "'Release_x64': {\n";
276 if (group_.release64) {
277 Indent(indent + kExtraIndent * 2) <<
278 "'msvs_configuration_platform': 'x64',\n";
279 Flags flags(FlagsFromTarget(group_.release64->item()->AsTarget()));
280 WriteVCFlags(flags, indent + kExtraIndent * 2);
281 }
282 Indent(indent + kExtraIndent) << "},\n";
283
284 Indent(indent) << "},\n";
285
286 WriteSources(target_, indent);
287 WriteDeps(target_, indent);
288 }
289
290 void GypBinaryTargetWriter::WriteLinuxConfiguration(int indent) {
291 // The Linux stuff works differently. On Linux we support cross-compiles and
292 // all ninja generators know to look for target conditions. Other platforms'
293 // generators don't all do this, so we can't have the same GYP structure.
294 Indent(indent) << "'target_conditions': [\n";
295 // The host toolset is configured for the current computer, we will only have
296 // this when doing cross-compiles.
297 if (group_.host_debug && group_.host_release) {
298 Indent(indent + kExtraIndent) << "['_toolset == \"host\"', {\n";
299 Indent(indent + kExtraIndent * 2) << "'configurations': {\n";
300 Indent(indent + kExtraIndent * 3) << "'Debug': {\n";
301 WriteLinuxFlagsForTarget(group_.host_debug->item()->AsTarget(),
302 indent + kExtraIndent * 4);
303 Indent(indent + kExtraIndent * 3) << "},\n";
304 Indent(indent + kExtraIndent * 3) << "'Release': {\n";
305 WriteLinuxFlagsForTarget(group_.host_release->item()->AsTarget(),
306 indent + kExtraIndent * 4);
307 Indent(indent + kExtraIndent * 3) << "},\n";
308 Indent(indent + kExtraIndent * 2) << "}\n";
309
310 // The sources are per-toolset but shared between debug & release.
311 WriteSources(group_.host_debug->item()->AsTarget(),
312 indent + kExtraIndent * 2);
313
314 Indent(indent + kExtraIndent) << "],\n";
315 }
316
317 // The target toolset is the "regular" one.
318 Indent(indent + kExtraIndent) << "['_toolset == \"target\"', {\n";
319 Indent(indent + kExtraIndent * 2) << "'configurations': {\n";
320 Indent(indent + kExtraIndent * 3) << "'Debug': {\n";
321 WriteLinuxFlagsForTarget(group_.debug->item()->AsTarget(),
322 indent + kExtraIndent * 4);
323 Indent(indent + kExtraIndent * 3) << "},\n";
324 Indent(indent + kExtraIndent * 3) << "'Release': {\n";
325 WriteLinuxFlagsForTarget(group_.release->item()->AsTarget(),
326 indent + kExtraIndent * 4);
327 Indent(indent + kExtraIndent * 3) << "},\n";
328 Indent(indent + kExtraIndent * 2) << "},\n";
329
330 WriteSources(target_, indent + kExtraIndent * 2);
331
332 Indent(indent + kExtraIndent) << "},],\n";
333 Indent(indent) << "],\n";
334
335 // Deps in GYP can not vary based on the toolset.
336 WriteDeps(target_, indent);
337 }
338
339 void GypBinaryTargetWriter::WriteMacConfiguration(int indent) {
340 // The Mac flags are parameterized by the GYP generator (Ninja vs. XCode).
341 const char kNinjaGeneratorCondition[] =
342 "'conditions': [['\"<(GENERATOR)\"==\"ninja\"', {\n";
343 const char kNinjaGeneratorElse[] = "}, {\n";
344 const char kNinjaGeneratorEnd[] = "}]],\n";
345
346 Indent(indent) << "'configurations': {\n";
347
348 // Debug.
349 Indent(indent + kExtraIndent) << "'Debug': {\n";
350 Indent(indent + kExtraIndent * 2) << kNinjaGeneratorCondition;
351 {
352 // Ninja generator.
353 WriteMacTargetAndHostFlags(group_.debug, group_.host_debug,
354 indent + kExtraIndent * 3);
355 }
356 Indent(indent + kExtraIndent * 2) << kNinjaGeneratorElse;
357 if (group_.xcode_debug) {
358 // XCode generator.
359 WriteMacTargetAndHostFlags(group_.xcode_debug, group_.xcode_host_debug,
360 indent + kExtraIndent * 3);
361 }
362 Indent(indent + kExtraIndent * 2) << kNinjaGeneratorEnd;
363 Indent(indent + kExtraIndent) << "},\n";
364
365 // Release.
366 Indent(indent + kExtraIndent) << "'Release': {\n";
367 Indent(indent + kExtraIndent * 2) << kNinjaGeneratorCondition;
368 {
369 // Ninja generator.
370 WriteMacTargetAndHostFlags(group_.release, group_.host_release,
371 indent + kExtraIndent * 3);
372 }
373 Indent(indent + kExtraIndent * 2) << kNinjaGeneratorElse;
374 if (group_.xcode_release) {
375 // XCode generator.
376 WriteMacTargetAndHostFlags(group_.xcode_release, group_.xcode_host_release,
377 indent + kExtraIndent * 3);
378 }
379 Indent(indent + kExtraIndent * 2) << kNinjaGeneratorEnd;
380 Indent(indent + kExtraIndent) << "},\n";
381
382 Indent(indent) << "},\n";
383
384 WriteSources(target_, indent);
385 WriteDeps(target_, indent);
386 }
387
388 void GypBinaryTargetWriter::WriteVCFlags(Flags& flags, int indent) {
389 // Defines and includes go outside of the msvs settings.
390 WriteNamedArray("defines", flags.defines, indent);
391 WriteIncludeDirs(flags, indent);
392
393 // C flags.
394 Indent(indent) << "'msvs_settings': {\n";
395 Indent(indent + kExtraIndent) << "'VCCLCompilerTool': {\n";
396
397 // GYP always uses the VC optimization flag to add a /O? on Visual Studio.
398 // This can produce duplicate values. So look up the GYP value corresponding
399 // to the flags used, and set the same one.
400 std::string optimization = GetVCOptimization(&flags.cflags);
401 WriteNamedArray("AdditionalOptions", flags.cflags, indent + kExtraIndent * 2);
402 // TODO(brettw) cflags_c and cflags_cc!
403 Indent(indent + kExtraIndent * 2) << "'Optimization': "
404 << optimization << ",\n";
405 Indent(indent + kExtraIndent) << "},\n";
406
407 // Linker tool stuff.
408 Indent(indent + kExtraIndent) << "'VCLinkerTool': {\n";
409
410 // ...Library dirs.
411 EscapeOptions escape_options;
412 escape_options.mode = ESCAPE_JSON;
413 if (!flags.lib_dirs.empty()) {
414 Indent(indent + kExtraIndent * 2) << "'AdditionalLibraryDirectories': [";
415 for (size_t i = 0; i < flags.lib_dirs.size(); i++) {
416 out_ << " '";
417 EscapeStringToStream(out_,
418 helper_.GetDirReference(flags.lib_dirs[i], false),
419 escape_options);
420 out_ << "',";
421 }
422 out_ << " ],\n";
423 }
424
425 // ...Libraries.
426 WriteNamedArray("AdditionalDependencies", flags.libs,
427 indent + kExtraIndent * 2);
428
429 // ...LD flags.
430 // TODO(brettw) EnableUAC defaults to on and needs to be set. Also
431 // UACExecutionLevel and UACUIAccess depends on that and defaults to 0/false.
432 WriteNamedArray("AdditionalOptions", flags.ldflags, 14);
433 Indent(indent + kExtraIndent) << "},\n";
434 Indent(indent) << "},\n";
435 }
436
437 void GypBinaryTargetWriter::WriteMacFlags(const Target* target,
438 Flags& flags,
439 int indent) {
440 WriteNamedArray("defines", flags.defines, indent);
441 WriteIncludeDirs(flags, indent);
442
443 // Libraries and library directories.
444 EscapeOptions escape_options;
445 escape_options.mode = ESCAPE_JSON;
446 if (!flags.lib_dirs.empty()) {
447 Indent(indent + kExtraIndent) << "'library_dirs': [";
448 for (size_t i = 0; i < flags.lib_dirs.size(); i++) {
449 out_ << " '";
450 EscapeStringToStream(out_,
451 helper_.GetDirReference(flags.lib_dirs[i], false),
452 escape_options);
453 out_ << "',";
454 }
455 out_ << " ],\n";
456 }
457 if (!flags.libs.empty()) {
458 Indent(indent) << "'link_settings': {\n";
459 Indent(indent + kExtraIndent) << "'libraries': [";
460 for (size_t i = 0; i < flags.libs.size(); i++) {
461 out_ << " '-l";
462 EscapeStringToStream(out_, flags.libs[i], escape_options);
463 out_ << "',";
464 }
465 out_ << " ],\n";
466 Indent(indent) << "},\n";
467 }
468
469 Indent(indent) << "'xcode_settings': {\n";
470
471 // Architecture. GYP reads this value and uses it to generate the -arch
472 // flag, so we always want to remove it from the cflags (which is a side
473 // effect of what GetMacArch does), even in cases where we don't use the
474 // value (in the iOS arm below).
475 std::string arch = GetMacArch(&flags.cflags);
476 if (IsIOS(target)) {
477 // When writing an iOS "target" (not host) target, we set VALID_ARCHS
478 // instead of ARCHS and always use this hardcoded value. This matches the
479 // GYP build.
480 Indent(indent + kExtraIndent) << "'VALID_ARCHS': ['armv7', 'i386'],\n";
481
482 // Tell XCode to target both iPhone and iPad. GN has no such concept.
483 Indent(indent + kExtraIndent) << "'TARGETED_DEVICE_FAMILY': '1,2',\n";
484
485 if (IsIOSSimulator(flags.cflags)) {
486 Indent(indent + kExtraIndent) << "'SDKROOT': 'iphonesimulator',\n";
487 } else {
488 Indent(indent + kExtraIndent) << "'SDKROOT': 'iphoneos',\n";
489 std::string min_ver = GetIPhoneVersionMin(&flags.cflags);
490 if (!min_ver.empty()) {
491 Indent(indent + kExtraIndent) << "'IPHONEOS_DEPLOYMENT_TARGET': '"
492 << min_ver << "',\n";
493 }
494 }
495 } else {
496 // When doing regular Mac and "host" iOS (which look like regular Mac)
497 // builds, we can set the ARCHS value to what's specified in the build.
498 if (arch == "i386")
499 Indent(indent + kExtraIndent) << "'ARCHS': [ 'i386' ],\n";
500 else if (arch == "x86_64")
501 Indent(indent + kExtraIndent) << "'ARCHS': [ 'x86_64' ],\n";
502 }
503
504 // C/C++ flags.
505 if (!flags.cflags.empty() || !flags.cflags_c.empty() ||
506 !flags.cflags_objc.empty()) {
507 Indent(indent + kExtraIndent) << "'OTHER_CFLAGS': [";
508 WriteArrayValues(out_, flags.cflags);
509 WriteArrayValues(out_, flags.cflags_c);
510 WriteArrayValues(out_, flags.cflags_objc);
511 out_ << " ],\n";
512 }
513 if (!flags.cflags.empty() || !flags.cflags_cc.empty() ||
514 !flags.cflags_objcc.empty()) {
515 Indent(indent + kExtraIndent) << "'OTHER_CPLUSPLUSFLAGS': [";
516 WriteArrayValues(out_, flags.cflags);
517 WriteArrayValues(out_, flags.cflags_cc);
518 WriteArrayValues(out_, flags.cflags_objcc);
519 out_ << " ],\n";
520 }
521
522 // Ld flags. Don't write these for static libraries. Otherwise, they'll be
523 // passed to the library tool which doesn't expect it (the toolchain does
524 // not use ldflags so these are ignored in the normal build).
525 if (target->output_type() != Target::STATIC_LIBRARY)
526 WriteNamedArray("OTHER_LDFLAGS", flags.ldflags, indent + kExtraIndent);
527
528 // Write the compiler that XCode should use. When we're using clang, we want
529 // the custom one, otherwise don't add this and the default compiler will be
530 // used.
531 //
532 // TODO(brettw) this is a hack. We could add a way for the GN build to set
533 // these values but as far as I can see this is the only use for them, so
534 // currently we manually check the build config's is_clang value.
535 if (IsClang(target)) {
536 base::FilePath clang_path =
537 target_->settings()->build_settings()->GetFullPath(SourceFile(
538 "//third_party/llvm-build/Release+Asserts/bin/clang"));
539 base::FilePath clang_pp_path =
540 target_->settings()->build_settings()->GetFullPath(SourceFile(
541 "//third_party/llvm-build/Release+Asserts/bin/clang++"));
542
543 Indent(indent + kExtraIndent)
544 << "'CC': '" << FilePathToUTF8(clang_path) << "',\n";
545 Indent(indent + kExtraIndent)
546 << "'LDPLUSPLUS': '" << FilePathToUTF8(clang_pp_path) << "',\n";
547 }
548
549 Indent(indent) << "},\n";
550 }
551
552 void GypBinaryTargetWriter::WriteLinuxFlagsForTarget(const Target* target,
553 int indent) {
554 Flags flags(FlagsFromTarget(target));
555 WriteLinuxFlags(flags, indent);
556 }
557
558 void GypBinaryTargetWriter::WriteLinuxFlags(const Flags& flags, int indent) {
559 WriteIncludeDirs(flags, indent);
560 WriteNamedArray("defines", flags.defines, indent);
561 WriteNamedArray("cflags", flags.cflags, indent);
562 WriteNamedArray("cflags_c", flags.cflags_c, indent);
563 WriteNamedArray("cflags_cc", flags.cflags_cc, indent);
564 WriteNamedArray("cflags_objc", flags.cflags_objc, indent);
565 WriteNamedArray("cflags_objcc", flags.cflags_objcc, indent);
566
567 // Put libraries and library directories in with ldflags.
568 Indent(indent) << "'ldflags': ["; \
569 WriteArrayValues(out_, flags.ldflags);
570
571 EscapeOptions escape_options;
572 escape_options.mode = ESCAPE_JSON;
573 for (size_t i = 0; i < flags.lib_dirs.size(); i++) {
574 out_ << " '-L";
575 EscapeStringToStream(out_,
576 helper_.GetDirReference(flags.lib_dirs[i], false),
577 escape_options);
578 out_ << "',";
579 }
580
581 for (size_t i = 0; i < flags.libs.size(); i++) {
582 out_ << " '-l";
583 EscapeStringToStream(out_, flags.libs[i], escape_options);
584 out_ << "',";
585 }
586 out_ << " ],\n";
587 }
588
589 void GypBinaryTargetWriter::WriteMacTargetAndHostFlags(
590 const BuilderRecord* target,
591 const BuilderRecord* host,
592 int indent) {
593 // The Mac flags are sometimes (when cross-compiling) also parameterized on
594 // the toolset.
595 const char kToolsetTargetCondition[] =
596 "'target_conditions': [['_toolset==\"target\"', {\n";
597 const char kToolsetTargetElse[] = "}, {\n";
598 const char kToolsetTargetEnd[] = "}]],\n";
599
600 int extra_indent = 0;
601 if (host) {
602 // Write out the first part of the conditional.
603 Indent(indent) << kToolsetTargetCondition;
604 extra_indent = kExtraIndent;
605 }
606
607 // Always write the target flags (may or may not be inside a target
608 // conditional).
609 {
610 Flags flags(FlagsFromTarget(target->item()->AsTarget()));
611 WriteMacFlags(target->item()->AsTarget(), flags, indent + extra_indent);
612 }
613
614 // Now optionally write the host conditional arm.
615 if (host) {
616 Indent(indent) << kToolsetTargetElse;
617 Flags flags(FlagsFromTarget(host->item()->AsTarget()));
618 WriteMacFlags(host->item()->AsTarget(), flags, indent + kExtraIndent);
619 Indent(indent) << kToolsetTargetEnd;
620 }
621 }
622
623 void GypBinaryTargetWriter::WriteSources(const Target* target, int indent) {
624 Indent(indent) << "'sources': [\n";
625
626 const Target::FileList& sources = target->sources();
627 for (size_t i = 0; i < sources.size(); i++) {
628 const SourceFile& input_file = sources[i];
629 Indent(indent + kExtraIndent) << "'" << helper_.GetFileReference(input_file)
630 << "',\n";
631 }
632
633 Indent(indent) << "],\n";
634 }
635
636 void GypBinaryTargetWriter::WriteDeps(const Target* target, int indent) {
637 const LabelTargetVector& deps = target->deps();
638 if (deps.empty())
639 return;
640
641 EscapeOptions escape_options;
642 escape_options.mode = ESCAPE_JSON;
643
644 Indent(indent) << "'dependencies': [\n";
645 for (size_t i = 0; i < deps.size(); i++) {
646 Indent(indent + kExtraIndent) << "'";
647 EscapeStringToStream(out_, helper_.GetFullRefForTarget(deps[i].ptr),
648 escape_options);
649 out_ << "',\n";
650 }
651 Indent(indent) << "],\n";
652 }
653
654 void GypBinaryTargetWriter::WriteIncludeDirs(const Flags& flags, int indent) {
655 if (flags.include_dirs.empty())
656 return;
657
658 EscapeOptions options;
659 options.mode = ESCAPE_JSON;
660
661 Indent(indent) << "'include_dirs': [";
662 for (size_t i = 0; i < flags.include_dirs.size(); i++) {
663 out_ << " '";
664 EscapeStringToStream(out_,
665 helper_.GetDirReference(flags.include_dirs[i], false),
666 options);
667 out_ << "',";
668 }
669 out_ << " ],\n";
670 }
671
672 void GypBinaryTargetWriter::WriteDirectDependentSettings(int indent) {
673 if (target_->direct_dependent_configs().empty())
674 return;
675 Indent(indent) << "'direct_dependent_settings': {\n";
676
677 Flags flags(FlagsFromConfigList(target_->direct_dependent_configs()));
678 if (target_->settings()->IsLinux())
679 WriteLinuxFlags(flags, indent + kExtraIndent);
680 else if (target_->settings()->IsWin())
681 WriteVCFlags(flags, indent + kExtraIndent);
682 else if (target_->settings()->IsMac())
683 WriteMacFlags(target_, flags, indent + kExtraIndent);
684 Indent(indent) << "},\n";
685 }
686
687 void GypBinaryTargetWriter::WriteAllDependentSettings(int indent) {
688 if (target_->all_dependent_configs().empty())
689 return;
690 Indent(indent) << "'all_dependent_settings': {\n";
691
692 Flags flags(FlagsFromConfigList(target_->all_dependent_configs()));
693 if (target_->settings()->IsLinux())
694 WriteLinuxFlags(flags, indent + kExtraIndent);
695 else if (target_->settings()->IsWin())
696 WriteVCFlags(flags, indent + kExtraIndent);
697 else if (target_->settings()->IsMac())
698 WriteMacFlags(target_, flags, indent + kExtraIndent);
699 Indent(indent) << "},\n";
700 }
701
702 GypBinaryTargetWriter::Flags GypBinaryTargetWriter::FlagsFromTarget(
703 const Target* target) const {
704 Flags ret;
705
706 // Extracts a vector of the given type and name from the config values.
707 #define EXTRACT(type, name) \
708 { \
709 Accumulator<type> acc(&ret.name); \
710 RecursiveTargetConfigToStream<type>(target, &ConfigValues::name, \
711 acc, out_); \
712 }
713
714 EXTRACT(std::string, defines);
715 EXTRACT(SourceDir, include_dirs);
716 EXTRACT(std::string, cflags);
717 EXTRACT(std::string, cflags_c);
718 EXTRACT(std::string, cflags_cc);
719 EXTRACT(std::string, cflags_objc);
720 EXTRACT(std::string, cflags_objcc);
721 EXTRACT(std::string, ldflags);
722
723 #undef EXTRACT
724
725 const OrderedSet<SourceDir>& all_lib_dirs = target->all_lib_dirs();
726 for (size_t i = 0; i < all_lib_dirs.size(); i++)
727 ret.lib_dirs.push_back(all_lib_dirs[i]);
728
729 const OrderedSet<std::string> all_libs = target->all_libs();
730 for (size_t i = 0; i < all_libs.size(); i++)
731 ret.libs.push_back(all_libs[i]);
732
733 return ret;
734 }
735
736 GypBinaryTargetWriter::Flags GypBinaryTargetWriter::FlagsFromConfigList(
737 const LabelConfigVector& configs) const {
738 Flags ret;
739
740 #define EXTRACT(type, name) \
741 FillConfigListValues<type>(configs, &ConfigValues::name, &ret.name);
742
743 EXTRACT(std::string, defines);
744 EXTRACT(SourceDir, include_dirs);
745 EXTRACT(std::string, cflags);
746 EXTRACT(std::string, cflags_c);
747 EXTRACT(std::string, cflags_cc);
748 EXTRACT(std::string, cflags_objc);
749 EXTRACT(std::string, cflags_objcc);
750 EXTRACT(std::string, ldflags);
751 EXTRACT(SourceDir, lib_dirs);
752 EXTRACT(std::string, libs);
753
754 #undef EXTRACT
755
756 return ret;
757 }
758
759 void GypBinaryTargetWriter::WriteNamedArray(
760 const char* name,
761 const std::vector<std::string>& values,
762 int indent) {
763 if (values.empty())
764 return;
765
766 EscapeOptions options;
767 options.mode = ESCAPE_JSON;
768
769 Indent(indent) << "'" << name << "': [";
770 WriteArrayValues(out_, values);
771 out_ << " ],\n";
772 }
773
OLDNEW
« no previous file with comments | « tools/gn/gyp_binary_target_writer.h ('k') | tools/gn/gyp_binary_target_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698