diff options
Diffstat (limited to 'Source')
81 files changed, 1412 insertions, 1926 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 8ed7b2f..71a7dbd 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -168,6 +168,8 @@ set(SRCS cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h cmCacheManager.cxx cmCacheManager.h + cmCheckCustomOutputs.h + cmCheckCustomOutputs.cxx cmCLocaleEnvironmentScope.h cmCLocaleEnvironmentScope.cxx cmCommandArgumentParserHelper.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9a4f63e..d24c2c0 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 20190920) +set(CMake_VERSION_PATCH 20190925) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 02b00e3..ce690f9 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -9,6 +9,7 @@ #include "cmMessageType.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cm_static_string_view.hxx" #include "cmake.h" #include <cstring> @@ -16,17 +17,15 @@ class cmExecutionStatus; -cmCTestBuildCommand::cmCTestBuildCommand() +void cmCTestBuildCommand::BindArguments() { - this->GlobalGenerator = nullptr; - this->Arguments[ctb_NUMBER_ERRORS] = "NUMBER_ERRORS"; - this->Arguments[ctb_NUMBER_WARNINGS] = "NUMBER_WARNINGS"; - this->Arguments[ctb_TARGET] = "TARGET"; - this->Arguments[ctb_CONFIGURATION] = "CONFIGURATION"; - this->Arguments[ctb_FLAGS] = "FLAGS"; - this->Arguments[ctb_PROJECT_NAME] = "PROJECT_NAME"; - this->Arguments[ctb_LAST] = nullptr; - this->Last = ctb_LAST; + this->cmCTestHandlerCommand::BindArguments(); + this->Bind("NUMBER_ERRORS"_s, this->NumberErrors); + this->Bind("NUMBER_WARNINGS"_s, this->NumberWarnings); + this->Bind("TARGET"_s, this->Target); + this->Bind("CONFIGURATION"_s, this->Configuration); + this->Bind("FLAGS"_s, this->Flags); + this->Bind("PROJECT_NAME"_s, this->ProjectName); } cmCTestBuildCommand::~cmCTestBuildCommand() @@ -60,20 +59,17 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() // const char* ctestBuildConfiguration = this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION"); - const char* cmakeBuildConfiguration = - (this->Values[ctb_CONFIGURATION] && *this->Values[ctb_CONFIGURATION]) - ? this->Values[ctb_CONFIGURATION] + const char* cmakeBuildConfiguration = !this->Configuration.empty() + ? this->Configuration.c_str() : ((ctestBuildConfiguration && *ctestBuildConfiguration) ? ctestBuildConfiguration : this->CTest->GetConfigType().c_str()); - const char* cmakeBuildAdditionalFlags = - (this->Values[ctb_FLAGS] && *this->Values[ctb_FLAGS]) - ? this->Values[ctb_FLAGS] + const char* cmakeBuildAdditionalFlags = !this->Flags.empty() + ? this->Flags.c_str() : this->Makefile->GetDefinition("CTEST_BUILD_FLAGS"); - const char* cmakeBuildTarget = - (this->Values[ctb_TARGET] && *this->Values[ctb_TARGET]) - ? this->Values[ctb_TARGET] + const char* cmakeBuildTarget = !this->Target.empty() + ? this->Target.c_str() : this->Makefile->GetDefinition("CTEST_BUILD_TARGET"); if (cmakeGeneratorName && *cmakeGeneratorName) { @@ -153,16 +149,13 @@ bool cmCTestBuildCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) { bool ret = cmCTestHandlerCommand::InitialPass(args, status); - if (this->Values[ctb_NUMBER_ERRORS] && *this->Values[ctb_NUMBER_ERRORS]) { + if (!this->NumberErrors.empty()) { this->Makefile->AddDefinition( - this->Values[ctb_NUMBER_ERRORS], - std::to_string(this->Handler->GetTotalErrors())); + this->NumberErrors, std::to_string(this->Handler->GetTotalErrors())); } - if (this->Values[ctb_NUMBER_WARNINGS] && - *this->Values[ctb_NUMBER_WARNINGS]) { + if (!this->NumberWarnings.empty()) { this->Makefile->AddDefinition( - this->Values[ctb_NUMBER_WARNINGS], - std::to_string(this->Handler->GetTotalWarnings())); + this->NumberWarnings, std::to_string(this->Handler->GetTotalWarnings())); } return ret; } diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h index 14f70bf..791e1f0 100644 --- a/Source/CTest/cmCTestBuildCommand.h +++ b/Source/CTest/cmCTestBuildCommand.h @@ -27,7 +27,6 @@ class cmGlobalGenerator; class cmCTestBuildCommand : public cmCTestHandlerCommand { public: - cmCTestBuildCommand(); ~cmCTestBuildCommand() override; /** @@ -49,23 +48,19 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; - cmGlobalGenerator* GlobalGenerator; + cmGlobalGenerator* GlobalGenerator = nullptr; protected: cmCTestBuildHandler* Handler; - enum - { - ctb_BUILD = ct_LAST, - ctb_NUMBER_ERRORS, - ctb_NUMBER_WARNINGS, - ctb_TARGET, - ctb_CONFIGURATION, - ctb_FLAGS, - ctb_PROJECT_NAME, - ctb_LAST - }; - + void BindArguments() override; cmCTestGenericHandler* InitializeHandler() override; + + std::string NumberErrors; + std::string NumberWarnings; + std::string Target; + std::string Configuration; + std::string Flags; + std::string ProjectName; }; #endif diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index 8a56f3d..948b9fb 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -8,25 +8,25 @@ #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cm_static_string_view.hxx" #include "cmake.h" #include <cstring> #include <sstream> #include <vector> -cmCTestConfigureCommand::cmCTestConfigureCommand() +void cmCTestConfigureCommand::BindArguments() { - this->Arguments[ctc_OPTIONS] = "OPTIONS"; - this->Arguments[ctc_LAST] = nullptr; - this->Last = ctc_LAST; + this->cmCTestHandlerCommand::BindArguments(); + this->Bind("OPTIONS"_s, this->Options); } cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() { std::vector<std::string> options; - if (this->Values[ctc_OPTIONS]) { - cmExpandList(this->Values[ctc_OPTIONS], options); + if (!this->Options.empty()) { + cmExpandList(this->Options, options); } if (this->CTest->GetCTestConfiguration("BuildDirectory").empty()) { diff --git a/Source/CTest/cmCTestConfigureCommand.h b/Source/CTest/cmCTestConfigureCommand.h index 36ca7d5..0bc7848 100644 --- a/Source/CTest/cmCTestConfigureCommand.h +++ b/Source/CTest/cmCTestConfigureCommand.h @@ -23,8 +23,6 @@ class cmCTestGenericHandler; class cmCTestConfigureCommand : public cmCTestHandlerCommand { public: - cmCTestConfigureCommand(); - /** * This is a virtual constructor for the command. */ @@ -42,14 +40,10 @@ public: std::string GetName() const override { return "ctest_configure"; } protected: + void BindArguments() override; cmCTestGenericHandler* InitializeHandler() override; - enum - { - ctc_FIRST = ct_LAST, - ctc_OPTIONS, - ctc_LAST - }; + std::string Options; }; #endif diff --git a/Source/CTest/cmCTestCoverageCommand.cxx b/Source/CTest/cmCTestCoverageCommand.cxx index 07aae76..b66bba7 100644 --- a/Source/CTest/cmCTestCoverageCommand.cxx +++ b/Source/CTest/cmCTestCoverageCommand.cxx @@ -2,14 +2,26 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestCoverageCommand.h" +#include <set> + +#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestCoverageHandler.h" +#include "cm_static_string_view.hxx" class cmCTestGenericHandler; -cmCTestCoverageCommand::cmCTestCoverageCommand() +void cmCTestCoverageCommand::BindArguments() +{ + this->cmCTestHandlerCommand::BindArguments(); + this->Bind("LABELS"_s, this->Labels); +} + +void cmCTestCoverageCommand::CheckArguments( + std::vector<std::string> const& keywords) { - this->LabelsMentioned = false; + this->LabelsMentioned = + !this->Labels.empty() || cmContains(keywords, "LABELS"); } cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler() @@ -24,34 +36,10 @@ cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler() // If a LABELS option was given, select only files with the labels. if (this->LabelsMentioned) { - handler->SetLabelFilter(this->Labels); + handler->SetLabelFilter( + std::set<std::string>(this->Labels.begin(), this->Labels.end())); } handler->SetQuiet(this->Quiet); return handler; } - -bool cmCTestCoverageCommand::CheckArgumentKeyword(std::string const& arg) -{ - // Look for arguments specific to this command. - if (arg == "LABELS") { - this->ArgumentDoing = ArgumentDoingLabels; - this->LabelsMentioned = true; - return true; - } - - // Look for other arguments. - return this->Superclass::CheckArgumentKeyword(arg); -} - -bool cmCTestCoverageCommand::CheckArgumentValue(std::string const& arg) -{ - // Handle states specific to this command. - if (this->ArgumentDoing == ArgumentDoingLabels) { - this->Labels.insert(arg); - return true; - } - - // Look for other arguments. - return this->Superclass::CheckArgumentValue(arg); -} diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h index 75aefdf..fcffa75 100644 --- a/Source/CTest/cmCTestCoverageCommand.h +++ b/Source/CTest/cmCTestCoverageCommand.h @@ -8,9 +8,9 @@ #include "cmCTestHandlerCommand.h" #include "cmCommand.h" -#include <set> #include <string> #include <utility> +#include <vector> #include <cm/memory> @@ -24,8 +24,6 @@ class cmCTestGenericHandler; class cmCTestCoverageCommand : public cmCTestHandlerCommand { public: - cmCTestCoverageCommand(); - /** * This is a virtual constructor for the command. */ @@ -42,22 +40,13 @@ public: */ std::string GetName() const override { return "ctest_coverage"; } - using Superclass = cmCTestHandlerCommand; - protected: + void BindArguments() override; + void CheckArguments(std::vector<std::string> const& keywords) override; cmCTestGenericHandler* InitializeHandler() override; - bool CheckArgumentKeyword(std::string const& arg) override; - bool CheckArgumentValue(std::string const& arg) override; - - enum - { - ArgumentDoingLabels = Superclass::ArgumentDoingLast1, - ArgumentDoingLast2 - }; - bool LabelsMentioned; - std::set<std::string> Labels; + std::vector<std::string> Labels; }; #endif diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 9c5425d..3f9ce4e 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -7,31 +7,16 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" +#include "cm_static_string_view.hxx" +#include <algorithm> #include <cstdlib> #include <cstring> #include <sstream> -cmCTestHandlerCommand::cmCTestHandlerCommand() -{ - const size_t INIT_SIZE = 100; - size_t cc; - this->Arguments.reserve(INIT_SIZE); - for (cc = 0; cc < INIT_SIZE; ++cc) { - this->Arguments.push_back(nullptr); - } - this->Arguments[ct_RETURN_VALUE] = "RETURN_VALUE"; - this->Arguments[ct_CAPTURE_CMAKE_ERROR] = "CAPTURE_CMAKE_ERROR"; - this->Arguments[ct_SOURCE] = "SOURCE"; - this->Arguments[ct_BUILD] = "BUILD"; - this->Arguments[ct_SUBMIT_INDEX] = "SUBMIT_INDEX"; - this->Last = ct_LAST; - this->AppendXML = false; - this->Quiet = false; -} - namespace { // class to save and restore the error state for ctest_* commands // if a ctest_* command has a CAPTURE_CMAKE_ERROR then put the error @@ -90,30 +75,30 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, // save error state and restore it if needed SaveRestoreErrorState errorState; // Allocate space for argument values. - this->Values.clear(); - this->Values.resize(this->Last, nullptr); + this->BindArguments(); // Process input arguments. - this->ArgumentDoing = ArgumentDoingNone; - // look at all arguments and do not short circuit on the first - // bad one so that CAPTURE_CMAKE_ERROR can override setting the - // global error state - bool foundBadArgument = false; - for (std::string const& arg : args) { - // Check this argument. - if (!this->CheckArgumentKeyword(arg) && !this->CheckArgumentValue(arg)) { - std::ostringstream e; - e << "called with unknown argument \"" << arg << "\"."; - this->SetError(e.str()); - foundBadArgument = true; - } - // note bad argument - if (this->ArgumentDoing == ArgumentDoingError) { - foundBadArgument = true; - } + std::vector<std::string> unparsedArguments; + std::vector<std::string> keywordsMissingValue; + std::vector<std::string> parsedKeywords; + this->Parse(args, &unparsedArguments, &keywordsMissingValue, + &parsedKeywords); + this->CheckArguments(keywordsMissingValue); + + std::sort(parsedKeywords.begin(), parsedKeywords.end()); + auto it = std::adjacent_find(parsedKeywords.begin(), parsedKeywords.end()); + if (it != parsedKeywords.end()) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Called with more than one value for ", *it)); + } + + bool const foundBadArgument = !unparsedArguments.empty(); + if (foundBadArgument) { + this->SetError(cmStrCat("called with unknown argument \"", + unparsedArguments.front(), "\".")); } - bool captureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] && - *this->Values[ct_CAPTURE_CMAKE_ERROR]); + bool const captureCMakeError = !this->CaptureCMakeError.empty(); // now that arguments are parsed check to see if there is a // CAPTURE_CMAKE_ERROR specified let the errorState object know. if (captureCMakeError) { @@ -123,8 +108,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, if (foundBadArgument) { // store the cmake error if (captureCMakeError) { - this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], - "-1"); + this->Makefile->AddDefinition(this->CaptureCMakeError, "-1"); std::string const err = this->GetName() + " " + status.GetError(); if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) { cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n"); @@ -146,10 +130,9 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, this->CTest->SetConfigType(ctestConfigType); } - if (this->Values[ct_BUILD]) { + if (!this->Build.empty()) { this->CTest->SetCTestConfiguration( - "BuildDirectory", - cmSystemTools::CollapseFullPath(this->Values[ct_BUILD]).c_str(), + "BuildDirectory", cmSystemTools::CollapseFullPath(this->Build).c_str(), this->Quiet); } else { std::string const& bdir = @@ -163,13 +146,11 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, "CTEST_BINARY_DIRECTORY not set" << std::endl;); } } - if (this->Values[ct_SOURCE]) { + if (!this->Source.empty()) { cmCTestLog(this->CTest, DEBUG, - "Set source directory to: " << this->Values[ct_SOURCE] - << std::endl); + "Set source directory to: " << this->Source << std::endl); this->CTest->SetCTestConfiguration( - "SourceDirectory", - cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(), + "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(), this->Quiet); } else { this->CTest->SetCTestConfiguration( @@ -192,8 +173,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, "Cannot instantiate test handler " << this->GetName() << std::endl); if (captureCMakeError) { - this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], - "-1"); + this->Makefile->AddDefinition(this->CaptureCMakeError, "-1"); std::string const& err = status.GetError(); if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) { cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n"); @@ -203,11 +183,11 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, return false; } - handler->SetAppendXML(this->AppendXML); + handler->SetAppendXML(this->Append); handler->PopulateCustomVectors(this->Makefile); - if (this->Values[ct_SUBMIT_INDEX]) { - handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX])); + if (!this->SubmitIndex.empty()) { + handler->SetSubmitIndex(atoi(this->SubmitIndex.c_str())); } cmWorkingDirectory workdir( this->CTest->GetCTestConfiguration("BuildDirectory")); @@ -216,8 +196,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, this->CTest->GetCTestConfiguration("BuildDirectory") + " : " + std::strerror(workdir.GetLastResult())); if (captureCMakeError) { - this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], - "-1"); + this->Makefile->AddDefinition(this->CaptureCMakeError, "-1"); cmCTestLog(this->CTest, ERROR_MESSAGE, this->GetName() << " " << status.GetError() << "\n"); // return success because failure is recorded in CAPTURE_CMAKE_ERROR @@ -227,9 +206,8 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, } int res = handler->ProcessHandler(); - if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) { - this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE], - std::to_string(res)); + if (!this->ReturnValue.empty()) { + this->Makefile->AddDefinition(this->ReturnValue, std::to_string(res)); } this->ProcessAdditionalValues(handler); // log the error message if there was an error @@ -245,8 +223,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, } } // store the captured cmake error state 0 or -1 - this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], - returnString); + this->Makefile->AddDefinition(this->CaptureCMakeError, returnString); } return true; } @@ -255,47 +232,17 @@ void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*) { } -bool cmCTestHandlerCommand::CheckArgumentKeyword(std::string const& arg) +void cmCTestHandlerCommand::BindArguments() { - // Look for non-value arguments common to all commands. - if (arg == "APPEND") { - this->ArgumentDoing = ArgumentDoingNone; - this->AppendXML = true; - return true; - } - if (arg == "QUIET") { - this->ArgumentDoing = ArgumentDoingNone; - this->Quiet = true; - return true; - } - - // Check for a keyword in our argument/value table. - for (unsigned int k = 0; k < this->Arguments.size(); ++k) { - if (this->Arguments[k] && arg == this->Arguments[k]) { - this->ArgumentDoing = ArgumentDoingKeyword; - this->ArgumentIndex = k; - return true; - } - } - return false; + this->Bind("APPEND"_s, this->Append); + this->Bind("QUIET"_s, this->Quiet); + this->Bind("RETURN_VALUE"_s, this->ReturnValue); + this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError); + this->Bind("SOURCE"_s, this->Source); + this->Bind("BUILD"_s, this->Build); + this->Bind("SUBMIT_INDEX"_s, this->SubmitIndex); } -bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg) +void cmCTestHandlerCommand::CheckArguments(std::vector<std::string> const&) { - if (this->ArgumentDoing == ArgumentDoingKeyword) { - this->ArgumentDoing = ArgumentDoingNone; - unsigned int k = this->ArgumentIndex; - if (this->Values[k]) { - std::ostringstream e; - e << "Called with more than one value for " << this->Arguments[k]; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); - this->ArgumentDoing = ArgumentDoingError; - return true; - } - this->Values[k] = arg.c_str(); - cmCTestLog(this->CTest, DEBUG, - "Set " << this->Arguments[k] << " to " << arg << "\n"); - return true; - } - return false; } diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h index 79d61f3..5bbc569 100644 --- a/Source/CTest/cmCTestHandlerCommand.h +++ b/Source/CTest/cmCTestHandlerCommand.h @@ -5,9 +5,9 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cmArgumentParser.h" #include "cmCTestCommand.h" -#include <stddef.h> #include <string> #include <vector> @@ -19,11 +19,11 @@ class cmExecutionStatus; * * cmCTestHandlerCommand defineds the command to test the project. */ -class cmCTestHandlerCommand : public cmCTestCommand +class cmCTestHandlerCommand + : public cmCTestCommand + , public cmArgumentParser<void> { public: - cmCTestHandlerCommand(); - /** * The name of the command as specified in CMakeList.txt. */ @@ -36,42 +36,22 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; - enum - { - ct_NONE, - ct_RETURN_VALUE, - ct_CAPTURE_CMAKE_ERROR, - ct_BUILD, - ct_SOURCE, - ct_SUBMIT_INDEX, - ct_LAST - }; - protected: virtual cmCTestGenericHandler* InitializeHandler() = 0; virtual void ProcessAdditionalValues(cmCTestGenericHandler* handler); // Command argument handling. - virtual bool CheckArgumentKeyword(std::string const& arg); - virtual bool CheckArgumentValue(std::string const& arg); - enum - { - ArgumentDoingNone, - ArgumentDoingError, - ArgumentDoingKeyword, - ArgumentDoingLast1 - }; - int ArgumentDoing; - unsigned int ArgumentIndex; - - bool AppendXML; - bool Quiet; - - std::string ReturnVariable; - std::vector<const char*> Arguments; - std::vector<const char*> Values; - size_t Last; + virtual void BindArguments(); + virtual void CheckArguments(std::vector<std::string> const& keywords); + + bool Append = false; + bool Quiet = false; + std::string CaptureCMakeError; + std::string ReturnValue; + std::string Build; + std::string Source; + std::string SubmitIndex; }; #define CTEST_COMMAND_APPEND_OPTION_DOCS \ diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx index 804efa5..abad5fc 100644 --- a/Source/CTest/cmCTestMemCheckCommand.cxx +++ b/Source/CTest/cmCTestMemCheckCommand.cxx @@ -2,18 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestMemCheckCommand.h" -#include <string> -#include <vector> - #include "cmCTest.h" #include "cmCTestMemCheckHandler.h" #include "cmMakefile.h" +#include "cm_static_string_view.hxx" -cmCTestMemCheckCommand::cmCTestMemCheckCommand() +void cmCTestMemCheckCommand::BindArguments() { - this->Arguments[ctm_DEFECT_COUNT] = "DEFECT_COUNT"; - this->Arguments[ctm_LAST] = nullptr; - this->Last = ctm_LAST; + this->cmCTestTestCommand::BindArguments(); + this->Bind("DEFECT_COUNT"_s, this->DefectCount); } cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler() @@ -43,9 +40,9 @@ cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler() void cmCTestMemCheckCommand::ProcessAdditionalValues( cmCTestGenericHandler* handler) { - if (this->Values[ctm_DEFECT_COUNT] && *this->Values[ctm_DEFECT_COUNT]) { + if (!this->DefectCount.empty()) { this->Makefile->AddDefinition( - this->Values[ctm_DEFECT_COUNT], + this->DefectCount, std::to_string( static_cast<cmCTestMemCheckHandler*>(handler)->GetDefectCount())); } diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h index 5dad4e7..8f4ffb8 100644 --- a/Source/CTest/cmCTestMemCheckCommand.h +++ b/Source/CTest/cmCTestMemCheckCommand.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <string> #include <utility> #include <cm/memory> @@ -22,8 +23,6 @@ class cmCTestGenericHandler; class cmCTestMemCheckCommand : public cmCTestTestCommand { public: - cmCTestMemCheckCommand(); - /** * This is a virtual constructor for the command. */ @@ -36,15 +35,13 @@ public: } protected: + void BindArguments() override; + cmCTestGenericHandler* InitializeActualHandler() override; void ProcessAdditionalValues(cmCTestGenericHandler* handler) override; - enum - { - ctm_DEFECT_COUNT = ctt_LAST, - ctm_LAST - }; + std::string DefectCount; }; #endif diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index 2e2cf1a..706b45a 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -2,14 +2,18 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestSubmitCommand.h" +#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestSubmitHandler.h" #include "cmCommand.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cm_static_string_view.hxx" +#include <set> #include <sstream> #include <utility> @@ -17,18 +21,6 @@ class cmExecutionStatus; -cmCTestSubmitCommand::cmCTestSubmitCommand() -{ - this->PartsMentioned = false; - this->FilesMentioned = false; - this->InternalTest = false; - this->RetryCount = ""; - this->RetryDelay = ""; - this->CDashUpload = false; - this->Arguments[cts_BUILD_ID] = "BUILD_ID"; - this->Last = cts_LAST; -} - /** * This is a virtual constructor for the command. */ @@ -106,13 +98,18 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() // without any of the default parts. // handler->SelectParts(std::set<cmCTest::Part>()); - handler->SelectFiles(this->Files); + handler->SelectFiles( + std::set<std::string>(this->Files.begin(), this->Files.end())); } // If a PARTS option was given, select only the named parts for submission. // if (this->PartsMentioned) { - handler->SelectParts(this->Parts); + auto parts = + cmMakeRange(this->Parts).transform([this](std::string const& arg) { + return this->CTest->GetPartFromName(arg.c_str()); + }); + handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end())); } // Pass along any HTTPHEADER to the handler if this option was given. @@ -140,133 +137,61 @@ bool cmCTestSubmitCommand::InitialPass(std::vector<std::string> const& args, bool ret = this->cmCTestHandlerCommand::InitialPass(args, status); - if (this->Values[cts_BUILD_ID] && *this->Values[cts_BUILD_ID]) { - this->Makefile->AddDefinition(this->Values[cts_BUILD_ID], - this->CTest->GetBuildID()); + if (!this->BuildID.empty()) { + this->Makefile->AddDefinition(this->BuildID, this->CTest->GetBuildID()); } return ret; } -bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg) +void cmCTestSubmitCommand::BindArguments() { if (this->CDashUpload) { // Arguments specific to the CDASH_UPLOAD signature. - if (arg == "CDASH_UPLOAD") { - this->ArgumentDoing = ArgumentDoingCDashUpload; - return true; - } - - if (arg == "CDASH_UPLOAD_TYPE") { - this->ArgumentDoing = ArgumentDoingCDashUploadType; - return true; - } + this->Bind("CDASH_UPLOAD", this->CDashUploadFile); + this->Bind("CDASH_UPLOAD_TYPE", this->CDashUploadType); } else { // Arguments that cannot be used with CDASH_UPLOAD. - if (arg == "PARTS") { - this->ArgumentDoing = ArgumentDoingParts; - this->PartsMentioned = true; - return true; - } - - if (arg == "FILES") { - this->ArgumentDoing = ArgumentDoingFiles; - this->FilesMentioned = true; - return true; - } + this->Bind("PARTS"_s, this->Parts); + this->Bind("FILES"_s, this->Files); } // Arguments used by both modes. - if (arg == "HTTPHEADER") { - this->ArgumentDoing = ArgumentDoingHttpHeader; - return true; - } - - if (arg == "RETRY_COUNT") { - this->ArgumentDoing = ArgumentDoingRetryCount; - return true; - } - - if (arg == "RETRY_DELAY") { - this->ArgumentDoing = ArgumentDoingRetryDelay; - return true; - } - - if (arg == "SUBMIT_URL") { - this->ArgumentDoing = ArgumentDoingSubmitURL; - return true; - } - - if (arg == "INTERNAL_TEST_CHECKSUM") { - this->InternalTest = true; - return true; - } + this->Bind("BUILD_ID"_s, this->BuildID); + this->Bind("HTTPHEADER"_s, this->HttpHeaders); + this->Bind("RETRY_COUNT"_s, this->RetryCount); + this->Bind("RETRY_DELAY"_s, this->RetryDelay); + this->Bind("SUBMIT_URL"_s, this->SubmitURL); + this->Bind("INTERNAL_TEST_CHECKSUM", this->InternalTest); // Look for other arguments. - return this->Superclass::CheckArgumentKeyword(arg); + this->cmCTestHandlerCommand::BindArguments(); } -bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg) +void cmCTestSubmitCommand::CheckArguments( + std::vector<std::string> const& keywords) { - // Handle states specific to this command. - if (this->ArgumentDoing == ArgumentDoingParts) { + this->PartsMentioned = !this->Parts.empty() || cmContains(keywords, "PARTS"); + this->FilesMentioned = !this->Files.empty() || cmContains(keywords, "FILES"); + + cmEraseIf(this->Parts, [this](std::string const& arg) -> bool { cmCTest::Part p = this->CTest->GetPartFromName(arg.c_str()); - if (p != cmCTest::PartCount) { - this->Parts.insert(p); - } else { + if (p == cmCTest::PartCount) { std::ostringstream e; e << "Part name \"" << arg << "\" is invalid."; this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); - this->ArgumentDoing = ArgumentDoingError; + return true; } - return true; - } + return false; + }); - if (this->ArgumentDoing == ArgumentDoingFiles) { - if (cmSystemTools::FileExists(arg)) { - this->Files.insert(arg); - } else { + cmEraseIf(this->Files, [this](std::string const& arg) -> bool { + if (!cmSystemTools::FileExists(arg)) { std::ostringstream e; e << "File \"" << arg << "\" does not exist. Cannot submit " << "a non-existent file."; this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); - this->ArgumentDoing = ArgumentDoingError; + return true; } - return true; - } - - if (this->ArgumentDoing == ArgumentDoingHttpHeader) { - this->HttpHeaders.push_back(arg); - return true; - } - - if (this->ArgumentDoing == ArgumentDoingRetryCount) { - this->RetryCount = arg; - return true; - } - - if (this->ArgumentDoing == ArgumentDoingRetryDelay) { - this->RetryDelay = arg; - return true; - } - - if (this->ArgumentDoing == ArgumentDoingCDashUpload) { - this->ArgumentDoing = ArgumentDoingNone; - this->CDashUploadFile = arg; - return true; - } - - if (this->ArgumentDoing == ArgumentDoingCDashUploadType) { - this->ArgumentDoing = ArgumentDoingNone; - this->CDashUploadType = arg; - return true; - } - - if (this->ArgumentDoing == ArgumentDoingSubmitURL) { - this->ArgumentDoing = ArgumentDoingNone; - this->SubmitURL = arg; - return true; - } - - // Look for other arguments. - return this->Superclass::CheckArgumentValue(arg); + return false; + }); } diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h index 8562207..249f844 100644 --- a/Source/CTest/cmCTestSubmitCommand.h +++ b/Source/CTest/cmCTestSubmitCommand.h @@ -5,11 +5,9 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include "cmCTest.h" #include "cmCTestHandlerCommand.h" #include <memory> -#include <set> #include <string> #include <vector> @@ -26,7 +24,6 @@ class cmExecutionStatus; class cmCTestSubmitCommand : public cmCTestHandlerCommand { public: - cmCTestSubmitCommand(); std::unique_ptr<cmCommand> Clone() override; bool InitialPass(std::vector<std::string> const& args, @@ -37,45 +34,26 @@ public: */ std::string GetName() const override { return "ctest_submit"; } - using Superclass = cmCTestHandlerCommand; - protected: + void BindArguments() override; + void CheckArguments(std::vector<std::string> const& keywords) override; cmCTestGenericHandler* InitializeHandler() override; - bool CheckArgumentKeyword(std::string const& arg) override; - bool CheckArgumentValue(std::string const& arg) override; - - enum - { - ArgumentDoingParts = Superclass::ArgumentDoingLast1, - ArgumentDoingFiles, - ArgumentDoingRetryDelay, - ArgumentDoingRetryCount, - ArgumentDoingCDashUpload, - ArgumentDoingCDashUploadType, - ArgumentDoingHttpHeader, - ArgumentDoingSubmitURL, - ArgumentDoingLast2 - }; - - enum - { - cts_BUILD_ID = ct_LAST, - cts_LAST - }; + bool CDashUpload = false; + bool FilesMentioned = false; + bool InternalTest = false; + bool PartsMentioned = false; - bool PartsMentioned; - std::set<cmCTest::Part> Parts; - bool FilesMentioned; - bool InternalTest; - std::set<std::string> Files; - std::string RetryCount; - std::string RetryDelay; - bool CDashUpload; + std::string BuildID; std::string CDashUploadFile; std::string CDashUploadType; - std::vector<std::string> HttpHeaders; + std::string RetryCount; + std::string RetryDelay; std::string SubmitURL; + + std::vector<std::string> Files; + std::vector<std::string> HttpHeaders; + std::vector<std::string> Parts; }; #endif diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 3a29ad3..c277db8 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -8,30 +8,29 @@ #include "cmDuration.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" +#include "cm_static_string_view.hxx" #include <chrono> #include <cstdlib> #include <sstream> -#include <vector> -cmCTestTestCommand::cmCTestTestCommand() +void cmCTestTestCommand::BindArguments() { - this->Arguments[ctt_START] = "START"; - this->Arguments[ctt_END] = "END"; - this->Arguments[ctt_STRIDE] = "STRIDE"; - this->Arguments[ctt_EXCLUDE] = "EXCLUDE"; - this->Arguments[ctt_INCLUDE] = "INCLUDE"; - this->Arguments[ctt_EXCLUDE_LABEL] = "EXCLUDE_LABEL"; - this->Arguments[ctt_INCLUDE_LABEL] = "INCLUDE_LABEL"; - this->Arguments[ctt_EXCLUDE_FIXTURE] = "EXCLUDE_FIXTURE"; - this->Arguments[ctt_EXCLUDE_FIXTURE_SETUP] = "EXCLUDE_FIXTURE_SETUP"; - this->Arguments[ctt_EXCLUDE_FIXTURE_CLEANUP] = "EXCLUDE_FIXTURE_CLEANUP"; - this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL"; - this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM"; - this->Arguments[ctt_STOP_TIME] = "STOP_TIME"; - this->Arguments[ctt_TEST_LOAD] = "TEST_LOAD"; - this->Arguments[ctt_LAST] = nullptr; - this->Last = ctt_LAST; + this->cmCTestHandlerCommand::BindArguments(); + this->Bind("START"_s, this->Start); + this->Bind("END"_s, this->End); + this->Bind("STRIDE"_s, this->Stride); + this->Bind("EXCLUDE"_s, this->Exclude); + this->Bind("INCLUDE"_s, this->Include); + this->Bind("EXCLUDE_LABEL"_s, this->ExcludeLabel); + this->Bind("INCLUDE_LABEL"_s, this->IncludeLabel); + this->Bind("EXCLUDE_FIXTURE"_s, this->ExcludeFixture); + this->Bind("EXCLUDE_FIXTURE_SETUP"_s, this->ExcludeFixtureSetup); + this->Bind("EXCLUDE_FIXTURE_CLEANUP"_s, this->ExcludeFixtureCleanup); + this->Bind("PARALLEL_LEVEL"_s, this->ParallelLevel); + this->Bind("SCHEDULE_RANDOM"_s, this->ScheduleRandom); + this->Bind("STOP_TIME"_s, this->StopTime); + this->Bind("TEST_LOAD"_s, this->TestLoad); } cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() @@ -51,57 +50,44 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() } this->CTest->SetTimeOut(timeout); cmCTestGenericHandler* handler = this->InitializeActualHandler(); - if (this->Values[ctt_START] || this->Values[ctt_END] || - this->Values[ctt_STRIDE]) { - std::ostringstream testsToRunString; - if (this->Values[ctt_START]) { - testsToRunString << this->Values[ctt_START]; - } - testsToRunString << ","; - if (this->Values[ctt_END]) { - testsToRunString << this->Values[ctt_END]; - } - testsToRunString << ","; - if (this->Values[ctt_STRIDE]) { - testsToRunString << this->Values[ctt_STRIDE]; - } - handler->SetOption("TestsToRunInformation", - testsToRunString.str().c_str()); + if (!this->Start.empty() || !this->End.empty() || !this->Stride.empty()) { + handler->SetOption( + "TestsToRunInformation", + cmStrCat(this->Start, ',', this->End, ',', this->Stride).c_str()); } - if (this->Values[ctt_EXCLUDE]) { - handler->SetOption("ExcludeRegularExpression", this->Values[ctt_EXCLUDE]); + if (!this->Exclude.empty()) { + handler->SetOption("ExcludeRegularExpression", this->Exclude.c_str()); } - if (this->Values[ctt_INCLUDE]) { - handler->SetOption("IncludeRegularExpression", this->Values[ctt_INCLUDE]); + if (!this->Include.empty()) { + handler->SetOption("IncludeRegularExpression", this->Include.c_str()); } - if (this->Values[ctt_EXCLUDE_LABEL]) { + if (!this->ExcludeLabel.empty()) { handler->SetOption("ExcludeLabelRegularExpression", - this->Values[ctt_EXCLUDE_LABEL]); + this->ExcludeLabel.c_str()); } - if (this->Values[ctt_INCLUDE_LABEL]) { - handler->SetOption("LabelRegularExpression", - this->Values[ctt_INCLUDE_LABEL]); + if (!this->IncludeLabel.empty()) { + handler->SetOption("LabelRegularExpression", this->IncludeLabel.c_str()); } - if (this->Values[ctt_EXCLUDE_FIXTURE]) { + if (!this->ExcludeFixture.empty()) { handler->SetOption("ExcludeFixtureRegularExpression", - this->Values[ctt_EXCLUDE_FIXTURE]); + this->ExcludeFixture.c_str()); } - if (this->Values[ctt_EXCLUDE_FIXTURE_SETUP]) { + if (!this->ExcludeFixtureSetup.empty()) { handler->SetOption("ExcludeFixtureSetupRegularExpression", - this->Values[ctt_EXCLUDE_FIXTURE_SETUP]); + this->ExcludeFixtureSetup.c_str()); } - if (this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]) { + if (!this->ExcludeFixtureCleanup.empty()) { handler->SetOption("ExcludeFixtureCleanupRegularExpression", - this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]); + this->ExcludeFixtureCleanup.c_str()); } - if (this->Values[ctt_PARALLEL_LEVEL]) { - handler->SetOption("ParallelLevel", this->Values[ctt_PARALLEL_LEVEL]); + if (!this->ParallelLevel.empty()) { + handler->SetOption("ParallelLevel", this->ParallelLevel.c_str()); } - if (this->Values[ctt_SCHEDULE_RANDOM]) { - handler->SetOption("ScheduleRandom", this->Values[ctt_SCHEDULE_RANDOM]); + if (!this->ScheduleRandom.empty()) { + handler->SetOption("ScheduleRandom", this->ScheduleRandom.c_str()); } - if (this->Values[ctt_STOP_TIME]) { - this->CTest->SetStopTime(this->Values[ctt_STOP_TIME]); + if (!this->StopTime.empty()) { + this->CTest->SetStopTime(this->StopTime); } // Test load is determined by: TEST_LOAD argument, @@ -109,12 +95,12 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() // command line argument... in that order. unsigned long testLoad; const char* ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD"); - if (this->Values[ctt_TEST_LOAD] && *this->Values[ctt_TEST_LOAD]) { - if (!cmStrToULong(this->Values[ctt_TEST_LOAD], &testLoad)) { + if (!this->TestLoad.empty()) { + if (!cmStrToULong(this->TestLoad.c_str(), &testLoad)) { testLoad = 0; cmCTestLog(this->CTest, WARNING, - "Invalid value for 'TEST_LOAD' : " - << this->Values[ctt_TEST_LOAD] << std::endl); + "Invalid value for 'TEST_LOAD' : " << this->TestLoad + << std::endl); } } else if (ctestTestLoad && *ctestTestLoad) { if (!cmStrToULong(ctestTestLoad, &testLoad)) { diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h index a9ba3ab..edd21b7 100644 --- a/Source/CTest/cmCTestTestCommand.h +++ b/Source/CTest/cmCTestTestCommand.h @@ -23,8 +23,6 @@ class cmCTestGenericHandler; class cmCTestTestCommand : public cmCTestHandlerCommand { public: - cmCTestTestCommand(); - /** * This is a virtual constructor for the command. */ @@ -42,29 +40,24 @@ public: std::string GetName() const override { return "ctest_test"; } protected: + void BindArguments() override; virtual cmCTestGenericHandler* InitializeActualHandler(); cmCTestGenericHandler* InitializeHandler() override; - enum - { - ctt_BUILD = ct_LAST, - ctt_RETURN_VALUE, - ctt_START, - ctt_END, - ctt_STRIDE, - ctt_EXCLUDE, - ctt_INCLUDE, - ctt_EXCLUDE_LABEL, - ctt_INCLUDE_LABEL, - ctt_EXCLUDE_FIXTURE, - ctt_EXCLUDE_FIXTURE_SETUP, - ctt_EXCLUDE_FIXTURE_CLEANUP, - ctt_PARALLEL_LEVEL, - ctt_SCHEDULE_RANDOM, - ctt_STOP_TIME, - ctt_TEST_LOAD, - ctt_LAST - }; + std::string Start; + std::string End; + std::string Stride; + std::string Exclude; + std::string Include; + std::string ExcludeLabel; + std::string IncludeLabel; + std::string ExcludeFixture; + std::string ExcludeFixtureSetup; + std::string ExcludeFixtureCleanup; + std::string ParallelLevel; + std::string ScheduleRandom; + std::string StopTime; + std::string TestLoad; }; #endif diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx index 65dc921..673eb9a 100644 --- a/Source/CTest/cmCTestUpdateCommand.cxx +++ b/Source/CTest/cmCTestUpdateCommand.cxx @@ -7,14 +7,11 @@ #include "cmMakefile.h" #include "cmSystemTools.h" -#include <vector> - cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler() { - if (this->Values[ct_SOURCE]) { + if (!this->Source.empty()) { this->CTest->SetCTestConfiguration( - "SourceDirectory", - cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(), + "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(), this->Quiet); } else { this->CTest->SetCTestConfiguration( diff --git a/Source/CTest/cmCTestUpdateCommand.h b/Source/CTest/cmCTestUpdateCommand.h index 5b0e07e..a4798a5 100644 --- a/Source/CTest/cmCTestUpdateCommand.h +++ b/Source/CTest/cmCTestUpdateCommand.h @@ -23,8 +23,6 @@ class cmCTestGenericHandler; class cmCTestUpdateCommand : public cmCTestHandlerCommand { public: - cmCTestUpdateCommand() {} - /** * This is a virtual constructor for the command. */ diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx index 59fbf37..9180821 100644 --- a/Source/CTest/cmCTestUploadCommand.cxx +++ b/Source/CTest/cmCTestUploadCommand.cxx @@ -2,61 +2,45 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestUploadCommand.h" +#include <set> #include <sstream> #include <vector> +#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestUploadHandler.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmSystemTools.h" +#include "cm_static_string_view.hxx" -cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler() -{ - cmCTestUploadHandler* handler = this->CTest->GetUploadHandler(); - handler->Initialize(); - handler->SetFiles(this->Files); - handler->SetQuiet(this->Quiet); - return handler; -} - -bool cmCTestUploadCommand::CheckArgumentKeyword(std::string const& arg) +void cmCTestUploadCommand::BindArguments() { - if (arg == "FILES") { - this->ArgumentDoing = ArgumentDoingFiles; - return true; - } - if (arg == "QUIET") { - this->ArgumentDoing = ArgumentDoingNone; - this->Quiet = true; - return true; - } - if (arg == "CAPTURE_CMAKE_ERROR") { - this->ArgumentDoing = ArgumentDoingCaptureCMakeError; - return true; - } - return false; + this->Bind("FILES"_s, this->Files); + this->Bind("QUIET"_s, this->Quiet); + this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError); } -bool cmCTestUploadCommand::CheckArgumentValue(std::string const& arg) +void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&) { - if (this->ArgumentDoing == ArgumentDoingCaptureCMakeError) { - this->Values[ct_CAPTURE_CMAKE_ERROR] = arg.c_str(); - return true; - } - if (this->ArgumentDoing == ArgumentDoingFiles) { - if (cmSystemTools::FileExists(arg)) { - this->Files.insert(arg); + cmEraseIf(this->Files, [this](std::string const& arg) -> bool { + if (!cmSystemTools::FileExists(arg)) { + std::ostringstream e; + e << "File \"" << arg << "\" does not exist. Cannot submit " + << "a non-existent file."; + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return true; } - std::ostringstream e; - e << "File \"" << arg << "\" does not exist. Cannot submit " - << "a non-existent file."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); - this->ArgumentDoing = ArgumentDoingError; return false; - } + }); +} - // Look for other arguments. - return this->Superclass::CheckArgumentValue(arg); +cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler() +{ + cmCTestUploadHandler* handler = this->CTest->GetUploadHandler(); + handler->Initialize(); + handler->SetFiles( + std::set<std::string>(this->Files.begin(), this->Files.end())); + handler->SetQuiet(this->Quiet); + return handler; } diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h index 39314f2..f78f0ec 100644 --- a/Source/CTest/cmCTestUploadCommand.h +++ b/Source/CTest/cmCTestUploadCommand.h @@ -8,9 +8,9 @@ #include "cmCTestHandlerCommand.h" #include "cmCommand.h" -#include <set> #include <string> #include <utility> +#include <vector> #include <cm/memory> @@ -41,22 +41,12 @@ public: */ std::string GetName() const override { return "ctest_upload"; } - using Superclass = cmCTestHandlerCommand; - protected: + void BindArguments() override; + void CheckArguments(std::vector<std::string> const&) override; cmCTestGenericHandler* InitializeHandler() override; - bool CheckArgumentKeyword(std::string const& arg) override; - bool CheckArgumentValue(std::string const& arg) override; - - enum - { - ArgumentDoingFiles = Superclass::ArgumentDoingLast1, - ArgumentDoingCaptureCMakeError, - ArgumentDoingLast2 - }; - - std::set<std::string> Files; + std::vector<std::string> Files; }; #endif diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 35db6a4..94de851 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -5,6 +5,7 @@ #include <sstream> #include <unordered_set> +#include "cmCheckCustomOutputs.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmExecutionStatus.h" @@ -16,9 +17,6 @@ #include "cmSystemTools.h" #include "cmTarget.h" -static bool cmAddCustomCommandCommandCheckOutputs( - const std::vector<std::string>& outputs, cmExecutionStatus& status); - bool cmAddCustomCommandCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -307,9 +305,9 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, } // Make sure the output names and locations are safe. - if (!cmAddCustomCommandCommandCheckOutputs(output, status) || - !cmAddCustomCommandCommandCheckOutputs(outputs, status) || - !cmAddCustomCommandCommandCheckOutputs(byproducts, status)) { + if (!cmCheckCustomOutputs(output, "OUTPUT", status) || + !cmCheckCustomOutputs(outputs, "OUTPUTS", status) || + !cmCheckCustomOutputs(byproducts, "BYPRODUCTS", status)) { return false; } @@ -322,8 +320,8 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, // No command for this output exists. status.SetError( - cmStrCat("given APPEND option with output\n\"", output[0], - "\"\nwhich is not already a custom command output.")); + cmStrCat("given APPEND option with output\n ", output[0], + "\nwhich is not already a custom command output.")); return false; } @@ -387,29 +385,3 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, return true; } - -bool cmAddCustomCommandCommandCheckOutputs( - const std::vector<std::string>& outputs, cmExecutionStatus& status) -{ - cmMakefile& mf = status.GetMakefile(); - for (std::string const& o : outputs) { - // Make sure the file will not be generated into the source - // directory during an out of source build. - if (!mf.CanIWriteThisFile(o)) { - std::string e = "attempted to have a file \"" + o + - "\" in a source directory as an output of custom command."; - status.SetError(e); - cmSystemTools::SetFatalErrorOccured(); - return false; - } - - // Make sure the output file name has no invalid characters. - std::string::size_type pos = o.find_first_of("#<>"); - if (pos != std::string::npos) { - status.SetError(cmStrCat("called with OUTPUT containing a \"", o[pos], - "\". This character is not allowed.")); - return false; - } - } - return true; -} diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index 9fd1234..b580c43 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -4,6 +4,7 @@ #include <utility> +#include "cmCheckCustomOutputs.h" #include "cmCustomCommandLines.h" #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" @@ -205,6 +206,11 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args, return false; } + // Make sure the byproduct names and locations are safe. + if (!cmCheckCustomOutputs(byproducts, "BYPRODUCTS", status)) { + return false; + } + // Add the utility target to the makefile. bool escapeOldStyle = !verbatim; cmTarget* target = mf.AddUtilityCommand( diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx index 751d117..4c87177 100644 --- a/Source/cmArgumentParser.cxx +++ b/Source/cmArgumentParser.cxx @@ -61,10 +61,14 @@ void Instance::Bind(MultiStringList& val) void Instance::Consume(cm::string_view arg, void* result, std::vector<std::string>* unparsedArguments, - std::vector<std::string>* keywordsMissingValue) + std::vector<std::string>* keywordsMissingValue, + std::vector<std::string>* parsedKeywords) { auto const it = this->Bindings.Find(arg); if (it != this->Bindings.end()) { + if (parsedKeywords != nullptr) { + parsedKeywords->emplace_back(arg); + } it->second(*this, result); if (this->ExpectValue && keywordsMissingValue != nullptr) { keywordsMissingValue->emplace_back(arg); diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h index b6798bc..9be2488 100644 --- a/Source/cmArgumentParser.h +++ b/Source/cmArgumentParser.h @@ -45,7 +45,8 @@ public: void Consume(cm::string_view arg, void* result, std::vector<std::string>* unparsedArguments, - std::vector<std::string>* keywordsMissingValue); + std::vector<std::string>* keywordsMissingValue, + std::vector<std::string>* parsedKeywords); private: ActionMap const& Bindings; @@ -79,21 +80,25 @@ public: template <typename Range> void Parse(Result& result, Range const& args, std::vector<std::string>* unparsedArguments = nullptr, - std::vector<std::string>* keywordsMissingValue = nullptr) const + std::vector<std::string>* keywordsMissingValue = nullptr, + std::vector<std::string>* parsedKeywords = nullptr) const { ArgumentParser::Instance instance(this->Bindings); for (cm::string_view arg : args) { - instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue); + instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue, + parsedKeywords); } } template <typename Range> Result Parse(Range const& args, std::vector<std::string>* unparsedArguments = nullptr, - std::vector<std::string>* keywordsMissingValue = nullptr) const + std::vector<std::string>* keywordsMissingValue = nullptr, + std::vector<std::string>* parsedKeywords = nullptr) const { Result result; - this->Parse(result, args, unparsedArguments, keywordsMissingValue); + this->Parse(result, args, unparsedArguments, keywordsMissingValue, + parsedKeywords); return result; } @@ -116,11 +121,13 @@ public: template <typename Range> void Parse(Range const& args, std::vector<std::string>* unparsedArguments = nullptr, - std::vector<std::string>* keywordsMissingValue = nullptr) const + std::vector<std::string>* keywordsMissingValue = nullptr, + std::vector<std::string>* parsedKeywords = nullptr) const { ArgumentParser::Instance instance(this->Bindings); for (cm::string_view arg : args) { - instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue); + instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue, + parsedKeywords); } } diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 9c7beca..1eaf48b 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -561,7 +561,7 @@ void* CCONV cmAddSource(void* arg, void* arg2) // Create the real cmSourceFile instance and copy over saved information. cmSourceFile* rsf = mf->GetOrCreateSource(osf->FullPath); - rsf->GetProperties() = osf->Properties; + rsf->SetProperties(osf->Properties); for (std::string const& d : osf->Depends) { rsf->AddDepend(d); } diff --git a/Source/cmCheckCustomOutputs.cxx b/Source/cmCheckCustomOutputs.cxx new file mode 100644 index 0000000..7645c88 --- /dev/null +++ b/Source/cmCheckCustomOutputs.cxx @@ -0,0 +1,36 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCheckCustomOutputs.h" + +#include "cmExecutionStatus.h" +#include "cmMakefile.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +bool cmCheckCustomOutputs(const std::vector<std::string>& outputs, + cm::string_view keyword, cmExecutionStatus& status) +{ + cmMakefile& mf = status.GetMakefile(); + + for (std::string const& o : outputs) { + // Make sure the file will not be generated into the source + // directory during an out of source build. + if (!mf.CanIWriteThisFile(o)) { + status.SetError( + cmStrCat("attempted to have a file\n ", o, + "\nin a source directory as an output of custom command.")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + // Make sure the output file name has no invalid characters. + std::string::size_type pos = o.find_first_of("#<>"); + if (pos != std::string::npos) { + status.SetError(cmStrCat("called with ", keyword, " containing a \"", + o[pos], "\". This character is not allowed.")); + return false; + } + } + + return true; +} diff --git a/Source/cmCheckCustomOutputs.h b/Source/cmCheckCustomOutputs.h new file mode 100644 index 0000000..7c4b3fe --- /dev/null +++ b/Source/cmCheckCustomOutputs.h @@ -0,0 +1,18 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCheckCustomOutputs_h +#define cmCheckCustomOutputs_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <cm/string_view> + +#include <string> +#include <vector> + +class cmExecutionStatus; + +bool cmCheckCustomOutputs(const std::vector<std::string>& outputs, + cm::string_view keyword, cmExecutionStatus& status); + +#endif diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 262590b..88d17f1 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -231,20 +231,18 @@ void GetProjectCommands(cmState* state) cmGetSourceFilePropertyCommand); state->AddBuiltinCommand("get_target_property", cmGetTargetPropertyCommand); state->AddBuiltinCommand("get_test_property", cmGetTestPropertyCommand); - state->AddBuiltinCommand("include_directories", - cm::make_unique<cmIncludeDirectoryCommand>()); + state->AddBuiltinCommand("include_directories", cmIncludeDirectoryCommand); state->AddBuiltinCommand("include_regular_expression", cmIncludeRegularExpressionCommand); - state->AddBuiltinCommand("install", cm::make_unique<cmInstallCommand>()); + state->AddBuiltinCommand("install", cmInstallCommand); state->AddBuiltinCommand("install_files", cmInstallFilesCommand); state->AddBuiltinCommand("install_targets", cmInstallTargetsCommand); - state->AddBuiltinCommand("link_directories", - cm::make_unique<cmLinkDirectoriesCommand>()); - state->AddBuiltinCommand("project", cm::make_unique<cmProjectCommand>()); + state->AddBuiltinCommand("link_directories", cmLinkDirectoriesCommand); + state->AddBuiltinCommand("project", cmProjectCommand); state->AddBuiltinCommand("set_source_files_properties", cmSetSourceFilesPropertiesCommand); state->AddBuiltinCommand("set_target_properties", - cm::make_unique<cmSetTargetPropertiesCommand>()); + cmSetTargetPropertiesCommand); state->AddBuiltinCommand("set_tests_properties", cmSetTestsPropertiesCommand); state->AddBuiltinCommand("subdirs", cmSubdirCommand); @@ -259,7 +257,7 @@ void GetProjectCommands(cmState* state) "target_include_directories", cm::make_unique<cmTargetIncludeDirectoriesCommand>()); state->AddBuiltinCommand("target_link_libraries", - cm::make_unique<cmTargetLinkLibrariesCommand>()); + cmTargetLinkLibrariesCommand); state->AddBuiltinCommand("target_sources", cm::make_unique<cmTargetSourcesCommand>()); state->AddBuiltinCommand("try_compile", @@ -275,7 +273,7 @@ void GetProjectCommands(cmState* state) state->AddBuiltinCommand("add_compile_options", cmAddCompileOptionsCommand); state->AddBuiltinCommand("aux_source_directory", cmAuxSourceDirectoryCommand); - state->AddBuiltinCommand("export", cm::make_unique<cmExportCommand>()); + state->AddBuiltinCommand("export", cmExportCommand); state->AddBuiltinCommand("fltk_wrap_ui", cmFLTKWrapUICommand); state->AddBuiltinCommand("include_external_msproject", cmIncludeExternalMSProjectCommand); @@ -286,13 +284,11 @@ void GetProjectCommands(cmState* state) cm::make_unique<cmTargetLinkOptionsCommand>()); state->AddBuiltinCommand("target_link_directories", cm::make_unique<cmTargetLinkDirectoriesCommand>()); - state->AddBuiltinCommand("load_cache", - cm::make_unique<cmLoadCacheCommand>()); + state->AddBuiltinCommand("load_cache", cmLoadCacheCommand); state->AddBuiltinCommand("qt_wrap_cpp", cmQTWrapCPPCommand); state->AddBuiltinCommand("qt_wrap_ui", cmQTWrapUICommand); state->AddBuiltinCommand("remove_definitions", cmRemoveDefinitionsCommand); - state->AddBuiltinCommand("source_group", - cm::make_unique<cmSourceGroupCommand>()); + state->AddBuiltinCommand("source_group", cmSourceGroupCommand); state->AddDisallowedCommand( "export_library_dependencies", cmExportLibraryDependenciesCommand, diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index ddb855b..7f3e052 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -19,7 +19,7 @@ namespace { void AppendPaths(const std::vector<std::string>& inputs, - cmGeneratorExpression& ge, cmLocalGenerator* lg, + cmGeneratorExpression const& ge, cmLocalGenerator* lg, std::string const& config, std::vector<std::string>& output) { for (std::string const& in : inputs) { @@ -45,15 +45,15 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, , LG(lg) , OldStyle(cc.GetEscapeOldStyle()) , MakeVars(cc.GetEscapeAllowMakeVars()) - , GE(new cmGeneratorExpression(cc.GetBacktrace())) , EmulatorsWithArguments(cc.GetCommandLines().size()) { + cmGeneratorExpression ge(cc.GetBacktrace()); + const cmCustomCommandLines& cmdlines = this->CC.GetCommandLines(); for (cmCustomCommandLine const& cmdline : cmdlines) { cmCustomCommandLine argv; for (std::string const& clarg : cmdline) { - std::unique_ptr<cmCompiledGeneratorExpression> cge = - this->GE->Parse(clarg); + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(clarg); std::string parsed_arg = cge->Evaluate(this->LG, this->Config); if (this->CC.GetCommandExpandLists()) { cmAppend(argv, cmExpandedList(parsed_arg)); @@ -72,15 +72,14 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, this->CommandLines.push_back(std::move(argv)); } - AppendPaths(cc.GetByproducts(), *this->GE, this->LG, this->Config, + AppendPaths(cc.GetByproducts(), ge, this->LG, this->Config, this->Byproducts); - AppendPaths(cc.GetDepends(), *this->GE, this->LG, this->Config, - this->Depends); + AppendPaths(cc.GetDepends(), ge, this->LG, this->Config, this->Depends); const std::string& workingdirectory = this->CC.GetWorkingDirectory(); if (!workingdirectory.empty()) { std::unique_ptr<cmCompiledGeneratorExpression> cge = - this->GE->Parse(workingdirectory); + ge.Parse(workingdirectory); this->WorkingDirectory = cge->Evaluate(this->LG, this->Config); // Convert working directory to a full path. if (!this->WorkingDirectory.empty()) { @@ -93,11 +92,6 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, this->FillEmulatorsWithArguments(); } -cmCustomCommandGenerator::~cmCustomCommandGenerator() -{ - delete this->GE; -} - unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const { return static_cast<unsigned int>(this->CC.GetCommandLines().size()); diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index d614302..50f292e 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -10,7 +10,6 @@ #include <vector> class cmCustomCommand; -class cmGeneratorExpression; class cmLocalGenerator; class cmCustomCommandGenerator @@ -20,7 +19,6 @@ class cmCustomCommandGenerator cmLocalGenerator* LG; bool OldStyle; bool MakeVars; - cmGeneratorExpression* GE; cmCustomCommandLines CommandLines; std::vector<std::vector<std::string>> EmulatorsWithArguments; std::vector<std::string> Byproducts; @@ -34,7 +32,6 @@ class cmCustomCommandGenerator public: cmCustomCommandGenerator(cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg); - ~cmCustomCommandGenerator(); cmCustomCommandGenerator(const cmCustomCommandGenerator&) = delete; cmCustomCommandGenerator& operator=(const cmCustomCommandGenerator&) = delete; diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index a380b41..012a0b1 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -5,7 +5,6 @@ #include "cmsys/FStream.hxx" #include <utility> -#include "cmAlgorithms.h" #include "cmFileTime.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -67,7 +66,6 @@ cmDependsC::cmDependsC(cmLocalGenerator* lg, const std::string& targetDir, cmDependsC::~cmDependsC() { this->WriteCacheFile(); - cmDeleteAll(this->FileCache); } bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, @@ -172,9 +170,9 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, // Check whether this file is already in the cache auto fileIt = this->FileCache.find(fullName); if (fileIt != this->FileCache.end()) { - fileIt->second->Used = true; + fileIt->second.Used = true; dependencies.insert(fullName); - for (UnscannedEntry const& inc : fileIt->second->UnscannedEntries) { + for (UnscannedEntry const& inc : fileIt->second.UnscannedEntries) { if (this->Encountered.find(inc.FileName) == this->Encountered.end()) { this->Encountered.insert(inc.FileName); @@ -260,8 +258,7 @@ void cmDependsC::ReadCacheFile() if (res && newer) // cache is newer than the parsed file { - cacheEntry = new cmIncludeLines; - this->FileCache[line] = cacheEntry; + cacheEntry = &this->FileCache[line]; } // file doesn't exist, check that the regular expressions // haven't changed @@ -313,10 +310,10 @@ void cmDependsC::WriteCacheFile() const cacheOut << this->IncludeRegexTransformString << "\n\n"; for (auto const& fileIt : this->FileCache) { - if (fileIt.second->Used) { + if (fileIt.second.Used) { cacheOut << fileIt.first << std::endl; - for (UnscannedEntry const& inc : fileIt.second->UnscannedEntries) { + for (UnscannedEntry const& inc : fileIt.second.UnscannedEntries) { cacheOut << inc.FileName << std::endl; if (inc.QuotedLocation.empty()) { cacheOut << "-" << std::endl; @@ -332,9 +329,8 @@ void cmDependsC::WriteCacheFile() const void cmDependsC::Scan(std::istream& is, const std::string& directory, const std::string& fullName) { - cmIncludeLines* newCacheEntry = new cmIncludeLines; - newCacheEntry->Used = true; - this->FileCache[fullName] = newCacheEntry; + cmIncludeLines& newCacheEntry = this->FileCache[fullName]; + newCacheEntry.Used = true; // Read one line at a time. std::string line; @@ -370,7 +366,7 @@ void cmDependsC::Scan(std::istream& is, const std::string& directory, // This kind of problem will be fixed when a more // preprocessor-like implementation of this scanner is created. if (this->IncludeRegexScan.find(entry.FileName)) { - newCacheEntry->UnscannedEntries.push_back(entry); + newCacheEntry.UnscannedEntries.push_back(entry); if (this->Encountered.find(entry.FileName) == this->Encountered.end()) { this->Encountered.insert(entry.FileName); diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index cbdc276..7d732d9 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -84,7 +84,7 @@ protected: std::set<std::string> Encountered; std::queue<UnscannedEntry> Unscanned; - std::map<std::string, cmIncludeLines*> FileCache; + std::map<std::string, cmIncludeLines> FileCache; std::map<std::string, std::string> HeaderLocationCache; std::string CacheFileName; diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 2713856..79af6e9 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -11,6 +11,7 @@ #include "cmAlgorithms.h" #include "cmArgumentParser.h" +#include "cmExecutionStatus.h" #include "cmExportBuildAndroidMKGenerator.h" #include "cmExportBuildFileGenerator.h" #include "cmExportSet.h" @@ -23,23 +24,31 @@ #include "cmSystemTools.h" #include "cmTarget.h" -class cmExecutionStatus; - #if defined(__HAIKU__) # include <FindDirectory.h> # include <StorageDefs.h> #endif -bool cmExportCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +#if defined(_WIN32) && !defined(__CYGWIN__) +# include <windows.h> +#endif + +static bool HandlePackage(std::vector<std::string> const& args, + cmExecutionStatus& status); + +static void StorePackageRegistry(cmMakefile& mf, std::string const& package, + const char* content, const char* hash); + +bool cmExportCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("called with too few arguments"); + status.SetError("called with too few arguments"); return false; } if (args[0] == "PACKAGE") { - return this->HandlePackage(args); + return HandlePackage(args, status); } struct Arguments @@ -72,7 +81,7 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args, parser.Parse(args, &unknownArgs, &keywordsMissingValue); if (!unknownArgs.empty()) { - this->SetError("Unknown argument: \"" + unknownArgs.front() + "\"."); + status.SetError("Unknown argument: \"" + unknownArgs.front() + "\"."); return false; } @@ -84,7 +93,7 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args, } if (arguments.Filename.empty() && fname.empty()) { if (args[0] != "EXPORT") { - this->SetError("FILE <filename> option missing."); + status.SetError("FILE <filename> option missing."); return false; } fname = arguments.ExportSetName + ".cmake"; @@ -95,30 +104,32 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args, std::ostringstream e; e << "FILE option given filename \"" << arguments.Filename << "\" which does not have an extension of \".cmake\".\n"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } fname = arguments.Filename; } + cmMakefile& mf = status.GetMakefile(); + // Get the file to write. if (cmSystemTools::FileIsFullPath(fname)) { - if (!this->Makefile->CanIWriteThisFile(fname)) { + if (!mf.CanIWriteThisFile(fname)) { std::ostringstream e; e << "FILE option given filename \"" << fname << "\" which is in the source tree.\n"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } else { // Interpret relative paths with respect to the current build dir. - std::string dir = this->Makefile->GetCurrentBinaryDirectory(); + std::string const& dir = mf.GetCurrentBinaryDirectory(); fname = dir + "/" + fname; } std::vector<std::string> targets; - cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + cmGlobalGenerator* gg = mf.GetGlobalGenerator(); cmExportSet* exportSet = nullptr; if (args[0] == "EXPORT") { @@ -127,32 +138,32 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args, if (it == setMap.end()) { std::ostringstream e; e << "Export set \"" << arguments.ExportSetName << "\" not found."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } exportSet = &it->second; } else if (!arguments.Targets.empty() || cmContains(keywordsMissingValue, "TARGETS")) { for (std::string const& currentTarget : arguments.Targets) { - if (this->Makefile->IsAlias(currentTarget)) { + if (mf.IsAlias(currentTarget)) { std::ostringstream e; e << "given ALIAS target \"" << currentTarget << "\" which may not be exported."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } if (cmTarget* target = gg->FindTarget(currentTarget)) { if (target->GetType() == cmStateEnums::UTILITY) { - this->SetError("given custom target \"" + currentTarget + - "\" which may not be exported."); + status.SetError("given custom target \"" + currentTarget + + "\" which may not be exported."); return false; } } else { std::ostringstream e; e << "given target \"" << currentTarget << "\" which is not built by this project."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } targets.push_back(currentTarget); @@ -165,7 +176,7 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args, } } } else { - this->SetError("EXPORT or TARGETS specifier missing."); + status.SetError("EXPORT or TARGETS specifier missing."); return false; } @@ -184,12 +195,12 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args, } else { ebfg->SetTargets(targets); } - this->Makefile->AddExportBuildFileGenerator(ebfg); + mf.AddExportBuildFileGenerator(ebfg); ebfg->SetExportOld(arguments.ExportOld); // Compute the set of configurations exported. std::vector<std::string> configurationTypes; - this->Makefile->GetConfigurations(configurationTypes); + mf.GetConfigurations(configurationTypes); if (configurationTypes.empty()) { configurationTypes.emplace_back(); } @@ -205,7 +216,8 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args, return true; } -bool cmExportCommand::HandlePackage(std::vector<std::string> const& args) +static bool HandlePackage(std::vector<std::string> const& args, + cmExecutionStatus& status) { // Parse PACKAGE mode arguments. enum Doing @@ -222,14 +234,14 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args) } else { std::ostringstream e; e << "PACKAGE given unknown argument: " << args[i]; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } // Verify the package name. if (package.empty()) { - this->SetError("PACKAGE must be given a package name."); + status.SetError("PACKAGE must be given a package name."); return false; } const char* packageExpr = "^[A-Za-z0-9_.-]+$"; @@ -238,16 +250,18 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args) std::ostringstream e; e << "PACKAGE given invalid package name \"" << package << "\". " << "Package names must match \"" << packageExpr << "\"."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } + cmMakefile& mf = status.GetMakefile(); + // CMP0090 decides both the default and what variable changes it. - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0090)) { + switch (mf.GetPolicyStatus(cmPolicies::CMP0090)) { case cmPolicies::WARN: case cmPolicies::OLD: // Default is to export, but can be disabled. - if (this->Makefile->IsOn("CMAKE_EXPORT_NO_PACKAGE_REGISTRY")) { + if (mf.IsOn("CMAKE_EXPORT_NO_PACKAGE_REGISTRY")) { return true; } break; @@ -255,7 +269,7 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args) case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: // Default is to not export, but can be enabled. - if (!this->Makefile->IsOn("CMAKE_EXPORT_PACKAGE_REGISTRY")) { + if (!mf.IsOn("CMAKE_EXPORT_PACKAGE_REGISTRY")) { return true; } break; @@ -264,22 +278,17 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args) // We store the current build directory in the registry as a value // named by a hash of its own content. This is deterministic and is // unique with high probability. - const std::string& outDir = this->Makefile->GetCurrentBinaryDirectory(); + const std::string& outDir = mf.GetCurrentBinaryDirectory(); std::string hash = cmSystemTools::ComputeStringMD5(outDir); -#if defined(_WIN32) && !defined(__CYGWIN__) - this->StorePackageRegistryWin(package, outDir.c_str(), hash.c_str()); -#else - this->StorePackageRegistryDir(package, outDir.c_str(), hash.c_str()); -#endif + StorePackageRegistry(mf, package, outDir.c_str(), hash.c_str()); return true; } #if defined(_WIN32) && !defined(__CYGWIN__) -# include <windows.h> -void cmExportCommand::ReportRegistryError(std::string const& msg, - std::string const& key, long err) +static void ReportRegistryError(cmMakefile& mf, std::string const& msg, + std::string const& key, long err) { std::ostringstream e; e << msg << "\n" @@ -291,12 +300,11 @@ void cmExportCommand::ReportRegistryError(std::string const& msg, e << "Windows reported:\n" << " " << cmsys::Encoding::ToNarrow(winmsg); } - this->Makefile->IssueMessage(MessageType::WARNING, e.str()); + mf.IssueMessage(MessageType::WARNING, e.str()); } -void cmExportCommand::StorePackageRegistryWin(std::string const& package, - const char* content, - const char* hash) +static void StorePackageRegistry(cmMakefile& mf, std::string const& package, + const char* content, const char* hash) { std::string key = cmStrCat("Software\\Kitware\\CMake\\Packages\\", package); HKEY hKey; @@ -304,7 +312,7 @@ void cmExportCommand::StorePackageRegistryWin(std::string const& package, RegCreateKeyExW(HKEY_CURRENT_USER, cmsys::Encoding::ToWide(key).c_str(), 0, 0, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, 0, &hKey, 0); if (err != ERROR_SUCCESS) { - this->ReportRegistryError("Cannot create/open registry key", key, err); + ReportRegistryError(mf, "Cannot create/open registry key", key, err); return; } @@ -317,14 +325,13 @@ void cmExportCommand::StorePackageRegistryWin(std::string const& package, if (err != ERROR_SUCCESS) { std::ostringstream msg; msg << "Cannot set registry value \"" << hash << "\" under key"; - this->ReportRegistryError(msg.str(), key, err); + ReportRegistryError(mf, msg.str(), key, err); return; } } #else -void cmExportCommand::StorePackageRegistryDir(std::string const& package, - const char* content, - const char* hash) +static void StorePackageRegistry(cmMakefile& mf, std::string const& package, + const char* content, const char* hash) { # if defined(__HAIKU__) char dir[B_PATH_NAME_LENGTH]; @@ -356,7 +363,7 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package, << " " << fname << "\n" << cmSystemTools::GetLastSystemError() << "\n"; /* clang-format on */ - this->Makefile->IssueMessage(MessageType::WARNING, e.str()); + mf.IssueMessage(MessageType::WARNING, e.str()); } } } diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h index 819a3c3..9655628 100644 --- a/Source/cmExportCommand.h +++ b/Source/cmExportCommand.h @@ -8,38 +8,9 @@ #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" - class cmExecutionStatus; -class cmExportCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmExportCommand>(); - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - bool HandlePackage(std::vector<std::string> const& args); - void StorePackageRegistryWin(std::string const& package, const char* content, - const char* hash); - void StorePackageRegistryDir(std::string const& package, const char* content, - const char* hash); - void ReportRegistryError(std::string const& msg, std::string const& key, - long err); -}; +bool cmExportCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index f9a28cd..e142560 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -380,7 +380,7 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( this->ReplaceInstallPrefix(dirs); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs); std::string exportDirs = - cge->Evaluate(target->GetLocalGenerator(), "", false, target); + cge->Evaluate(target->GetLocalGenerator(), "", target); if (cge->GetHadContextSensitiveCondition()) { cmLocalGenerator* lg = target->GetLocalGenerator(); diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 5631d60..4027d4b 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -74,9 +74,8 @@ std::string cmExportTryCompileFileGenerator::FindTargets( cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator()); - std::string result = - cge->Evaluate(tgt->GetLocalGenerator(), this->Config, false, &gDummyHead, - tgt, &dagChecker, language); + std::string result = cge->Evaluate(tgt->GetLocalGenerator(), this->Config, + &gDummyHead, &dagChecker, tgt, language); const std::set<cmGeneratorTarget const*>& allTargets = cge->GetAllTargetsSeen(); diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index f49ed2c..1f31069 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -21,40 +21,56 @@ cmGeneratorExpression::cmGeneratorExpression(cmListFileBacktrace backtrace) { } +cmGeneratorExpression::~cmGeneratorExpression() = default; + std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse( - std::string const& input) + std::string input) const { return std::unique_ptr<cmCompiledGeneratorExpression>( - new cmCompiledGeneratorExpression(this->Backtrace, input)); + new cmCompiledGeneratorExpression(this->Backtrace, std::move(input))); } std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse( - const char* input) + const char* input) const { return this->Parse(std::string(input ? input : "")); } -cmGeneratorExpression::~cmGeneratorExpression() = default; - -const std::string& cmCompiledGeneratorExpression::Evaluate( - cmLocalGenerator* lg, const std::string& config, bool quiet, - const cmGeneratorTarget* headTarget, +std::string cmGeneratorExpression::Evaluate( + std::string input, cmLocalGenerator* lg, const std::string& config, + cmGeneratorTarget const* headTarget, cmGeneratorExpressionDAGChecker* dagChecker, - std::string const& language) const + cmGeneratorTarget const* currentTarget, std::string const& language) { - return this->Evaluate(lg, config, quiet, headTarget, headTarget, dagChecker, + if (Find(input) != std::string::npos) { + cmCompiledGeneratorExpression cge(cmListFileBacktrace(), std::move(input)); + return cge.Evaluate(lg, config, headTarget, dagChecker, currentTarget, language); + } + return input; +} + +std::string cmGeneratorExpression::Evaluate( + const char* input, cmLocalGenerator* lg, const std::string& config, + cmGeneratorTarget const* headTarget, + cmGeneratorExpressionDAGChecker* dagChecker, + cmGeneratorTarget const* currentTarget, std::string const& language) +{ + return input ? Evaluate(std::string(input), lg, config, headTarget, + dagChecker, currentTarget, language) + : ""; } const std::string& cmCompiledGeneratorExpression::Evaluate( - cmLocalGenerator* lg, const std::string& config, bool quiet, - const cmGeneratorTarget* headTarget, const cmGeneratorTarget* currentTarget, + cmLocalGenerator* lg, const std::string& config, + const cmGeneratorTarget* headTarget, cmGeneratorExpressionDAGChecker* dagChecker, - std::string const& language) const + const cmGeneratorTarget* currentTarget, std::string const& language) const { cmGeneratorExpressionContext context( - lg, config, quiet, headTarget, currentTarget ? currentTarget : headTarget, - this->EvaluateForBuildsystem, this->Backtrace, language); + lg, config, this->Quiet, headTarget, + currentTarget ? currentTarget : headTarget, this->EvaluateForBuildsystem, + this->Backtrace, language); return this->EvaluateWithContext(context, dagChecker); } @@ -97,9 +113,10 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( cmListFileBacktrace backtrace, std::string input) : Backtrace(std::move(backtrace)) , Input(std::move(input)) + , EvaluateForBuildsystem(false) + , Quiet(false) , HadContextSensitiveCondition(false) , HadHeadSensitiveCondition(false) - , EvaluateForBuildsystem(false) { cmGeneratorExpressionLexer l; std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(this->Input); @@ -377,10 +394,10 @@ void cmCompiledGeneratorExpression::GetMaxLanguageStandard( } const std::string& cmGeneratorExpressionInterpreter::Evaluate( - const char* expression, const std::string& property) + std::string expression, const std::string& property) { this->CompiledGeneratorExpression = - this->GeneratorExpression.Parse(expression); + this->GeneratorExpression.Parse(std::move(expression)); // Specify COMPILE_OPTIONS to DAGchecker, same semantic as COMPILE_FLAGS cmGeneratorExpressionDAGChecker dagChecker( @@ -389,6 +406,12 @@ const std::string& cmGeneratorExpressionInterpreter::Evaluate( nullptr); return this->CompiledGeneratorExpression->Evaluate( - this->LocalGenerator, this->Config, false, this->HeadTarget, &dagChecker, + this->LocalGenerator, this->Config, this->HeadTarget, &dagChecker, nullptr, this->Language); } + +const std::string& cmGeneratorExpressionInterpreter::Evaluate( + const char* expression, const std::string& property) +{ + return this->Evaluate(std::string(expression ? expression : ""), property); +} diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index ef76651..de5c705 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -41,8 +41,22 @@ public: cmGeneratorExpression& operator=(cmGeneratorExpression const&) = delete; std::unique_ptr<cmCompiledGeneratorExpression> Parse( - std::string const& input); - std::unique_ptr<cmCompiledGeneratorExpression> Parse(const char* input); + std::string input) const; + std::unique_ptr<cmCompiledGeneratorExpression> Parse( + const char* input) const; + + static std::string Evaluate( + std::string input, cmLocalGenerator* lg, const std::string& config, + cmGeneratorTarget const* headTarget = nullptr, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr, + cmGeneratorTarget const* currentTarget = nullptr, + std::string const& language = std::string()); + static std::string Evaluate( + const char* input, cmLocalGenerator* lg, const std::string& config, + cmGeneratorTarget const* headTarget = nullptr, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr, + cmGeneratorTarget const* currentTarget = nullptr, + std::string const& language = std::string()); enum PreprocessContext { @@ -87,15 +101,10 @@ public: cmCompiledGeneratorExpression const&) = delete; const std::string& Evaluate( - cmLocalGenerator* lg, const std::string& config, bool quiet = false, + cmLocalGenerator* lg, const std::string& config, cmGeneratorTarget const* headTarget = nullptr, - cmGeneratorTarget const* currentTarget = nullptr, cmGeneratorExpressionDAGChecker* dagChecker = nullptr, - std::string const& language = std::string()) const; - const std::string& Evaluate( - cmLocalGenerator* lg, const std::string& config, bool quiet, - cmGeneratorTarget const* headTarget, - cmGeneratorExpressionDAGChecker* dagChecker, + cmGeneratorTarget const* currentTarget = nullptr, std::string const& language = std::string()) const; /** Get set of targets found during evaluations. */ @@ -135,6 +144,8 @@ public: this->EvaluateForBuildsystem = eval; } + void SetQuiet(bool quiet) { this->Quiet = quiet; } + void GetMaxLanguageStandard(cmGeneratorTarget const* tgt, std::map<std::string, std::string>& mapping); @@ -152,6 +163,8 @@ private: std::vector<cmGeneratorExpressionEvaluator*> Evaluators; const std::string Input; bool NeedsEvaluation; + bool EvaluateForBuildsystem; + bool Quiet; mutable std::set<cmGeneratorTarget*> DependTargets; mutable std::set<cmGeneratorTarget const*> AllTargetsSeen; @@ -163,7 +176,6 @@ private: mutable bool HadContextSensitiveCondition; mutable bool HadHeadSensitiveCondition; mutable std::set<cmGeneratorTarget const*> SourceSensitiveTargets; - bool EvaluateForBuildsystem; }; class cmGeneratorExpressionInterpreter @@ -172,11 +184,11 @@ public: cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator, std::string config, cmGeneratorTarget const* headTarget, - std::string lang = std::string()) + std::string language = std::string()) : LocalGenerator(localGenerator) , Config(std::move(config)) , HeadTarget(headTarget) - , Language(std::move(lang)) + , Language(std::move(language)) { } @@ -185,13 +197,10 @@ public: cmGeneratorExpressionInterpreter& operator=( cmGeneratorExpressionInterpreter const&) = delete; + const std::string& Evaluate(std::string expression, + const std::string& property); const std::string& Evaluate(const char* expression, const std::string& property); - const std::string& Evaluate(const std::string& expression, - const std::string& property) - { - return this->Evaluate(expression.c_str(), property); - } protected: cmGeneratorExpression GeneratorExpression; diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index eb43270..aa2c1a6 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -37,8 +37,8 @@ void cmGeneratorExpressionEvaluationFile::Generate( { std::string rawCondition = this->Condition->GetInput(); if (!rawCondition.empty()) { - std::string condResult = this->Condition->Evaluate( - lg, config, false, nullptr, nullptr, nullptr, lang); + std::string condResult = + this->Condition->Evaluate(lg, config, nullptr, nullptr, nullptr, lang); if (condResult == "0") { return; } @@ -54,9 +54,9 @@ void cmGeneratorExpressionEvaluationFile::Generate( } std::string outputFileName = this->OutputFileExpr->Evaluate( - lg, config, false, nullptr, nullptr, nullptr, lang); - const std::string& outputContent = inputExpression->Evaluate( - lg, config, false, nullptr, nullptr, nullptr, lang); + lg, config, nullptr, nullptr, nullptr, lang); + const std::string& outputContent = + inputExpression->Evaluate(lg, config, nullptr, nullptr, nullptr, lang); if (cmSystemTools::FileIsFullPath(outputFileName)) { outputFileName = cmSystemTools::CollapseFullPath(outputFileName); @@ -100,8 +100,8 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile( gg->GetEnabledLanguages(enabledLanguages); for (std::string const& le : enabledLanguages) { - std::string name = this->OutputFileExpr->Evaluate( - lg, config, false, nullptr, nullptr, nullptr, le); + std::string name = this->OutputFileExpr->Evaluate(lg, config, nullptr, + nullptr, nullptr, le); cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource( name, false, cmSourceFileLocationKind::Known); // Tell TraceDependencies that the file is not expected to exist diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index d524867..641cbaf 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -45,15 +45,16 @@ std::string cmGeneratorExpressionNode::EvaluateDependentExpression( std::string const& prop, cmLocalGenerator* lg, cmGeneratorExpressionContext* context, cmGeneratorTarget const* headTarget, - cmGeneratorTarget const* currentTarget, - cmGeneratorExpressionDAGChecker* dagChecker) + cmGeneratorExpressionDAGChecker* dagChecker, + cmGeneratorTarget const* currentTarget) { cmGeneratorExpression ge(context->Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); cge->SetEvaluateForBuildsystem(context->EvaluateForBuildsystem); + cge->SetQuiet(context->Quiet); std::string result = - cge->Evaluate(lg, context->Config, context->Quiet, headTarget, - currentTarget, dagChecker, context->Language); + cge->Evaluate(lg, context->Config, headTarget, dagChecker, currentTarget, + context->Language); if (cge->GetHadContextSensitiveCondition()) { context->HadContextSensitiveCondition = true; } @@ -477,13 +478,13 @@ protected: } return this->EvaluateDependentExpression( - expression, context->LG, context, context->HeadTarget, - context->CurrentTarget, &dagChecker); + expression, context->LG, context, context->HeadTarget, &dagChecker, + context->CurrentTarget); } return this->EvaluateDependentExpression( - expression, context->LG, context, context->HeadTarget, - context->CurrentTarget, dagCheckerParent); + expression, context->LG, context, context->HeadTarget, dagCheckerParent, + context->CurrentTarget); } }; @@ -1331,7 +1332,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode if (!interfacePropertyName.empty()) { result = this->EvaluateDependentExpression(result, context->LG, context, - target, target, &dagChecker); + target, &dagChecker, target); std::string linkedTargetsContent = getLinkedTargetsContent( target, interfacePropertyName, context, &dagChecker); if (!linkedTargetsContent.empty()) { diff --git a/Source/cmGeneratorExpressionNode.h b/Source/cmGeneratorExpressionNode.h index 7a36924..13e8484 100644 --- a/Source/cmGeneratorExpressionNode.h +++ b/Source/cmGeneratorExpressionNode.h @@ -43,8 +43,8 @@ struct cmGeneratorExpressionNode static std::string EvaluateDependentExpression( std::string const& prop, cmLocalGenerator* lg, cmGeneratorExpressionContext* context, const cmGeneratorTarget* headTarget, - const cmGeneratorTarget* currentTarget, - cmGeneratorExpressionDAGChecker* dagChecker); + cmGeneratorExpressionDAGChecker* dagChecker, + const cmGeneratorTarget* currentTarget); static const cmGeneratorExpressionNode* GetNode( const std::string& identifier); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 18ca478..07578cc 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -84,16 +84,10 @@ public: virtual ~TargetPropertyEntry() = default; virtual const std::string& Evaluate( - cmLocalGenerator* lg, const std::string& config, bool quiet = false, - cmGeneratorTarget const* headTarget = nullptr, - cmGeneratorTarget const* currentTarget = nullptr, - cmGeneratorExpressionDAGChecker* dagChecker = nullptr, - std::string const& language = std::string()) const = 0; - virtual const std::string& Evaluate( - cmLocalGenerator* lg, const std::string& config, bool quiet, + cmLocalGenerator* lg, const std::string& config, cmGeneratorTarget const* headTarget, cmGeneratorExpressionDAGChecker* dagChecker, - std::string const& language = std::string()) const = 0; + std::string const& language) const = 0; virtual cmListFileBacktrace GetBacktrace() const = 0; virtual std::string const& GetInput() const = 0; @@ -113,23 +107,12 @@ public: { } - const std::string& Evaluate( - cmLocalGenerator* lg, const std::string& config, bool quiet = false, - cmGeneratorTarget const* headTarget = nullptr, - cmGeneratorTarget const* currentTarget = nullptr, - cmGeneratorExpressionDAGChecker* dagChecker = nullptr, - std::string const& language = std::string()) const override - { - return this->ge->Evaluate(lg, config, quiet, headTarget, currentTarget, - dagChecker, language); - } - const std::string& Evaluate( - cmLocalGenerator* lg, const std::string& config, bool quiet, - cmGeneratorTarget const* headTarget, - cmGeneratorExpressionDAGChecker* dagChecker, - std::string const& language = std::string()) const override + const std::string& Evaluate(cmLocalGenerator* lg, const std::string& config, + cmGeneratorTarget const* headTarget, + cmGeneratorExpressionDAGChecker* dagChecker, + std::string const& language) const override { - return this->ge->Evaluate(lg, config, quiet, headTarget, dagChecker, + return this->ge->Evaluate(lg, config, headTarget, dagChecker, nullptr, language); } @@ -161,15 +144,7 @@ public: { } - const std::string& Evaluate(cmLocalGenerator*, const std::string&, bool, - cmGeneratorTarget const*, - cmGeneratorTarget const*, - cmGeneratorExpressionDAGChecker*, - std::string const&) const override - { - return this->PropertyValue; - } - const std::string& Evaluate(cmLocalGenerator*, const std::string&, bool, + const std::string& Evaluate(cmLocalGenerator*, const std::string&, cmGeneratorTarget const*, cmGeneratorExpressionDAGChecker*, std::string const&) const override @@ -198,7 +173,7 @@ cmGeneratorTarget::TargetPropertyEntry* CreateTargetPropertyEntry( return new TargetPropertyEntryGenex(std::move(cge)); } - return new TargetPropertyEntryString(propertyValue, backtrace); + return new TargetPropertyEntryString(propertyValue, std::move(backtrace)); } void CreatePropertyGeneratorExpressions( @@ -245,7 +220,7 @@ EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry( cmGeneratorTarget::TargetPropertyEntry* entry) { EvaluatedTargetPropertyEntry ee(entry->LinkImplItem, entry->GetBacktrace()); - cmExpandList(entry->Evaluate(thisTarget->GetLocalGenerator(), config, false, + cmExpandList(entry->Evaluate(thisTarget->GetLocalGenerator(), config, thisTarget, dagChecker, lang), ee.Values); if (entry->GetHadContextSensitiveCondition()) { @@ -512,9 +487,8 @@ std::string cmGeneratorTarget::GetOutputName( } // Now evaluate genex and update the previously-prepared map entry. - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outName); - i->second = cge->Evaluate(this->LocalGenerator, config); + i->second = + cmGeneratorExpression::Evaluate(outName, this->LocalGenerator, config); } else if (i->second.empty()) { // An empty map entry indicates we have been called recursively // from the above block. @@ -734,9 +708,8 @@ void handleSystemIncludesDep(cmLocalGenerator* lg, { if (const char* dirs = depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) { - cmGeneratorExpression ge; - cmExpandList(ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, - depTgt, dagChecker, language), + cmExpandList(cmGeneratorExpression::Evaluate(dirs, lg, config, headTarget, + dagChecker, depTgt, language), result); } if (!depTgt->IsImported() || excludeImported) { @@ -745,9 +718,8 @@ void handleSystemIncludesDep(cmLocalGenerator* lg, if (const char* dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) { - cmGeneratorExpression ge; - cmExpandList(ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, - depTgt, dagChecker, language), + cmExpandList(cmGeneratorExpression::Evaluate(dirs, lg, config, headTarget, + dagChecker, depTgt, language), result); } } @@ -1117,9 +1089,9 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory( std::vector<std::string> result; for (std::string const& it : this->Target->GetSystemIncludeDirectories()) { - cmGeneratorExpression ge; - cmExpandList(ge.Parse(it)->Evaluate(this->LocalGenerator, config, false, - this, &dagChecker, language), + cmExpandList(cmGeneratorExpression::Evaluate(it, this->LocalGenerator, + config, this, &dagChecker, + nullptr, language), result); } @@ -1225,7 +1197,7 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( if (const char* p = this->GetProperty(prop)) { result = cmGeneratorExpressionNode::EvaluateDependentExpression( - p, context->LG, context, headTarget, this, &dagChecker); + p, context->LG, context, headTarget, &dagChecker, this); } if (cmLinkInterfaceLibraries const* iface = @@ -1315,7 +1287,7 @@ void AddObjectEntries(cmGeneratorTarget const* headTarget, EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace); cmExpandList(cge->Evaluate(headTarget->GetLocalGenerator(), config, - false, headTarget, dagChecker), + headTarget, dagChecker), ee.Values); if (cge->GetHadContextSensitiveCondition()) { ee.ContextDependent = true; @@ -1454,11 +1426,14 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources); // Collect TARGET_OBJECTS of direct object link-dependencies. - std::vector<EvaluatedTargetPropertyEntry> linkObjectsEntries; - AddObjectEntries(this, config, &dagChecker, linkObjectsEntries); + bool contextDependentObjects = false; std::vector<std::string>::size_type numFilesBefore2 = files.size(); - bool contextDependentObjects = - processSources(this, linkObjectsEntries, files, uniqueSrcs, debugSources); + if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) { + std::vector<EvaluatedTargetPropertyEntry> linkObjectsEntries; + AddObjectEntries(this, config, &dagChecker, linkObjectsEntries); + contextDependentObjects = processSources(this, linkObjectsEntries, files, + uniqueSrcs, debugSources); + } if (!contextDependentDirectSources && !(contextDependentInterfaceSources && numFilesBefore < files.size()) && @@ -2540,12 +2515,11 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result, if (!prop) { return; } - cmGeneratorExpression ge; cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr, nullptr); - cmExpandList(ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, - this, &dagChecker), + cmExpandList(cmGeneratorExpression::Evaluate(prop, this->LocalGenerator, + config, this, &dagChecker), result); } @@ -2815,7 +2789,8 @@ void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc) // Check for target references in generator expressions. for (std::string const& cl : cCmdLine) { const std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cl); - cge->Evaluate(this->GeneratorTarget->GetLocalGenerator(), "", true); + cge->SetQuiet(true); + cge->Evaluate(this->GeneratorTarget->GetLocalGenerator(), ""); std::set<cmGeneratorTarget*> geTargets = cge->GetTargets(); targets.insert(geTargets.begin(), geTargets.end()); } @@ -5311,9 +5286,9 @@ void cmGeneratorTarget::ExpandLinkItems( } std::vector<std::string> libs; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); - cmExpandList(cge->Evaluate(this->LocalGenerator, config, false, headTarget, - this, &dagChecker), - libs); + cmExpandList( + cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, this), + libs); this->LookupLinkItems(libs, cge->GetBacktrace(), items); hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); } @@ -5576,18 +5551,15 @@ bool cmGeneratorTarget::ComputeOutputDir(const std::string& config, // Select an output directory. if (const char* config_outdir = this->GetProperty(configProp)) { // Use the user-specified per-configuration output directory. - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(config_outdir); - out = cge->Evaluate(this->LocalGenerator, config); + out = cmGeneratorExpression::Evaluate(config_outdir, this->LocalGenerator, + config); // Skip per-configuration subdirectory. conf.clear(); } else if (const char* outdir = this->GetProperty(propertyName)) { // Use the user-specified output directory. - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outdir); - out = cge->Evaluate(this->LocalGenerator, config); + out = + cmGeneratorExpression::Evaluate(outdir, this->LocalGenerator, config); // Skip per-configuration subdirectory if the value contained a // generator expression. @@ -5655,18 +5627,15 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind, // Select an output directory. if (const char* config_outdir = this->GetProperty(configProp)) { // Use the user-specified per-configuration output directory. - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(config_outdir); - out = cge->Evaluate(this->LocalGenerator, config); + out = cmGeneratorExpression::Evaluate(config_outdir, this->LocalGenerator, + config); // Skip per-configuration subdirectory. conf.clear(); } else if (const char* outdir = this->GetProperty(propertyName)) { // Use the user-specified output directory. - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outdir); - out = cge->Evaluate(this->LocalGenerator, config); + out = + cmGeneratorExpression::Evaluate(outdir, this->LocalGenerator, config); // Skip per-configuration subdirectory if the value contained a // generator expression. @@ -5721,8 +5690,7 @@ bool cmGeneratorTarget::GetRPATH(const std::string& config, return false; } - cmGeneratorExpression ge; - rpath = ge.Parse(value)->Evaluate(this->LocalGenerator, config); + rpath = cmGeneratorExpression::Evaluate(value, this->LocalGenerator, config); return true; } @@ -6383,7 +6351,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cmGeneratorExpression ge(*btIt); std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le); std::string const& evaluated = - cge->Evaluate(this->LocalGenerator, config, false, head, &dagChecker); + cge->Evaluate(this->LocalGenerator, config, head, &dagChecker); cmExpandList(evaluated, llibs); if (cge->GetHadHeadSensitiveCondition()) { impl.HadHeadSensitiveCondition = true; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 372e658..3075c1a 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -555,8 +555,6 @@ protected: cmTarget* FindTargetImpl(std::string const& name) const; cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const; - cmGeneratorTarget* FindImportedGeneratorTargetImpl( - std::string const& name) const; const char* GetPredefinedTargetsFolder(); diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 188aef2..0915189 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -672,10 +672,8 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( for (std::string const& i : configs) { const char* propertyValue = target->Target->GetMakefile()->GetDefinition(propertyName); - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(propertyValue); - if (cmIsOn(cge->Evaluate(target->GetLocalGenerator(), i))) { + if (cmIsOn(cmGeneratorExpression::Evaluate( + propertyValue, target->GetLocalGenerator(), i))) { activeConfigs.insert(i); } } diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 255739d..f25d2e2 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -284,11 +284,9 @@ bool cmGlobalVisualStudio8Generator::DeployInhibited( cmGeneratorTarget const& target, const char* config) const { bool rVal = false; - if (const char* propStr = target.GetProperty("VS_NO_SOLUTION_DEPLOY")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propStr); - std::string prop = cge->Evaluate(target.LocalGenerator, config); - rVal = cmIsOn(prop); + if (const char* prop = target.GetProperty("VS_NO_SOLUTION_DEPLOY")) { + rVal = cmIsOn( + cmGeneratorExpression::Evaluate(prop, target.LocalGenerator, config)); } return rVal; } diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 1cb8b53..7a564ed 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -891,7 +891,6 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( gt->LocalGenerator->ComputeObjectFilenames(mapping, gt); std::string obj_dir = gt->ObjectDirectory; std::string cmakeCommand = cmSystemTools::GetCMakeCommand(); - cmSystemTools::ConvertToWindowsExtendedPath(cmakeCommand); std::string obj_dir_expanded = obj_dir; cmSystemTools::ReplaceString(obj_dir_expanded, this->GetCMakeCFGIntDir(), configName.c_str()); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 643cc99..2c3d3ad 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2381,10 +2381,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, std::string attribute = prop.substr(16); this->FilterConfigurationAttribute(configName, attribute); if (!attribute.empty()) { - cmGeneratorExpression ge; - std::string processed = - ge.Parse(gtgt->GetProperty(prop)) - ->Evaluate(this->CurrentLocalGenerator, configName); + std::string processed = cmGeneratorExpression::Evaluate( + gtgt->GetProperty(prop), this->CurrentLocalGenerator, configName); buildSettings->AddAttribute(attribute, this->CreateString(processed)); } @@ -3118,10 +3116,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( std::string attribute = var.substr(22); this->FilterConfigurationAttribute(config.first, attribute); if (!attribute.empty()) { - cmGeneratorExpression ge; - std::string processed = - ge.Parse(this->CurrentMakefile->GetDefinition(var)) - ->Evaluate(this->CurrentLocalGenerator, config.first); + std::string processed = cmGeneratorExpression::Evaluate( + this->CurrentMakefile->GetDefinition(var), + this->CurrentLocalGenerator, config.first); buildSettingsForCfg->AddAttribute(attribute, this->CreateString(processed)); } diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index a4d0a0d..170aea1 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -7,24 +7,28 @@ #include <utility> #include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; +static void GetIncludes(cmMakefile& mf, const std::string& arg, + std::vector<std::string>& incs); +static void NormalizeInclude(cmMakefile& mf, std::string& inc); -// cmIncludeDirectoryCommand -bool cmIncludeDirectoryCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmIncludeDirectoryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { return true; } + cmMakefile& mf = status.GetMakefile(); + auto i = args.begin(); - bool before = this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_BEFORE"); + bool before = mf.IsOn("CMAKE_INCLUDE_DIRECTORIES_BEFORE"); bool system = false; if ((*i) == "BEFORE") { @@ -45,13 +49,13 @@ bool cmIncludeDirectoryCommand::InitialPass( continue; } if (i->empty()) { - this->SetError("given empty-string as include directory."); + status.SetError("given empty-string as include directory."); return false; } std::vector<std::string> includes; - this->GetIncludes(*i, includes); + GetIncludes(mf, *i, includes); if (before) { cmAppend(beforeIncludes, includes); @@ -64,9 +68,9 @@ bool cmIncludeDirectoryCommand::InitialPass( } std::reverse(beforeIncludes.begin(), beforeIncludes.end()); - this->Makefile->AddIncludeDirectories(afterIncludes); - this->Makefile->AddIncludeDirectories(beforeIncludes, before); - this->Makefile->AddSystemIncludeDirectories(systemIncludes); + mf.AddIncludeDirectories(afterIncludes); + mf.AddIncludeDirectories(beforeIncludes, before); + mf.AddSystemIncludeDirectories(systemIncludes); return true; } @@ -83,8 +87,8 @@ bool cmIncludeDirectoryCommand::InitialPass( // output from a program and passing it into a command the cleanup doesn't // always happen // -void cmIncludeDirectoryCommand::GetIncludes(const std::string& arg, - std::vector<std::string>& incs) +static void GetIncludes(cmMakefile& mf, const std::string& arg, + std::vector<std::string>& incs) { // break apart any line feed arguments std::string::size_type pos = 0; @@ -92,7 +96,7 @@ void cmIncludeDirectoryCommand::GetIncludes(const std::string& arg, while ((pos = arg.find('\n', lastPos)) != std::string::npos) { if (pos) { std::string inc = arg.substr(lastPos, pos); - this->NormalizeInclude(inc); + NormalizeInclude(mf, inc); if (!inc.empty()) { incs.push_back(std::move(inc)); } @@ -100,13 +104,13 @@ void cmIncludeDirectoryCommand::GetIncludes(const std::string& arg, lastPos = pos + 1; } std::string inc = arg.substr(lastPos); - this->NormalizeInclude(inc); + NormalizeInclude(mf, inc); if (!inc.empty()) { incs.push_back(std::move(inc)); } } -void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc) +static void NormalizeInclude(cmMakefile& mf, std::string& inc) { std::string::size_type b = inc.find_first_not_of(" \r"); std::string::size_type e = inc.find_last_not_of(" \r"); @@ -119,13 +123,9 @@ void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc) if (!cmIsOff(inc)) { cmSystemTools::ConvertToUnixSlashes(inc); - - if (!cmSystemTools::FileIsFullPath(inc)) { - if (!cmGeneratorExpression::StartsWithGeneratorExpression(inc)) { - std::string tmp = - cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', inc); - inc = tmp; - } + if (!cmSystemTools::FileIsFullPath(inc) && + !cmGeneratorExpression::StartsWithGeneratorExpression(inc)) { + inc = cmStrCat(mf.GetCurrentSourceDirectory(), '/', inc); } } } diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h index bcaae9d..66caff7 100644 --- a/Source/cmIncludeDirectoryCommand.h +++ b/Source/cmIncludeDirectoryCommand.h @@ -8,40 +8,9 @@ #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmIncludeDirectoryCommand - * \brief Add include directories to the build. - * - * cmIncludeDirectoryCommand is used to specify directory locations - * to search for included files. - */ -class cmIncludeDirectoryCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmIncludeDirectoryCommand>(); - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -protected: - // used internally - void GetIncludes(const std::string& arg, std::vector<std::string>& incs); - void NormalizeInclude(std::string& inc); -}; +bool cmIncludeDirectoryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index f7050d4..27d0dfb 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -4,12 +4,14 @@ #include "cm_static_string_view.hxx" #include "cmsys/Glob.hxx" +#include <cm/memory> #include <cstddef> #include <set> #include <sstream> #include <utility> #include "cmArgumentParser.h" +#include "cmExecutionStatus.h" #include "cmExportSet.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -26,13 +28,61 @@ #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" +#include "cmSubcommandTable.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" -class cmExecutionStatus; +namespace { -static cmInstallTargetGenerator* CreateInstallTargetGenerator( +class Helper +{ +public: + Helper(cmExecutionStatus& status) + : Status(status) + , Makefile(&status.GetMakefile()) + { + this->DefaultComponentName = this->Makefile->GetSafeDefinition( + "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); + if (this->DefaultComponentName.empty()) { + this->DefaultComponentName = "Unspecified"; + } + } + + void SetError(std::string const& err) { this->Status.SetError(err); } + + bool MakeFilesFullPath(const char* modeName, + const std::vector<std::string>& relFiles, + std::vector<std::string>& absFiles); + bool CheckCMP0006(bool& failure); + + std::string GetDestination(const cmInstallCommandArguments* args, + const std::string& varName, + const std::string& guess); + std::string GetRuntimeDestination(const cmInstallCommandArguments* args); + std::string GetSbinDestination(const cmInstallCommandArguments* args); + std::string GetArchiveDestination(const cmInstallCommandArguments* args); + std::string GetLibraryDestination(const cmInstallCommandArguments* args); + std::string GetIncludeDestination(const cmInstallCommandArguments* args); + std::string GetSysconfDestination(const cmInstallCommandArguments* args); + std::string GetSharedStateDestination(const cmInstallCommandArguments* args); + std::string GetLocalStateDestination(const cmInstallCommandArguments* args); + std::string GetRunStateDestination(const cmInstallCommandArguments* args); + std::string GetDataRootDestination(const cmInstallCommandArguments* args); + std::string GetDataDestination(const cmInstallCommandArguments* args); + std::string GetInfoDestination(const cmInstallCommandArguments* args); + std::string GetLocaleDestination(const cmInstallCommandArguments* args); + std::string GetManDestination(const cmInstallCommandArguments* args); + std::string GetDocDestination(const cmInstallCommandArguments* args); + std::string GetDestinationForType(const cmInstallCommandArguments* args, + const std::string& type); + + cmExecutionStatus& Status; + cmMakefile* Makefile; + std::string DefaultComponentName; +}; + +cmInstallTargetGenerator* CreateInstallTargetGenerator( cmTarget& target, const cmInstallCommandArguments& args, bool impLib, cmListFileBacktrace const& backtrace, const std::string& destination, bool forceOpt = false, bool namelink = false) @@ -51,7 +101,7 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator( return g; } -static cmInstallTargetGenerator* CreateInstallTargetGenerator( +cmInstallTargetGenerator* CreateInstallTargetGenerator( cmTarget& target, const cmInstallCommandArguments& args, bool impLib, cmListFileBacktrace const& backtrace, bool forceOpt = false, bool namelink = false) @@ -61,7 +111,7 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator( namelink); } -static cmInstallFilesGenerator* CreateInstallFilesGenerator( +cmInstallFilesGenerator* CreateInstallFilesGenerator( cmMakefile* mf, const std::vector<std::string>& absFiles, const cmInstallCommandArguments& args, bool programs, const std::string& destination) @@ -74,7 +124,7 @@ static cmInstallFilesGenerator* CreateInstallFilesGenerator( args.GetExcludeFromAll(), args.GetRename().c_str(), args.GetOptional()); } -static cmInstallFilesGenerator* CreateInstallFilesGenerator( +cmInstallFilesGenerator* CreateInstallFilesGenerator( cmMakefile* mf, const std::vector<std::string>& absFiles, const cmInstallCommandArguments& args, bool programs) { @@ -82,68 +132,18 @@ static cmInstallFilesGenerator* CreateInstallFilesGenerator( args.GetDestination()); } -static const std::set<std::string> allowedTypes{ +std::set<std::string> const allowedTypes{ "BIN", "SBIN", "LIB", "INCLUDE", "SYSCONF", "SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA", "INFO", "LOCALE", "MAN", "DOC", }; -// cmInstallCommand -bool cmInstallCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool HandleScriptMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { - // Allow calling with no arguments so that arguments may be built up - // using a variable that may be left empty. - if (args.empty()) { - return true; - } - - // Enable the install target. - this->Makefile->GetGlobalGenerator()->EnableInstallTarget(); - - this->DefaultComponentName = - this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); - if (this->DefaultComponentName.empty()) { - this->DefaultComponentName = "Unspecified"; - } - - std::string const& mode = args[0]; - - // Switch among the command modes. - if (mode == "SCRIPT") { - return this->HandleScriptMode(args); - } - if (mode == "CODE") { - return this->HandleScriptMode(args); - } - if (mode == "TARGETS") { - return this->HandleTargetsMode(args); - } - if (mode == "FILES") { - return this->HandleFilesMode(args); - } - if (mode == "PROGRAMS") { - return this->HandleFilesMode(args); - } - if (mode == "DIRECTORY") { - return this->HandleDirectoryMode(args); - } - if (mode == "EXPORT") { - return this->HandleExportMode(args); - } - if (mode == "EXPORT_ANDROID_MK") { - return this->HandleExportAndroidMKMode(args); - } - - // Unknown mode. - std::string e = cmStrCat("called with unknown mode ", args[0]); - this->SetError(e); - return false; -} + Helper helper(status); -bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args) -{ - std::string component = this->DefaultComponentName; + std::string component = helper.DefaultComponentName; int componentCount = 0; bool doing_script = false; bool doing_code = false; @@ -163,9 +163,9 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args) } if (componentCount > 1) { - this->SetError("given more than one COMPONENT for the SCRIPT or CODE " - "signature of the INSTALL command. " - "Use multiple INSTALL commands with one COMPONENT each."); + status.SetError("given more than one COMPONENT for the SCRIPT or CODE " + "signature of the INSTALL command. " + "Use multiple INSTALL commands with one COMPONENT each."); return false; } @@ -187,40 +187,43 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args) std::string script = arg; if (!cmSystemTools::FileIsFullPath(script)) { script = - cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', arg); + cmStrCat(helper.Makefile->GetCurrentSourceDirectory(), '/', arg); } if (cmSystemTools::FileIsDirectory(script)) { - this->SetError("given a directory as value of SCRIPT argument."); + status.SetError("given a directory as value of SCRIPT argument."); return false; } - this->Makefile->AddInstallGenerator(new cmInstallScriptGenerator( + helper.Makefile->AddInstallGenerator(new cmInstallScriptGenerator( script.c_str(), false, component.c_str(), exclude_from_all)); } else if (doing_code) { doing_code = false; std::string const& code = arg; - this->Makefile->AddInstallGenerator(new cmInstallScriptGenerator( + helper.Makefile->AddInstallGenerator(new cmInstallScriptGenerator( code.c_str(), true, component.c_str(), exclude_from_all)); } } if (doing_script) { - this->SetError("given no value for SCRIPT argument."); + status.SetError("given no value for SCRIPT argument."); return false; } if (doing_code) { - this->SetError("given no value for CODE argument."); + status.SetError("given no value for CODE argument."); return false; } // Tell the global generator about any installation component names // specified. - this->Makefile->GetGlobalGenerator()->AddInstallComponent(component); + helper.Makefile->GetGlobalGenerator()->AddInstallComponent(component); return true; } -bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) +bool HandleTargetsMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { + Helper helper(status); + // This is the TARGETS mode. std::vector<cmTarget*> targets; @@ -260,21 +263,21 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) std::vector<std::string> targetList; std::string exports; std::vector<std::string> unknownArgs; - cmInstallCommandArguments genericArgs(this->DefaultComponentName); + cmInstallCommandArguments genericArgs(helper.DefaultComponentName); genericArgs.Bind("TARGETS"_s, targetList); genericArgs.Bind("EXPORT"_s, exports); genericArgs.Parse(genericArgVector, &unknownArgs); bool success = genericArgs.Finalize(); - cmInstallCommandArguments archiveArgs(this->DefaultComponentName); - cmInstallCommandArguments libraryArgs(this->DefaultComponentName); - cmInstallCommandArguments runtimeArgs(this->DefaultComponentName); - cmInstallCommandArguments objectArgs(this->DefaultComponentName); - cmInstallCommandArguments frameworkArgs(this->DefaultComponentName); - cmInstallCommandArguments bundleArgs(this->DefaultComponentName); - cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName); - cmInstallCommandArguments publicHeaderArgs(this->DefaultComponentName); - cmInstallCommandArguments resourceArgs(this->DefaultComponentName); + cmInstallCommandArguments archiveArgs(helper.DefaultComponentName); + cmInstallCommandArguments libraryArgs(helper.DefaultComponentName); + cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName); + cmInstallCommandArguments objectArgs(helper.DefaultComponentName); + cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName); + cmInstallCommandArguments bundleArgs(helper.DefaultComponentName); + cmInstallCommandArguments privateHeaderArgs(helper.DefaultComponentName); + cmInstallCommandArguments publicHeaderArgs(helper.DefaultComponentName); + cmInstallCommandArguments resourceArgs(helper.DefaultComponentName); cmInstallCommandIncludesArgument includesArgs; // now parse the args for specific parts of the target (e.g. LIBRARY, @@ -292,7 +295,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) if (!unknownArgs.empty()) { // Unknown argument. - this->SetError( + status.SetError( cmStrCat("TARGETS given unknown argument \"", unknownArgs[0], "\".")); return false; } @@ -328,7 +331,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() || bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() || publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly()) { - this->SetError( + status.SetError( "TARGETS given NAMELINK_ONLY option not in LIBRARY group. " "The NAMELINK_ONLY option may be specified only following LIBRARY."); return false; @@ -337,7 +340,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() || bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() || publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip()) { - this->SetError( + status.SetError( "TARGETS given NAMELINK_SKIP option not in LIBRARY group. " "The NAMELINK_SKIP option may be specified only following LIBRARY."); return false; @@ -350,15 +353,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) privateHeaderArgs.HasNamelinkComponent() || publicHeaderArgs.HasNamelinkComponent() || resourceArgs.HasNamelinkComponent()) { - this->SetError( + status.SetError( "TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. " "The NAMELINK_COMPONENT option may be specified only following " "LIBRARY."); return false; } if (libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip()) { - this->SetError("TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. " - "At most one of these two options may be specified."); + status.SetError("TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. " + "At most one of these two options may be specified."); return false; } if (!genericArgs.GetType().empty() || !archiveArgs.GetType().empty() || @@ -366,7 +369,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) !objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() || !bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() || !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) { - this->SetError( + status.SetError( "TARGETS given TYPE option. The TYPE option may only be specified in " " install(FILES) and install(DIRECTORIES)."); return false; @@ -388,17 +391,17 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) for (std::string const& tgt : targetList) { - if (this->Makefile->IsAlias(tgt)) { - this->SetError( + if (helper.Makefile->IsAlias(tgt)) { + status.SetError( cmStrCat("TARGETS given target \"", tgt, "\" which is an alias.")); return false; } // Lookup this target in the current directory. - cmTarget* target = this->Makefile->FindLocalNonAliasTarget(tgt); + cmTarget* target = helper.Makefile->FindLocalNonAliasTarget(tgt); if (!target) { // If no local target has been found, find it in the global scope. cmTarget* const global_target = - this->Makefile->GetGlobalGenerator()->FindTarget(tgt, true); + helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true); if (global_target && !global_target->IsImported()) { target = global_target; } @@ -411,7 +414,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) target->GetType() != cmStateEnums::MODULE_LIBRARY && target->GetType() != cmStateEnums::OBJECT_LIBRARY && target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - this->SetError( + status.SetError( cmStrCat("TARGETS given target \"", tgt, "\" which is not an executable, library, or module.")); return false; @@ -420,7 +423,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) targets.push_back(target); } else { // Did not find the target. - this->SetError( + status.SetError( cmStrCat("TARGETS given target \"", tgt, "\" which does not exist.")); return false; } @@ -472,20 +475,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) if (!archiveArgs.GetDestination().empty()) { // The import library uses the ARCHIVE properties. archiveGenerator = CreateInstallTargetGenerator( - target, archiveArgs, true, this->Makefile->GetBacktrace()); + target, archiveArgs, true, helper.Makefile->GetBacktrace()); } if (!runtimeArgs.GetDestination().empty()) { // The DLL uses the RUNTIME properties. runtimeGenerator = CreateInstallTargetGenerator( - target, runtimeArgs, false, this->Makefile->GetBacktrace()); + target, runtimeArgs, false, helper.Makefile->GetBacktrace()); } if ((archiveGenerator == nullptr) && (runtimeGenerator == nullptr)) { archiveGenerator = CreateInstallTargetGenerator( - target, archiveArgs, true, this->Makefile->GetBacktrace(), - this->GetArchiveDestination(nullptr)); + target, archiveArgs, true, helper.Makefile->GetBacktrace(), + helper.GetArchiveDestination(nullptr)); runtimeGenerator = CreateInstallTargetGenerator( - target, runtimeArgs, false, this->Makefile->GetBacktrace(), - this->GetRuntimeDestination(nullptr)); + target, runtimeArgs, false, helper.Makefile->GetBacktrace(), + helper.GetRuntimeDestination(nullptr)); } } else { // This is a non-DLL platform. @@ -500,9 +503,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // Use the FRAMEWORK properties. if (!frameworkArgs.GetDestination().empty()) { frameworkGenerator = CreateInstallTargetGenerator( - target, frameworkArgs, false, this->Makefile->GetBacktrace()); + target, frameworkArgs, false, helper.Makefile->GetBacktrace()); } else { - this->SetError( + status.SetError( cmStrCat("TARGETS given no FRAMEWORK DESTINATION for shared " "library FRAMEWORK target \"", target.GetName(), "\".")); @@ -512,15 +515,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // The shared library uses the LIBRARY properties. if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) { libraryGenerator = CreateInstallTargetGenerator( - target, libraryArgs, false, this->Makefile->GetBacktrace(), - this->GetLibraryDestination(&libraryArgs)); + target, libraryArgs, false, helper.Makefile->GetBacktrace(), + helper.GetLibraryDestination(&libraryArgs)); libraryGenerator->SetNamelinkMode( cmInstallTargetGenerator::NamelinkModeSkip); } if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) { namelinkGenerator = CreateInstallTargetGenerator( - target, libraryArgs, false, this->Makefile->GetBacktrace(), - this->GetLibraryDestination(&libraryArgs), false, true); + target, libraryArgs, false, helper.Makefile->GetBacktrace(), + helper.GetLibraryDestination(&libraryArgs), false, true); namelinkGenerator->SetNamelinkMode( cmInstallTargetGenerator::NamelinkModeOnly); } @@ -541,32 +544,31 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // Use the FRAMEWORK properties. if (!frameworkArgs.GetDestination().empty()) { frameworkGenerator = CreateInstallTargetGenerator( - target, frameworkArgs, false, this->Makefile->GetBacktrace()); + target, frameworkArgs, false, helper.Makefile->GetBacktrace()); } else { - this->SetError( + status.SetError( cmStrCat("TARGETS given no FRAMEWORK DESTINATION for static " "library FRAMEWORK target \"", target.GetName(), "\".")); - return false; } } else { // Static libraries use ARCHIVE properties. archiveGenerator = CreateInstallTargetGenerator( - target, archiveArgs, false, this->Makefile->GetBacktrace(), - this->GetArchiveDestination(&archiveArgs)); + target, archiveArgs, false, helper.Makefile->GetBacktrace(), + helper.GetArchiveDestination(&archiveArgs)); } } break; case cmStateEnums::MODULE_LIBRARY: { // Modules use LIBRARY properties. if (!libraryArgs.GetDestination().empty()) { libraryGenerator = CreateInstallTargetGenerator( - target, libraryArgs, false, this->Makefile->GetBacktrace()); + target, libraryArgs, false, helper.Makefile->GetBacktrace()); libraryGenerator->SetNamelinkMode(namelinkMode); namelinkOnly = (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); } else { - this->SetError( + status.SetError( cmStrCat("TARGETS given no LIBRARY DESTINATION for module " "target \"", target.GetName(), "\".")); @@ -578,16 +580,16 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) if (!objectArgs.GetDestination().empty()) { // Verify that we know where the objects are to install them. std::string reason; - if (!this->Makefile->GetGlobalGenerator() + if (!helper.Makefile->GetGlobalGenerator() ->HasKnownObjectFileLocation(&reason)) { - this->SetError( + status.SetError( cmStrCat("TARGETS given OBJECT library \"", target.GetName(), "\" whose objects may not be installed", reason, ".")); return false; } objectGenerator = CreateInstallTargetGenerator( - target, objectArgs, false, this->Makefile->GetBacktrace()); + target, objectArgs, false, helper.Makefile->GetBacktrace()); } else { // Installing an OBJECT library without a destination transforms // it to an INTERFACE library. It installs no files but can be @@ -599,29 +601,29 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // Application bundles use the BUNDLE properties. if (!bundleArgs.GetDestination().empty()) { bundleGenerator = CreateInstallTargetGenerator( - target, bundleArgs, false, this->Makefile->GetBacktrace()); + target, bundleArgs, false, helper.Makefile->GetBacktrace()); } else if (!runtimeArgs.GetDestination().empty()) { bool failure = false; - if (this->CheckCMP0006(failure)) { + if (helper.CheckCMP0006(failure)) { // For CMake 2.4 compatibility fallback to the RUNTIME // properties. bundleGenerator = CreateInstallTargetGenerator( - target, runtimeArgs, false, this->Makefile->GetBacktrace()); + target, runtimeArgs, false, helper.Makefile->GetBacktrace()); } else if (failure) { return false; } } if (!bundleGenerator) { - this->SetError(cmStrCat("TARGETS given no BUNDLE DESTINATION for " - "MACOSX_BUNDLE executable target \"", - target.GetName(), "\".")); + status.SetError(cmStrCat("TARGETS given no BUNDLE DESTINATION for " + "MACOSX_BUNDLE executable target \"", + target.GetName(), "\".")); return false; } } else { // Executables use the RUNTIME properties. runtimeGenerator = CreateInstallTargetGenerator( - target, runtimeArgs, false, this->Makefile->GetBacktrace(), - this->GetRuntimeDestination(&runtimeArgs)); + target, runtimeArgs, false, helper.Makefile->GetBacktrace(), + helper.GetRuntimeDestination(&runtimeArgs)); } // On DLL platforms an executable may also have an import @@ -632,7 +634,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) target.IsExecutableWithExports()) { // The import library uses the ARCHIVE properties. archiveGenerator = CreateInstallTargetGenerator( - target, archiveArgs, true, this->Makefile->GetBacktrace(), true); + target, archiveArgs, true, helper.Makefile->GetBacktrace(), true); } } break; case cmStateEnums::INTERFACE_LIBRARY: @@ -662,42 +664,42 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) if ((files) && (*files)) { std::vector<std::string> relFiles = cmExpandedList(files); std::vector<std::string> absFiles; - if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) { + if (!helper.MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) { return false; } // Create the files install generator. privateHeaderGenerator = CreateInstallFilesGenerator( - this->Makefile, absFiles, privateHeaderArgs, false, - this->GetIncludeDestination(&privateHeaderArgs)); + helper.Makefile, absFiles, privateHeaderArgs, false, + helper.GetIncludeDestination(&privateHeaderArgs)); } files = target.GetProperty("PUBLIC_HEADER"); if ((files) && (*files)) { std::vector<std::string> relFiles = cmExpandedList(files); std::vector<std::string> absFiles; - if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) { + if (!helper.MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) { return false; } // Create the files install generator. publicHeaderGenerator = CreateInstallFilesGenerator( - this->Makefile, absFiles, publicHeaderArgs, false, - this->GetIncludeDestination(&publicHeaderArgs)); + helper.Makefile, absFiles, publicHeaderArgs, false, + helper.GetIncludeDestination(&publicHeaderArgs)); } files = target.GetProperty("RESOURCE"); if ((files) && (*files)) { std::vector<std::string> relFiles = cmExpandedList(files); std::vector<std::string> absFiles; - if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles)) { + if (!helper.MakeFilesFullPath("RESOURCE", relFiles, absFiles)) { return false; } // Create the files install generator. if (!resourceArgs.GetDestination().empty()) { resourceGenerator = CreateInstallFilesGenerator( - this->Makefile, absFiles, resourceArgs, false); + helper.Makefile, absFiles, resourceArgs, false); } else { cmSystemTools::Message( cmStrCat("INSTALL TARGETS - target ", target.GetName(), @@ -721,16 +723,16 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) installsPublicHeader || publicHeaderGenerator != nullptr; installsResource = installsResource || resourceGenerator; - this->Makefile->AddInstallGenerator(archiveGenerator); - this->Makefile->AddInstallGenerator(libraryGenerator); - this->Makefile->AddInstallGenerator(namelinkGenerator); - this->Makefile->AddInstallGenerator(runtimeGenerator); - this->Makefile->AddInstallGenerator(objectGenerator); - this->Makefile->AddInstallGenerator(frameworkGenerator); - this->Makefile->AddInstallGenerator(bundleGenerator); - this->Makefile->AddInstallGenerator(privateHeaderGenerator); - this->Makefile->AddInstallGenerator(publicHeaderGenerator); - this->Makefile->AddInstallGenerator(resourceGenerator); + helper.Makefile->AddInstallGenerator(archiveGenerator); + helper.Makefile->AddInstallGenerator(libraryGenerator); + helper.Makefile->AddInstallGenerator(namelinkGenerator); + helper.Makefile->AddInstallGenerator(runtimeGenerator); + helper.Makefile->AddInstallGenerator(objectGenerator); + helper.Makefile->AddInstallGenerator(frameworkGenerator); + helper.Makefile->AddInstallGenerator(bundleGenerator); + helper.Makefile->AddInstallGenerator(privateHeaderGenerator); + helper.Makefile->AddInstallGenerator(publicHeaderGenerator); + helper.Makefile->AddInstallGenerator(resourceGenerator); // Add this install rule to an export if one was specified and // this is not a namelink-only rule. @@ -747,7 +749,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) te->InterfaceIncludeDirectories = cmJoin(includesArgs.GetIncludeDirs(), ";"); - this->Makefile->GetGlobalGenerator() + helper.Makefile->GetGlobalGenerator() ->GetExportSets()[exports] .AddTargetExport(std::move(te)); } @@ -756,54 +758,57 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // Tell the global generator about any installation component names // specified if (installsArchive) { - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( archiveArgs.GetComponent()); } if (installsLibrary) { - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( libraryArgs.GetComponent()); } if (installsNamelink) { - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( libraryArgs.GetNamelinkComponent()); } if (installsRuntime) { - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( runtimeArgs.GetComponent()); } if (installsObject) { - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( objectArgs.GetComponent()); } if (installsFramework) { - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( frameworkArgs.GetComponent()); } if (installsBundle) { - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( bundleArgs.GetComponent()); } if (installsPrivateHeader) { - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( privateHeaderArgs.GetComponent()); } if (installsPublicHeader) { - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( publicHeaderArgs.GetComponent()); } if (installsResource) { - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( resourceArgs.GetComponent()); } return true; } -bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) +bool HandleFilesMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { + Helper helper(status); + // This is the FILES mode. bool programs = (args[0] == "PROGRAMS"); - cmInstallCommandArguments ica(this->DefaultComponentName); + cmInstallCommandArguments ica(helper.DefaultComponentName); std::vector<std::string> files; ica.Bind(programs ? "PROGRAMS"_s : "FILES"_s, files); std::vector<std::string> unknownArgs; @@ -811,14 +816,14 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) if (!unknownArgs.empty()) { // Unknown argument. - this->SetError( + status.SetError( cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\".")); return false; } std::string type = ica.GetType(); if (!type.empty() && allowedTypes.count(type) == 0) { - this->SetError( + status.SetError( cmStrCat(args[0], " given non-type \"", type, "\" with TYPE argument.")); return false; } @@ -832,27 +837,27 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) if (!ica.GetRename().empty() && filesVector.size() > 1) { // The rename option works only with one file. - this->SetError( + status.SetError( cmStrCat(args[0], " given RENAME option with more than one file.")); return false; } std::vector<std::string> absFiles; - if (!this->MakeFilesFullPath(args[0].c_str(), filesVector, absFiles)) { + if (!helper.MakeFilesFullPath(args[0].c_str(), filesVector, absFiles)) { return false; } - cmPolicies::PolicyStatus status = - this->Makefile->GetPolicyStatus(cmPolicies::CMP0062); + cmPolicies::PolicyStatus policyStatus = + helper.Makefile->GetPolicyStatus(cmPolicies::CMP0062); - cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + cmGlobalGenerator* gg = helper.Makefile->GetGlobalGenerator(); for (std::string const& file : filesVector) { if (gg->IsExportedTargetsFile(file)) { const char* modal = nullptr; std::ostringstream e; MessageType messageType = MessageType::AUTHOR_WARNING; - switch (status) { + switch (policyStatus) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0062) << "\n"; modal = "should"; @@ -872,7 +877,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) << " not be installed with the " "install() command. Use the install(EXPORT) mechanism " "instead. See the cmake-packages(7) manual for more.\n"; - this->Makefile->IssueMessage(messageType, e.str()); + helper.Makefile->IssueMessage(messageType, e.str()); if (messageType == MessageType::FATAL_ERROR) { return false; } @@ -885,34 +890,36 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) } if (!type.empty() && !ica.GetDestination().empty()) { - this->SetError(cmStrCat(args[0], - " given both TYPE and DESTINATION arguments. " - "You may only specify one.")); + status.SetError(cmStrCat(args[0], + " given both TYPE and DESTINATION arguments. " + "You may only specify one.")); return false; } - std::string destination = this->GetDestinationForType(&ica, type); + std::string destination = helper.GetDestinationForType(&ica, type); if (destination.empty()) { // A destination is required. - this->SetError(cmStrCat(args[0], " given no DESTINATION!")); + status.SetError(cmStrCat(args[0], " given no DESTINATION!")); return false; } // Create the files install generator. - this->Makefile->AddInstallGenerator(CreateInstallFilesGenerator( - this->Makefile, absFiles, ica, programs, destination)); + helper.Makefile->AddInstallGenerator(CreateInstallFilesGenerator( + helper.Makefile, absFiles, ica, programs, destination)); // Tell the global generator about any installation component names // specified. - this->Makefile->GetGlobalGenerator()->AddInstallComponent( + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( ica.GetComponent()); return true; } -bool cmInstallCommand::HandleDirectoryMode( - std::vector<std::string> const& args) +bool HandleDirectoryMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { + Helper helper(status); + enum Doing { DoingNone, @@ -937,14 +944,14 @@ bool cmInstallCommand::HandleDirectoryMode( std::string permissions_file; std::string permissions_dir; std::vector<std::string> configurations; - std::string component = this->DefaultComponentName; + std::string component = helper.DefaultComponentName; std::string literal_args; std::string type; for (unsigned int i = 1; i < args.size(); ++i) { if (args[i] == "DESTINATION") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -952,8 +959,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingDestination; } else if (args[i] == "TYPE") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -961,8 +968,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingType; } else if (args[i] == "OPTIONAL") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -971,8 +978,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingNone; } else if (args[i] == "MESSAGE_NEVER") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -990,16 +997,16 @@ bool cmInstallCommand::HandleDirectoryMode( } else if (args[i] == "EXCLUDE") { // Add this property to the current match rule. if (!in_match_mode || doing == DoingPattern || doing == DoingRegex) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" before a PATTERN or REGEX is given.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" before a PATTERN or REGEX is given.")); return false; } literal_args += " EXCLUDE"; doing = DoingNone; } else if (args[i] == "PERMISSIONS") { if (!in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" before a PATTERN or REGEX is given.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" before a PATTERN or REGEX is given.")); return false; } @@ -1008,8 +1015,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingPermsMatch; } else if (args[i] == "FILE_PERMISSIONS") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1017,8 +1024,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingPermsFile; } else if (args[i] == "DIRECTORY_PERMISSIONS") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1026,8 +1033,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingPermsDir; } else if (args[i] == "USE_SOURCE_PERMISSIONS") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1036,8 +1043,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingNone; } else if (args[i] == "FILES_MATCHING") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1046,8 +1053,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingNone; } else if (args[i] == "CONFIGURATIONS") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1055,8 +1062,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingConfigurations; } else if (args[i] == "COMPONENT") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1064,8 +1071,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingComponent; } else if (args[i] == "EXCLUDE_FROM_ALL") { if (in_match_mode) { - this->SetError(cmStrCat(args[0], " does not allow \"", args[i], - "\" after PATTERN or REGEX.")); + status.SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } exclude_from_all = true; @@ -1076,14 +1083,14 @@ bool cmInstallCommand::HandleDirectoryMode( std::string::size_type gpos = cmGeneratorExpression::Find(dir); if (gpos != 0 && !cmSystemTools::FileIsFullPath(dir)) { dir = - cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', args[i]); + cmStrCat(helper.Makefile->GetCurrentSourceDirectory(), '/', args[i]); } // Make sure the name is a directory. if (cmSystemTools::FileExists(dir) && !cmSystemTools::FileIsDirectory(dir)) { - this->SetError(cmStrCat(args[0], " given non-directory \"", args[i], - "\" to install.")); + status.SetError(cmStrCat(args[0], " given non-directory \"", args[i], + "\" to install.")); return false; } @@ -1096,8 +1103,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingNone; } else if (doing == DoingType) { if (allowedTypes.count(args[i]) == 0) { - this->SetError(cmStrCat(args[0], " given non-type \"", args[i], - "\" with TYPE argument.")); + status.SetError(cmStrCat(args[0], " given non-type \"", args[i], + "\" with TYPE argument.")); return false; } @@ -1133,15 +1140,15 @@ bool cmInstallCommand::HandleDirectoryMode( // Check the requested permission. if (!cmInstallCommandArguments::CheckPermissions(args[i], permissions_file)) { - this->SetError(cmStrCat(args[0], " given invalid file permission \"", - args[i], "\".")); + status.SetError(cmStrCat(args[0], " given invalid file permission \"", + args[i], "\".")); return false; } } else if (doing == DoingPermsDir) { // Check the requested permission. if (!cmInstallCommandArguments::CheckPermissions(args[i], permissions_dir)) { - this->SetError(cmStrCat( + status.SetError(cmStrCat( args[0], " given invalid directory permission \"", args[i], "\".")); return false; } @@ -1149,13 +1156,13 @@ bool cmInstallCommand::HandleDirectoryMode( // Check the requested permission. if (!cmInstallCommandArguments::CheckPermissions(args[i], literal_args)) { - this->SetError( + status.SetError( cmStrCat(args[0], " given invalid permission \"", args[i], "\".")); return false; } } else { // Unknown argument. - this->SetError( + status.SetError( cmStrCat(args[0], " given unknown argument \"", args[i], "\".")); return false; } @@ -1174,40 +1181,42 @@ bool cmInstallCommand::HandleDirectoryMode( if (!destination) { if (type.empty()) { // A destination is required. - this->SetError(cmStrCat(args[0], " given no DESTINATION!")); + status.SetError(cmStrCat(args[0], " given no DESTINATION!")); return false; } - destinationStr = this->GetDestinationForType(nullptr, type); + destinationStr = helper.GetDestinationForType(nullptr, type); destination = destinationStr.c_str(); } else if (!type.empty()) { - this->SetError(cmStrCat(args[0], - " given both TYPE and DESTINATION " - "arguments. You may only specify one.")); + status.SetError(cmStrCat(args[0], + " given both TYPE and DESTINATION " + "arguments. You may only specify one.")); return false; } cmInstallGenerator::MessageLevel message = - cmInstallGenerator::SelectMessageLevel(this->Makefile, message_never); + cmInstallGenerator::SelectMessageLevel(helper.Makefile, message_never); // Create the directory install generator. - this->Makefile->AddInstallGenerator(new cmInstallDirectoryGenerator( + helper.Makefile->AddInstallGenerator(new cmInstallDirectoryGenerator( dirs, destination, permissions_file.c_str(), permissions_dir.c_str(), configurations, component.c_str(), message, exclude_from_all, literal_args.c_str(), optional)); // Tell the global generator about any installation component names // specified. - this->Makefile->GetGlobalGenerator()->AddInstallComponent(component); + helper.Makefile->GetGlobalGenerator()->AddInstallComponent(component); return true; } -bool cmInstallCommand::HandleExportAndroidMKMode( - std::vector<std::string> const& args) +bool HandleExportAndroidMKMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { #ifndef CMAKE_BOOTSTRAP + Helper helper(status); + // This is the EXPORT mode. - cmInstallCommandArguments ica(this->DefaultComponentName); + cmInstallCommandArguments ica(helper.DefaultComponentName); std::string exp; std::string name_space; @@ -1224,7 +1233,7 @@ bool cmInstallCommand::HandleExportAndroidMKMode( if (!unknownArgs.empty()) { // Unknown argument. - this->SetError( + status.SetError( cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\".")); return false; } @@ -1236,30 +1245,30 @@ bool cmInstallCommand::HandleExportAndroidMKMode( // Make sure there is a destination. if (ica.GetDestination().empty()) { // A destination is required. - this->SetError(cmStrCat(args[0], " given no DESTINATION!")); + status.SetError(cmStrCat(args[0], " given no DESTINATION!")); return false; } // Check the file name. std::string fname = filename; if (fname.find_first_of(":/\\") != std::string::npos) { - this->SetError(cmStrCat(args[0], " given invalid export file name \"", - fname, - "\". The FILE argument may not contain a path. " - "Specify the path in the DESTINATION argument.")); + status.SetError(cmStrCat(args[0], " given invalid export file name \"", + fname, + "\". The FILE argument may not contain a path. " + "Specify the path in the DESTINATION argument.")); return false; } // Check the file extension. if (!fname.empty() && cmSystemTools::GetFilenameLastExtension(fname) != ".mk") { - this->SetError(cmStrCat( + status.SetError(cmStrCat( args[0], " given invalid export file name \"", fname, R"(". The FILE argument must specify a name ending in ".mk".)")); return false; } if (fname.find_first_of(":/\\") != std::string::npos) { - this->SetError( + status.SetError( cmStrCat(args[0], " given export name \"", exp, "\". " "This name cannot be safely converted to a file name. " @@ -1273,10 +1282,10 @@ bool cmInstallCommand::HandleExportAndroidMKMode( } cmExportSet& exportSet = - this->Makefile->GetGlobalGenerator()->GetExportSets()[exp]; + helper.Makefile->GetGlobalGenerator()->GetExportSets()[exp]; cmInstallGenerator::MessageLevel message = - cmInstallGenerator::SelectMessageLevel(this->Makefile); + cmInstallGenerator::SelectMessageLevel(helper.Makefile); // Create the export install generator. cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator( @@ -1284,20 +1293,23 @@ bool cmInstallCommand::HandleExportAndroidMKMode( ica.GetConfigurations(), ica.GetComponent().c_str(), message, ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld, true); - this->Makefile->AddInstallGenerator(exportGenerator); + helper.Makefile->AddInstallGenerator(exportGenerator); return true; #else static_cast<void>(args); - this->SetError("EXPORT_ANDROID_MK not supported in bootstrap cmake"); + status.SetError("EXPORT_ANDROID_MK not supported in bootstrap cmake"); return false; #endif } -bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) +bool HandleExportMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { + Helper helper(status); + // This is the EXPORT mode. - cmInstallCommandArguments ica(this->DefaultComponentName); + cmInstallCommandArguments ica(helper.DefaultComponentName); std::string exp; std::string name_space; @@ -1314,7 +1326,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) if (!unknownArgs.empty()) { // Unknown argument. - this->SetError( + status.SetError( cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\".")); return false; } @@ -1326,25 +1338,25 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) // Make sure there is a destination. if (ica.GetDestination().empty()) { // A destination is required. - this->SetError(cmStrCat(args[0], " given no DESTINATION!")); + status.SetError(cmStrCat(args[0], " given no DESTINATION!")); return false; } // Check the file name. std::string fname = filename; if (fname.find_first_of(":/\\") != std::string::npos) { - this->SetError(cmStrCat(args[0], " given invalid export file name \"", - fname, - "\". " - "The FILE argument may not contain a path. " - "Specify the path in the DESTINATION argument.")); + status.SetError(cmStrCat(args[0], " given invalid export file name \"", + fname, + "\". " + "The FILE argument may not contain a path. " + "Specify the path in the DESTINATION argument.")); return false; } // Check the file extension. if (!fname.empty() && cmSystemTools::GetFilenameLastExtension(fname) != ".cmake") { - this->SetError( + status.SetError( cmStrCat(args[0], " given invalid export file name \"", fname, "\". " "The FILE argument must specify a name ending in \".cmake\".")); @@ -1356,7 +1368,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) fname = cmStrCat(exp, ".cmake"); if (fname.find_first_of(":/\\") != std::string::npos) { - this->SetError(cmStrCat( + status.SetError(cmStrCat( args[0], " given export name \"", exp, "\". " "This name cannot be safely converted to a file name. " @@ -1367,17 +1379,17 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) } cmExportSet& exportSet = - this->Makefile->GetGlobalGenerator()->GetExportSets()[exp]; + helper.Makefile->GetGlobalGenerator()->GetExportSets()[exp]; if (exportOld) { for (auto const& te : exportSet.GetTargetExports()) { cmTarget* tgt = - this->Makefile->GetGlobalGenerator()->FindTarget(te->TargetName); + helper.Makefile->GetGlobalGenerator()->FindTarget(te->TargetName); const bool newCMP0022Behavior = (tgt && tgt->GetPolicyStatusCMP0022() != cmPolicies::WARN && tgt->GetPolicyStatusCMP0022() != cmPolicies::OLD); if (!newCMP0022Behavior) { - this->SetError(cmStrCat( + status.SetError(cmStrCat( "INSTALL(EXPORT) given keyword \"" "EXPORT_LINK_INTERFACE_LIBRARIES\", but target \"", te->TargetName, "\" does not have policy CMP0022 set to NEW.")); @@ -1387,7 +1399,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) } cmInstallGenerator::MessageLevel message = - cmInstallGenerator::SelectMessageLevel(this->Makefile); + cmInstallGenerator::SelectMessageLevel(helper.Makefile); // Create the export install generator. cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator( @@ -1395,14 +1407,14 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) ica.GetConfigurations(), ica.GetComponent().c_str(), message, ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld, false); - this->Makefile->AddInstallGenerator(exportGenerator); + helper.Makefile->AddInstallGenerator(exportGenerator); return true; } -bool cmInstallCommand::MakeFilesFullPath( - const char* modeName, const std::vector<std::string>& relFiles, - std::vector<std::string>& absFiles) +bool Helper::MakeFilesFullPath(const char* modeName, + const std::vector<std::string>& relFiles, + std::vector<std::string>& absFiles) { for (std::string const& relFile : relFiles) { std::string file = relFile; @@ -1424,7 +1436,7 @@ bool cmInstallCommand::MakeFilesFullPath( return true; } -bool cmInstallCommand::CheckCMP0006(bool& failure) +bool Helper::CheckCMP0006(bool& failure) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) { case cmPolicies::WARN: @@ -1449,9 +1461,9 @@ bool cmInstallCommand::CheckCMP0006(bool& failure) return false; } -std::string cmInstallCommand::GetDestination( - const cmInstallCommandArguments* args, const std::string& varName, - const std::string& guess) +std::string Helper::GetDestination(const cmInstallCommandArguments* args, + const std::string& varName, + const std::string& guess) { if (args && !args->GetDestination().empty()) { return args->GetDestination(); @@ -1463,55 +1475,54 @@ std::string cmInstallCommand::GetDestination( return guess; } -std::string cmInstallCommand::GetRuntimeDestination( +std::string Helper::GetRuntimeDestination( const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_BINDIR", "bin"); } -std::string cmInstallCommand::GetSbinDestination( - const cmInstallCommandArguments* args) +std::string Helper::GetSbinDestination(const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_SBINDIR", "sbin"); } -std::string cmInstallCommand::GetArchiveDestination( +std::string Helper::GetArchiveDestination( const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib"); } -std::string cmInstallCommand::GetLibraryDestination( +std::string Helper::GetLibraryDestination( const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib"); } -std::string cmInstallCommand::GetIncludeDestination( +std::string Helper::GetIncludeDestination( const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_INCLUDEDIR", "include"); } -std::string cmInstallCommand::GetSysconfDestination( +std::string Helper::GetSysconfDestination( const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_SYSCONFDIR", "etc"); } -std::string cmInstallCommand::GetSharedStateDestination( +std::string Helper::GetSharedStateDestination( const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_SHAREDSTATEDIR", "com"); } -std::string cmInstallCommand::GetLocalStateDestination( +std::string Helper::GetLocalStateDestination( const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_LOCALSTATEDIR", "var"); } -std::string cmInstallCommand::GetRunStateDestination( +std::string Helper::GetRunStateDestination( const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_RUNSTATEDIR", @@ -1519,49 +1530,44 @@ std::string cmInstallCommand::GetRunStateDestination( "/run"); } -std::string cmInstallCommand::GetDataRootDestination( +std::string Helper::GetDataRootDestination( const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_DATAROOTDIR", "share"); } -std::string cmInstallCommand::GetDataDestination( - const cmInstallCommandArguments* args) +std::string Helper::GetDataDestination(const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_DATADIR", this->GetDataRootDestination(nullptr)); } -std::string cmInstallCommand::GetInfoDestination( - const cmInstallCommandArguments* args) +std::string Helper::GetInfoDestination(const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_INFODIR", this->GetDataRootDestination(nullptr) + "/info"); } -std::string cmInstallCommand::GetLocaleDestination( - const cmInstallCommandArguments* args) +std::string Helper::GetLocaleDestination(const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_LOCALEDIR", this->GetDataRootDestination(nullptr) + "/locale"); } -std::string cmInstallCommand::GetManDestination( - const cmInstallCommandArguments* args) +std::string Helper::GetManDestination(const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_MANDIR", this->GetDataRootDestination(nullptr) + "/man"); } -std::string cmInstallCommand::GetDocDestination( - const cmInstallCommandArguments* args) +std::string Helper::GetDocDestination(const cmInstallCommandArguments* args) { return this->GetDestination(args, "CMAKE_INSTALL_DOCDIR", this->GetDataRootDestination(nullptr) + "/doc"); } -std::string cmInstallCommand::GetDestinationForType( +std::string Helper::GetDestinationForType( const cmInstallCommandArguments* args, const std::string& type) { if (args && !args->GetDestination().empty()) { @@ -1608,3 +1614,31 @@ std::string cmInstallCommand::GetDestinationForType( } return ""; } + +} // namespace + +bool cmInstallCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + // Allow calling with no arguments so that arguments may be built up + // using a variable that may be left empty. + if (args.empty()) { + return true; + } + + // Enable the install target. + status.GetMakefile().GetGlobalGenerator()->EnableInstallTarget(); + + static cmSubcommandTable const subcommand{ + { "SCRIPT"_s, HandleScriptMode }, + { "CODE"_s, HandleScriptMode }, + { "TARGETS"_s, HandleTargetsMode }, + { "FILES"_s, HandleFilesMode }, + { "PROGRAMS"_s, HandleFilesMode }, + { "DIRECTORY"_s, HandleDirectoryMode }, + { "EXPORT"_s, HandleExportMode }, + { "EXPORT_ANDROID_MK"_s, HandleExportAndroidMKMode }, + }; + + return subcommand(args[0], args, status); +} diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 9ffb842..32f00ce 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -8,71 +8,9 @@ #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" - class cmExecutionStatus; -class cmInstallCommandArguments; - -/** \class cmInstallCommand - * \brief Specifies where to install some files - * - * cmInstallCommand is a general-purpose interface command for - * specifying install rules. - */ -class cmInstallCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmInstallCommand>(); - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - bool HandleScriptMode(std::vector<std::string> const& args); - bool HandleTargetsMode(std::vector<std::string> const& args); - bool HandleFilesMode(std::vector<std::string> const& args); - bool HandleDirectoryMode(std::vector<std::string> const& args); - bool HandleExportMode(std::vector<std::string> const& args); - bool HandleExportAndroidMKMode(std::vector<std::string> const& args); - bool MakeFilesFullPath(const char* modeName, - const std::vector<std::string>& relFiles, - std::vector<std::string>& absFiles); - bool CheckCMP0006(bool& failure); - - std::string GetDestination(const cmInstallCommandArguments* args, - const std::string& varName, - const std::string& guess); - std::string GetRuntimeDestination(const cmInstallCommandArguments* args); - std::string GetSbinDestination(const cmInstallCommandArguments* args); - std::string GetArchiveDestination(const cmInstallCommandArguments* args); - std::string GetLibraryDestination(const cmInstallCommandArguments* args); - std::string GetIncludeDestination(const cmInstallCommandArguments* args); - std::string GetSysconfDestination(const cmInstallCommandArguments* args); - std::string GetSharedStateDestination(const cmInstallCommandArguments* args); - std::string GetLocalStateDestination(const cmInstallCommandArguments* args); - std::string GetRunStateDestination(const cmInstallCommandArguments* args); - std::string GetDataRootDestination(const cmInstallCommandArguments* args); - std::string GetDataDestination(const cmInstallCommandArguments* args); - std::string GetInfoDestination(const cmInstallCommandArguments* args); - std::string GetLocaleDestination(const cmInstallCommandArguments* args); - std::string GetManDestination(const cmInstallCommandArguments* args); - std::string GetDocDestination(const cmInstallCommandArguments* args); - std::string GetDestinationForType(const cmInstallCommandArguments* args, - const std::string& type); - std::string DefaultComponentName; -}; +bool cmInstallCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index 1d8210c..259c7f7 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -9,8 +9,6 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#include <memory> - cmInstallDirectoryGenerator::cmInstallDirectoryGenerator( std::vector<std::string> const& dirs, const char* dest, const char* file_permissions, const char* dir_permissions, @@ -64,10 +62,9 @@ void cmInstallDirectoryGenerator::GenerateScriptForConfig( std::ostream& os, const std::string& config, Indent indent) { std::vector<std::string> dirs; - cmGeneratorExpression ge; for (std::string const& d : this->Directories) { - std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(d); - cmExpandList(cge->Evaluate(this->LocalGenerator, config), dirs); + cmExpandList( + cmGeneratorExpression::Evaluate(d, this->LocalGenerator, config), dirs); } // Make sure all dirs have absolute paths. @@ -97,6 +94,6 @@ void cmInstallDirectoryGenerator::AddDirectoryInstallRule( std::string cmInstallDirectoryGenerator::GetDestination( std::string const& config) const { - cmGeneratorExpression ge; - return ge.Parse(this->Destination)->Evaluate(this->LocalGenerator, config); + return cmGeneratorExpression::Evaluate(this->Destination, + this->LocalGenerator, config); } diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index c4048d4..f5b69a5 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -6,8 +6,6 @@ #include "cmInstallType.h" #include "cmStringAlgorithms.h" -#include <memory> - class cmLocalGenerator; cmInstallFilesGenerator::cmInstallFilesGenerator( @@ -51,8 +49,8 @@ bool cmInstallFilesGenerator::Compute(cmLocalGenerator* lg) std::string cmInstallFilesGenerator::GetDestination( std::string const& config) const { - cmGeneratorExpression ge; - return ge.Parse(this->Destination)->Evaluate(this->LocalGenerator, config); + return cmGeneratorExpression::Evaluate(this->Destination, + this->LocalGenerator, config); } void cmInstallFilesGenerator::AddFilesInstallRule( @@ -82,10 +80,9 @@ void cmInstallFilesGenerator::GenerateScriptForConfig( std::ostream& os, const std::string& config, Indent indent) { std::vector<std::string> files; - cmGeneratorExpression ge; for (std::string const& f : this->Files) { - std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(f); - cmExpandList(cge->Evaluate(this->LocalGenerator, config), files); + cmExpandList( + cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config), files); } this->AddFilesInstallRule(os, config, indent, files); } diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx index b7b7817..ea29455 100644 --- a/Source/cmInstallScriptGenerator.cxx +++ b/Source/cmInstallScriptGenerator.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallScriptGenerator.h" -#include <memory> #include <ostream> #include <vector> @@ -79,11 +78,9 @@ void cmInstallScriptGenerator::GenerateScriptForConfig( std::ostream& os, const std::string& config, Indent indent) { if (this->AllowGenex) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(this->Script); this->AddScriptInstallRule(os, indent, - cge->Evaluate(this->LocalGenerator, config)); + cmGeneratorExpression::Evaluate( + this->Script, this->LocalGenerator, config)); } else { this->AddScriptInstallRule(os, indent, this->Script); } diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 90b0e1d..0cd04cc 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -4,7 +4,6 @@ #include <cassert> #include <map> -#include <memory> #include <set> #include <sstream> #include <utility> @@ -375,9 +374,8 @@ void cmInstallTargetGenerator::GetInstallObjectNames( std::string cmInstallTargetGenerator::GetDestination( std::string const& config) const { - cmGeneratorExpression ge; - return ge.Parse(this->Destination) - ->Evaluate(this->Target->GetLocalGenerator(), config); + return cmGeneratorExpression::Evaluate( + this->Destination, this->Target->GetLocalGenerator(), config); } std::string cmInstallTargetGenerator::GetInstallFilename( diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx index 52e28d3..79180cb 100644 --- a/Source/cmJsonObjects.cxx +++ b/Source/cmJsonObjects.cxx @@ -32,7 +32,6 @@ #include <functional> #include <limits> #include <map> -#include <memory> #include <set> #include <string> #include <unordered_map> @@ -357,10 +356,8 @@ static Json::Value DumpCTestInfo(cmLocalGenerator* lg, cmTest* testInfo, } // Remove any config specific variables from the output. - cmGeneratorExpression ge; - auto cge = ge.Parse(command); - const std::string& processed = cge->Evaluate(lg, config); - result[kCTEST_COMMAND] = processed; + result[kCTEST_COMMAND] = + cmGeneratorExpression::Evaluate(command, lg, config); // Build up the list of properties that may have been specified Json::Value properties = Json::arrayValue; @@ -369,9 +366,8 @@ static Json::Value DumpCTestInfo(cmLocalGenerator* lg, cmTest* testInfo, entry[kKEY_KEY] = prop.first; // Remove config variables from the value too. - auto cge_value = ge.Parse(prop.second); - const std::string& processed_value = cge_value->Evaluate(lg, config); - entry[kVALUE_KEY] = processed_value; + entry[kVALUE_KEY] = + cmGeneratorExpression::Evaluate(prop.second, lg, config); properties.append(entry); } result[kPROPERTIES_KEY] = properties; diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx index 57b69c8..2914046 100644 --- a/Source/cmLinkDirectoriesCommand.cxx +++ b/Source/cmLinkDirectoriesCommand.cxx @@ -4,6 +4,7 @@ #include <sstream> +#include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -11,17 +12,18 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; +static void AddLinkDir(cmMakefile& mf, std::string const& dir, + std::vector<std::string>& directories); -// cmLinkDirectoriesCommand -bool cmLinkDirectoriesCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmLinkDirectoriesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { return true; } - bool before = this->Makefile->IsOn("CMAKE_LINK_DIRECTORIES_BEFORE"); + cmMakefile& mf = status.GetMakefile(); + bool before = mf.IsOn("CMAKE_LINK_DIRECTORIES_BEFORE"); auto i = args.cbegin(); if ((*i) == "BEFORE") { @@ -34,16 +36,16 @@ bool cmLinkDirectoriesCommand::InitialPass( std::vector<std::string> directories; for (; i != args.cend(); ++i) { - this->AddLinkDir(*i, directories); + AddLinkDir(mf, *i, directories); } - this->Makefile->AddLinkDirectory(cmJoin(directories, ";"), before); + mf.AddLinkDirectory(cmJoin(directories, ";"), before); return true; } -void cmLinkDirectoriesCommand::AddLinkDir( - std::string const& dir, std::vector<std::string>& directories) +static void AddLinkDir(cmMakefile& mf, std::string const& dir, + std::vector<std::string>& directories) { std::string unixPath = dir; cmSystemTools::ConvertToUnixSlashes(unixPath); @@ -56,10 +58,10 @@ void cmLinkDirectoriesCommand::AddLinkDir( << " " << unixPath << "\n" << "as a link directory.\n"; /* clang-format on */ - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0015)) { + switch (mf.GetPolicyStatus(cmPolicies::CMP0015)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015); - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); break; case cmPolicies::OLD: // OLD behavior does not convert @@ -67,7 +69,7 @@ void cmLinkDirectoriesCommand::AddLinkDir( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0015); - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + mf.IssueMessage(MessageType::FATAL_ERROR, e.str()); CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior converts @@ -75,9 +77,7 @@ void cmLinkDirectoriesCommand::AddLinkDir( break; } if (convertToAbsolute) { - std::string tmp = - cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', unixPath); - unixPath = tmp; + unixPath = cmStrCat(mf.GetCurrentSourceDirectory(), '/', unixPath); } } directories.push_back(unixPath); diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h index 489d90f..a7caa5c 100644 --- a/Source/cmLinkDirectoriesCommand.h +++ b/Source/cmLinkDirectoriesCommand.h @@ -8,41 +8,9 @@ #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmLinkDirectoriesCommand - * \brief Define a list of directories containing files to link. - * - * cmLinkDirectoriesCommand is used to specify a list - * of directories containing files to link into executable(s). - * Note that the command supports the use of CMake built-in variables - * such as CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR. - */ -class cmLinkDirectoriesCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmLinkDirectoriesCommand>(); - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - void AddLinkDir(std::string const& dir, - std::vector<std::string>& directories); -}; +bool cmLinkDirectoriesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx index 3fd7343..cca1633 100644 --- a/Source/cmLoadCacheCommand.cxx +++ b/Source/cmLoadCacheCommand.cxx @@ -3,24 +3,30 @@ #include "cmLoadCacheCommand.h" #include "cmsys/FStream.hxx" +#include <set> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmake.h" -class cmExecutionStatus; +static bool ReadWithPrefix(std::vector<std::string> const& args, + cmExecutionStatus& status); -// cmLoadCacheCommand -bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +static void CheckLine(cmMakefile& mf, std::string const& prefix, + std::set<std::string> const& variablesToRead, + const char* line); + +bool cmLoadCacheCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with wrong number of arguments."); + status.SetError("called with wrong number of arguments."); } if (args.size() >= 2 && args[1] == "READ_WITH_PREFIX") { - return this->ReadWithPrefix(args); + return ReadWithPrefix(args, status); } // Cache entries to be excluded from the import list. @@ -59,24 +65,26 @@ bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& args, } } + cmMakefile& mf = status.GetMakefile(); + // Loop over each build directory listed in the arguments. Each // directory has a cache file. for (std::string const& arg : args) { if ((arg == "EXCLUDE") || (arg == "INCLUDE_INTERNALS")) { break; } - this->Makefile->GetCMakeInstance()->LoadCache(arg, false, excludes, - includes); + mf.GetCMakeInstance()->LoadCache(arg, false, excludes, includes); } return true; } -bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args) +static bool ReadWithPrefix(std::vector<std::string> const& args, + cmExecutionStatus& status) { // Make sure we have a prefix. if (args.size() < 3) { - this->SetError("READ_WITH_PREFIX form must specify a prefix."); + status.SetError("READ_WITH_PREFIX form must specify a prefix."); return false; } @@ -84,17 +92,19 @@ bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args) std::string cacheFile = args[0] + "/CMakeCache.txt"; if (!cmSystemTools::FileExists(cacheFile)) { std::string e = "Cannot load cache file from " + cacheFile; - this->SetError(e); + status.SetError(e); return false; } // Prepare the table of variables to read. - this->Prefix = args[2]; - this->VariablesToRead.insert(args.begin() + 3, args.end()); + std::string const prefix = args[2]; + std::set<std::string> const variablesToRead(args.begin() + 3, args.end()); // Read the cache file. cmsys::ifstream fin(cacheFile.c_str()); + cmMakefile& mf = status.GetMakefile(); + // This is a big hack read loop to overcome a buggy ifstream // implementation on HP-UX. This should work on all platforms even // for small buffer sizes. @@ -123,7 +133,7 @@ bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args) } if (i != end) { // Completed a line. - this->CheckLine(line.c_str()); + CheckLine(mf, prefix, variablesToRead, line.c_str()); line.clear(); // Skip the newline character. @@ -134,13 +144,15 @@ bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args) } if (!line.empty()) { // Partial last line. - this->CheckLine(line.c_str()); + CheckLine(mf, prefix, variablesToRead, line.c_str()); } return true; } -void cmLoadCacheCommand::CheckLine(const char* line) +static void CheckLine(cmMakefile& mf, std::string const& prefix, + std::set<std::string> const& variablesToRead, + const char* line) { // Check one line of the cache file. std::string var; @@ -148,14 +160,14 @@ void cmLoadCacheCommand::CheckLine(const char* line) cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED; if (cmake::ParseCacheEntry(line, var, value, type)) { // Found a real entry. See if this one was requested. - if (this->VariablesToRead.find(var) != this->VariablesToRead.end()) { + if (variablesToRead.find(var) != variablesToRead.end()) { // This was requested. Set this variable locally with the given // prefix. - var = this->Prefix + var; + var = prefix + var; if (!value.empty()) { - this->Makefile->AddDefinition(var, value); + mf.AddDefinition(var, value); } else { - this->Makefile->RemoveDefinition(var); + mf.RemoveDefinition(var); } } } diff --git a/Source/cmLoadCacheCommand.h b/Source/cmLoadCacheCommand.h index 37f0372..7cee663 100644 --- a/Source/cmLoadCacheCommand.h +++ b/Source/cmLoadCacheCommand.h @@ -5,45 +5,12 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <set> #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmLoadCacheCommand - * \brief load a cache file - * - * cmLoadCacheCommand loads the non internal values of a cache file - */ -class cmLoadCacheCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmLoadCacheCommand>(); - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -protected: - std::set<std::string> VariablesToRead; - std::string Prefix; - - bool ReadWithPrefix(std::vector<std::string> const& args); - void CheckLine(const char* line); -}; +bool cmLoadCacheCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index e059548..93e074d 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -48,7 +48,6 @@ #include <functional> #include <initializer_list> #include <iterator> -#include <memory> #include <sstream> #include <unordered_set> #include <utility> @@ -925,10 +924,8 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, // to ON if (char const* jmcExprGen = target->GetProperty("VS_JUST_MY_CODE_DEBUGGING")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(jmcExprGen); - std::string isJMCEnabled = cge->Evaluate(this, config); + std::string isJMCEnabled = + cmGeneratorExpression::Evaluate(jmcExprGen, this, config); if (cmIsOn(isJMCEnabled)) { std::vector<std::string> optVec = cmExpandedList(jmc); std::string jmcFlags; @@ -1710,11 +1707,8 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, if (!msvcRuntimeLibraryValue) { msvcRuntimeLibraryValue = msvcRuntimeLibraryDefault; } - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(msvcRuntimeLibraryValue); - std::string const msvcRuntimeLibrary = - cge->Evaluate(this, config, false, target); + std::string const msvcRuntimeLibrary = cmGeneratorExpression::Evaluate( + msvcRuntimeLibraryValue, this, config, target); if (!msvcRuntimeLibrary.empty()) { if (const char* msvcRuntimeLibraryOptions = this->Makefile->GetDefinition( diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 0fe385f..82dc943 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -608,12 +608,10 @@ void cmLocalNinjaGenerator::AdditionalCleanFiles() this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { std::vector<std::string> cleanFiles; { - cmGeneratorExpression ge; - auto cge = ge.Parse(prop_value); - cmExpandList( - cge->Evaluate(this, - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), - cleanFiles); + cmExpandList(cmGeneratorExpression::Evaluate( + prop_value, this, + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), + cleanFiles); } std::string const& binaryDir = this->GetCurrentBinaryDirectory(); cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator(); diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 08bec70..f64534c 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -93,7 +93,6 @@ private: void WriteProcessedMakefile(std::ostream& os); void WritePools(std::ostream& os); - void WriteCustomCommandRule(); void WriteCustomCommandBuildStatement(cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps); diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index a7be04e..1d87e93 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1083,12 +1083,10 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( // Look for additional files registered for cleaning in this directory. if (const char* prop_value = this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop_value); - cmExpandList( - cge->Evaluate(this, - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), - cleanFiles); + cmExpandList(cmGeneratorExpression::Evaluate( + prop_value, this, + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), + cleanFiles); } if (cleanFiles.empty()) { return; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 482af22..d352f8e 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -154,11 +154,10 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() auto evaluatedFiles = [this](const char* prop_value) -> std::vector<std::string> { std::vector<std::string> files; - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop_value); - cmExpandList(cge->Evaluate(this->LocalGenerator, this->ConfigName, false, - this->GeneratorTarget, nullptr, nullptr), - files); + cmExpandList( + cmGeneratorExpression::Evaluate(prop_value, this->LocalGenerator, + this->ConfigName, this->GeneratorTarget), + files); return files; }; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 2ab5adf..613e7aa 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1317,14 +1317,11 @@ void cmNinjaTargetGenerator::AdditionalCleanFiles() this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) { cmLocalNinjaGenerator* lg = this->LocalGenerator; std::vector<std::string> cleanFiles; - { - cmGeneratorExpression ge; - auto cge = ge.Parse(prop_value); - cmExpandList(cge->Evaluate( - lg, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"), - false, this->GeneratorTarget, nullptr, nullptr), - cleanFiles); - } + cmExpandList(cmGeneratorExpression::Evaluate( + prop_value, lg, + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"), + this->GeneratorTarget), + cleanFiles); std::string const& binaryDir = lg->GetCurrentBinaryDirectory(); cmGlobalNinjaGenerator* gg = lg->GetGlobalNinjaGenerator(); for (std::string const& cleanFile : cleanFiles) { diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 5fa6a21..373e767 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -10,6 +10,7 @@ #include <limits> #include <utility> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -17,40 +18,39 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; +static bool IncludeByVariable(cmExecutionStatus& status, + const std::string& variable); +static void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name, + std::string const& value); -// cmProjectCommand -bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmProjectCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("PROJECT called with incorrect number of arguments"); + status.SetError("PROJECT called with incorrect number of arguments"); return false; } - if (!this->IncludeByVariable("CMAKE_PROJECT_INCLUDE_BEFORE")) { + cmMakefile& mf = status.GetMakefile(); + if (!IncludeByVariable(status, "CMAKE_PROJECT_INCLUDE_BEFORE")) { return false; } std::string const& projectName = args[0]; - this->Makefile->SetProjectName(projectName); + mf.SetProjectName(projectName); - this->Makefile->AddCacheDefinition( - projectName + "_BINARY_DIR", - this->Makefile->GetCurrentBinaryDirectory().c_str(), - "Value Computed by CMake", cmStateEnums::STATIC); - this->Makefile->AddCacheDefinition( - projectName + "_SOURCE_DIR", - this->Makefile->GetCurrentSourceDirectory().c_str(), - "Value Computed by CMake", cmStateEnums::STATIC); + mf.AddCacheDefinition(projectName + "_BINARY_DIR", + mf.GetCurrentBinaryDirectory().c_str(), + "Value Computed by CMake", cmStateEnums::STATIC); + mf.AddCacheDefinition(projectName + "_SOURCE_DIR", + mf.GetCurrentSourceDirectory().c_str(), + "Value Computed by CMake", cmStateEnums::STATIC); - this->Makefile->AddDefinition("PROJECT_BINARY_DIR", - this->Makefile->GetCurrentBinaryDirectory()); - this->Makefile->AddDefinition("PROJECT_SOURCE_DIR", - this->Makefile->GetCurrentSourceDirectory()); + mf.AddDefinition("PROJECT_BINARY_DIR", mf.GetCurrentBinaryDirectory()); + mf.AddDefinition("PROJECT_SOURCE_DIR", mf.GetCurrentSourceDirectory()); - this->Makefile->AddDefinition("PROJECT_NAME", projectName); + mf.AddDefinition("PROJECT_NAME", projectName); // Set the CMAKE_PROJECT_NAME variable to be the highest-level // project name in the tree. If there are two project commands @@ -58,12 +58,10 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, // CMakeLists.txt file, then go with the last one, so that // CMAKE_PROJECT_NAME will match PROJECT_NAME, and cmake --build // will work. - if (!this->Makefile->GetDefinition("CMAKE_PROJECT_NAME") || - (this->Makefile->IsRootMakefile())) { - this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", projectName); - this->Makefile->AddCacheDefinition( - "CMAKE_PROJECT_NAME", projectName.c_str(), "Value Computed by CMake", - cmStateEnums::STATIC); + if (!mf.GetDefinition("CMAKE_PROJECT_NAME") || mf.IsRootMakefile()) { + mf.AddDefinition("CMAKE_PROJECT_NAME", projectName); + mf.AddCacheDefinition("CMAKE_PROJECT_NAME", projectName.c_str(), + "Value Computed by CMake", cmStateEnums::STATIC); } bool haveVersion = false; @@ -90,9 +88,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, for (size_t i = 1; i < args.size(); ++i) { if (args[i] == "LANGUAGES") { if (haveLanguages) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "LANGUAGES may be specified at most once."); + mf.IssueMessage(MessageType::FATAL_ERROR, + "LANGUAGES may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -106,12 +103,12 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, "the following parameters must be specified after LANGUAGES " "keyword: ", cmJoin(languages, ", "), '.'); - this->Makefile->IssueMessage(MessageType::WARNING, msg); + mf.IssueMessage(MessageType::WARNING, msg); } } else if (args[i] == "VERSION") { if (haveVersion) { - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "VERSION may be specified at most once."); + mf.IssueMessage(MessageType::FATAL_ERROR, + "VERSION may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -120,8 +117,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, missedValueReporter(); } doing = DoingVersion; - missedValueReporter = [this, &resetReporter]() { - this->Makefile->IssueMessage( + missedValueReporter = [&mf, &resetReporter]() { + mf.IssueMessage( MessageType::WARNING, "VERSION keyword not followed by a value or was followed by a " "value that expanded to nothing."); @@ -129,9 +126,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, }; } else if (args[i] == "DESCRIPTION") { if (haveDescription) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "DESCRIPTION may be specified at most once."); + mf.IssueMessage(MessageType::FATAL_ERROR, + "DESCRIPTION may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -140,8 +136,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, missedValueReporter(); } doing = DoingDescription; - missedValueReporter = [this, &resetReporter]() { - this->Makefile->IssueMessage( + missedValueReporter = [&mf, &resetReporter]() { + mf.IssueMessage( MessageType::WARNING, "DESCRIPTION keyword not followed by a value or was followed " "by a value that expanded to nothing."); @@ -149,16 +145,15 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, }; } else if (args[i] == "HOMEPAGE_URL") { if (haveHomepage) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "HOMEPAGE_URL may be specified at most once."); + mf.IssueMessage(MessageType::FATAL_ERROR, + "HOMEPAGE_URL may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; } haveHomepage = true; doing = DoingHomepage; - missedValueReporter = [this, &resetReporter]() { - this->Makefile->IssueMessage( + missedValueReporter = [&mf, &resetReporter]() { + mf.IssueMessage( MessageType::WARNING, "HOMEPAGE_URL keyword not followed by a value or was followed " "by a value that expanded to nothing."); @@ -190,10 +185,9 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, if ((haveVersion || haveDescription || haveHomepage) && !haveLanguages && !languages.empty()) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "project with VERSION, DESCRIPTION or HOMEPAGE_URL must " - "use LANGUAGES before language names."); + mf.IssueMessage(MessageType::FATAL_ERROR, + "project with VERSION, DESCRIPTION or HOMEPAGE_URL must " + "use LANGUAGES before language names."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -202,13 +196,12 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } cmPolicies::PolicyStatus const cmp0048 = - this->Makefile->GetPolicyStatus(cmPolicies::CMP0048); + mf.GetPolicyStatus(cmPolicies::CMP0048); if (haveVersion) { // Set project VERSION variables to given values if (cmp0048 == cmPolicies::OLD || cmp0048 == cmPolicies::WARN) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "VERSION not allowed unless CMP0048 is set to NEW"); + mf.IssueMessage(MessageType::FATAL_ERROR, + "VERSION not allowed unless CMP0048 is set to NEW"); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -217,13 +210,13 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, R"(^([0-9]+(\.[0-9]+(\.[0-9]+(\.[0-9]+)?)?)?)?$)"); if (!vx.find(version)) { std::string e = R"(VERSION ")" + version + R"(" format invalid.)"; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); + mf.IssueMessage(MessageType::FATAL_ERROR, e); cmSystemTools::SetFatalErrorOccured(); return true; } cmPolicies::PolicyStatus const cmp0096 = - this->Makefile->GetPolicyStatus(cmPolicies::CMP0096); + mf.GetPolicyStatus(cmPolicies::CMP0096); constexpr std::size_t MAX_VERSION_COMPONENTS = 4u; std::string version_string; @@ -257,34 +250,30 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, std::string vv; vv = projectName + "_VERSION"; - this->Makefile->AddDefinition("PROJECT_VERSION", version_string); - this->Makefile->AddDefinition(vv, version_string); + mf.AddDefinition("PROJECT_VERSION", version_string); + mf.AddDefinition(vv, version_string); vv = projectName + "_VERSION_MAJOR"; - this->Makefile->AddDefinition("PROJECT_VERSION_MAJOR", - version_components[0]); - this->Makefile->AddDefinition(vv, version_components[0]); + mf.AddDefinition("PROJECT_VERSION_MAJOR", version_components[0]); + mf.AddDefinition(vv, version_components[0]); vv = projectName + "_VERSION_MINOR"; - this->Makefile->AddDefinition("PROJECT_VERSION_MINOR", - version_components[1]); - this->Makefile->AddDefinition(vv, version_components[1]); + mf.AddDefinition("PROJECT_VERSION_MINOR", version_components[1]); + mf.AddDefinition(vv, version_components[1]); vv = projectName + "_VERSION_PATCH"; - this->Makefile->AddDefinition("PROJECT_VERSION_PATCH", - version_components[2]); - this->Makefile->AddDefinition(vv, version_components[2]); + mf.AddDefinition("PROJECT_VERSION_PATCH", version_components[2]); + mf.AddDefinition(vv, version_components[2]); vv = projectName + "_VERSION_TWEAK"; - this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK", - version_components[3]); - this->Makefile->AddDefinition(vv, version_components[3]); + mf.AddDefinition("PROJECT_VERSION_TWEAK", version_components[3]); + mf.AddDefinition(vv, version_components[3]); // Also, try set top level variables - TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION", version_string.c_str()); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MAJOR", - version_components[0].c_str()); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MINOR", - version_components[1].c_str()); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_PATCH", - version_components[2].c_str()); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_TWEAK", - version_components[3].c_str()); + TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_VERSION", version_string); + TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_VERSION_MAJOR", + version_components[0]); + TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_VERSION_MINOR", + version_components[1]); + TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_VERSION_PATCH", + version_components[2]); + TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_VERSION_TWEAK", + version_components[3]); } else if (cmp0048 != cmPolicies::OLD) { // Set project VERSION variables to empty std::vector<std::string> vv = { "PROJECT_VERSION", @@ -297,7 +286,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, projectName + "_VERSION_MINOR", projectName + "_VERSION_PATCH", projectName + "_VERSION_TWEAK" }; - if (this->Makefile->IsRootMakefile()) { + if (mf.IsRootMakefile()) { vv.emplace_back("CMAKE_PROJECT_VERSION"); vv.emplace_back("CMAKE_PROJECT_VERSION_MAJOR"); vv.emplace_back("CMAKE_PROJECT_VERSION_MINOR"); @@ -306,7 +295,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } std::string vw; for (std::string const& i : vv) { - const char* const v = this->Makefile->GetDefinition(i); + const char* const v = mf.GetDefinition(i); if (v && *v) { if (cmp0048 == cmPolicies::WARN) { if (!injectedProjectCommand) { @@ -314,51 +303,54 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, vw += i; } } else { - this->Makefile->AddDefinition(i, ""); + mf.AddDefinition(i, ""); } } } if (!vw.empty()) { - this->Makefile->IssueMessage( + mf.IssueMessage( MessageType::AUTHOR_WARNING, cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0048), "\nThe following variable(s) would be set to empty:", vw)); } } - this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description); - this->Makefile->AddDefinition(projectName + "_DESCRIPTION", description); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_DESCRIPTION", description.c_str()); + mf.AddDefinition("PROJECT_DESCRIPTION", description); + mf.AddDefinition(projectName + "_DESCRIPTION", description); + TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_DESCRIPTION", description); - this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage); - this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL", homepage); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str()); + mf.AddDefinition("PROJECT_HOMEPAGE_URL", homepage); + mf.AddDefinition(projectName + "_HOMEPAGE_URL", homepage); + TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_HOMEPAGE_URL", homepage); if (languages.empty()) { // if no language is specified do c and c++ languages = { "C", "CXX" }; } - this->Makefile->EnableLanguage(languages, false); + mf.EnableLanguage(languages, false); - if (!this->IncludeByVariable("CMAKE_PROJECT_INCLUDE")) { + if (!IncludeByVariable(status, "CMAKE_PROJECT_INCLUDE")) { return false; } - if (!this->IncludeByVariable("CMAKE_PROJECT_" + projectName + "_INCLUDE")) { + if (!IncludeByVariable(status, + "CMAKE_PROJECT_" + projectName + "_INCLUDE")) { return false; } return true; } -bool cmProjectCommand::IncludeByVariable(const std::string& variable) +static bool IncludeByVariable(cmExecutionStatus& status, + const std::string& variable) { - const char* const include = this->Makefile->GetDefinition(variable); + cmMakefile& mf = status.GetMakefile(); + const char* const include = mf.GetDefinition(variable); if (!include) { return true; } - const bool readit = this->Makefile->ReadDependentFile(include); + const bool readit = mf.ReadDependentFile(include); if (readit) { return true; } @@ -367,24 +359,20 @@ bool cmProjectCommand::IncludeByVariable(const std::string& variable) return true; } - std::string m = cmStrCat("could not find file:\n" - " ", - include); - this->SetError(m); + status.SetError(cmStrCat("could not find file:\n ", include)); return false; } -void cmProjectCommand::TopLevelCMakeVarCondSet(const char* const name, - const char* const value) +static void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name, + std::string const& value) { // Set the CMAKE_PROJECT_XXX variable to be the highest-level // project name in the tree. If there are two project commands // in the same CMakeLists.txt file, and it is the top level // CMakeLists.txt file, then go with the last one. - if (!this->Makefile->GetDefinition(name) || - (this->Makefile->IsRootMakefile())) { - this->Makefile->AddDefinition(name, value); - this->Makefile->AddCacheDefinition(name, value, "Value Computed by CMake", - cmStateEnums::STATIC); + if (!mf.GetDefinition(name) || mf.IsRootMakefile()) { + mf.AddDefinition(name, value); + mf.AddCacheDefinition(name, value.c_str(), "Value Computed by CMake", + cmStateEnums::STATIC); } } diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h index ffbd330..c06b459 100644 --- a/Source/cmProjectCommand.h +++ b/Source/cmProjectCommand.h @@ -8,41 +8,9 @@ #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmProjectCommand - * \brief Specify the name for this build project. - * - * cmProjectCommand is used to specify a name for this build project. - * It is defined once per set of CMakeList.txt files (including - * all subdirectories). Currently it just sets the name of the workspace - * file for Microsoft Visual C++ - */ -class cmProjectCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmProjectCommand>(); - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - bool IncludeByVariable(const std::string& variable); - void TopLevelCMakeVarCondSet(const char* name, const char* value); -}; +bool cmProjectCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx index b4360e4..8d917db 100644 --- a/Source/cmSetTargetPropertiesCommand.cxx +++ b/Source/cmSetTargetPropertiesCommand.cxx @@ -5,31 +5,32 @@ #include <iterator> #include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" -class cmExecutionStatus; +static bool SetOneTarget(const std::string& tname, + std::vector<std::string>& propertyPairs, + cmMakefile* mf); -// cmSetTargetPropertiesCommand -bool cmSetTargetPropertiesCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } // first collect up the list of files std::vector<std::string> propertyPairs; int numFiles = 0; - std::vector<std::string>::const_iterator j; - for (j = args.begin(); j != args.end(); ++j) { + for (auto j = args.begin(); j != args.end(); ++j) { if (*j == "PROPERTIES") { // now loop through the rest of the arguments, new style ++j; if (std::distance(j, args.end()) % 2 != 0) { - this->SetError("called with incorrect number of arguments."); + status.SetError("called with incorrect number of arguments."); return false; } cmAppend(propertyPairs, j, args.end()); @@ -38,33 +39,32 @@ bool cmSetTargetPropertiesCommand::InitialPass( numFiles++; } if (propertyPairs.empty()) { - this->SetError("called with illegal arguments, maybe missing " - "a PROPERTIES specifier?"); + status.SetError("called with illegal arguments, maybe missing " + "a PROPERTIES specifier?"); return false; } + cmMakefile& mf = status.GetMakefile(); + // now loop over all the targets - int i; - for (i = 0; i < numFiles; ++i) { - if (this->Makefile->IsAlias(args[i])) { - this->SetError("can not be used on an ALIAS target."); + for (int i = 0; i < numFiles; ++i) { + if (mf.IsAlias(args[i])) { + status.SetError("can not be used on an ALIAS target."); return false; } - bool ret = cmSetTargetPropertiesCommand::SetOneTarget( - args[i], propertyPairs, this->Makefile); + bool ret = SetOneTarget(args[i], propertyPairs, &mf); if (!ret) { - std::string message = - cmStrCat("Can not find target to add properties to: ", args[i]); - this->SetError(message); + status.SetError( + cmStrCat("Can not find target to add properties to: ", args[i])); return false; } } return true; } -bool cmSetTargetPropertiesCommand::SetOneTarget( - const std::string& tname, std::vector<std::string>& propertyPairs, - cmMakefile* mf) +static bool SetOneTarget(const std::string& tname, + std::vector<std::string>& propertyPairs, + cmMakefile* mf) { if (cmTarget* target = mf->FindTargetToUse(tname)) { // now loop through all the props and set them diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h index e77b752..9d40c74 100644 --- a/Source/cmSetTargetPropertiesCommand.h +++ b/Source/cmSetTargetPropertiesCommand.h @@ -8,34 +8,9 @@ #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" - class cmExecutionStatus; -class cmMakefile; - -class cmSetTargetPropertiesCommand : public cmCommand -{ -public: - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmSetTargetPropertiesCommand>(); - } - - /** - * This is called when the command is first encountered in - * the input file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - /** - * Used by this command and cmSetPropertiesCommand - */ - static bool SetOneTarget(const std::string& tname, - std::vector<std::string>& propertyPairs, - cmMakefile* mf); -}; +bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 3344217..bd68d04 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -314,6 +314,13 @@ bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const return cmIsOn(this->GetProperty(prop)); } +void cmSourceFile::SetProperties(cmPropertyMap properties) +{ + this->Properties = std::move(properties); + + this->IsGenerated = this->GetPropertyAsBool(propGENERATED); +} + cmCustomCommand* cmSourceFile::GetCustomCommand() const { return this->CustomCommand.get(); diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index ff465c7..3b18fdb 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -94,8 +94,9 @@ public: void AddDepend(const std::string& d) { this->Depends.push_back(d); } // Get the properties - cmPropertyMap& GetProperties() { return this->Properties; } const cmPropertyMap& GetProperties() const { return this->Properties; } + // Set the properties + void SetProperties(cmPropertyMap properties); /** * Check whether the given source file location could refer to this diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx index 3be7fec..3a13e57 100644 --- a/Source/cmSourceGroupCommand.cxx +++ b/Source/cmSourceGroupCommand.cxx @@ -3,16 +3,22 @@ #include "cmSourceGroupCommand.h" #include <cstddef> +#include <map> #include <set> #include <utility> #include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmSourceGroup.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" namespace { + +using ParsedArguments = std::map<std::string, std::vector<std::string>>; +using ExpectedOptions = std::vector<std::string>; + const std::string kTreeOptionName = "TREE"; const std::string kPrefixOptionName = "PREFIX"; const std::string kFilesOptionName = "FILES"; @@ -117,13 +123,8 @@ bool addFilesToItsSourceGroups(const std::string& root, return true; } -} -class cmExecutionStatus; - -// cmSourceGroupCommand -cmSourceGroupCommand::ExpectedOptions -cmSourceGroupCommand::getExpectedOptions() const +ExpectedOptions getExpectedOptions() { ExpectedOptions options; @@ -135,15 +136,14 @@ cmSourceGroupCommand::getExpectedOptions() const return options; } -bool cmSourceGroupCommand::isExpectedOption( - const std::string& argument, const ExpectedOptions& expectedOptions) +bool isExpectedOption(const std::string& argument, + const ExpectedOptions& expectedOptions) { return cmContains(expectedOptions, argument); } -void cmSourceGroupCommand::parseArguments( - const std::vector<std::string>& args, - cmSourceGroupCommand::ParsedArguments& parsedArguments) +void parseArguments(const std::vector<std::string>& args, + ParsedArguments& parsedArguments) { const ExpectedOptions expectedOptions = getExpectedOptions(); size_t i = 0; @@ -172,21 +172,35 @@ void cmSourceGroupCommand::parseArguments( } } -bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +} // namespace + +static bool checkArgumentsPreconditions(const ParsedArguments& parsedArguments, + std::string& errorMsg); + +static bool processTree(cmMakefile& mf, ParsedArguments& parsedArguments, + std::string& errorMsg); + +static bool checkSingleParameterArgumentPreconditions( + const std::string& argument, const ParsedArguments& parsedArguments, + std::string& errorMsg); + +bool cmSourceGroupCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } + cmMakefile& mf = status.GetMakefile(); + // If only two arguments are given, the pre-1.8 version of the // command is being invoked. if (args.size() == 2 && args[1] != "FILES") { - cmSourceGroup* sg = this->Makefile->GetOrCreateSourceGroup(args[0]); + cmSourceGroup* sg = mf.GetOrCreateSourceGroup(args[0]); if (!sg) { - this->SetError("Could not create or find source group"); + status.SetError("Could not create or find source group"); return false; } @@ -204,21 +218,21 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args, } if (parsedArguments.find(kTreeOptionName) != parsedArguments.end()) { - if (!processTree(parsedArguments, errorMsg)) { - this->SetError(errorMsg); + if (!processTree(mf, parsedArguments, errorMsg)) { + status.SetError(errorMsg); return false; } } else { if (parsedArguments.find(kSourceGroupOptionName) == parsedArguments.end()) { - this->SetError("Missing source group name."); + status.SetError("Missing source group name."); return false; } - cmSourceGroup* sg = this->Makefile->GetOrCreateSourceGroup(args[0]); + cmSourceGroup* sg = mf.GetOrCreateSourceGroup(args[0]); if (!sg) { - this->SetError("Could not create or find source group"); + status.SetError("Could not create or find source group"); return false; } @@ -234,8 +248,7 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args, for (auto const& filesArg : filesArguments) { std::string src = filesArg; if (!cmSystemTools::FileIsFullPath(src)) { - src = - cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', filesArg); + src = cmStrCat(mf.GetCurrentSourceDirectory(), '/', filesArg); } src = cmSystemTools::CollapseFullPath(src); sg->AddGroupFile(src); @@ -245,8 +258,8 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args, return true; } -bool cmSourceGroupCommand::checkArgumentsPreconditions( - const ParsedArguments& parsedArguments, std::string& errorMsg) const +static bool checkArgumentsPreconditions(const ParsedArguments& parsedArguments, + std::string& errorMsg) { return checkSingleParameterArgumentPreconditions( kPrefixOptionName, parsedArguments, errorMsg) && @@ -256,8 +269,8 @@ bool cmSourceGroupCommand::checkArgumentsPreconditions( parsedArguments, errorMsg); } -bool cmSourceGroupCommand::processTree(ParsedArguments& parsedArguments, - std::string& errorMsg) +static bool processTree(cmMakefile& mf, ParsedArguments& parsedArguments, + std::string& errorMsg) { const std::string root = cmSystemTools::CollapseFullPath(parsedArguments[kTreeOptionName].front()); @@ -265,9 +278,8 @@ bool cmSourceGroupCommand::processTree(ParsedArguments& parsedArguments, ? "" : parsedArguments[kPrefixOptionName].front(); - const std::vector<std::string> filesVector = - prepareFilesPathsForTree(parsedArguments[kFilesOptionName], - this->Makefile->GetCurrentSourceDirectory()); + const std::vector<std::string> filesVector = prepareFilesPathsForTree( + parsedArguments[kFilesOptionName], mf.GetCurrentSourceDirectory()); if (!rootIsPrefix(root, filesVector, errorMsg)) { return false; @@ -276,13 +288,13 @@ bool cmSourceGroupCommand::processTree(ParsedArguments& parsedArguments, std::set<std::string> sourceGroupPaths = getSourceGroupFilesPaths(root, filesVector); - return addFilesToItsSourceGroups(root, sourceGroupPaths, prefix, - *(this->Makefile), errorMsg); + return addFilesToItsSourceGroups(root, sourceGroupPaths, prefix, mf, + errorMsg); } -bool cmSourceGroupCommand::checkSingleParameterArgumentPreconditions( +static bool checkSingleParameterArgumentPreconditions( const std::string& argument, const ParsedArguments& parsedArguments, - std::string& errorMsg) const + std::string& errorMsg) { auto foundArgument = parsedArguments.find(argument); if (foundArgument != parsedArguments.end()) { diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h index 6273d92..ad39701 100644 --- a/Source/cmSourceGroupCommand.h +++ b/Source/cmSourceGroupCommand.h @@ -5,59 +5,12 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <map> #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmSourceGroupCommand - * \brief Adds a cmSourceGroup to the cmMakefile. - * - * cmSourceGroupCommand is used to define cmSourceGroups which split up - * source files in to named, organized groups in the generated makefiles. - */ -class cmSourceGroupCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmSourceGroupCommand>(); - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - using ParsedArguments = std::map<std::string, std::vector<std::string>>; - using ExpectedOptions = std::vector<std::string>; - - ExpectedOptions getExpectedOptions() const; - - bool isExpectedOption(const std::string& argument, - const ExpectedOptions& expectedOptions); - - void parseArguments(const std::vector<std::string>& args, - cmSourceGroupCommand::ParsedArguments& parsedArguments); - - bool processTree(ParsedArguments& parsedArguments, std::string& errorMsg); - - bool checkArgumentsPreconditions(const ParsedArguments& parsedArguments, - std::string& errorMsg) const; - bool checkSingleParameterArgumentPreconditions( - const std::string& argument, const ParsedArguments& parsedArguments, - std::string& errorMsg) const; -}; +bool cmSourceGroupCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 93ad2d7..6de312c 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -503,7 +503,7 @@ void cmState::AddScriptedCommand(std::string const& name, Command command) std::string sName = cmSystemTools::LowerCase(name); // if the command already exists, give a new name to the old command. - if (Command oldCmd = this->GetCommand(sName)) { + if (Command oldCmd = this->GetCommandByExactName(sName)) { this->ScriptedCommands["_" + sName] = oldCmd; } diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index b432599..0d2383a 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -5,6 +5,7 @@ #include <cstring> #include <sstream> +#include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -15,44 +16,64 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmTargetLinkLibraryType.h" #include "cmake.h" -class cmExecutionStatus; +namespace { -const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] = { - "general", "debug", "optimized" +enum ProcessingState +{ + ProcessingLinkLibraries, + ProcessingPlainLinkInterface, + ProcessingKeywordLinkInterface, + ProcessingPlainPublicInterface, + ProcessingKeywordPublicInterface, + ProcessingPlainPrivateInterface, + ProcessingKeywordPrivateInterface }; -// cmTargetLinkLibrariesCommand -bool cmTargetLinkLibrariesCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +const char* LinkLibraryTypeNames[3] = { "general", "debug", "optimized" }; + +} // namespace + +static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left, + int right); + +static bool HandleLibrary(cmMakefile& mf, cmTarget* target, + ProcessingState currentProcessingState, + const std::string& lib, cmTargetLinkLibraryType llt); + +bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { // Must have at least one argument. if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } + + cmMakefile& mf = status.GetMakefile(); + // Alias targets cannot be on the LHS of this command. - if (this->Makefile->IsAlias(args[0])) { - this->SetError("can not be used on an ALIAS target."); + if (mf.IsAlias(args[0])) { + status.SetError("can not be used on an ALIAS target."); return false; } // Lookup the target for which libraries are specified. - this->Target = - this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget( - args[0]); - if (!this->Target) { + cmTarget* target = + mf.GetCMakeInstance()->GetGlobalGenerator()->FindTarget(args[0]); + if (!target) { const std::vector<cmTarget*>& importedTargets = - this->Makefile->GetOwnedImportedTargets(); + mf.GetOwnedImportedTargets(); for (cmTarget* importedTarget : importedTargets) { if (importedTarget->GetName() == args[0]) { - this->Target = importedTarget; + target = importedTarget; break; } } } - if (!this->Target) { + if (!target) { MessageType t = MessageType::FATAL_ERROR; // fail by default std::ostringstream e; e << "Cannot specify link libraries for target \"" << args[0] << "\" " @@ -60,7 +81,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( // The bad target is the only argument. Check how policy CMP0016 is set, // and accept, warn or fail respectively: if (args.size() < 2) { - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0016)) { + switch (mf.GetPolicyStatus(cmPolicies::CMP0016)) { case cmPolicies::WARN: t = MessageType::AUTHOR_WARNING; // Print the warning. @@ -84,10 +105,10 @@ bool cmTargetLinkLibrariesCommand::InitialPass( // Now actually print the message. switch (t) { case MessageType::AUTHOR_WARNING: - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); break; case MessageType::FATAL_ERROR: - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + mf.IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); break; default: @@ -97,11 +118,11 @@ bool cmTargetLinkLibrariesCommand::InitialPass( } // Having a UTILITY library on the LHS is a bug. - if (this->Target->GetType() == cmStateEnums::UTILITY) { + if (target->GetType() == cmStateEnums::UTILITY) { std::ostringstream e; const char* modal = nullptr; MessageType messageType = MessageType::AUTHOR_WARNING; - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0039)) { + switch (mf.GetPolicyStatus(cmPolicies::CMP0039)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0039) << "\n"; modal = "should"; @@ -114,9 +135,9 @@ bool cmTargetLinkLibrariesCommand::InitialPass( messageType = MessageType::FATAL_ERROR; } if (modal) { - e << "Utility target \"" << this->Target->GetName() << "\" " << modal + e << "Utility target \"" << target->GetName() << "\" " << modal << " not be used as the target of a target_link_libraries call."; - this->Makefile->IssueMessage(messageType, e.str()); + mf.IssueMessage(messageType, e.str()); if (messageType == MessageType::FATAL_ERROR) { return false; } @@ -134,15 +155,15 @@ bool cmTargetLinkLibrariesCommand::InitialPass( // Start with primary linking and switch to link interface // specification if the keyword is encountered as the first argument. - this->CurrentProcessingState = ProcessingLinkLibraries; + ProcessingState currentProcessingState = ProcessingLinkLibraries; // Add libraries, note that there is an optional prefix // of debug and optimized that can be used. for (unsigned int i = 1; i < args.size(); ++i) { if (args[i] == "LINK_INTERFACE_LIBRARIES") { - this->CurrentProcessingState = ProcessingPlainLinkInterface; + currentProcessingState = ProcessingPlainLinkInterface; if (i != 1) { - this->Makefile->IssueMessage( + mf.IssueMessage( MessageType::FATAL_ERROR, "The LINK_INTERFACE_LIBRARIES option must appear as the second " "argument, just after the target name."); @@ -150,84 +171,83 @@ bool cmTargetLinkLibrariesCommand::InitialPass( } } else if (args[i] == "INTERFACE") { if (i != 1 && - this->CurrentProcessingState != ProcessingKeywordPrivateInterface && - this->CurrentProcessingState != ProcessingKeywordPublicInterface && - this->CurrentProcessingState != ProcessingKeywordLinkInterface) { - this->Makefile->IssueMessage( + currentProcessingState != ProcessingKeywordPrivateInterface && + currentProcessingState != ProcessingKeywordPublicInterface && + currentProcessingState != ProcessingKeywordLinkInterface) { + mf.IssueMessage( MessageType::FATAL_ERROR, "The INTERFACE, PUBLIC or PRIVATE option must appear as the second " "argument, just after the target name."); return true; } - this->CurrentProcessingState = ProcessingKeywordLinkInterface; + currentProcessingState = ProcessingKeywordLinkInterface; } else if (args[i] == "LINK_PUBLIC") { if (i != 1 && - this->CurrentProcessingState != ProcessingPlainPrivateInterface && - this->CurrentProcessingState != ProcessingPlainPublicInterface) { - this->Makefile->IssueMessage( + currentProcessingState != ProcessingPlainPrivateInterface && + currentProcessingState != ProcessingPlainPublicInterface) { + mf.IssueMessage( MessageType::FATAL_ERROR, "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second " "argument, just after the target name."); return true; } - this->CurrentProcessingState = ProcessingPlainPublicInterface; + currentProcessingState = ProcessingPlainPublicInterface; } else if (args[i] == "PUBLIC") { if (i != 1 && - this->CurrentProcessingState != ProcessingKeywordPrivateInterface && - this->CurrentProcessingState != ProcessingKeywordPublicInterface && - this->CurrentProcessingState != ProcessingKeywordLinkInterface) { - this->Makefile->IssueMessage( + currentProcessingState != ProcessingKeywordPrivateInterface && + currentProcessingState != ProcessingKeywordPublicInterface && + currentProcessingState != ProcessingKeywordLinkInterface) { + mf.IssueMessage( MessageType::FATAL_ERROR, "The INTERFACE, PUBLIC or PRIVATE option must appear as the second " "argument, just after the target name."); return true; } - this->CurrentProcessingState = ProcessingKeywordPublicInterface; + currentProcessingState = ProcessingKeywordPublicInterface; } else if (args[i] == "LINK_PRIVATE") { - if (i != 1 && - this->CurrentProcessingState != ProcessingPlainPublicInterface && - this->CurrentProcessingState != ProcessingPlainPrivateInterface) { - this->Makefile->IssueMessage( + if (i != 1 && currentProcessingState != ProcessingPlainPublicInterface && + currentProcessingState != ProcessingPlainPrivateInterface) { + mf.IssueMessage( MessageType::FATAL_ERROR, "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second " "argument, just after the target name."); return true; } - this->CurrentProcessingState = ProcessingPlainPrivateInterface; + currentProcessingState = ProcessingPlainPrivateInterface; } else if (args[i] == "PRIVATE") { if (i != 1 && - this->CurrentProcessingState != ProcessingKeywordPrivateInterface && - this->CurrentProcessingState != ProcessingKeywordPublicInterface && - this->CurrentProcessingState != ProcessingKeywordLinkInterface) { - this->Makefile->IssueMessage( + currentProcessingState != ProcessingKeywordPrivateInterface && + currentProcessingState != ProcessingKeywordPublicInterface && + currentProcessingState != ProcessingKeywordLinkInterface) { + mf.IssueMessage( MessageType::FATAL_ERROR, "The INTERFACE, PUBLIC or PRIVATE option must appear as the second " "argument, just after the target name."); return true; } - this->CurrentProcessingState = ProcessingKeywordPrivateInterface; + currentProcessingState = ProcessingKeywordPrivateInterface; } else if (args[i] == "debug") { if (haveLLT) { - this->LinkLibraryTypeSpecifierWarning(llt, DEBUG_LibraryType); + LinkLibraryTypeSpecifierWarning(mf, llt, DEBUG_LibraryType); } llt = DEBUG_LibraryType; haveLLT = true; } else if (args[i] == "optimized") { if (haveLLT) { - this->LinkLibraryTypeSpecifierWarning(llt, OPTIMIZED_LibraryType); + LinkLibraryTypeSpecifierWarning(mf, llt, OPTIMIZED_LibraryType); } llt = OPTIMIZED_LibraryType; haveLLT = true; } else if (args[i] == "general") { if (haveLLT) { - this->LinkLibraryTypeSpecifierWarning(llt, GENERAL_LibraryType); + LinkLibraryTypeSpecifierWarning(mf, llt, GENERAL_LibraryType); } llt = GENERAL_LibraryType; haveLLT = true; } else if (haveLLT) { // The link type was specified by the previous argument. haveLLT = false; - if (!this->HandleLibrary(args[i], llt)) { + if (!HandleLibrary(mf, target, currentProcessingState, args[i], llt)) { return false; } } else { @@ -239,7 +259,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( // with old versions of CMake and new) llt = GENERAL_LibraryType; std::string linkType = cmStrCat(args[0], "_LINK_TYPE"); - const char* linkTypeString = this->Makefile->GetDefinition(linkType); + const char* linkTypeString = mf.GetDefinition(linkType); if (linkTypeString) { if (strcmp(linkTypeString, "debug") == 0) { llt = DEBUG_LibraryType; @@ -248,7 +268,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( llt = OPTIMIZED_LibraryType; } } - if (!this->HandleLibrary(args[i], llt)) { + if (!HandleLibrary(mf, target, currentProcessingState, args[i], llt)) { return false; } } @@ -256,16 +276,14 @@ bool cmTargetLinkLibrariesCommand::InitialPass( // Make sure the last argument was not a library type specifier. if (haveLLT) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("The \"", - cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[llt], - "\" argument must be followed by a library.")); + mf.IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("The \"", LinkLibraryTypeNames[llt], + "\" argument must be followed by a library.")); cmSystemTools::SetFatalErrorOccured(); } const cmPolicies::PolicyStatus policy22Status = - this->Target->GetPolicyStatusCMP0022(); + target->GetPolicyStatusCMP0022(); // If any of the LINK_ options were given, make sure the // LINK_INTERFACE_LIBRARIES target property exists. @@ -274,41 +292,40 @@ bool cmTargetLinkLibrariesCommand::InitialPass( // result in an empty link interface. if ((policy22Status == cmPolicies::OLD || policy22Status == cmPolicies::WARN) && - this->CurrentProcessingState != ProcessingLinkLibraries && - !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES")) { - this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", ""); + currentProcessingState != ProcessingLinkLibraries && + !target->GetProperty("LINK_INTERFACE_LIBRARIES")) { + target->SetProperty("LINK_INTERFACE_LIBRARIES", ""); } return true; } -void cmTargetLinkLibrariesCommand::LinkLibraryTypeSpecifierWarning(int left, - int right) +static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left, + int right) { - this->Makefile->IssueMessage( + mf.IssueMessage( MessageType::AUTHOR_WARNING, cmStrCat( - "Link library type specifier \"", - cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[left], - "\" is followed by specifier \"", - cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[right], + "Link library type specifier \"", LinkLibraryTypeNames[left], + "\" is followed by specifier \"", LinkLibraryTypeNames[right], "\" instead of a library name. The first specifier will be ignored.")); } -bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, - cmTargetLinkLibraryType llt) +static bool HandleLibrary(cmMakefile& mf, cmTarget* target, + ProcessingState currentProcessingState, + const std::string& lib, cmTargetLinkLibraryType llt) { - if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && - this->CurrentProcessingState != ProcessingKeywordLinkInterface) { - this->Makefile->IssueMessage( + if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY && + currentProcessingState != ProcessingKeywordLinkInterface) { + mf.IssueMessage( MessageType::FATAL_ERROR, "INTERFACE library can only be used with the INTERFACE keyword of " "target_link_libraries"); return false; } - if (this->Target->IsImported() && - this->CurrentProcessingState != ProcessingKeywordLinkInterface) { - this->Makefile->IssueMessage( + if (target->IsImported() && + currentProcessingState != ProcessingKeywordLinkInterface) { + mf.IssueMessage( MessageType::FATAL_ERROR, "IMPORTED library can only be used with the INTERFACE keyword of " "target_link_libraries"); @@ -316,19 +333,18 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, } cmTarget::TLLSignature sig = - (this->CurrentProcessingState == ProcessingPlainPrivateInterface || - this->CurrentProcessingState == ProcessingPlainPublicInterface || - this->CurrentProcessingState == ProcessingKeywordPrivateInterface || - this->CurrentProcessingState == ProcessingKeywordPublicInterface || - this->CurrentProcessingState == ProcessingKeywordLinkInterface) + (currentProcessingState == ProcessingPlainPrivateInterface || + currentProcessingState == ProcessingPlainPublicInterface || + currentProcessingState == ProcessingKeywordPrivateInterface || + currentProcessingState == ProcessingKeywordPublicInterface || + currentProcessingState == ProcessingKeywordLinkInterface) ? cmTarget::KeywordTLLSignature : cmTarget::PlainTLLSignature; - if (!this->Target->PushTLLCommandTrace( - sig, this->Makefile->GetExecutionContext())) { + if (!target->PushTLLCommandTrace(sig, mf.GetExecutionContext())) { std::ostringstream e; const char* modal = nullptr; MessageType messageType = MessageType::AUTHOR_WARNING; - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0023)) { + switch (mf.GetPolicyStatus(cmPolicies::CMP0023)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n"; modal = "should"; @@ -349,14 +365,14 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, e << "The " << existingSig << " signature for target_link_libraries has " "already been used with the target \"" - << this->Target->GetName() + << target->GetName() << "\". All uses of target_link_libraries with a target " << modal << " be either all-keyword or all-plain.\n"; - this->Target->GetTllSignatureTraces(e, - sig == cmTarget::KeywordTLLSignature - ? cmTarget::PlainTLLSignature - : cmTarget::KeywordTLLSignature); - this->Makefile->IssueMessage(messageType, e.str()); + target->GetTllSignatureTraces(e, + sig == cmTarget::KeywordTLLSignature + ? cmTarget::PlainTLLSignature + : cmTarget::KeywordTLLSignature); + mf.IssueMessage(messageType, e.str()); if (messageType == MessageType::FATAL_ERROR) { return false; } @@ -366,9 +382,9 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, bool warnRemoteInterface = false; bool rejectRemoteLinking = false; bool encodeRemoteReference = false; - if (this->Makefile != this->Target->GetMakefile()) { + if (&mf != target->GetMakefile()) { // The LHS target was created in another directory. - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0079)) { + switch (mf.GetPolicyStatus(cmPolicies::CMP0079)) { case cmPolicies::WARN: warnRemoteInterface = true; CM_FALLTHROUGH; @@ -389,7 +405,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, // same directory as the target was created. Add a suffix to // the name to tell ResolveLinkItem to look up the name in the // caller's directory. - cmDirectoryId const dirId = this->Makefile->GetDirectoryId(); + cmDirectoryId const dirId = mf.GetDirectoryId(); libRef = lib + CMAKE_DIRECTORY_ID_SEP + dirId.String; } else { // This is an absolute path or a library name added by a caller @@ -401,21 +417,21 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, // Handle normal case where the command was called with another keyword than // INTERFACE / LINK_INTERFACE_LIBRARIES or none at all. (The "LINK_LIBRARIES" // property of the target on the LHS shall be populated.) - if (this->CurrentProcessingState != ProcessingKeywordLinkInterface && - this->CurrentProcessingState != ProcessingPlainLinkInterface) { + if (currentProcessingState != ProcessingKeywordLinkInterface && + currentProcessingState != ProcessingPlainLinkInterface) { if (rejectRemoteLinking) { - this->Makefile->IssueMessage( + mf.IssueMessage( MessageType::FATAL_ERROR, cmStrCat("Attempt to add link library \"", lib, "\" to target \"", - this->Target->GetName(), + target->GetName(), "\" which is not built in this " "directory.\nThis is allowed only when policy CMP0079 " "is set to NEW.")); return false; } - cmTarget* tgt = this->Makefile->GetGlobalGenerator()->FindTarget(lib); + cmTarget* tgt = mf.GetGlobalGenerator()->FindTarget(lib); if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) && (tgt->GetType() != cmStateEnums::SHARED_LIBRARY) && @@ -423,7 +439,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, (tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) && (tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) && !tgt->IsExecutableWithExports()) { - this->Makefile->IssueMessage( + mf.IssueMessage( MessageType::FATAL_ERROR, cmStrCat( "Target \"", lib, "\" of type ", @@ -433,15 +449,15 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, "executables with the ENABLE_EXPORTS property set.")); } - this->Target->AddLinkLibrary(*this->Makefile, lib, libRef, llt); + target->AddLinkLibrary(mf, lib, libRef, llt); } if (warnRemoteInterface) { - this->Makefile->IssueMessage( + mf.IssueMessage( MessageType::AUTHOR_WARNING, cmStrCat( cmPolicies::GetPolicyWarning(cmPolicies::CMP0079), "\nTarget\n ", - this->Target->GetName(), + target->GetName(), "\nis not created in this " "directory. For compatibility with older versions of CMake, link " "library\n ", @@ -454,18 +470,17 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, // LINK_PRIVATE and stop its processing. (The "INTERFACE_LINK_LIBRARIES" // property of the target on the LHS shall only be populated if it is a // STATIC library.) - if (this->CurrentProcessingState == ProcessingKeywordPrivateInterface || - this->CurrentProcessingState == ProcessingPlainPrivateInterface) { - if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY || - this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { + if (currentProcessingState == ProcessingKeywordPrivateInterface || + currentProcessingState == ProcessingPlainPrivateInterface) { + if (target->GetType() == cmStateEnums::STATIC_LIBRARY || + target->GetType() == cmStateEnums::OBJECT_LIBRARY) { std::string configLib = - this->Target->GetDebugGeneratorExpressions(libRef, llt); + target->GetDebugGeneratorExpressions(libRef, llt); if (cmGeneratorExpression::IsValidTargetName(lib) || cmGeneratorExpression::Find(lib) != std::string::npos) { configLib = "$<LINK_ONLY:" + configLib + ">"; } - this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES", - configLib.c_str()); + target->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib.c_str()); } return true; } @@ -473,23 +488,23 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, // Handle general case where the command was called with another keyword than // PRIVATE / LINK_PRIVATE or none at all. (The "INTERFACE_LINK_LIBRARIES" // property of the target on the LHS shall be populated.) - this->Target->AppendProperty( + target->AppendProperty( "INTERFACE_LINK_LIBRARIES", - this->Target->GetDebugGeneratorExpressions(libRef, llt).c_str()); + target->GetDebugGeneratorExpressions(libRef, llt).c_str()); // Stop processing if called without any keyword. - if (this->CurrentProcessingState == ProcessingLinkLibraries) { + if (currentProcessingState == ProcessingLinkLibraries) { return true; } // Stop processing if policy CMP0022 is set to NEW. const cmPolicies::PolicyStatus policy22Status = - this->Target->GetPolicyStatusCMP0022(); + target->GetPolicyStatusCMP0022(); if (policy22Status != cmPolicies::OLD && policy22Status != cmPolicies::WARN) { return true; } // Stop processing if called with an INTERFACE library on the LHS. - if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { return true; } @@ -499,7 +514,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, { // Get the list of configurations considered to be DEBUG. std::vector<std::string> debugConfigs = - this->Makefile->GetCMakeInstance()->GetDebugConfigs(); + mf.GetCMakeInstance()->GetDebugConfigs(); std::string prop; // Include this library in the link interface for the target. @@ -507,19 +522,19 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, // Put in the DEBUG configuration interfaces. for (std::string const& dc : debugConfigs) { prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); - this->Target->AppendProperty(prop, libRef.c_str()); + target->AppendProperty(prop, libRef.c_str()); } } if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) { // Put in the non-DEBUG configuration interfaces. - this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef.c_str()); + target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef.c_str()); // Make sure the DEBUG configuration interfaces exist so that the // general one will not be used as a fall-back. for (std::string const& dc : debugConfigs) { prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); - if (!this->Target->GetProperty(prop)) { - this->Target->SetProperty(prop, ""); + if (!target->GetProperty(prop)) { + target->SetProperty(prop, ""); } } } diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index caf2cf4..4b2deab 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -8,61 +8,9 @@ #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" -#include "cmTargetLinkLibraryType.h" - class cmExecutionStatus; -class cmTarget; - -/** \class cmTargetLinkLibrariesCommand - * \brief Specify a list of libraries to link into executables. - * - * cmTargetLinkLibrariesCommand is used to specify a list of libraries to link - * into executable(s) or shared objects. The names of the libraries - * should be those defined by the LIBRARY(library) command(s). - * - * Additionally, it allows to propagate usage-requirements (including link - * libraries) from one target into another. - */ -class cmTargetLinkLibrariesCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmTargetLinkLibrariesCommand>(); - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - void LinkLibraryTypeSpecifierWarning(int left, int right); - static const char* LinkLibraryTypeNames[3]; - - cmTarget* Target = nullptr; - enum ProcessingState - { - ProcessingLinkLibraries, - ProcessingPlainLinkInterface, - ProcessingKeywordLinkInterface, - ProcessingPlainPublicInterface, - ProcessingKeywordPublicInterface, - ProcessingPlainPrivateInterface, - ProcessingKeywordPrivateInterface - }; - - ProcessingState CurrentProcessingState = ProcessingLinkLibraries; - bool HandleLibrary(const std::string& lib, cmTargetLinkLibraryType llt); -}; +bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx index 97f1bea..5751fff 100644 --- a/Source/cmTargetPrecompileHeadersCommand.cxx +++ b/Source/cmTargetPrecompileHeadersCommand.cxx @@ -2,17 +2,29 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetPrecompileHeadersCommand.h" +#include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmStringAlgorithms.h" +#include "cmSystemTools.h" #include "cmTarget.h" +#include <utility> + bool cmTargetPrecompileHeadersCommand::InitialPass( std::vector<std::string> const& args, cmExecutionStatus&) { return this->HandleArguments(args, "PRECOMPILE_HEADERS", PROCESS_REUSE_FROM); } +void cmTargetPrecompileHeadersCommand::HandleInterfaceContent( + cmTarget* tgt, const std::vector<std::string>& content, bool prepend, + bool system) +{ + cmTargetPropCommandBase::HandleInterfaceContent( + tgt, ConvertToAbsoluteContent(tgt, content, true), prepend, system); +} + void cmTargetPrecompileHeadersCommand::HandleMissingTarget( const std::string& name) { @@ -31,6 +43,33 @@ std::string cmTargetPrecompileHeadersCommand::Join( bool cmTargetPrecompileHeadersCommand::HandleDirectContent( cmTarget* tgt, const std::vector<std::string>& content, bool, bool) { - tgt->AppendProperty("PRECOMPILE_HEADERS", this->Join(content).c_str()); + tgt->AppendProperty( + "PRECOMPILE_HEADERS", + this->Join(ConvertToAbsoluteContent(tgt, content, false)).c_str()); return true; } + +std::vector<std::string> +cmTargetPrecompileHeadersCommand::ConvertToAbsoluteContent( + cmTarget* /*tgt*/, const std::vector<std::string>& content, + bool /*isInterfaceContent*/) +{ + std::vector<std::string> absoluteContent; + absoluteContent.reserve(content.size()); + for (std::string const& src : content) { + std::string absoluteSrc; + // Use '<foo.h>' and '"foo.h"' includes and absolute paths as-is. + // Interpret relative paths with respect to the source directory. + // If the path starts in a generator expression, assume it is absolute. + if (cmHasLiteralPrefix(src, "<") || cmHasLiteralPrefix(src, "\"") || + cmSystemTools::FileIsFullPath(src) || + cmGeneratorExpression::Find(src) == 0) { + absoluteSrc = src; + } else { + absoluteSrc = + cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', src); + } + absoluteContent.emplace_back(std::move(absoluteSrc)); + } + return absoluteContent; +} diff --git a/Source/cmTargetPrecompileHeadersCommand.h b/Source/cmTargetPrecompileHeadersCommand.h index 7e4558e..00dc928 100644 --- a/Source/cmTargetPrecompileHeadersCommand.h +++ b/Source/cmTargetPrecompileHeadersCommand.h @@ -28,6 +28,11 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; +protected: + void HandleInterfaceContent(cmTarget* tgt, + const std::vector<std::string>& content, + bool prepend, bool system) override; + private: void HandleMissingTarget(const std::string& name) override; @@ -36,6 +41,10 @@ private: bool prepend, bool system) override; std::string Join(const std::vector<std::string>& content) override; + + std::vector<std::string> ConvertToAbsoluteContent( + cmTarget* tgt, const std::vector<std::string>& content, + bool isInterfaceContent); }; #endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 4b83595..d28905a 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1139,10 +1139,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0) std::string configType; if (const char* vsConfigurationType = this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(vsConfigurationType); - configType = cge->Evaluate(this->LocalGenerator, c); + configType = cmGeneratorExpression::Evaluate(vsConfigurationType, + this->LocalGenerator, c); } else { switch (this->GeneratorTarget->GetType()) { case cmStateEnums::SHARED_LIBRARY: @@ -1468,6 +1466,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( } // output files for custom command std::stringstream outputs; + bool symbolic = false; { const char* sep = ""; for (std::string const& o : ccg.GetOutputs()) { @@ -1475,6 +1474,12 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( ConvertToWindowsSlash(out); outputs << sep << out; sep = ";"; + if (!symbolic) { + if (cmSourceFile* sf = this->Makefile->GetSource( + o, cmSourceFileLocationKind::Known)) { + symbolic = sf->GetPropertyAsBool("SYMBOLIC"); + } + } } } if (this->ProjectType == csproj) { @@ -1484,7 +1489,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( outputs.str(), comment); } else { this->WriteCustomRuleCpp(*spe2, c, script, additional_inputs.str(), - outputs.str(), comment); + outputs.str(), comment, symbolic); } } } @@ -1492,7 +1497,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp( Elem& e2, std::string const& config, std::string const& script, std::string const& additional_inputs, std::string const& outputs, - std::string const& comment) + std::string const& comment, bool symbolic) { const std::string cond = this->CalcCondition(config); e2.WritePlatformConfigTag("Message", cond, comment); @@ -1504,6 +1509,13 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp( // VS >= 11 let us turn off linking of custom command outputs. e2.WritePlatformConfigTag("LinkObjects", cond, "false"); } + if (symbolic && + this->LocalGenerator->GetVersion() >= + cmGlobalVisualStudioGenerator::VS16) { + // VS >= 16.4 warn if outputs are not created, but one of our + // outputs is marked SYMBOLIC and not expected to be created. + e2.WritePlatformConfigTag("VerifyInputsAndOutputsExist", cond, "false"); + } } void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp( @@ -2447,49 +2459,32 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( if (ttype <= cmStateEnums::UTILITY) { if (const char* workingDir = this->GeneratorTarget->GetProperty( "VS_DEBUGGER_WORKING_DIRECTORY")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(workingDir); - std::string genWorkingDir = - cge->Evaluate(this->LocalGenerator, config); - + std::string genWorkingDir = cmGeneratorExpression::Evaluate( + workingDir, this->LocalGenerator, config); e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond, genWorkingDir); } if (const char* environment = this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(environment); - std::string genEnvironment = - cge->Evaluate(this->LocalGenerator, config); - + std::string genEnvironment = cmGeneratorExpression::Evaluate( + environment, this->LocalGenerator, config); e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond, genEnvironment); } if (const char* debuggerCommand = this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) { - - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(debuggerCommand); - std::string genDebuggerCommand = - cge->Evaluate(this->LocalGenerator, config); - + std::string genDebuggerCommand = cmGeneratorExpression::Evaluate( + debuggerCommand, this->LocalGenerator, config); e1.WritePlatformConfigTag("LocalDebuggerCommand", cond, genDebuggerCommand); } if (const char* commandArguments = this->GeneratorTarget->GetProperty( "VS_DEBUGGER_COMMAND_ARGUMENTS")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(commandArguments); - std::string genCommandArguments = - cge->Evaluate(this->LocalGenerator, config); - + std::string genCommandArguments = cmGeneratorExpression::Evaluate( + commandArguments, this->LocalGenerator, config); e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond, genCommandArguments); } @@ -3479,22 +3474,16 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( if (const char* nativeLibDirectoriesExpression = this->GeneratorTarget->GetProperty("ANDROID_NATIVE_LIB_DIRECTORIES")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(nativeLibDirectoriesExpression); - std::string nativeLibDirs = - cge->Evaluate(this->LocalGenerator, configName); + std::string nativeLibDirs = cmGeneratorExpression::Evaluate( + nativeLibDirectoriesExpression, this->LocalGenerator, configName); e2.Element("NativeLibDirectories", nativeLibDirs); } if (const char* nativeLibDependenciesExpression = this->GeneratorTarget->GetProperty( "ANDROID_NATIVE_LIB_DEPENDENCIES")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(nativeLibDependenciesExpression); - std::string nativeLibDeps = - cge->Evaluate(this->LocalGenerator, configName); + std::string nativeLibDeps = cmGeneratorExpression::Evaluate( + nativeLibDependenciesExpression, this->LocalGenerator, configName); e2.Element("NativeLibDependencies", nativeLibDeps); } @@ -3505,11 +3494,8 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( if (const char* jarDirectoriesExpression = this->GeneratorTarget->GetProperty("ANDROID_JAR_DIRECTORIES")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(jarDirectoriesExpression); - std::string jarDirectories = - cge->Evaluate(this->LocalGenerator, configName); + std::string jarDirectories = cmGeneratorExpression::Evaluate( + jarDirectoriesExpression, this->LocalGenerator, configName); e2.Element("JarDirectories", jarDirectories); } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 4dd92eb..a18a33d 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -142,7 +142,7 @@ private: std::string const& script, std::string const& additional_inputs, std::string const& outputs, - std::string const& comment); + std::string const& comment, bool symbolic); void WriteCustomRuleCSharp(Elem& e0, std::string const& config, std::string const& commandName, std::string const& script, |