Coverage Report

Created: 2026-10-28 06:38

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
0
  bool SupportsInstallPrepFileDependencies() 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
0
      : GG(gg)
122
0
    {
123
0
    }
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
                               std::string const& 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, std::string const& name,
154
                            std::string const& value,
155
                            std::string const& 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, std::string const& filename,
162
                           std::string const& 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, cmNinjaDeps const& targets,
169
                           std::string const& comment = "");
170
171
0
  bool IsGCCOnWindows() const { return this->UsingGCCOnWindows; }
172
0
  void MarkAsGCCOnWindows() { this->UsingGCCOnWindows = true; }
173
174
  cmGlobalNinjaGenerator(cmake* cm);
175
176
  static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory()
177
19.9k
  {
178
19.9k
    return std::unique_ptr<cmGlobalGeneratorFactory>(
179
19.9k
      new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>());
180
19.9k
  }
181
182
  std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
183
    cmMakefile* mf) override;
184
185
  std::string GetName() const override
186
0
  {
187
0
    return cmGlobalNinjaGenerator::GetActualName();
188
0
  }
189
190
0
  static std::string GetActualName() { return "Ninja"; }
191
192
0
  bool IsNinja() const override { return true; }
193
194
  /** Get encoding used by generator for ninja files */
195
  codecvt_Encoding GetMakefileEncoding() const override;
196
197
  static cmDocumentationEntry GetDocumentation();
198
199
  void EnableLanguage(std::vector<std::string> const& languages,
200
                      cmMakefile* mf, bool optional) override;
201
202
  std::vector<GeneratedMakeCommand> GenerateBuildCommand(
203
    std::string const& makeProgram, std::string const& projectName,
204
    std::string const& projectDir, std::vector<std::string> const& targetNames,
205
    std::string const& config, int jobs, bool verbose,
206
    cmBuildOptions buildOptions = cmBuildOptions(),
207
    std::vector<std::string> const& makeOptions = std::vector<std::string>(),
208
    BuildTryCompile isInTryCompile = BuildTryCompile::No) override;
209
210
  // Setup target names
211
0
  char const* GetAllTargetName() const override { return "all"; }
212
0
  char const* GetInstallTargetName() const override { return "install"; }
213
  char const* GetInstallLocalTargetName() const override
214
0
  {
215
0
    return "install/local";
216
0
  }
217
  char const* GetInstallStripTargetName() const override
218
0
  {
219
0
    return "install/strip";
220
0
  }
221
  char const* GetInstallParallelTargetName() const
222
0
  {
223
0
    return "install/parallel";
224
0
  }
225
0
  char const* GetTestTargetName() const override { return "test"; }
226
0
  char const* GetPackageTargetName() const override { return "package"; }
227
  char const* GetPackageSourceTargetName() const override
228
0
  {
229
0
    return "package_source";
230
0
  }
231
  char const* GetRebuildCacheTargetName() const override
232
0
  {
233
0
    return "rebuild_cache";
234
0
  }
235
0
  char const* GetCleanTargetName() const override { return "clean"; }
236
237
0
  bool SupportsCustomCommandDepfile() const override { return true; }
238
  cm::optional<cmDepfileFormat> DepfileFormat() const override
239
0
  {
240
0
    return cmDepfileFormat::GccDepfile;
241
0
  }
242
243
0
  bool SupportsLinkerDependencyFile() const override { return true; }
244
245
  virtual cmGeneratedFileStream* GetImplFileStream(
246
    std::string const& /*config*/) const
247
0
  {
248
0
    return this->BuildFileStream.get();
249
0
  }
250
251
  virtual cmGeneratedFileStream* GetConfigFileStream(
252
    std::string const& /*config*/) const
253
0
  {
254
0
    return this->BuildFileStream.get();
255
0
  }
256
257
  virtual cmGeneratedFileStream* GetDefaultFileStream() const
258
0
  {
259
0
    return this->BuildFileStream.get();
260
0
  }
261
262
  virtual cmGeneratedFileStream* GetCommonFileStream() const
263
0
  {
264
0
    return this->BuildFileStream.get();
265
0
  }
266
267
  cmGeneratedFileStream* GetRulesFileStream() const
268
0
  {
269
0
    return this->RulesFileStream.get();
270
0
  }
271
272
  std::string const& ConvertToNinjaPath(std::string const& path) const;
273
  std::string ConvertToNinjaAbsPath(std::string path) const;
274
275
  struct MapToNinjaPathImpl
276
  {
277
    cmGlobalNinjaGenerator* GG;
278
    MapToNinjaPathImpl(cmGlobalNinjaGenerator* gg)
279
0
      : GG(gg)
280
0
    {
281
0
    }
282
    std::string operator()(std::string const& path) const
283
0
    {
284
0
      return this->GG->ConvertToNinjaPath(path);
285
0
    }
286
  };
287
0
  MapToNinjaPathImpl MapToNinjaPath() { return { this }; }
288
289
#ifdef _WIN32
290
  std::string const& GetComspec() const { return this->Comspec; }
291
#endif
292
293
  // -- Additional clean files
294
  void AddAdditionalCleanFile(std::string fileName, std::string const& config);
295
  char const* GetAdditionalCleanTargetName() const
296
0
  {
297
0
    return "CMakeFiles/clean.additional";
298
0
  }
299
300
  static char const* GetByproductsForCleanTargetName()
301
0
  {
302
0
    return "CMakeFiles/cmake_byproducts_for_clean_target";
303
0
  }
304
305
  void AddCXXCompileCommand(std::string const& commandLine,
306
                            std::string const& sourceFile,
307
                            std::string const& objPath);
308
309
  /**
310
   * Add a rule to the generated build system.
311
   * Call WriteRule() behind the scene but perform some check before like:
312
   * - Do not add twice the same rule.
313
   */
314
  void AddRule(cmNinjaRule const& rule);
315
316
  bool HasRule(std::string const& name);
317
318
  void AddCustomCommandRule();
319
  void AddMacOSXContentRule();
320
321
  bool HasCustomCommandOutput(std::string const& output)
322
0
  {
323
0
    return this->CustomCommandOutputs.find(output) !=
324
0
      this->CustomCommandOutputs.end();
325
0
  }
326
327
  /// Called when we have seen the given custom command.  Returns true
328
  /// if we has seen it before.
329
  bool SeenCustomCommand(cmCustomCommand const* cc, std::string const& config)
330
0
  {
331
0
    return !this->Configs[config].CustomCommands.insert(cc).second;
332
0
  }
333
334
  /// Called when we have seen the given custom command output.
335
  void SeenCustomCommandOutput(std::string const& output)
336
0
  {
337
0
    this->CustomCommandOutputs.insert(output);
338
    // We don't need the assumed dependencies anymore, because we have
339
    // an output.
340
0
    this->AssumedSourceDependencies.erase(output);
341
0
  }
342
343
  void AddAssumedSourceDependencies(std::string const& source,
344
                                    cmNinjaDeps const& deps)
345
0
  {
346
0
    std::set<std::string>& ASD = this->AssumedSourceDependencies[source];
347
    // Because we may see the same source file multiple times (same source
348
    // specified in multiple targets), compute the union of any assumed
349
    // dependencies.
350
0
    ASD.insert(deps.begin(), deps.end());
351
0
  }
352
353
  virtual std::string OrderDependsTargetForTarget(
354
    cmGeneratorTarget const* target, std::string const& config) const;
355
356
  std::string OrderDependsTargetForTargetPrivate(
357
    cmGeneratorTarget const* target, std::string const& config) const;
358
359
  void AppendTargetOutputs(cmGeneratorTarget const* target,
360
                           cmNinjaDeps& outputs, std::string const& config,
361
                           cmNinjaTargetDepends depends) const;
362
  void AppendTargetDepends(cmGeneratorTarget const* target,
363
                           cmNinjaDeps& outputs, std::string const& config,
364
                           std::string const& fileConfig,
365
                           cmNinjaTargetDepends depends);
366
  void AppendTargetDependsClosure(cmGeneratorTarget const* target,
367
                                  std::unordered_set<std::string>& outputs,
368
                                  std::string const& config,
369
                                  std::string const& fileConfig,
370
                                  bool genexOutput, bool omit_self = true);
371
372
  void AppendDirectoryForConfig(std::string const& prefix,
373
                                std::string const& config,
374
                                std::string const& suffix,
375
                                std::string& dir) override;
376
377
  virtual void AppendNinjaFileArgument(GeneratedMakeCommand& /*command*/,
378
                                       std::string const& /*config*/) const
379
0
  {
380
0
  }
381
382
  virtual void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const
383
0
  {
384
0
    outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE));
385
0
    this->AddCMakeFilesToRebuild(outputs);
386
0
  }
387
388
  int GetRuleCmdLength(std::string const& name)
389
0
  {
390
0
    return this->RuleCmdLength[name];
391
0
  }
392
393
  void AddTargetAlias(std::string const& alias, cmGeneratorTarget* target,
394
                      std::string const& config);
395
396
  bool SupportsShortObjectNames() const override;
397
  void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
398
399
  // Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3
400
0
  static std::string RequiredNinjaVersion() { return "1.3"; }
401
0
  static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; }
402
0
  static std::string RequiredNinjaVersionForImplicitOuts() { return "1.7"; }
403
0
  static std::string RequiredNinjaVersionForManifestRestat() { return "1.8"; }
404
  static std::string RequiredNinjaVersionForMultilineDepfile()
405
0
  {
406
0
    return "1.9";
407
0
  }
408
0
  static std::string RequiredNinjaVersionForDyndepsCxx() { return "1.11"; }
409
0
  static std::string RequiredNinjaVersionForDyndepsFortran() { return "1.10"; }
410
0
  static std::string RequiredNinjaVersionForRestatTool() { return "1.10"; }
411
  static std::string RequiredNinjaVersionForUnconditionalRecompactTool()
412
0
  {
413
0
    return "1.10";
414
0
  }
415
  static std::string RequiredNinjaVersionForMultipleOutputs()
416
0
  {
417
0
    return "1.10";
418
0
  }
419
  static std::string RequiredNinjaVersionForMetadataOnRegeneration()
420
0
  {
421
0
    return "1.10.2";
422
0
  }
423
0
  static std::string RequiredNinjaVersionForCodePage() { return "1.11"; }
424
0
  static std::string RequiredNinjaVersionForCWDDepend() { return "1.7"; }
425
  bool SupportsDirectConsole() const override;
426
  bool SupportsImplicitOuts() const;
427
  bool SupportsManifestRestat() const;
428
  bool SupportsMultilineDepfile() const;
429
  bool SupportsCWDDepend() const;
430
431
  std::string NinjaOutputPath(std::string const& path) const;
432
0
  bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
433
  void StripNinjaOutputPathPrefixAsSuffix(std::string& path);
434
435
  /// Create a directory unless it was already created or found to exist
436
  /// during this generation.
437
  void EnsureDirectoryExists(std::string const& path);
438
439
  bool WriteDyndepFile(
440
    std::string const& dir_top_src, std::string const& dir_top_bld,
441
    std::string const& dir_cur_src, std::string const& dir_cur_bld,
442
    std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
443
    std::string const& module_dir,
444
    std::vector<std::string> const& linked_target_dirs,
445
    std::vector<std::string> const& forward_modules_from_target_dirs,
446
    std::string const& native_target_dir, std::string const& arg_lang,
447
    std::string const& arg_modmapfmt, cmCxxModuleExportInfo const& export_info,
448
    Json::Value const* cxx_interface_objects = nullptr);
449
450
  virtual std::string BuildAlias(std::string const& alias,
451
                                 std::string const& /*config*/) const
452
0
  {
453
0
    return alias;
454
0
  }
455
456
  virtual std::string ConfigDirectory(std::string const& /*config*/) const
457
0
  {
458
0
    return "";
459
0
  }
460
461
  cmNinjaDeps& GetByproductsForCleanTarget()
462
0
  {
463
0
    return this->ByproductsForCleanTarget;
464
0
  }
465
466
  cmNinjaDeps& GetByproductsForCleanTarget(std::string const& config)
467
0
  {
468
0
    return this->Configs[config].ByproductsForCleanTarget;
469
0
  }
470
471
  bool EnableCrossConfigBuild() const;
472
473
  std::set<std::string> GetCrossConfigs(std::string const& config) const;
474
475
  std::set<std::string> const& GetDefaultConfigs() const override
476
0
  {
477
0
    return this->DefaultConfigs;
478
0
  }
479
480
  std::set<std::string> const& GetPerConfigUtilityTargets() const
481
0
  {
482
0
    return this->PerConfigUtilityTargets;
483
0
  }
484
485
  void AddPerConfigUtilityTarget(std::string const& name)
486
0
  {
487
0
    this->PerConfigUtilityTargets.insert(name);
488
0
  }
489
490
  bool IsSingleConfigUtility(cmGeneratorTarget const* target) const;
491
492
  bool CheckCxxModuleSupport(CxxModuleSupportQuery query) override;
493
0
  bool SupportsBuildDatabase() const override { return true; }
494
495
  std::string ConvertToOutputPath(std::string path) const override;
496
497
protected:
498
  std::vector<std::string> const& GetConfigNames() const;
499
500
  void Generate() override;
501
502
0
  bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }
503
504
  virtual bool OpenBuildFileStreams();
505
  virtual void CloseBuildFileStreams();
506
507
  bool OpenFileStream(std::unique_ptr<cmGeneratedFileStream>& stream,
508
                      std::string const& name);
509
510
  static cm::optional<std::set<std::string>> ListSubsetWithAll(
511
    std::set<std::string> const& all, std::set<std::string> const& defaults,
512
    std::vector<std::string> const& items);
513
514
  std::set<std::string> CrossConfigs;
515
  std::set<std::string> DefaultConfigs;
516
  std::string DefaultFileConfig;
517
518
private:
519
  bool FindMakeProgram(cmMakefile* mf) override;
520
  void CheckNinjaFeatures();
521
  void CheckNinjaCodePage();
522
  bool CheckLanguages(std::vector<std::string> const& languages,
523
                      cmMakefile* mf) const override;
524
  bool CheckFortran(cmMakefile* mf) const;
525
  bool CheckISPC(cmMakefile* mf) const;
526
527
  void CloseCompileCommandsStream();
528
529
  bool OpenRulesFileStream();
530
  void CloseRulesFileStream();
531
  void CleanMetaData();
532
533
  void AppendCodegenOutputs(cmGeneratorTarget const* target, cmNinjaDeps& deps,
534
                            std::string const& config);
535
  void AppendCodegenTargetDepends(cmGeneratorTarget const* target,
536
                                  cmNinjaDeps& deps, std::string const& config,
537
                                  std::set<cmGeneratorTarget const*>& visited);
538
539
  /// Write the common disclaimer text at the top of each build file.
540
  void WriteDisclaimer(std::ostream& os) const;
541
542
  void WriteAssumedSourceDependencies();
543
  void WriteInstallPrepTargets();
544
  void WriteTestPrepTargets();
545
546
  void WritePerConfigPhony(std::string const& config,
547
                           cmNinjaBuild const& build);
548
  void WritePerConfigPhonyAliases(
549
    std::map<std::string, std::set<std::string>> const& configsByName);
550
551
  void WriteTargetAliases(std::ostream& os);
552
  void WriteFolderTargets(std::ostream& os);
553
554
  void WriteBuiltinTargets(std::ostream& os);
555
  void WriteTargetDefault(std::ostream& os);
556
  void WriteTargetRebuildManifest(std::ostream& os);
557
  bool WriteTargetCleanAdditional(std::ostream& os);
558
  void WriteTargetClean(std::ostream& os);
559
#ifndef CMAKE_BOOTSTRAP
560
  void WriteTargetInstrument(std::ostream& os);
561
#endif
562
  void WriteTargetHelp(std::ostream& os);
563
564
  void ComputeTargetDependsClosure(
565
    cmGeneratorTarget const* target,
566
    std::set<cmGeneratorTarget const*>& depends);
567
568
  std::string CMakeCmd() const;
569
  std::string NinjaCmd() const;
570
571
  /// The file containing the build statement. (the relationship of the
572
  /// compilation DAG).
573
  std::unique_ptr<cmGeneratedFileStream> BuildFileStream;
574
  /// The file containing the rule statements. (The action attached to each
575
  /// edge of the compilation DAG).
576
  std::unique_ptr<cmGeneratedFileStream> RulesFileStream;
577
  std::unique_ptr<cmGeneratedFileStream> CompileCommandsStream;
578
579
  /// The set of rules added to the generated build system.
580
  std::unordered_set<std::string> Rules;
581
582
  /// Length of rule command, used by rsp file evaluation
583
  std::unordered_map<std::string, int> RuleCmdLength;
584
585
  bool UsingGCCOnWindows = false;
586
587
  /// The set of custom command outputs we have seen.
588
  std::set<std::string> CustomCommandOutputs;
589
590
  /// Directories known to exist, see EnsureDirectoryExists.
591
  std::unordered_set<std::string> ExistingDirectories;
592
593
  /// The mapping from source file to assumed dependencies.
594
  std::map<std::string, std::set<std::string>> AssumedSourceDependencies;
595
596
  /// Utility targets which have per-config outputs
597
  std::set<std::string> PerConfigUtilityTargets;
598
599
  struct TargetAlias
600
  {
601
    cmGeneratorTarget* GeneratorTarget;
602
    std::string Config;
603
  };
604
  using TargetAliasMap = std::map<std::string, TargetAlias>;
605
  TargetAliasMap TargetAliases;
606
  TargetAliasMap DefaultTargetAliases;
607
608
  /// the local cache for calls to ConvertToNinjaPath
609
  mutable std::unordered_map<std::string, std::string> ConvertToNinjaPathCache;
610
611
  std::string NinjaCommand;
612
  std::string NinjaVersion;
613
  bool NinjaSupportsConsolePool = false;
614
  bool NinjaSupportsImplicitOuts = false;
615
  bool NinjaSupportsManifestRestat = false;
616
  bool NinjaSupportsMultilineDepfile = false;
617
  bool NinjaSupportsDyndepsCxx = false;
618
  bool NinjaSupportsDyndepsFortran = false;
619
  bool NinjaSupportsRestatTool = false;
620
  bool NinjaSupportsUnconditionalRecompactTool = false;
621
  bool NinjaSupportsMultipleOutputs = false;
622
  bool NinjaSupportsMetadataOnRegeneration = false;
623
  bool NinjaSupportsCodePage = false;
624
  bool NinjaSupportsCWDDepend = false;
625
626
  codecvt_Encoding NinjaExpectedEncoding = codecvt_Encoding::None;
627
628
#ifdef _WIN32
629
  // Windows Command shell.
630
  std::string Comspec;
631
#endif
632
633
  bool DiagnosedCxxModuleNinjaSupport = false;
634
635
  void InitOutputPathPrefix();
636
637
  std::string OutputPathPrefix;
638
  std::string TargetAll;
639
  std::string CMakeCacheFile;
640
641
  struct ByConfig
642
  {
643
    std::set<std::string> AdditionalCleanFiles;
644
645
    /// The set of custom commands we have seen.
646
    std::set<cmCustomCommand const*> CustomCommands;
647
648
    struct TargetDependsClosureKey
649
    {
650
      cmGeneratorTarget const* Target;
651
      std::string Config;
652
      bool GenexOutput;
653
    };
654
655
    std::map<TargetDependsClosureKey, std::unordered_set<std::string>>
656
      TargetDependsClosures;
657
658
    TargetAliasMap TargetAliases;
659
660
    cmNinjaDeps ByproductsForCleanTarget;
661
  };
662
  std::map<std::string, ByConfig> Configs;
663
664
  cmNinjaDeps ByproductsForCleanTarget;
665
666
  friend bool operator==(ByConfig::TargetDependsClosureKey const& lhs,
667
                         ByConfig::TargetDependsClosureKey const& rhs);
668
  friend bool operator!=(ByConfig::TargetDependsClosureKey const& lhs,
669
                         ByConfig::TargetDependsClosureKey const& rhs);
670
  friend bool operator<(ByConfig::TargetDependsClosureKey const& lhs,
671
                        ByConfig::TargetDependsClosureKey const& rhs);
672
  friend bool operator>(ByConfig::TargetDependsClosureKey const& lhs,
673
                        ByConfig::TargetDependsClosureKey const& rhs);
674
  friend bool operator<=(ByConfig::TargetDependsClosureKey const& lhs,
675
                         ByConfig::TargetDependsClosureKey const& rhs);
676
  friend bool operator>=(ByConfig::TargetDependsClosureKey const& lhs,
677
                         ByConfig::TargetDependsClosureKey const& rhs);
678
};
679
680
class cmGlobalNinjaMultiGenerator : public cmGlobalNinjaGenerator
681
{
682
public:
683
  /// The default name of Ninja's common file. Typically: common.ninja.
684
  static char const* NINJA_COMMON_FILE;
685
  /// The default file extension to use for per-config Ninja files.
686
  static char const* NINJA_FILE_EXTENSION;
687
688
  cmGlobalNinjaMultiGenerator(cmake* cm);
689
0
  bool IsMultiConfig() const override { return true; }
690
  static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory()
691
19.9k
  {
692
19.9k
    return std::unique_ptr<cmGlobalGeneratorFactory>(
693
19.9k
      new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>());
694
19.9k
  }
695
696
  static cmDocumentationEntry GetDocumentation();
697
698
  std::string GetName() const override
699
0
  {
700
0
    return cmGlobalNinjaMultiGenerator::GetActualName();
701
0
  }
702
703
0
  static std::string GetActualName() { return "Ninja Multi-Config"; }
704
705
  std::string BuildAlias(std::string const& alias,
706
                         std::string const& config) const override
707
0
  {
708
0
    if (config.empty()) {
709
0
      return alias;
710
0
    }
711
0
    return cmStrCat(alias, ":", config);
712
0
  }
713
714
  std::string ConfigDirectory(std::string const& config) const override
715
0
  {
716
0
    if (!config.empty()) {
717
0
      return cmStrCat('/', config);
718
0
    }
719
0
    return "";
720
0
  }
721
722
0
  char const* GetCMakeCFGIntDir() const override { return "${CONFIGURATION}"; }
723
724
  std::string ExpandCFGIntDir(std::string const& str,
725
                              std::string const& config) const override;
726
727
  cmGeneratedFileStream* GetImplFileStream(
728
    std::string const& config) const override
729
0
  {
730
0
    return this->ImplFileStreams.at(config).get();
731
0
  }
732
733
  cmGeneratedFileStream* GetConfigFileStream(
734
    std::string const& config) const override
735
0
  {
736
0
    return this->ConfigFileStreams.at(config).get();
737
0
  }
738
739
  cmGeneratedFileStream* GetDefaultFileStream() const override
740
0
  {
741
0
    return this->DefaultFileStream.get();
742
0
  }
743
744
  cmGeneratedFileStream* GetCommonFileStream() const override
745
0
  {
746
0
    return this->CommonFileStream.get();
747
0
  }
748
749
  void AppendNinjaFileArgument(GeneratedMakeCommand& command,
750
                               std::string const& config) const override;
751
752
  static std::string GetNinjaImplFilename(std::string const& config);
753
  static std::string GetNinjaConfigFilename(std::string const& config);
754
755
  void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const override;
756
757
  void GetQtAutoGenConfigs(std::vector<std::string>& configs) const override;
758
759
  bool InspectConfigTypeVariables() override;
760
761
  std::string GetDefaultBuildConfig() const override;
762
763
0
  bool SupportsDefaultBuildType() const override { return true; }
764
0
  bool SupportsCrossConfigs() const override { return true; }
765
0
  bool SupportsDefaultConfigs() const override { return true; }
766
767
  std::string OrderDependsTargetForTarget(
768
    cmGeneratorTarget const* target, std::string const& config) const override;
769
770
protected:
771
  bool OpenBuildFileStreams() override;
772
  void CloseBuildFileStreams() override;
773
774
private:
775
  std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>
776
    ImplFileStreams;
777
  std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>
778
    ConfigFileStreams;
779
  std::unique_ptr<cmGeneratedFileStream> CommonFileStream;
780
  std::unique_ptr<cmGeneratedFileStream> DefaultFileStream;
781
};