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

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: Add documentation for new flags to "gn gen" 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
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 {
brettw 2016/04/28 21:16:17 Blank line below
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()) {
brettw 2016/04/28 21:16:17 No {}
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
brettw 2016/04/28 21:16:17 Blank line before.
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 }
261
262 // PBXObjectVisitor -----------------------------------------------------------
263
264 PBXObjectVisitor::PBXObjectVisitor() {}
265
266 PBXObjectVisitor::~PBXObjectVisitor() {}
267
268 // PBXObject ------------------------------------------------------------------
269
270 PBXObject::PBXObject() {}
271
272 PBXObject::~PBXObject() {}
273
274 void PBXObject::SetId(const std::string& id) {
275 DCHECK(id_.empty());
276 DCHECK(!id.empty());
277 id_.assign(id);
278 }
279
280 std::string PBXObject::Reference() const {
281 std::string comment = Comment();
282 if (comment.empty())
283 return id_;
284
285 return id_ + " /* " + comment + " */";
286 }
287
288 std::string PBXObject::Comment() const {
289 return Name();
290 }
291
292 void PBXObject::Visit(PBXObjectVisitor& visitor) {
293 visitor.Visit(this);
294 }
295
296 // PBXBuildPhase --------------------------------------------------------------
297
298 PBXBuildPhase::PBXBuildPhase() {}
299
300 PBXBuildPhase::~PBXBuildPhase() {}
301
302 // PBXTarget ------------------------------------------------------------------
303
304 PBXTarget::PBXTarget(const std::string& name,
305 const std::string& shell_script,
306 const std::string& config_name,
307 const PBXAttributes& attributes)
308 : configurations_(new XCConfigurationList(config_name, attributes, this)),
309 name_(name) {
310 if (!shell_script.empty()) {
311 build_phases_.push_back(
312 base::WrapUnique(new PBXShellScriptBuildPhase(name, shell_script)));
313 }
314 }
315
316 PBXTarget::~PBXTarget() {}
317
318 std::string PBXTarget::Name() const {
319 return name_;
320 }
321
322 void PBXTarget::Visit(PBXObjectVisitor& visitor) {
323 PBXObject::Visit(visitor);
324 configurations_->Visit(visitor);
325 for (const auto& build_phase : build_phases_) {
326 build_phase->Visit(visitor);
327 }
328 }
329
330 // PBXAggregateTarget ---------------------------------------------------------
331
332 PBXAggregateTarget::PBXAggregateTarget(const std::string& name,
333 const std::string& shell_script,
334 const std::string& config_name,
335 const PBXAttributes& attributes)
336 : PBXTarget(name, shell_script, config_name, attributes) {}
337
338 PBXAggregateTarget::~PBXAggregateTarget() {}
339
340 PBXObjectClass PBXAggregateTarget::Class() const {
341 return PBXAggregateTargetClass;
342 }
343
344 void PBXAggregateTarget::Print(std::ostream& out, unsigned indent) const {
345 const std::string indent_str(indent, '\t');
346 const IndentRules rules = {false, indent + 1};
347 out << indent_str << Reference() << " = {\n";
348 PrintProperty(out, rules, "isa", ToString(Class()));
349 PrintProperty(out, rules, "buildConfigurationList", configurations_);
350 PrintProperty(out, rules, "buildPhases", build_phases_);
351 PrintProperty(out, rules, "dependencies", EmptyPBXObjectVector());
352 PrintProperty(out, rules, "name", name_);
353 PrintProperty(out, rules, "productName", name_);
354 out << indent_str << "};\n";
355 }
356
357 // PBXBuildFile ---------------------------------------------------------------
358
359 PBXBuildFile::PBXBuildFile(const PBXFileReference* file_reference,
360 const PBXSourcesBuildPhase* build_phase)
361 : file_reference_(file_reference), build_phase_(build_phase) {
362 DCHECK(file_reference_);
363 DCHECK(build_phase_);
364 }
365
366 PBXBuildFile::~PBXBuildFile() {}
367
368 PBXObjectClass PBXBuildFile::Class() const {
369 return PBXBuildFileClass;
370 }
371
372 std::string PBXBuildFile::Name() const {
373 return file_reference_->Name() + " in " + build_phase_->Name();
374 }
375
376 void PBXBuildFile::Print(std::ostream& out, unsigned indent) const {
377 const std::string indent_str(indent, '\t');
378 const IndentRules rules = {true, 0};
379 out << indent_str << Reference() << " = {";
380 PrintProperty(out, rules, "isa", ToString(Class()));
381 PrintProperty(out, rules, "fileRef", file_reference_);
382 out << "};\n";
383 }
384
385 // PBXFileReference -----------------------------------------------------------
386
387 PBXFileReference::PBXFileReference(const std::string& name,
388 const std::string& path,
389 const std::string& type)
390 : name_(name), path_(path), type_(type) {}
391
392 PBXFileReference::~PBXFileReference() {}
393
394 PBXObjectClass PBXFileReference::Class() const {
395 return PBXFileReferenceClass;
396 }
397
398 std::string PBXFileReference::Name() const {
399 return path_;
400 }
401
402 void PBXFileReference::Print(std::ostream& out, unsigned indent) const {
403 const std::string indent_str(indent, '\t');
404 const IndentRules rules = {true, 0};
405 out << indent_str << Reference() << " = {";
406 PrintProperty(out, rules, "isa", ToString(Class()));
407
408 if (!type_.empty()) {
409 PrintProperty(out, rules, "explicitFileType", type_);
410 PrintProperty(out, rules, "includeInIndex", 0u);
411 } else {
412 const base::FilePath::StringType ext =
413 base::FilePath::FromUTF8Unsafe(path_).Extension();
414
415 if (HasExplicitFileType(ext))
416 PrintProperty(out, rules, "explicitFileType", GetSourceType(ext));
417 else
418 PrintProperty(out, rules, "lastKnownFileType", GetSourceType(ext));
419 }
420
421 if (name_ != path_ && !name_.empty())
422 PrintProperty(out, rules, "name", name_);
423
424 PrintProperty(out, rules, "path", path_);
425 PrintProperty(out, rules, "sourceTree",
426 type_.empty() ? "<group>" : "BUILT_PRODUCTS_DIR");
427 out << "};\n";
428 }
429
430 // PBXFrameworksBuildPhase ----------------------------------------------------
431
432 PBXFrameworksBuildPhase::PBXFrameworksBuildPhase() {}
433
434 PBXFrameworksBuildPhase::~PBXFrameworksBuildPhase() {}
435
436 PBXObjectClass PBXFrameworksBuildPhase::Class() const {
437 return PBXFrameworksBuildPhaseClass;
438 }
439
440 std::string PBXFrameworksBuildPhase::Name() const {
441 return "Frameworks";
442 }
443
444 void PBXFrameworksBuildPhase::Print(std::ostream& out, unsigned indent) const {
445 const std::string indent_str(indent, '\t');
446 const IndentRules rules = {false, indent + 1};
447 out << indent_str << Reference() << " = {\n";
448 PrintProperty(out, rules, "isa", ToString(Class()));
449 PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
450 PrintProperty(out, rules, "files", EmptyPBXObjectVector());
451 PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
452 out << indent_str << "};\n";
453 }
454
455 // PBXGroup -------------------------------------------------------------------
456
457 PBXGroup::PBXGroup(const std::string& path, const std::string& name)
458 : name_(name), path_(path) {}
459
460 PBXGroup::~PBXGroup() {}
461
462 PBXObject* PBXGroup::AddChild(std::unique_ptr<PBXObject> child) {
463 DCHECK(child);
464 children_.push_back(std::move(child));
465 return children_.back().get();
466 }
467
468 PBXFileReference* PBXGroup::AddSourceFile(const std::string& source_path) {
469 DCHECK(!source_path.empty());
470 std::string::size_type sep = source_path.find(base::FilePath::kSeparators);
471 if (sep == std::string::npos) {
472 children_.push_back(base::WrapUnique(
473 new PBXFileReference(std::string(), source_path, std::string())));
474 return static_cast<PBXFileReference*>(children_.back().get());
475 }
476
477 PBXGroup* group = nullptr;
478 base::StringPiece component(source_path.data(), sep);
479 for (const auto& child : children_) {
480 if (child->Class() != PBXGroupClass)
481 continue;
482
483 PBXGroup* child_as_group = static_cast<PBXGroup*>(child.get());
484 if (child_as_group->path_ == component) {
485 group = child_as_group;
486 break;
487 }
488 }
489
490 if (!group) {
491 children_.push_back(base::WrapUnique(new PBXGroup(component.as_string())));
492 group = static_cast<PBXGroup*>(children_.back().get());
493 }
494
495 DCHECK(group);
496 DCHECK(group->path_ == component);
497 return group->AddSourceFile(source_path.substr(sep + 1));
498 }
499
500 PBXObjectClass PBXGroup::Class() const {
501 return PBXGroupClass;
502 }
503
504 std::string PBXGroup::Name() const {
505 if (!name_.empty())
506 return name_;
507 if (!path_.empty())
508 return path_;
509 return std::string();
510 }
511
512 void PBXGroup::Visit(PBXObjectVisitor& visitor) {
513 PBXObject::Visit(visitor);
514 for (const auto& child : children_) {
515 child->Visit(visitor);
516 }
517 }
518
519 void PBXGroup::Print(std::ostream& out, unsigned indent) const {
520 const std::string indent_str(indent, '\t');
521 const IndentRules rules = {false, indent + 1};
522 out << indent_str << Reference() << " = {\n";
523 PrintProperty(out, rules, "isa", ToString(Class()));
524 PrintProperty(out, rules, "children", children_);
525 if (!name_.empty())
526 PrintProperty(out, rules, "name", name_);
527 if (!path_.empty())
528 PrintProperty(out, rules, "path", path_);
529 PrintProperty(out, rules, "sourceTree", "<group>");
530 out << indent_str << "};\n";
531 }
532
533 // PBXNativeTarget ------------------------------------------------------------
534
535 PBXNativeTarget::PBXNativeTarget(const std::string& name,
536 const std::string& shell_script,
537 const std::string& config_name,
538 const PBXAttributes& attributes,
539 const std::string& product_type,
540 const PBXFileReference* product_reference)
541 : PBXTarget(name, shell_script, config_name, attributes),
542 product_reference_(product_reference),
543 product_type_(product_type) {
544 DCHECK(product_reference_);
545 build_phases_.push_back(base::WrapUnique(new PBXSourcesBuildPhase));
546 source_build_phase_ =
547 static_cast<PBXSourcesBuildPhase*>(build_phases_.back().get());
548
549 build_phases_.push_back(base::WrapUnique(new PBXFrameworksBuildPhase));
550 }
551
552 PBXNativeTarget::~PBXNativeTarget() {}
553
554 void PBXNativeTarget::AddFileForIndexing(
555 const PBXFileReference* file_reference) {
556 DCHECK(file_reference);
557 source_build_phase_->AddBuildFile(
558 base::WrapUnique(new PBXBuildFile(file_reference, source_build_phase_)));
559 }
560
561 PBXObjectClass PBXNativeTarget::Class() const {
562 return PBXNativeTargetClass;
563 }
564
565 void PBXNativeTarget::Print(std::ostream& out, unsigned indent) const {
566 const std::string indent_str(indent, '\t');
567 const IndentRules rules = {false, indent + 1};
568 out << indent_str << Reference() << " = {\n";
569 PrintProperty(out, rules, "isa", ToString(Class()));
570 PrintProperty(out, rules, "buildConfigurationList", configurations_);
571 PrintProperty(out, rules, "buildPhases", build_phases_);
572 PrintProperty(out, rules, "buildRules", EmptyPBXObjectVector());
573 PrintProperty(out, rules, "dependencies", EmptyPBXObjectVector());
574 PrintProperty(out, rules, "name", name_);
575 PrintProperty(out, rules, "productName", name_);
576 PrintProperty(out, rules, "productReference", product_reference_);
577 PrintProperty(out, rules, "productType", product_type_);
578 out << indent_str << "};\n";
579 }
580
581 // PBXProject -----------------------------------------------------------------
582
583 PBXProject::PBXProject(const std::string& name,
584 const std::string& config_name,
585 const std::string& source_path,
586 const PBXAttributes& attributes)
587 : name_(name), config_name_(config_name), target_for_indexing_(nullptr) {
588 attributes_["BuildIndependentTargetsInParallel"] = "YES";
589
590 main_group_.reset(new PBXGroup);
591 sources_ = static_cast<PBXGroup*>(main_group_->AddChild(
592 base::WrapUnique(new PBXGroup(source_path, "Source"))));
593 products_ = static_cast<PBXGroup*>(main_group_->AddChild(
594 base::WrapUnique(new PBXGroup(std::string(), "Product"))));
595 main_group_->AddChild(base::WrapUnique(new PBXGroup(std::string(), "Build")));
596
597 configurations_.reset(new XCConfigurationList(config_name, attributes, this));
598 }
599
600 PBXProject::~PBXProject() {}
601
602 void PBXProject::AddSourceFile(const std::string& source_path) {
603 PBXFileReference* file_reference = sources_->AddSourceFile(source_path);
604 const base::FilePath::StringType ext =
605 base::FilePath::FromUTF8Unsafe(source_path).Extension();
606 if (!IsSourceFileForIndexing(ext))
607 return;
608
609 if (!target_for_indexing_) {
610 PBXAttributes attributes;
611 attributes["EXECUTABLE_PREFIX"] = "";
612 attributes["HEADER_SEARCH_PATHS"] = sources_->path();
613 attributes["PRODUCT_NAME"] = name_;
614
615 PBXFileReference* product_reference = static_cast<PBXFileReference*>(
616 products_->AddChild(base::WrapUnique(new PBXFileReference(
617 std::string(), name_, "compiled.mach-o.executable"))));
618
619 const char product_type[] = "com.apple.product-type.tool";
620 targets_.push_back(base::WrapUnique(
621 new PBXNativeTarget(name_, std::string(), config_name_, attributes,
622 product_type, product_reference)));
623 target_for_indexing_ = static_cast<PBXNativeTarget*>(targets_.back().get());
624 }
625
626 DCHECK(target_for_indexing_);
627 target_for_indexing_->AddFileForIndexing(file_reference);
628 }
629
630 void PBXProject::AddAggregateTarget(const std::string& name,
631 const std::string& shell_script) {
632 PBXAttributes attributes;
633 attributes["CODE_SIGNING_REQUIRED"] = "NO";
634 attributes["CONFIGURATION_BUILD_DIR"] = ".";
635 attributes["PRODUCT_NAME"] = name;
636
637 targets_.push_back(base::WrapUnique(
638 new PBXAggregateTarget(name, shell_script, config_name_, attributes)));
639 }
640
641 void PBXProject::AddNativeTarget(const std::string& name,
642 const std::string& type,
643 const std::string& output_name,
644 const std::string& output_type,
645 const std::string& shell_script) {
646 const base::FilePath::StringType ext =
647 base::FilePath::FromUTF8Unsafe(output_name).Extension();
648
649 PBXFileReference* product = static_cast<PBXFileReference*>(
650 products_->AddChild(base::WrapUnique(new PBXFileReference(
651 name, output_name, type.empty() ? GetSourceType(ext) : type))));
652
653 PBXAttributes attributes;
654 attributes["CODE_SIGNING_REQUIRED"] = "NO";
655 attributes["CONFIGURATION_BUILD_DIR"] = ".";
656 attributes["PRODUCT_NAME"] = name;
657
658 targets_.push_back(base::WrapUnique(new PBXNativeTarget(
659 name, shell_script, config_name_, attributes, output_type, product)));
660 }
661
662 void PBXProject::SetProjectDirPath(const std::string& project_dir_path) {
663 DCHECK(!project_dir_path.empty());
664 project_dir_path_.assign(project_dir_path);
665 }
666
667 void PBXProject::SetProjectRoot(const std::string& project_root) {
668 DCHECK(!project_root.empty());
669 project_root_.assign(project_root);
670 }
671
672 void PBXProject::AddTarget(std::unique_ptr<PBXTarget> target) {
673 DCHECK(target);
674 targets_.push_back(std::move(target));
675 }
676
677 PBXObjectClass PBXProject::Class() const {
678 return PBXProjectClass;
679 }
680
681 std::string PBXProject::Name() const {
682 return name_;
683 }
684
685 std::string PBXProject::Comment() const {
686 return "Project object";
687 }
688
689 void PBXProject::Visit(PBXObjectVisitor& visitor) {
690 PBXObject::Visit(visitor);
691 configurations_->Visit(visitor);
692 main_group_->Visit(visitor);
693 for (const auto& target : targets_) {
694 target->Visit(visitor);
695 }
696 }
697
698 void PBXProject::Print(std::ostream& out, unsigned indent) const {
699 const std::string indent_str(indent, '\t');
700 const IndentRules rules = {false, indent + 1};
701 out << indent_str << Reference() << " = {\n";
702 PrintProperty(out, rules, "isa", ToString(Class()));
703 PrintProperty(out, rules, "attributes", attributes_);
704 PrintProperty(out, rules, "buildConfigurationList", configurations_);
705 PrintProperty(out, rules, "compatibilityVersion", "Xcode 3.2");
706 PrintProperty(out, rules, "developmentRegion", "English");
707 PrintProperty(out, rules, "hasScannedForEncodings", 1u);
708 PrintProperty(out, rules, "knownRegions", std::vector<std::string>({"en"}));
709 PrintProperty(out, rules, "mainGroup", main_group_);
710 PrintProperty(out, rules, "projectDirPath", project_dir_path_);
711 PrintProperty(out, rules, "projectRoot", project_root_);
712 PrintProperty(out, rules, "targets", targets_);
713 out << indent_str << "};\n";
714 }
715
716 // PBXShellScriptBuildPhase ---------------------------------------------------
717
718 PBXShellScriptBuildPhase::PBXShellScriptBuildPhase(
719 const std::string& name,
720 const std::string& shell_script)
721 : name_("Action \"Compile and copy " + name + " via ninja\""),
722 shell_script_(shell_script) {}
723
724 PBXShellScriptBuildPhase::~PBXShellScriptBuildPhase() {}
725
726 PBXObjectClass PBXShellScriptBuildPhase::Class() const {
727 return PBXShellScriptBuildPhaseClass;
728 }
729
730 std::string PBXShellScriptBuildPhase::Name() const {
731 return name_;
732 }
733
734 void PBXShellScriptBuildPhase::Print(std::ostream& out, unsigned indent) const {
735 const std::string indent_str(indent, '\t');
736 const IndentRules rules = {false, indent + 1};
737 out << indent_str << Reference() << " = {\n";
738 PrintProperty(out, rules, "isa", ToString(Class()));
739 PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
740 PrintProperty(out, rules, "files", EmptyPBXObjectVector());
741 PrintProperty(out, rules, "inputPaths", EmptyPBXObjectVector());
742 PrintProperty(out, rules, "name", name_);
743 PrintProperty(out, rules, "outputPaths", EmptyPBXObjectVector());
744 PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
745 PrintProperty(out, rules, "shellPath", "/bin/sh");
746 PrintProperty(out, rules, "shellScript", shell_script_);
747 PrintProperty(out, rules, "showEnvVarsInLog", 0u);
748 out << indent_str << "};\n";
749 }
750
751 // PBXSourcesBuildPhase -------------------------------------------------------
752
753 PBXSourcesBuildPhase::PBXSourcesBuildPhase() {}
754
755 PBXSourcesBuildPhase::~PBXSourcesBuildPhase() {}
756
757 void PBXSourcesBuildPhase::AddBuildFile(
758 std::unique_ptr<PBXBuildFile> build_file) {
759 files_.push_back(std::move(build_file));
760 }
761
762 PBXObjectClass PBXSourcesBuildPhase::Class() const {
763 return PBXSourcesBuildPhaseClass;
764 }
765
766 std::string PBXSourcesBuildPhase::Name() const {
767 return "Sources";
768 }
769
770 void PBXSourcesBuildPhase::Visit(PBXObjectVisitor& visitor) {
771 PBXBuildPhase::Visit(visitor);
772 for (const auto& file : files_) {
773 file->Visit(visitor);
774 }
775 }
776
777 void PBXSourcesBuildPhase::Print(std::ostream& out, unsigned indent) const {
778 const std::string indent_str(indent, '\t');
779 const IndentRules rules = {false, indent + 1};
780 out << indent_str << Reference() << " = {\n";
781 PrintProperty(out, rules, "isa", ToString(Class()));
782 PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
783 PrintProperty(out, rules, "files", files_);
784 PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
785 out << indent_str << "};\n";
786 }
787
788 // XCBuildConfiguration -------------------------------------------------------
789
790 XCBuildConfiguration::XCBuildConfiguration(const std::string& name,
791 const PBXAttributes& attributes)
792 : attributes_(attributes), name_(name) {}
793
794 XCBuildConfiguration::~XCBuildConfiguration() {}
795
796 PBXObjectClass XCBuildConfiguration::Class() const {
797 return XCBuildConfigurationClass;
798 }
799
800 std::string XCBuildConfiguration::Name() const {
801 return name_;
802 }
803
804 void XCBuildConfiguration::Print(std::ostream& out, unsigned indent) const {
805 const std::string indent_str(indent, '\t');
806 const IndentRules rules = {false, indent + 1};
807 out << indent_str << Reference() << " = {\n";
808 PrintProperty(out, rules, "isa", ToString(Class()));
809 PrintProperty(out, rules, "buildSettings", attributes_);
810 PrintProperty(out, rules, "name", name_);
811 out << indent_str << "};\n";
812 }
813
814 // XCConfigurationList --------------------------------------------------------
815
816 XCConfigurationList::XCConfigurationList(const std::string& name,
817 const PBXAttributes& attributes,
818 const PBXObject* owner_reference)
819 : owner_reference_(owner_reference) {
820 DCHECK(owner_reference_);
821 configurations_.push_back(
822 base::WrapUnique(new XCBuildConfiguration(name, attributes)));
823 }
824
825 XCConfigurationList::~XCConfigurationList() {}
826
827 PBXObjectClass XCConfigurationList::Class() const {
828 return XCConfigurationListClass;
829 }
830
831 std::string XCConfigurationList::Name() const {
832 std::stringstream buffer;
833 buffer << "Build configuration list for "
834 << ToString(owner_reference_->Class()) << " \""
835 << owner_reference_->Name() << "\"";
836 return buffer.str();
837 }
838
839 void XCConfigurationList::Visit(PBXObjectVisitor& visitor) {
840 PBXObject::Visit(visitor);
841 for (const auto& configuration : configurations_) {
842 configuration->Visit(visitor);
843 }
844 }
845
846 void XCConfigurationList::Print(std::ostream& out, unsigned indent) const {
847 const std::string indent_str(indent, '\t');
848 const IndentRules rules = {false, indent + 1};
849 out << indent_str << Reference() << " = {\n";
850 PrintProperty(out, rules, "isa", ToString(Class()));
851 PrintProperty(out, rules, "buildConfigurations", configurations_);
852 PrintProperty(out, rules, "defaultConfigurationIsVisible", 1u);
853 PrintProperty(out, rules, "defaultConfigurationName",
854 configurations_[0]->Name());
855 out << indent_str << "};\n";
856 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698