diff options
Diffstat (limited to 'Source')
28 files changed, 504 insertions, 619 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index fe40af3..b1f4ca5 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -532,6 +532,8 @@ set(SRCS cmFindProgramCommand.h cmForEachCommand.cxx cmForEachCommand.h + cmFunctionBlocker.cxx + cmFunctionBlocker.h cmFunctionCommand.cxx cmFunctionCommand.h cmGetCMakePropertyCommand.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 22f9369..e6d5e9d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 15) -set(CMake_VERSION_PATCH 20190802) +set(CMake_VERSION_PATCH 20190806) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 7a5b8d1..f8d9f1b 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -24,7 +24,6 @@ #include "cmCTestUploadCommand.h" #include "cmCommand.h" #include "cmDuration.h" -#include "cmFunctionBlocker.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -49,32 +48,8 @@ # include <unistd.h> #endif -class cmExecutionStatus; -struct cmListFileFunction; - #define CTEST_INITIAL_CMAKE_OUTPUT_FILE_NAME "CTestInitialCMakeOutput.log" -// used to keep elapsed time up to date -class cmCTestScriptFunctionBlocker : public cmFunctionBlocker -{ -public: - bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, - cmExecutionStatus& /*status*/) override; - // virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf); - // virtual void ScopeEnded(cmMakefile &mf); - - cmCTestScriptHandler* CTestScriptHandler; -}; - -// simply update the time and don't block anything -bool cmCTestScriptFunctionBlocker::IsFunctionBlocked( - const cmListFileFunction& /*lff*/, cmMakefile& /*mf*/, - cmExecutionStatus& /*status*/) -{ - this->CTestScriptHandler->UpdateElapsedTime(); - return false; -} - cmCTestScriptHandler::cmCTestScriptHandler() { this->Backup = false; @@ -373,12 +348,8 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) this->Makefile->AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0"); #endif - // always add a function blocker to update the elapsed time - { - auto fb = cm::make_unique<cmCTestScriptFunctionBlocker>(); - fb->CTestScriptHandler = this; - this->Makefile->AddFunctionBlocker(std::move(fb)); - } + // set a callback function to update the elapsed time + this->Makefile->OnExecuteCommand([this] { this->UpdateElapsedTime(); }); /* Execute CTestScriptMode.cmake, which loads CMakeDetermineSystem and CMakeSystemSpecificInformation, so diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 78cddf0..5f46631 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -990,11 +990,6 @@ void cmComputeLinkInformation::AddTargetItem(std::string const& item, return; } - // If this platform wants a flag before the full path, add it. - if (!this->LibLinkFileFlag.empty()) { - this->Items.emplace_back(this->LibLinkFileFlag, false); - } - // For compatibility with CMake 2.4 include the item's directory in // the linker search path. if (this->OldLinkDirMode && !target->IsFrameworkOnApple() && @@ -1057,11 +1052,6 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item) this->OldLinkDirItems.push_back(item); } - // If this platform wants a flag before the full path, add it. - if (!this->LibLinkFileFlag.empty()) { - this->Items.emplace_back(this->LibLinkFileFlag, false); - } - // Now add the full path to the library. this->Items.emplace_back(item, true); } diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 3be2c7f..784d3fa 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -56,6 +56,11 @@ public: std::string GetChrpathString() const; std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked() const; + std::string const& GetLibLinkFileFlag() const + { + return this->LibLinkFileFlag; + } + std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; } std::string GetRPathLinkString() const; diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index e9ee7f5..172897c 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -1144,12 +1144,9 @@ Json::Value Target::DumpInstallPrefix() Json::Value Target::DumpInstallDestinations() { Json::Value destinations = Json::arrayValue; - auto installGens = this->GT->Makefile->GetInstallGenerators(); - for (auto iGen : installGens) { - auto itGen = dynamic_cast<cmInstallTargetGenerator*>(iGen); - if (itGen != nullptr && itGen->GetTarget() == this->GT) { - destinations.append(this->DumpInstallDestination(itGen)); - } + auto installGens = this->GT->Target->GetInstallGenerators(); + for (auto itGen : installGens) { + destinations.append(this->DumpInstallDestination(itGen)); } return destinations; } diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 06dce2c..1d961be 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -8,16 +8,40 @@ #include <utility> #include "cm_memory.hxx" +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" #include "cmExecutionStatus.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" #include "cmSystemTools.h" +class cmForEachFunctionBlocker : public cmFunctionBlocker +{ +public: + cmForEachFunctionBlocker(cmMakefile* mf); + ~cmForEachFunctionBlocker() override; + + cm::string_view StartCommandName() const override { return "foreach"_s; } + cm::string_view EndCommandName() const override { return "endforeach"_s; } + + bool ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const override; + + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) override; + + std::vector<std::string> Args; + +private: + cmMakefile* Makefile; +}; + cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf) : Makefile(mf) - , Depth(0) { this->Makefile->PushLoopBlock(); } @@ -27,89 +51,58 @@ cmForEachFunctionBlocker::~cmForEachFunctionBlocker() this->Makefile->PopLoopBlock(); } -bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, - cmMakefile& mf, - cmExecutionStatus& inStatus) +bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const { - if (lff.Name.Lower == "foreach") { - // record the number of nested foreach commands - this->Depth++; - } else if (lff.Name.Lower == "endforeach") { - // if this is the endofreach for this statement - if (!this->Depth) { - // Remove the function blocker for this scope or bail. - std::unique_ptr<cmFunctionBlocker> fb( - mf.RemoveFunctionBlocker(this, lff)); - if (!fb) { - return false; - } + std::vector<std::string> expandedArguments; + mf.ExpandArguments(lff.Arguments, expandedArguments); + return expandedArguments.empty() || expandedArguments[0] == this->Args[0]; +} - // at end of for each execute recorded commands - // store the old value - std::string oldDef; - if (mf.GetDefinition(this->Args[0])) { - oldDef = mf.GetDefinition(this->Args[0]); - } +bool cmForEachFunctionBlocker::Replay( + std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus) +{ + cmMakefile& mf = inStatus.GetMakefile(); + // at end of for each execute recorded commands + // store the old value + std::string oldDef; + if (mf.GetDefinition(this->Args[0])) { + oldDef = mf.GetDefinition(this->Args[0]); + } - for (std::string const& arg : cmMakeRange(this->Args).advance(1)) { - // set the variable to the loop value - mf.AddDefinition(this->Args[0], arg); - // Invoke all the functions that were collected in the block. - cmExecutionStatus status(mf); - for (cmListFileFunction const& func : this->Functions) { - status.Clear(); - mf.ExecuteCommand(func, status); - if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef); - return true; - } - if (status.GetBreakInvoked()) { - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef); - return true; - } - if (status.GetContinueInvoked()) { - break; - } - if (cmSystemTools::GetFatalErrorOccured()) { - return true; - } - } + for (std::string const& arg : cmMakeRange(this->Args).advance(1)) { + // set the variable to the loop value + mf.AddDefinition(this->Args[0], arg); + // Invoke all the functions that were collected in the block. + cmExecutionStatus status(mf); + for (cmListFileFunction const& func : functions) { + status.Clear(); + mf.ExecuteCommand(func, status); + if (status.GetReturnInvoked()) { + inStatus.SetReturnInvoked(); + // restore the variable to its prior value + mf.AddDefinition(this->Args[0], oldDef); + return true; + } + if (status.GetBreakInvoked()) { + // restore the variable to its prior value + mf.AddDefinition(this->Args[0], oldDef); + return true; + } + if (status.GetContinueInvoked()) { + break; + } + if (cmSystemTools::GetFatalErrorOccured()) { + return true; } - - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef); - return true; } - // close out a nested foreach - this->Depth--; } - // record the command - this->Functions.push_back(lff); - - // always return true + // restore the variable to its prior value + mf.AddDefinition(this->Args[0], oldDef); return true; } -bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, - cmMakefile& mf) -{ - if (lff.Name.Lower == "endforeach") { - std::vector<std::string> expandedArguments; - mf.ExpandArguments(lff.Arguments, expandedArguments); - // if the endforeach has arguments then make sure - // they match the begin foreach arguments - if ((expandedArguments.empty() || - (expandedArguments[0] == this->Args[0]))) { - return true; - } - } - return false; -} - bool cmForEachCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus&) { diff --git a/Source/cmForEachCommand.h b/Source/cmForEachCommand.h index cd112b8..135abf0 100644 --- a/Source/cmForEachCommand.h +++ b/Source/cmForEachCommand.h @@ -11,28 +11,8 @@ #include "cm_memory.hxx" #include "cmCommand.h" -#include "cmFunctionBlocker.h" -#include "cmListFileCache.h" class cmExecutionStatus; -class cmMakefile; - -class cmForEachFunctionBlocker : public cmFunctionBlocker -{ -public: - cmForEachFunctionBlocker(cmMakefile* mf); - ~cmForEachFunctionBlocker() override; - bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, - cmExecutionStatus&) override; - bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override; - - std::vector<std::string> Args; - std::vector<cmListFileFunction> Functions; - -private: - cmMakefile* Makefile; - int Depth; -}; /// Starts foreach() ... endforeach() block class cmForEachCommand : public cmCommand diff --git a/Source/cmFunctionBlocker.cxx b/Source/cmFunctionBlocker.cxx new file mode 100644 index 0000000..5778a71 --- /dev/null +++ b/Source/cmFunctionBlocker.cxx @@ -0,0 +1,46 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFunctionBlocker.h" + +#include <cassert> +#include <sstream> +#include <utility> + +#include "cmExecutionStatus.h" +#include "cmMakefile.h" +#include "cmMessageType.h" + +bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, + cmExecutionStatus& status) +{ + if (lff.Name.Lower == this->StartCommandName()) { + this->ScopeDepth++; + } else if (lff.Name.Lower == this->EndCommandName()) { + this->ScopeDepth--; + if (this->ScopeDepth == 0U) { + cmMakefile& mf = status.GetMakefile(); + auto self = mf.RemoveFunctionBlocker(); + assert(self.get() == this); + + if (!this->ArgumentsMatch(lff, mf)) { + cmListFileContext const& lfc = this->GetStartingContext(); + cmListFileContext closingContext = + cmListFileContext::FromCommandContext(lff, lfc.FilePath); + std::ostringstream e; + /* clang-format off */ + e << "A logical block opening on the line\n" + << " " << lfc << "\n" + << "closes on the line\n" + << " " << closingContext << "\n" + << "with mis-matching arguments."; + /* clang-format on */ + mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + } + + return this->Replay(std::move(this->Functions), status); + } + } + + this->Functions.push_back(lff); + return true; +} diff --git a/Source/cmFunctionBlocker.h b/Source/cmFunctionBlocker.h index cd6b05d..87bdccd 100644 --- a/Source/cmFunctionBlocker.h +++ b/Source/cmFunctionBlocker.h @@ -3,6 +3,12 @@ #ifndef cmFunctionBlocker_h #define cmFunctionBlocker_h +#include "cmConfigure.h" // IWYU pragma: keep + +#include <vector> + +#include "cm_string_view.hxx" + #include "cmListFileCache.h" class cmExecutionStatus; @@ -14,17 +20,8 @@ public: /** * should a function be blocked */ - virtual bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, - cmExecutionStatus& status) = 0; - - /** - * should this function blocker be removed, useful when one function adds a - * blocker and another must remove it - */ - virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile&) - { - return false; - } + bool IsFunctionBlocked(cmListFileFunction const& lff, + cmExecutionStatus& status); virtual ~cmFunctionBlocker() = default; @@ -39,7 +36,19 @@ public: } private: + virtual cm::string_view StartCommandName() const = 0; + virtual cm::string_view EndCommandName() const = 0; + + virtual bool ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const = 0; + + virtual bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& status) = 0; + +private: cmListFileContext StartingContext; + std::vector<cmListFileFunction> Functions; + unsigned int ScopeDepth = 1; }; #endif diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index 2809cf7..610f516 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -5,8 +5,13 @@ #include <sstream> #include <utility> +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" + #include "cmAlgorithms.h" #include "cmExecutionStatus.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmPolicies.h" #include "cmRange.h" @@ -102,53 +107,42 @@ bool cmFunctionHelperCommand::operator()( return true; } -bool cmFunctionFunctionBlocker::IsFunctionBlocked( - const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus&) +class cmFunctionFunctionBlocker : public cmFunctionBlocker { - // record commands until we hit the ENDFUNCTION - // at the ENDFUNCTION call we shift gears and start looking for invocations - if (lff.Name.Lower == "function") { - this->Depth++; - } else if (lff.Name.Lower == "endfunction") { - // if this is the endfunction for this function then execute - if (!this->Depth) { - // create a new command and add it to cmake - cmFunctionHelperCommand f; - f.Args = this->Args; - f.Functions = this->Functions; - f.FilePath = this->GetStartingContext().FilePath; - mf.RecordPolicies(f.Policies); - mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f)); - // remove the function blocker now that the function is defined - mf.RemoveFunctionBlocker(this, lff); - return true; - } - // decrement for each nested function that ends - this->Depth--; - } +public: + cm::string_view StartCommandName() const override { return "function"_s; } + cm::string_view EndCommandName() const override { return "endfunction"_s; } - // if it wasn't an endfunction and we are not executing then we must be - // recording - this->Functions.push_back(lff); - return true; -} + bool ArgumentsMatch(cmListFileFunction const&, + cmMakefile& mf) const override; -bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, - cmMakefile& mf) + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& status) override; + + std::vector<std::string> Args; +}; + +bool cmFunctionFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const { - if (lff.Name.Lower == "endfunction") { - std::vector<std::string> expandedArguments; - mf.ExpandArguments(lff.Arguments, expandedArguments, - this->GetStartingContext().FilePath.c_str()); - // if the endfunction has arguments then make sure - // they match the ones in the opening function command - if ((expandedArguments.empty() || - (expandedArguments[0] == this->Args[0]))) { - return true; - } - } + std::vector<std::string> expandedArguments; + mf.ExpandArguments(lff.Arguments, expandedArguments, + this->GetStartingContext().FilePath.c_str()); + return expandedArguments.empty() || expandedArguments[0] == this->Args[0]; +} - return false; +bool cmFunctionFunctionBlocker::Replay( + std::vector<cmListFileFunction> functions, cmExecutionStatus& status) +{ + cmMakefile& mf = status.GetMakefile(); + // create a new command and add it to cmake + cmFunctionHelperCommand f; + f.Args = this->Args; + f.Functions = std::move(functions); + f.FilePath = this->GetStartingContext().FilePath; + mf.RecordPolicies(f.Policies); + mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f)); + return true; } bool cmFunctionCommand::InitialPass(std::vector<std::string> const& args, diff --git a/Source/cmFunctionCommand.h b/Source/cmFunctionCommand.h index 449a180..b334525 100644 --- a/Source/cmFunctionCommand.h +++ b/Source/cmFunctionCommand.h @@ -11,23 +11,8 @@ #include "cm_memory.hxx" #include "cmCommand.h" -#include "cmFunctionBlocker.h" -#include "cmListFileCache.h" class cmExecutionStatus; -class cmMakefile; - -class cmFunctionFunctionBlocker : public cmFunctionBlocker -{ -public: - bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf, - cmExecutionStatus&) override; - bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override; - - std::vector<std::string> Args; - std::vector<cmListFileFunction> Functions; - int Depth = 0; -}; /// Starts function() ... endfunction() block class cmFunctionCommand : public cmCommand diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 7340bc2..d9e5e71 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -5219,7 +5219,7 @@ void cmGeneratorTarget::ComputeLinkInterface( const std::string& config, cmOptionalLinkInterface& iface, cmGeneratorTarget const* headTarget) const { - if (iface.ExplicitLibraries) { + if (iface.Explicit) { if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->GetType() == cmStateEnums::STATIC_LIBRARY || this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { @@ -5603,8 +5603,9 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // libraries and executables that export symbols. const char* explicitLibraries = nullptr; std::string linkIfaceProp; - if (this->GetPolicyStatusCMP0022() != cmPolicies::OLD && - this->GetPolicyStatusCMP0022() != cmPolicies::WARN) { + bool const cmp0022NEW = (this->GetPolicyStatusCMP0022() != cmPolicies::OLD && + this->GetPolicyStatusCMP0022() != cmPolicies::WARN); + if (cmp0022NEW) { // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES. linkIfaceProp = "INTERFACE_LINK_LIBRARIES"; explicitLibraries = this->GetProperty(linkIfaceProp); @@ -5659,15 +5660,14 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( return; } iface.Exists = true; - iface.ExplicitLibraries = explicitLibraries; + iface.Explicit = cmp0022NEW || explicitLibraries != nullptr; if (explicitLibraries) { // The interface libraries have been explicitly set. this->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, headTarget, usage_requirements_only, iface.Libraries, iface.HadHeadSensitiveCondition); - } else if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN || - this->GetPolicyStatusCMP0022() == cmPolicies::OLD) + } else if (!cmp0022NEW) // If CMP0022 is NEW then the plain tll signature sets the // INTERFACE_LINK_LIBRARIES, so if we get here then the project // cleared the property explicitly and we should not fall back diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 385022c..c5cfd8c 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -3,10 +3,14 @@ #include "cmIfCommand.h" #include "cm_memory.hxx" +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" #include "cmConditionEvaluator.h" #include "cmExecutionStatus.h" #include "cmExpandedCommandArgument.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmOutputConverter.h" @@ -28,152 +32,138 @@ static std::string cmIfCommandError( return err; } -//========================================================================= -bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, - cmMakefile& mf, - cmExecutionStatus& inStatus) +class cmIfFunctionBlocker : public cmFunctionBlocker { - // we start by recording all the functions - if (lff.Name.Lower == "if") { - this->ScopeDepth++; - } else if (lff.Name.Lower == "endif") { - this->ScopeDepth--; - // if this is the endif for this if statement, then start executing - if (!this->ScopeDepth) { - // Remove the function blocker for this scope or bail. - std::unique_ptr<cmFunctionBlocker> fb( - mf.RemoveFunctionBlocker(this, lff)); - if (!fb) { - return false; +public: + cm::string_view StartCommandName() const override { return "if"_s; } + cm::string_view EndCommandName() const override { return "endif"_s; } + + bool ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile&) const override; + + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) override; + + std::vector<cmListFileArgument> Args; + bool IsBlocking; + bool HasRun = false; + bool ElseSeen = false; +}; + +bool cmIfFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile&) const +{ + return lff.Arguments.empty() || lff.Arguments == this->Args; +} + +bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) +{ + cmMakefile& mf = inStatus.GetMakefile(); + // execute the functions for the true parts of the if statement + cmExecutionStatus status(mf); + int scopeDepth = 0; + for (cmListFileFunction const& func : functions) { + // keep track of scope depth + if (func.Name.Lower == "if") { + scopeDepth++; + } + if (func.Name.Lower == "endif") { + scopeDepth--; + } + // watch for our state change + if (scopeDepth == 0 && func.Name.Lower == "else") { + + if (this->ElseSeen) { + cmListFileBacktrace bt = mf.GetBacktrace(func); + mf.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + "A duplicate ELSE command was found inside an IF block.", bt); + cmSystemTools::SetFatalErrorOccured(); + return true; } - // execute the functions for the true parts of the if statement - cmExecutionStatus status(mf); - int scopeDepth = 0; - for (cmListFileFunction const& func : this->Functions) { - // keep track of scope depth - if (func.Name.Lower == "if") { - scopeDepth++; - } - if (func.Name.Lower == "endif") { - scopeDepth--; + this->IsBlocking = this->HasRun; + this->HasRun = true; + this->ElseSeen = true; + + // if trace is enabled, print a (trivially) evaluated "else" + // statement + if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) { + mf.PrintCommandTrace(func); + } + } else if (scopeDepth == 0 && func.Name.Lower == "elseif") { + if (this->ElseSeen) { + cmListFileBacktrace bt = mf.GetBacktrace(func); + mf.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + "An ELSEIF command was found after an ELSE command.", bt); + cmSystemTools::SetFatalErrorOccured(); + return true; + } + + if (this->HasRun) { + this->IsBlocking = true; + } else { + // if trace is enabled, print the evaluated "elseif" statement + if (mf.GetCMakeInstance()->GetTrace()) { + mf.PrintCommandTrace(func); } - // watch for our state change - if (scopeDepth == 0 && func.Name.Lower == "else") { - - if (this->ElseSeen) { - cmListFileBacktrace bt = mf.GetBacktrace(func); - mf.GetCMakeInstance()->IssueMessage( - MessageType::FATAL_ERROR, - "A duplicate ELSE command was found inside an IF block.", bt); - cmSystemTools::SetFatalErrorOccured(); - return true; - } - this->IsBlocking = this->HasRun; - this->HasRun = true; - this->ElseSeen = true; + std::string errorString; - // if trace is enabled, print a (trivially) evaluated "else" - // statement - if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) { - mf.PrintCommandTrace(func); - } - } else if (scopeDepth == 0 && func.Name.Lower == "elseif") { - if (this->ElseSeen) { - cmListFileBacktrace bt = mf.GetBacktrace(func); - mf.GetCMakeInstance()->IssueMessage( - MessageType::FATAL_ERROR, - "An ELSEIF command was found after an ELSE command.", bt); + std::vector<cmExpandedCommandArgument> expandedArguments; + mf.ExpandArguments(func.Arguments, expandedArguments); + + MessageType messType; + + cmListFileContext conditionContext = + cmListFileContext::FromCommandContext( + func, this->GetStartingContext().FilePath); + + cmConditionEvaluator conditionEvaluator(mf, conditionContext, + mf.GetBacktrace(func)); + + bool isTrue = + conditionEvaluator.IsTrue(expandedArguments, errorString, messType); + + if (!errorString.empty()) { + std::string err = cmIfCommandError(expandedArguments); + err += errorString; + cmListFileBacktrace bt = mf.GetBacktrace(func); + mf.GetCMakeInstance()->IssueMessage(messType, err, bt); + if (messType == MessageType::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); return true; } - - if (this->HasRun) { - this->IsBlocking = true; - } else { - // if trace is enabled, print the evaluated "elseif" statement - if (mf.GetCMakeInstance()->GetTrace()) { - mf.PrintCommandTrace(func); - } - - std::string errorString; - - std::vector<cmExpandedCommandArgument> expandedArguments; - mf.ExpandArguments(func.Arguments, expandedArguments); - - MessageType messType; - - cmListFileContext conditionContext = - cmListFileContext::FromCommandContext( - func, this->GetStartingContext().FilePath); - - cmConditionEvaluator conditionEvaluator(mf, conditionContext, - mf.GetBacktrace(func)); - - bool isTrue = conditionEvaluator.IsTrue(expandedArguments, - errorString, messType); - - if (!errorString.empty()) { - std::string err = cmIfCommandError(expandedArguments); - err += errorString; - cmListFileBacktrace bt = mf.GetBacktrace(func); - mf.GetCMakeInstance()->IssueMessage(messType, err, bt); - if (messType == MessageType::FATAL_ERROR) { - cmSystemTools::SetFatalErrorOccured(); - return true; - } - } - - if (isTrue) { - this->IsBlocking = false; - this->HasRun = true; - } - } } - // should we execute? - else if (!this->IsBlocking) { - status.Clear(); - mf.ExecuteCommand(func, status); - if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); - return true; - } - if (status.GetBreakInvoked()) { - inStatus.SetBreakInvoked(); - return true; - } - if (status.GetContinueInvoked()) { - inStatus.SetContinueInvoked(); - return true; - } + if (isTrue) { + this->IsBlocking = false; + this->HasRun = true; } } - return true; } - } - // record the command - this->Functions.push_back(lff); - - // always return true - return true; -} - -//========================================================================= -bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, - cmMakefile&) -{ - if (lff.Name.Lower == "endif") { - // if the endif has arguments, then make sure - // they match the arguments of the matching if - if (lff.Arguments.empty() || lff.Arguments == this->Args) { - return true; + // should we execute? + else if (!this->IsBlocking) { + status.Clear(); + mf.ExecuteCommand(func, status); + if (status.GetReturnInvoked()) { + inStatus.SetReturnInvoked(); + return true; + } + if (status.GetBreakInvoked()) { + inStatus.SetBreakInvoked(); + return true; + } + if (status.GetContinueInvoked()) { + inStatus.SetContinueInvoked(); + return true; + } } } - - return false; + return true; } //========================================================================= @@ -208,7 +198,6 @@ bool cmIfCommand(std::vector<cmListFileArgument> const& args, { auto fb = cm::make_unique<cmIfFunctionBlocker>(); // if is isn't true block the commands - fb->ScopeDepth = 1; fb->IsBlocking = !isTrue; if (isTrue) { fb->HasRun = true; diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h index 775e609..820ffa4 100644 --- a/Source/cmIfCommand.h +++ b/Source/cmIfCommand.h @@ -7,26 +7,8 @@ #include <vector> -#include "cmFunctionBlocker.h" -#include "cmListFileCache.h" - class cmExecutionStatus; -class cmMakefile; - -class cmIfFunctionBlocker : public cmFunctionBlocker -{ -public: - bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, - cmExecutionStatus&) override; - bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override; - - std::vector<cmListFileArgument> Args; - std::vector<cmListFileFunction> Functions; - bool IsBlocking; - bool HasRun = false; - bool ElseSeen = false; - unsigned int ScopeDepth = 0; -}; +struct cmListFileArgument; /// Starts an if block bool cmIfCommand(std::vector<cmListFileArgument> const& args, diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index aca7268..5349a9d 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -43,11 +43,13 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator( target.SetHaveInstallRule(true); const char* component = namelink ? args.GetNamelinkComponent().c_str() : args.GetComponent().c_str(); - return new cmInstallTargetGenerator( + auto g = new cmInstallTargetGenerator( target.GetName(), destination.c_str(), impLib, args.GetPermissions().c_str(), args.GetConfigurations(), component, message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt, backtrace); + target.AddInstallGenerator(g); + return g; } static cmInstallTargetGenerator* CreateInstallTargetGenerator( diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index 6450c62..d71ff49 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -87,7 +87,7 @@ struct cmOptionalLinkInterface : public cmLinkInterface bool LibrariesDone = false; bool AllDone = false; bool Exists = false; - const char* ExplicitLibraries = nullptr; + bool Explicit = false; }; struct cmHeadToLinkInterfaceMap diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 8746b35..4430f97 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -63,6 +63,7 @@ std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli) continue; } if (item.IsPath) { + linkLibs += cli.GetLibLinkFileFlag(); linkLibs += this->ConvertToOutputFormat(this->ConvertToLinkReference(item.Value)); } else { diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 1f2b5b2..8689c8f 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -7,9 +7,13 @@ #include <utility> #include "cm_memory.hxx" +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" #include "cmAlgorithms.h" #include "cmExecutionStatus.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmPolicies.h" #include "cmRange.h" @@ -136,55 +140,43 @@ bool cmMacroHelperCommand::operator()( return true; } -bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, - cmMakefile& mf, - cmExecutionStatus&) +class cmMacroFunctionBlocker : public cmFunctionBlocker { - // record commands until we hit the ENDMACRO - // at the ENDMACRO call we shift gears and start looking for invocations - if (lff.Name.Lower == "macro") { - this->Depth++; - } else if (lff.Name.Lower == "endmacro") { - // if this is the endmacro for this macro then execute - if (!this->Depth) { - mf.AppendProperty("MACROS", this->Args[0].c_str()); - // create a new command and add it to cmake - cmMacroHelperCommand f; - f.Args = this->Args; - f.Functions = this->Functions; - f.FilePath = this->GetStartingContext().FilePath; - mf.RecordPolicies(f.Policies); - mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f)); - // remove the function blocker now that the macro is defined - mf.RemoveFunctionBlocker(this, lff); - return true; - } - // decrement for each nested macro that ends - this->Depth--; - } +public: + cm::string_view StartCommandName() const override { return "macro"_s; } + cm::string_view EndCommandName() const override { return "endmacro"_s; } - // if it wasn't an endmacro and we are not executing then we must be - // recording - this->Functions.push_back(lff); - return true; -} + bool ArgumentsMatch(cmListFileFunction const&, + cmMakefile& mf) const override; + + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& status) override; + + std::vector<std::string> Args; +}; -bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, - cmMakefile& mf) +bool cmMacroFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const { - if (lff.Name.Lower == "endmacro") { - std::vector<std::string> expandedArguments; - mf.ExpandArguments(lff.Arguments, expandedArguments, - this->GetStartingContext().FilePath.c_str()); - // if the endmacro has arguments make sure they - // match the arguments of the macro - if ((expandedArguments.empty() || - (expandedArguments[0] == this->Args[0]))) { - return true; - } - } + std::vector<std::string> expandedArguments; + mf.ExpandArguments(lff.Arguments, expandedArguments, + this->GetStartingContext().FilePath.c_str()); + return expandedArguments.empty() || expandedArguments[0] == this->Args[0]; +} - return false; +bool cmMacroFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& status) +{ + cmMakefile& mf = status.GetMakefile(); + mf.AppendProperty("MACROS", this->Args[0].c_str()); + // create a new command and add it to cmake + cmMacroHelperCommand f; + f.Args = this->Args; + f.Functions = std::move(functions); + f.FilePath = this->GetStartingContext().FilePath; + mf.RecordPolicies(f.Policies); + mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f)); + return true; } bool cmMacroCommand::InitialPass(std::vector<std::string> const& args, diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h index 3ebd959..0d7083a 100644 --- a/Source/cmMacroCommand.h +++ b/Source/cmMacroCommand.h @@ -11,23 +11,8 @@ #include "cm_memory.hxx" #include "cmCommand.h" -#include "cmFunctionBlocker.h" -#include "cmListFileCache.h" class cmExecutionStatus; -class cmMakefile; - -class cmMacroFunctionBlocker : public cmFunctionBlocker -{ -public: - bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf, - cmExecutionStatus&) override; - bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override; - - std::vector<std::string> Args; - std::vector<cmListFileFunction> Functions; - int Depth = 0; -}; /// Starts macro() ... endmacro() block class cmMacroCommand : public cmCommand diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 8188ffa..015453a 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -353,6 +353,11 @@ private: cmMakefile* Makefile; }; +void cmMakefile::OnExecuteCommand(std::function<void()> callback) +{ + this->ExecuteCommandCallback = std::move(callback); +} + bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, cmExecutionStatus& status) { @@ -364,6 +369,10 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, return result; } + if (this->ExecuteCommandCallback) { + this->ExecuteCommandCallback(); + } + // Place this call on the call stack. cmMakefileCall stack_manager(this, lff, status); static_cast<void>(stack_manager); @@ -3061,7 +3070,7 @@ bool cmMakefile::IsFunctionBlocked(const cmListFileFunction& lff, return false; } - return this->FunctionBlockers.top()->IsFunctionBlocked(lff, *this, status); + return this->FunctionBlockers.top()->IsFunctionBlocked(lff, status); } void cmMakefile::PushFunctionBlockerBarrier() @@ -3211,30 +3220,12 @@ void cmMakefile::AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb) this->FunctionBlockers.push(std::move(fb)); } -std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker( - cmFunctionBlocker* fb, const cmListFileFunction& lff) +std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker() { assert(!this->FunctionBlockers.empty()); - assert(this->FunctionBlockers.top().get() == fb); assert(this->FunctionBlockerBarriers.empty() || this->FunctionBlockers.size() > this->FunctionBlockerBarriers.back()); - // Warn if the arguments do not match, but always remove. - if (!fb->ShouldRemove(lff, *this)) { - cmListFileContext const& lfc = fb->GetStartingContext(); - cmListFileContext closingContext = - cmListFileContext::FromCommandContext(lff, lfc.FilePath); - std::ostringstream e; - /* clang-format off */ - e << "A logical block opening on the line\n" - << " " << lfc << "\n" - << "closes on the line\n" - << " " << closingContext << "\n" - << "with mis-matching arguments."; - /* clang-format on */ - this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); - } - auto b = std::move(this->FunctionBlockers.top()); this->FunctionBlockers.pop(); return b; diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index dc196ac..4d61c05 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -107,8 +107,7 @@ public: * Remove the function blocker whose scope ends with the given command. * This returns ownership of the function blocker object. */ - std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker( - cmFunctionBlocker* fb, const cmListFileFunction& lff); + std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker(); /** * Try running cmake and building a file. This is used for dynalically @@ -628,6 +627,11 @@ public: void PrintCommandTrace(const cmListFileFunction& lff) const; /** + * Set a callback that is invoked whenever ExecuteCommand is called. + */ + void OnExecuteCommand(std::function<void()> callback); + + /** * Execute a single CMake command. Returns true if the command * succeeded or false if it failed. */ @@ -964,6 +968,7 @@ private: bool EnforceUniqueDir(const std::string& srcPath, const std::string& binPath) const; + std::function<void()> ExecuteCommandCallback; using FunctionBlockerPtr = std::unique_ptr<cmFunctionBlocker>; using FunctionBlockersType = std::stack<FunctionBlockerPtr, std::vector<FunctionBlockerPtr>>; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index beccfce..7ca2391 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -180,6 +180,7 @@ public: std::vector<cmCustomCommand> PreBuildCommands; std::vector<cmCustomCommand> PreLinkCommands; std::vector<cmCustomCommand> PostBuildCommands; + std::vector<cmInstallTargetGenerator*> InstallGenerators; std::set<std::string> SystemIncludeDirectories; cmTarget::LinkLibraryVectorType OriginalLinkLibraries; std::vector<std::string> IncludeDirectoriesEntries; @@ -873,6 +874,17 @@ void cmTarget::SetHaveInstallRule(bool hir) impl->HaveInstallRule = hir; } +void cmTarget::AddInstallGenerator(cmInstallTargetGenerator* g) +{ + impl->InstallGenerators.emplace_back(g); +} + +std::vector<cmInstallTargetGenerator*> const& cmTarget::GetInstallGenerators() + const +{ + return impl->InstallGenerators; +} + bool cmTarget::GetIsGeneratorProvided() const { return impl->IsGeneratorProvided; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 4e5141b..2b75879 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -21,6 +21,7 @@ class cmCustomCommand; class cmGlobalGenerator; +class cmInstallTargetGenerator; class cmMakefile; class cmMessenger; class cmPropertyMap; @@ -147,6 +148,9 @@ public: bool GetHaveInstallRule() const; void SetHaveInstallRule(bool hir); + void AddInstallGenerator(cmInstallTargetGenerator* g); + std::vector<cmInstallTargetGenerator*> const& GetInstallGenerators() const; + /** * Get/Set whether this target was auto-created by a generator. */ diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 37d1c74..a396852 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -3,10 +3,14 @@ #include "cmWhileCommand.h" #include "cm_memory.hxx" +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" #include "cmConditionEvaluator.h" #include "cmExecutionStatus.h" #include "cmExpandedCommandArgument.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmSystemTools.h" @@ -14,9 +18,29 @@ #include <string> #include <utility> +class cmWhileFunctionBlocker : public cmFunctionBlocker +{ +public: + cmWhileFunctionBlocker(cmMakefile* mf); + ~cmWhileFunctionBlocker() override; + + cm::string_view StartCommandName() const override { return "while"_s; } + cm::string_view EndCommandName() const override { return "endwhile"_s; } + + bool ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const override; + + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) override; + + std::vector<cmListFileArgument> Args; + +private: + cmMakefile* Makefile; +}; + cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf) : Makefile(mf) - , Depth(0) { this->Makefile->PushLoopBlock(); } @@ -26,108 +50,77 @@ cmWhileFunctionBlocker::~cmWhileFunctionBlocker() this->Makefile->PopLoopBlock(); } -bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, - cmMakefile& mf, - cmExecutionStatus& inStatus) +bool cmWhileFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile&) const { - // at end of for each execute recorded commands - if (lff.Name.Lower == "while") { - // record the number of while commands past this one - this->Depth++; - } else if (lff.Name.Lower == "endwhile") { - // if this is the endwhile for this while loop then execute - if (!this->Depth) { - // Remove the function blocker for this scope or bail. - std::unique_ptr<cmFunctionBlocker> fb( - mf.RemoveFunctionBlocker(this, lff)); - if (!fb) { - return false; - } + return lff.Arguments.empty() || lff.Arguments == this->Args; +} - std::string errorString; - - std::vector<cmExpandedCommandArgument> expandedArguments; - mf.ExpandArguments(this->Args, expandedArguments); - MessageType messageType; - - cmListFileContext execContext = this->GetStartingContext(); - - cmCommandContext commandContext; - commandContext.Line = execContext.Line; - commandContext.Name = execContext.Name; - - cmConditionEvaluator conditionEvaluator(mf, this->GetStartingContext(), - mf.GetBacktrace(commandContext)); - - bool isTrue = - conditionEvaluator.IsTrue(expandedArguments, errorString, messageType); - - while (isTrue) { - if (!errorString.empty()) { - std::string err = "had incorrect arguments: "; - for (cmListFileArgument const& arg : this->Args) { - err += (arg.Delim ? "\"" : ""); - err += arg.Value; - err += (arg.Delim ? "\"" : ""); - err += " "; - } - err += "("; - err += errorString; - err += ")."; - mf.IssueMessage(messageType, err); - if (messageType == MessageType::FATAL_ERROR) { - cmSystemTools::SetFatalErrorOccured(); - return true; - } - } - - // Invoke all the functions that were collected in the block. - for (cmListFileFunction const& fn : this->Functions) { - cmExecutionStatus status(mf); - mf.ExecuteCommand(fn, status); - if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); - return true; - } - if (status.GetBreakInvoked()) { - return true; - } - if (status.GetContinueInvoked()) { - break; - } - if (cmSystemTools::GetFatalErrorOccured()) { - return true; - } - } - expandedArguments.clear(); - mf.ExpandArguments(this->Args, expandedArguments); - isTrue = conditionEvaluator.IsTrue(expandedArguments, errorString, - messageType); - } - return true; - } - // decrement for each nested while that ends - this->Depth--; - } +bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) +{ + cmMakefile& mf = inStatus.GetMakefile(); + std::string errorString; - // record the command - this->Functions.push_back(lff); + std::vector<cmExpandedCommandArgument> expandedArguments; + mf.ExpandArguments(this->Args, expandedArguments); + MessageType messageType; - // always return true - return true; -} + cmListFileContext execContext = this->GetStartingContext(); -bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, - cmMakefile&) -{ - if (lff.Name.Lower == "endwhile") { - // if the endwhile has arguments, then make sure - // they match the arguments of the matching while - if (lff.Arguments.empty() || lff.Arguments == this->Args) { - return true; + cmCommandContext commandContext; + commandContext.Line = execContext.Line; + commandContext.Name = execContext.Name; + + cmConditionEvaluator conditionEvaluator(mf, this->GetStartingContext(), + mf.GetBacktrace(commandContext)); + + bool isTrue = + conditionEvaluator.IsTrue(expandedArguments, errorString, messageType); + + while (isTrue) { + if (!errorString.empty()) { + std::string err = "had incorrect arguments: "; + for (cmListFileArgument const& arg : this->Args) { + err += (arg.Delim ? "\"" : ""); + err += arg.Value; + err += (arg.Delim ? "\"" : ""); + err += " "; + } + err += "("; + err += errorString; + err += ")."; + mf.IssueMessage(messageType, err); + if (messageType == MessageType::FATAL_ERROR) { + cmSystemTools::SetFatalErrorOccured(); + return true; + } } + + // Invoke all the functions that were collected in the block. + for (cmListFileFunction const& fn : functions) { + cmExecutionStatus status(mf); + mf.ExecuteCommand(fn, status); + if (status.GetReturnInvoked()) { + inStatus.SetReturnInvoked(); + return true; + } + if (status.GetBreakInvoked()) { + return true; + } + if (status.GetContinueInvoked()) { + break; + } + if (cmSystemTools::GetFatalErrorOccured()) { + return true; + } + } + expandedArguments.clear(); + mf.ExpandArguments(this->Args, expandedArguments); + isTrue = + conditionEvaluator.IsTrue(expandedArguments, errorString, messageType); } - return false; + return true; } bool cmWhileCommand(std::vector<cmListFileArgument> const& args, diff --git a/Source/cmWhileCommand.h b/Source/cmWhileCommand.h index 2257799..beca652 100644 --- a/Source/cmWhileCommand.h +++ b/Source/cmWhileCommand.h @@ -7,28 +7,8 @@ #include <vector> -#include "cmFunctionBlocker.h" -#include "cmListFileCache.h" - class cmExecutionStatus; -class cmMakefile; - -class cmWhileFunctionBlocker : public cmFunctionBlocker -{ -public: - cmWhileFunctionBlocker(cmMakefile* mf); - ~cmWhileFunctionBlocker() override; - bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, - cmExecutionStatus&) override; - bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override; - - std::vector<cmListFileArgument> Args; - std::vector<cmListFileFunction> Functions; - -private: - cmMakefile* Makefile; - int Depth; -}; +struct cmListFileArgument; /// \brief Starts a while loop bool cmWhileCommand(std::vector<cmListFileArgument> const& args, diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 309efd3..a81b7e4 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -28,6 +28,7 @@ #include "cmUtils.hxx" #include "cmVersionConfig.h" #include "cmWorkingDirectory.h" +#include "cm_string_view.hxx" #include "cm_sys_stat.h" #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -132,22 +133,15 @@ static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, } cmake::cmake(Role role, cmState::Mode mode) + : FileTimeCache(cm::make_unique<cmFileTimeCache>()) +#ifdef CMAKE_BUILD_WITH_CMAKE + , VariableWatch(cm::make_unique<cmVariableWatch>()) +#endif + , State(cm::make_unique<cmState>()) + , Messenger(cm::make_unique<cmMessenger>()) { - this->Trace = false; - this->TraceExpand = false; - this->WarnUninitialized = false; - this->WarnUnused = false; - this->WarnUnusedCli = true; - this->CheckSystemVars = false; - this->DebugOutput = false; - this->DebugTryCompile = false; - this->ClearBuildSystem = false; - this->FileTimeCache = cm::make_unique<cmFileTimeCache>(); - - this->State = cm::make_unique<cmState>(); this->State->SetMode(mode); this->CurrentSnapshot = this->State->CreateBaseSnapshot(); - this->Messenger = cm::make_unique<cmMessenger>(); #ifdef __APPLE__ struct rlimit rlp; @@ -159,16 +153,6 @@ cmake::cmake(Role role, cmState::Mode mode) } #endif - this->GlobalGenerator = nullptr; - this->GeneratorInstanceSet = false; - this->GeneratorPlatformSet = false; - this->GeneratorToolsetSet = false; - this->CurrentWorkingMode = NORMAL_MODE; - -#ifdef CMAKE_BUILD_WITH_CMAKE - this->VariableWatch = cm::make_unique<cmVariableWatch>(); -#endif - this->AddDefaultGenerators(); this->AddDefaultExtraGenerators(); if (role == RoleScript || role == RoleProject) { @@ -188,32 +172,25 @@ cmake::cmake(Role role, cmState::Mode mode) // Set up a list of source and header extensions. // These are used to find files when the extension is not given. { - auto fillExts = [](FileExtensions& exts, - std::initializer_list<const char*> extList) { + auto setupExts = [](FileExtensions& exts, + std::initializer_list<cm::string_view> extList) { // Fill ordered vector exts.ordered.reserve(extList.size()); - for (const char* ext : extList) { + for (cm::string_view ext : extList) { exts.ordered.emplace_back(ext); }; // Fill unordered set exts.unordered.insert(exts.ordered.begin(), exts.ordered.end()); }; - // Source extensions // The "c" extension MUST precede the "C" extension. - fillExts(this->SourceFileExtensions, - { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "m", "M", "mm" }); - - // Header extensions - fillExts(this->HeaderFileExtensions, - { "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" }); - - // Cuda extensions - fillExts(this->CudaFileExtensions, { "cu" }); - - // Fortran extensions - fillExts(this->FortranFileExtensions, - { "f", "F", "for", "f77", "f90", "f95", "f03" }); + setupExts(this->SourceFileExtensions, + { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "m", "M", "mm" }); + setupExts(this->HeaderFileExtensions, + { "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" }); + setupExts(this->CudaFileExtensions, { "cu" }); + setupExts(this->FortranFileExtensions, + { "f", "F", "for", "f77", "f90", "f95", "f03" }); } } diff --git a/Source/cmake.h b/Source/cmake.h index 6aa00e1..92494ae 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -509,14 +509,14 @@ protected: void AddDefaultGenerators(); void AddDefaultExtraGenerators(); - cmGlobalGenerator* GlobalGenerator; + cmGlobalGenerator* GlobalGenerator = nullptr; std::map<std::string, DiagLevel> DiagLevels; std::string GeneratorInstance; std::string GeneratorPlatform; std::string GeneratorToolset; - bool GeneratorInstanceSet; - bool GeneratorPlatformSet; - bool GeneratorToolsetSet; + bool GeneratorInstanceSet = false; + bool GeneratorPlatformSet = false; + bool GeneratorToolsetSet = false; //! read in a cmake list file to initialize the cache void ReadListFile(const std::vector<std::string>& args, @@ -543,14 +543,14 @@ protected: private: ProgressCallbackType ProgressCallback; - WorkingMode CurrentWorkingMode; - bool DebugOutput; - bool Trace; - bool TraceExpand; - bool WarnUninitialized; - bool WarnUnused; - bool WarnUnusedCli; - bool CheckSystemVars; + WorkingMode CurrentWorkingMode = NORMAL_MODE; + bool DebugOutput = false; + bool Trace = false; + bool TraceExpand = false; + bool WarnUninitialized = false; + bool WarnUnused = false; + bool WarnUnusedCli = true; + bool CheckSystemVars = false; std::map<std::string, bool> UsedCliVariables; std::string CMakeEditCommand; std::string CXXEnvironment; @@ -564,8 +564,8 @@ private: FileExtensions HeaderFileExtensions; FileExtensions CudaFileExtensions; FileExtensions FortranFileExtensions; - bool ClearBuildSystem; - bool DebugTryCompile; + bool ClearBuildSystem = false; + bool DebugTryCompile = false; std::unique_ptr<cmFileTimeCache> FileTimeCache; std::string GraphVizFile; InstalledFilesMap InstalledFiles; |