Coverage Report

Created: 2026-03-12 06:35

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