Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmGlobalGenerator.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 <cstddef>
8
#include <functional>
9
#include <iosfwd>
10
#include <map>
11
#include <memory>
12
#include <set>
13
#include <string>
14
#include <unordered_map>
15
#include <unordered_set>
16
#include <utility>
17
#include <vector>
18
19
#include <cm/optional>
20
#include <cm/string_view>
21
#include <cmext/algorithm>
22
#include <cmext/string_view>
23
24
#include "cmBuildOptions.h"
25
#include "cmCustomCommandLines.h"
26
#include "cmDuration.h"
27
#include "cmExportSet.h"
28
#include "cmLocalGenerator.h"
29
#include "cmStateSnapshot.h"
30
#include "cmStateTypes.h"
31
#include "cmStringAlgorithms.h"
32
#include "cmSystemTools.h"
33
#include "cmTarget.h"
34
#include "cmTargetDepend.h"
35
#include "cmValue.h"
36
#include "cmXcFramework.h"
37
38
#if !defined(CMAKE_BOOTSTRAP)
39
#  include <cm3p/json/value.h>
40
41
#  include "cmFileLockPool.h"
42
#endif
43
44
0
#define CMAKE_DIRECTORY_ID_SEP "::@"
45
46
enum class cmDepfileFormat;
47
enum class codecvt_Encoding;
48
49
class cmBuildArgs;
50
class cmDirectoryId;
51
class cmExportBuildFileGenerator;
52
class cmExternalMakefileProjectGenerator;
53
class cmGeneratorTarget;
54
class cmInstallRuntimeDependencySet;
55
class cmLinkLineComputer;
56
class cmMakefile;
57
class cmOutputConverter;
58
class cmQtAutoGenGlobalInitializer;
59
class cmSourceFile;
60
class cmState;
61
class cmStateDirectory;
62
class cmake;
63
64
namespace detail {
65
inline void AppendStrs(std::vector<std::string>&)
66
0
{
67
0
}
68
template <typename T, typename... Ts>
69
inline void AppendStrs(std::vector<std::string>& command, T&& s, Ts&&... ts)
70
0
{
71
0
  command.emplace_back(std::forward<T>(s));
72
0
  AppendStrs(command, std::forward<Ts>(ts)...);
73
0
}
Unexecuted instantiation: void detail::AppendStrs<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: void detail::AppendStrs<char const (&) [3]>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [3])
Unexecuted instantiation: void detail::AppendStrs<char const (&) [3], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [3], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: void detail::AppendStrs<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: void detail::AppendStrs<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: void detail::AppendStrs<char const (&) [8], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [8], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: void detail::AppendStrs<char const (&) [21]>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [21])
Unexecuted instantiation: void detail::AppendStrs<char const (&) [15]>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [15])
Unexecuted instantiation: void detail::AppendStrs<char const (&) [9]>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [9])
Unexecuted instantiation: void detail::AppendStrs<char const (&) [10]>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [10])
Unexecuted instantiation: void detail::AppendStrs<char const (&) [5], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [5], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: void detail::AppendStrs<char const (&) [7]>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [7])
Unexecuted instantiation: void detail::AppendStrs<char const (&) [56]>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [56])
Unexecuted instantiation: void detail::AppendStrs<char const (&) [4]>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, char const (&) [4])
74
75
struct GeneratedMakeCommand
76
{
77
  // Add each argument as a separate element to the vector
78
  template <typename... T>
79
  void Add(T&&... args)
80
0
  {
81
    // iterate the args and append each one
82
0
    AppendStrs(this->PrimaryCommand, std::forward<T>(args)...);
83
0
  }
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [3]>(char const (&) [3])
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [3], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(char const (&) [3], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [8], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(char const (&) [8], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [21]>(char const (&) [21])
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [15]>(char const (&) [15])
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [9]>(char const (&) [9])
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [10]>(char const (&) [10])
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [5], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(char const (&) [5], std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [7]>(char const (&) [7])
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [56]>(char const (&) [56])
Unexecuted instantiation: void detail::GeneratedMakeCommand::Add<char const (&) [4]>(char const (&) [4])
84
85
  // Add each value in the iterators as a separate element to the vector
86
  void Add(std::vector<std::string>::const_iterator start,
87
           std::vector<std::string>::const_iterator end)
88
0
  {
89
0
    cm::append(this->PrimaryCommand, start, end);
90
0
  }
91
92
0
  std::string Printable() const { return cmJoin(this->PrimaryCommand, " "); }
93
  std::string QuotedPrintable() const;
94
95
  std::vector<std::string> PrimaryCommand;
96
  bool RequiresOutputForward = false;
97
};
98
}
99
namespace Json {
100
class StreamWriter;
101
}
102
103
/** \class cmGlobalGenerator
104
 * \brief Responsible for overseeing the generation process for the entire tree
105
 *
106
 * Subclasses of this class generate makefiles for various
107
 * platforms.
108
 */
109
class cmGlobalGenerator
110
{
111
public:
112
  using LocalGeneratorVector = std::vector<std::unique_ptr<cmLocalGenerator>>;
113
  enum class BuildTryCompile
114
  {
115
    No,
116
    Yes,
117
  };
118
119
  //! Free any memory allocated with the GlobalGenerator
120
  cmGlobalGenerator(cmake* cm);
121
  virtual ~cmGlobalGenerator();
122
123
  virtual std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
124
    cmMakefile* mf);
125
126
  //! Get the name for this generator
127
0
  virtual std::string GetName() const { return "Generic"; }
128
129
  /** Check whether the given name matches the current generator.  */
130
  virtual bool MatchesGeneratorName(std::string const& name) const
131
0
  {
132
0
    return this->GetName() == name;
133
0
  }
134
135
  /** Get encoding used by generator for makefile files */
136
  virtual codecvt_Encoding GetMakefileEncoding() const;
137
138
#if !defined(CMAKE_BOOTSTRAP)
139
  /** Get a JSON object describing the generator.  */
140
  virtual Json::Value GetJson() const;
141
#endif
142
143
  /** Tell the generator about the target system.  */
144
0
  virtual bool SetSystemName(std::string const&, cmMakefile*) { return true; }
145
146
  /** Set the generator-specific instance.  Returns true if supported.  */
147
  virtual bool SetGeneratorInstance(std::string const& i, cmMakefile* mf);
148
149
  /** Set the generator-specific platform name.  Returns true if platform
150
      is supported and false otherwise.  */
151
  virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
152
153
  /** Set the generator-specific toolset name.  Returns true if toolset
154
      is supported and false otherwise.  */
155
  virtual bool SetGeneratorToolset(std::string const& ts, bool build,
156
                                   cmMakefile* mf);
157
158
  /** Read any other cache entries needed for cmake --build. */
159
  virtual bool ReadCacheEntriesForBuild(cmState const& /*state*/)
160
0
  {
161
0
    return true;
162
0
  }
163
164
  /**
165
   * Create LocalGenerators and process the CMakeLists files. This does not
166
   * actually produce any makefiles, DSPs, etc.
167
   */
168
  virtual void Configure();
169
170
0
  virtual bool InspectConfigTypeVariables() { return true; }
171
172
  enum class CxxModuleSupportQuery
173
  {
174
    // Support is expected at the call site.
175
    Expected,
176
    // The call site is querying for support and handles problems by itself.
177
    Inspect,
178
  };
179
  virtual bool CheckCxxModuleSupport(CxxModuleSupportQuery /*query*/)
180
0
  {
181
0
    return false;
182
0
  }
183
184
0
  virtual bool SupportsCustomObjectNames() const { return true; }
185
186
0
  virtual bool SupportsBuildDatabase() const { return false; }
187
  bool AddBuildDatabaseTargets();
188
  void AddBuildDatabaseFile(std::string const& lang, std::string const& config,
189
                            std::string const& path);
190
191
0
  virtual bool IsGNUMakeJobServerAware() const { return false; }
192
193
  bool Compute();
194
0
  virtual void AddExtraIDETargets() {}
195
196
  enum TargetTypes
197
  {
198
    AllTargets,
199
    ImportedOnly
200
  };
201
202
  void CreateImportedGenerationObjects(
203
    cmMakefile* mf, std::vector<std::string> const& targets,
204
    std::vector<cmGeneratorTarget const*>& exports);
205
  void CreateGenerationObjects(TargetTypes targetTypes = AllTargets);
206
207
  /**
208
   * Generate the all required files for building this project/tree. This
209
   * basically creates a series of LocalGenerators for each directory and
210
   * requests that they Generate.
211
   */
212
  virtual void Generate();
213
214
  virtual std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer(
215
    cmOutputConverter* outputConverter,
216
    cmStateDirectory const& stateDir) const;
217
218
  std::unique_ptr<cmLinkLineComputer> CreateMSVC60LinkLineComputer(
219
    cmOutputConverter* outputConverter,
220
    cmStateDirectory const& stateDir) const;
221
222
  /**
223
   * Set/Get and Clear the enabled languages.
224
   */
225
  void SetLanguageEnabled(std::string const&, cmMakefile* mf);
226
  bool GetLanguageEnabled(std::string const&) const;
227
  void ClearEnabledLanguages();
228
  void GetEnabledLanguages(std::vector<std::string>& lang) const;
229
  /**
230
   * Try to determine system information such as shared library
231
   * extension, pthreads, byte order etc.
232
   */
233
  virtual void EnableLanguage(std::vector<std::string> const& languages,
234
                              cmMakefile*, bool optional);
235
236
  /**
237
   * Resolve the CMAKE_<lang>_COMPILER setting for the given language.
238
   * Intended to be called from EnableLanguage.
239
   */
240
  void ResolveLanguageCompiler(std::string const& lang, cmMakefile* mf,
241
                               bool optional) const;
242
243
  /**
244
   * Try to determine system information, get it from another generator
245
   */
246
  void EnableLanguagesFromGenerator(cmGlobalGenerator* gen, cmMakefile* mf);
247
248
  /**
249
   * Try running cmake and building a file. This is used for dynamically
250
   * loaded commands, not as part of the usual build process.
251
   */
252
  int TryCompile(int jobs, std::string const& bindir,
253
                 std::string const& projectName, std::string const& targetName,
254
                 bool fast, std::string& output, cmMakefile* mf);
255
256
  /**
257
   * Build a file given the following information. This is a more direct call
258
   * that is used by both CTest and TryCompile. If target name is NULL or
259
   * empty then all is assumed. clean indicates if a "make clean" should be
260
   * done first.
261
   */
262
  int Build(
263
    cmBuildArgs const& buildArgs, std::vector<std::string> const& targetNames,
264
    std::ostream& ostr, std::string const& makeProgram,
265
    std::string const& config, cmBuildOptions buildOptions, cmDuration timeout,
266
    cmSystemTools::OutputOption outputMode,
267
    std::vector<std::string> const& nativeOptions = std::vector<std::string>(),
268
    BuildTryCompile isInTryCompile = BuildTryCompile::No);
269
270
  /**
271
   * Open a generated IDE project given the following information.
272
   */
273
  virtual bool Open(std::string const& bindir, std::string const& projectName,
274
                    bool dryRun);
275
276
  struct GeneratedMakeCommand final : public detail::GeneratedMakeCommand
277
  {
278
  };
279
280
  virtual std::vector<GeneratedMakeCommand> GenerateBuildCommand(
281
    std::string const& makeProgram, std::string const& projectName,
282
    std::string const& projectDir, std::vector<std::string> const& targetNames,
283
    std::string const& config, int jobs, bool verbose,
284
    cmBuildOptions buildOptions = cmBuildOptions(),
285
    std::vector<std::string> const& makeOptions = std::vector<std::string>(),
286
    BuildTryCompile isInTryCompile = BuildTryCompile::No);
287
288
  virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const;
289
290
  /**
291
   * Generate a "cmake --build" call for a given target, config and parallel
292
   * level.
293
   */
294
  std::string GenerateCMakeBuildCommand(std::string const& target,
295
                                        std::string const& config,
296
                                        std::string const& parallel,
297
                                        std::string const& native,
298
                                        bool ignoreErrors);
299
300
  //! Get the CMake instance
301
32
  cmake* GetCMakeInstance() const { return this->CMakeInstance; }
302
303
  void SetConfiguredFilesPath(cmGlobalGenerator* gen);
304
  std::vector<std::unique_ptr<cmMakefile>> const& GetMakefiles() const
305
0
  {
306
0
    return this->Makefiles;
307
0
  }
308
  LocalGeneratorVector const& GetLocalGenerators() const
309
0
  {
310
0
    return this->LocalGenerators;
311
0
  }
312
313
  std::vector<cmGeneratorTarget*> GetLocalGeneratorTargetsInOrder(
314
    cmLocalGenerator* lg) const;
315
316
  cmMakefile* GetCurrentMakefile() const
317
0
  {
318
0
    return this->CurrentConfigureMakefile;
319
0
  }
320
321
  void SetCurrentMakefile(cmMakefile* mf)
322
0
  {
323
0
    this->CurrentConfigureMakefile = mf;
324
0
  }
325
326
  void AddMakefile(std::unique_ptr<cmMakefile> mf);
327
328
  //! Set an generator for an "external makefile based project"
329
  void SetExternalMakefileProjectGenerator(
330
    std::unique_ptr<cmExternalMakefileProjectGenerator> extraGenerator);
331
332
  std::string GetExtraGeneratorName() const;
333
334
  void AddInstallComponent(std::string const& component);
335
336
  /** Mark the (absolute path to a) file as generated.  */
337
  void MarkAsGeneratedFile(std::string const& filepath);
338
  /** Determine if the absolute filepath belongs to a generated file.  */
339
  bool IsGeneratedFile(std::string const& filepath);
340
341
  std::set<std::string> const* GetInstallComponents() const
342
0
  {
343
0
    return &this->InstallComponents;
344
0
  }
345
346
0
  cmExportSetMap& GetExportSets() { return this->ExportSets; }
347
348
  cmValue GetGlobalSetting(std::string const& name) const;
349
  bool GlobalSettingIsOn(std::string const& name) const;
350
  std::string GetSafeGlobalSetting(std::string const& name) const;
351
352
  /** Add a file to the manifest of generated targets for a configuration.  */
353
  void AddToManifest(std::string const& f);
354
355
  void EnableInstallTarget();
356
357
  cmDuration TryCompileTimeout;
358
359
0
  bool GetForceUnixPaths() const { return this->ForceUnixPaths; }
360
0
  bool GetToolSupportsColor() const { return this->ToolSupportsColor; }
361
362
  //! return the language for the given extension
363
  cm::string_view GetLanguageFromExtension(cm::string_view ext) const;
364
  //! is an extension to be ignored
365
  bool IgnoreFile(cm::string_view ext) const;
366
  //! What is the preference for linkers and this language (None or Preferred)
367
  int GetLinkerPreference(std::string const& lang) const;
368
  //! What is the object file extension for a given source file?
369
  std::string GetLanguageOutputExtension(cmSourceFile const&) const;
370
  //! What is the object file extension for a given language?
371
  std::string GetLanguageOutputExtension(std::string const& lang) const;
372
373
  //! What is the configurations directory variable called?
374
0
  virtual char const* GetCMakeCFGIntDir() const { return "."; }
375
376
  //! expand CFGIntDir for a configuration
377
  virtual std::string ExpandCFGIntDir(std::string const& str,
378
                                      std::string const& config) const;
379
380
  /** Get whether the generator should use a script for link commands.  */
381
0
  bool GetUseLinkScript() const { return this->UseLinkScript; }
382
383
  /** Get whether the generator should produce special marks on rules
384
      producing symbolic (non-file) outputs.  */
385
0
  bool GetNeedSymbolicMark() const { return this->NeedSymbolicMark; }
386
387
  /*
388
   * Determine what program to use for building the project.
389
   */
390
  virtual bool FindMakeProgram(cmMakefile*);
391
392
  //! Find a target by name by searching the local generators.
393
  cmTarget* FindTarget(std::string const& name,
394
                       cmStateEnums::TargetDomainSet domains = {
395
                         cmStateEnums::TargetDomain::NATIVE,
396
                         cmStateEnums::TargetDomain::ALIAS }) const;
397
398
  cmGeneratorTarget* FindGeneratorTarget(std::string const& name) const;
399
400
  void AddAlias(std::string const& name, std::string const& tgtName);
401
  bool IsAlias(std::string const& name) const;
402
403
  /** Determine if a name resolves to a framework on disk or a built target
404
      that is a framework. */
405
  bool NameResolvesToFramework(std::string const& libname) const;
406
  /** Split a framework path to the directory and name of the framework as well
407
   * as optional suffix.
408
   * Returns std::nullopt if the path does not match with framework format
409
   * when extendedFormat is true, required format is relaxed (i.e. extension
410
   * `.framework' is optional). Used when FRAMEWORK link feature is
411
   * specified */
412
  struct FrameworkDescriptor
413
  {
414
    FrameworkDescriptor(std::string directory, std::string name)
415
0
      : Directory(std::move(directory))
416
0
      , Name(std::move(name))
417
0
    {
418
0
    }
419
    FrameworkDescriptor(std::string directory, std::string version,
420
                        std::string name)
421
0
      : Directory(std::move(directory))
422
0
      , Version(std::move(version))
423
0
      , Name(std::move(name))
424
0
    {
425
0
    }
426
    FrameworkDescriptor(std::string directory, std::string version,
427
                        std::string name, std::string suffix)
428
0
      : Directory(std::move(directory))
429
0
      , Version(std::move(version))
430
0
      , Name(std::move(name))
431
0
      , Suffix(std::move(suffix))
432
0
    {
433
0
    }
434
    std::string GetLinkName() const
435
0
    {
436
0
      return this->Suffix.empty() ? this->Name
437
0
                                  : cmStrCat(this->Name, ',', this->Suffix);
438
0
    }
439
    std::string GetFullName() const
440
0
    {
441
0
      return cmStrCat(this->Name, ".framework/"_s, this->Name, this->Suffix);
442
0
    }
443
    std::string GetVersionedName() const
444
0
    {
445
0
      return this->Version.empty()
446
0
        ? this->GetFullName()
447
0
        : cmStrCat(this->Name, ".framework/Versions/"_s, this->Version, '/',
448
0
                   this->Name, this->Suffix);
449
0
    }
450
    std::string GetFrameworkPath() const
451
0
    {
452
0
      return this->Directory.empty()
453
0
        ? cmStrCat(this->Name, ".framework"_s)
454
0
        : cmStrCat(this->Directory, '/', this->Name, ".framework"_s);
455
0
    }
456
    std::string GetFullPath() const
457
0
    {
458
0
      return this->Directory.empty()
459
0
        ? this->GetFullName()
460
0
        : cmStrCat(this->Directory, '/', this->GetFullName());
461
0
    }
462
    std::string GetVersionedPath() const
463
0
    {
464
0
      return this->Directory.empty()
465
0
        ? this->GetVersionedName()
466
0
        : cmStrCat(this->Directory, '/', this->GetVersionedName());
467
0
    }
468
469
    std::string const Directory;
470
    std::string const Version;
471
    std::string const Name;
472
    std::string const Suffix;
473
  };
474
  enum class FrameworkFormat
475
  {
476
    Strict,
477
    Relaxed,
478
    Extended
479
  };
480
  cm::optional<FrameworkDescriptor> SplitFrameworkPath(
481
    std::string const& path,
482
    FrameworkFormat format = FrameworkFormat::Relaxed) const;
483
484
  cmMakefile* FindMakefile(std::string const& start_dir) const;
485
  cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const;
486
487
  /** Append the subdirectory for the given configuration.  If anything is
488
      appended the given prefix and suffix will be appended around it, which
489
      is useful for leading or trailing slashes.  */
490
  virtual void AppendDirectoryForConfig(std::string const& prefix,
491
                                        std::string const& config,
492
                                        std::string const& suffix,
493
                                        std::string& dir);
494
495
  /** Get the content of a directory.  Directory listings are cached
496
      and re-loaded from disk only when modified.  During the generation
497
      step the content will include the target files to be built even if
498
      they do not yet exist.  */
499
  std::set<std::string> const& GetDirectoryContent(std::string const& dir,
500
                                                   bool needDisk = true);
501
502
  void IndexTarget(cmTarget* t);
503
  void IndexGeneratorTarget(cmGeneratorTarget* gt);
504
505
  // Index the target using a name that is unique to that target
506
  // even if other targets have the same name.
507
  std::string IndexGeneratorTargetUniquely(cmGeneratorTarget const* gt);
508
509
  static bool IsReservedTarget(std::string const& name);
510
511
0
  virtual char const* GetAllTargetName() const { return "ALL_BUILD"; }
512
0
  virtual char const* GetInstallTargetName() const { return "INSTALL"; }
513
0
  virtual char const* GetInstallLocalTargetName() const { return nullptr; }
514
0
  virtual char const* GetInstallStripTargetName() const { return nullptr; }
515
0
  virtual char const* GetPreinstallTargetName() const { return nullptr; }
516
0
  virtual char const* GetTestTargetName() const { return "RUN_TESTS"; }
517
0
  virtual char const* GetPackageTargetName() const { return "PACKAGE"; }
518
0
  virtual char const* GetPackageSourceTargetName() const { return nullptr; }
519
0
  virtual char const* GetEditCacheTargetName() const { return nullptr; }
520
0
  virtual char const* GetRebuildCacheTargetName() const { return nullptr; }
521
0
  virtual char const* GetCleanTargetName() const { return nullptr; }
522
523
  // Lookup edit_cache target command preferred by this generator.
524
0
  virtual std::string GetEditCacheCommand() const { return ""; }
525
526
  // Default config to use for cmake --build
527
0
  virtual std::string GetDefaultBuildConfig() const { return "Debug"; }
528
529
  virtual cmValue GetDebuggerWorkingDirectory(cmGeneratorTarget* gt) const;
530
531
  // Class to track a set of dependencies.
532
  using TargetDependSet = cmTargetDependSet;
533
534
  // what targets does the specified target depend on directly
535
  // via a target_link_libraries or add_dependencies
536
  TargetDependSet const& GetTargetDirectDepends(
537
    cmGeneratorTarget const* target) const;
538
539
  // Return true if target 'l' occurs before 'r' in a global ordering
540
  // of targets that respects inter-target dependencies.
541
  bool TargetOrderIndexLess(cmGeneratorTarget const* l,
542
                            cmGeneratorTarget const* r) const;
543
544
  std::map<std::string, std::vector<cmLocalGenerator*>> const& GetProjectMap()
545
    const
546
0
  {
547
0
    return this->ProjectMap;
548
0
  }
549
550
  // track files replaced during a Generate
551
  void FileReplacedDuringGenerate(std::string const& filename);
552
  void GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames);
553
554
  void AddRuleHash(std::vector<std::string> const& outputs,
555
                   std::string const& content);
556
557
  /** Return whether the given binary directory is unused.  */
558
  bool BinaryDirectoryIsNew(std::string const& dir)
559
0
  {
560
0
    return this->BinaryDirectories.insert(dir).second;
561
0
  }
562
563
  /** Return true if the generated build tree may contain multiple builds.
564
      i.e. "Can I build Debug and Release in the same tree?" */
565
0
  virtual bool IsMultiConfig() const { return false; }
566
567
0
  virtual bool IsXcode() const { return false; }
568
569
0
  virtual bool IsVisualStudio() const { return false; }
570
571
0
  virtual bool IsVisualStudioAtLeast10() const { return false; }
572
573
0
  virtual bool IsNinja() const { return false; }
574
575
0
  virtual bool IsFastbuild() const { return false; }
576
577
  /** Return true if we know the exact location of object files for the given
578
     cmTarget. If false, store the reason in the given string. This is
579
     meaningful only after EnableLanguage has been called.  */
580
  virtual bool HasKnownObjectFileLocation(cmTarget const&, std::string*) const
581
0
  {
582
0
    return true;
583
0
  }
584
585
  virtual bool UseFolderProperty() const;
586
587
0
  virtual bool IsIPOSupported() const { return false; }
588
589
  /** Return whether the generator can import external visual studio project
590
      using INCLUDE_EXTERNAL_MSPROJECT */
591
0
  virtual bool IsIncludeExternalMSProjectSupported() const { return false; }
592
593
  /** Return whether the generator should use EFFECTIVE_PLATFORM_NAME. This is
594
      relevant for mixed macOS and iOS builds. */
595
0
  virtual bool UseEffectivePlatformName(cmMakefile*) const { return false; }
596
597
  /** Return whether the "Resources" folder prefix should be stripped from
598
      MacFolder. */
599
  virtual bool ShouldStripResourcePath(cmMakefile*) const;
600
601
0
  virtual bool SupportsCustomCommandDepfile() const { return false; }
602
  virtual cm::optional<cmDepfileFormat> DepfileFormat() const
603
0
  {
604
0
    return cm::nullopt;
605
0
  }
606
607
0
  virtual bool SupportsLinkerDependencyFile() const { return false; }
608
609
  /** Generate an <output>.rule file path for a given command output.  */
610
  virtual std::string GenerateRuleFile(std::string const& output) const;
611
612
0
  virtual bool SupportsDefaultBuildType() const { return false; }
613
0
  virtual bool SupportsCrossConfigs() const { return false; }
614
0
  virtual bool SupportsDefaultConfigs() const { return false; }
615
616
  virtual std::string ConvertToOutputPath(std::string path) const
617
0
  {
618
0
    return path;
619
0
  }
620
  virtual std::string GetConfigDirectory(std::string const& config) const
621
0
  {
622
0
    if (!this->IsMultiConfig() || config.empty()) {
623
0
      return {};
624
0
    }
625
0
    return cmStrCat('/', config);
626
0
  }
627
628
  static std::string EscapeJSON(std::string const& s);
629
630
  void ProcessEvaluationFiles();
631
632
  std::map<std::string, cmExportBuildFileGenerator*>& GetBuildExportSets()
633
0
  {
634
0
    return this->BuildExportSets;
635
0
  }
636
  void AddBuildExportSet(cmExportBuildFileGenerator* gen);
637
  void AddBuildExportExportSet(cmExportBuildFileGenerator* gen);
638
  bool IsExportedTargetsFile(std::string const& filename) const;
639
  cmExportBuildFileGenerator* GetExportedTargetsFile(
640
    std::string const& filename) const;
641
  void AddCMP0068WarnTarget(std::string const& target);
642
643
  virtual bool SupportsShortObjectNames() const;
644
  bool UseShortObjectNames(
645
    cmStateEnums::IntermediateDirKind kind =
646
      cmStateEnums::IntermediateDirKind::ObjectFiles) const;
647
  virtual std::string GetShortBinaryOutputDir() const;
648
  std::string ComputeTargetShortName(std::string const& bindir,
649
                                     std::string const& targetName) const;
650
  struct TargetDirectoryRegistration
651
  {
652
0
    TargetDirectoryRegistration() = default;
653
    TargetDirectoryRegistration(cmGeneratorTarget const* t, bool w)
654
0
      : CollidesWith(t)
655
0
      , Warned(w)
656
0
    {
657
0
    }
658
659
    cmGeneratorTarget const* CollidesWith = nullptr;
660
    bool Warned = false;
661
  };
662
  TargetDirectoryRegistration& RegisterTargetDirectory(
663
    cmGeneratorTarget const* tgt, std::string const& targetDir) const;
664
665
  virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
666
667
  bool GenerateCPackPropertiesFile();
668
669
  void SetFilenameTargetDepends(
670
    cmSourceFile* sf, std::set<cmGeneratorTarget const*> const& tgts);
671
  std::set<cmGeneratorTarget const*> const& GetFilenameTargetDepends(
672
    cmSourceFile* sf) const;
673
674
#if !defined(CMAKE_BOOTSTRAP)
675
0
  cmFileLockPool& GetFileLockPool() { return this->FileLockPool; }
676
#endif
677
678
  std::string MakeSilentFlag;
679
680
  size_t RecursionDepth = 0;
681
682
  virtual void GetQtAutoGenConfigs(std::vector<std::string>& configs) const
683
0
  {
684
0
    configs.emplace_back("$<CONFIG>");
685
0
  }
686
687
  std::string const& GetRealPath(std::string const& dir);
688
689
  std::string NewDeferId();
690
691
  cmInstallRuntimeDependencySet* CreateAnonymousRuntimeDependencySet();
692
693
  cmInstallRuntimeDependencySet* GetNamedRuntimeDependencySet(
694
    std::string const& name);
695
696
  enum class StripCommandStyle
697
  {
698
    Default,
699
    Apple,
700
  };
701
  StripCommandStyle GetStripCommandStyle(std::string const& strip);
702
703
  std::string GetEncodedLiteral(std::string const& lit);
704
0
  virtual std::string& EncodeLiteral(std::string& lit) { return lit; }
705
706
  bool CheckCMP0171() const;
707
708
  void AddInstallScript(std::string const& file);
709
  void AddTestFile(std::string const& file);
710
  void AddCMakeFilesToRebuild(std::vector<std::string>& files) const;
711
712
  virtual std::set<std::string> const& GetDefaultConfigs() const
713
0
  {
714
0
    static std::set<std::string> configs;
715
0
    return configs;
716
0
  }
717
718
  bool ShouldWarnCMP0210(std::string const& lang);
719
720
  bool ShouldWarnExperimental(cm::string_view featureName,
721
                              cm::string_view featureUuid);
722
723
  cm::optional<cmXcFrameworkPlist> GetXcFrameworkPListContent(
724
    std::string const& path) const;
725
  void SetXcFrameworkPListContent(std::string const& path,
726
                                  cmXcFrameworkPlist const& content);
727
728
protected:
729
  /** Get all targets produced under the given root, plus the transitive
730
      closure of targets on which they depend, possibly from other dirs.  */
731
  TargetDependSet GetTargetsForProject(
732
    cmLocalGenerator const* root,
733
    std::vector<cmLocalGenerator*> const& generators) const;
734
735
  bool IsRootOnlyTarget(cmGeneratorTarget* target) const;
736
  void AddTargetDepends(cmGeneratorTarget const* target,
737
                        TargetDependSet& projectTargets) const;
738
  void SetLanguageEnabledFlag(std::string const& l, cmMakefile* mf);
739
  void SetLanguageEnabledMaps(std::string const& l, cmMakefile* mf);
740
  void FillExtensionToLanguageMap(std::string const& l, cmMakefile* mf);
741
  virtual bool CheckLanguages(std::vector<std::string> const& languages,
742
                              cmMakefile* mf) const;
743
  virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
744
                                   cmValue envVar) const;
745
746
  virtual bool ComputeTargetDepends();
747
748
#if !defined(CMAKE_BOOTSTRAP)
749
  void WriteJsonContent(std::string const& fname,
750
                        Json::Value const& value) const;
751
  void WriteInstallJson() const;
752
#endif
753
754
  virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
755
756
  bool ApplyCXXStdTargets();
757
  bool DiscoverSyntheticTargets();
758
759
  bool AddHeaderSetVerification();
760
761
  void CreateFileGenerateOutputs();
762
  bool AddAutomaticSources();
763
764
  std::string SelectMakeProgram(std::string const& makeProgram,
765
                                std::string const& makeDefault = "") const;
766
767
  // Fill the ProjectMap, this must be called after LocalGenerators
768
  // has been populated.
769
  void FillProjectMap();
770
  void CheckTargetProperties();
771
  bool IsExcluded(cmStateSnapshot const& root,
772
                  cmStateSnapshot const& snp) const;
773
  bool IsExcluded(cmLocalGenerator const* root,
774
                  cmLocalGenerator const* gen) const;
775
  bool IsExcluded(cmLocalGenerator const* root,
776
                  cmGeneratorTarget const* target) const;
777
0
  virtual void InitializeProgressMarks() {}
778
779
  struct GlobalTargetInfo
780
  {
781
    std::string Name;
782
    std::string Message;
783
    cmCustomCommandLines CommandLines;
784
    std::vector<std::string> Depends;
785
    std::string WorkingDir;
786
    bool UsesTerminal = false;
787
    cmTarget::PerConfig PerConfig = cmTarget::PerConfig::Yes;
788
    bool StdPipesUTF8 = false;
789
    std::string Role;
790
  };
791
792
  void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets);
793
794
  void AddGlobalTarget_Package(std::vector<GlobalTargetInfo>& targets);
795
  void AddGlobalTarget_PackageSource(std::vector<GlobalTargetInfo>& targets);
796
  void AddGlobalTarget_Test(std::vector<GlobalTargetInfo>& targets);
797
  void AddGlobalTarget_EditCache(std::vector<GlobalTargetInfo>& targets) const;
798
  void AddGlobalTarget_RebuildCache(
799
    std::vector<GlobalTargetInfo>& targets) const;
800
  void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets);
801
  void CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);
802
803
  void ReserveGlobalTargetCodegen();
804
805
  std::string FindMakeProgramFile;
806
  std::string ConfiguredFilesPath;
807
  cmake* CMakeInstance;
808
  std::vector<std::unique_ptr<cmMakefile>> Makefiles;
809
  LocalGeneratorVector LocalGenerators;
810
811
#ifndef CMAKE_BOOTSTRAP
812
  std::unique_ptr<cmQtAutoGenGlobalInitializer> QtAutoGen;
813
#endif
814
815
  cmMakefile* CurrentConfigureMakefile;
816
  // map from project name to vector of local generators in that project
817
  std::map<std::string, std::vector<cmLocalGenerator*>> ProjectMap;
818
819
  // Set of named installation components requested by the project.
820
  std::set<std::string> InstallComponents;
821
  // Sets of named target exports
822
  cmExportSetMap ExportSets;
823
  std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets;
824
  std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets;
825
826
  std::map<std::string, std::string> AliasTargets;
827
828
  cmTarget* FindTargetImpl(std::string const& name,
829
                           cmStateEnums::TargetDomainSet domains) const;
830
831
  cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const;
832
833
  std::string GetPredefinedTargetsFolder() const;
834
835
private:
836
  using TargetMap = std::unordered_map<std::string, cmTarget*>;
837
  using GeneratorTargetMap =
838
    std::unordered_map<std::string, cmGeneratorTarget*>;
839
  using MakefileMap = std::unordered_map<std::string, cmMakefile*>;
840
  using LocalGeneratorMap = std::unordered_map<std::string, cmLocalGenerator*>;
841
  using TargetDirectoryRegistrationMap =
842
    std::map<cmGeneratorTarget const*, TargetDirectoryRegistration>;
843
  using TargetDirectoryMap =
844
    std::unordered_map<std::string, std::set<cmGeneratorTarget const*>>;
845
  // Map efficiently from target name to cmTarget instance.
846
  // Do not use this structure for looping over all targets.
847
  // It contains both normal and globally visible imported targets.
848
  TargetMap TargetSearchIndex;
849
  GeneratorTargetMap GeneratorTargetSearchIndex;
850
851
  // Map from target to a directory registration.
852
  mutable TargetDirectoryRegistrationMap TargetDirectoryRegistrations;
853
  // Map from target directories to targets using it.
854
  mutable TargetDirectoryMap TargetDirectories;
855
856
  // Map efficiently from source directory path to cmMakefile instance.
857
  // Do not use this structure for looping over all directories.
858
  // It may not contain all of them (see note in IndexMakefile method).
859
  MakefileMap MakefileSearchIndex;
860
861
  // Map efficiently from source directory path to cmLocalGenerator instance.
862
  // Do not use this structure for looping over all directories.
863
  // Its order is not deterministic.
864
  LocalGeneratorMap LocalGeneratorSearchIndex;
865
866
  void ComputeTargetOrder();
867
  void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index);
868
  std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex;
869
870
  cmMakefile* TryCompileOuterMakefile;
871
  // If you add a new map here, make sure it is copied
872
  // in EnableLanguagesFromGenerator
873
  std::map<std::string, bool> IgnoreExtensions;
874
  std::set<std::string> LanguagesReady; // Ready for try_compile
875
  std::set<std::string> LanguagesInProgress;
876
  std::map<std::string, std::string> OutputExtensions;
877
  std::map<std::string, std::string> LanguageToOutputExtension;
878
#if __cplusplus >= 201402L || defined(_MSVC_LANG) && _MSVC_LANG >= 201402L
879
  std::map<std::string, std::string, std::less<void>> ExtensionToLanguage;
880
#else
881
  std::map<std::string, std::string> ExtensionToLanguage;
882
#endif
883
  std::map<std::string, int> LanguageToLinkerPreference;
884
885
#if !defined(CMAKE_BOOTSTRAP)
886
  std::unique_ptr<Json::StreamWriter> JsonWriter;
887
#endif
888
889
#ifdef __APPLE__
890
  std::map<std::string, StripCommandStyle> StripCommandStyleMap;
891
#endif
892
893
  // Deferral id generation.
894
  size_t NextDeferId = 0;
895
896
  // Record hashes for rules and outputs.
897
  struct RuleHash
898
  {
899
    char Data[32];
900
  };
901
  std::map<std::string, RuleHash> RuleHashes;
902
  void CheckRuleHashes();
903
  void CheckRuleHashes(std::string const& pfile, std::string const& home);
904
  void WriteRuleHashes(std::string const& pfile);
905
906
  void WriteSummary();
907
  void WriteSummary(cmGeneratorTarget* target);
908
  void FinalizeTargetConfiguration();
909
910
  virtual void ForceLinkerLanguages();
911
912
  void CheckTargetLinkLibraries() const;
913
  bool CheckTargetsForMissingSources() const;
914
  bool CheckTargetsForType() const;
915
  void MarkTargetsForPchReuse() const;
916
917
  void CreateLocalGenerators();
918
919
  void CheckCompilerIdCompatibility(cmMakefile* mf,
920
                                    std::string const& lang) const;
921
922
  void ComputeBuildFileGenerators();
923
924
  std::unique_ptr<cmExternalMakefileProjectGenerator> ExtraGenerator;
925
926
  // track files replaced during a Generate
927
  std::vector<std::string> FilesReplacedDuringGenerate;
928
929
  // Store computed inter-target dependencies.
930
  using TargetDependMap = std::map<cmGeneratorTarget const*, TargetDependSet>;
931
  TargetDependMap TargetDependencies;
932
933
  friend class cmake;
934
  void CreateGeneratorTargets(
935
    TargetTypes targetTypes, cmMakefile* mf, cmLocalGenerator* lg,
936
    std::map<cmTarget*, cmGeneratorTarget*> const& importedMap);
937
  void CreateGeneratorTargets(TargetTypes targetTypes);
938
939
  void ClearGeneratorMembers();
940
941
  bool CheckReservedTargetName(std::string const& targetName,
942
                               std::string const& reason) const;
943
  bool CheckReservedTargetNamePrefix(std::string const& targetPrefix,
944
                                     std::string const& reason) const;
945
946
  void IndexMakefile(cmMakefile* mf);
947
  void IndexLocalGenerator(cmLocalGenerator* lg);
948
949
0
  virtual char const* GetBuildIgnoreErrorsFlag() const { return nullptr; }
950
951
  bool UnsupportedVariableIsDefined(std::string const& name,
952
                                    bool supported) const;
953
954
  // Cache directory content and target files to be built.
955
  struct DirectoryContent
956
  {
957
    long LastDiskTime = -1;
958
    std::set<std::string> All;
959
    std::set<std::string> Generated;
960
  };
961
  std::map<std::string, DirectoryContent> DirectoryContentMap;
962
963
  // Cache parsed PList files
964
  std::map<std::string, cmXcFrameworkPlist> XcFrameworkPListContentMap;
965
966
  // Set of binary directories on disk.
967
  std::set<std::string> BinaryDirectories;
968
969
  // track targets to issue CMP0068 warning for.
970
  std::set<std::string> CMP0068WarnTargets;
971
972
  std::unordered_set<std::string> WarnedCMP0210Languages;
973
974
  std::unordered_set<std::string> WarnedExperimental;
975
976
  mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*>>
977
    FilenameTargetDepends;
978
979
  std::map<std::string, std::string> RealPaths;
980
981
  std::unordered_set<std::string> GeneratedFiles;
982
983
  std::vector<std::unique_ptr<cmInstallRuntimeDependencySet>>
984
    RuntimeDependencySets;
985
  std::map<std::string, cmInstallRuntimeDependencySet*>
986
    RuntimeDependencySetsByName;
987
988
  std::vector<std::string> InstallScripts;
989
  std::vector<std::string> TestFiles;
990
991
#if !defined(CMAKE_BOOTSTRAP)
992
  // Pool of file locks
993
  cmFileLockPool FileLockPool;
994
#endif
995
996
  using PerLanguageModuleDatabases =
997
    std::map<std::string, std::vector<std::string>>;
998
  using PerConfigModuleDatabases =
999
    std::map<std::string, PerLanguageModuleDatabases>;
1000
  PerConfigModuleDatabases PerConfigModuleDbs;
1001
  PerLanguageModuleDatabases PerLanguageModuleDbs;
1002
1003
  enum class IntermediateDirStrategy
1004
  {
1005
    Full,
1006
    Short,
1007
  };
1008
  IntermediateDirStrategy IntDirStrategy = IntermediateDirStrategy::Full;
1009
  IntermediateDirStrategy QtAutogenIntDirStrategy =
1010
    IntermediateDirStrategy::Full;
1011
1012
protected:
1013
  float FirstTimeProgress;
1014
  bool NeedSymbolicMark;
1015
  bool UseLinkScript;
1016
  bool ForceUnixPaths;
1017
  bool ToolSupportsColor;
1018
  bool InstallTargetEnabled;
1019
  bool AllowGlobalTargetCodegen;
1020
};