c3df7d9358fc2016735702d5a9ba2a4fc8e809ec
[platform/upstream/cmake.git] / Source / cmGlobalNinjaGenerator.h
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
4   Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>
5
6   Distributed under the OSI-approved BSD License (the "License");
7   see accompanying file Copyright.txt for details.
8
9   This software is distributed WITHOUT ANY WARRANTY; without even the
10   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11   See the License for more information.
12 ============================================================================*/
13 #ifndef cmGlobalNinjaGenerator_h
14 #  define cmGlobalNinjaGenerator_h
15
16 #  include "cmGlobalGenerator.h"
17 #  include "cmGlobalGeneratorFactory.h"
18 #  include "cmNinjaTypes.h"
19
20 //#define NINJA_GEN_VERBOSE_FILES
21
22 class cmLocalGenerator;
23 class cmGeneratedFileStream;
24 class cmGeneratorTarget;
25
26 /**
27  * \class cmGlobalNinjaGenerator
28  * \brief Write a build.ninja file.
29  *
30  * The main differences between this generator and the UnixMakefile
31  * generator family are:
32  * - We don't care about VERBOSE variable or RULE_MESSAGES property since
33  *   it is handle by Ninja's -v option.
34  * - We don't care about computing any progress status since Ninja manages
35  *   it itself.
36  * - We don't care about generating a clean target since Ninja already have
37  *   a clean tool.
38  * - We generate one build.ninja and one rules.ninja per project.
39  * - We try to minimize the number of generated rules: one per target and
40  *   language.
41  * - We use Ninja special variable $in and $out to produce nice output.
42  * - We extensively use Ninja variable overloading system to minimize the
43  *   number of generated rules.
44  */
45 class cmGlobalNinjaGenerator : public cmGlobalGenerator
46 {
47 public:
48   /// The default name of Ninja's build file. Typically: build.ninja.
49   static const char* NINJA_BUILD_FILE;
50
51   /// The default name of Ninja's rules file. Typically: rules.ninja.
52   /// It is included in the main build.ninja file.
53   static const char* NINJA_RULES_FILE;
54
55   /// The indentation string used when generating Ninja's build file.
56   static const char* INDENT;
57
58   /// Write @a count times INDENT level to output stream @a os.
59   static void Indent(std::ostream& os, int count);
60
61   /// Write a divider in the given output stream @a os.
62   static void WriteDivider(std::ostream& os);
63
64   static std::string EncodeIdent(const std::string &ident, std::ostream &vars);
65   static std::string EncodeLiteral(const std::string &lit);
66   static std::string EncodePath(const std::string &path);
67
68   /**
69    * Write the given @a comment to the output stream @a os. It
70    * handles new line character properly.
71    */
72   static void WriteComment(std::ostream& os, const std::string& comment);
73
74   /**
75    * Write a build statement to @a os with the @a comment using
76    * the @a rule the list of @a outputs files and inputs.
77    * It also writes the variables bound to this build statement.
78    * @warning no escaping of any kind is done here.
79    */
80   static void WriteBuild(std::ostream& os,
81                          const std::string& comment,
82                          const std::string& rule,
83                          const cmNinjaDeps& outputs,
84                          const cmNinjaDeps& explicitDeps,
85                          const cmNinjaDeps& implicitDeps,
86                          const cmNinjaDeps& orderOnlyDeps,
87                          const cmNinjaVars& variables,
88                          const std::string& rspfile = std::string(),
89                          int cmdLineLimit = -1);
90
91   /**
92    * Helper to write a build statement with the special 'phony' rule.
93    */
94   static void WritePhonyBuild(std::ostream& os,
95                               const std::string& comment,
96                               const cmNinjaDeps& outputs,
97                               const cmNinjaDeps& explicitDeps,
98                               const cmNinjaDeps& implicitDeps = cmNinjaDeps(),
99                               const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps(),
100                               const cmNinjaVars& variables = cmNinjaVars());
101
102   void WriteCustomCommandBuild(const std::string& command,
103                                const std::string& description,
104                                const std::string& comment,
105                                const cmNinjaDeps& outputs,
106                                const cmNinjaDeps& deps = cmNinjaDeps(),
107                              const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps());
108   void WriteMacOSXContentBuild(const std::string& input,
109                                const std::string& output);
110
111   /**
112    * Write a rule statement named @a name to @a os with the @a comment,
113    * the mandatory @a command, the @a depfile and the @a description.
114    * It also writes the variables bound to this rule statement.
115    * @warning no escaping of any kind is done here.
116    */
117   static void WriteRule(std::ostream& os,
118                         const std::string& name,
119                         const std::string& command,
120                         const std::string& description,
121                         const std::string& comment,
122                         const std::string& depfile,
123                         const std::string& rspfile,
124                         const std::string& rspcontent,
125                         bool restat,
126                         bool generator);
127
128   /**
129    * Write a variable named @a name to @a os with value @a value and an
130    * optional @a comment. An @a indent level can be specified.
131    * @warning no escaping of any kind is done here.
132    */
133   static void WriteVariable(std::ostream& os,
134                             const std::string& name,
135                             const std::string& value,
136                             const std::string& comment = "",
137                             int indent = 0);
138
139   /**
140    * Write an include statement including @a filename with an optional
141    * @a comment to the @a os stream.
142    */
143   static void WriteInclude(std::ostream& os,
144                            const std::string& filename,
145                            const std::string& comment = "");
146
147   /**
148    * Write a default target statement specifying @a targets as
149    * the default targets.
150    */
151   static void WriteDefault(std::ostream& os,
152                            const cmNinjaDeps& targets,
153                            const std::string& comment = "");
154
155
156   static bool IsMinGW() { return UsingMinGW; }
157
158
159 public:
160   /// Default constructor.
161   cmGlobalNinjaGenerator();
162
163   /// Convenience method for creating an instance of this class.
164   static cmGlobalGeneratorFactory* NewFactory() {
165     return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); }
166
167   /// Destructor.
168   virtual ~cmGlobalNinjaGenerator() { }
169
170   /// Overloaded methods. @see cmGlobalGenerator::CreateLocalGenerator()
171   virtual cmLocalGenerator* CreateLocalGenerator();
172
173   /// Overloaded methods. @see cmGlobalGenerator::GetName().
174   virtual const char* GetName() const {
175     return cmGlobalNinjaGenerator::GetActualName(); }
176
177   /// @return the name of this generator.
178   static const char* GetActualName() { return "Ninja"; }
179
180   /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
181   static void GetDocumentation(cmDocumentationEntry& entry);
182
183   /// Overloaded methods. @see cmGlobalGenerator::Generate()
184   virtual void Generate();
185
186   /// Overloaded methods. @see cmGlobalGenerator::EnableLanguage()
187   virtual void EnableLanguage(std::vector<std::string>const& languages,
188                               cmMakefile* mf,
189                               bool optional);
190
191   /// Overloaded methods. @see cmGlobalGenerator::GenerateBuildCommand()
192   virtual std::string GenerateBuildCommand(const char* makeProgram,
193                                            const char* projectName,
194                                            const char* additionalOptions,
195                                            const char* targetName,
196                                            const char* config,
197                                            bool ignoreErrors,
198                                            bool fast);
199
200   // Setup target names
201   virtual const char* GetAllTargetName()           const { return "all"; }
202   virtual const char* GetInstallTargetName()       const { return "install"; }
203   virtual const char* GetInstallLocalTargetName()  const {
204     return "install/local";
205   }
206   virtual const char* GetInstallStripTargetName()  const {
207     return "install/strip";
208   }
209   virtual const char* GetTestTargetName()          const { return "test"; }
210   virtual const char* GetPackageTargetName()       const { return "package"; }
211   virtual const char* GetPackageSourceTargetName() const {
212     return "package_source";
213   }
214   virtual const char* GetEditCacheTargetName()     const {
215     return "edit_cache";
216   }
217   virtual const char* GetRebuildCacheTargetName()  const {
218     return "rebuild_cache";
219   }
220   virtual const char* GetCleanTargetName()         const { return "clean"; }
221
222
223   cmGeneratedFileStream* GetBuildFileStream() const {
224     return this->BuildFileStream; }
225
226   cmGeneratedFileStream* GetRulesFileStream() const {
227     return this->RulesFileStream; }
228
229   void AddCXXCompileCommand(const std::string &commandLine,
230                             const std::string &sourceFile);
231
232   /**
233    * Add a rule to the generated build system.
234    * Call WriteRule() behind the scene but perform some check before like:
235    * - Do not add twice the same rule.
236    */
237   void AddRule(const std::string& name,
238                const std::string& command,
239                const std::string& description,
240                const std::string& comment,
241                const std::string& depfile = "",
242                const std::string& rspfile = "",
243                const std::string& rspcontent = "",
244                bool restat = false,
245                bool generator = false);
246
247   bool HasRule(const std::string& name);
248
249   void AddCustomCommandRule();
250   void AddMacOSXContentRule();
251
252   bool HasCustomCommandOutput(const std::string &output) {
253     return this->CustomCommandOutputs.find(output) !=
254            this->CustomCommandOutputs.end();
255   }
256
257   /// Called when we have seen the given custom command.  Returns true
258   /// if we has seen it before.
259   bool SeenCustomCommand(cmCustomCommand const *cc) {
260     return !this->CustomCommands.insert(cc).second;
261   }
262
263   /// Called when we have seen the given custom command output.
264   void SeenCustomCommandOutput(const std::string &output) {
265     this->CustomCommandOutputs.insert(output);
266     // We don't need the assumed dependencies anymore, because we have
267     // an output.
268     this->AssumedSourceDependencies.erase(output);
269   }
270
271   void AddAssumedSourceDependencies(const std::string &source,
272                                     const cmNinjaDeps &deps) {
273     std::set<std::string> &ASD = this->AssumedSourceDependencies[source];
274     // Because we may see the same source file multiple times (same source
275     // specified in multiple targets), compute the union of any assumed
276     // dependencies.
277     ASD.insert(deps.begin(), deps.end());
278   }
279
280   void AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs);
281   void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs);
282   void AddDependencyToAll(cmTarget* target);
283   void AddDependencyToAll(const std::string& input);
284
285   const std::vector<cmLocalGenerator*>& GetLocalGenerators() const {
286     return LocalGenerators; }
287
288   bool IsExcluded(cmLocalGenerator* root, cmTarget& target) {
289     return cmGlobalGenerator::IsExcluded(root, target); }
290
291   int GetRuleCmdLength(const std::string& name) {
292     return RuleCmdLength[name]; }
293
294   void AddTargetAlias(const std::string& alias, cmTarget* target);
295
296
297 protected:
298
299   /// Overloaded methods.
300   /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
301   virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { return true; }
302
303
304 private:
305
306   /// @see cmGlobalGenerator::ComputeTargetObjects
307   virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const;
308
309   void OpenBuildFileStream();
310   void CloseBuildFileStream();
311
312   void CloseCompileCommandsStream();
313
314   void OpenRulesFileStream();
315   void CloseRulesFileStream();
316
317   /// Write the common disclaimer text at the top of each build file.
318   void WriteDisclaimer(std::ostream& os);
319
320   void WriteAssumedSourceDependencies();
321
322   void WriteTargetAliases(std::ostream& os);
323
324   void WriteBuiltinTargets(std::ostream& os);
325   void WriteTargetAll(std::ostream& os);
326   void WriteTargetRebuildManifest(std::ostream& os);
327   void WriteTargetClean(std::ostream& os);
328   void WriteTargetHelp(std::ostream& os);
329
330   std::string ninjaCmd() const;
331
332
333   /// The file containing the build statement. (the relation ship of the
334   /// compilation DAG).
335   cmGeneratedFileStream* BuildFileStream;
336   /// The file containing the rule statements. (The action attached to each
337   /// edge of the compilation DAG).
338   cmGeneratedFileStream* RulesFileStream;
339   cmGeneratedFileStream* CompileCommandsStream;
340
341   /// The type used to store the set of rules added to the generated build
342   /// system.
343   typedef std::set<std::string> RulesSetType;
344
345   /// The set of rules added to the generated build system.
346   RulesSetType Rules;
347
348   /// Length of rule command, used by rsp file evaluation
349   std::map<std::string, int> RuleCmdLength;
350
351   /// The set of dependencies to add to the "all" target.
352   cmNinjaDeps AllDependencies;
353
354   /// The set of custom commands we have seen.
355   std::set<cmCustomCommand const*> CustomCommands;
356
357   /// The set of custom command outputs we have seen.
358   std::set<std::string> CustomCommandOutputs;
359
360   /// The mapping from source file to assumed dependencies.
361   std::map<std::string, std::set<std::string> > AssumedSourceDependencies;
362
363   typedef std::map<std::string, cmTarget*> TargetAliasMap;
364   TargetAliasMap TargetAliases;
365
366   static cmLocalGenerator* LocalGenerator;
367
368   static bool UsingMinGW;
369
370 };
371
372 #endif // ! cmGlobalNinjaGenerator_h