1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 file Copyright.txt or https://cmake.org/licensing for details. */ 3 #pragma once 4 5 #include "cmConfigure.h" // IWYU pragma: keep 6 7 #include <cstddef> 8 #include <deque> 9 #include <functional> 10 #include <map> 11 #include <memory> 12 #include <set> 13 #include <stack> 14 #include <string> 15 #include <unordered_map> 16 #include <utility> 17 #include <vector> 18 19 #include <cm/optional> 20 #include <cm/string_view> 21 22 #include "cmsys/RegularExpression.hxx" 23 24 #include "cm_sys_stat.h" 25 26 #include "cmAlgorithms.h" 27 #include "cmCustomCommandTypes.h" 28 #include "cmListFileCache.h" 29 #include "cmMessageType.h" 30 #include "cmNewLineStyle.h" 31 #include "cmPolicies.h" 32 #include "cmSourceFileLocationKind.h" 33 #include "cmStateSnapshot.h" 34 #include "cmStateTypes.h" 35 #include "cmValue.h" 36 37 // IWYU does not see that 'std::unordered_map<std::string, cmTarget>' 38 // will not compile without the complete type. 39 #include "cmTarget.h" // IWYU pragma: keep 40 41 #if !defined(CMAKE_BOOTSTRAP) 42 # include "cmSourceGroup.h" 43 #endif 44 45 class cmCompiledGeneratorExpression; 46 class cmCustomCommandLines; 47 class cmExecutionStatus; 48 class cmExpandedCommandArgument; 49 class cmExportBuildFileGenerator; 50 class cmFunctionBlocker; 51 class cmGeneratorExpressionEvaluationFile; 52 class cmGlobalGenerator; 53 class cmImplicitDependsList; 54 class cmInstallGenerator; 55 class cmLocalGenerator; 56 class cmMessenger; 57 class cmSourceFile; 58 class cmState; 59 class cmTest; 60 class cmTestGenerator; 61 class cmVariableWatch; 62 class cmake; 63 64 /** A type-safe wrapper for a string representing a directory id. */ 65 class cmDirectoryId 66 { 67 public: 68 cmDirectoryId(std::string s); 69 std::string String; 70 }; 71 72 /** \class cmMakefile 73 * \brief Process the input CMakeLists.txt file. 74 * 75 * Process and store into memory the input CMakeLists.txt file. 76 * Each CMakeLists.txt file is parsed and the commands found there 77 * are added into the build process. 78 */ 79 class cmMakefile 80 { 81 public: 82 /* Mark a variable as used */ 83 void MarkVariableAsUsed(const std::string& var); 84 /* return true if a variable has been initialized */ 85 bool VariableInitialized(const std::string&) const; 86 87 /** 88 * Construct an empty makefile. 89 */ 90 cmMakefile(cmGlobalGenerator* globalGenerator, 91 const cmStateSnapshot& snapshot); 92 93 /** 94 * Destructor. 95 */ 96 ~cmMakefile(); 97 98 cmMakefile(cmMakefile const&) = delete; 99 cmMakefile& operator=(cmMakefile const&) = delete; 100 101 cmDirectoryId GetDirectoryId() const; 102 103 bool ReadListFile(const std::string& filename); 104 105 bool ReadListFileAsString(const std::string& content, 106 const std::string& virtualFileName); 107 108 bool ReadDependentFile(const std::string& filename, 109 bool noPolicyScope = true); 110 111 /** 112 * Add a function blocker to this makefile 113 */ 114 void AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb); 115 116 /// @return whether we are processing the top CMakeLists.txt file. 117 bool IsRootMakefile() const; 118 119 /** 120 * Remove the function blocker whose scope ends with the given command. 121 * This returns ownership of the function blocker object. 122 */ 123 std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker(); 124 125 /** 126 * Try running cmake and building a file. This is used for dynamically 127 * loaded commands, not as part of the usual build process. 128 */ 129 int TryCompile(const std::string& srcdir, const std::string& bindir, 130 const std::string& projectName, const std::string& targetName, 131 bool fast, int jobs, 132 const std::vector<std::string>* cmakeArgs, 133 std::string& output); 134 135 bool GetIsSourceFileTryCompile() const; 136 137 /** 138 * Help enforce global target name uniqueness. 139 */ 140 bool EnforceUniqueName(std::string const& name, std::string& msg, 141 bool isCustom = false) const; 142 143 using GeneratorAction = 144 std::function<void(cmLocalGenerator&, const cmListFileBacktrace&)>; 145 146 /** 147 * Register an action that is executed during Generate 148 */ 149 void AddGeneratorAction(GeneratorAction action); 150 151 /** 152 * Perform generate actions, Library dependency analysis etc before output of 153 * the makefile. 154 */ 155 void Generate(cmLocalGenerator& lg); 156 157 /** 158 * Get the target for PRE_BUILD, PRE_LINK, or POST_BUILD commands. 159 */ 160 cmTarget* GetCustomCommandTarget(const std::string& target, 161 cmObjectLibraryCommands objLibCommands, 162 const cmListFileBacktrace& lfbt) const; 163 164 /** 165 * Dispatch adding a custom PRE_BUILD, PRE_LINK, or POST_BUILD command to a 166 * target. 167 */ 168 cmTarget* AddCustomCommandToTarget( 169 const std::string& target, const std::vector<std::string>& byproducts, 170 const std::vector<std::string>& depends, 171 const cmCustomCommandLines& commandLines, cmCustomCommandType type, 172 const char* comment, const char* workingDir, 173 cmPolicies::PolicyStatus cmp0116, bool escapeOldStyle = true, 174 bool uses_terminal = false, const std::string& depfile = "", 175 const std::string& job_pool = "", bool command_expand_lists = false, 176 bool stdPipesUTF8 = false); 177 178 /** 179 * Called for each file with custom command. 180 */ 181 using CommandSourceCallback = std::function<void(cmSourceFile*)>; 182 183 /** 184 * Dispatch adding a custom command to a source file. 185 */ 186 void AddCustomCommandToOutput( 187 const std::string& output, const std::vector<std::string>& depends, 188 const std::string& main_dependency, 189 const cmCustomCommandLines& commandLines, const char* comment, 190 const char* workingDir, cmPolicies::PolicyStatus cmp0116, 191 const CommandSourceCallback& callback = nullptr, bool replace = false, 192 bool escapeOldStyle = true, bool uses_terminal = false, 193 bool command_expand_lists = false, const std::string& depfile = "", 194 const std::string& job_pool = "", bool stdPipesUTF8 = false); 195 void AddCustomCommandToOutput( 196 const std::vector<std::string>& outputs, 197 const std::vector<std::string>& byproducts, 198 const std::vector<std::string>& depends, 199 const std::string& main_dependency, 200 const cmImplicitDependsList& implicit_depends, 201 const cmCustomCommandLines& commandLines, const char* comment, 202 const char* workingDir, cmPolicies::PolicyStatus cmp0116, 203 const CommandSourceCallback& callback = nullptr, bool replace = false, 204 bool escapeOldStyle = true, bool uses_terminal = false, 205 bool command_expand_lists = false, const std::string& depfile = "", 206 const std::string& job_pool = "", bool stdPipesUTF8 = false); 207 void AddCustomCommandOldStyle(const std::string& target, 208 const std::vector<std::string>& outputs, 209 const std::vector<std::string>& depends, 210 const std::string& source, 211 const cmCustomCommandLines& commandLines, 212 const char* comment, 213 cmPolicies::PolicyStatus cmp0116); 214 void AppendCustomCommandToOutput( 215 const std::string& output, const std::vector<std::string>& depends, 216 const cmImplicitDependsList& implicit_depends, 217 const cmCustomCommandLines& commandLines); 218 219 /** 220 * Add a define flag to the build. 221 */ 222 void AddDefineFlag(std::string const& definition); 223 void RemoveDefineFlag(std::string const& definition); 224 void AddCompileDefinition(std::string const& definition); 225 void AddCompileOption(std::string const& option); 226 void AddLinkOption(std::string const& option); 227 void AddLinkDirectory(std::string const& directory, bool before = false); 228 229 /** Create a new imported target with the name and type given. */ 230 cmTarget* AddImportedTarget(const std::string& name, 231 cmStateEnums::TargetType type, bool global); 232 233 std::pair<cmTarget&, bool> CreateNewTarget( 234 const std::string& name, cmStateEnums::TargetType type, 235 cmTarget::PerConfig perConfig = cmTarget::PerConfig::Yes); 236 237 cmTarget* AddNewTarget(cmStateEnums::TargetType type, 238 const std::string& name); 239 240 /** Create a target instance for the utility. */ 241 cmTarget* AddNewUtilityTarget(const std::string& utilityName, 242 bool excludeFromAll); 243 244 /** 245 * Add an executable to the build. 246 */ 247 cmTarget* AddExecutable(const std::string& exename, 248 const std::vector<std::string>& srcs, 249 bool excludeFromAll = false); 250 251 /** 252 * Dispatch adding a utility to the build. A utility target is a command 253 * that is run every time the target is built. 254 */ 255 cmTarget* AddUtilityCommand( 256 const std::string& utilityName, bool excludeFromAll, 257 const char* workingDir, const std::vector<std::string>& byproducts, 258 const std::vector<std::string>& depends, 259 const cmCustomCommandLines& commandLines, cmPolicies::PolicyStatus cmp0116, 260 bool escapeOldStyle = true, const char* comment = nullptr, 261 bool uses_terminal = false, bool command_expand_lists = false, 262 const std::string& job_pool = "", bool stdPipesUTF8 = false); 263 264 /** 265 * Add a subdirectory to the build. 266 */ 267 void AddSubDirectory(const std::string& fullSrcDir, 268 const std::string& fullBinDir, bool excludeFromAll, 269 bool immediate); 270 271 void Configure(); 272 273 /** 274 * Configure a subdirectory 275 */ 276 void ConfigureSubDirectory(cmMakefile* mf); 277 278 /** 279 * Add an include directory to the build. 280 */ 281 void AddIncludeDirectories(const std::vector<std::string>& incs, 282 bool before = false); 283 284 /** 285 * Add a variable definition to the build. This variable 286 * can be used in CMake to refer to lists, directories, etc. 287 */ 288 void AddDefinition(const std::string& name, cm::string_view value); AddDefinition(const std::string & name,cmValue value)289 void AddDefinition(const std::string& name, cmValue value) 290 { 291 this->AddDefinition(name, *value); 292 } 293 /** 294 * Add bool variable definition to the build. 295 */ 296 void AddDefinitionBool(const std::string& name, bool); 297 //! Add a definition to this makefile and the global cmake cache. 298 void AddCacheDefinition(const std::string& name, const char* value, 299 const char* doc, cmStateEnums::CacheEntryType type, 300 bool force = false); 301 void AddCacheDefinition(const std::string& name, const std::string& value, 302 const char* doc, cmStateEnums::CacheEntryType type, 303 bool force = false) 304 { 305 this->AddCacheDefinition(name, value.c_str(), doc, type, force); 306 } 307 308 /** 309 * Remove a variable definition from the build. This is not valid 310 * for cache entries, and will only affect the current makefile. 311 */ 312 void RemoveDefinition(const std::string& name); 313 //! Remove a definition from the cache. 314 void RemoveCacheDefinition(const std::string& name) const; 315 316 /** 317 * Specify the name of the project for this build. 318 */ 319 void SetProjectName(std::string const& name); 320 321 void InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault); 322 323 /* Get the default configuration */ 324 std::string GetDefaultConfiguration() const; 325 326 enum GeneratorConfigQuery 327 { 328 IncludeEmptyConfig, // Include "" aka noconfig 329 ExcludeEmptyConfig, // Exclude "" aka noconfig 330 OnlyMultiConfig, 331 }; 332 333 /** Get the configurations for dependency checking. */ 334 std::vector<std::string> GetGeneratorConfigs( 335 GeneratorConfigQuery mode) const; 336 337 /** 338 * Set the name of the library. 339 */ 340 cmTarget* AddLibrary(const std::string& libname, 341 cmStateEnums::TargetType type, 342 const std::vector<std::string>& srcs, 343 bool excludeFromAll = false); 344 void AddAlias(const std::string& libname, const std::string& tgt, 345 bool globallyVisible = true); 346 347 //@{ 348 /** 349 * Set, Push, Pop policy values for CMake. 350 */ 351 bool SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status); 352 bool SetPolicy(const char* id, cmPolicies::PolicyStatus status); 353 cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id, 354 bool parent_scope = false) const; 355 bool SetPolicyVersion(std::string const& version_min, 356 std::string const& version_max); 357 void RecordPolicies(cmPolicies::PolicyMap& pm) const; 358 //@} 359 360 /** Helper class to push and pop policies automatically. */ 361 class PolicyPushPop 362 { 363 public: 364 PolicyPushPop(cmMakefile* m); 365 ~PolicyPushPop(); 366 367 PolicyPushPop(const PolicyPushPop&) = delete; 368 PolicyPushPop& operator=(const PolicyPushPop&) = delete; 369 370 private: 371 cmMakefile* Makefile; 372 }; 373 friend class PolicyPushPop; 374 375 /** 376 * Determine if the given context, name pair has already been reported 377 * in context of CMP0054. 378 */ 379 bool HasCMP0054AlreadyBeenReported(const cmListFileContext& context) const; 380 381 bool IgnoreErrorsCMP0061() const; 382 383 std::string const& GetHomeDirectory() const; 384 std::string const& GetHomeOutputDirectory() const; 385 386 /** 387 * Set CMAKE_SCRIPT_MODE_FILE variable when running a -P script. 388 */ 389 void SetScriptModeFile(std::string const& scriptfile); 390 391 /** 392 * Set CMAKE_ARGC, CMAKE_ARGV0 ... variables. 393 */ 394 void SetArgcArgv(const std::vector<std::string>& args); 395 396 std::string const& GetCurrentSourceDirectory() const; 397 std::string const& GetCurrentBinaryDirectory() const; 398 399 //@} 400 401 /** 402 * Set a regular expression that include files must match 403 * in order to be considered as part of the depend information. 404 */ SetIncludeRegularExpression(const std::string & regex)405 void SetIncludeRegularExpression(const std::string& regex) 406 { 407 this->SetProperty("INCLUDE_REGULAR_EXPRESSION", regex.c_str()); 408 } GetIncludeRegularExpression()409 const std::string& GetIncludeRegularExpression() const 410 { 411 return this->GetProperty("INCLUDE_REGULAR_EXPRESSION"); 412 } 413 414 /** 415 * Set a regular expression that include files that are not found 416 * must match in order to be considered a problem. 417 */ SetComplainRegularExpression(const std::string & regex)418 void SetComplainRegularExpression(const std::string& regex) 419 { 420 this->ComplainFileRegularExpression = regex; 421 } GetComplainRegularExpression()422 const std::string& GetComplainRegularExpression() const 423 { 424 return this->ComplainFileRegularExpression; 425 } 426 427 // -- List of targets 428 using cmTargetMap = std::unordered_map<std::string, cmTarget>; 429 /** Get the target map */ GetTargets()430 cmTargetMap& GetTargets() { return this->Targets; } 431 /** Get the target map - const version */ GetTargets()432 cmTargetMap const& GetTargets() const { return this->Targets; } 433 GetOwnedImportedTargets()434 const std::vector<std::unique_ptr<cmTarget>>& GetOwnedImportedTargets() const 435 { 436 return this->ImportedTargetsOwned; 437 } 438 std::vector<cmTarget*> GetImportedTargets() const; 439 440 cmTarget* FindLocalNonAliasTarget(const std::string& name) const; 441 442 /** Find a target to use in place of the given name. The target 443 returned may be imported or built within the project. */ 444 cmTarget* FindTargetToUse(const std::string& name, 445 bool excludeAliases = false) const; 446 bool IsAlias(const std::string& name) const; 447 GetAliasTargets()448 std::map<std::string, std::string> GetAliasTargets() const 449 { 450 return this->AliasTargets; 451 } 452 453 /** 454 * Mark include directories as system directories. 455 */ 456 void AddSystemIncludeDirectories(const std::set<std::string>& incs); 457 458 /** Get a cmSourceFile pointer for a given source name, if the name is 459 * not found, then a null pointer is returned. 460 */ 461 cmSourceFile* GetSource( 462 const std::string& sourceName, 463 cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous) const; 464 465 /** Create the source file and return it. generated 466 * indicates if it is a generated file, this is used in determining 467 * how to create the source file instance e.g. name 468 */ 469 cmSourceFile* CreateSource( 470 const std::string& sourceName, bool generated = false, 471 cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous); 472 473 /** Get a cmSourceFile pointer for a given source name, if the name is 474 * not found, then create the source file and return it. generated 475 * indicates if it is a generated file, this is used in determining 476 * how to create the source file instance e.g. name 477 */ 478 cmSourceFile* GetOrCreateSource( 479 const std::string& sourceName, bool generated = false, 480 cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous); 481 482 /** Get a cmSourceFile pointer for a given source name and always mark the 483 * file as generated, if the name is not found, then create the source file 484 * and return it. 485 */ 486 cmSourceFile* GetOrCreateGeneratedSource(const std::string& sourceName); 487 488 void AddTargetObject(std::string const& tgtName, std::string const& objFile); 489 490 /** 491 * Given a variable name, return its value (as a string). 492 * If the variable is not found in this makefile instance, the 493 * cache is then queried. 494 */ 495 cmValue GetDefinition(const std::string&) const; 496 const std::string& GetSafeDefinition(const std::string&) const; 497 const std::string& GetRequiredDefinition(const std::string& name) const; 498 bool IsDefinitionSet(const std::string&) const; 499 bool IsNormalDefinitionSet(const std::string&) const; 500 bool GetDefExpandList(const std::string& name, std::vector<std::string>& out, 501 bool emptyArgs = false) const; 502 /** 503 * Get the list of all variables in the current space. If argument 504 * cacheonly is specified and is greater than 0, then only cache 505 * variables will be listed. 506 */ 507 std::vector<std::string> GetDefinitions() const; 508 509 /** 510 * Test a boolean variable to see if it is true or false. 511 * If the variable is not found in this makefile instance, the 512 * cache is then queried. 513 * Returns false if no entry defined. 514 */ 515 bool IsOn(const std::string& name) const; 516 bool IsSet(const std::string& name) const; 517 518 /** Return whether the target platform is 32-bit. */ 519 bool PlatformIs32Bit() const; 520 521 /** Return whether the target platform is 64-bit. */ 522 bool PlatformIs64Bit() const; 523 /** Return whether the target platform is x32. */ 524 bool PlatformIsx32() const; 525 526 /** Apple SDK Type */ 527 enum class AppleSDK 528 { 529 MacOS, 530 IPhoneOS, 531 IPhoneSimulator, 532 AppleTVOS, 533 AppleTVSimulator, 534 WatchOS, 535 WatchSimulator, 536 }; 537 538 /** What SDK type points CMAKE_OSX_SYSROOT to? */ 539 AppleSDK GetAppleSDKType() const; 540 541 /** Return whether the target platform is Apple iOS. */ 542 bool PlatformIsAppleEmbedded() const; 543 544 /** Retrieve soname flag for the specified language if supported */ 545 const char* GetSONameFlag(const std::string& language) const; 546 547 /** 548 * Get a list of preprocessor define flags. 549 */ GetDefineFlags()550 std::string GetDefineFlags() const { return this->DefineFlags; } 551 552 /** 553 * Make sure CMake can write this file 554 */ 555 bool CanIWriteThisFile(std::string const& fileName) const; 556 557 #if !defined(CMAKE_BOOTSTRAP) 558 /** 559 * Get the vector source groups. 560 */ GetSourceGroups()561 const std::vector<cmSourceGroup>& GetSourceGroups() const 562 { 563 return this->SourceGroups; 564 } 565 566 /** 567 * Get the source group 568 */ 569 cmSourceGroup* GetSourceGroup(const std::vector<std::string>& name) const; 570 571 /** 572 * Add a root source group for consideration when adding a new source. 573 */ 574 void AddSourceGroup(const std::string& name, const char* regex = nullptr); 575 576 /** 577 * Add a source group for consideration when adding a new source. 578 * name is tokenized. 579 */ 580 void AddSourceGroup(const std::vector<std::string>& name, 581 const char* regex = nullptr); 582 583 /** 584 * Get and existing or create a new source group. 585 */ 586 cmSourceGroup* GetOrCreateSourceGroup( 587 const std::vector<std::string>& folders); 588 589 /** 590 * Get and existing or create a new source group. 591 * The name will be tokenized. 592 */ 593 cmSourceGroup* GetOrCreateSourceGroup(const std::string& name); 594 595 /** 596 * find what source group this source is in 597 */ 598 cmSourceGroup* FindSourceGroup(const std::string& source, 599 std::vector<cmSourceGroup>& groups) const; 600 #endif 601 602 /** 603 * Get the vector of list files on which this makefile depends 604 */ GetListFiles()605 const std::vector<std::string>& GetListFiles() const 606 { 607 return this->ListFiles; 608 } 609 //! When the file changes cmake will be re-run from the build system. AddCMakeDependFile(const std::string & file)610 void AddCMakeDependFile(const std::string& file) 611 { 612 this->ListFiles.push_back(file); 613 } 614 void AddCMakeDependFilesFromUser(); 615 616 std::string FormatListFileStack() const; 617 618 /** 619 * Get the current context backtrace. 620 */ 621 cmListFileBacktrace GetBacktrace() const; 622 623 /** 624 * Get the vector of files created by this makefile 625 */ GetOutputFiles()626 const std::vector<std::string>& GetOutputFiles() const 627 { 628 return this->OutputFiles; 629 } AddCMakeOutputFile(const std::string & file)630 void AddCMakeOutputFile(const std::string& file) 631 { 632 this->OutputFiles.push_back(file); 633 } 634 635 /** 636 * Expand all defined variables in the string. 637 * Defined variables come from the this->Definitions map. 638 * They are expanded with ${var} where var is the 639 * entry in the this->Definitions map. Also \@var\@ is 640 * expanded to match autoconf style expansions. 641 */ 642 const std::string& ExpandVariablesInString(std::string& source) const; 643 const std::string& ExpandVariablesInString( 644 std::string& source, bool escapeQuotes, bool noEscapes, 645 bool atOnly = false, const char* filename = nullptr, long line = -1, 646 bool removeEmpty = false, bool replaceAt = false) const; 647 648 /** 649 * Remove any remaining variables in the string. Anything with ${var} or 650 * \@var\@ will be removed. 651 */ 652 void RemoveVariablesInString(std::string& source, bool atOnly = false) const; 653 654 /** 655 * Expand variables in the makefiles ivars such as link directories etc 656 */ 657 void ExpandVariablesCMP0019(); 658 659 /** 660 * Replace variables and #cmakedefine lines in the given string. 661 * See cmConfigureFileCommand for details. 662 */ 663 void ConfigureString(const std::string& input, std::string& output, 664 bool atOnly, bool escapeQuotes) const; 665 666 /** 667 * Copy file but change lines according to ConfigureString 668 */ 669 int ConfigureFile(const std::string& infile, const std::string& outfile, 670 bool copyonly, bool atOnly, bool escapeQuotes, 671 mode_t permissions = 0, cmNewLineStyle = cmNewLineStyle()); 672 673 /** 674 * Print a command's invocation 675 */ 676 void PrintCommandTrace(cmListFileFunction const& lff, 677 cm::optional<std::string> const& deferId = {}) const; 678 679 /** 680 * Set a callback that is invoked whenever ExecuteCommand is called. 681 */ 682 void OnExecuteCommand(std::function<void()> callback); 683 684 /** 685 * Execute a single CMake command. Returns true if the command 686 * succeeded or false if it failed. 687 */ 688 bool ExecuteCommand(const cmListFileFunction& lff, cmExecutionStatus& status, 689 cm::optional<std::string> deferId = {}); 690 691 //! Enable support for named language, if nil then all languages are 692 /// enabled. 693 void EnableLanguage(std::vector<std::string> const& languages, 694 bool optional); 695 696 cmState* GetState() const; 697 698 /** 699 * Get the variable watch. This is used to determine when certain variables 700 * are accessed. 701 */ 702 #ifndef CMAKE_BOOTSTRAP 703 cmVariableWatch* GetVariableWatch() const; 704 #endif 705 706 //! Display progress or status message. 707 void DisplayStatus(const std::string&, float) const; 708 709 /** 710 * Expand the given list file arguments into the full set after 711 * variable replacement and list expansion. 712 */ 713 bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs, 714 std::vector<std::string>& outArgs) const; 715 bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs, 716 std::vector<cmExpandedCommandArgument>& outArgs) const; 717 718 /** 719 * Get the instance 720 */ 721 cmake* GetCMakeInstance() const; 722 cmMessenger* GetMessenger() const; 723 cmGlobalGenerator* GetGlobalGenerator() const; 724 725 /** 726 * Get all the source files this makefile knows about 727 */ GetSourceFiles()728 const std::vector<std::unique_ptr<cmSourceFile>>& GetSourceFiles() const 729 { 730 return this->SourceFiles; 731 } 732 GetOrderedTargets()733 std::vector<cmTarget*> const& GetOrderedTargets() const 734 { 735 return this->OrderedTargets; 736 } 737 738 //! Add a new cmTest to the list of tests for this makefile. 739 cmTest* CreateTest(const std::string& testName); 740 741 /** Get a cmTest pointer for a given test name, if the name is 742 * not found, then a null pointer is returned. 743 */ 744 cmTest* GetTest(const std::string& testName) const; 745 746 /** 747 * Get all tests that run under the given configuration. 748 */ 749 void GetTests(const std::string& config, std::vector<cmTest*>& tests) const; 750 751 /** 752 * Return a location of a file in cmake or custom modules directory 753 */ GetModulesFile(const std::string & name)754 std::string GetModulesFile(const std::string& name) const 755 { 756 bool system; 757 std::string debugBuffer; 758 return this->GetModulesFile(name, system, false, debugBuffer); 759 } 760 761 /** 762 * Return a location of a file in cmake or custom modules directory 763 */ GetModulesFile(const std::string & name,bool & system)764 std::string GetModulesFile(const std::string& name, bool& system) const 765 { 766 std::string debugBuffer; 767 return this->GetModulesFile(name, system, false, debugBuffer); 768 } 769 770 std::string GetModulesFile(const std::string& name, bool& system, bool debug, 771 std::string& debugBuffer) const; 772 773 //! Set/Get a property of this directory 774 void SetProperty(const std::string& prop, const char* value); 775 void SetProperty(const std::string& prop, cmValue value); SetProperty(const std::string & prop,const std::string & value)776 void SetProperty(const std::string& prop, const std::string& value) 777 { 778 this->SetProperty(prop, cmValue(value)); 779 } 780 void AppendProperty(const std::string& prop, const std::string& value, 781 bool asString = false); 782 cmValue GetProperty(const std::string& prop) const; 783 cmValue GetProperty(const std::string& prop, bool chain) const; 784 bool GetPropertyAsBool(const std::string& prop) const; 785 std::vector<std::string> GetPropertyKeys() const; 786 787 //! Initialize a makefile from its parent 788 void InitializeFromParent(cmMakefile* parent); 789 790 void AddInstallGenerator(std::unique_ptr<cmInstallGenerator> g); 791 GetInstallGenerators()792 std::vector<std::unique_ptr<cmInstallGenerator>>& GetInstallGenerators() 793 { 794 return this->InstallGenerators; 795 } 796 const std::vector<std::unique_ptr<cmInstallGenerator>>& GetInstallGenerators()797 GetInstallGenerators() const 798 { 799 return this->InstallGenerators; 800 } 801 802 void AddTestGenerator(std::unique_ptr<cmTestGenerator> g); 803 GetTestGenerators()804 const std::vector<std::unique_ptr<cmTestGenerator>>& GetTestGenerators() 805 const 806 { 807 return this->TestGenerators; 808 } 809 810 class FunctionPushPop 811 { 812 public: 813 FunctionPushPop(cmMakefile* mf, std::string const& fileName, 814 cmPolicies::PolicyMap const& pm); 815 ~FunctionPushPop(); 816 817 FunctionPushPop(const FunctionPushPop&) = delete; 818 FunctionPushPop& operator=(const FunctionPushPop&) = delete; 819 Quiet()820 void Quiet() { this->ReportError = false; } 821 822 private: 823 cmMakefile* Makefile; 824 bool ReportError; 825 }; 826 827 class MacroPushPop 828 { 829 public: 830 MacroPushPop(cmMakefile* mf, std::string const& fileName, 831 cmPolicies::PolicyMap const& pm); 832 ~MacroPushPop(); 833 834 MacroPushPop(const MacroPushPop&) = delete; 835 MacroPushPop& operator=(const MacroPushPop&) = delete; 836 Quiet()837 void Quiet() { this->ReportError = false; } 838 839 private: 840 cmMakefile* Makefile; 841 bool ReportError; 842 }; 843 844 void PushFunctionScope(std::string const& fileName, 845 cmPolicies::PolicyMap const& pm); 846 void PopFunctionScope(bool reportError); 847 void PushMacroScope(std::string const& fileName, 848 cmPolicies::PolicyMap const& pm); 849 void PopMacroScope(bool reportError); 850 void PushScope(); 851 void PopScope(); 852 void RaiseScope(const std::string& var, const char* value); 853 854 // push and pop loop scopes 855 void PushLoopBlockBarrier(); 856 void PopLoopBlockBarrier(); 857 858 /** Helper class to push and pop scopes automatically. */ 859 class ScopePushPop 860 { 861 public: ScopePushPop(cmMakefile * m)862 ScopePushPop(cmMakefile* m) 863 : Makefile(m) 864 { 865 this->Makefile->PushScope(); 866 } 867 ~ScopePushPop()868 ~ScopePushPop() { this->Makefile->PopScope(); } 869 870 ScopePushPop(ScopePushPop const&) = delete; 871 ScopePushPop& operator=(ScopePushPop const&) = delete; 872 873 private: 874 cmMakefile* Makefile; 875 }; 876 877 void IssueMessage(MessageType t, std::string const& text) const; 878 879 /** Set whether or not to report a CMP0000 violation. */ SetCheckCMP0000(bool b)880 void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; } 881 882 bool CheckCMP0037(std::string const& targetName, 883 cmStateEnums::TargetType targetType) const; 884 885 cmBTStringRange GetIncludeDirectoriesEntries() const; 886 cmBTStringRange GetCompileOptionsEntries() const; 887 cmBTStringRange GetCompileDefinitionsEntries() const; 888 cmBTStringRange GetLinkOptionsEntries() const; 889 cmBTStringRange GetLinkDirectoriesEntries() const; 890 GetSystemIncludeDirectories()891 std::set<std::string> const& GetSystemIncludeDirectories() const 892 { 893 return this->SystemIncludeDirectories; 894 } 895 896 bool PolicyOptionalWarningEnabled(std::string const& var) const; 897 898 void PushLoopBlock(); 899 void PopLoopBlock(); 900 bool IsLoopBlock() const; 901 902 void ClearMatches(); 903 void StoreMatches(cmsys::RegularExpression& re); 904 905 cmStateSnapshot GetStateSnapshot() const; 906 907 const char* GetDefineFlagsCMP0059() const; 908 909 void EnforceDirectoryLevelRules() const; 910 911 void AddEvaluationFile( 912 const std::string& inputFile, const std::string& targetName, 913 std::unique_ptr<cmCompiledGeneratorExpression> outputName, 914 std::unique_ptr<cmCompiledGeneratorExpression> condition, 915 const std::string& newLineCharacter, mode_t permissions, 916 bool inputIsContent); 917 const std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>& 918 GetEvaluationFiles() const; 919 920 std::vector<std::unique_ptr<cmExportBuildFileGenerator>> const& 921 GetExportBuildFileGenerators() const; 922 void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen); 923 void AddExportBuildFileGenerator( 924 std::unique_ptr<cmExportBuildFileGenerator> gen); 925 926 // Maintain a stack of package roots to allow nested PACKAGE_ROOT_PATH 927 // searches 928 std::deque<std::vector<std::string>> FindPackageRootPathStack; 929 930 void MaybeWarnCMP0074(std::string const& pkg); 931 void MaybeWarnUninitialized(std::string const& variable, 932 const char* sourceFilename) const; 933 bool IsProjectFile(const char* filename) const; 934 935 int GetRecursionDepth() const; 936 void SetRecursionDepth(int recursionDepth); 937 938 std::string NewDeferId() const; 939 bool DeferCall(std::string id, std::string fileName, cmListFileFunction lff); 940 bool DeferCancelCall(std::string const& id); 941 cm::optional<std::string> DeferGetCallIds() const; 942 cm::optional<std::string> DeferGetCall(std::string const& id) const; 943 944 protected: 945 // add link libraries and directories to the target 946 void AddGlobalLinkInformation(cmTarget& target); 947 948 mutable std::set<cmListFileContext> CMP0054ReportedIds; 949 950 // libraries, classes, and executables 951 mutable cmTargetMap Targets; 952 std::map<std::string, std::string> AliasTargets; 953 954 std::vector<cmTarget*> OrderedTargets; 955 956 std::vector<std::unique_ptr<cmSourceFile>> SourceFiles; 957 958 // Because cmSourceFile names are compared in a fuzzy way (see 959 // cmSourceFileLocation::Match()) we can't have a straight mapping from 960 // filename to cmSourceFile. To make lookups more efficient we store the 961 // Name portion of the cmSourceFileLocation and then compare on the list of 962 // cmSourceFiles that might match that name. Note that on platforms which 963 // have a case-insensitive filesystem we store the key in all lowercase. 964 using SourceFileMap = 965 std::unordered_map<std::string, std::vector<cmSourceFile*>>; 966 SourceFileMap SourceFileSearchIndex; 967 968 // For "Known" paths we can store a direct filename to cmSourceFile map 969 std::unordered_map<std::string, cmSourceFile*> KnownFileSearchIndex; 970 971 // Tests 972 std::map<std::string, std::unique_ptr<cmTest>> Tests; 973 974 // The set of include directories that are marked as system include 975 // directories. 976 std::set<std::string> SystemIncludeDirectories; 977 978 std::vector<std::string> ListFiles; 979 std::vector<std::string> OutputFiles; 980 981 std::vector<std::unique_ptr<cmInstallGenerator>> InstallGenerators; 982 std::vector<std::unique_ptr<cmTestGenerator>> TestGenerators; 983 984 std::string ComplainFileRegularExpression; 985 std::string DefineFlags; 986 987 // Track the value of the computed DEFINITIONS property. 988 std::string DefineFlagsOrig; 989 990 #if !defined(CMAKE_BOOTSTRAP) 991 std::vector<cmSourceGroup> SourceGroups; 992 size_t ObjectLibrariesSourceGroupIndex; 993 #endif 994 995 cmGlobalGenerator* GlobalGenerator; 996 bool IsFunctionBlocked(const cmListFileFunction& lff, 997 cmExecutionStatus& status); 998 999 private: 1000 cmStateSnapshot StateSnapshot; 1001 cmListFileBacktrace Backtrace; 1002 int RecursionDepth; 1003 1004 struct DeferCommand 1005 { 1006 // Id is empty for an already-executed or canceled operation. 1007 std::string Id; 1008 std::string FilePath; 1009 cmListFileFunction Command; 1010 }; 1011 struct DeferCommands 1012 { 1013 std::vector<DeferCommand> Commands; 1014 }; 1015 std::unique_ptr<DeferCommands> Defer; 1016 bool DeferRunning = false; 1017 1018 void DoGenerate(cmLocalGenerator& lg); 1019 1020 void RunListFile(cmListFile const& listFile, 1021 const std::string& filenametoread, 1022 DeferCommands* defer = nullptr); 1023 1024 bool ParseDefineFlag(std::string const& definition, bool remove); 1025 1026 bool EnforceUniqueDir(const std::string& srcPath, 1027 const std::string& binPath) const; 1028 1029 std::function<void()> ExecuteCommandCallback; 1030 using FunctionBlockerPtr = std::unique_ptr<cmFunctionBlocker>; 1031 using FunctionBlockersType = 1032 std::stack<FunctionBlockerPtr, std::vector<FunctionBlockerPtr>>; 1033 FunctionBlockersType FunctionBlockers; 1034 std::vector<FunctionBlockersType::size_type> FunctionBlockerBarriers; 1035 void PushFunctionBlockerBarrier(); 1036 void PopFunctionBlockerBarrier(bool reportError = true); 1037 1038 std::stack<int> LoopBlockCounter; 1039 1040 mutable cmsys::RegularExpression cmDefineRegex; 1041 mutable cmsys::RegularExpression cmDefine01Regex; 1042 mutable cmsys::RegularExpression cmAtVarRegex; 1043 mutable cmsys::RegularExpression cmNamedCurly; 1044 1045 std::vector<cmMakefile*> UnConfiguredDirectories; 1046 std::vector<std::unique_ptr<cmExportBuildFileGenerator>> 1047 ExportBuildFileGenerators; 1048 1049 std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>> 1050 EvaluationFiles; 1051 1052 std::vector<cmExecutionStatus*> ExecutionStatusStack; 1053 friend class cmMakefileCall; 1054 friend class cmParseFileScope; 1055 1056 std::vector<std::unique_ptr<cmTarget>> ImportedTargetsOwned; 1057 using TargetMap = std::unordered_map<std::string, cmTarget*>; 1058 TargetMap ImportedTargets; 1059 1060 // Internal policy stack management. 1061 void PushPolicy(bool weak = false, 1062 cmPolicies::PolicyMap const& pm = cmPolicies::PolicyMap()); 1063 void PopPolicy(); 1064 void PopSnapshot(bool reportError = true); 1065 friend bool cmCMakePolicyCommand(std::vector<std::string> const& args, 1066 cmExecutionStatus& status); 1067 class IncludeScope; 1068 friend class IncludeScope; 1069 1070 class ListFileScope; 1071 friend class ListFileScope; 1072 1073 class DeferScope; 1074 friend class DeferScope; 1075 1076 class DeferCallScope; 1077 friend class DeferCallScope; 1078 1079 class BuildsystemFileScope; 1080 friend class BuildsystemFileScope; 1081 1082 // CMP0053 == old 1083 MessageType ExpandVariablesInStringOld(std::string& errorstr, 1084 std::string& source, 1085 bool escapeQuotes, bool noEscapes, 1086 bool atOnly, const char* filename, 1087 long line, bool removeEmpty, 1088 bool replaceAt) const; 1089 // CMP0053 == new 1090 MessageType ExpandVariablesInStringNew(std::string& errorstr, 1091 std::string& source, 1092 bool escapeQuotes, bool noEscapes, 1093 bool atOnly, const char* filename, 1094 long line, bool replaceAt) const; 1095 1096 bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const; 1097 1098 void CreateGeneratedOutputs(const std::vector<std::string>& outputs); 1099 1100 std::vector<BT<GeneratorAction>> GeneratorActions; 1101 bool GeneratorActionsInvoked = false; 1102 1103 bool CheckSystemVars; 1104 bool CheckCMP0000; 1105 std::set<std::string> WarnedCMP0074; 1106 bool IsSourceFileTryCompile; 1107 mutable bool SuppressSideEffects; 1108 }; 1109