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 "cmNinjaTypes.h"
19 //#define NINJA_GEN_VERBOSE_FILES
21 class cmLocalGenerator;
22 class cmGeneratedFileStream;
23 class cmGeneratorTarget;
26 * \class cmGlobalNinjaGenerator
27 * \brief Write a build.ninja file.
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
35 * - We don't care about generating a clean target since Ninja already have
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
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.
44 class cmGlobalNinjaGenerator : public cmGlobalGenerator
47 /// The default name of Ninja's build file. Typically: build.ninja.
48 static const char* NINJA_BUILD_FILE;
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;
54 /// The indentation string used when generating Ninja's build file.
55 static const char* INDENT;
57 /// Write @a count times INDENT level to output stream @a os.
58 static void Indent(std::ostream& os, int count);
60 /// Write a divider in the given output stream @a os.
61 static void WriteDivider(std::ostream& os);
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);
68 * Write the given @a comment to the output stream @a os. It
69 * handles new line character properly.
71 static void WriteComment(std::ostream& os, const std::string& comment);
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.
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);
90 * Helper to write a build statement with the special 'phony' rule.
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());
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);
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.
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,
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.
131 static void WriteVariable(std::ostream& os,
132 const std::string& name,
133 const std::string& value,
134 const std::string& comment = "",
138 * Write an include statement including @a filename with an optional
139 * @a comment to the @a os stream.
141 static void WriteInclude(std::ostream& os,
142 const std::string& filename,
143 const std::string& comment = "");
146 * Write a default target statement specifying @a targets as
147 * the default targets.
149 static void WriteDefault(std::ostream& os,
150 const cmNinjaDeps& targets,
151 const std::string& comment = "");
154 static bool IsMinGW() { return UsingMinGW; }
158 /// Default constructor.
159 cmGlobalNinjaGenerator();
161 /// Convenience method for creating an instance of this class.
162 static cmGlobalGenerator* New() {
163 return new cmGlobalNinjaGenerator; }
166 virtual ~cmGlobalNinjaGenerator() { }
168 /// Overloaded methods. @see cmGlobalGenerator::CreateLocalGenerator()
169 virtual cmLocalGenerator* CreateLocalGenerator();
171 /// Overloaded methods. @see cmGlobalGenerator::GetName().
172 virtual const char* GetName() const {
173 return cmGlobalNinjaGenerator::GetActualName(); }
175 /// @return the name of this generator.
176 static const char* GetActualName() { return "Ninja"; }
178 /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
179 virtual void GetDocumentation(cmDocumentationEntry& entry) const;
181 /// Overloaded methods. @see cmGlobalGenerator::Generate()
182 virtual void Generate();
184 /// Overloaded methods. @see cmGlobalGenerator::EnableLanguage()
185 virtual void EnableLanguage(std::vector<std::string>const& languages,
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,
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";
204 virtual const char* GetInstallStripTargetName() const {
205 return "install/strip";
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";
212 virtual const char* GetEditCacheTargetName() const {
215 virtual const char* GetRebuildCacheTargetName() const {
216 return "rebuild_cache";
218 virtual const char* GetCleanTargetName() const { return "clean"; }
221 cmGeneratedFileStream* GetBuildFileStream() const {
222 return this->BuildFileStream; }
224 cmGeneratedFileStream* GetRulesFileStream() const {
225 return this->RulesFileStream; }
227 void AddCXXCompileCommand(const std::string &commandLine,
228 const std::string &sourceFile);
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.
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 = "",
243 bool generator = false);
245 bool HasRule(const std::string& name);
247 void AddCustomCommandRule();
248 void AddMacOSXContentRule();
250 bool HasCustomCommandOutput(const std::string &output) {
251 return this->CustomCommandOutputs.find(output) !=
252 this->CustomCommandOutputs.end();
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;
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
266 this->AssumedSourceDependencies.erase(output);
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
275 ASD.insert(deps.begin(), deps.end());
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);
283 const std::vector<cmLocalGenerator*>& GetLocalGenerators() const {
284 return LocalGenerators; }
286 bool IsExcluded(cmLocalGenerator* root, cmTarget& target) {
287 return cmGlobalGenerator::IsExcluded(root, target); }
289 int GetRuleCmdLength(const std::string& name) {
290 return RuleCmdLength[name]; }
292 void AddTargetAlias(const std::string& alias, cmTarget* target);
297 /// Overloaded methods.
298 /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
299 virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { return true; }
304 /// @see cmGlobalGenerator::ComputeTargetObjects
305 virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const;
307 void OpenBuildFileStream();
308 void CloseBuildFileStream();
310 void CloseCompileCommandsStream();
312 void OpenRulesFileStream();
313 void CloseRulesFileStream();
315 /// Write the common disclaimer text at the top of each build file.
316 void WriteDisclaimer(std::ostream& os);
318 void WriteAssumedSourceDependencies();
320 void WriteTargetAliases(std::ostream& os);
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);
328 std::string ninjaCmd() const;
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;
339 /// The type used to store the set of rules added to the generated build
341 typedef std::set<std::string> RulesSetType;
343 /// The set of rules added to the generated build system.
346 /// Length of rule command, used by rsp file evaluation
347 std::map<std::string, int> RuleCmdLength;
349 /// The set of dependencies to add to the "all" target.
350 cmNinjaDeps AllDependencies;
352 /// The set of custom commands we have seen.
353 std::set<cmCustomCommand const*> CustomCommands;
355 /// The set of custom command outputs we have seen.
356 std::set<std::string> CustomCommandOutputs;
358 /// The mapping from source file to assumed dependencies.
359 std::map<std::string, std::set<std::string> > AssumedSourceDependencies;
361 typedef std::map<std::string, cmTarget*> TargetAliasMap;
362 TargetAliasMap TargetAliases;
364 static cmLocalGenerator* LocalGenerator;
366 static bool UsingMinGW;
370 #endif // ! cmGlobalNinjaGenerator_h