cmake.h 24.4 KB
Newer Older
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
3 4 5
#ifndef cmake_h
#define cmake_h

6
#include "cmConfigure.h" // IWYU pragma: keep
7

8
#include <functional>
9
#include <map>
10
#include <memory> // IWYU pragma: keep
11 12
#include <set>
#include <string>
13
#include <unordered_set>
14 15
#include <vector>

16 17
#include "cmInstalledFile.h"
#include "cmListFileCache.h"
18
#include "cmMessageType.h"
19
#include "cmState.h"
20 21 22
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"

23
#if defined(CMAKE_BUILD_WITH_CMAKE)
24
#  include "cm_jsoncpp_value.h"
25 26
#endif

27
class cmExternalMakefileProjectGeneratorFactory;
28
class cmFileAPI;
29
class cmFileTimeComparison;
Ken Martin's avatar
Ken Martin committed
30
class cmGlobalGenerator;
31
class cmGlobalGeneratorFactory;
Ken Martin's avatar
Ken Martin committed
32
class cmMakefile;
33
class cmMessenger;
34
class cmVariableWatch;
35
struct cmDocumentationEntry;
Ken Martin's avatar
Ken Martin committed
36

37 38 39
/** \brief Represents a cmake invocation.
 *
 * This class represents a cmake invocation. It is the top level class when
40
 * running cmake. Most cmake based GUIs should primarily create an instance
41 42 43 44 45
 * of this class and communicate with it.
 *
 * The basic process for a GUI is as follows:
 *
 * -# Create a cmake instance
46
 * -# Set the Home directories, generator, and cmake command. this
47 48 49 50 51 52 53 54 55 56
 *    can be done using the Set methods or by using SetArgs and passing in
 *    command line arguments.
 * -# Load the cache by calling LoadCache (duh)
 * -# if you are using command line arguments with -D or -C flags then
 *    call SetCacheArgs (or if for some other reason you want to modify the
 *    cache), do it now.
 * -# Finally call Configure
 * -# Let the user change values and go back to step 5
 * -# call Generate

57
 * If your GUI allows the user to change the home directories then
58 59 60
 * you must at a minimum redo steps 2 through 7.
 */

Ken Martin's avatar
Ken Martin committed
61
class cmake
Ken Martin's avatar
Ken Martin committed
62
{
63
public:
64 65 66 67 68 69 70
  enum Role
  {
    RoleInternal, // no commands
    RoleScript,   // script commands
    RoleProject   // all commands
  };

71 72 73
  enum DiagLevel
  {
    DIAG_IGNORE,
74 75
    DIAG_WARN,
    DIAG_ERROR
76
  };
77

78
  /** \brief Describes the working modes of cmake */
79 80
  enum WorkingMode
  {
81
    NORMAL_MODE, ///< Cmake runs to create project files
82 83 84 85 86 87
                 /** \brief Script mode (started by using -P).
                  *
                  * In script mode there is no generator and no cache. Also,
                  * languages are not enabled, so add_executable and things do
                  * nothing.
                  */
88
    SCRIPT_MODE,
89 90 91 92 93 94 95
    /** \brief A pkg-config like mode
     *
     * In this mode cmake just searches for a package and prints the results to
     * stdout. This is similar to SCRIPT_MODE, but commands like add_library()
     * work too, since they may be used e.g. in exported target files. Started
     * via --find-package.
     */
96 97
    FIND_PACKAGE_MODE
  };
98 99

  struct GeneratorInfo
100
  {
101
    std::string name;
102 103
    std::string baseName;
    std::string extraName;
104
    bool supportsToolset;
105
    bool supportsPlatform;
106
    std::vector<std::string> supportedPlatforms;
107
    std::string defaultPlatform;
108
    bool isAlias;
109
  };
110

111
  typedef std::map<std::string, cmInstalledFile> InstalledFilesMap;
112

113 114 115
  static const int NO_BUILD_PARALLEL_LEVEL = -1;
  static const int DEFAULT_BUILD_PARALLEL_LEVEL = 0;

116
  /// Default constructor
117
  cmake(Role role, cmState::Mode mode);
118
  /// Destructor
Ken Martin's avatar
Ken Martin committed
119
  ~cmake();
Ken Martin's avatar
Ken Martin committed
120

wahikihiki's avatar
wahikihiki committed
121 122 123
  cmake(cmake const&) = delete;
  cmake& operator=(cmake const&) = delete;

124
#if defined(CMAKE_BUILD_WITH_CMAKE)
125
  Json::Value ReportVersionJson() const;
126
  Json::Value ReportCapabilitiesJson(bool haveServerMode) const;
127
#endif
128
  std::string ReportCapabilities(bool haveServerMode) const;
129

Ken Martin's avatar
Ken Martin committed
130 131 132
  //@{
  /**
   * Set/Get the home directory (or output directory) in the project. The
133
   * home directory is the top directory of the project. It is the
134
   * path-to-source cmake was run with.
Ken Martin's avatar
Ken Martin committed
135
   */
136
  void SetHomeDirectory(const std::string& dir);
137
  std::string const& GetHomeDirectory() const;
138
  void SetHomeOutputDirectory(const std::string& dir);
139
  std::string const& GetHomeOutputDirectory() const;
Ken Martin's avatar
Ken Martin committed
140 141 142 143 144
  //@}

  /**
   * Handle a command line invocation of cmake.
   */
145 146 147 148 149
  int Run(const std::vector<std::string>& args)
  {
    return this->Run(args, false);
  }
  int Run(const std::vector<std::string>& args, bool noconfigure);
Ken Martin's avatar
Ken Martin committed
150 151

  /**
152
   * Run the global generator Generate step.
Ken Martin's avatar
Ken Martin committed
153
   */
Ken Martin's avatar
Ken Martin committed
154 155 156 157 158 159 160 161
  int Generate();

  /**
   * Configure the cmMakefiles. This routine will create a GlobalGenerator if
   * one has not already been set. It will then Call Configure on the
   * GlobalGenerator. This in turn will read in an process all the CMakeList
   * files for the tree. It will not produce any actual Makefiles, or
   * workspaces. Generate does that.  */
162
  int Configure();
163
  int ActualConfigure();
164

165
  ///! Break up a line like VAR:type="value" into var, type and value
166 167
  static bool ParseCacheEntry(const std::string& entry, std::string& var,
                              std::string& value,
168
                              cmStateEnums::CacheEntryType& type);
169

Andy Cedilnik's avatar
Andy Cedilnik committed
170
  int LoadCache();
171 172 173 174 175 176
  bool LoadCache(const std::string& path);
  bool LoadCache(const std::string& path, bool internal,
                 std::set<std::string>& excludes,
                 std::set<std::string>& includes);
  bool SaveCache(const std::string& path);
  bool DeleteCache(const std::string& path);
177
  void PreLoadCMakeFiles();
Ken Martin's avatar
Ken Martin committed
178 179

  ///! Create a GlobalGenerator
180
  cmGlobalGenerator* CreateGlobalGenerator(const std::string& name);
Ken Martin's avatar
Ken Martin committed
181 182

  ///! Return the global generator assigned to this instance of cmake
183
  cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; }
184
  ///! Return the global generator assigned to this instance of cmake, const
185
  const cmGlobalGenerator* GetGlobalGenerator() const
186 187 188
  {
    return this->GlobalGenerator;
  }
Ken Martin's avatar
Ken Martin committed
189

190
  ///! Return the full path to where the CMakeCache.txt file should be.
191
  static std::string FindCacheFile(const std::string& binaryDir);
192

Ken Martin's avatar
Ken Martin committed
193
  ///! Return the global generator assigned to this instance of cmake
194
  void SetGlobalGenerator(cmGlobalGenerator*);
Ken Martin's avatar
Ken Martin committed
195 196

  ///! Get the names of the current registered generators
197 198
  void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators,
                               bool includeNamesWithPlatform = true) const;
Ken Martin's avatar
Ken Martin committed
199

200 201 202 203 204 205
  ///! Set the name of the selected generator-specific instance.
  void SetGeneratorInstance(std::string const& instance)
  {
    this->GeneratorInstance = instance;
  }

206 207
  ///! Set the name of the selected generator-specific platform.
  void SetGeneratorPlatform(std::string const& ts)
208 209 210
  {
    this->GeneratorPlatform = ts;
  }
211

212 213
  ///! Set the name of the selected generator-specific toolset.
  void SetGeneratorToolset(std::string const& ts)
214 215 216
  {
    this->GeneratorToolset = ts;
  }
217

218
  const std::vector<std::string>& GetSourceExtensions() const
219 220 221
  {
    return this->SourceFileExtensions;
  }
222 223 224 225 226 227 228

  bool IsSourceExtension(const std::string& ext) const
  {
    return this->SourceFileExtensionsSet.find(ext) !=
      this->SourceFileExtensionsSet.end();
  }

229
  const std::vector<std::string>& GetHeaderExtensions() const
230 231 232
  {
    return this->HeaderFileExtensions;
  }
233

234 235 236 237 238 239 240 241 242
  bool IsHeaderExtension(const std::string& ext) const
  {
    return this->HeaderFileExtensionsSet.find(ext) !=
      this->HeaderFileExtensionsSet.end();
  }

  // Strips the extension (if present and known) from a filename
  std::string StripExtension(const std::string& file) const;

Ken Martin's avatar
Ken Martin committed
243 244 245
  /**
   * Given a variable name, return its value (as a string).
   */
246
  const char* GetCacheDefinition(const std::string&) const;
247
  ///! Add an entry into the cache
248
  void AddCacheEntry(const std::string& key, const char* value,
249
                     const char* helpString, int type);
250

251 252 253 254 255 256 257 258 259 260
  bool DoWriteGlobVerifyTarget() const;
  std::string const& GetGlobVerifyScript() const;
  std::string const& GetGlobVerifyStamp() const;
  void AddGlobCacheEntry(bool recurse, bool listDirectories,
                         bool followSymlinks, const std::string& relative,
                         const std::string& expression,
                         const std::vector<std::string>& files,
                         const std::string& variable,
                         cmListFileBacktrace const& bt);

261
  /**
262 263 264 265
   * Get the system information and write it to the file specified
   */
  int GetSystemInformation(std::vector<std::string>&);

266
  ///! Parse command line arguments
267
  void SetArgs(const std::vector<std::string>& args);
Ken Martin's avatar
Ken Martin committed
268

269
  ///! Is this cmake running as a result of a TRY_COMPILE command
270 271
  bool GetIsInTryCompile() const;
  void SetIsInTryCompile(bool b);
272

273
  ///! Parse command line arguments that might set cache values
274
  bool SetCacheArgs(const std::vector<std::string>&);
Ken Martin's avatar
Ken Martin committed
275

276
  using ProgressCallbackType = std::function<void(const std::string&, float)>;
Ken Martin's avatar
Ken Martin committed
277
  /**
278
   *  Set the function used by GUIs to receive progress updates
279
   *  Function gets passed: message as a const char*, a progress
Ken Martin's avatar
Ken Martin committed
280
   *  amount ranging from 0 to 1.0 and client data. The progress
281
   *  number provided may be negative in cases where a message is
Ken Martin's avatar
Ken Martin committed
282 283
   *  to be displayed without any progress percentage.
   */
284
  void SetProgressCallback(ProgressCallbackType f);
Ken Martin's avatar
Ken Martin committed
285 286

  ///! this is called by generators to update the progress
287
  void UpdateProgress(const std::string& msg, float prog);
Ken Martin's avatar
Ken Martin committed
288

289
#if defined(CMAKE_BUILD_WITH_CMAKE)
290
  ///! Get the variable watch object
291
  cmVariableWatch* GetVariableWatch() { return this->VariableWatch; }
292
#endif
293

294
  std::vector<cmDocumentationEntry> GetGeneratorsDocumentation();
295

296
  ///! Set/Get a property of this target file
297 298 299 300
  void SetProperty(const std::string& prop, const char* value);
  void AppendProperty(const std::string& prop, const char* value,
                      bool asString = false);
  const char* GetProperty(const std::string& prop);
301
  bool GetPropertyAsBool(const std::string& prop);
302

303
  ///! Get or create an cmInstalledFile instance and return a pointer to it
304 305
  cmInstalledFile* GetOrCreateInstalledFile(cmMakefile* mf,
                                            const std::string& name);
306 307 308 309

  cmInstalledFile const* GetInstalledFile(const std::string& name) const;

  InstalledFilesMap const& GetInstalledFiles() const
310 311 312
  {
    return this->InstalledFiles;
  }
313

314 315
  ///! Do all the checks before running configure
  int DoPreConfigureChecks();
316

317 318
  void SetWorkingMode(WorkingMode mode) { this->CurrentWorkingMode = mode; }
  WorkingMode GetWorkingMode() { return this->CurrentWorkingMode; }
319

320
  ///! Debug the try compile stuff by not deleting the files
321 322
  bool GetDebugTryCompile() { return this->DebugTryCompile; }
  void DebugTryCompileOn() { this->DebugTryCompile = true; }
323

324 325 326
  /**
   * Generate CMAKE_ROOT and CMAKE_COMMAND cache entries
   */
327
  int AddCMakePaths();
328

329 330 331
  /**
   * Get the file comparison class
   */
332
  cmFileTimeComparison* GetFileComparison() { return this->FileComparison; }
333

334 335
  // Do we want debug output during the cmake run.
  bool GetDebugOutput() { return this->DebugOutput; }
336
  void SetDebugOutputOn(bool b) { this->DebugOutput = b; }
337

Bill Hoffman's avatar
Bill Hoffman committed
338
  // Do we want trace output during the cmake run.
339 340 341 342
  bool GetTrace() { return this->Trace; }
  void SetTrace(bool b) { this->Trace = b; }
  bool GetTraceExpand() { return this->TraceExpand; }
  void SetTraceExpand(bool b) { this->TraceExpand = b; }
343 344 345 346 347 348 349 350
  void AddTraceSource(std::string const& file)
  {
    this->TraceOnlyThisSources.push_back(file);
  }
  std::vector<std::string> const& GetTraceSources() const
  {
    return this->TraceOnlyThisSources;
  }
351 352 353 354 355 356 357 358
  bool GetWarnUninitialized() { return this->WarnUninitialized; }
  void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; }
  bool GetWarnUnused() { return this->WarnUnused; }
  void SetWarnUnused(bool b) { this->WarnUnused = b; }
  bool GetWarnUnusedCli() { return this->WarnUnusedCli; }
  void SetWarnUnusedCli(bool b) { this->WarnUnusedCli = b; }
  bool GetCheckSystemVars() { return this->CheckSystemVars; }
  void SetCheckSystemVars(bool b) { this->CheckSystemVars = b; }
359 360 361

  void MarkCliAsUsed(const std::string& variable);

362 363
  /** Get the list of configurations (in upper case) considered to be
      debugging configurations.*/
364
  std::vector<std::string> GetDebugConfigs();
365

366
  void SetCMakeEditCommand(std::string const& s)
367 368 369
  {
    this->CMakeEditCommand = s;
  }
370
  std::string const& GetCMakeEditCommand() const
371 372 373
  {
    return this->CMakeEditCommand;
  }
374

375 376
  cmMessenger* GetMessenger() const;

377 378 379 380 381
  /*
   * Get the state of the suppression of developer (author) warnings.
   * Returns false, by default, if developer warnings should be shown, true
   * otherwise.
   */
382
  bool GetSuppressDevWarnings() const;
383
  /*
384
   * Set the state of the suppression of developer (author) warnings.
385
   */
386 387
  void SetSuppressDevWarnings(bool v);

388 389 390 391 392
  /*
   * Get the state of the suppression of deprecated warnings.
   * Returns false, by default, if deprecated warnings should be shown, true
   * otherwise.
   */
393
  bool GetSuppressDeprecatedWarnings() const;
394 395 396 397
  /*
   * Set the state of the suppression of deprecated warnings.
   */
  void SetSuppressDeprecatedWarnings(bool v);
398

399 400 401 402 403
  /*
   * Get the state of treating developer (author) warnings as errors.
   * Returns false, by default, if warnings should not be treated as errors,
   * true otherwise.
   */
404
  bool GetDevWarningsAsErrors() const;
405 406 407 408 409 410 411 412 413 414
  /**
   * Set the state of treating developer (author) warnings as errors.
   */
  void SetDevWarningsAsErrors(bool v);

  /*
   * Get the state of treating deprecated warnings as errors.
   * Returns false, by default, if warnings should not be treated as errors,
   * true otherwise.
   */
415
  bool GetDeprecatedWarningsAsErrors() const;
416 417 418 419 420
  /**
   * Set the state of treating developer (author) warnings as errors.
   */
  void SetDeprecatedWarningsAsErrors(bool v);

421
  /** Display a message to the user.  */
422
  void IssueMessage(
423
    MessageType t, std::string const& text,
424
    cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
425

426
  ///! run the --build option
427
  int Build(int jobs, const std::string& dir, const std::string& target,
428
            const std::string& config,
429 430
            const std::vector<std::string>& nativeOptions, bool clean,
            bool verbose);
431

432 433 434
  ///! run the --open option
  bool Open(const std::string& dir, bool dryRun);

435 436
  void UnwatchUnusedCli(const std::string& var);
  void WatchUnusedCli(const std::string& var);
Stephen Kelly's avatar
Stephen Kelly committed
437 438

  cmState* GetState() const { return this->State; }
439
  void SetCurrentSnapshot(cmStateSnapshot const& snapshot)
440 441 442
  {
    this->CurrentSnapshot = snapshot;
  }
443
  cmStateSnapshot GetCurrentSnapshot() const { return this->CurrentSnapshot; }
Stephen Kelly's avatar
Stephen Kelly committed
444

445
protected:
446
  void RunCheckForUnusedVariables();
447
  int HandleDeleteCacheVariables(const std::string& var);
448

449 450
  typedef std::vector<cmGlobalGeneratorFactory*> RegisteredGeneratorsVector;
  RegisteredGeneratorsVector Generators;
451 452 453
  typedef std::vector<cmExternalMakefileProjectGeneratorFactory*>
    RegisteredExtraGeneratorsVector;
  RegisteredExtraGeneratorsVector ExtraGenerators;
454 455
  void AddScriptingCommands();
  void AddProjectCommands();
456
  void AddDefaultGenerators();
457
  void AddDefaultExtraGenerators();
Ken Martin's avatar
Ken Martin committed
458

459
  cmGlobalGenerator* GlobalGenerator;
460
  std::map<std::string, DiagLevel> DiagLevels;
461
  std::string GeneratorInstance;
462
  std::string GeneratorPlatform;
463
  std::string GeneratorToolset;
464

Ken Martin's avatar
Ken Martin committed
465
  ///! read in a cmake list file to initialize the cache
466 467
  void ReadListFile(const std::vector<std::string>& args,
                    const std::string& path);
468
  bool FindPackage(const std::vector<std::string>& args);
469 470 471 472

  ///! Check if CMAKE_CACHEFILE_DIR is set. If it is not, delete the log file.
  ///  If it is set, truncate it to 50kb
  void TruncateOutputLog(const char* fname);
473

474 475 476 477 478
  /**
   * Method called to check build system integrity at build time.
   * Returns 1 if CMake should rerun and 0 otherwise.
   */
  int CheckBuildSystem();
479

480
  void SetDirectoriesFromFile(const char* arg);
481

Ken Martin's avatar
Ken Martin committed
482
  //! Make sure all commands are what they say they are and there is no
483
  /// macros.
484
  void CleanupCommandsAndMacros();
485

486
  void GenerateGraphViz(const char* fileName) const;
487

488
private:
489
  ProgressCallbackType ProgressCallback;
490
  WorkingMode CurrentWorkingMode;
491
  bool DebugOutput;
Bill Hoffman's avatar
Bill Hoffman committed
492
  bool Trace;
493
  bool TraceExpand;
494
  bool WarnUninitialized;
495
  bool WarnUnused;
496
  bool WarnUnusedCli;
497
  bool CheckSystemVars;
498
  std::map<std::string, bool> UsedCliVariables;
499
  std::string CMakeEditCommand;
500 501 502
  std::string CXXEnvironment;
  std::string CCEnvironment;
  std::string CheckBuildSystemArgument;
503
  std::string CheckStampFile;
504
  std::string CheckStampList;
505
  std::string VSSolutionFile;
506
  std::vector<std::string> SourceFileExtensions;
507
  std::unordered_set<std::string> SourceFileExtensionsSet;
508
  std::vector<std::string> HeaderFileExtensions;
509
  std::unordered_set<std::string> HeaderFileExtensionsSet;
510 511 512 513
  bool ClearBuildSystem;
  bool DebugTryCompile;
  cmFileTimeComparison* FileComparison;
  std::string GraphVizFile;
514
  InstalledFilesMap InstalledFiles;
515

516 517
#if defined(CMAKE_BUILD_WITH_CMAKE)
  cmVariableWatch* VariableWatch;
518
  std::unique_ptr<cmFileAPI> FileAPI;
519 520
#endif

Stephen Kelly's avatar
Stephen Kelly committed
521
  cmState* State;
522
  cmStateSnapshot CurrentSnapshot;
523
  cmMessenger* Messenger;
Stephen Kelly's avatar
Stephen Kelly committed
524

525 526
  std::vector<std::string> TraceOnlyThisSources;

527
  void UpdateConversionPathTable();
528 529 530

  // Print a list of valid generators to stderr.
  void PrintGeneratorList();
531

532
  std::unique_ptr<cmGlobalGenerator> EvaluateDefaultGlobalGenerator();
533 534
  void CreateDefaultGlobalGenerator();

535 536
  void AppendGlobalGeneratorsDocumentation(std::vector<cmDocumentationEntry>&);
  void AppendExtraGeneratorsDocumentation(std::vector<cmDocumentationEntry>&);
Ken Martin's avatar
Ken Martin committed
537 538
};

539
#define CMAKE_STANDARD_OPTIONS_TABLE                                          \
540 541 542
  { "-S <path-to-source>", "Explicitly specify a source directory." },        \
    { "-B <path-to-build>", "Explicitly specify a build directory." },        \
    { "-C <initial-cache>", "Pre-load a script to populate the cache." },     \
543
    { "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, \
544 545 546 547 548 549 550 551 552 553 554 555
    { "-U <globbing_expr>", "Remove matching entries from CMake cache." },    \
    { "-G <generator-name>", "Specify a build system generator." },           \
    { "-T <toolset-name>",                                                    \
      "Specify toolset name if supported by generator." },                    \
    { "-A <platform-name>",                                                   \
      "Specify platform name if supported by generator." },                   \
    { "-Wdev", "Enable developer warnings." },                                \
    { "-Wno-dev", "Suppress developer warnings." },                           \
    { "-Werror=dev", "Make developer warnings errors." },                     \
    { "-Wno-error=dev", "Make developer warnings not errors." },              \
    { "-Wdeprecated", "Enable deprecation warnings." },                       \
    { "-Wno-deprecated", "Suppress deprecation warnings." },                  \
556 557 558
    { "-Werror=deprecated",                                                   \
      "Make deprecated macro and function warnings "                          \
      "errors." },                                                            \
559
  {                                                                           \
560 561 562
    "-Wno-error=deprecated",                                                  \
      "Make deprecated macro and function warnings "                          \
      "not errors."                                                           \
563 564 565
  }

#define FOR_EACH_C_FEATURE(F)                                                 \
566 567 568
  F(c_std_90)                                                                 \
  F(c_std_99)                                                                 \
  F(c_std_11)                                                                 \
569 570 571
  F(c_function_prototypes)                                                    \
  F(c_restrict)                                                               \
  F(c_static_assert)                                                          \
572 573
  F(c_variadic_macros)

574
#define FOR_EACH_CXX_FEATURE(F)                                               \
575 576 577
  F(cxx_std_98)                                                               \
  F(cxx_std_11)                                                               \
  F(cxx_std_14)                                                               \
578
  F(cxx_std_17)                                                               \
579
  F(cxx_std_20)                                                               \
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
  F(cxx_aggregate_default_initializers)                                       \
  F(cxx_alias_templates)                                                      \
  F(cxx_alignas)                                                              \
  F(cxx_alignof)                                                              \
  F(cxx_attributes)                                                           \
  F(cxx_attribute_deprecated)                                                 \
  F(cxx_auto_type)                                                            \
  F(cxx_binary_literals)                                                      \
  F(cxx_constexpr)                                                            \
  F(cxx_contextual_conversions)                                               \
  F(cxx_decltype)                                                             \
  F(cxx_decltype_auto)                                                        \
  F(cxx_decltype_incomplete_return_types)                                     \
  F(cxx_default_function_template_args)                                       \
  F(cxx_defaulted_functions)                                                  \
  F(cxx_defaulted_move_initializers)                                          \
  F(cxx_delegating_constructors)                                              \
  F(cxx_deleted_functions)                                                    \
  F(cxx_digit_separators)                                                     \
  F(cxx_enum_forward_declarations)                                            \
  F(cxx_explicit_conversions)                                                 \
  F(cxx_extended_friend_declarations)                                         \
  F(cxx_extern_templates)                                                     \
  F(cxx_final)                                                                \
  F(cxx_func_identifier)                                                      \
  F(cxx_generalized_initializers)                                             \
  F(cxx_generic_lambdas)                                                      \
  F(cxx_inheriting_constructors)                                              \
  F(cxx_inline_namespaces)                                                    \
  F(cxx_lambdas)                                                              \
  F(cxx_lambda_init_captures)                                                 \
  F(cxx_local_type_template_args)                                             \
  F(cxx_long_long_type)                                                       \
  F(cxx_noexcept)                                                             \
  F(cxx_nonstatic_member_init)                                                \
  F(cxx_nullptr)                                                              \
  F(cxx_override)                                                             \
  F(cxx_range_for)                                                            \
  F(cxx_raw_string_literals)                                                  \
  F(cxx_reference_qualified_functions)                                        \
  F(cxx_relaxed_constexpr)                                                    \
  F(cxx_return_type_deduction)                                                \
  F(cxx_right_angle_brackets)                                                 \
  F(cxx_rvalue_references)                                                    \
  F(cxx_sizeof_member)                                                        \
  F(cxx_static_assert)                                                        \
  F(cxx_strong_enums)                                                         \
  F(cxx_template_template_parameters)                                         \
  F(cxx_thread_local)                                                         \
  F(cxx_trailing_return_types)                                                \
  F(cxx_unicode_literals)                                                     \
  F(cxx_uniform_initialization)                                               \
  F(cxx_unrestricted_unions)                                                  \
  F(cxx_user_literals)                                                        \
  F(cxx_variable_templates)                                                   \
  F(cxx_variadic_macros)                                                      \
636 637
  F(cxx_variadic_templates)

638
#endif