File: cmGlobalFastbuildGenerator.h

package info (click to toggle)
cmake 4.2.1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 152,348 kB
  • sloc: ansic: 403,894; cpp: 303,807; sh: 4,097; python: 3,582; yacc: 3,106; lex: 1,279; f90: 538; asm: 471; lisp: 375; cs: 270; java: 266; fortran: 239; objc: 215; perl: 213; xml: 198; makefile: 108; javascript: 83; pascal: 63; tcl: 55; php: 25; ruby: 22
file content (627 lines) | stat: -rw-r--r-- 20,239 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#pragma once

#include <algorithm>
#include <iterator>
#include <map>
#include <set>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include <cm/memory>
#include <cm/optional>

#include <assert.h>

#include "cmBuildOptions.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalCommonGenerator.h"
class cmFastbuildTargetGenerator;
class cmGeneratorTarget;
class cmGlobalGeneratorFactory;
class cmMakefile;
class cmake;
struct cmDocumentationEntry;

#define FASTBUILD_DOLLAR_TAG "FASTBUILD_DOLLAR_TAG"
#define FASTBUILD_1_INPUT_PLACEHOLDER                                         \
  FASTBUILD_DOLLAR_TAG "FB_INPUT_1_PLACEHOLDER" FASTBUILD_DOLLAR_TAG
#define FASTBUILD_1_0_INPUT_PLACEHOLDER                                       \
  FASTBUILD_DOLLAR_TAG "FB_INPUT_1_0_PLACEHOLDER" FASTBUILD_DOLLAR_TAG
#define FASTBUILD_1_1_INPUT_PLACEHOLDER                                       \
  FASTBUILD_DOLLAR_TAG "FB_INPUT_1_1_PLACEHOLDER" FASTBUILD_DOLLAR_TAG

#define FASTBUILD_2_INPUT_PLACEHOLDER                                         \
  FASTBUILD_DOLLAR_TAG "FB_INPUT_2_PLACEHOLDER" FASTBUILD_DOLLAR_TAG

#define FASTBUILD_3_INPUT_PLACEHOLDER                                         \
  FASTBUILD_DOLLAR_TAG "FB_INPUT_3_PLACEHOLDER" FASTBUILD_DOLLAR_TAG

// Alias to artifacts that can be consumed by the linker (DLL or Library).
#define FASTBUILD_LINK_ARTIFACTS_ALIAS_POSTFIX "-link-artifacts"
// Alias to all the ObjectList nodes.
#define FASTBUILD_OBJECTS_ALIAS_POSTFIX "-objects"
// Alias to all the dependencies of the target.
#define FASTBUILD_DEPS_ARTIFACTS_ALIAS_POSTFIX "-deps"
#define FASTBUILD_PRE_BUILD_ALIAS_POSTFIX "-pre-build"
#define FASTBUILD_PRE_LINK_ALIAS_POSTFIX "-pre-link"
#define FASTBUILD_POST_BUILD_ALIAS_POSTFIX "-post-build"
// Alias to all other custom commands in the target.
#define FASTBUILD_CUSTOM_COMMAND_ALIAS_POSTFIX "-custom-commands"
// Alias to outputs produced by a custom command (since FASTBuild exec node
// does not support more than 1 output).
#define FASTBUILD_OUTPUTS_ALIAS_POSTFIX "-outputs"
// Alias to byproducts produced by a custom command (since FASTBuild exec node
// does not support more than 1 output).
#define FASTBUILD_BYPRODUCTS_ALIAS_POSTFIX "-byproducts"

#define FASTBUILD_COMPILER_PREFIX "Compiler_"
#define FASTBUILD_LAUNCHER_PREFIX "Launcher_"
#define FASTBUILD_LINKER_LAUNCHER_PREFIX "LinkerLauncher_"

#define FASTBUILD_RESTAT_FILE "FASTBUILD_RESTAT"

#define FASTBUILD_UTIL_CONCURRENCY_GROUP_NAME "Utils"

#define FASTBUILD_ALL_TARGET_NAME "all"
#define FASTBUILD_CLEAN_TARGET_NAME "clean"

#define FASTBUILD_NOOP_FILE_NAME "fbuild_noop"
#define FASTBUILD_CLEAN_FILE_NAME "fbuild_clean-out"

#define FASTBUILD_BUILD_FILE "fbuild.bff"

#define FASTBUILD_DUMMY_OUTPUT_EXTENSION ".fbuild-cc-out"

#if defined(_WIN32)
#  define FASTBUILD_SCRIPT_FILE_EXTENSION ".bat"
#  define FASTBUILD_SCRIPT_FILE_ARG "/C "
#  define FASTBUILD_SCRIPT_CD "cd /D "
#  define FASTBUILD_CLEAN_SCRIPT_NAME "clean" FASTBUILD_SCRIPT_FILE_EXTENSION
#else
#  define FASTBUILD_SCRIPT_FILE_EXTENSION ".sh"
#  define FASTBUILD_SCRIPT_FILE_ARG ""
#  define FASTBUILD_SCRIPT_CD "cd "
#  define FASTBUILD_CLEAN_SCRIPT_NAME "clean" FASTBUILD_SCRIPT_FILE_EXTENSION
#endif

enum class FastbuildTargetDepType
{
  // Order-only dependency that is not going to appear in the generated file.
  ORDER_ONLY,
  // Regular target dep.
  REGULAR,
};
struct FastbuildTargetDep
{
  std::string Name;
  FastbuildTargetDepType Type = FastbuildTargetDepType::REGULAR;
  FastbuildTargetDep(std::string n)
    : Name(std::move(n))
  {
  }
  bool operator==(FastbuildTargetDep const& rhs) const
  {
    return this->Name == rhs.Name;
  }
  bool operator<(FastbuildTargetDep const& rhs) const
  {
    return this->Name < rhs.Name;
  }
};

enum class FastbuildTargetType
{
  ALIAS, // Alias node
  EXEC,  // Exec node
  LINK,  // Library, DLL or Executable
  OBJECTLIST,
  UNITY,
};

struct FastbuildTargetBase
{
  // Target name with config postfix.
  std::string Name;
  // Target name without config postfix, we use it to locate IDE project for
  // the given target and add +1 config to it.
  std::string BaseName;
  std::string BasePath;
  std::set<FastbuildTargetDep> PreBuildDependencies;
  bool Hidden = true;
  FastbuildTargetType Type;
  explicit FastbuildTargetBase(FastbuildTargetType TargetType)
    : Type(TargetType)
  {
  }
};
using FastbuildTargetPtrT = std::unique_ptr<FastbuildTargetBase>;

struct FastbuildAliasNode : public FastbuildTargetBase
{
  bool ExcludeFromAll = false;
  FastbuildAliasNode()
    : FastbuildTargetBase(FastbuildTargetType::ALIAS)
  {
  }
};

struct FastbuildExecNode : public FastbuildTargetBase
{
  std::string ExecExecutable;
  std::string ExecArguments;
  std::string ScriptFile;
  std::string ExecWorkingDir;
  bool ExecUseStdOutAsOutput = false;
  std::string ExecOutput;
  std::vector<std::string> ExecInput;
  std::vector<std::string> ExecInputPath;
  std::vector<std::string> ExecInputPattern;
  bool ExecInputPathRecurse = false;
  bool ExecAlways = false;
  FastbuildAliasNode OutputsAlias;
  FastbuildAliasNode ByproductsAlias;
  std::string ConcurrencyGroupName;
  bool ExcludeFromAll = false;
  FastbuildExecNode()
    : FastbuildTargetBase(FastbuildTargetType::EXEC)
  {
  }

  bool NeedsDepsCheckExec = false;
};

struct FastbuildCompiler
{
  std::map<std::string, std::string> ExtraVariables;
  std::string Name;
  std::string Executable;
  std::string CmakeCompilerID;
  std::string CompilerFamily = "custom";
  std::string CmakeCompilerVersion;
  std::string Language;
  std::vector<std::string> ExtraFiles;
  bool UseLightCache = false;
  bool ClangRewriteIncludes = true;
  bool ClangGCCUpdateXLanguageArg = false;
  bool AllowResponseFile = false;
  bool ForceResponseFile = false;
  bool UseRelativePaths = false;
  bool UseDeterministicPaths = false;
  std::string SourceMapping;
  // Only used for launchers.
  std::string Args;
  bool DontUseEnv = false;
};

struct FastbuildObjectListNode : public FastbuildTargetBase
{
  std::string Compiler;
  std::string CompilerOptions;
  std::string CompilerOutputPath;
  std::string CompilerOutputExtension;
  std::vector<std::string> CompilerInputUnity;
  std::string PCHInputFile;
  std::string PCHOutputFile;
  std::string PCHOptions;

  std::vector<std::string> CompilerInputFiles;
  bool AllowCaching = true;
  bool AllowDistribution = true;

  std::set<std::string> ObjectOutputs;
  std::set<std::string> ObjectDepends;

  // Apple only.
  std::string arch;
  FastbuildObjectListNode()
    : FastbuildTargetBase(FastbuildTargetType::OBJECTLIST)
  {
  }
};

struct FastbuildUnityNode : public FastbuildTargetBase
{
  std::string UnityOutputPath;
  std::vector<std::string> UnityInputFiles;
  std::string UnityOutputPattern;
  std::vector<std::string> UnityInputIsolatedFiles;
  FastbuildUnityNode()
    : FastbuildTargetBase(FastbuildTargetType::UNITY)
  {
  }
};

struct IDEProjectConfig
{
  std::string Config;
  std::string Target;
  // VS only.
  std::string Platform;

  std::string XCodeBaseSDK;
  std::string XCodeDebugWorkingDir;
  std::string XCodeIphoneOSDeploymentTarget;
};

struct IDEProjectCommon
{
  std::string Alias;
  std::string ProjectOutput;
  std::string ProjectBasePath;

  std::vector<IDEProjectConfig> ProjectConfigs;
};

struct XCodeProject : public IDEProjectCommon
{
};

struct VCXProject : public IDEProjectCommon
{
  std::string folder;
};

struct FastbuildLinkerNode
{
  enum
  {
    EXECUTABLE,
    SHARED_LIBRARY,
    STATIC_LIBRARY,
    NONE
  } Type = NONE;

  std::string Name;
  std::string Compiler;
  std::string CompilerOptions;
  std::string Linker;
  std::string LinkerType;
  std::string LinkerOutput;
  std::string LinkerOptions;
  std::vector<std::string> LibrarianAdditionalInputs;
  // We only use Libraries2 for tracking dependencies.
  std::vector<std::string> Libraries2;
  std::set<std::string> PreBuildDependencies;
  bool LinkerLinkObjects = false;
  std::string LinkerStampExe;
  std::string LinkerStampExeArgs;
  // Apple only.
  std::string Arch;
};

struct FastbuildCopyNode
{
  std::string Name;
  std::string Source;
  std::string Dest;
  std::string PreBuildDependencies;
  bool CopyDir = false;
};

struct FastbuildExecNodes
{
  std::vector<FastbuildExecNode> Nodes;
  FastbuildAliasNode Alias;
};

struct FastbuildTarget : public FastbuildTargetBase
{
  std::map<std::string, std::string> Variables;
  std::vector<FastbuildObjectListNode> ObjectListNodes;
  std::vector<FastbuildUnityNode> UnityNodes;
  // Potentially multiple libs for different archs (apple only)
  std::vector<FastbuildLinkerNode> CudaDeviceLinkNode;
  std::vector<FastbuildLinkerNode> LinkerNode;
  std::string RealOutput;
  FastbuildAliasNode PreBuildExecNodes, ExecNodes;
  std::vector<FastbuildAliasNode> AliasNodes;
  // This alias must be written before all other nodes, since they might need
  // to refer to it.
  FastbuildAliasNode DependenciesAlias;
  std::vector<FastbuildCopyNode> CopyNodes;
  FastbuildExecNodes PreLinkExecNodes;
  FastbuildExecNodes PostBuildExecNodes;
  bool IsGlobal = false;
  bool ExcludeFromAll = false;
  bool AllowDistribution = true;
  FastbuildTarget()
    : FastbuildTargetBase(FastbuildTargetType::LINK)
  {
  }

  void GenerateAliases();
};

class cmGlobalFastbuildGenerator : public cmGlobalCommonGenerator
{
public:
  cmGlobalFastbuildGenerator(cmake* cm);

  void ReadCompilerOptions(FastbuildCompiler& compiler, cmMakefile* mf);
  void ProcessEnvironment();

  static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory();
  void Generate() override;

  bool FindMakeProgram(cmMakefile* mf) override;

  void EnableLanguage(std::vector<std::string> const& lang, cmMakefile* mf,
                      bool optional) override;

  bool IsFastbuild() const override { return true; }

  std::vector<GeneratedMakeCommand> GenerateBuildCommand(
    std::string const& makeProgram, std::string const& projectName,
    std::string const& projectDir, std::vector<std::string> const& targetNames,
    std::string const& config, int jobs, bool verbose,
    cmBuildOptions buildOptions = cmBuildOptions(),
    std::vector<std::string> const& makeOptions = std::vector<std::string>(),
    BuildTryCompile isInTryCompile = BuildTryCompile::No) override;

  std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
    cmMakefile* makefile) override;
  std::string GetName() const override
  {
    return cmGlobalFastbuildGenerator::GetActualName();
  }

  bool IsMultiConfig() const override { return false; }

  bool SupportsCustomObjectNames() const override { return false; }

  void ComputeTargetObjectDirectory(cmGeneratorTarget*) const override;
  void AppendDirectoryForConfig(std::string const& prefix,
                                std::string const& config,
                                std::string const& suffix,
                                std::string& dir) override;

  static std::string GetActualName() { return "FASTBuild"; }
  static std::string RequiredFastbuildVersion() { return "1.14"; }

  // Setup target names
  char const* GetAllTargetName() const override
  {
    return FASTBUILD_ALL_TARGET_NAME;
  }
  char const* GetInstallTargetName() const override { return "install"; }
  char const* GetCleanTargetName() const override
  {
    return FASTBUILD_CLEAN_TARGET_NAME;
  }
  char const* GetInstallLocalTargetName() const override
  {
    return "install/local";
  }
  char const* GetInstallStripTargetName() const override
  {
    return "install/strip";
  }
  char const* GetInstallParallelTargetName() const
  {
    return "install/parallel";
  }
  char const* GetTestTargetName() const override { return "RUN_TESTS"; }
  char const* GetPackageTargetName() const override { return "package"; }
  char const* GetPackageSourceTargetName() const override
  {
    return "package_source";
  }
  char const* GetRebuildCacheTargetName() const override
  {
    return "rebuild_cache";
  }
  char const* GetCMakeCFGIntDir() const override { return "."; }

  /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
  static cmDocumentationEntry GetDocumentation();

  static bool SupportsToolset() { return false; }

  static bool SupportsPlatform() { return false; }

  bool IsIPOSupported() const override { return true; }

  void OpenBuildFileStream();
  void CloseBuildFileStream();

  std::vector<std::string> const& GetConfigNames() const;

  bool Open(std::string const& bindir, std::string const& projectName,
            bool dryRun) override;

  std::string ConvertToFastbuildPath(std::string const& path) const;
  std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer(
    cmOutputConverter* outputConverter,
    cmStateDirectory const& /* stateDir */) const override;

  bool SupportsCustomCommandDepfile() const override { return true; }
  cm::optional<cmDepfileFormat> DepfileFormat() const override
  {
    return cm::nullopt;
  }

  static std::string Quote(std::string const& str,
                           std::string const& quotation = "'");
  static std::string QuoteIfHasSpaces(std::string str);

  template <class T>
  static std::vector<std::string> Wrap(T const& in,
                                       std::string const& prefix = "'",
                                       std::string const& suffix = "'",
                                       bool escape_dollar = true);

  void WriteDivider();
  void WriteComment(std::string const& comment, int indent = 0);

  /// Write @a count times INDENT level to output stream @a os.
  void Indent(int count);

  void WriteVariable(std::string const& key, std::string const& value,
                     std::string const& op, int indent = 0);
  void WriteVariable(std::string const& key, std::string const& value,
                     int indent = 0);
  void WriteCommand(std::string const& command,
                    std::string const& value = std::string(), int indent = 0);
  void WriteArray(std::string const& key,
                  std::vector<std::string> const& values, int indent = 0);
  void WriteStruct(
    std::string const& name,
    std::vector<std::pair<std::string, std::string>> const& variables,
    int indent = 0);
  void WriteArray(std::string const& key,
                  std::vector<std::string> const& values,
                  std::string const& op, int indent = 0);

  template <typename T>
  std::vector<std::string> ConvertToFastbuildPath(T const& container) const
  {
    std::vector<std::string> ret;
    ret.reserve(container.size());
    for (auto const& path : container) {
      ret.push_back(ConvertToFastbuildPath(path));
    }
    return ret;
  }

  // Wrapper to sort array of conforming structs (which have .Name
  // and .PreBuildDependencies fields).
  template <class T>
  static void TopologicalSort(std::vector<T>& nodes)
  {
    static_assert(std::is_base_of<FastbuildTargetBase, T>::value,
                  "T must be derived from FastbuildTargetBase");
    std::vector<FastbuildTargetPtrT> tmp;
    tmp.reserve(nodes.size());
    for (auto& node : nodes) {
      tmp.emplace_back(cm::make_unique<T>(std::move(node)));
    }
    nodes.clear();
    TopologicalSort(tmp);
    for (auto& node : tmp) {
      nodes.emplace_back(std::move(static_cast<T&>(*node)));
    }
  }
  // Stable topological sort.
  static void TopologicalSort(std::vector<FastbuildTargetPtrT>& nodes);

  void WriteDisclaimer();
  void WriteEnvironment();
  void WriteSettings();
  void WriteCompilers();
  void WriteTargets();

  void WriteTarget(FastbuildTarget const& target);
  void WriteExec(FastbuildExecNode const& Exec, int indent = 1);
  void WriteUnity(FastbuildUnityNode const& Unity);
  void WriteObjectList(FastbuildObjectListNode const& ObjectList,
                       bool allowDistribution);
  void WriteLinker(FastbuildLinkerNode const&, bool);
  void WriteAlias(FastbuildAliasNode const& Alias, int indent = 1);
  void WriteCopy(FastbuildCopyNode const& Copy);

  void WriteIDEProjects();
  std::string GetIDEBuildArgs() const;
  void WriteVSBuildCommands();
  void WriteXCodeBuildCommands();
  void WriteIDEProjectCommon(IDEProjectCommon const& project);
  void WriteIDEProjectConfig(std::vector<IDEProjectConfig> const& configs,
                             std::string const& keyName = "ProjectConfigs");

  void WriteSolution();
  void WriteXCodeTopLevelProject();
  void WriteTargetRebuildBFF();
  void WriteCleanScript();
  void WriteTargetClean();

  void AddTargetAll();
  void AddGlobCheckExec();

  void AddCompiler(std::string const& lang, cmMakefile* mf);
  void AddLauncher(std::string const& prefix, std::string const& launcher,
                   std::string const& lang, std::string const& args);
  void AddIDEProject(FastbuildTarget const& target, std::string const& config);

  template <class T>
  void AddTarget(T target)
  {
    // Sometimes equivalent CCs are added to different targets. We try to
    // de-dup it by assigning all execs a name which is a hash computed based
    // on various properties (like input, output, deps.). Apparently, there are
    // still some CCs intersection between different targets.
    auto val = AllGeneratedCommands.emplace(target.Name);
    if (val.second) {
      FastbuildTargets.emplace_back(cm::make_unique<T>(std::move(target)));
    }
    // Get the intersection of CC's deps. Just mimicking what
    // cmLocalNinjaGenerator::WriteCustomCommandBuildStatement does. (I don't
    // think it's right in general case, each CC should be added only to 1
    // target, not to multiple )
    else {
      auto it =
        std::find_if(FastbuildTargets.begin(), FastbuildTargets.end(),
                     [&target](FastbuildTargetPtrT const& existingTarget) {
                       return existingTarget->Name == target.Name;
                     });
      assert(it != FastbuildTargets.end());

      std::set<FastbuildTargetDep> intersection;
      std::set_intersection(
        target.PreBuildDependencies.begin(), target.PreBuildDependencies.end(),
        (*it)->PreBuildDependencies.begin(), (*it)->PreBuildDependencies.end(),
        std::inserter(intersection, intersection.end()));
      (*it)->PreBuildDependencies = std::move(intersection);
    }
  }

  static std::string GetExternalShellExecutable();
  std::string GetTargetName(cmGeneratorTarget const* GeneratorTarget) const;
  cm::optional<FastbuildTarget> GetTargetByOutputName(
    std::string const& output) const;
  void AskCMakeToMakeRebuildBFFUpToDate(std::string const& workingDir) const;
  void ExecuteFastbuildTarget(
    std::string const& dir, std::string const& target, std::string& output,
    std::vector<std::string> const& fbuildOptions = {}) const;

  bool IsExcluded(cmGeneratorTarget* target);

  void LogMessage(std::string const& m) const;

  void AddFileToClean(std::string const& file);

  /// The set of compilers added to the generated build system.
  std::map<std::string, FastbuildCompiler> Compilers;

  std::vector<FastbuildTargetPtrT> FastbuildTargets;

  /// The file containing the build statement.
  std::unique_ptr<cmGeneratedFileStream> BuildFileStream;

  std::string FastbuildCommand;
  std::string FastbuildVersion;

  std::map<std::string, std::unique_ptr<cmFastbuildTargetGenerator>> Targets;

  std::unordered_set<std::string> AllFoldersToClean;
  // Sometime we need to keep some files that are generated only during
  // configuration (like .objs files used to create module definition from
  // objects).
  std::unordered_set<std::string> AllFilesToKeep;
  bool UsingRelativePaths = false;

private:
  std::unordered_set<std::string> AllFilesToClean;
  // https://cmake.org/cmake/help/latest/module/ExternalProject.html#command:externalproject_add_steptargets
  std::unordered_set<std::string /*exec name*/> AllGeneratedCommands;

  std::unordered_map<std::string /*base target name (without -config)*/,
                     std::pair<VCXProject, XCodeProject>>
    IDEProjects;
  // Env that we're going to embed to the generated file.
  std::vector<std::string> LocalEnvironment;
};