Coverage Report

Created: 2026-02-09 06:05

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
44
  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 ShouldWarnExperimental(cm::string_view featureName,
719
                              cm::string_view featureUuid);
720
721
  cm::optional<cmXcFrameworkPlist> GetXcFrameworkPListContent(
722
    std::string const& path) const;
723
  void SetXcFrameworkPListContent(std::string const& path,
724
                                  cmXcFrameworkPlist const& content);
725
726
protected:
727
  /** Get all targets produced under the given root, plus the transitive
728
      closure of targets on which they depend, possibly from other dirs.  */
729
  TargetDependSet GetTargetsForProject(
730
    cmLocalGenerator const* root,
731
    std::vector<cmLocalGenerator*> const& generators) const;
732
733
  bool IsRootOnlyTarget(cmGeneratorTarget* target) const;
734
  void AddTargetDepends(cmGeneratorTarget const* target,
735
                        TargetDependSet& projectTargets) const;
736
  void SetLanguageEnabledFlag(std::string const& l, cmMakefile* mf);
737
  void SetLanguageEnabledMaps(std::string const& l, cmMakefile* mf);
738
  void FillExtensionToLanguageMap(std::string const& l, cmMakefile* mf);
739
  virtual bool CheckLanguages(std::vector<std::string> const& languages,
740
                              cmMakefile* mf) const;
741
  virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
742
                                   cmValue envVar) const;
743
744
  virtual bool ComputeTargetDepends();
745
746
#if !defined(CMAKE_BOOTSTRAP)
747
  void WriteJsonContent(std::string const& fname,
748
                        Json::Value const& value) const;
749
  void WriteInstallJson() const;
750
#endif
751
752
  virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
753
754
  bool ApplyCXXStdTargets();
755
  bool DiscoverSyntheticTargets();
756
757
  bool AddHeaderSetVerification();
758
759
  void CreateFileGenerateOutputs();
760
  bool AddAutomaticSources();
761
762
  std::string SelectMakeProgram(std::string const& makeProgram,
763
                                std::string const& makeDefault = "") const;
764
765
  // Fill the ProjectMap, this must be called after LocalGenerators
766
  // has been populated.
767
  void FillProjectMap();
768
  void CheckTargetProperties();
769
  bool IsExcluded(cmStateSnapshot const& root,
770
                  cmStateSnapshot const& snp) const;
771
  bool IsExcluded(cmLocalGenerator const* root,
772
                  cmLocalGenerator const* gen) const;
773
  bool IsExcluded(cmLocalGenerator const* root,
774
                  cmGeneratorTarget const* target) const;
775
0
  virtual void InitializeProgressMarks() {}
776
777
  struct GlobalTargetInfo
778
  {
779
    std::string Name;
780
    std::string Message;
781
    cmCustomCommandLines CommandLines;
782
    std::vector<std::string> Depends;
783
    std::string WorkingDir;
784
    bool UsesTerminal = false;
785
    cmTarget::PerConfig PerConfig = cmTarget::PerConfig::Yes;
786
    bool StdPipesUTF8 = false;
787
    std::string Role;
788
  };
789
790
  void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets);
791
792
  void AddGlobalTarget_Package(std::vector<GlobalTargetInfo>& targets);
793
  void AddGlobalTarget_PackageSource(std::vector<GlobalTargetInfo>& targets);
794
  void AddGlobalTarget_Test(std::vector<GlobalTargetInfo>& targets);
795
  void AddGlobalTarget_EditCache(std::vector<GlobalTargetInfo>& targets) const;
796
  void AddGlobalTarget_RebuildCache(
797
    std::vector<GlobalTargetInfo>& targets) const;
798
  void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets);
799
  void CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);
800
801
  void ReserveGlobalTargetCodegen();
802
803
  std::string FindMakeProgramFile;
804
  std::string ConfiguredFilesPath;
805
  cmake* CMakeInstance;
806
  std::vector<std::unique_ptr<cmMakefile>> Makefiles;
807
  LocalGeneratorVector LocalGenerators;
808
809
#ifndef CMAKE_BOOTSTRAP
810
  std::unique_ptr<cmQtAutoGenGlobalInitializer> QtAutoGen;
811
#endif
812
813
  cmMakefile* CurrentConfigureMakefile;
814
  // map from project name to vector of local generators in that project
815
  std::map<std::string, std::vector<cmLocalGenerator*>> ProjectMap;
816
817
  // Set of named installation components requested by the project.
818
  std::set<std::string> InstallComponents;
819
  // Sets of named target exports
820
  cmExportSetMap ExportSets;
821
  std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets;
822
  std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets;
823
824
  std::map<std::string, std::string> AliasTargets;
825
826
  cmTarget* FindTargetImpl(std::string const& name,
827
                           cmStateEnums::TargetDomainSet domains) const;
828
829
  cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const;
830
831
  std::string GetPredefinedTargetsFolder() const;
832
833
private:
834
  using TargetMap = std::unordered_map<std::string, cmTarget*>;
835
  using GeneratorTargetMap =
836
    std::unordered_map<std::string, cmGeneratorTarget*>;
837
  using MakefileMap = std::unordered_map<std::string, cmMakefile*>;
838
  using LocalGeneratorMap = std::unordered_map<std::string, cmLocalGenerator*>;
839
  using TargetDirectoryRegistrationMap =
840
    std::map<cmGeneratorTarget const*, TargetDirectoryRegistration>;
841
  using TargetDirectoryMap =
842
    std::unordered_map<std::string, std::set<cmGeneratorTarget const*>>;
843
  // Map efficiently from target name to cmTarget instance.
844
  // Do not use this structure for looping over all targets.
845
  // It contains both normal and globally visible imported targets.
846
  TargetMap TargetSearchIndex;
847
  GeneratorTargetMap GeneratorTargetSearchIndex;
848
849
  // Map from target to a directory registration.
850
  mutable TargetDirectoryRegistrationMap TargetDirectoryRegistrations;
851
  // Map from target directories to targets using it.
852
  mutable TargetDirectoryMap TargetDirectories;
853
854
  // Map efficiently from source directory path to cmMakefile instance.
855
  // Do not use this structure for looping over all directories.
856
  // It may not contain all of them (see note in IndexMakefile method).
857
  MakefileMap MakefileSearchIndex;
858
859
  // Map efficiently from source directory path to cmLocalGenerator instance.
860
  // Do not use this structure for looping over all directories.
861
  // Its order is not deterministic.
862
  LocalGeneratorMap LocalGeneratorSearchIndex;
863
864
  void ComputeTargetOrder();
865
  void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index);
866
  std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex;
867
868
  cmMakefile* TryCompileOuterMakefile;
869
  // If you add a new map here, make sure it is copied
870
  // in EnableLanguagesFromGenerator
871
  std::map<std::string, bool> IgnoreExtensions;
872
  std::set<std::string> LanguagesReady; // Ready for try_compile
873
  std::set<std::string> LanguagesInProgress;
874
  std::map<std::string, std::string> OutputExtensions;
875
  std::map<std::string, std::string> LanguageToOutputExtension;
876
#if __cplusplus >= 201402L || defined(_MSVC_LANG) && _MSVC_LANG >= 201402L
877
  std::map<std::string, std::string, std::less<void>> ExtensionToLanguage;
878
#else
879
  std::map<std::string, std::string> ExtensionToLanguage;
880
#endif
881
  std::map<std::string, int> LanguageToLinkerPreference;
882
883
#if !defined(CMAKE_BOOTSTRAP)
884
  std::unique_ptr<Json::StreamWriter> JsonWriter;
885
#endif
886
887
#ifdef __APPLE__
888
  std::map<std::string, StripCommandStyle> StripCommandStyleMap;
889
#endif
890
891
  // Deferral id generation.
892
  size_t NextDeferId = 0;
893
894
  // Record hashes for rules and outputs.
895
  struct RuleHash
896
  {
897
    char Data[32];
898
  };
899
  std::map<std::string, RuleHash> RuleHashes;
900
  void CheckRuleHashes();
901
  void CheckRuleHashes(std::string const& pfile, std::string const& home);
902
  void WriteRuleHashes(std::string const& pfile);
903
904
  void WriteSummary();
905
  void WriteSummary(cmGeneratorTarget* target);
906
  void FinalizeTargetConfiguration();
907
908
  virtual void ForceLinkerLanguages();
909
910
  void CheckTargetLinkLibraries() const;
911
  bool CheckTargetsForMissingSources() const;
912
  bool CheckTargetsForType() const;
913
  void MarkTargetsForPchReuse() const;
914
915
  void CreateLocalGenerators();
916
917
  void CheckCompilerIdCompatibility(cmMakefile* mf,
918
                                    std::string const& lang) const;
919
920
  void ComputeBuildFileGenerators();
921
922
  std::unique_ptr<cmExternalMakefileProjectGenerator> ExtraGenerator;
923
924
  // track files replaced during a Generate
925
  std::vector<std::string> FilesReplacedDuringGenerate;
926
927
  // Store computed inter-target dependencies.
928
  using TargetDependMap = std::map<cmGeneratorTarget const*, TargetDependSet>;
929
  TargetDependMap TargetDependencies;
930
931
  friend class cmake;
932
  void CreateGeneratorTargets(
933
    TargetTypes targetTypes, cmMakefile* mf, cmLocalGenerator* lg,
934
    std::map<cmTarget*, cmGeneratorTarget*> const& importedMap);
935
  void CreateGeneratorTargets(TargetTypes targetTypes);
936
937
  void ClearGeneratorMembers();
938
939
  bool CheckReservedTargetName(std::string const& targetName,
940
                               std::string const& reason) const;
941
  bool CheckReservedTargetNamePrefix(std::string const& targetPrefix,
942
                                     std::string const& reason) const;
943
944
  void IndexMakefile(cmMakefile* mf);
945
  void IndexLocalGenerator(cmLocalGenerator* lg);
946
947
0
  virtual char const* GetBuildIgnoreErrorsFlag() const { return nullptr; }
948
949
  bool UnsupportedVariableIsDefined(std::string const& name,
950
                                    bool supported) const;
951
952
  // Cache directory content and target files to be built.
953
  struct DirectoryContent
954
  {
955
    long LastDiskTime = -1;
956
    std::set<std::string> All;
957
    std::set<std::string> Generated;
958
  };
959
  std::map<std::string, DirectoryContent> DirectoryContentMap;
960
961
  // Cache parsed PList files
962
  std::map<std::string, cmXcFrameworkPlist> XcFrameworkPListContentMap;
963
964
  // Set of binary directories on disk.
965
  std::set<std::string> BinaryDirectories;
966
967
  // track targets to issue CMP0068 warning for.
968
  std::set<std::string> CMP0068WarnTargets;
969
970
  std::unordered_set<std::string> WarnedExperimental;
971
972
  mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*>>
973
    FilenameTargetDepends;
974
975
  std::map<std::string, std::string> RealPaths;
976
977
  std::unordered_set<std::string> GeneratedFiles;
978
979
  std::vector<std::unique_ptr<cmInstallRuntimeDependencySet>>
980
    RuntimeDependencySets;
981
  std::map<std::string, cmInstallRuntimeDependencySet*>
982
    RuntimeDependencySetsByName;
983
984
  std::vector<std::string> InstallScripts;
985
  std::vector<std::string> TestFiles;
986
987
#if !defined(CMAKE_BOOTSTRAP)
988
  // Pool of file locks
989
  cmFileLockPool FileLockPool;
990
#endif
991
992
  using PerLanguageModuleDatabases =
993
    std::map<std::string, std::vector<std::string>>;
994
  using PerConfigModuleDatabases =
995
    std::map<std::string, PerLanguageModuleDatabases>;
996
  PerConfigModuleDatabases PerConfigModuleDbs;
997
  PerLanguageModuleDatabases PerLanguageModuleDbs;
998
999
  enum class IntermediateDirStrategy
1000
  {
1001
    Full,
1002
    Short,
1003
  };
1004
  IntermediateDirStrategy IntDirStrategy = IntermediateDirStrategy::Full;
1005
  IntermediateDirStrategy QtAutogenIntDirStrategy =
1006
    IntermediateDirStrategy::Full;
1007
1008
protected:
1009
  float FirstTimeProgress;
1010
  bool NeedSymbolicMark;
1011
  bool UseLinkScript;
1012
  bool ForceUnixPaths;
1013
  bool ToolSupportsColor;
1014
  bool InstallTargetEnabled;
1015
  bool AllowGlobalTargetCodegen;
1016
};