Coverage Report

Created: 2026-09-14 06:43

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