Coverage Report

Created: 2026-02-09 06:05

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& arg_lang, std::string const& arg_modmapfmt,
437
    cmCxxModuleExportInfo const& export_info);
438
439
  virtual std::string BuildAlias(std::string const& alias,
440
                                 std::string const& /*config*/) const
441
0
  {
442
0
    return alias;
443
0
  }
444
445
  virtual std::string ConfigDirectory(std::string const& /*config*/) const
446
0
  {
447
0
    return "";
448
0
  }
449
450
  cmNinjaDeps& GetByproductsForCleanTarget()
451
0
  {
452
0
    return this->ByproductsForCleanTarget;
453
0
  }
454
455
  cmNinjaDeps& GetByproductsForCleanTarget(std::string const& config)
456
0
  {
457
0
    return this->Configs[config].ByproductsForCleanTarget;
458
0
  }
459
460
  bool EnableCrossConfigBuild() const;
461
462
  std::set<std::string> GetCrossConfigs(std::string const& config) const;
463
464
  std::set<std::string> const& GetDefaultConfigs() const override
465
0
  {
466
0
    return this->DefaultConfigs;
467
0
  }
468
469
  std::set<std::string> const& GetPerConfigUtilityTargets() const
470
0
  {
471
0
    return this->PerConfigUtilityTargets;
472
0
  }
473
474
  void AddPerConfigUtilityTarget(std::string const& name)
475
0
  {
476
0
    this->PerConfigUtilityTargets.insert(name);
477
0
  }
478
479
  bool IsSingleConfigUtility(cmGeneratorTarget const* target) const;
480
481
  bool CheckCxxModuleSupport(CxxModuleSupportQuery query) override;
482
0
  bool SupportsBuildDatabase() const override { return true; }
483
484
  std::string ConvertToOutputPath(std::string path) const override;
485
486
protected:
487
  std::vector<std::string> const& GetConfigNames() const;
488
489
  void Generate() override;
490
491
0
  bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }
492
493
  virtual bool OpenBuildFileStreams();
494
  virtual void CloseBuildFileStreams();
495
496
  bool OpenFileStream(std::unique_ptr<cmGeneratedFileStream>& stream,
497
                      std::string const& name);
498
499
  static cm::optional<std::set<std::string>> ListSubsetWithAll(
500
    std::set<std::string> const& all, std::set<std::string> const& defaults,
501
    std::vector<std::string> const& items);
502
503
  std::set<std::string> CrossConfigs;
504
  std::set<std::string> DefaultConfigs;
505
  std::string DefaultFileConfig;
506
507
private:
508
  bool FindMakeProgram(cmMakefile* mf) override;
509
  void CheckNinjaFeatures();
510
  void CheckNinjaCodePage();
511
  bool CheckLanguages(std::vector<std::string> const& languages,
512
                      cmMakefile* mf) const override;
513
  bool CheckFortran(cmMakefile* mf) const;
514
  bool CheckISPC(cmMakefile* mf) const;
515
516
  void CloseCompileCommandsStream();
517
518
  bool OpenRulesFileStream();
519
  void CloseRulesFileStream();
520
  void CleanMetaData();
521
522
  /// Write the common disclaimer text at the top of each build file.
523
  void WriteDisclaimer(std::ostream& os) const;
524
525
  void WriteAssumedSourceDependencies();
526
527
  void WriteTargetAliases(std::ostream& os);
528
  void WriteFolderTargets(std::ostream& os);
529
530
  void WriteBuiltinTargets(std::ostream& os);
531
  void WriteTargetDefault(std::ostream& os);
532
  void WriteTargetRebuildManifest(std::ostream& os);
533
  bool WriteTargetCleanAdditional(std::ostream& os);
534
  void WriteTargetClean(std::ostream& os);
535
#ifndef CMAKE_BOOTSTRAP
536
  void WriteTargetInstrument(std::ostream& os);
537
#endif
538
  void WriteTargetHelp(std::ostream& os);
539
540
  void ComputeTargetDependsClosure(
541
    cmGeneratorTarget const* target,
542
    std::set<cmGeneratorTarget const*>& depends);
543
544
  std::string CMakeCmd() const;
545
  std::string NinjaCmd() const;
546
547
  /// The file containing the build statement. (the relationship of the
548
  /// compilation DAG).
549
  std::unique_ptr<cmGeneratedFileStream> BuildFileStream;
550
  /// The file containing the rule statements. (The action attached to each
551
  /// edge of the compilation DAG).
552
  std::unique_ptr<cmGeneratedFileStream> RulesFileStream;
553
  std::unique_ptr<cmGeneratedFileStream> CompileCommandsStream;
554
555
  /// The set of rules added to the generated build system.
556
  std::unordered_set<std::string> Rules;
557
558
  /// Length of rule command, used by rsp file evaluation
559
  std::unordered_map<std::string, int> RuleCmdLength;
560
561
  bool UsingGCCOnWindows = false;
562
563
  /// The set of custom command outputs we have seen.
564
  std::set<std::string> CustomCommandOutputs;
565
566
  /// The mapping from source file to assumed dependencies.
567
  std::map<std::string, std::set<std::string>> AssumedSourceDependencies;
568
569
  /// Utility targets which have per-config outputs
570
  std::set<std::string> PerConfigUtilityTargets;
571
572
  struct TargetAlias
573
  {
574
    cmGeneratorTarget* GeneratorTarget;
575
    std::string Config;
576
  };
577
  using TargetAliasMap = std::map<std::string, TargetAlias>;
578
  TargetAliasMap TargetAliases;
579
  TargetAliasMap DefaultTargetAliases;
580
581
  /// the local cache for calls to ConvertToNinjaPath
582
  mutable std::unordered_map<std::string, std::string> ConvertToNinjaPathCache;
583
584
  std::string NinjaCommand;
585
  std::string NinjaVersion;
586
  bool NinjaSupportsConsolePool = false;
587
  bool NinjaSupportsImplicitOuts = false;
588
  bool NinjaSupportsManifestRestat = false;
589
  bool NinjaSupportsMultilineDepfile = false;
590
  bool NinjaSupportsDyndepsCxx = false;
591
  bool NinjaSupportsDyndepsFortran = false;
592
  bool NinjaSupportsRestatTool = false;
593
  bool NinjaSupportsUnconditionalRecompactTool = false;
594
  bool NinjaSupportsMultipleOutputs = false;
595
  bool NinjaSupportsMetadataOnRegeneration = false;
596
  bool NinjaSupportsCodePage = false;
597
  bool NinjaSupportsCWDDepend = false;
598
599
  codecvt_Encoding NinjaExpectedEncoding = codecvt_Encoding::None;
600
601
#ifdef _WIN32
602
  // Windows Command shell.
603
  std::string Comspec;
604
#endif
605
606
  bool DiagnosedCxxModuleNinjaSupport = false;
607
608
  void InitOutputPathPrefix();
609
610
  std::string OutputPathPrefix;
611
  std::string TargetAll;
612
  std::string CMakeCacheFile;
613
614
  struct ByConfig
615
  {
616
    std::set<std::string> AdditionalCleanFiles;
617
618
    /// The set of custom commands we have seen.
619
    std::set<cmCustomCommand const*> CustomCommands;
620
621
    struct TargetDependsClosureKey
622
    {
623
      cmGeneratorTarget const* Target;
624
      std::string Config;
625
      bool GenexOutput;
626
    };
627
628
    std::map<TargetDependsClosureKey, std::unordered_set<std::string>>
629
      TargetDependsClosures;
630
631
    TargetAliasMap TargetAliases;
632
633
    cmNinjaDeps ByproductsForCleanTarget;
634
  };
635
  std::map<std::string, ByConfig> Configs;
636
637
  cmNinjaDeps ByproductsForCleanTarget;
638
639
  friend bool operator==(ByConfig::TargetDependsClosureKey const& lhs,
640
                         ByConfig::TargetDependsClosureKey const& rhs);
641
  friend bool operator!=(ByConfig::TargetDependsClosureKey const& lhs,
642
                         ByConfig::TargetDependsClosureKey const& rhs);
643
  friend bool operator<(ByConfig::TargetDependsClosureKey const& lhs,
644
                        ByConfig::TargetDependsClosureKey const& rhs);
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
};
652
653
class cmGlobalNinjaMultiGenerator : public cmGlobalNinjaGenerator
654
{
655
public:
656
  /// The default name of Ninja's common file. Typically: common.ninja.
657
  static char const* NINJA_COMMON_FILE;
658
  /// The default file extension to use for per-config Ninja files.
659
  static char const* NINJA_FILE_EXTENSION;
660
661
  cmGlobalNinjaMultiGenerator(cmake* cm);
662
0
  bool IsMultiConfig() const override { return true; }
663
  static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory()
664
35
  {
665
35
    return std::unique_ptr<cmGlobalGeneratorFactory>(
666
35
      new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>());
667
35
  }
668
669
  static cmDocumentationEntry GetDocumentation();
670
671
  std::string GetName() const override
672
0
  {
673
0
    return cmGlobalNinjaMultiGenerator::GetActualName();
674
0
  }
675
676
0
  static std::string GetActualName() { return "Ninja Multi-Config"; }
677
678
  std::string BuildAlias(std::string const& alias,
679
                         std::string const& config) const override
680
0
  {
681
0
    if (config.empty()) {
682
0
      return alias;
683
0
    }
684
0
    return cmStrCat(alias, ":", config);
685
0
  }
686
687
  std::string ConfigDirectory(std::string const& config) const override
688
0
  {
689
0
    if (!config.empty()) {
690
0
      return cmStrCat('/', config);
691
0
    }
692
0
    return "";
693
0
  }
694
695
0
  char const* GetCMakeCFGIntDir() const override { return "${CONFIGURATION}"; }
696
697
  std::string ExpandCFGIntDir(std::string const& str,
698
                              std::string const& config) const override;
699
700
  cmGeneratedFileStream* GetImplFileStream(
701
    std::string const& config) const override
702
0
  {
703
0
    return this->ImplFileStreams.at(config).get();
704
0
  }
705
706
  cmGeneratedFileStream* GetConfigFileStream(
707
    std::string const& config) const override
708
0
  {
709
0
    return this->ConfigFileStreams.at(config).get();
710
0
  }
711
712
  cmGeneratedFileStream* GetDefaultFileStream() const override
713
0
  {
714
0
    return this->DefaultFileStream.get();
715
0
  }
716
717
  cmGeneratedFileStream* GetCommonFileStream() const override
718
0
  {
719
0
    return this->CommonFileStream.get();
720
0
  }
721
722
  void AppendNinjaFileArgument(GeneratedMakeCommand& command,
723
                               std::string const& config) const override;
724
725
  static std::string GetNinjaImplFilename(std::string const& config);
726
  static std::string GetNinjaConfigFilename(std::string const& config);
727
728
  void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const override;
729
730
  void GetQtAutoGenConfigs(std::vector<std::string>& configs) const override;
731
732
  bool InspectConfigTypeVariables() override;
733
734
  std::string GetDefaultBuildConfig() const override;
735
736
0
  bool SupportsDefaultBuildType() const override { return true; }
737
0
  bool SupportsCrossConfigs() const override { return true; }
738
0
  bool SupportsDefaultConfigs() const override { return true; }
739
740
  std::string OrderDependsTargetForTarget(
741
    cmGeneratorTarget const* target, std::string const& config) const override;
742
743
protected:
744
  bool OpenBuildFileStreams() override;
745
  void CloseBuildFileStreams() override;
746
747
private:
748
  std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>
749
    ImplFileStreams;
750
  std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>
751
    ConfigFileStreams;
752
  std::unique_ptr<cmGeneratedFileStream> CommonFileStream;
753
  std::unique_ptr<cmGeneratedFileStream> DefaultFileStream;
754
};