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 #ifndef TOOLS_GN_XCODE_OBJECT_H_ 6 #define TOOLS_GN_XCODE_OBJECT_H_ 7 8 #include <iosfwd> 9 #include <map> 10 #include <memory> 11 #include <string> 12 #include <vector> 13 14 // Helper classes to generate Xcode project files. 15 // 16 // This code is based on gyp xcodeproj_file.py generator. It does not support 17 // all features of Xcode project but instead just enough to implement a hybrid 18 // mode where Xcode uses external scripts to perform the compilation steps. 19 // 20 // See 21 // https://chromium.googlesource.com/external/gyp/+/master/pylib/gyp/xcodeproj_file.py 22 // for more information on Xcode project file format. 23 24 // PBXObjectClass ------------------------------------------------------------- 25 26 enum PBXObjectClass { 27 // Those values needs to stay sorted in alphabetic order. 28 PBXAggregateTargetClass, 29 PBXBuildFileClass, 30 PBXContainerItemProxyClass, 31 PBXFileReferenceClass, 32 PBXFrameworksBuildPhaseClass, 33 PBXGroupClass, 34 PBXNativeTargetClass, 35 PBXProjectClass, 36 PBXResourcesBuildPhaseClass, 37 PBXShellScriptBuildPhaseClass, 38 PBXSourcesBuildPhaseClass, 39 PBXTargetDependencyClass, 40 XCBuildConfigurationClass, 41 XCConfigurationListClass, 42 }; 43 44 const char* ToString(PBXObjectClass cls); 45 46 // Forward-declarations ------------------------------------------------------- 47 48 class PBXAggregateTarget; 49 class PBXBuildFile; 50 class PBXBuildPhase; 51 class PBXContainerItemProxy; 52 class PBXFileReference; 53 class PBXFrameworksBuildPhase; 54 class PBXGroup; 55 class PBXNativeTarget; 56 class PBXObject; 57 class PBXProject; 58 class PBXResourcesBuildPhase; 59 class PBXShellScriptBuildPhase; 60 class PBXSourcesBuildPhase; 61 class PBXTarget; 62 class PBXTargetDependency; 63 class XCBuildConfiguration; 64 class XCConfigurationList; 65 66 using PBXAttributes = std::map<std::string, std::string>; 67 68 // PBXObjectVisitor ----------------------------------------------------------- 69 70 class PBXObjectVisitor { 71 public: 72 PBXObjectVisitor(); 73 virtual ~PBXObjectVisitor(); 74 virtual void Visit(PBXObject* object) = 0; 75 76 private: 77 PBXObjectVisitor(const PBXObjectVisitor&) = delete; 78 PBXObjectVisitor& operator=(const PBXObjectVisitor&) = delete; 79 }; 80 81 // PBXObjectVisitorConst ------------------------------------------------------ 82 83 class PBXObjectVisitorConst { 84 public: 85 PBXObjectVisitorConst(); 86 virtual ~PBXObjectVisitorConst(); 87 virtual void Visit(const PBXObject* object) = 0; 88 89 private: 90 PBXObjectVisitorConst(const PBXObjectVisitorConst&) = delete; 91 PBXObjectVisitorConst& operator=(const PBXObjectVisitorConst&) = delete; 92 }; 93 94 // PBXObject ------------------------------------------------------------------ 95 96 class PBXObject { 97 public: 98 PBXObject(); 99 virtual ~PBXObject(); 100 id()101 const std::string id() const { return id_; } 102 void SetId(const std::string& id); 103 104 std::string Reference() const; 105 106 virtual PBXObjectClass Class() const = 0; 107 virtual std::string Name() const = 0; 108 virtual std::string Comment() const; 109 virtual void Visit(PBXObjectVisitor& visitor); 110 virtual void Visit(PBXObjectVisitorConst& visitor) const; 111 virtual void Print(std::ostream& out, unsigned indent) const = 0; 112 113 private: 114 std::string id_; 115 116 PBXObject(const PBXObject&) = delete; 117 PBXObject& operator=(const PBXObject&) = delete; 118 }; 119 120 // PBXBuildPhase -------------------------------------------------------------- 121 122 class PBXBuildPhase : public PBXObject { 123 public: 124 PBXBuildPhase(); 125 ~PBXBuildPhase() override; 126 127 void AddBuildFile(std::unique_ptr<PBXBuildFile> build_file); 128 129 // PBXObject implementation. 130 void Visit(PBXObjectVisitor& visitor) override; 131 void Visit(PBXObjectVisitorConst& visitor) const override; 132 133 protected: 134 std::vector<std::unique_ptr<PBXBuildFile>> files_; 135 136 private: 137 PBXBuildPhase(const PBXBuildPhase&) = delete; 138 PBXBuildPhase& operator=(const PBXBuildPhase&) = delete; 139 }; 140 141 // PBXTarget ------------------------------------------------------------------ 142 143 class PBXTarget : public PBXObject { 144 public: 145 PBXTarget(const std::string& name, 146 const std::string& shell_script, 147 const std::vector<std::string>& configs, 148 const PBXAttributes& attributes); 149 ~PBXTarget() override; 150 151 void AddDependency(std::unique_ptr<PBXTargetDependency> dependency); 152 153 // PBXObject implementation. 154 std::string Name() const override; 155 void Visit(PBXObjectVisitor& visitor) override; 156 void Visit(PBXObjectVisitorConst& visitor) const override; 157 158 protected: 159 std::unique_ptr<XCConfigurationList> configurations_; 160 std::vector<std::unique_ptr<PBXBuildPhase>> build_phases_; 161 std::vector<std::unique_ptr<PBXTargetDependency>> dependencies_; 162 PBXSourcesBuildPhase* source_build_phase_ = nullptr; 163 PBXResourcesBuildPhase* resource_build_phase_ = nullptr; 164 std::string name_; 165 166 private: 167 PBXTarget(const PBXTarget&) = delete; 168 PBXTarget& operator=(const PBXTarget&) = delete; 169 }; 170 171 // PBXAggregateTarget --------------------------------------------------------- 172 173 class PBXAggregateTarget : public PBXTarget { 174 public: 175 PBXAggregateTarget(const std::string& name, 176 const std::string& shell_script, 177 const std::vector<std::string>& configs, 178 const PBXAttributes& attributes); 179 ~PBXAggregateTarget() override; 180 181 // PBXObject implementation. 182 PBXObjectClass Class() const override; 183 void Print(std::ostream& out, unsigned indent) const override; 184 185 private: 186 PBXAggregateTarget(const PBXAggregateTarget&) = delete; 187 PBXAggregateTarget& operator=(const PBXAggregateTarget&) = delete; 188 }; 189 190 // PBXBuildFile --------------------------------------------------------------- 191 192 class PBXBuildFile : public PBXObject { 193 public: 194 PBXBuildFile(const PBXFileReference* file_reference, 195 const PBXBuildPhase* build_phase); 196 ~PBXBuildFile() override; 197 198 // PBXObject implementation. 199 PBXObjectClass Class() const override; 200 std::string Name() const override; 201 void Print(std::ostream& out, unsigned indent) const override; 202 203 private: 204 const PBXFileReference* file_reference_ = nullptr; 205 const PBXBuildPhase* build_phase_ = nullptr; 206 207 PBXBuildFile(const PBXBuildFile&) = delete; 208 PBXBuildFile& operator=(const PBXBuildFile&) = delete; 209 }; 210 211 // PBXContainerItemProxy ------------------------------------------------------ 212 class PBXContainerItemProxy : public PBXObject { 213 public: 214 PBXContainerItemProxy(const PBXProject* project, const PBXTarget* target); 215 ~PBXContainerItemProxy() override; 216 217 // PBXObject implementation. 218 PBXObjectClass Class() const override; 219 std::string Name() const override; 220 void Print(std::ostream& out, unsigned indent) const override; 221 222 private: 223 const PBXProject* project_ = nullptr; 224 const PBXTarget* target_ = nullptr; 225 226 PBXContainerItemProxy(const PBXContainerItemProxy&) = delete; 227 PBXContainerItemProxy& operator=(const PBXContainerItemProxy&) = delete; 228 }; 229 230 // PBXFileReference ----------------------------------------------------------- 231 232 class PBXFileReference : public PBXObject { 233 public: 234 PBXFileReference(const std::string& name, 235 const std::string& path, 236 const std::string& type); 237 ~PBXFileReference() override; 238 239 // PBXObject implementation. 240 PBXObjectClass Class() const override; 241 std::string Name() const override; 242 std::string Comment() const override; 243 void Print(std::ostream& out, unsigned indent) const override; 244 path()245 const std::string& path() const { return path_; } 246 247 private: 248 std::string name_; 249 std::string path_; 250 std::string type_; 251 252 PBXFileReference(const PBXFileReference&) = delete; 253 PBXFileReference& operator=(const PBXFileReference&) = delete; 254 }; 255 256 // PBXFrameworksBuildPhase ---------------------------------------------------- 257 258 class PBXFrameworksBuildPhase : public PBXBuildPhase { 259 public: 260 PBXFrameworksBuildPhase(); 261 ~PBXFrameworksBuildPhase() override; 262 263 // PBXObject implementation. 264 PBXObjectClass Class() const override; 265 std::string Name() const override; 266 void Print(std::ostream& out, unsigned indent) const override; 267 268 private: 269 PBXFrameworksBuildPhase(const PBXFrameworksBuildPhase&) = delete; 270 PBXFrameworksBuildPhase& operator=(const PBXFrameworksBuildPhase&) = delete; 271 }; 272 273 // PBXGroup ------------------------------------------------------------------- 274 275 class PBXGroup : public PBXObject { 276 public: 277 explicit PBXGroup(const std::string& path = std::string(), 278 const std::string& name = std::string()); 279 ~PBXGroup() override; 280 path()281 const std::string& path() const { return path_; } name()282 const std::string& name() const { return name_; } 283 284 PBXFileReference* AddSourceFile(const std::string& navigator_path, 285 const std::string& source_path); 286 287 template <typename T, typename... Args> CreateChild(Args &&...args)288 T* CreateChild(Args&&... args) { 289 return static_cast<T*>( 290 AddChildImpl(std::make_unique<T>(std::forward<Args>(args)...))); 291 } 292 293 // PBXObject implementation. 294 PBXObjectClass Class() const override; 295 std::string Name() const override; 296 void Visit(PBXObjectVisitor& visitor) override; 297 void Visit(PBXObjectVisitorConst& visitor) const override; 298 void Print(std::ostream& out, unsigned indent) const override; 299 300 // Returns whether the current PBXGroup should sort last when sorting 301 // children of a PBXGroup. This should only be used for the "Products" 302 // group which is hidden in Xcode UI when it is the last children of 303 // the main PBXProject group. 304 virtual bool SortLast() const; 305 306 private: 307 PBXObject* AddChildImpl(std::unique_ptr<PBXObject> child); 308 309 std::vector<std::unique_ptr<PBXObject>> children_; 310 std::string name_; 311 std::string path_; 312 313 PBXGroup(const PBXGroup&) = delete; 314 PBXGroup& operator=(const PBXGroup&) = delete; 315 }; 316 317 // PBXMainGroup --------------------------------------------------------------- 318 319 class PBXMainGroup : public PBXGroup { 320 public: 321 explicit PBXMainGroup(const std::string& source_path); 322 ~PBXMainGroup() override; 323 324 std::string Name() const override; 325 }; 326 327 // PBXProductsGroup ----------------------------------------------------------- 328 329 class PBXProductsGroup : public PBXGroup { 330 public: 331 explicit PBXProductsGroup(); 332 ~PBXProductsGroup() override; 333 334 bool SortLast() const override; 335 }; 336 337 // PBXNativeTarget ------------------------------------------------------------ 338 339 class PBXNativeTarget : public PBXTarget { 340 public: 341 PBXNativeTarget(const std::string& name, 342 const std::string& shell_script, 343 const std::vector<std::string>& configs, 344 const PBXAttributes& attributes, 345 const std::string& product_type, 346 const std::string& product_name, 347 const PBXFileReference* product_reference); 348 ~PBXNativeTarget() override; 349 350 void AddResourceFile(const PBXFileReference* file_reference); 351 352 void AddFileForIndexing(const PBXFileReference* file_reference); 353 354 // PBXObject implementation. 355 PBXObjectClass Class() const override; 356 void Print(std::ostream& out, unsigned indent) const override; 357 358 private: 359 const PBXFileReference* product_reference_ = nullptr; 360 std::string product_type_; 361 std::string product_name_; 362 363 PBXNativeTarget(const PBXNativeTarget&) = delete; 364 PBXNativeTarget& operator=(const PBXNativeTarget&) = delete; 365 }; 366 367 // PBXProject ----------------------------------------------------------------- 368 369 class PBXProject : public PBXObject { 370 public: 371 PBXProject(const std::string& name, 372 std::vector<std::string> configs, 373 const std::string& source_path, 374 const PBXAttributes& attributes); 375 ~PBXProject() override; 376 377 void AddSourceFileToIndexingTarget(const std::string& navigator_path, 378 const std::string& source_path); 379 void AddSourceFile(const std::string& navigator_path, 380 const std::string& source_path, 381 PBXNativeTarget* target); 382 void AddAggregateTarget(const std::string& name, 383 const std::string& output_dir, 384 const std::string& shell_script); 385 void AddIndexingTarget(); 386 PBXNativeTarget* AddNativeTarget( 387 const std::string& name, 388 const std::string& type, 389 const std::string& output_dir, 390 const std::string& output_name, 391 const std::string& output_type, 392 const std::string& shell_script, 393 const PBXAttributes& extra_attributes = PBXAttributes()); 394 395 void SetProjectDirPath(const std::string& project_dir_path); 396 void SetProjectRoot(const std::string& project_root); 397 void AddTarget(std::unique_ptr<PBXTarget> target); 398 399 // PBXObject implementation. 400 PBXObjectClass Class() const override; 401 std::string Name() const override; 402 std::string Comment() const override; 403 void Visit(PBXObjectVisitor& visitor) override; 404 void Visit(PBXObjectVisitorConst& visitor) const override; 405 void Print(std::ostream& out, unsigned indent) const override; 406 407 private: 408 PBXAttributes attributes_; 409 std::unique_ptr<XCConfigurationList> configurations_; 410 std::unique_ptr<PBXGroup> main_group_; 411 std::string project_dir_path_; 412 std::string project_root_; 413 std::vector<std::unique_ptr<PBXTarget>> targets_; 414 std::string name_; 415 std::vector<std::string> configs_; 416 417 PBXGroup* products_ = nullptr; 418 PBXNativeTarget* target_for_indexing_ = nullptr; 419 420 PBXProject(const PBXProject&) = delete; 421 PBXProject& operator=(const PBXProject&) = delete; 422 }; 423 424 // PBXResourcesBuildPhase ----------------------------------------------------- 425 426 class PBXResourcesBuildPhase : public PBXBuildPhase { 427 public: 428 PBXResourcesBuildPhase(); 429 ~PBXResourcesBuildPhase() override; 430 431 // PBXObject implementation. 432 PBXObjectClass Class() const override; 433 std::string Name() const override; 434 void Print(std::ostream& out, unsigned indent) const override; 435 436 private: 437 PBXResourcesBuildPhase(const PBXResourcesBuildPhase&) = delete; 438 PBXResourcesBuildPhase& operator=(const PBXResourcesBuildPhase&) = delete; 439 }; 440 441 // PBXShellScriptBuildPhase --------------------------------------------------- 442 443 class PBXShellScriptBuildPhase : public PBXBuildPhase { 444 public: 445 PBXShellScriptBuildPhase(const std::string& name, 446 const std::string& shell_script); 447 ~PBXShellScriptBuildPhase() override; 448 449 // PBXObject implementation. 450 PBXObjectClass Class() const override; 451 std::string Name() const override; 452 void Print(std::ostream& out, unsigned indent) const override; 453 454 private: 455 std::string name_; 456 std::string shell_script_; 457 458 PBXShellScriptBuildPhase(const PBXShellScriptBuildPhase&) = delete; 459 PBXShellScriptBuildPhase& operator=(const PBXShellScriptBuildPhase&) = delete; 460 }; 461 462 // PBXSourcesBuildPhase ------------------------------------------------------- 463 464 class PBXSourcesBuildPhase : public PBXBuildPhase { 465 public: 466 PBXSourcesBuildPhase(); 467 ~PBXSourcesBuildPhase() override; 468 469 // PBXObject implementation. 470 PBXObjectClass Class() const override; 471 std::string Name() const override; 472 void Print(std::ostream& out, unsigned indent) const override; 473 474 private: 475 PBXSourcesBuildPhase(const PBXSourcesBuildPhase&) = delete; 476 PBXSourcesBuildPhase& operator=(const PBXSourcesBuildPhase&) = delete; 477 }; 478 479 // PBXTargetDependency ----------------------------------------------------- 480 class PBXTargetDependency : public PBXObject { 481 public: 482 PBXTargetDependency( 483 const PBXTarget* target, 484 std::unique_ptr<PBXContainerItemProxy> container_item_proxy); 485 ~PBXTargetDependency() override; 486 487 // PBXObject implementation. 488 PBXObjectClass Class() const override; 489 std::string Name() const override; 490 void Visit(PBXObjectVisitor& visitor) override; 491 void Visit(PBXObjectVisitorConst& visitor) const override; 492 void Print(std::ostream& out, unsigned indent) const override; 493 494 private: 495 const PBXTarget* target_ = nullptr; 496 std::unique_ptr<PBXContainerItemProxy> container_item_proxy_; 497 498 PBXTargetDependency(const PBXTargetDependency&) = delete; 499 PBXTargetDependency& operator=(const PBXTargetDependency&) = delete; 500 }; 501 502 // XCBuildConfiguration ------------------------------------------------------- 503 504 class XCBuildConfiguration : public PBXObject { 505 public: 506 XCBuildConfiguration(const std::string& name, 507 const PBXAttributes& attributes); 508 ~XCBuildConfiguration() override; 509 510 // PBXObject implementation. 511 PBXObjectClass Class() const override; 512 std::string Name() const override; 513 void Print(std::ostream& out, unsigned indent) const override; 514 515 private: 516 PBXAttributes attributes_; 517 std::string name_; 518 519 XCBuildConfiguration(const XCBuildConfiguration&) = delete; 520 XCBuildConfiguration& operator=(const XCBuildConfiguration&) = delete; 521 }; 522 523 // XCConfigurationList -------------------------------------------------------- 524 525 class XCConfigurationList : public PBXObject { 526 public: 527 XCConfigurationList(const std::vector<std::string>& configs, 528 const PBXAttributes& attributes, 529 const PBXObject* owner_reference); 530 ~XCConfigurationList() override; 531 532 // PBXObject implementation. 533 PBXObjectClass Class() const override; 534 std::string Name() const override; 535 void Visit(PBXObjectVisitor& visitor) override; 536 void Visit(PBXObjectVisitorConst& visitor) const override; 537 void Print(std::ostream& out, unsigned indent) const override; 538 539 private: 540 std::vector<std::unique_ptr<XCBuildConfiguration>> configurations_; 541 const PBXObject* owner_reference_ = nullptr; 542 543 XCConfigurationList(const XCConfigurationList&) = delete; 544 XCConfigurationList& operator=(const XCConfigurationList&) = delete; 545 }; 546 547 #endif // TOOLS_GN_XCODE_OBJECT_H_ 548