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