cmMakefile.h 34.5 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
#ifndef cmMakefile_h
#define cmMakefile_h
5

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

8
#include "cmsys/RegularExpression.hxx"
9
#include <deque>
10
#include <map>
11
#include <memory>
12 13
#include <set>
#include <stack>
14
#include <stddef.h>
15
#include <string>
16
#include <unordered_map>
17 18
#include <vector>

19
#include "cmAlgorithms.h"
20
#include "cmListFileCache.h"
21
#include "cmMessageType.h"
22
#include "cmNewLineStyle.h"
23
#include "cmPolicies.h"
24
#include "cmSourceFileLocationKind.h"
25
#include "cmStateSnapshot.h"
26
#include "cmStateTypes.h"
27
#include "cmTarget.h"
28

29
#if defined(CMAKE_BUILD_WITH_CMAKE)
30
#  include "cmSourceGroup.h"
31 32
#endif

33
class cmCommand;
34 35 36 37 38 39 40 41
class cmCompiledGeneratorExpression;
class cmCustomCommandLines;
class cmExecutionStatus;
class cmExpandedCommandArgument;
class cmExportBuildFileGenerator;
class cmFunctionBlocker;
class cmGeneratorExpressionEvaluationFile;
class cmGlobalGenerator;
42
class cmInstallGenerator;
43
class cmMessenger;
44
class cmSourceFile;
45
class cmState;
46
class cmTest;
47
class cmTestGenerator;
48
class cmVariableWatch;
49
class cmake;
50

51 52 53 54 55 56 57 58
/** A type-safe wrapper for a string representing a directory id.  */
class cmDirectoryId
{
public:
  cmDirectoryId(std::string s);
  std::string String;
};

59 60 61 62
/** \class cmMakefile
 * \brief Process the input CMakeLists.txt file.
 *
 * Process and store into memory the input CMakeLists.txt file.
63
 * Each CMakeLists.txt file is parsed and the commands found there
64 65
 * are added into the build process.
 */
66 67 68
class cmMakefile
{
public:
69
  /* Mark a variable as used */
70
  void MarkVariableAsUsed(const std::string& var);
71
  /* return true if a variable has been initialized */
72
  bool VariableInitialized(const std::string&) const;
73

74 75 76
  /**
   * Construct an empty makefile.
   */
77
  cmMakefile(cmGlobalGenerator* globalGenerator,
78
             const cmStateSnapshot& snapshot);
79 80 81 82

  /**
   * Destructor.
   */
Ken Martin's avatar
Ken Martin committed
83
  ~cmMakefile();
84

wahikihiki's avatar
wahikihiki committed
85 86 87
  cmMakefile(cmMakefile const&) = delete;
  cmMakefile& operator=(cmMakefile const&) = delete;

88 89
  cmDirectoryId GetDirectoryId() const;

90
  bool ReadListFile(const std::string& filename);
91

92 93
  bool ReadDependentFile(const std::string& filename,
                         bool noPolicyScope = true);
94

95 96 97
  /**
   * Add a function blocker to this makefile
   */
98
  void AddFunctionBlocker(cmFunctionBlocker* fb);
99

100 101 102
  /// @return whether we are processing the top CMakeLists.txt file.
  bool IsRootMakefile() const;

103 104 105 106
  /**
   * Remove the function blocker whose scope ends with the given command.
   * This returns ownership of the function blocker object.
   */
107
  std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker(
108
    cmFunctionBlocker* fb, const cmListFileFunction& lff);
109

110 111 112 113
  /**
   * Try running cmake and building a file. This is used for dynalically
   * loaded commands, not as part of the usual build process.
   */
114
  int TryCompile(const std::string& srcdir, const std::string& bindir,
115
                 const std::string& projectName, const std::string& targetName,
116 117
                 bool fast, int jobs,
                 const std::vector<std::string>* cmakeArgs,
118
                 std::string& output);
119

120 121
  bool GetIsSourceFileTryCompile() const;

122 123 124
  /**
   * Help enforce global target name uniqueness.
   */
125
  bool EnforceUniqueName(std::string const& name, std::string& msg,
126
                         bool isCustom = false) const;
127

128
  /**
129
   * Perform FinalPass, Library dependency analysis etc before output of the
130
   * makefile.
131
   */
132
  void ConfigureFinalPass();
133

134 135 136 137
  /**
   * run the final pass on all commands.
   */
  void FinalPass();
138

139 140 141 142 143 144 145
  /** How to handle custom commands for object libraries */
  enum ObjectLibraryCommands
  {
    RejectObjectLibraryCommands,
    AcceptObjectLibraryCommands
  };

146
  /** Add a custom command to the build.  */
147 148 149 150 151
  void AddCustomCommandToTarget(
    const std::string& target, const std::vector<std::string>& byproducts,
    const std::vector<std::string>& depends,
    const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
    const char* comment, const char* workingDir, bool escapeOldStyle = true,
152
    bool uses_terminal = false, const std::string& depfile = "",
153
    const std::string& job_pool = "", bool command_expand_lists = false,
154
    ObjectLibraryCommands objLibraryCommands = RejectObjectLibraryCommands);
155 156
  cmSourceFile* AddCustomCommandToOutput(
    const std::vector<std::string>& outputs,
157
    const std::vector<std::string>& byproducts,
158
    const std::vector<std::string>& depends,
159
    const std::string& main_dependency,
160 161
    const cmCustomCommandLines& commandLines, const char* comment,
    const char* workingDir, bool replace = false, bool escapeOldStyle = true,
162
    bool uses_terminal = false, bool command_expand_lists = false,
163
    const std::string& depfile = "", const std::string& job_pool = "");
164
  cmSourceFile* AddCustomCommandToOutput(
165
    const std::string& output, const std::vector<std::string>& depends,
166
    const std::string& main_dependency,
167 168
    const cmCustomCommandLines& commandLines, const char* comment,
    const char* workingDir, bool replace = false, bool escapeOldStyle = true,
169
    bool uses_terminal = false, bool command_expand_lists = false,
170
    const std::string& depfile = "", const std::string& job_pool = "");
171
  void AddCustomCommandOldStyle(const std::string& target,
172 173
                                const std::vector<std::string>& outputs,
                                const std::vector<std::string>& depends,
174
                                const std::string& source,
175 176 177
                                const cmCustomCommandLines& commandLines,
                                const char* comment);

178 179 180
  /**
   * Add a define flag to the build.
   */
181 182
  void AddDefineFlag(std::string const& definition);
  void RemoveDefineFlag(std::string const& definition);
183
  void AddCompileDefinition(std::string const& definition);
184
  void AddCompileOption(std::string const& option);
185
  void AddLinkOption(std::string const& option);
186
  void AddLinkDirectory(std::string const& directory, bool before = false);
187

188
  /** Create a new imported target with the name and type given.  */
189
  cmTarget* AddImportedTarget(const std::string& name,
190
                              cmStateEnums::TargetType type, bool global);
191

192 193
  cmTarget* AddNewTarget(cmStateEnums::TargetType type,
                         const std::string& name);
194

195 196 197
  /**
   * Add an executable to the build.
   */
198
  cmTarget* AddExecutable(const std::string& exename,
199
                          const std::vector<std::string>& srcs,
Ken Martin's avatar
Ken Martin committed
200
                          bool excludeFromAll = false);
201

202 203 204 205 206 207 208
  /** Where the target originated from. */
  enum class TargetOrigin
  {
    Project,
    Generator
  };

209
  /**
Luz Paz's avatar
Luz Paz committed
210
   * Add a utility to the build.  A utility target is a command that
211
   * is run every time the target is built.
212
   */
Daniel Pfeifer's avatar
Daniel Pfeifer committed
213
  cmTarget* AddUtilityCommand(const std::string& utilityName,
214
                              TargetOrigin origin, bool excludeFromAll,
Daniel Pfeifer's avatar
Daniel Pfeifer committed
215 216 217 218 219 220
                              const std::vector<std::string>& depends,
                              const char* workingDirectory,
                              const char* command, const char* arg1 = nullptr,
                              const char* arg2 = nullptr,
                              const char* arg3 = nullptr,
                              const char* arg4 = nullptr);
221
  cmTarget* AddUtilityCommand(
222
    const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
223 224
    const char* workingDirectory, const std::vector<std::string>& depends,
    const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
Daniel Pfeifer's avatar
Daniel Pfeifer committed
225
    const char* comment = nullptr, bool uses_terminal = false,
226
    bool command_expand_lists = false, const std::string& job_pool = "");
227
  cmTarget* AddUtilityCommand(
228
    const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
229 230 231
    const char* workingDirectory, const std::vector<std::string>& byproducts,
    const std::vector<std::string>& depends,
    const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
Daniel Pfeifer's avatar
Daniel Pfeifer committed
232
    const char* comment = nullptr, bool uses_terminal = false,
233
    bool command_expand_lists = false, const std::string& job_pool = "");
234

235 236 237
  /**
   * Add a subdirectory to the build.
   */
238
  void AddSubDirectory(const std::string& fullSrcDir,
239
                       const std::string& fullBinDir, bool excludeFromAll,
240
                       bool immediate);
241

242 243
  void Configure();

244 245 246
  /**
   * Configure a subdirectory
   */
247
  void ConfigureSubDirectory(cmMakefile* mf);
248

249 250 251
  /**
   * Add an include directory to the build.
   */
252
  void AddIncludeDirectories(const std::vector<std::string>& incs,
253
                             bool before = false);
254 255 256 257 258

  /**
   * Add a variable definition to the build. This variable
   * can be used in CMake to refer to lists, directories, etc.
   */
259
  void AddDefinition(const std::string& name, const char* value);
260
  //! Add a definition to this makefile and the global cmake cache.
261
  void AddCacheDefinition(const std::string& name, const char* value,
262
                          const char* doc, cmStateEnums::CacheEntryType type,
263
                          bool force = false);
264

265
  /**
266
   * Add bool variable definition to the build.
267
   */
268
  void AddDefinition(const std::string& name, bool);
269

270 271 272 273
  /**
   * Remove a variable definition from the build.  This is not valid
   * for cache entries, and will only affect the current makefile.
   */
274
  void RemoveDefinition(const std::string& name);
275
  //! Remove a definition from the cache.
276
  void RemoveCacheDefinition(const std::string& name);
277

278 279 280
  /**
   * Specify the name of the project for this build.
   */
281
  void SetProjectName(std::string const& name);
282

283
  /** Get the configurations to be generated.  */
284
  std::string GetConfigurations(std::vector<std::string>& configs,
285 286
                                bool single = true) const;

287 288 289
  /**
   * Set the name of the library.
   */
290 291
  cmTarget* AddLibrary(const std::string& libname,
                       cmStateEnums::TargetType type,
292 293
                       const std::vector<std::string>& srcs,
                       bool excludeFromAll = false);
294
  void AddAlias(const std::string& libname, const std::string& tgt);
295

296 297
  //@{
  /**
298 299
   * Set, Push, Pop policy values for CMake.
   */
300
  bool SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
301
  bool SetPolicy(const char* id, cmPolicies::PolicyStatus status);
302 303
  cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id,
                                           bool parent_scope = false) const;
304 305
  bool SetPolicyVersion(std::string const& version_min,
                        std::string const& version_max);
306
  void RecordPolicies(cmPolicies::PolicyMap& pm);
307 308
  //@}

309 310 311 312
  /** Helper class to push and pop policies automatically.  */
  class PolicyPushPop
  {
  public:
313
    PolicyPushPop(cmMakefile* m);
314
    ~PolicyPushPop();
315

316 317 318
    PolicyPushPop(const PolicyPushPop&) = delete;
    PolicyPushPop& operator=(const PolicyPushPop&) = delete;

319 320 321 322 323
  private:
    cmMakefile* Makefile;
  };
  friend class PolicyPushPop;

324 325 326 327
  /**
   * Determine if the given context, name pair has already been reported
   * in context of CMP0054.
   */
328
  bool HasCMP0054AlreadyBeenReported(const cmListFileContext& context) const;
329

330 331
  bool IgnoreErrorsCMP0061() const;

332 333
  std::string const& GetHomeDirectory() const;
  std::string const& GetHomeOutputDirectory() const;
334 335 336 337

  /**
   * Set CMAKE_SCRIPT_MODE_FILE variable when running a -P script.
   */
338
  void SetScriptModeFile(std::string const& scriptfile);
339

340 341 342 343 344
  /**
   * Set CMAKE_ARGC, CMAKE_ARGV0 ... variables.
   */
  void SetArgcArgv(const std::vector<std::string>& args);

345 346
  std::string const& GetCurrentSourceDirectory() const;
  std::string const& GetCurrentBinaryDirectory() const;
347

Ken Martin's avatar
Ken Martin committed
348
  //@}
349

350
  /**
351 352 353 354
   * Set a regular expression that include files must match
   * in order to be considered as part of the depend information.
   */
  void SetIncludeRegularExpression(const char* regex)
355 356 357
  {
    this->SetProperty("INCLUDE_REGULAR_EXPRESSION", regex);
  }
358
  const char* GetIncludeRegularExpression() const
359 360 361
  {
    return this->GetProperty("INCLUDE_REGULAR_EXPRESSION");
  }
362

363
  /**
364 365 366
   * Set a regular expression that include files that are not found
   * must match in order to be considered a problem.
   */
367
  void SetComplainRegularExpression(const std::string& regex)
368 369 370
  {
    this->ComplainFileRegularExpression = regex;
  }
371
  const char* GetComplainRegularExpression() const
372 373 374
  {
    return this->ComplainFileRegularExpression.c_str();
  }
375

376 377 378 379 380 381 382
  // -- List of targets
  typedef std::unordered_map<std::string, cmTarget> cmTargetMap;
  /** Get the target map */
  cmTargetMap& GetTargets() { return this->Targets; }
  /** Get the target map - const version */
  cmTargetMap const& GetTargets() const { return this->Targets; }

383 384 385 386
  const std::vector<cmTarget*>& GetOwnedImportedTargets() const
  {
    return this->ImportedTargetsOwned;
  }
387
  std::vector<cmTarget*> GetImportedTargets() const;
388

389
  cmTarget* FindLocalNonAliasTarget(const std::string& name) const;
390

391 392
  /** Find a target to use in place of the given name.  The target
      returned may be imported or built within the project.  */
393
  cmTarget* FindTargetToUse(const std::string& name,
394 395
                            bool excludeAliases = false) const;
  bool IsAlias(const std::string& name) const;
396

397 398 399 400 401
  std::map<std::string, std::string> GetAliasTargets() const
  {
    return this->AliasTargets;
  }

402 403 404
  /**
   * Mark include directories as system directories.
   */
405
  void AddSystemIncludeDirectories(const std::set<std::string>& incs);
406

407 408 409
  /** Get a cmSourceFile pointer for a given source name, if the name is
   *  not found, then a null pointer is returned.
   */
410 411 412
  cmSourceFile* GetSource(
    const std::string& sourceName,
    cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous) const;
413

414 415 416 417
  /** Create the source file and return it. generated
   * indicates if it is a generated file, this is used in determining
   * how to create the source file instance e.g. name
   */
418 419 420
  cmSourceFile* CreateSource(
    const std::string& sourceName, bool generated = false,
    cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous);
421

422
  /** Get a cmSourceFile pointer for a given source name, if the name is
423
   *  not found, then create the source file and return it. generated
424 425 426
   * indicates if it is a generated file, this is used in determining
   * how to create the source file instance e.g. name
   */
427 428 429
  cmSourceFile* GetOrCreateSource(
    const std::string& sourceName, bool generated = false,
    cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous);
430

431 432
  void AddTargetObject(std::string const& tgtName, std::string const& objFile);

433 434
  /**
   * Given a variable name, return its value (as a string).
435 436
   * If the variable is not found in this makefile instance, the
   * cache is then queried.
437
   */
438
  const char* GetDefinition(const std::string&) const;
439 440
  const std::string* GetDef(const std::string&) const;
  const std::string& GetSafeDefinition(const std::string&) const;
441
  const std::string& GetRequiredDefinition(const std::string& name) const;
442
  bool IsDefinitionSet(const std::string&) const;
443 444 445 446 447
  /**
   * Get the list of all variables in the current space. If argument
   * cacheonly is specified and is greater than 0, then only cache
   * variables will be listed.
   */
448
  std::vector<std::string> GetDefinitions() const;
449

450 451 452 453 454
  /**
   * Test a boolean variable to see if it is true or false.
   * If the variable is not found in this makefile instance, the
   * cache is then queried.
   * Returns false if no entry defined.
455
   */
456 457
  bool IsOn(const std::string& name) const;
  bool IsSet(const std::string& name) const;
458

459 460 461
  /** Return whether the target platform is 32-bit. */
  bool PlatformIs32Bit() const;

462 463
  /** Return whether the target platform is 64-bit.  */
  bool PlatformIs64Bit() const;
Steven Newbury's avatar
Steven Newbury committed
464 465
  /** Return whether the target platform is x32.  */
  bool PlatformIsx32() const;
466

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
  /** Apple SDK Type */
  enum class AppleSDK
  {
    MacOS,
    IPhoneOS,
    IPhoneSimulator,
    AppleTVOS,
    AppleTVSimulator,
    WatchOS,
    WatchSimulator,
  };

  /** What SDK type points CMAKE_OSX_SYSROOT to? */
  AppleSDK GetAppleSDKType() const;

482
  /** Return whether the target platform is Apple iOS.  */
483
  bool PlatformIsAppleEmbedded() const;
484

485
  /** Retrieve soname flag for the specified language if supported */
486
  const char* GetSONameFlag(const std::string& language) const;
487

488
  /**
489
   * Get a list of preprocessor define flags.
490
   */
491
  std::string GetDefineFlags() const { return this->DefineFlags; }
492 493 494 495

  /**
   * Make sure CMake can write this file
   */
496
  bool CanIWriteThisFile(std::string const& fileName) const;
497

498
#if defined(CMAKE_BUILD_WITH_CMAKE)
499 500 501 502
  /**
   * Get the vector source groups.
   */
  const std::vector<cmSourceGroup>& GetSourceGroups() const
503 504 505
  {
    return this->SourceGroups;
  }
506

507 508 509
  /**
   * Get the source group
   */
510
  cmSourceGroup* GetSourceGroup(const std::vector<std::string>& name) const;
511 512 513 514 515 516 517 518 519 520 521 522 523

  /**
   * Add a root source group for consideration when adding a new source.
   */
  void AddSourceGroup(const std::string& name, const char* regex = nullptr);

  /**
   * Add a source group for consideration when adding a new source.
   * name is tokenized.
   */
  void AddSourceGroup(const std::vector<std::string>& name,
                      const char* regex = nullptr);

524 525 526 527 528 529 530 531 532 533 534 535
  /**
   * Get and existing or create a new source group.
   */
  cmSourceGroup* GetOrCreateSourceGroup(
    const std::vector<std::string>& folders);

  /**
   * Get and existing or create a new source group.
   * The name will be tokenized.
   */
  cmSourceGroup* GetOrCreateSourceGroup(const std::string& name);

536 537 538
  /**
   * find what source group this source is in
   */
539
  cmSourceGroup* FindSourceGroup(const std::string& source,
540
                                 std::vector<cmSourceGroup>& groups) const;
541
#endif
542

543 544 545 546
  /**
   * Get the vector of list files on which this makefile depends
   */
  const std::vector<std::string>& GetListFiles() const
547 548 549
  {
    return this->ListFiles;
  }
550
  //! When the file changes cmake will be re-run from the build system.
551
  void AddCMakeDependFile(const std::string& file)
552 553 554
  {
    this->ListFiles.push_back(file);
  }
555
  void AddCMakeDependFilesFromUser();
556

557
  std::string FormatListFileStack() const;
558

559 560 561
  /**
   * Get the current context backtrace.
   */
562
  cmListFileBacktrace GetBacktrace() const;
563
  cmListFileBacktrace GetBacktrace(cmCommandContext const& lfc) const;
564
  cmListFileContext GetExecutionContext() const;
565

566 567 568 569
  /**
   * Get the vector of  files created by this makefile
   */
  const std::vector<std::string>& GetOutputFiles() const
570 571 572
  {
    return this->OutputFiles;
  }
573
  void AddCMakeOutputFile(const std::string& file)
574 575 576
  {
    this->OutputFiles.push_back(file);
  }
577

578
  /**
579
   * Expand all defined variables in the string.
580
   * Defined variables come from the this->Definitions map.
581
   * They are expanded with ${var} where var is the
Nicolas Despres's avatar
Nicolas Despres committed
582
   * entry in the this->Definitions map.  Also \@var\@ is
583
   * expanded to match autoconf style expansions.
584
   */
585 586 587 588 589
  const std::string& ExpandVariablesInString(std::string& source) const;
  const std::string& ExpandVariablesInString(
    std::string& source, bool escapeQuotes, bool noEscapes,
    bool atOnly = false, const char* filename = nullptr, long line = -1,
    bool removeEmpty = false, bool replaceAt = false) const;
590

591 592
  /**
   * Remove any remaining variables in the string. Anything with ${var} or
Nicolas Despres's avatar
Nicolas Despres committed
593
   * \@var\@ will be removed.
594
   */
595
  void RemoveVariablesInString(std::string& source, bool atOnly = false) const;
596

597 598 599
  /**
   * Expand variables in the makefiles ivars such as link directories etc
   */
600
  void ExpandVariablesCMP0019();
601 602 603 604 605 606

  /**
   * Replace variables and #cmakedefine lines in the given string.
   * See cmConfigureFileCommand for details.
   */
  void ConfigureString(const std::string& input, std::string& output,
607
                       bool atOnly, bool escapeQuotes) const;
608

609
  /**
luz.paz's avatar
luz.paz committed
610
   * Copy file but change lines according to ConfigureString
611
   */
612 613
  int ConfigureFile(const std::string& infile, const std::string& outfile,
                    bool copyonly, bool atOnly, bool escapeQuotes,
614
                    cmNewLineStyle = cmNewLineStyle());
615

616 617 618
  /**
   * Print a command's invocation
   */
619
  void PrintCommandTrace(const cmListFileFunction& lff) const;
620

Ken Martin's avatar
Ken Martin committed
621
  /**
622 623
   * Execute a single CMake command.  Returns true if the command
   * succeeded or false if it failed.
Ken Martin's avatar
Ken Martin committed
624
   */
625
  bool ExecuteCommand(const cmListFileFunction& lff,
626
                      cmExecutionStatus& status);
627

628
  //! Enable support for named language, if nil then all languages are
629 630 631
  /// enabled.
  void EnableLanguage(std::vector<std::string> const& languages,
                      bool optional);
632

633
  cmState* GetState() const;
634

635 636 637 638
/**
 * Get the variable watch. This is used to determine when certain variables
 * are accessed.
 */
639
#ifdef CMAKE_BUILD_WITH_CMAKE
640
  cmVariableWatch* GetVariableWatch() const;
641
#endif
642

643
  //! Display progress or status message.
644
  void DisplayStatus(const std::string&, float) const;
645

646 647 648 649
  /**
   * Expand the given list file arguments into the full set after
   * variable replacement and list expansion.
   */
650
  bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs,
651
                       std::vector<std::string>& outArgs,
Daniel Pfeifer's avatar
Daniel Pfeifer committed
652
                       const char* filename = nullptr) const;
653 654

  bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs,
655
                       std::vector<cmExpandedCommandArgument>& outArgs,
Daniel Pfeifer's avatar
Daniel Pfeifer committed
656
                       const char* filename = nullptr) const;
657

658 659
  /**
   * Get the instance
660
   */
661
  cmake* GetCMakeInstance() const;
662
  cmMessenger* GetMessenger() const;
663
  cmGlobalGenerator* GetGlobalGenerator() const;
664

665 666 667
  /**
   * Get all the source files this makefile knows about
   */
668 669 670 671
  const std::vector<cmSourceFile*>& GetSourceFiles() const
  {
    return this->SourceFiles;
  }
672 673 674 675 676

  /**
   * Is there a source file that has the provided source file as an output?
   * if so then return it
   */
677
  cmSourceFile* GetSourceFileWithOutput(const std::string& outName) const;
678

679
  //! Add a new cmTest to the list of tests for this makefile.
680
  cmTest* CreateTest(const std::string& testName);
681 682 683 684

  /** Get a cmTest pointer for a given test name, if the name is
   *  not found, then a null pointer is returned.
   */
685
  cmTest* GetTest(const std::string& testName) const;
686

687 688 689 690 691
  /**
   * Get all tests that run under the given configuration.
   */
  void GetTests(const std::string& config, std::vector<cmTest*>& tests);

692 693 694
  /**
   * Return a location of a file in cmake or custom modules directory
   */
695
  std::string GetModulesFile(const std::string& name) const
696 697 698 699 700
  {
    bool system;
    return this->GetModulesFile(name, system);
  }

701
  std::string GetModulesFile(const std::string& name, bool& system) const;
702

703
  //! Set/Get a property of this directory
704 705 706 707 708
  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) const;
  const char* GetProperty(const std::string& prop, bool chain) const;
709
  bool GetPropertyAsBool(const std::string& prop) const;
710
  std::vector<std::string> GetPropertyKeys() const;
711

712
  //! Initialize a makefile from its parent
713
  void InitializeFromParent(cmMakefile* parent);
714

715
  void AddInstallGenerator(cmInstallGenerator* g)
716
  {
717
    if (g) {
718
      this->InstallGenerators.push_back(g);
719
    }
720
  }
721
  std::vector<cmInstallGenerator*>& GetInstallGenerators()
722 723 724
  {
    return this->InstallGenerators;
  }
725 726 727 728
  const std::vector<cmInstallGenerator*>& GetInstallGenerators() const
  {
    return this->InstallGenerators;
  }
729

730
  void AddTestGenerator(cmTestGenerator* g)
731
  {
732
    if (g) {
733
      this->TestGenerators.push_back(g);
734
    }
735
  }
736
  const std::vector<cmTestGenerator*>& GetTestGenerators() const
737 738 739
  {
    return this->TestGenerators;
  }
740

741 742 743
  class FunctionPushPop
  {
  public:
744
    FunctionPushPop(cmMakefile* mf, std::string const& fileName,
745 746 747
                    cmPolicies::PolicyMap const& pm);
    ~FunctionPushPop();

748 749 750
    FunctionPushPop(const FunctionPushPop&) = delete;
    FunctionPushPop& operator=(const FunctionPushPop&) = delete;

751
    void Quiet() { this->ReportError = false; }
752

753 754 755 756 757
  private:
    cmMakefile* Makefile;
    bool ReportError;
  };

758 759 760
  class MacroPushPop
  {
  public:
761 762
    MacroPushPop(cmMakefile* mf, std::string const& fileName,
                 cmPolicies::PolicyMap const& pm);
763 764
    ~MacroPushPop();

765 766 767
    MacroPushPop(const MacroPushPop&) = delete;
    MacroPushPop& operator=(const MacroPushPop&) = delete;

768
    void Quiet() { this->ReportError = false; }
769

770 771 772 773 774
  private:
    cmMakefile* Makefile;
    bool ReportError;
  };

775 776
  void PushFunctionScope(std::string const& fileName,
                         cmPolicies::PolicyMap const& pm);
777
  void PopFunctionScope(bool reportError);
778 779
  void PushMacroScope(std::string const& fileName,
                      cmPolicies::PolicyMap const& pm);
780
  void PopMacroScope(bool reportError);
781 782
  void PushScope();
  void PopScope();
783
  void RaiseScope(const std::string& var, const char* value);
784

785 786 787 788
  // push and pop loop scopes
  void PushLoopBlockBarrier();
  void PopLoopBlockBarrier();

789 790 791 792
  /** Helper class to push and pop scopes automatically.  */
  class ScopePushPop
  {
  public:
793 794 795 796 797
    ScopePushPop(cmMakefile* m)
      : Makefile(m)
    {
      this->Makefile->PushScope();
    }
wahikihiki's avatar
wahikihiki committed
798

799
    ~ScopePushPop() { this->Makefile->PopScope(); }
800

wahikihiki's avatar
wahikihiki committed
801 802 803
    ScopePushPop(ScopePushPop const&) = delete;
    ScopePushPop& operator=(ScopePushPop const&) = delete;

804 805 806 807
  private:
    cmMakefile* Makefile;
  };

808
  void IssueMessage(MessageType t, std::string const& text) const;
809

810 811 812
  /** Set whether or not to report a CMP0000 violation.  */
  void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; }

813 814 815
  bool CheckCMP0037(std::string const& targetName,
                    cmStateEnums::TargetType targetType) const;

816 817 818 819 820 821
  cmStringRange GetIncludeDirectoriesEntries() const;
  cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
  cmStringRange GetCompileOptionsEntries() const;
  cmBacktraceRange GetCompileOptionsBacktraces() const;
  cmStringRange GetCompileDefinitionsEntries() const;
  cmBacktraceRange GetCompileDefinitionsBacktraces() const;
822 823
  cmStringRange GetLinkOptionsEntries() const;
  cmBacktraceRange GetLinkOptionsBacktraces() const;
824 825
  cmStringRange GetLinkDirectoriesEntries() const;
  cmBacktraceRange GetLinkDirectoriesBacktraces() const;
826

827 828 829 830
  std::set<std::string> const& GetSystemIncludeDirectories() const
  {
    return this->SystemIncludeDirectories;
  }
831

832 833
  bool PolicyOptionalWarningEnabled(std::string const& var);

834
  bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature,
Daniel Pfeifer's avatar
Daniel Pfeifer committed
835
                                std::string* error = nullptr) const;
836

837
  bool CompileFeatureKnown(cmTarget const* target, const std::string& feature,
838
                           std::string& lang, std::string* error) const;
839

840
  const char* CompileFeaturesAvailable(const std::string& lang,
841
                                       std::string* error) const;
842

843
  bool HaveStandardAvailable(cmTarget const* target, std::string const& lang,
844
                             const std::string& feature) const;
845

846
  bool IsLaterStandard(std::string const& lang, std::string const& lhs,
847 848
                       std::string const& rhs);

849 850 851 852
  void PushLoopBlock();
  void PopLoopBlock();
  bool IsLoopBlock() const;

853 854 855
  void ClearMatches();
  void StoreMatches(cmsys::RegularExpression& re);

856
  cmStateSnapshot GetStateSnapshot() const;
857

858 859
  const char* GetDefineFlagsCMP0059() const;

860 861
  std::string GetExecutionFilePath() const;

862 863
  void EnforceDirectoryLevelRules() const;

864 865 866 867 868
  void AddEvaluationFile(
    const std::string& inputFile,
    std::unique_ptr<cmCompiledGeneratorExpression> outputName,
    std::unique_ptr<cmCompiledGeneratorExpression> condition,
    bool inputIsContent);
869 870
  std::vector<cmGeneratorExpressionEvaluationFile*> GetEvaluationFiles() const;

871 872
  std::vector<cmExportBuildFileGenerator*> GetExportBuildFileGenerators()
    const;
873 874 875
  void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen);
  void AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen);

876 877 878 879 880
  // Maintain a stack of package roots to allow nested PACKAGE_ROOT_PATH
  // searches
  std::deque<std::vector<std::string>> FindPackageRootPathStack;

  void MaybeWarnCMP0074(std::string const& pkg);
881 882
  void MaybeWarnUninitialized(std::string const& variable,
                              const char* sourceFilename) const;
883
  bool IsProjectFile(const char* filename) const;
884

885 886 887
  int GetRecursionDepth() const;
  void SetRecursionDepth(int recursionDepth);

888
protected:
889
  // add link libraries and directories to the target
890
  void AddGlobalLinkInformation(cmTarget& target);
891 892

  // Check for a an unused variable
893
  void LogUnused(const char* reason, const std::string& name) const;
894

895 896
  mutable std::set<cmListFileContext> CMP0054ReportedIds;

897
  // libraries, classes, and executables
898
  mutable cmTargetMap Targets;
899
  std::map<std::string, std::string> AliasTargets;
900 901 902 903 904 905 906 907 908 909 910 911

  typedef std::vector<cmSourceFile*> SourceFileVec;
  SourceFileVec SourceFiles;

  // Because cmSourceFile names are compared in a fuzzy way (see
  // cmSourceFileLocation::Match()) we can't have a straight mapping from
  // filename to cmSourceFile.  To make lookups more efficient we store the
  // Name portion of the cmSourceFileLocation and then compare on the list of
  // cmSourceFiles that might match that name.  Note that on platforms which
  // have a case-insensitive filesystem we store the key in all lowercase.
  typedef std::unordered_map<std::string, SourceFileVec> SourceFileMap;
  SourceFileMap SourceFileSearchIndex;
912

913 914 915
  // For "Known" paths we can store a direct filename to cmSourceFile map
  std::unordered_map<std::string, cmSourceFile*> KnownFileSearchIndex;

916
  // Tests
917
  std::map<std::string, cmTest*> Tests;
918

919 920
  // The set of include directories that are marked as system include
  // directories.
921
  std::set<std::string> SystemIncludeDirectories;
922

923 924
  std::vector<std::string> ListFiles;
  std::vector<std::string> OutputFiles;
925

926
  std::vector<cmInstallGenerator*> InstallGenerators;
927
  std::vector<cmTestGenerator*> TestGenerators;
928 929 930

  std::string ComplainFileRegularExpression;
  std::string DefineFlags;
931

932 933 934
  // Track the value of the computed DEFINITIONS property.
  std::string DefineFlagsOrig;

935
#if defined(CMAKE_BUILD_WITH_CMAKE)
936
  std::vector<cmSourceGroup> SourceGroups;
937
  size_t ObjectLibrariesSourceGroupIndex;
938 939
#endif

940
  std::vector<std::unique_ptr<cmCommand>> FinalPassCommands;
941
  cmGlobalGenerator* GlobalGenerator;
942
  bool IsFunctionBlocked(const cmListFileFunction& lff,
943
                         cmExecutionStatus& status);
944

945
private:
946
  cmStateSnapshot StateSnapshot;
947
  cmListFileBacktrace Backtrace;
948
  int RecursionDepth;
949

950 951
  void ReadListFile(cmListFile const& listFile,
                    const std::string& filenametoread);
952

953 954
  bool ParseDefineFlag(std::string const& definition, bool remove);

955 956
  bool EnforceUniqueDir(const std::string& srcPath,
                        const std::string& binPath) const;
957

958 959 960 961 962
  typedef std::vector<cmFunctionBlocker*> FunctionBlockersType;
  FunctionBlockersType FunctionBlockers;
  std::vector<FunctionBlockersType::size_type> FunctionBlockerBarriers;
  void PushFunctionBlockerBarrier();
  void PopFunctionBlockerBarrier(bool reportError = true);
963

964 965
  std::stack<int> LoopBlockCounter;

966 967
  mutable cmsys::RegularExpression cmDefineRegex;
  mutable cmsys::RegularExpression cmDefine01Regex;
968
  mutable cmsys::RegularExpression cmAtVarRegex;
969
  mutable cmsys::RegularExpression cmNamedCurly;
970

971
  std::vector<cmMakefile*> UnConfiguredDirectories;
972
  std::vector<cmExportBuildFileGenerator*> ExportBuildFileGenerators;
973

974 975
  std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles;

976
  std::vector<cmExecutionStatus*> ExecutionStatusStack;
977
  friend class cmMakefileCall;
978
  friend class cmParseFileScope;
979

980
  std::vector<cmTarget*> ImportedTargetsOwned;
981
  typedef std::unordered_map<std::string, cmTarget*> TargetMap;
982
  TargetMap ImportedTargets;
983 984

  // Internal policy stack management.
985 986
  void PushPolicy(bool weak = false,
                  cmPolicies::PolicyMap const& pm = cmPolicies::PolicyMap());
987
  void PopPolicy();
988
  void PopSnapshot(bool reportError = true);
989
  friend class cmCMakePolicyCommand;
990
  class IncludeScope;
991

992
  friend class IncludeScope;
993
  class ListFileScope;
994

995 996
  friend class ListFileScope;
  class BuildsystemFileScope;
997

998
  friend class BuildsystemFileScope;
999

1000
  // CMP0053 == old
1001 1002 1003 1004 1005 1006
  MessageType ExpandVariablesInStringOld(std::string& errorstr,
                                         std::string& source,
                                         bool escapeQuotes, bool noEscapes,
                                         bool atOnly, const char* filename,
                                         long line, bool removeEmpty,
                                         bool replaceAt) const;
1007
  // CMP0053 == new
1008 1009 1010 1011 1012
  MessageType ExpandVariablesInStringNew(std::string& errorstr,
                                         std::string& source,
                                         bool escapeQuotes, bool noEscapes,
                                         bool atOnly, const char* filename,
                                         long line, bool replaceAt) const;
1013
  /**
1014
   * Old version of GetSourceFileWithOutput(const std::string&) kept for
1015 1016
   * backward-compatibility. It implements a linear search and support
   * relative file paths. It is used as a fall back by
1017
   * GetSourceFileWithOutput(const std::string&).
1018
   */
1019
  cmSourceFile* LinearGetSourceFileWithOutput(const std::string& cname) const;
1020

1021
  // A map for fast output to input look up.
1022
  typedef std::unordered_map<std::string, cmSourceFile*> OutputToSourceMap;
1023 1024 1025 1026 1027 1028
  OutputToSourceMap OutputToSource;

  void UpdateOutputToSourceMap(std::vector<std::string> const& outputs,
                               cmSourceFile* source);
  void UpdateOutputToSourceMap(std::string const& output,
                               cmSourceFile* source);
1029

1030
  bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature,
Daniel Pfeifer's avatar
Daniel Pfeifer committed
1031
                                 std::string* error = nullptr) const;
1032

1033
  bool AddRequiredTargetCxxFeature(cmTarget* target,
1034
                                   const std::string& feature,
Daniel Pfeifer's avatar
Daniel Pfeifer committed
1035
                                   std::string* error = nullptr) const;
1036 1037 1038 1039

  void CheckNeededCLanguage(const std::string& feature, bool& needC90,
                            bool& needC99, bool& needC11) const;
  void CheckNeededCxxLanguage(const std::string& feature