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

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

Issue 2623203004: Consolidate Xcode Project Setup (Closed)
Patch Set: Rebase Created 3 years, 11 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_writer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 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/xcode_writer.h" 5 #include "tools/gn/xcode_writer.h"
6 6
7 #include <iomanip> 7 #include <iomanip>
8 #include <map> 8 #include <map>
9 #include <memory> 9 #include <memory>
10 #include <sstream> 10 #include <sstream>
(...skipping 14 matching lines...) Expand all
25 #include "tools/gn/settings.h" 25 #include "tools/gn/settings.h"
26 #include "tools/gn/source_file.h" 26 #include "tools/gn/source_file.h"
27 #include "tools/gn/target.h" 27 #include "tools/gn/target.h"
28 #include "tools/gn/value.h" 28 #include "tools/gn/value.h"
29 #include "tools/gn/variables.h" 29 #include "tools/gn/variables.h"
30 #include "tools/gn/xcode_object.h" 30 #include "tools/gn/xcode_object.h"
31 31
32 namespace { 32 namespace {
33 33
34 using TargetToFileList = std::unordered_map<const Target*, Target::FileList>; 34 using TargetToFileList = std::unordered_map<const Target*, Target::FileList>;
35 using TargetToNativeTarget = 35 using TargetToTarget = std::unordered_map<const Target*, const Target*>;
36 std::unordered_map<const Target*, PBXNativeTarget*>;
37 using FileToTargets = std::map<SourceFile,
38 std::vector<const Target*>,
39 bool (*)(const SourceFile&, const SourceFile&)>;
40 36
41 const char kEarlGreyFileNameIdentifier[] = "egtest.mm"; 37 const char kEarlGreyFileNameIdentifier[] = "egtest.mm";
42 const char kXCTestFileNameIdentifier[] = "xctest.mm"; 38 const char kXCTestFileNameIdentifier[] = "xctest.mm";
43 const char kXCTestModuleTargetNamePostfix[] = "_module"; 39 const char kXCTestModuleTargetNamePostfix[] = "_module";
44 const char kXCTestFileReferenceFolder[] = "xctests/";
45 40
46 struct SafeEnvironmentVariableInfo { 41 struct SafeEnvironmentVariableInfo {
47 const char* name; 42 const char* name;
48 bool capture_at_generation; 43 bool capture_at_generation;
49 }; 44 };
50 45
51 SafeEnvironmentVariableInfo kSafeEnvironmentVariables[] = { 46 SafeEnvironmentVariableInfo kSafeEnvironmentVariables[] = {
52 {"HOME", true}, {"LANG", true}, {"PATH", true}, 47 {"HOME", true}, {"LANG", true}, {"PATH", true},
53 {"USER", true}, {"TMPDIR", false}, 48 {"USER", true}, {"TMPDIR", false},
54 }; 49 };
55 50
56 bool CompareSourceFiles(const SourceFile& lhs, const SourceFile& rhs) {
57 if (lhs.GetName() < rhs.GetName())
58 return true;
59 else if (lhs.GetName() > rhs.GetName())
60 return false;
61 else
62 return lhs.value() < rhs.value();
63 }
64
65 XcodeWriter::TargetOsType GetTargetOs(const Args& args) { 51 XcodeWriter::TargetOsType GetTargetOs(const Args& args) {
66 const Value* target_os_value = args.GetArgOverride(variables::kTargetOs); 52 const Value* target_os_value = args.GetArgOverride(variables::kTargetOs);
67 if (target_os_value) { 53 if (target_os_value) {
68 if (target_os_value->type() == Value::STRING) { 54 if (target_os_value->type() == Value::STRING) {
69 if (target_os_value->string_value() == "ios") 55 if (target_os_value->string_value() == "ios")
70 return XcodeWriter::WRITER_TARGET_OS_IOS; 56 return XcodeWriter::WRITER_TARGET_OS_IOS;
71 } 57 }
72 } 58 }
73 return XcodeWriter::WRITER_TARGET_OS_MACOS; 59 return XcodeWriter::WRITER_TARGET_OS_MACOS;
74 } 60 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 } 100 }
115 101
116 bool IsXCTestModuleTarget(const Target* target) { 102 bool IsXCTestModuleTarget(const Target* target) {
117 return target->output_type() == Target::CREATE_BUNDLE && 103 return target->output_type() == Target::CREATE_BUNDLE &&
118 target->bundle_data().product_type() == 104 target->bundle_data().product_type() ==
119 "com.apple.product-type.bundle.unit-test" && 105 "com.apple.product-type.bundle.unit-test" &&
120 base::EndsWith(target->label().name(), kXCTestModuleTargetNamePostfix, 106 base::EndsWith(target->label().name(), kXCTestModuleTargetNamePostfix,
121 base::CompareCase::SENSITIVE); 107 base::CompareCase::SENSITIVE);
122 } 108 }
123 109
110 bool IsXCTestFile(const SourceFile& file) {
111 return base::EndsWith(file.GetName(), kEarlGreyFileNameIdentifier,
112 base::CompareCase::SENSITIVE) ||
113 base::EndsWith(file.GetName(), kXCTestFileNameIdentifier,
114 base::CompareCase::SENSITIVE);
115 }
116
124 const Target* FindXCTestApplicationTarget( 117 const Target* FindXCTestApplicationTarget(
125 const Target* xctest_module_target, 118 const Target* xctest_module_target,
126 const std::vector<const Target*>& targets) { 119 const std::vector<const Target*>& targets) {
127 DCHECK(IsXCTestModuleTarget(xctest_module_target)); 120 DCHECK(IsXCTestModuleTarget(xctest_module_target));
128 DCHECK(base::EndsWith(xctest_module_target->label().name(), 121 DCHECK(base::EndsWith(xctest_module_target->label().name(),
129 kXCTestModuleTargetNamePostfix, 122 kXCTestModuleTargetNamePostfix,
130 base::CompareCase::SENSITIVE)); 123 base::CompareCase::SENSITIVE));
131 std::string application_target_name = 124 std::string application_target_name =
132 xctest_module_target->label().name().substr( 125 xctest_module_target->label().name().substr(
133 0, xctest_module_target->label().name().size() - 126 0, xctest_module_target->label().name().size() -
134 strlen(kXCTestModuleTargetNamePostfix)); 127 strlen(kXCTestModuleTargetNamePostfix));
135 for (const Target* target : targets) { 128 for (const Target* target : targets) {
136 if (target->label().name() == application_target_name) { 129 if (target->label().name() == application_target_name) {
137 return target; 130 return target;
138 } 131 }
139 } 132 }
140 NOTREACHED(); 133 NOTREACHED();
141 return nullptr; 134 return nullptr;
142 } 135 }
143 136
144 // Returns the corresponding application targets given XCTest module targets. 137 // Given XCTest module targets, find the corresponding application targets and
138 // the mappings between them.
145 void FindXCTestApplicationTargets( 139 void FindXCTestApplicationTargets(
146 const std::vector<const Target*>& xctest_module_targets, 140 const std::vector<const Target*>& xctest_module_targets,
147 const std::vector<const Target*>& targets, 141 const std::vector<const Target*>& targets,
148 std::vector<const Target*>* xctest_application_targets) { 142 std::vector<const Target*>* xctest_application_targets,
143 TargetToTarget* xctest_module_to_application_target) {
149 for (const Target* xctest_module_target : xctest_module_targets) { 144 for (const Target* xctest_module_target : xctest_module_targets) {
150 xctest_application_targets->push_back( 145 xctest_application_targets->push_back(
151 FindXCTestApplicationTarget(xctest_module_target, targets)); 146 FindXCTestApplicationTarget(xctest_module_target, targets));
147 xctest_module_to_application_target->insert(std::make_pair(
148 xctest_module_target, xctest_application_targets->back()));
152 } 149 }
153 } 150 }
154 151
155 // Searches the list of xctest files recursively under |target|. 152 // Searches the list of xctest files recursively under |target|.
156 void SearchXCTestFiles(const Target* target, 153 void SearchXCTestFiles(const Target* target,
157 TargetToFileList* xctest_files_per_target) { 154 TargetToFileList* xctest_files_per_target) {
158 // Early return if already visited and processed. 155 // Early return if already visited and processed.
159 if (xctest_files_per_target->find(target) != xctest_files_per_target->end()) 156 if (xctest_files_per_target->find(target) != xctest_files_per_target->end())
160 return; 157 return;
161 158
162 Target::FileList xctest_files; 159 Target::FileList xctest_files;
163 for (const SourceFile& file : target->sources()) { 160 for (const SourceFile& file : target->sources()) {
164 if (base::EndsWith(file.GetName(), kEarlGreyFileNameIdentifier, 161 if (IsXCTestFile(file)) {
165 base::CompareCase::SENSITIVE) ||
166 base::EndsWith(file.GetName(), kXCTestFileNameIdentifier,
167 base::CompareCase::SENSITIVE)) {
168 xctest_files.push_back(file); 162 xctest_files.push_back(file);
169 } 163 }
170 } 164 }
171 165
172 // Call recursively on public and private deps. 166 // Call recursively on public and private deps.
173 for (const auto& t : target->public_deps()) { 167 for (const auto& t : target->public_deps()) {
174 SearchXCTestFiles(t.ptr, xctest_files_per_target); 168 SearchXCTestFiles(t.ptr, xctest_files_per_target);
175 const Target::FileList& deps_xctest_files = 169 const Target::FileList& deps_xctest_files =
176 (*xctest_files_per_target)[t.ptr]; 170 (*xctest_files_per_target)[t.ptr];
177 xctest_files.insert(xctest_files.end(), deps_xctest_files.begin(), 171 xctest_files.insert(xctest_files.end(), deps_xctest_files.begin(),
(...skipping 11 matching lines...) Expand all
189 // Sort xctest_files to remove duplicates. 183 // Sort xctest_files to remove duplicates.
190 std::sort(xctest_files.begin(), xctest_files.end()); 184 std::sort(xctest_files.begin(), xctest_files.end());
191 xctest_files.erase(std::unique(xctest_files.begin(), xctest_files.end()), 185 xctest_files.erase(std::unique(xctest_files.begin(), xctest_files.end()),
192 xctest_files.end()); 186 xctest_files.end());
193 187
194 xctest_files_per_target->insert(std::make_pair(target, xctest_files)); 188 xctest_files_per_target->insert(std::make_pair(target, xctest_files));
195 } 189 }
196 190
197 // Finds the list of xctest files recursively under each of the application 191 // Finds the list of xctest files recursively under each of the application
198 // targets. 192 // targets.
199 void FindXCTestFilesForTargets( 193 void FindXCTestFilesForApplicationTargets(
200 const std::vector<const Target*>& application_targets, 194 const std::vector<const Target*>& application_targets,
201 std::vector<Target::FileList>* file_lists) { 195 TargetToFileList* xctest_files_per_application_target) {
202 TargetToFileList xctest_files_per_target; 196 TargetToFileList xctest_files_per_target;
203
204 for (const Target* target : application_targets) { 197 for (const Target* target : application_targets) {
205 DCHECK(IsApplicationTarget(target)); 198 DCHECK(IsApplicationTarget(target));
206 SearchXCTestFiles(target, &xctest_files_per_target); 199 SearchXCTestFiles(target, &xctest_files_per_target);
207 file_lists->push_back(xctest_files_per_target[target]); 200 xctest_files_per_application_target->insert(
201 std::make_pair(target, xctest_files_per_target[target]));
208 } 202 }
209 } 203 }
210 204
211 // Maps each xctest file to a list of xctest application targets that contains
212 // the file.
213 void MapXCTestFileToApplicationTargets(
214 const std::vector<const Target*>& xctest_application_targets,
215 const std::vector<Target::FileList>& xctest_file_lists,
216 FileToTargets* xctest_file_to_application_targets) {
217 DCHECK_EQ(xctest_application_targets.size(), xctest_file_lists.size());
218
219 for (size_t i = 0; i < xctest_application_targets.size(); ++i) {
220 const Target* xctest_application_target = xctest_application_targets[i];
221 DCHECK(IsApplicationTarget(xctest_application_target));
222
223 for (const SourceFile& source : xctest_file_lists[i]) {
224 auto iter = xctest_file_to_application_targets->find(source);
225 if (iter == xctest_file_to_application_targets->end()) {
226 iter =
227 xctest_file_to_application_targets
228 ->insert(std::make_pair(source, std::vector<const Target*>()))
229 .first;
230 }
231 iter->second.push_back(xctest_application_target);
232 }
233 }
234 }
235
236 class CollectPBXObjectsPerClassHelper : public PBXObjectVisitor { 205 class CollectPBXObjectsPerClassHelper : public PBXObjectVisitor {
237 public: 206 public:
238 CollectPBXObjectsPerClassHelper() {} 207 CollectPBXObjectsPerClassHelper() {}
239 208
240 void Visit(PBXObject* object) override { 209 void Visit(PBXObject* object) override {
241 DCHECK(object); 210 DCHECK(object);
242 objects_per_class_[object->Class()].push_back(object); 211 objects_per_class_[object->Class()].push_back(object);
243 } 212 }
244 213
245 const std::map<PBXObjectClass, std::vector<const PBXObject*>>& 214 const std::map<PBXObjectClass, std::vector<const PBXObject*>>&
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 config_name = config_name.substr(0, separator); 303 config_name = config_name.substr(0, separator);
335 304
336 std::vector<const Target*> targets; 305 std::vector<const Target*> targets;
337 std::vector<const Target*> all_targets = builder.GetAllResolvedTargets(); 306 std::vector<const Target*> all_targets = builder.GetAllResolvedTargets();
338 if (!XcodeWriter::FilterTargets(build_settings, all_targets, 307 if (!XcodeWriter::FilterTargets(build_settings, all_targets,
339 dir_filters_string, &targets, err)) { 308 dir_filters_string, &targets, err)) {
340 return false; 309 return false;
341 } 310 }
342 311
343 XcodeWriter workspace(workspace_name); 312 XcodeWriter workspace(workspace_name);
344 workspace.CreateProductsProject(targets, attributes, source_path, config_name, 313 workspace.CreateProductsProject(targets, all_targets, attributes, source_path,
345 root_target_name, ninja_extra_args, 314 config_name, root_target_name,
346 build_settings, target_os); 315 ninja_extra_args, build_settings, target_os);
347
348 workspace.CreateSourcesProject(
349 all_targets, build_settings->build_dir(), attributes, source_path,
350 build_settings->root_path_utf8(), config_name, target_os);
351 316
352 return workspace.WriteFiles(build_settings, err); 317 return workspace.WriteFiles(build_settings, err);
353 } 318 }
354 319
355 XcodeWriter::XcodeWriter(const std::string& name) : name_(name) { 320 XcodeWriter::XcodeWriter(const std::string& name) : name_(name) {
356 if (name_.empty()) 321 if (name_.empty())
357 name_.assign("all"); 322 name_.assign("all");
358 } 323 }
359 324
360 XcodeWriter::~XcodeWriter() {} 325 XcodeWriter::~XcodeWriter() {}
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 for (const Target* target : targets) { 385 for (const Target* target : targets) {
421 if (!IsXCTestModuleTarget(target)) 386 if (!IsXCTestModuleTarget(target))
422 continue; 387 continue;
423 388
424 xctest_module_targets->push_back(target); 389 xctest_module_targets->push_back(target);
425 } 390 }
426 } 391 }
427 392
428 void XcodeWriter::CreateProductsProject( 393 void XcodeWriter::CreateProductsProject(
429 const std::vector<const Target*>& targets, 394 const std::vector<const Target*>& targets,
395 const std::vector<const Target*>& all_targets,
430 const PBXAttributes& attributes, 396 const PBXAttributes& attributes,
431 const std::string& source_path, 397 const std::string& source_path,
432 const std::string& config_name, 398 const std::string& config_name,
433 const std::string& root_target, 399 const std::string& root_target,
434 const std::string& ninja_extra_args, 400 const std::string& ninja_extra_args,
435 const BuildSettings* build_settings, 401 const BuildSettings* build_settings,
436 TargetOsType target_os) { 402 TargetOsType target_os) {
437 std::unique_ptr<PBXProject> main_project( 403 std::unique_ptr<PBXProject> main_project(
438 new PBXProject("products", config_name, source_path, attributes)); 404 new PBXProject("products", config_name, source_path, attributes));
405 SourceDir source_dir("//");
406
407 // Add all source files for indexing.
408 std::vector<SourceFile> sources;
409 for (const Target* target : all_targets) {
410 for (const SourceFile& source : target->sources()) {
411 if (IsStringInOutputDir(build_settings->build_dir(), source.value()))
412 continue;
413
414 sources.push_back(source);
415 }
416 }
417
418 // Sort sources to ensure determinisn of the project file generation and
419 // remove duplicate reference to the source files (can happen due to the
420 // bundle_data targets).
421 std::sort(sources.begin(), sources.end());
422 sources.erase(std::unique(sources.begin(), sources.end()), sources.end());
423
424 for (const SourceFile& source : sources) {
425 std::string source_file = RebasePath(source.value(), source_dir,
426 build_settings->root_path_utf8());
427 main_project->AddSourceFileToIndexingTarget(source_file, source_file,
428 CompilerFlags::NONE);
429 }
439 430
440 // Filter xctest module and application targets and find list of xctest files 431 // Filter xctest module and application targets and find list of xctest files
441 // recursively under them. 432 // recursively under them.
442 std::vector<const Target*> xctest_module_targets; 433 std::vector<const Target*> xctest_module_targets;
443 FilterXCTestModuleTargets(targets, &xctest_module_targets); 434 FilterXCTestModuleTargets(targets, &xctest_module_targets);
444 435
436 // There is a 1 on 1 mapping between |xctest_module_targets| and
437 // |xctest_application_targets|.
445 std::vector<const Target*> xctest_application_targets; 438 std::vector<const Target*> xctest_application_targets;
439 TargetToTarget xctest_module_to_application_target;
446 FindXCTestApplicationTargets(xctest_module_targets, targets, 440 FindXCTestApplicationTargets(xctest_module_targets, targets,
447 &xctest_application_targets); 441 &xctest_application_targets,
442 &xctest_module_to_application_target);
448 DCHECK_EQ(xctest_module_targets.size(), xctest_application_targets.size()); 443 DCHECK_EQ(xctest_module_targets.size(), xctest_application_targets.size());
444 DCHECK_EQ(xctest_module_targets.size(),
445 xctest_module_to_application_target.size());
449 446
450 std::vector<Target::FileList> xctest_file_lists; 447 TargetToFileList xctest_files_per_application_target;
451 FindXCTestFilesForTargets(xctest_application_targets, &xctest_file_lists); 448 FindXCTestFilesForApplicationTargets(xctest_application_targets,
452 DCHECK_EQ(xctest_application_targets.size(), xctest_file_lists.size()); 449 &xctest_files_per_application_target);
450 DCHECK_EQ(xctest_application_targets.size(),
451 xctest_files_per_application_target.size());
453 452
454 std::string build_path; 453 std::string build_path;
455 std::unique_ptr<base::Environment> env(base::Environment::Create()); 454 std::unique_ptr<base::Environment> env(base::Environment::Create());
456 455
457 main_project->AddAggregateTarget( 456 main_project->AddAggregateTarget(
458 "All", GetBuildScript(root_target, ninja_extra_args, env.get())); 457 "All", GetBuildScript(root_target, ninja_extra_args, env.get()));
459 458
460 TargetToNativeTarget xctest_application_to_module_native_target;
461
462 for (const Target* target : targets) { 459 for (const Target* target : targets) {
463 switch (target->output_type()) { 460 switch (target->output_type()) {
464 case Target::EXECUTABLE: 461 case Target::EXECUTABLE:
465 if (target_os == XcodeWriter::WRITER_TARGET_OS_IOS) 462 if (target_os == XcodeWriter::WRITER_TARGET_OS_IOS)
466 continue; 463 continue;
467 464
468 main_project->AddNativeTarget( 465 main_project->AddNativeTarget(
469 target->label().name(), "compiled.mach-o.executable", 466 target->label().name(), "compiled.mach-o.executable",
470 target->output_name().empty() ? target->label().name() 467 target->output_name().empty() ? target->label().name()
471 : target->output_name(), 468 : target->output_name(),
(...skipping 23 matching lines...) Expand all
495 .GetBundleRootDirOutput(target->settings()) 492 .GetBundleRootDirOutput(target->settings())
496 .value(), 493 .value(),
497 build_settings->build_dir()), 494 build_settings->build_dir()),
498 target->bundle_data().product_type(), 495 target->bundle_data().product_type(),
499 GetBuildScript(target->label().name(), ninja_extra_args, env.get()), 496 GetBuildScript(target->label().name(), ninja_extra_args, env.get()),
500 extra_attributes); 497 extra_attributes);
501 498
502 if (!IsXCTestModuleTarget(target)) 499 if (!IsXCTestModuleTarget(target))
503 continue; 500 continue;
504 501
505 // Populate |xctest_application_to_module_native_target| for XCTest 502 // Add xctest files to the "Compiler Sources" of corresponding xctest
506 // module targets. 503 // native targets.
507 const Target* application_target = 504 const Target::FileList& xctest_file_list =
508 FindXCTestApplicationTarget(target, xctest_application_targets); 505 xctest_files_per_application_target
509 xctest_application_to_module_native_target.insert( 506 [xctest_module_to_application_target[target]];
510 std::make_pair(application_target, native_target)); 507
508 for (const SourceFile& source : xctest_file_list) {
509 std::string source_path = RebasePath(
510 source.value(), source_dir, build_settings->root_path_utf8());
511
512 // Test files need to be known to Xcode for proper indexing and for
513 // discovery of tests function for XCTest, but the compilation is done
514 // via ninja and thus must prevent Xcode from compiling the files by
515 // adding '-help' as per file compiler flag.
516 main_project->AddSourceFile(source_path, source_path,
517 CompilerFlags::HELP, native_target);
518 }
511 519
512 break; 520 break;
513 } 521 }
514 522
515 default: 523 default:
516 break; 524 break;
517 } 525 }
518 } 526 }
519 527
520 FileToTargets xctest_file_to_application_targets(CompareSourceFiles);
521 MapXCTestFileToApplicationTargets(xctest_application_targets,
522 xctest_file_lists,
523 &xctest_file_to_application_targets);
524
525 // Add xctest files to the "Compiler Sources" of corresponding xctest native
526 // targets.
527 SourceDir source_dir("//");
528 for (const auto& item : xctest_file_to_application_targets) {
529 const SourceFile& source = item.first;
530 for (const Target* xctest_application_target : item.second) {
531 std::string navigator_path =
532 kXCTestFileReferenceFolder + source.GetName();
533 std::string source_path = RebasePath(source.value(), source_dir,
534 build_settings->root_path_utf8());
535 PBXNativeTarget* xctest_module_native_target =
536 xctest_application_to_module_native_target[xctest_application_target];
537
538 // Test files need to be known to Xcode for proper indexing and for
539 // discovery of tests function for XCTest, but the compilation is done
540 // via ninja and thus must prevent Xcode from compiling the files by
541 // adding '-help' as per file compiler flag.
542 main_project->AddSourceFile(navigator_path, source_path,
543 CompilerFlags::HELP,
544 xctest_module_native_target);
545 }
546 }
547
548 projects_.push_back(std::move(main_project)); 528 projects_.push_back(std::move(main_project));
549 } 529 }
550 530
551 void XcodeWriter::CreateSourcesProject(
552 const std::vector<const Target*>& targets,
553 const SourceDir& root_build_dir,
554 const PBXAttributes& attributes,
555 const std::string& source_path,
556 const std::string& absolute_source_path,
557 const std::string& config_name,
558 TargetOsType target_os) {
559 std::vector<SourceFile> sources;
560 for (const Target* target : targets) {
561 for (const SourceFile& source : target->sources()) {
562 if (IsStringInOutputDir(root_build_dir, source.value()))
563 continue;
564
565 sources.push_back(source);
566 }
567 }
568
569 std::unique_ptr<PBXProject> sources_for_indexing(
570 new PBXProject("sources", config_name, source_path, attributes));
571
572 // Sort sources to ensure determinisn of the project file generation and
573 // remove duplicate reference to the source files (can happen due to the
574 // bundle_data targets).
575 std::sort(sources.begin(), sources.end());
576 sources.erase(std::unique(sources.begin(), sources.end()), sources.end());
577
578 SourceDir source_dir("//");
579 for (const SourceFile& source : sources) {
580 std::string source_file =
581 RebasePath(source.value(), source_dir, absolute_source_path);
582 sources_for_indexing->AddSourceFileToIndexingTarget(
583 source_file, source_file, CompilerFlags::NONE);
584 }
585
586 projects_.push_back(std::move(sources_for_indexing));
587 }
588
589 bool XcodeWriter::WriteFiles(const BuildSettings* build_settings, Err* err) { 531 bool XcodeWriter::WriteFiles(const BuildSettings* build_settings, Err* err) {
590 for (const auto& project : projects_) { 532 for (const auto& project : projects_) {
591 if (!WriteProjectFile(build_settings, project.get(), err)) 533 if (!WriteProjectFile(build_settings, project.get(), err))
592 return false; 534 return false;
593 } 535 }
594 536
595 SourceFile xcworkspacedata_file = 537 SourceFile xcworkspacedata_file =
596 build_settings->build_dir().ResolveRelativeFile( 538 build_settings->build_dir().ResolveRelativeFile(
597 Value(nullptr, name_ + ".xcworkspace/contents.xcworkspacedata"), err); 539 Value(nullptr, name_ + ".xcworkspace/contents.xcworkspacedata"), err);
598 if (xcworkspacedata_file.is_null()) 540 if (xcworkspacedata_file.is_null())
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 for (auto* object : pair.second) { 596 for (auto* object : pair.second) {
655 object->Print(out, 2); 597 object->Print(out, 2);
656 } 598 }
657 out << "/* End " << ToString(pair.first) << " section */\n"; 599 out << "/* End " << ToString(pair.first) << " section */\n";
658 } 600 }
659 601
660 out << "\t};\n" 602 out << "\t};\n"
661 << "\trootObject = " << project->Reference() << ";\n" 603 << "\trootObject = " << project->Reference() << ";\n"
662 << "}\n"; 604 << "}\n";
663 } 605 }
OLDNEW
« no previous file with comments | « tools/gn/xcode_writer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698