resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmGlobalNinjaGenerator.h
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #pragma once
4
5 #include "cmConfigure.h" // IWYU pragma: keep
6
7 #include <iosfwd>
8 #include <map>
9 #include <memory>
10 #include <set>
11 #include <string>
12 #include <unordered_map>
13 #include <unordered_set>
14 #include <utility>
15 #include <vector>
16
17 #include <cm/optional>
18
19 #include "cm_codecvt.hxx"
20
21 #include "cmBuildOptions.h"
22 #include "cmGeneratedFileStream.h"
23 #include "cmGlobalCommonGenerator.h"
24 #include "cmGlobalGeneratorFactory.h"
25 #include "cmNinjaTypes.h"
26 #include "cmPolicies.h"
27 #include "cmStringAlgorithms.h"
28 #include "cmTransformDepfile.h"
29
30 class cmCustomCommand;
31 class cmGeneratorTarget;
32 class cmLinkLineComputer;
33 class cmLocalGenerator;
34 class cmMakefile;
35 class cmOutputConverter;
36 class cmStateDirectory;
37 class cmake;
38 struct cmDocumentationEntry;
39
40 /**
41  * \class cmGlobalNinjaGenerator
42  * \brief Write a build.ninja file.
43  *
44  * The main differences between this generator and the UnixMakefile
45  * generator family are:
46  * - We don't care about VERBOSE variable or RULE_MESSAGES property since
47  *   it is handle by Ninja's -v option.
48  * - We don't care about computing any progress status since Ninja manages
49  *   it itself.
50  * - We generate one build.ninja and one rules.ninja per project.
51  * - We try to minimize the number of generated rules: one per target and
52  *   language.
53  * - We use Ninja special variable $in and $out to produce nice output.
54  * - We extensively use Ninja variable overloading system to minimize the
55  *   number of generated rules.
56  */
57 class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator
58 {
59 public:
60   /// The default name of Ninja's build file. Typically: build.ninja.
61   static const char* NINJA_BUILD_FILE;
62
63   /// The default name of Ninja's rules file. Typically: rules.ninja.
64   /// It is included in the main build.ninja file.
65   static const char* NINJA_RULES_FILE;
66
67   /// The indentation string used when generating Ninja's build file.
68   static const char* INDENT;
69
70   /// The shell command used for a no-op.
71   static std::string const SHELL_NOOP;
72
73   /// Write @a count times INDENT level to output stream @a os.
74   static void Indent(std::ostream& os, int count);
75
76   /// Write a divider in the given output stream @a os.
77   static void WriteDivider(std::ostream& os);
78
79   static std::string EncodeRuleName(std::string const& name);
80   std::string EncodeLiteral(const std::string& lit);
81   void EncodeLiteralInplace(std::string& lit);
82   std::string EncodePath(const std::string& path);
83
84   std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer(
85     cmOutputConverter* outputConverter,
86     cmStateDirectory const& stateDir) const override;
87
88   /**
89    * Write the given @a comment to the output stream @a os. It
90    * handles new line character properly.
91    */
92   static void WriteComment(std::ostream& os, const std::string& comment);
93
94   /**
95    * Utilized by the generator factory to determine if this generator
96    * supports toolsets.
97    */
98   static bool SupportsToolset() { return false; }
99
100   /**
101    * Utilized by the generator factory to determine if this generator
102    * supports platforms.
103    */
104   static bool SupportsPlatform() { return false; }
105
106   bool IsIPOSupported() const override { return true; }
107
108   /**
109    * Write a build statement @a build to @a os.
110    * @warning no escaping of any kind is done here.
111    */
112   void WriteBuild(std::ostream& os, cmNinjaBuild const& build,
113                   int cmdLineLimit = 0, bool* usedResponseFile = nullptr);
114
115   class CCOutputs
116   {
117     cmGlobalNinjaGenerator* GG;
118
119   public:
120     CCOutputs(cmGlobalNinjaGenerator* gg)
121       : GG(gg)
122     {
123     }
124     void Add(std::vector<std::string> const& outputs);
125     cmNinjaDeps ExplicitOuts;
126     cmNinjaDeps WorkDirOuts;
127   };
128
129   void WriteCustomCommandBuild(std::string const& command,
130                                std::string const& description,
131                                std::string const& comment,
132                                std::string const& depfile,
133                                std::string const& pool, bool uses_terminal,
134                                bool restat, std::string const& config,
135                                CCOutputs outputs,
136                                cmNinjaDeps explicitDeps = cmNinjaDeps(),
137                                cmNinjaDeps orderOnlyDeps = cmNinjaDeps());
138
139   void WriteMacOSXContentBuild(std::string input, std::string output,
140                                const std::string& config);
141
142   /**
143    * Write a rule statement to @a os.
144    * @warning no escaping of any kind is done here.
145    */
146   static void WriteRule(std::ostream& os, cmNinjaRule const& rule);
147
148   /**
149    * Write a variable named @a name to @a os with value @a value and an
150    * optional @a comment. An @a indent level can be specified.
151    * @warning no escaping of any kind is done here.
152    */
153   static void WriteVariable(std::ostream& os, const std::string& name,
154                             const std::string& value,
155                             const std::string& comment = "", int indent = 0);
156
157   /**
158    * Write an include statement including @a filename with an optional
159    * @a comment to the @a os stream.
160    */
161   static void WriteInclude(std::ostream& os, const std::string& filename,
162                            const std::string& comment = "");
163
164   /**
165    * Write a default target statement specifying @a targets as
166    * the default targets.
167    */
168   static void WriteDefault(std::ostream& os, const cmNinjaDeps& targets,
169                            const std::string& comment = "");
170
171   bool IsGCCOnWindows() const { return this->UsingGCCOnWindows; }
172
173   cmGlobalNinjaGenerator(cmake* cm);
174
175   static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory()
176   {
177     return std::unique_ptr<cmGlobalGeneratorFactory>(
178       new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>());
179   }
180
181   std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
182     cmMakefile* mf) override;
183
184   std::string GetName() const override
185   {
186     return cmGlobalNinjaGenerator::GetActualName();
187   }
188
189   static std::string GetActualName() { return "Ninja"; }
190
191   bool IsNinja() const override { return true; }
192
193   /** Get encoding used by generator for ninja files */
194   codecvt::Encoding GetMakefileEncoding() const override;
195
196   static void GetDocumentation(cmDocumentationEntry& entry);
197
198   void EnableLanguage(std::vector<std::string> const& languages,
199                       cmMakefile* mf, bool optional) override;
200
201   std::vector<GeneratedMakeCommand> GenerateBuildCommand(
202     const std::string& makeProgram, const std::string& projectName,
203     const std::string& projectDir, std::vector<std::string> const& targetNames,
204     const std::string& config, int jobs, bool verbose,
205     const cmBuildOptions& buildOptions = cmBuildOptions(),
206     std::vector<std::string> const& makeOptions =
207       std::vector<std::string>()) override;
208
209   // Setup target names
210   const char* GetAllTargetName() const override { return "all"; }
211   const char* GetInstallTargetName() const override { return "install"; }
212   const char* GetInstallLocalTargetName() const override
213   {
214     return "install/local";
215   }
216   const char* GetInstallStripTargetName() const override
217   {
218     return "install/strip";
219   }
220   const char* GetTestTargetName() const override { return "test"; }
221   const char* GetPackageTargetName() const override { return "package"; }
222   const char* GetPackageSourceTargetName() const override
223   {
224     return "package_source";
225   }
226   const char* GetRebuildCacheTargetName() const override
227   {
228     return "rebuild_cache";
229   }
230   const char* GetCleanTargetName() const override { return "clean"; }
231
232   bool SupportsCustomCommandDepfile() const override { return true; }
233   cm::optional<cmDepfileFormat> DepfileFormat() const override
234   {
235     return cmDepfileFormat::GccDepfile;
236   }
237
238   virtual cmGeneratedFileStream* GetImplFileStream(
239     const std::string& /*config*/) const
240   {
241     return this->BuildFileStream.get();
242   }
243
244   virtual cmGeneratedFileStream* GetConfigFileStream(
245     const std::string& /*config*/) const
246   {
247     return this->BuildFileStream.get();
248   }
249
250   virtual cmGeneratedFileStream* GetDefaultFileStream() const
251   {
252     return this->BuildFileStream.get();
253   }
254
255   virtual cmGeneratedFileStream* GetCommonFileStream() const
256   {
257     return this->BuildFileStream.get();
258   }
259
260   cmGeneratedFileStream* GetRulesFileStream() const
261   {
262     return this->RulesFileStream.get();
263   }
264
265   std::string const& ConvertToNinjaPath(const std::string& path) const;
266   std::string ConvertToNinjaAbsPath(std::string path) const;
267
268   struct MapToNinjaPathImpl
269   {
270     cmGlobalNinjaGenerator* GG;
271     MapToNinjaPathImpl(cmGlobalNinjaGenerator* gg)
272       : GG(gg)
273     {
274     }
275     std::string operator()(std::string const& path) const
276     {
277       return this->GG->ConvertToNinjaPath(path);
278     }
279   };
280   MapToNinjaPathImpl MapToNinjaPath() { return { this }; }
281
282   // -- Additional clean files
283   void AddAdditionalCleanFile(std::string fileName, const std::string& config);
284   const char* GetAdditionalCleanTargetName() const
285   {
286     return "CMakeFiles/clean.additional";
287   }
288
289   static const char* GetByproductsForCleanTargetName()
290   {
291     return "CMakeFiles/cmake_byproducts_for_clean_target";
292   }
293
294   void AddCXXCompileCommand(const std::string& commandLine,
295                             const std::string& sourceFile);
296
297   /**
298    * Add a rule to the generated build system.
299    * Call WriteRule() behind the scene but perform some check before like:
300    * - Do not add twice the same rule.
301    */
302   void AddRule(cmNinjaRule const& rule);
303
304   bool HasRule(const std::string& name);
305
306   void AddCustomCommandRule();
307   void AddMacOSXContentRule();
308
309   bool HasCustomCommandOutput(const std::string& output)
310   {
311     return this->CustomCommandOutputs.find(output) !=
312       this->CustomCommandOutputs.end();
313   }
314
315   /// Called when we have seen the given custom command.  Returns true
316   /// if we has seen it before.
317   bool SeenCustomCommand(cmCustomCommand const* cc, const std::string& config)
318   {
319     return !this->Configs[config].CustomCommands.insert(cc).second;
320   }
321
322   /// Called when we have seen the given custom command output.
323   void SeenCustomCommandOutput(const std::string& output)
324   {
325     this->CustomCommandOutputs.insert(output);
326     // We don't need the assumed dependencies anymore, because we have
327     // an output.
328     this->AssumedSourceDependencies.erase(output);
329   }
330
331   void AddAssumedSourceDependencies(const std::string& source,
332                                     const cmNinjaDeps& deps)
333   {
334     std::set<std::string>& ASD = this->AssumedSourceDependencies[source];
335     // Because we may see the same source file multiple times (same source
336     // specified in multiple targets), compute the union of any assumed
337     // dependencies.
338     ASD.insert(deps.begin(), deps.end());
339   }
340
341   virtual std::string OrderDependsTargetForTarget(
342     cmGeneratorTarget const* target, const std::string& config) const;
343
344   void AppendTargetOutputs(cmGeneratorTarget const* target,
345                            cmNinjaDeps& outputs, const std::string& config,
346                            cmNinjaTargetDepends depends) const;
347   void AppendTargetDepends(cmGeneratorTarget const* target,
348                            cmNinjaDeps& outputs, const std::string& config,
349                            const std::string& fileConfig,
350                            cmNinjaTargetDepends depends);
351   void AppendTargetDependsClosure(cmGeneratorTarget const* target,
352                                   cmNinjaDeps& outputs,
353                                   const std::string& config,
354                                   const std::string& fileConfig,
355                                   bool genexOutput);
356   void AppendTargetDependsClosure(cmGeneratorTarget const* target,
357                                   cmNinjaOuts& outputs,
358                                   const std::string& config,
359                                   const std::string& fileConfig,
360                                   bool genexOutput, bool omit_self);
361
362   void AppendDirectoryForConfig(const std::string& prefix,
363                                 const std::string& config,
364                                 const std::string& suffix,
365                                 std::string& dir) override;
366
367   virtual void AppendNinjaFileArgument(GeneratedMakeCommand& /*command*/,
368                                        const std::string& /*config*/) const
369   {
370   }
371
372   virtual void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const
373   {
374     outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE));
375   }
376
377   int GetRuleCmdLength(const std::string& name)
378   {
379     return this->RuleCmdLength[name];
380   }
381
382   void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target,
383                       const std::string& config);
384
385   void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
386
387   // Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3
388   static std::string RequiredNinjaVersion() { return "1.3"; }
389   static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; }
390   static std::string RequiredNinjaVersionForImplicitOuts() { return "1.7"; }
391   static std::string RequiredNinjaVersionForManifestRestat() { return "1.8"; }
392   static std::string RequiredNinjaVersionForMultilineDepfile()
393   {
394     return "1.9";
395   }
396   static std::string RequiredNinjaVersionForDyndeps() { return "1.10"; }
397   static std::string RequiredNinjaVersionForRestatTool() { return "1.10"; }
398   static std::string RequiredNinjaVersionForUnconditionalRecompactTool()
399   {
400     return "1.10";
401   }
402   static std::string RequiredNinjaVersionForMultipleOutputs()
403   {
404     return "1.10";
405   }
406   static std::string RequiredNinjaVersionForMetadataOnRegeneration()
407   {
408     return "1.10.2";
409   }
410   static std::string RequiredNinjaVersionForCodePage() { return "1.11"; }
411   bool SupportsDirectConsole() const override;
412   bool SupportsImplicitOuts() const;
413   bool SupportsManifestRestat() const;
414   bool SupportsMultilineDepfile() const;
415
416   std::string NinjaOutputPath(std::string const& path) const;
417   bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
418   void StripNinjaOutputPathPrefixAsSuffix(std::string& path);
419
420   struct CxxModuleExportInfo;
421   bool WriteDyndepFile(
422     std::string const& dir_top_src, std::string const& dir_top_bld,
423     std::string const& dir_cur_src, std::string const& dir_cur_bld,
424     std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
425     std::string const& module_dir,
426     std::vector<std::string> const& linked_target_dirs,
427     std::string const& arg_lang, std::string const& arg_modmapfmt,
428     CxxModuleExportInfo const& export_info);
429
430   virtual std::string BuildAlias(const std::string& alias,
431                                  const std::string& /*config*/) const
432   {
433     return alias;
434   }
435
436   virtual std::string ConfigDirectory(const std::string& /*config*/) const
437   {
438     return "";
439   }
440
441   cmNinjaDeps& GetByproductsForCleanTarget()
442   {
443     return this->ByproductsForCleanTarget;
444   }
445
446   cmNinjaDeps& GetByproductsForCleanTarget(const std::string& config)
447   {
448     return this->Configs[config].ByproductsForCleanTarget;
449   }
450
451   bool EnableCrossConfigBuild() const;
452
453   std::set<std::string> GetCrossConfigs(const std::string& config) const;
454
455   const std::set<std::string>& GetDefaultConfigs() const
456   {
457     return this->DefaultConfigs;
458   }
459
460   const std::set<std::string>& GetPerConfigUtilityTargets() const
461   {
462     return this->PerConfigUtilityTargets;
463   }
464
465   void AddPerConfigUtilityTarget(const std::string& name)
466   {
467     this->PerConfigUtilityTargets.insert(name);
468   }
469
470   bool IsSingleConfigUtility(cmGeneratorTarget const* target) const;
471
472   bool CheckCxxModuleSupport();
473
474 protected:
475   void Generate() override;
476
477   bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }
478
479   virtual bool OpenBuildFileStreams();
480   virtual void CloseBuildFileStreams();
481
482   bool OpenFileStream(std::unique_ptr<cmGeneratedFileStream>& stream,
483                       const std::string& name);
484
485   static cm::optional<std::set<std::string>> ListSubsetWithAll(
486     const std::set<std::string>& all, const std::set<std::string>& defaults,
487     const std::vector<std::string>& items);
488
489   std::set<std::string> CrossConfigs;
490   std::set<std::string> DefaultConfigs;
491   std::string DefaultFileConfig;
492
493 private:
494   bool FindMakeProgram(cmMakefile* mf) override;
495   void CheckNinjaFeatures();
496   void CheckNinjaCodePage();
497   bool CheckLanguages(std::vector<std::string> const& languages,
498                       cmMakefile* mf) const override;
499   bool CheckFortran(cmMakefile* mf) const;
500   bool CheckISPC(cmMakefile* mf) const;
501
502   void CloseCompileCommandsStream();
503
504   bool OpenRulesFileStream();
505   void CloseRulesFileStream();
506   void CleanMetaData();
507
508   /// Write the common disclaimer text at the top of each build file.
509   void WriteDisclaimer(std::ostream& os) const;
510
511   void WriteAssumedSourceDependencies();
512
513   void WriteTargetAliases(std::ostream& os);
514   void WriteFolderTargets(std::ostream& os);
515   void WriteUnknownExplicitDependencies(std::ostream& os);
516
517   void WriteBuiltinTargets(std::ostream& os);
518   void WriteTargetDefault(std::ostream& os);
519   void WriteTargetRebuildManifest(std::ostream& os);
520   bool WriteTargetCleanAdditional(std::ostream& os);
521   void WriteTargetClean(std::ostream& os);
522   void WriteTargetHelp(std::ostream& os);
523
524   void ComputeTargetDependsClosure(
525     cmGeneratorTarget const* target,
526     std::set<cmGeneratorTarget const*>& depends);
527
528   std::string CMakeCmd() const;
529   std::string NinjaCmd() const;
530
531   /// The file containing the build statement. (the relationship of the
532   /// compilation DAG).
533   std::unique_ptr<cmGeneratedFileStream> BuildFileStream;
534   /// The file containing the rule statements. (The action attached to each
535   /// edge of the compilation DAG).
536   std::unique_ptr<cmGeneratedFileStream> RulesFileStream;
537   std::unique_ptr<cmGeneratedFileStream> CompileCommandsStream;
538
539   /// The set of rules added to the generated build system.
540   std::unordered_set<std::string> Rules;
541
542   /// Length of rule command, used by rsp file evaluation
543   std::unordered_map<std::string, int> RuleCmdLength;
544
545   bool UsingGCCOnWindows = false;
546
547   /// The set of custom command outputs we have seen.
548   std::set<std::string> CustomCommandOutputs;
549
550   /// Whether we are collecting known build outputs and needed
551   /// dependencies to determine unknown dependencies.
552   bool ComputingUnknownDependencies = false;
553   cmPolicies::PolicyStatus PolicyCMP0058 = cmPolicies::WARN;
554
555   /// The combined explicit dependencies of custom build commands
556   std::set<std::string> CombinedCustomCommandExplicitDependencies;
557
558   /// When combined with CombinedCustomCommandExplicitDependencies it allows
559   /// us to detect the set of explicit dependencies that have
560   std::set<std::string> CombinedBuildOutputs;
561
562   /// The mapping from source file to assumed dependencies.
563   std::map<std::string, std::set<std::string>> AssumedSourceDependencies;
564
565   /// Utility targets which have per-config outputs
566   std::set<std::string> PerConfigUtilityTargets;
567
568   struct TargetAlias
569   {
570     cmGeneratorTarget* GeneratorTarget;
571     std::string Config;
572   };
573   using TargetAliasMap = std::map<std::string, TargetAlias>;
574   TargetAliasMap TargetAliases;
575   TargetAliasMap DefaultTargetAliases;
576
577   /// the local cache for calls to ConvertToNinjaPath
578   mutable std::unordered_map<std::string, std::string> ConvertToNinjaPathCache;
579
580   std::string NinjaCommand;
581   std::string NinjaVersion;
582   bool NinjaSupportsConsolePool = false;
583   bool NinjaSupportsImplicitOuts = false;
584   bool NinjaSupportsManifestRestat = false;
585   bool NinjaSupportsMultilineDepfile = false;
586   bool NinjaSupportsDyndeps = false;
587   bool NinjaSupportsRestatTool = false;
588   bool NinjaSupportsUnconditionalRecompactTool = false;
589   bool NinjaSupportsMultipleOutputs = false;
590   bool NinjaSupportsMetadataOnRegeneration = false;
591   bool NinjaSupportsCodePage = false;
592
593   codecvt::Encoding NinjaExpectedEncoding = codecvt::None;
594
595   bool DiagnosedCxxModuleSupport = false;
596
597   void InitOutputPathPrefix();
598
599   std::string OutputPathPrefix;
600   std::string TargetAll;
601   std::string CMakeCacheFile;
602   bool DisableCleandead = false;
603
604   struct ByConfig
605   {
606     std::set<std::string> AdditionalCleanFiles;
607
608     /// The set of custom commands we have seen.
609     std::set<cmCustomCommand const*> CustomCommands;
610
611     struct TargetDependsClosureKey
612     {
613       cmGeneratorTarget const* Target;
614       std::string Config;
615       bool GenexOutput;
616     };
617
618     std::map<TargetDependsClosureKey, cmNinjaOuts> TargetDependsClosures;
619
620     TargetAliasMap TargetAliases;
621
622     cmNinjaDeps ByproductsForCleanTarget;
623   };
624   std::map<std::string, ByConfig> Configs;
625
626   cmNinjaDeps ByproductsForCleanTarget;
627
628   friend bool operator==(const ByConfig::TargetDependsClosureKey& lhs,
629                          const ByConfig::TargetDependsClosureKey& rhs);
630   friend bool operator!=(const ByConfig::TargetDependsClosureKey& lhs,
631                          const ByConfig::TargetDependsClosureKey& rhs);
632   friend bool operator<(const ByConfig::TargetDependsClosureKey& lhs,
633                         const ByConfig::TargetDependsClosureKey& rhs);
634   friend bool operator>(const ByConfig::TargetDependsClosureKey& lhs,
635                         const ByConfig::TargetDependsClosureKey& rhs);
636   friend bool operator<=(const ByConfig::TargetDependsClosureKey& lhs,
637                          const ByConfig::TargetDependsClosureKey& rhs);
638   friend bool operator>=(const ByConfig::TargetDependsClosureKey& lhs,
639                          const ByConfig::TargetDependsClosureKey& rhs);
640 };
641
642 class cmGlobalNinjaMultiGenerator : public cmGlobalNinjaGenerator
643 {
644 public:
645   /// The default name of Ninja's common file. Typically: common.ninja.
646   static const char* NINJA_COMMON_FILE;
647   /// The default file extension to use for per-config Ninja files.
648   static const char* NINJA_FILE_EXTENSION;
649
650   cmGlobalNinjaMultiGenerator(cmake* cm);
651   bool IsMultiConfig() const override { return true; }
652   static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory()
653   {
654     return std::unique_ptr<cmGlobalGeneratorFactory>(
655       new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>());
656   }
657
658   static void GetDocumentation(cmDocumentationEntry& entry);
659
660   std::string GetName() const override
661   {
662     return cmGlobalNinjaMultiGenerator::GetActualName();
663   }
664
665   static std::string GetActualName() { return "Ninja Multi-Config"; }
666
667   std::string BuildAlias(const std::string& alias,
668                          const std::string& config) const override
669   {
670     if (config.empty()) {
671       return alias;
672     }
673     return cmStrCat(alias, ":", config);
674   }
675
676   std::string ConfigDirectory(const std::string& config) const override
677   {
678     if (!config.empty()) {
679       return cmStrCat('/', config);
680     }
681     return "";
682   }
683
684   const char* GetCMakeCFGIntDir() const override { return "${CONFIGURATION}"; }
685
686   std::string ExpandCFGIntDir(const std::string& str,
687                               const std::string& config) const override;
688
689   cmGeneratedFileStream* GetImplFileStream(
690     const std::string& config) const override
691   {
692     return this->ImplFileStreams.at(config).get();
693   }
694
695   cmGeneratedFileStream* GetConfigFileStream(
696     const std::string& config) const override
697   {
698     return this->ConfigFileStreams.at(config).get();
699   }
700
701   cmGeneratedFileStream* GetDefaultFileStream() const override
702   {
703     return this->DefaultFileStream.get();
704   }
705
706   cmGeneratedFileStream* GetCommonFileStream() const override
707   {
708     return this->CommonFileStream.get();
709   }
710
711   void AppendNinjaFileArgument(GeneratedMakeCommand& command,
712                                const std::string& config) const override;
713
714   static std::string GetNinjaImplFilename(const std::string& config);
715   static std::string GetNinjaConfigFilename(const std::string& config);
716
717   void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const override;
718
719   void GetQtAutoGenConfigs(std::vector<std::string>& configs) const override;
720
721   bool InspectConfigTypeVariables() override;
722
723   std::string GetDefaultBuildConfig() const override;
724
725   bool SupportsDefaultBuildType() const override { return true; }
726   bool SupportsCrossConfigs() const override { return true; }
727   bool SupportsDefaultConfigs() const override { return true; }
728
729   std::string OrderDependsTargetForTarget(
730     cmGeneratorTarget const* target, const std::string& config) const override;
731
732 protected:
733   bool OpenBuildFileStreams() override;
734   void CloseBuildFileStreams() override;
735
736 private:
737   std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>
738     ImplFileStreams;
739   std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>
740     ConfigFileStreams;
741   std::unique_ptr<cmGeneratedFileStream> CommonFileStream;
742   std::unique_ptr<cmGeneratedFileStream> DefaultFileStream;
743 };