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>
6 Distributed under the OSI-approved BSD License (the "License");
7 see accompanying file Copyright.txt for details.
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
16 # include "cmGlobalGenerator.h"
17 # include "cmGlobalGeneratorFactory.h"
18 # include "cmNinjaTypes.h"
20 //#define NINJA_GEN_VERBOSE_FILES
22 class cmLocalGenerator;
23 class cmGeneratedFileStream;
24 class cmGeneratorTarget;
27 * \class cmGlobalNinjaGenerator
28 * \brief Write a build.ninja file.
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
36 * - We don't care about generating a clean target since Ninja already have
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
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.
45 class cmGlobalNinjaGenerator : public cmGlobalGenerator
48 /// The default name of Ninja's build file. Typically: build.ninja.
49 static const char* NINJA_BUILD_FILE;
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;
55 /// The indentation string used when generating Ninja's build file.
56 static const char* INDENT;
58 /// Write @a count times INDENT level to output stream @a os.
59 static void Indent(std::ostream& os, int count);
61 /// Write a divider in the given output stream @a os.
62 static void WriteDivider(std::ostream& os);
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);
69 * Write the given @a comment to the output stream @a os. It
70 * handles new line character properly.
72 static void WriteComment(std::ostream& os, const std::string& comment);
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.
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);
92 * Helper to write a build statement with the special 'phony' rule.
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());
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);
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.
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,
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.
133 static void WriteVariable(std::ostream& os,
134 const std::string& name,
135 const std::string& value,
136 const std::string& comment = "",
140 * Write an include statement including @a filename with an optional
141 * @a comment to the @a os stream.
143 static void WriteInclude(std::ostream& os,
144 const std::string& filename,
145 const std::string& comment = "");
148 * Write a default target statement specifying @a targets as
149 * the default targets.
151 static void WriteDefault(std::ostream& os,
152 const cmNinjaDeps& targets,
153 const std::string& comment = "");
156 static bool IsMinGW() { return UsingMinGW; }
160 /// Default constructor.
161 cmGlobalNinjaGenerator();
163 /// Convenience method for creating an instance of this class.
164 static cmGlobalGeneratorFactory* NewFactory() {
165 return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); }
168 virtual ~cmGlobalNinjaGenerator() { }
170 /// Overloaded methods. @see cmGlobalGenerator::CreateLocalGenerator()
171 virtual cmLocalGenerator* CreateLocalGenerator();
173 /// Overloaded methods. @see cmGlobalGenerator::GetName().
174 virtual const char* GetName() const {
175 return cmGlobalNinjaGenerator::GetActualName(); }
177 /// @return the name of this generator.
178 static const char* GetActualName() { return "Ninja"; }
180 /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
181 static void GetDocumentation(cmDocumentationEntry& entry);
183 /// Overloaded methods. @see cmGlobalGenerator::Generate()
184 virtual void Generate();
186 /// Overloaded methods. @see cmGlobalGenerator::EnableLanguage()
187 virtual void EnableLanguage(std::vector<std::string>const& languages,
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,
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";
207 virtual const char* GetInstallStripTargetName() const {
208 return "install/strip";
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";
215 virtual const char* GetEditCacheTargetName() const {
218 virtual const char* GetRebuildCacheTargetName() const {
219 return "rebuild_cache";
221 virtual const char* GetCleanTargetName() const { return "clean"; }
224 cmGeneratedFileStream* GetBuildFileStream() const {
225 return this->BuildFileStream; }
227 cmGeneratedFileStream* GetRulesFileStream() const {
228 return this->RulesFileStream; }
230 void AddCXXCompileCommand(const std::string &commandLine,
231 const std::string &sourceFile);
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.
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 = "",
246 bool generator = false);
248 bool HasRule(const std::string& name);
250 void AddCustomCommandRule();
251 void AddMacOSXContentRule();
253 bool HasCustomCommandOutput(const std::string &output) {
254 return this->CustomCommandOutputs.find(output) !=
255 this->CustomCommandOutputs.end();
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;
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
269 this->AssumedSourceDependencies.erase(output);
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
278 ASD.insert(deps.begin(), deps.end());
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);
286 const std::vector<cmLocalGenerator*>& GetLocalGenerators() const {
287 return LocalGenerators; }
289 bool IsExcluded(cmLocalGenerator* root, cmTarget& target) {
290 return cmGlobalGenerator::IsExcluded(root, target); }
292 int GetRuleCmdLength(const std::string& name) {
293 return RuleCmdLength[name]; }
295 void AddTargetAlias(const std::string& alias, cmTarget* target);
300 /// Overloaded methods.
301 /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
302 virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { return true; }
307 /// @see cmGlobalGenerator::ComputeTargetObjects
308 virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const;
310 void OpenBuildFileStream();
311 void CloseBuildFileStream();
313 void CloseCompileCommandsStream();
315 void OpenRulesFileStream();
316 void CloseRulesFileStream();
318 /// Write the common disclaimer text at the top of each build file.
319 void WriteDisclaimer(std::ostream& os);
321 void WriteAssumedSourceDependencies();
323 void WriteTargetAliases(std::ostream& os);
324 void WriteUnknownExplicitDependencies(std::ostream& os);
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);
332 std::string ninjaCmd() const;
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;
343 /// The type used to store the set of rules added to the generated build
345 typedef std::set<std::string> RulesSetType;
347 /// The set of rules added to the generated build system.
350 /// Length of rule command, used by rsp file evaluation
351 std::map<std::string, int> RuleCmdLength;
353 /// The set of dependencies to add to the "all" target.
354 cmNinjaDeps AllDependencies;
356 /// The set of custom commands we have seen.
357 std::set<cmCustomCommand const*> CustomCommands;
359 /// The set of custom command outputs we have seen.
360 std::set<std::string> CustomCommandOutputs;
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;
368 /// The mapping from source file to assumed dependencies.
369 std::map<std::string, std::set<std::string> > AssumedSourceDependencies;
371 typedef std::map<std::string, cmTarget*> TargetAliasMap;
372 TargetAliasMap TargetAliases;
374 static cmLocalGenerator* LocalGenerator;
376 static bool UsingMinGW;
380 #endif // ! cmGlobalNinjaGenerator_h