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::string& config_name,
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::string& config_name,
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 
is_source()287   bool is_source() const { return is_source_; }
set_is_source(bool is_source)288   void set_is_source(bool is_source) { is_source_ = is_source; }
289 
autosorted()290   bool autosorted() const { return autosorted_; }
set_autosorted(bool autosorted)291   void set_autosorted(bool autosorted) { autosorted_ = autosorted; }
292 
293   template <typename T, typename... Args>
CreateChild(Args &&...args)294   T* CreateChild(Args&&... args) {
295     return static_cast<T*>(
296         AddChildImpl(std::make_unique<T>(std::forward<Args>(args)...)));
297   }
298 
299   // PBXObject implementation.
300   PBXObjectClass Class() const override;
301   std::string Name() const override;
302   void Visit(PBXObjectVisitor& visitor) override;
303   void Visit(PBXObjectVisitorConst& visitor) const override;
304   void Print(std::ostream& out, unsigned indent) const override;
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   bool is_source_ = false;
313   bool autosorted_ = true;
314 
315   PBXGroup(const PBXGroup&) = delete;
316   PBXGroup& operator=(const PBXGroup&) = delete;
317 };
318 
319 // PBXNativeTarget ------------------------------------------------------------
320 
321 class PBXNativeTarget : public PBXTarget {
322  public:
323   PBXNativeTarget(const std::string& name,
324                   const std::string& shell_script,
325                   const std::string& config_name,
326                   const PBXAttributes& attributes,
327                   const std::string& product_type,
328                   const std::string& product_name,
329                   const PBXFileReference* product_reference);
330   ~PBXNativeTarget() override;
331 
332   void AddResourceFile(const PBXFileReference* file_reference);
333 
334   void AddFileForIndexing(const PBXFileReference* file_reference);
335 
336   // PBXObject implementation.
337   PBXObjectClass Class() const override;
338   void Print(std::ostream& out, unsigned indent) const override;
339 
340  private:
341   const PBXFileReference* product_reference_ = nullptr;
342   std::string product_type_;
343   std::string product_name_;
344 
345   PBXNativeTarget(const PBXNativeTarget&) = delete;
346   PBXNativeTarget& operator=(const PBXNativeTarget&) = delete;
347 };
348 
349 // PBXProject -----------------------------------------------------------------
350 
351 class PBXProject : public PBXObject {
352  public:
353   PBXProject(const std::string& name,
354              const std::string& config_name,
355              const std::string& source_path,
356              const PBXAttributes& attributes);
357   ~PBXProject() override;
358 
359   void AddSourceFileToIndexingTarget(const std::string& navigator_path,
360                                      const std::string& source_path);
361   void AddSourceFile(const std::string& navigator_path,
362                      const std::string& source_path,
363                      PBXNativeTarget* target);
364   void AddAggregateTarget(const std::string& name,
365                           const std::string& shell_script);
366   void AddIndexingTarget();
367   PBXNativeTarget* AddNativeTarget(
368       const std::string& name,
369       const std::string& type,
370       const std::string& output_dir,
371       const std::string& output_name,
372       const std::string& output_type,
373       const std::string& shell_script,
374       const PBXAttributes& extra_attributes = PBXAttributes());
375 
376   void SetProjectDirPath(const std::string& project_dir_path);
377   void SetProjectRoot(const std::string& project_root);
378   void AddTarget(std::unique_ptr<PBXTarget> target);
379 
380   // PBXObject implementation.
381   PBXObjectClass Class() const override;
382   std::string Name() const override;
383   std::string Comment() const override;
384   void Visit(PBXObjectVisitor& visitor) override;
385   void Visit(PBXObjectVisitorConst& visitor) const override;
386   void Print(std::ostream& out, unsigned indent) const override;
387 
388  private:
389   PBXAttributes attributes_;
390   std::unique_ptr<XCConfigurationList> configurations_;
391   std::unique_ptr<PBXGroup> main_group_;
392   std::string project_dir_path_;
393   std::string project_root_;
394   std::vector<std::unique_ptr<PBXTarget>> targets_;
395   std::string name_;
396   std::string config_name_;
397 
398   PBXGroup* sources_ = nullptr;
399   PBXGroup* products_ = nullptr;
400   PBXNativeTarget* target_for_indexing_ = nullptr;
401 
402   PBXProject(const PBXProject&) = delete;
403   PBXProject& operator=(const PBXProject&) = delete;
404 };
405 
406 // PBXResourcesBuildPhase -----------------------------------------------------
407 
408 class PBXResourcesBuildPhase : public PBXBuildPhase {
409  public:
410   PBXResourcesBuildPhase();
411   ~PBXResourcesBuildPhase() override;
412 
413   // PBXObject implementation.
414   PBXObjectClass Class() const override;
415   std::string Name() const override;
416   void Print(std::ostream& out, unsigned indent) const override;
417 
418  private:
419   PBXResourcesBuildPhase(const PBXResourcesBuildPhase&) = delete;
420   PBXResourcesBuildPhase& operator=(const PBXResourcesBuildPhase&) = delete;
421 };
422 
423 // PBXShellScriptBuildPhase ---------------------------------------------------
424 
425 class PBXShellScriptBuildPhase : public PBXBuildPhase {
426  public:
427   PBXShellScriptBuildPhase(const std::string& name,
428                            const std::string& shell_script);
429   ~PBXShellScriptBuildPhase() 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   std::string name_;
438   std::string shell_script_;
439 
440   PBXShellScriptBuildPhase(const PBXShellScriptBuildPhase&) = delete;
441   PBXShellScriptBuildPhase& operator=(const PBXShellScriptBuildPhase&) = delete;
442 };
443 
444 // PBXSourcesBuildPhase -------------------------------------------------------
445 
446 class PBXSourcesBuildPhase : public PBXBuildPhase {
447  public:
448   PBXSourcesBuildPhase();
449   ~PBXSourcesBuildPhase() override;
450 
451   // PBXObject implementation.
452   PBXObjectClass Class() const override;
453   std::string Name() const override;
454   void Print(std::ostream& out, unsigned indent) const override;
455 
456  private:
457   PBXSourcesBuildPhase(const PBXSourcesBuildPhase&) = delete;
458   PBXSourcesBuildPhase& operator=(const PBXSourcesBuildPhase&) = delete;
459 };
460 
461 // PBXTargetDependency -----------------------------------------------------
462 class PBXTargetDependency : public PBXObject {
463  public:
464   PBXTargetDependency(
465       const PBXTarget* target,
466       std::unique_ptr<PBXContainerItemProxy> container_item_proxy);
467   ~PBXTargetDependency() override;
468 
469   // PBXObject implementation.
470   PBXObjectClass Class() const override;
471   std::string Name() const override;
472   void Visit(PBXObjectVisitor& visitor) override;
473   void Visit(PBXObjectVisitorConst& visitor) const override;
474   void Print(std::ostream& out, unsigned indent) const override;
475 
476  private:
477   const PBXTarget* target_ = nullptr;
478   std::unique_ptr<PBXContainerItemProxy> container_item_proxy_;
479 
480   PBXTargetDependency(const PBXTargetDependency&) = delete;
481   PBXTargetDependency& operator=(const PBXTargetDependency&) = delete;
482 };
483 
484 // XCBuildConfiguration -------------------------------------------------------
485 
486 class XCBuildConfiguration : public PBXObject {
487  public:
488   XCBuildConfiguration(const std::string& name,
489                        const PBXAttributes& attributes);
490   ~XCBuildConfiguration() override;
491 
492   // PBXObject implementation.
493   PBXObjectClass Class() const override;
494   std::string Name() const override;
495   void Print(std::ostream& out, unsigned indent) const override;
496 
497  private:
498   PBXAttributes attributes_;
499   std::string name_;
500 
501   XCBuildConfiguration(const XCBuildConfiguration&) = delete;
502   XCBuildConfiguration& operator=(const XCBuildConfiguration&) = delete;
503 };
504 
505 // XCConfigurationList --------------------------------------------------------
506 
507 class XCConfigurationList : public PBXObject {
508  public:
509   XCConfigurationList(const std::string& name,
510                       const PBXAttributes& attributes,
511                       const PBXObject* owner_reference);
512   ~XCConfigurationList() override;
513 
514   // PBXObject implementation.
515   PBXObjectClass Class() const override;
516   std::string Name() const override;
517   void Visit(PBXObjectVisitor& visitor) override;
518   void Visit(PBXObjectVisitorConst& visitor) const override;
519   void Print(std::ostream& out, unsigned indent) const override;
520 
521  private:
522   std::vector<std::unique_ptr<XCBuildConfiguration>> configurations_;
523   const PBXObject* owner_reference_ = nullptr;
524 
525   XCConfigurationList(const XCConfigurationList&) = delete;
526   XCConfigurationList& operator=(const XCConfigurationList&) = delete;
527 };
528 
529 #endif  // TOOLS_GN_XCODE_OBJECT_H_
530