Imported Upstream version 2.8.12.2
[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   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   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* projectDir,
195                                            const char* additionalOptions,
196                                            const char* targetName,
197                                            const char* config,
198                                            bool ignoreErrors,
199                                            bool fast);
200
201   // Setup target names
202   virtual const char* GetAllTargetName()           const { return "all"; }
203   virtual const char* GetInstallTargetName()       const { return "install"; }
204   virtual const char* GetInstallLocalTargetName()  const {
205     return "install/local";
206   }
207   virtual const char* GetInstallStripTargetName()  const {
208     return "install/strip";
209   }
210   virtual const char* GetTestTargetName()          const { return "test"; }
211   virtual const char* GetPackageTargetName()       const { return "package"; }
212   virtual const char* GetPackageSourceTargetName() const {
213     return "package_source";
214   }
215   virtual const char* GetEditCacheTargetName()     const {
216     return "edit_cache";
217   }
218   virtual const char* GetRebuildCacheTargetName()  const {
219     return "rebuild_cache";
220   }
221   virtual const char* GetCleanTargetName()         const { return "clean"; }
222
223
224   cmGeneratedFileStream* GetBuildFileStream() const {
225     return this->BuildFileStream; }
226
227   cmGeneratedFileStream* GetRulesFileStream() const {
228     return this->RulesFileStream; }
229
230   void AddCXXCompileCommand(const std::string &commandLine,
231                             const std::string &sourceFile);
232
233   /**
234    * Add a rule to the generated build system.
235    * Call WriteRule() behind the scene but perform some check before like:
236    * - Do not add twice the same rule.
237    */
238   void AddRule(const std::string& name,
239                const std::string& command,
240                const std::string& description,
241                const std::string& comment,
242                const std::string& depfile = "",
243                const std::string& rspfile = "",
244                const std::string& rspcontent = "",
245                bool restat = false,
246                bool generator = false);
247
248   bool HasRule(const std::string& name);
249
250   void AddCustomCommandRule();
251   void AddMacOSXContentRule();
252
253   bool HasCustomCommandOutput(const std::string &output) {
254     return this->CustomCommandOutputs.find(output) !=
255            this->CustomCommandOutputs.end();
256   }
257
258   /// Called when we have seen the given custom command.  Returns true
259   /// if we has seen it before.
260   bool SeenCustomCommand(cmCustomCommand const *cc) {
261     return !this->CustomCommands.insert(cc).second;
262   }
263
264   /// Called when we have seen the given custom command output.
265   void SeenCustomCommandOutput(const std::string &output) {
266     this->CustomCommandOutputs.insert(output);
267     // We don't need the assumed dependencies anymore, because we have
268     // an output.
269     this->AssumedSourceDependencies.erase(output);
270   }
271
272   void AddAssumedSourceDependencies(const std::string &source,
273                                     const cmNinjaDeps &deps) {
274     std::set<std::string> &ASD = this->AssumedSourceDependencies[source];
275     // Because we may see the same source file multiple times (same source
276     // specified in multiple targets), compute the union of any assumed
277     // dependencies.
278     ASD.insert(deps.begin(), deps.end());
279   }
280
281   void AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs);
282   void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs);
283   void AddDependencyToAll(cmTarget* target);
284   void AddDependencyToAll(const std::string& input);
285
286   const std::vector<cmLocalGenerator*>& GetLocalGenerators() const {
287     return LocalGenerators; }
288
289   bool IsExcluded(cmLocalGenerator* root, cmTarget& target) {
290     return cmGlobalGenerator::IsExcluded(root, target); }
291
292   int GetRuleCmdLength(const std::string& name) {
293     return RuleCmdLength[name]; }
294
295   void AddTargetAlias(const std::string& alias, cmTarget* target);
296
297
298 protected:
299
300   /// Overloaded methods.
301   /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
302   virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { return true; }
303
304
305 private:
306
307   /// @see cmGlobalGenerator::ComputeTargetObjects
308   virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const;
309
310   void OpenBuildFileStream();
311   void CloseBuildFileStream();
312
313   void CloseCompileCommandsStream();
314
315   void OpenRulesFileStream();
316   void CloseRulesFileStream();
317
318   /// Write the common disclaimer text at the top of each build file.
319   void WriteDisclaimer(std::ostream& os);
320
321   void WriteAssumedSourceDependencies();
322
323   void WriteTargetAliases(std::ostream& os);
324   void WriteUnknownExplicitDependencies(std::ostream& os);
325
326   void WriteBuiltinTargets(std::ostream& os);
327   void WriteTargetAll(std::ostream& os);
328   void WriteTargetRebuildManifest(std::ostream& os);
329   void WriteTargetClean(std::ostream& os);
330   void WriteTargetHelp(std::ostream& os);
331
332   std::string ninjaCmd() const;
333
334
335   /// The file containing the build statement. (the relation ship of the
336   /// compilation DAG).
337   cmGeneratedFileStream* BuildFileStream;
338   /// The file containing the rule statements. (The action attached to each
339   /// edge of the compilation DAG).
340   cmGeneratedFileStream* RulesFileStream;
341   cmGeneratedFileStream* CompileCommandsStream;
342
343   /// The type used to store the set of rules added to the generated build
344   /// system.
345   typedef std::set<std::string> RulesSetType;
346
347   /// The set of rules added to the generated build system.
348   RulesSetType Rules;
349
350   /// Length of rule command, used by rsp file evaluation
351   std::map<std::string, int> RuleCmdLength;
352
353   /// The set of dependencies to add to the "all" target.
354   cmNinjaDeps AllDependencies;
355
356   /// The set of custom commands we have seen.
357   std::set<cmCustomCommand const*> CustomCommands;
358
359   /// The set of custom command outputs we have seen.
360   std::set<std::string> CustomCommandOutputs;
361
362   //The combined explicit dependencies of all build commands that the global
363   //generator has issued. When combined with CombinedBuildOutputs it allows
364   //us to detect the set of explicit dependencies that have
365   std::set<std::string> CombinedBuildExplicitDependencies;
366   std::set<std::string> CombinedBuildOutputs;
367
368   /// The mapping from source file to assumed dependencies.
369   std::map<std::string, std::set<std::string> > AssumedSourceDependencies;
370
371   typedef std::map<std::string, cmTarget*> TargetAliasMap;
372   TargetAliasMap TargetAliases;
373
374   static cmLocalGenerator* LocalGenerator;
375
376   static bool UsingMinGW;
377
378 };
379
380 #endif // ! cmGlobalNinjaGenerator_h