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

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

Issue 1827103005: [GN] Add support for generating Xcode projects. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Improve comment about "assert(product_type != "")" Created 4 years, 7 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
« no previous file with comments | « tools/gn/xcode_object.h ('k') | tools/gn/xcode_writer.h » ('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 2016 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/xcode_object.h"
6
7 #include <iomanip>
8 #include <sstream>
9 #include <utility>
10
11 #include "base/files/file_path.h"
12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/strings/string_util.h"
15
16 // Helper methods -------------------------------------------------------------
17
18 namespace {
19 struct IndentRules {
20 bool one_line;
21 unsigned level;
22 };
23
24 std::vector<std::unique_ptr<PBXObject>> EmptyPBXObjectVector() {
25 return std::vector<std::unique_ptr<PBXObject>>();
26 }
27
28 bool CharNeedEscaping(char c) {
29 if (base::IsAsciiAlpha(c) || base::IsAsciiDigit(c))
30 return false;
31 if (c == '$' || c == '.' || c == '/' || c == '_')
32 return false;
33 return true;
34 }
35
36 bool StringNeedEscaping(const std::string& string) {
37 if (string.empty())
38 return true;
39 if (string.find("___") != std::string::npos)
40 return true;
41
42 for (char c : string) {
43 if (CharNeedEscaping(c))
44 return true;
45 }
46 return false;
47 }
48
49 std::string EncodeString(const std::string& string) {
50 if (!StringNeedEscaping(string))
51 return string;
52
53 std::stringstream buffer;
54 buffer << '"';
55 for (char c : string) {
56 if (c <= 31) {
57 switch (c) {
58 case '\a':
59 buffer << "\\a";
60 break;
61 case '\b':
62 buffer << "\\b";
63 break;
64 case '\t':
65 buffer << "\\t";
66 break;
67 case '\n':
68 case '\r':
69 buffer << "\\n";
70 break;
71 case '\v':
72 buffer << "\\v";
73 break;
74 case '\f':
75 buffer << "\\f";
76 break;
77 default:
78 buffer << std::hex << std::setw(4) << std::left << "\\U"
79 << static_cast<unsigned>(c);
80 break;
81 }
82 } else {
83 if (c == '"' || c == '\\')
84 buffer << '\\';
85 buffer << c;
86 }
87 }
88 buffer << '"';
89 return buffer.str();
90 }
91
92 const char* GetSourceType(const base::FilePath::StringType& ext) {
93 std::map<base::FilePath::StringType, const char*> extension_map = {
94 {FILE_PATH_LITERAL(".a"), "archive.ar"},
95 {FILE_PATH_LITERAL(".app"), "wrapper.application"},
96 {FILE_PATH_LITERAL(".bdic"), "file"},
97 {FILE_PATH_LITERAL(".bundle"), "wrapper.cfbundle"},
98 {FILE_PATH_LITERAL(".c"), "sourcecode.c.c"},
99 {FILE_PATH_LITERAL(".cc"), "sourcecode.cpp.cpp"},
100 {FILE_PATH_LITERAL(".cpp"), "sourcecode.cpp.cpp"},
101 {FILE_PATH_LITERAL(".css"), "text.css"},
102 {FILE_PATH_LITERAL(".cxx"), "sourcecode.cpp.cpp"},
103 {FILE_PATH_LITERAL(".dart"), "sourcecode"},
104 {FILE_PATH_LITERAL(".dylib"), "compiled.mach-o.dylib"},
105 {FILE_PATH_LITERAL(".framework"), "wrapper.framework"},
106 {FILE_PATH_LITERAL(".h"), "sourcecode.c.h"},
107 {FILE_PATH_LITERAL(".hxx"), "sourcecode.cpp.h"},
108 {FILE_PATH_LITERAL(".icns"), "image.icns"},
109 {FILE_PATH_LITERAL(".java"), "sourcecode.java"},
110 {FILE_PATH_LITERAL(".js"), "sourcecode.javascript"},
111 {FILE_PATH_LITERAL(".kext"), "wrapper.kext"},
112 {FILE_PATH_LITERAL(".m"), "sourcecode.c.objc"},
113 {FILE_PATH_LITERAL(".mm"), "sourcecode.cpp.objcpp"},
114 {FILE_PATH_LITERAL(".nib"), "wrapper.nib"},
115 {FILE_PATH_LITERAL(".o"), "compiled.mach-o.objfile"},
116 {FILE_PATH_LITERAL(".pdf"), "image.pdf"},
117 {FILE_PATH_LITERAL(".pl"), "text.script.perl"},
118 {FILE_PATH_LITERAL(".plist"), "text.plist.xml"},
119 {FILE_PATH_LITERAL(".pm"), "text.script.perl"},
120 {FILE_PATH_LITERAL(".png"), "image.png"},
121 {FILE_PATH_LITERAL(".py"), "text.script.python"},
122 {FILE_PATH_LITERAL(".r"), "sourcecode.rez"},
123 {FILE_PATH_LITERAL(".rez"), "sourcecode.rez"},
124 {FILE_PATH_LITERAL(".s"), "sourcecode.asm"},
125 {FILE_PATH_LITERAL(".storyboard"), "file.storyboard"},
126 {FILE_PATH_LITERAL(".strings"), "text.plist.strings"},
127 {FILE_PATH_LITERAL(".swift"), "sourcecode.swift"},
128 {FILE_PATH_LITERAL(".ttf"), "file"},
129 {FILE_PATH_LITERAL(".xcassets"), "folder.assetcatalog"},
130 {FILE_PATH_LITERAL(".xcconfig"), "text.xcconfig"},
131 {FILE_PATH_LITERAL(".xcdatamodel"), "wrapper.xcdatamodel"},
132 {FILE_PATH_LITERAL(".xcdatamodeld"), "wrapper.xcdatamodeld"},
133 {FILE_PATH_LITERAL(".xib"), "file.xib"},
134 {FILE_PATH_LITERAL(".y"), "sourcecode.yacc"},
135 };
136
137 const auto& iter = extension_map.find(ext);
138 if (iter != extension_map.end()) {
139 return iter->second;
140 }
141
142 return "text";
143 }
144
145 bool HasExplicitFileType(const base::FilePath::StringType& ext) {
146 return ext == FILE_PATH_LITERAL(".dart");
147 }
148
149 bool IsSourceFileForIndexing(const base::FilePath::StringType& ext) {
150 return ext == FILE_PATH_LITERAL(".c") || ext == FILE_PATH_LITERAL(".cc") ||
151 ext == FILE_PATH_LITERAL(".cpp") || ext == FILE_PATH_LITERAL(".cxx") ||
152 ext == FILE_PATH_LITERAL(".m") || ext == FILE_PATH_LITERAL(".mm");
153 }
154
155 void PrintValue(std::ostream& out, IndentRules rules, unsigned value) {
156 out << value;
157 }
158
159 void PrintValue(std::ostream& out, IndentRules rules, const char* value) {
160 out << EncodeString(value);
161 }
162
163 void PrintValue(std::ostream& out,
164 IndentRules rules,
165 const std::string& value) {
166 out << EncodeString(value);
167 }
168
169 void PrintValue(std::ostream& out, IndentRules rules, const PBXObject* value) {
170 out << value->Reference();
171 }
172
173 template <typename ObjectClass>
174 void PrintValue(std::ostream& out,
175 IndentRules rules,
176 const std::unique_ptr<ObjectClass>& value) {
177 PrintValue(out, rules, value.get());
178 }
179
180 template <typename ValueType>
181 void PrintValue(std::ostream& out,
182 IndentRules rules,
183 const std::vector<ValueType>& values) {
184 IndentRules sub_rule{rules.one_line, rules.level + 1};
185 out << "(" << (rules.one_line ? " " : "\n");
186 for (const auto& value : values) {
187 if (!sub_rule.one_line)
188 out << std::string(sub_rule.level, '\t');
189
190 PrintValue(out, sub_rule, value);
191 out << "," << (rules.one_line ? " " : "\n");
192 }
193
194 if (!rules.one_line && rules.level)
195 out << std::string(rules.level, '\t');
196 out << ")";
197 }
198
199 template <typename ValueType>
200 void PrintValue(std::ostream& out,
201 IndentRules rules,
202 const std::map<std::string, ValueType>& values) {
203 IndentRules sub_rule{rules.one_line, rules.level + 1};
204 out << "{" << (rules.one_line ? " " : "\n");
205 for (const auto& pair : values) {
206 if (!sub_rule.one_line)
207 out << std::string(sub_rule.level, '\t');
208
209 out << pair.first << " = ";
210 PrintValue(out, sub_rule, pair.second);
211 out << ";" << (rules.one_line ? " " : "\n");
212 }
213
214 if (!rules.one_line && rules.level)
215 out << std::string(rules.level, '\t');
216 out << "}";
217 }
218
219 template <typename ValueType>
220 void PrintProperty(std::ostream& out,
221 IndentRules rules,
222 const char* name,
223 ValueType&& value) {
224 if (!rules.one_line && rules.level)
225 out << std::string(rules.level, '\t');
226
227 out << name << " = ";
228 PrintValue(out, rules, std::forward<ValueType>(value));
229 out << ";" << (rules.one_line ? " " : "\n");
230 }
231 } // namespace
232
233 // PBXObjectClass -------------------------------------------------------------
234
235 const char* ToString(PBXObjectClass cls) {
236 switch (cls) {
237 case PBXAggregateTargetClass:
238 return "PBXAggregateTarget";
239 case PBXBuildFileClass:
240 return "PBXBuildFile";
241 case PBXFileReferenceClass:
242 return "PBXFileReference";
243 case PBXFrameworksBuildPhaseClass:
244 return "PBXFrameworksBuildPhase";
245 case PBXGroupClass:
246 return "PBXGroup";
247 case PBXNativeTargetClass:
248 return "PBXNativeTarget";
249 case PBXProjectClass:
250 return "PBXProject";
251 case PBXShellScriptBuildPhaseClass:
252 return "PBXShellScriptBuildPhase";
253 case PBXSourcesBuildPhaseClass:
254 return "PBXSourcesBuildPhase";
255 case XCBuildConfigurationClass:
256 return "XCBuildConfiguration";
257 case XCConfigurationListClass:
258 return "XCConfigurationList";
259 }
260 NOTREACHED();
261 return nullptr;
262 }
263
264 // PBXObjectVisitor -----------------------------------------------------------
265
266 PBXObjectVisitor::PBXObjectVisitor() {}
267
268 PBXObjectVisitor::~PBXObjectVisitor() {}
269
270 // PBXObject ------------------------------------------------------------------
271
272 PBXObject::PBXObject() {}
273
274 PBXObject::~PBXObject() {}
275
276 void PBXObject::SetId(const std::string& id) {
277 DCHECK(id_.empty());
278 DCHECK(!id.empty());
279 id_.assign(id);
280 }
281
282 std::string PBXObject::Reference() const {
283 std::string comment = Comment();
284 if (comment.empty())
285 return id_;
286
287 return id_ + " /* " + comment + " */";
288 }
289
290 std::string PBXObject::Comment() const {
291 return Name();
292 }
293
294 void PBXObject::Visit(PBXObjectVisitor& visitor) {
295 visitor.Visit(this);
296 }
297
298 // PBXBuildPhase --------------------------------------------------------------
299
300 PBXBuildPhase::PBXBuildPhase() {}
301
302 PBXBuildPhase::~PBXBuildPhase() {}
303
304 // PBXTarget ------------------------------------------------------------------
305
306 PBXTarget::PBXTarget(const std::string& name,
307 const std::string& shell_script,
308 const std::string& config_name,
309 const PBXAttributes& attributes)
310 : configurations_(new XCConfigurationList(config_name, attributes, this)),
311 name_(name) {
312 if (!shell_script.empty()) {
313 build_phases_.push_back(
314 base::WrapUnique(new PBXShellScriptBuildPhase(name, shell_script)));
315 }
316 }
317
318 PBXTarget::~PBXTarget() {}
319
320 std::string PBXTarget::Name() const {
321 return name_;
322 }
323
324 void PBXTarget::Visit(PBXObjectVisitor& visitor) {
325 PBXObject::Visit(visitor);
326 configurations_->Visit(visitor);
327 for (const auto& build_phase : build_phases_) {
328 build_phase->Visit(visitor);
329 }
330 }
331
332 // PBXAggregateTarget ---------------------------------------------------------
333
334 PBXAggregateTarget::PBXAggregateTarget(const std::string& name,
335 const std::string& shell_script,
336 const std::string& config_name,
337 const PBXAttributes& attributes)
338 : PBXTarget(name, shell_script, config_name, attributes) {}
339
340 PBXAggregateTarget::~PBXAggregateTarget() {}
341
342 PBXObjectClass PBXAggregateTarget::Class() const {
343 return PBXAggregateTargetClass;
344 }
345
346 void PBXAggregateTarget::Print(std::ostream& out, unsigned indent) const {
347 const std::string indent_str(indent, '\t');
348 const IndentRules rules = {false, indent + 1};
349 out << indent_str << Reference() << " = {\n";
350 PrintProperty(out, rules, "isa", ToString(Class()));
351 PrintProperty(out, rules, "buildConfigurationList", configurations_);
352 PrintProperty(out, rules, "buildPhases", build_phases_);
353 PrintProperty(out, rules, "dependencies", EmptyPBXObjectVector());
354 PrintProperty(out, rules, "name", name_);
355 PrintProperty(out, rules, "productName", name_);
356 out << indent_str << "};\n";
357 }
358
359 // PBXBuildFile ---------------------------------------------------------------
360
361 PBXBuildFile::PBXBuildFile(const PBXFileReference* file_reference,
362 const PBXSourcesBuildPhase* build_phase)
363 : file_reference_(file_reference), build_phase_(build_phase) {
364 DCHECK(file_reference_);
365 DCHECK(build_phase_);
366 }
367
368 PBXBuildFile::~PBXBuildFile() {}
369
370 PBXObjectClass PBXBuildFile::Class() const {
371 return PBXBuildFileClass;
372 }
373
374 std::string PBXBuildFile::Name() const {
375 return file_reference_->Name() + " in " + build_phase_->Name();
376 }
377
378 void PBXBuildFile::Print(std::ostream& out, unsigned indent) const {
379 const std::string indent_str(indent, '\t');
380 const IndentRules rules = {true, 0};
381 out << indent_str << Reference() << " = {";
382 PrintProperty(out, rules, "isa", ToString(Class()));
383 PrintProperty(out, rules, "fileRef", file_reference_);
384 out << "};\n";
385 }
386
387 // PBXFileReference -----------------------------------------------------------
388
389 PBXFileReference::PBXFileReference(const std::string& name,
390 const std::string& path,
391 const std::string& type)
392 : name_(name), path_(path), type_(type) {}
393
394 PBXFileReference::~PBXFileReference() {}
395
396 PBXObjectClass PBXFileReference::Class() const {
397 return PBXFileReferenceClass;
398 }
399
400 std::string PBXFileReference::Name() const {
401 return path_;
402 }
403
404 void PBXFileReference::Print(std::ostream& out, unsigned indent) const {
405 const std::string indent_str(indent, '\t');
406 const IndentRules rules = {true, 0};
407 out << indent_str << Reference() << " = {";
408 PrintProperty(out, rules, "isa", ToString(Class()));
409
410 if (!type_.empty()) {
411 PrintProperty(out, rules, "explicitFileType", type_);
412 PrintProperty(out, rules, "includeInIndex", 0u);
413 } else {
414 const base::FilePath::StringType ext =
415 base::FilePath::FromUTF8Unsafe(path_).Extension();
416
417 if (HasExplicitFileType(ext))
418 PrintProperty(out, rules, "explicitFileType", GetSourceType(ext));
419 else
420 PrintProperty(out, rules, "lastKnownFileType", GetSourceType(ext));
421 }
422
423 if (name_ != path_ && !name_.empty())
424 PrintProperty(out, rules, "name", name_);
425
426 PrintProperty(out, rules, "path", path_);
427 PrintProperty(out, rules, "sourceTree",
428 type_.empty() ? "<group>" : "BUILT_PRODUCTS_DIR");
429 out << "};\n";
430 }
431
432 // PBXFrameworksBuildPhase ----------------------------------------------------
433
434 PBXFrameworksBuildPhase::PBXFrameworksBuildPhase() {}
435
436 PBXFrameworksBuildPhase::~PBXFrameworksBuildPhase() {}
437
438 PBXObjectClass PBXFrameworksBuildPhase::Class() const {
439 return PBXFrameworksBuildPhaseClass;
440 }
441
442 std::string PBXFrameworksBuildPhase::Name() const {
443 return "Frameworks";
444 }
445
446 void PBXFrameworksBuildPhase::Print(std::ostream& out, unsigned indent) const {
447 const std::string indent_str(indent, '\t');
448 const IndentRules rules = {false, indent + 1};
449 out << indent_str << Reference() << " = {\n";
450 PrintProperty(out, rules, "isa", ToString(Class()));
451 PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
452 PrintProperty(out, rules, "files", EmptyPBXObjectVector());
453 PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
454 out << indent_str << "};\n";
455 }
456
457 // PBXGroup -------------------------------------------------------------------
458
459 PBXGroup::PBXGroup(const std::string& path, const std::string& name)
460 : name_(name), path_(path) {}
461
462 PBXGroup::~PBXGroup() {}
463
464 PBXObject* PBXGroup::AddChild(std::unique_ptr<PBXObject> child) {
465 DCHECK(child);
466 children_.push_back(std::move(child));
467 return children_.back().get();
468 }
469
470 PBXFileReference* PBXGroup::AddSourceFile(const std::string& source_path) {
471 DCHECK(!source_path.empty());
472 std::string::size_type sep = source_path.find("/");
473 if (sep == std::string::npos) {
474 children_.push_back(base::WrapUnique(
475 new PBXFileReference(std::string(), source_path, std::string())));
476 return static_cast<PBXFileReference*>(children_.back().get());
477 }
478
479 PBXGroup* group = nullptr;
480 base::StringPiece component(source_path.data(), sep);
481 for (const auto& child : children_) {
482 if (child->Class() != PBXGroupClass)
483 continue;
484
485 PBXGroup* child_as_group = static_cast<PBXGroup*>(child.get());
486 if (child_as_group->path_ == component) {
487 group = child_as_group;
488 break;
489 }
490 }
491
492 if (!group) {
493 children_.push_back(base::WrapUnique(new PBXGroup(component.as_string())));
494 group = static_cast<PBXGroup*>(children_.back().get());
495 }
496
497 DCHECK(group);
498 DCHECK(group->path_ == component);
499 return group->AddSourceFile(source_path.substr(sep + 1));
500 }
501
502 PBXObjectClass PBXGroup::Class() const {
503 return PBXGroupClass;
504 }
505
506 std::string PBXGroup::Name() const {
507 if (!name_.empty())
508 return name_;
509 if (!path_.empty())
510 return path_;
511 return std::string();
512 }
513
514 void PBXGroup::Visit(PBXObjectVisitor& visitor) {
515 PBXObject::Visit(visitor);
516 for (const auto& child : children_) {
517 child->Visit(visitor);
518 }
519 }
520
521 void PBXGroup::Print(std::ostream& out, unsigned indent) const {
522 const std::string indent_str(indent, '\t');
523 const IndentRules rules = {false, indent + 1};
524 out << indent_str << Reference() << " = {\n";
525 PrintProperty(out, rules, "isa", ToString(Class()));
526 PrintProperty(out, rules, "children", children_);
527 if (!name_.empty())
528 PrintProperty(out, rules, "name", name_);
529 if (!path_.empty())
530 PrintProperty(out, rules, "path", path_);
531 PrintProperty(out, rules, "sourceTree", "<group>");
532 out << indent_str << "};\n";
533 }
534
535 // PBXNativeTarget ------------------------------------------------------------
536
537 PBXNativeTarget::PBXNativeTarget(const std::string& name,
538 const std::string& shell_script,
539 const std::string& config_name,
540 const PBXAttributes& attributes,
541 const std::string& product_type,
542 const PBXFileReference* product_reference)
543 : PBXTarget(name, shell_script, config_name, attributes),
544 product_reference_(product_reference),
545 product_type_(product_type) {
546 DCHECK(product_reference_);
547 build_phases_.push_back(base::WrapUnique(new PBXSourcesBuildPhase));
548 source_build_phase_ =
549 static_cast<PBXSourcesBuildPhase*>(build_phases_.back().get());
550
551 build_phases_.push_back(base::WrapUnique(new PBXFrameworksBuildPhase));
552 }
553
554 PBXNativeTarget::~PBXNativeTarget() {}
555
556 void PBXNativeTarget::AddFileForIndexing(
557 const PBXFileReference* file_reference) {
558 DCHECK(file_reference);
559 source_build_phase_->AddBuildFile(
560 base::WrapUnique(new PBXBuildFile(file_reference, source_build_phase_)));
561 }
562
563 PBXObjectClass PBXNativeTarget::Class() const {
564 return PBXNativeTargetClass;
565 }
566
567 void PBXNativeTarget::Print(std::ostream& out, unsigned indent) const {
568 const std::string indent_str(indent, '\t');
569 const IndentRules rules = {false, indent + 1};
570 out << indent_str << Reference() << " = {\n";
571 PrintProperty(out, rules, "isa", ToString(Class()));
572 PrintProperty(out, rules, "buildConfigurationList", configurations_);
573 PrintProperty(out, rules, "buildPhases", build_phases_);
574 PrintProperty(out, rules, "buildRules", EmptyPBXObjectVector());
575 PrintProperty(out, rules, "dependencies", EmptyPBXObjectVector());
576 PrintProperty(out, rules, "name", name_);
577 PrintProperty(out, rules, "productName", name_);
578 PrintProperty(out, rules, "productReference", product_reference_);
579 PrintProperty(out, rules, "productType", product_type_);
580 out << indent_str << "};\n";
581 }
582
583 // PBXProject -----------------------------------------------------------------
584
585 PBXProject::PBXProject(const std::string& name,
586 const std::string& config_name,
587 const std::string& source_path,
588 const PBXAttributes& attributes)
589 : name_(name), config_name_(config_name), target_for_indexing_(nullptr) {
590 attributes_["BuildIndependentTargetsInParallel"] = "YES";
591
592 main_group_.reset(new PBXGroup);
593 sources_ = static_cast<PBXGroup*>(main_group_->AddChild(
594 base::WrapUnique(new PBXGroup(source_path, "Source"))));
595 products_ = static_cast<PBXGroup*>(main_group_->AddChild(
596 base::WrapUnique(new PBXGroup(std::string(), "Product"))));
597 main_group_->AddChild(base::WrapUnique(new PBXGroup(std::string(), "Build")));
598
599 configurations_.reset(new XCConfigurationList(config_name, attributes, this));
600 }
601
602 PBXProject::~PBXProject() {}
603
604 void PBXProject::AddSourceFile(const std::string& source_path) {
605 PBXFileReference* file_reference = sources_->AddSourceFile(source_path);
606 const base::FilePath::StringType ext =
607 base::FilePath::FromUTF8Unsafe(source_path).Extension();
608 if (!IsSourceFileForIndexing(ext))
609 return;
610
611 if (!target_for_indexing_) {
612 PBXAttributes attributes;
613 attributes["EXECUTABLE_PREFIX"] = "";
614 attributes["HEADER_SEARCH_PATHS"] = sources_->path();
615 attributes["PRODUCT_NAME"] = name_;
616
617 PBXFileReference* product_reference = static_cast<PBXFileReference*>(
618 products_->AddChild(base::WrapUnique(new PBXFileReference(
619 std::string(), name_, "compiled.mach-o.executable"))));
620
621 const char product_type[] = "com.apple.product-type.tool";
622 targets_.push_back(base::WrapUnique(
623 new PBXNativeTarget(name_, std::string(), config_name_, attributes,
624 product_type, product_reference)));
625 target_for_indexing_ = static_cast<PBXNativeTarget*>(targets_.back().get());
626 }
627
628 DCHECK(target_for_indexing_);
629 target_for_indexing_->AddFileForIndexing(file_reference);
630 }
631
632 void PBXProject::AddAggregateTarget(const std::string& name,
633 const std::string& shell_script) {
634 PBXAttributes attributes;
635 attributes["CODE_SIGNING_REQUIRED"] = "NO";
636 attributes["CONFIGURATION_BUILD_DIR"] = ".";
637 attributes["PRODUCT_NAME"] = name;
638
639 targets_.push_back(base::WrapUnique(
640 new PBXAggregateTarget(name, shell_script, config_name_, attributes)));
641 }
642
643 void PBXProject::AddNativeTarget(const std::string& name,
644 const std::string& type,
645 const std::string& output_name,
646 const std::string& output_type,
647 const std::string& shell_script) {
648 const base::FilePath::StringType ext =
649 base::FilePath::FromUTF8Unsafe(output_name).Extension();
650
651 PBXFileReference* product = static_cast<PBXFileReference*>(
652 products_->AddChild(base::WrapUnique(new PBXFileReference(
653 name, output_name, type.empty() ? GetSourceType(ext) : type))));
654
655 PBXAttributes attributes;
656 attributes["CODE_SIGNING_REQUIRED"] = "NO";
657 attributes["CONFIGURATION_BUILD_DIR"] = ".";
658 attributes["PRODUCT_NAME"] = name;
659
660 targets_.push_back(base::WrapUnique(new PBXNativeTarget(
661 name, shell_script, config_name_, attributes, output_type, product)));
662 }
663
664 void PBXProject::SetProjectDirPath(const std::string& project_dir_path) {
665 DCHECK(!project_dir_path.empty());
666 project_dir_path_.assign(project_dir_path);
667 }
668
669 void PBXProject::SetProjectRoot(const std::string& project_root) {
670 DCHECK(!project_root.empty());
671 project_root_.assign(project_root);
672 }
673
674 void PBXProject::AddTarget(std::unique_ptr<PBXTarget> target) {
675 DCHECK(target);
676 targets_.push_back(std::move(target));
677 }
678
679 PBXObjectClass PBXProject::Class() const {
680 return PBXProjectClass;
681 }
682
683 std::string PBXProject::Name() const {
684 return name_;
685 }
686
687 std::string PBXProject::Comment() const {
688 return "Project object";
689 }
690
691 void PBXProject::Visit(PBXObjectVisitor& visitor) {
692 PBXObject::Visit(visitor);
693 configurations_->Visit(visitor);
694 main_group_->Visit(visitor);
695 for (const auto& target : targets_) {
696 target->Visit(visitor);
697 }
698 }
699
700 void PBXProject::Print(std::ostream& out, unsigned indent) const {
701 const std::string indent_str(indent, '\t');
702 const IndentRules rules = {false, indent + 1};
703 out << indent_str << Reference() << " = {\n";
704 PrintProperty(out, rules, "isa", ToString(Class()));
705 PrintProperty(out, rules, "attributes", attributes_);
706 PrintProperty(out, rules, "buildConfigurationList", configurations_);
707 PrintProperty(out, rules, "compatibilityVersion", "Xcode 3.2");
708 PrintProperty(out, rules, "developmentRegion", "English");
709 PrintProperty(out, rules, "hasScannedForEncodings", 1u);
710 PrintProperty(out, rules, "knownRegions", std::vector<std::string>({"en"}));
711 PrintProperty(out, rules, "mainGroup", main_group_);
712 PrintProperty(out, rules, "projectDirPath", project_dir_path_);
713 PrintProperty(out, rules, "projectRoot", project_root_);
714 PrintProperty(out, rules, "targets", targets_);
715 out << indent_str << "};\n";
716 }
717
718 // PBXShellScriptBuildPhase ---------------------------------------------------
719
720 PBXShellScriptBuildPhase::PBXShellScriptBuildPhase(
721 const std::string& name,
722 const std::string& shell_script)
723 : name_("Action \"Compile and copy " + name + " via ninja\""),
724 shell_script_(shell_script) {}
725
726 PBXShellScriptBuildPhase::~PBXShellScriptBuildPhase() {}
727
728 PBXObjectClass PBXShellScriptBuildPhase::Class() const {
729 return PBXShellScriptBuildPhaseClass;
730 }
731
732 std::string PBXShellScriptBuildPhase::Name() const {
733 return name_;
734 }
735
736 void PBXShellScriptBuildPhase::Print(std::ostream& out, unsigned indent) const {
737 const std::string indent_str(indent, '\t');
738 const IndentRules rules = {false, indent + 1};
739 out << indent_str << Reference() << " = {\n";
740 PrintProperty(out, rules, "isa", ToString(Class()));
741 PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
742 PrintProperty(out, rules, "files", EmptyPBXObjectVector());
743 PrintProperty(out, rules, "inputPaths", EmptyPBXObjectVector());
744 PrintProperty(out, rules, "name", name_);
745 PrintProperty(out, rules, "outputPaths", EmptyPBXObjectVector());
746 PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
747 PrintProperty(out, rules, "shellPath", "/bin/sh");
748 PrintProperty(out, rules, "shellScript", shell_script_);
749 PrintProperty(out, rules, "showEnvVarsInLog", 0u);
750 out << indent_str << "};\n";
751 }
752
753 // PBXSourcesBuildPhase -------------------------------------------------------
754
755 PBXSourcesBuildPhase::PBXSourcesBuildPhase() {}
756
757 PBXSourcesBuildPhase::~PBXSourcesBuildPhase() {}
758
759 void PBXSourcesBuildPhase::AddBuildFile(
760 std::unique_ptr<PBXBuildFile> build_file) {
761 files_.push_back(std::move(build_file));
762 }
763
764 PBXObjectClass PBXSourcesBuildPhase::Class() const {
765 return PBXSourcesBuildPhaseClass;
766 }
767
768 std::string PBXSourcesBuildPhase::Name() const {
769 return "Sources";
770 }
771
772 void PBXSourcesBuildPhase::Visit(PBXObjectVisitor& visitor) {
773 PBXBuildPhase::Visit(visitor);
774 for (const auto& file : files_) {
775 file->Visit(visitor);
776 }
777 }
778
779 void PBXSourcesBuildPhase::Print(std::ostream& out, unsigned indent) const {
780 const std::string indent_str(indent, '\t');
781 const IndentRules rules = {false, indent + 1};
782 out << indent_str << Reference() << " = {\n";
783 PrintProperty(out, rules, "isa", ToString(Class()));
784 PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
785 PrintProperty(out, rules, "files", files_);
786 PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
787 out << indent_str << "};\n";
788 }
789
790 // XCBuildConfiguration -------------------------------------------------------
791
792 XCBuildConfiguration::XCBuildConfiguration(const std::string& name,
793 const PBXAttributes& attributes)
794 : attributes_(attributes), name_(name) {}
795
796 XCBuildConfiguration::~XCBuildConfiguration() {}
797
798 PBXObjectClass XCBuildConfiguration::Class() const {
799 return XCBuildConfigurationClass;
800 }
801
802 std::string XCBuildConfiguration::Name() const {
803 return name_;
804 }
805
806 void XCBuildConfiguration::Print(std::ostream& out, unsigned indent) const {
807 const std::string indent_str(indent, '\t');
808 const IndentRules rules = {false, indent + 1};
809 out << indent_str << Reference() << " = {\n";
810 PrintProperty(out, rules, "isa", ToString(Class()));
811 PrintProperty(out, rules, "buildSettings", attributes_);
812 PrintProperty(out, rules, "name", name_);
813 out << indent_str << "};\n";
814 }
815
816 // XCConfigurationList --------------------------------------------------------
817
818 XCConfigurationList::XCConfigurationList(const std::string& name,
819 const PBXAttributes& attributes,
820 const PBXObject* owner_reference)
821 : owner_reference_(owner_reference) {
822 DCHECK(owner_reference_);
823 configurations_.push_back(
824 base::WrapUnique(new XCBuildConfiguration(name, attributes)));
825 }
826
827 XCConfigurationList::~XCConfigurationList() {}
828
829 PBXObjectClass XCConfigurationList::Class() const {
830 return XCConfigurationListClass;
831 }
832
833 std::string XCConfigurationList::Name() const {
834 std::stringstream buffer;
835 buffer << "Build configuration list for "
836 << ToString(owner_reference_->Class()) << " \""
837 << owner_reference_->Name() << "\"";
838 return buffer.str();
839 }
840
841 void XCConfigurationList::Visit(PBXObjectVisitor& visitor) {
842 PBXObject::Visit(visitor);
843 for (const auto& configuration : configurations_) {
844 configuration->Visit(visitor);
845 }
846 }
847
848 void XCConfigurationList::Print(std::ostream& out, unsigned indent) const {
849 const std::string indent_str(indent, '\t');
850 const IndentRules rules = {false, indent + 1};
851 out << indent_str << Reference() << " = {\n";
852 PrintProperty(out, rules, "isa", ToString(Class()));
853 PrintProperty(out, rules, "buildConfigurations", configurations_);
854 PrintProperty(out, rules, "defaultConfigurationIsVisible", 1u);
855 PrintProperty(out, rules, "defaultConfigurationName",
856 configurations_[0]->Name());
857 out << indent_str << "};\n";
858 }
OLDNEW
« no previous file with comments | « tools/gn/xcode_object.h ('k') | tools/gn/xcode_writer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698