// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef TOOLS_GN_XCODE_OBJECT_H_ #define TOOLS_GN_XCODE_OBJECT_H_ #include #include #include #include #include // Helper classes to generate Xcode project files. // // This code is based on gyp xcodeproj_file.py generator. It does not support // all features of Xcode project but instead just enough to implement a hybrid // mode where Xcode uses external scripts to perform the compilation steps. // // See // https://chromium.googlesource.com/external/gyp/+/master/pylib/gyp/xcodeproj_file.py // for more information on Xcode project file format. // PBXObjectClass ------------------------------------------------------------- enum PBXObjectClass { // Those values needs to stay sorted in alphabetic order. PBXAggregateTargetClass, PBXBuildFileClass, PBXContainerItemProxyClass, PBXFileReferenceClass, PBXFrameworksBuildPhaseClass, PBXGroupClass, PBXNativeTargetClass, PBXProjectClass, PBXResourcesBuildPhaseClass, PBXShellScriptBuildPhaseClass, PBXSourcesBuildPhaseClass, PBXTargetDependencyClass, XCBuildConfigurationClass, XCConfigurationListClass, }; const char* ToString(PBXObjectClass cls); // Forward-declarations ------------------------------------------------------- class PBXAggregateTarget; class PBXBuildFile; class PBXBuildPhase; class PBXContainerItemProxy; class PBXFileReference; class PBXFrameworksBuildPhase; class PBXGroup; class PBXNativeTarget; class PBXObject; class PBXProject; class PBXResourcesBuildPhase; class PBXShellScriptBuildPhase; class PBXSourcesBuildPhase; class PBXTarget; class PBXTargetDependency; class XCBuildConfiguration; class XCConfigurationList; using PBXAttributes = std::map; // PBXObjectVisitor ----------------------------------------------------------- class PBXObjectVisitor { public: PBXObjectVisitor(); virtual ~PBXObjectVisitor(); virtual void Visit(PBXObject* object) = 0; private: PBXObjectVisitor(const PBXObjectVisitor&) = delete; PBXObjectVisitor& operator=(const PBXObjectVisitor&) = delete; }; // PBXObjectVisitorConst ------------------------------------------------------ class PBXObjectVisitorConst { public: PBXObjectVisitorConst(); virtual ~PBXObjectVisitorConst(); virtual void Visit(const PBXObject* object) = 0; private: PBXObjectVisitorConst(const PBXObjectVisitorConst&) = delete; PBXObjectVisitorConst& operator=(const PBXObjectVisitorConst&) = delete; }; // PBXObject ------------------------------------------------------------------ class PBXObject { public: PBXObject(); virtual ~PBXObject(); const std::string id() const { return id_; } void SetId(const std::string& id); std::string Reference() const; virtual PBXObjectClass Class() const = 0; virtual std::string Name() const = 0; virtual std::string Comment() const; virtual void Visit(PBXObjectVisitor& visitor); virtual void Visit(PBXObjectVisitorConst& visitor) const; virtual void Print(std::ostream& out, unsigned indent) const = 0; private: std::string id_; PBXObject(const PBXObject&) = delete; PBXObject& operator=(const PBXObject&) = delete; }; // PBXBuildPhase -------------------------------------------------------------- class PBXBuildPhase : public PBXObject { public: PBXBuildPhase(); ~PBXBuildPhase() override; void AddBuildFile(std::unique_ptr build_file); // PBXObject implementation. void Visit(PBXObjectVisitor& visitor) override; void Visit(PBXObjectVisitorConst& visitor) const override; protected: std::vector> files_; private: PBXBuildPhase(const PBXBuildPhase&) = delete; PBXBuildPhase& operator=(const PBXBuildPhase&) = delete; }; // PBXTarget ------------------------------------------------------------------ class PBXTarget : public PBXObject { public: PBXTarget(const std::string& name, const std::string& shell_script, const std::vector& configs, const PBXAttributes& attributes); ~PBXTarget() override; void AddDependency(std::unique_ptr dependency); // PBXObject implementation. std::string Name() const override; void Visit(PBXObjectVisitor& visitor) override; void Visit(PBXObjectVisitorConst& visitor) const override; protected: std::unique_ptr configurations_; std::vector> build_phases_; std::vector> dependencies_; PBXSourcesBuildPhase* source_build_phase_ = nullptr; PBXResourcesBuildPhase* resource_build_phase_ = nullptr; std::string name_; private: PBXTarget(const PBXTarget&) = delete; PBXTarget& operator=(const PBXTarget&) = delete; }; // PBXAggregateTarget --------------------------------------------------------- class PBXAggregateTarget : public PBXTarget { public: PBXAggregateTarget(const std::string& name, const std::string& shell_script, const std::vector& configs, const PBXAttributes& attributes); ~PBXAggregateTarget() override; // PBXObject implementation. PBXObjectClass Class() const override; void Print(std::ostream& out, unsigned indent) const override; private: PBXAggregateTarget(const PBXAggregateTarget&) = delete; PBXAggregateTarget& operator=(const PBXAggregateTarget&) = delete; }; // PBXBuildFile --------------------------------------------------------------- class PBXBuildFile : public PBXObject { public: PBXBuildFile(const PBXFileReference* file_reference, const PBXBuildPhase* build_phase); ~PBXBuildFile() override; // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; void Print(std::ostream& out, unsigned indent) const override; private: const PBXFileReference* file_reference_ = nullptr; const PBXBuildPhase* build_phase_ = nullptr; PBXBuildFile(const PBXBuildFile&) = delete; PBXBuildFile& operator=(const PBXBuildFile&) = delete; }; // PBXContainerItemProxy ------------------------------------------------------ class PBXContainerItemProxy : public PBXObject { public: PBXContainerItemProxy(const PBXProject* project, const PBXTarget* target); ~PBXContainerItemProxy() override; // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; void Print(std::ostream& out, unsigned indent) const override; private: const PBXProject* project_ = nullptr; const PBXTarget* target_ = nullptr; PBXContainerItemProxy(const PBXContainerItemProxy&) = delete; PBXContainerItemProxy& operator=(const PBXContainerItemProxy&) = delete; }; // PBXFileReference ----------------------------------------------------------- class PBXFileReference : public PBXObject { public: PBXFileReference(const std::string& name, const std::string& path, const std::string& type); ~PBXFileReference() override; // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; std::string Comment() const override; void Print(std::ostream& out, unsigned indent) const override; const std::string& path() const { return path_; } private: std::string name_; std::string path_; std::string type_; PBXFileReference(const PBXFileReference&) = delete; PBXFileReference& operator=(const PBXFileReference&) = delete; }; // PBXFrameworksBuildPhase ---------------------------------------------------- class PBXFrameworksBuildPhase : public PBXBuildPhase { public: PBXFrameworksBuildPhase(); ~PBXFrameworksBuildPhase() override; // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; void Print(std::ostream& out, unsigned indent) const override; private: PBXFrameworksBuildPhase(const PBXFrameworksBuildPhase&) = delete; PBXFrameworksBuildPhase& operator=(const PBXFrameworksBuildPhase&) = delete; }; // PBXGroup ------------------------------------------------------------------- class PBXGroup : public PBXObject { public: explicit PBXGroup(const std::string& path = std::string(), const std::string& name = std::string()); ~PBXGroup() override; const std::string& path() const { return path_; } const std::string& name() const { return name_; } PBXFileReference* AddSourceFile(const std::string& navigator_path, const std::string& source_path); template T* CreateChild(Args&&... args) { return static_cast( AddChildImpl(std::make_unique(std::forward(args)...))); } // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; void Visit(PBXObjectVisitor& visitor) override; void Visit(PBXObjectVisitorConst& visitor) const override; void Print(std::ostream& out, unsigned indent) const override; // Returns whether the current PBXGroup should sort last when sorting // children of a PBXGroup. This should only be used for the "Products" // group which is hidden in Xcode UI when it is the last children of // the main PBXProject group. virtual bool SortLast() const; private: PBXObject* AddChildImpl(std::unique_ptr child); std::vector> children_; std::string name_; std::string path_; PBXGroup(const PBXGroup&) = delete; PBXGroup& operator=(const PBXGroup&) = delete; }; // PBXMainGroup --------------------------------------------------------------- class PBXMainGroup : public PBXGroup { public: explicit PBXMainGroup(const std::string& source_path); ~PBXMainGroup() override; std::string Name() const override; }; // PBXProductsGroup ----------------------------------------------------------- class PBXProductsGroup : public PBXGroup { public: explicit PBXProductsGroup(); ~PBXProductsGroup() override; bool SortLast() const override; }; // PBXNativeTarget ------------------------------------------------------------ class PBXNativeTarget : public PBXTarget { public: PBXNativeTarget(const std::string& name, const std::string& shell_script, const std::vector& configs, const PBXAttributes& attributes, const std::string& product_type, const std::string& product_name, const PBXFileReference* product_reference); ~PBXNativeTarget() override; void AddResourceFile(const PBXFileReference* file_reference); void AddFileForIndexing(const PBXFileReference* file_reference); // PBXObject implementation. PBXObjectClass Class() const override; void Print(std::ostream& out, unsigned indent) const override; private: const PBXFileReference* product_reference_ = nullptr; std::string product_type_; std::string product_name_; PBXNativeTarget(const PBXNativeTarget&) = delete; PBXNativeTarget& operator=(const PBXNativeTarget&) = delete; }; // PBXProject ----------------------------------------------------------------- class PBXProject : public PBXObject { public: PBXProject(const std::string& name, std::vector configs, const std::string& source_path, const PBXAttributes& attributes); ~PBXProject() override; void AddSourceFileToIndexingTarget(const std::string& navigator_path, const std::string& source_path); void AddSourceFile(const std::string& navigator_path, const std::string& source_path, PBXNativeTarget* target); void AddAggregateTarget(const std::string& name, const std::string& output_dir, const std::string& shell_script); void AddIndexingTarget(); PBXNativeTarget* AddNativeTarget( const std::string& name, const std::string& type, const std::string& output_dir, const std::string& output_name, const std::string& output_type, const std::string& shell_script, const PBXAttributes& extra_attributes = PBXAttributes()); void SetProjectDirPath(const std::string& project_dir_path); void SetProjectRoot(const std::string& project_root); void AddTarget(std::unique_ptr target); // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; std::string Comment() const override; void Visit(PBXObjectVisitor& visitor) override; void Visit(PBXObjectVisitorConst& visitor) const override; void Print(std::ostream& out, unsigned indent) const override; private: PBXAttributes attributes_; std::unique_ptr configurations_; std::unique_ptr main_group_; std::string project_dir_path_; std::string project_root_; std::vector> targets_; std::string name_; std::vector configs_; PBXGroup* products_ = nullptr; PBXNativeTarget* target_for_indexing_ = nullptr; PBXProject(const PBXProject&) = delete; PBXProject& operator=(const PBXProject&) = delete; }; // PBXResourcesBuildPhase ----------------------------------------------------- class PBXResourcesBuildPhase : public PBXBuildPhase { public: PBXResourcesBuildPhase(); ~PBXResourcesBuildPhase() override; // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; void Print(std::ostream& out, unsigned indent) const override; private: PBXResourcesBuildPhase(const PBXResourcesBuildPhase&) = delete; PBXResourcesBuildPhase& operator=(const PBXResourcesBuildPhase&) = delete; }; // PBXShellScriptBuildPhase --------------------------------------------------- class PBXShellScriptBuildPhase : public PBXBuildPhase { public: PBXShellScriptBuildPhase(const std::string& name, const std::string& shell_script); ~PBXShellScriptBuildPhase() override; // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; void Print(std::ostream& out, unsigned indent) const override; private: std::string name_; std::string shell_script_; PBXShellScriptBuildPhase(const PBXShellScriptBuildPhase&) = delete; PBXShellScriptBuildPhase& operator=(const PBXShellScriptBuildPhase&) = delete; }; // PBXSourcesBuildPhase ------------------------------------------------------- class PBXSourcesBuildPhase : public PBXBuildPhase { public: PBXSourcesBuildPhase(); ~PBXSourcesBuildPhase() override; // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; void Print(std::ostream& out, unsigned indent) const override; private: PBXSourcesBuildPhase(const PBXSourcesBuildPhase&) = delete; PBXSourcesBuildPhase& operator=(const PBXSourcesBuildPhase&) = delete; }; // PBXTargetDependency ----------------------------------------------------- class PBXTargetDependency : public PBXObject { public: PBXTargetDependency( const PBXTarget* target, std::unique_ptr container_item_proxy); ~PBXTargetDependency() override; // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; void Visit(PBXObjectVisitor& visitor) override; void Visit(PBXObjectVisitorConst& visitor) const override; void Print(std::ostream& out, unsigned indent) const override; private: const PBXTarget* target_ = nullptr; std::unique_ptr container_item_proxy_; PBXTargetDependency(const PBXTargetDependency&) = delete; PBXTargetDependency& operator=(const PBXTargetDependency&) = delete; }; // XCBuildConfiguration ------------------------------------------------------- class XCBuildConfiguration : public PBXObject { public: XCBuildConfiguration(const std::string& name, const PBXAttributes& attributes); ~XCBuildConfiguration() override; // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; void Print(std::ostream& out, unsigned indent) const override; private: PBXAttributes attributes_; std::string name_; XCBuildConfiguration(const XCBuildConfiguration&) = delete; XCBuildConfiguration& operator=(const XCBuildConfiguration&) = delete; }; // XCConfigurationList -------------------------------------------------------- class XCConfigurationList : public PBXObject { public: XCConfigurationList(const std::vector& configs, const PBXAttributes& attributes, const PBXObject* owner_reference); ~XCConfigurationList() override; // PBXObject implementation. PBXObjectClass Class() const override; std::string Name() const override; void Visit(PBXObjectVisitor& visitor) override; void Visit(PBXObjectVisitorConst& visitor) const override; void Print(std::ostream& out, unsigned indent) const override; private: std::vector> configurations_; const PBXObject* owner_reference_ = nullptr; XCConfigurationList(const XCConfigurationList&) = delete; XCConfigurationList& operator=(const XCConfigurationList&) = delete; }; #endif // TOOLS_GN_XCODE_OBJECT_H_