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