diff options
Diffstat (limited to 'Source')
138 files changed, 5257 insertions, 2453 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 6adc9cf..c19c154 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -44,7 +44,7 @@ endif() if(NOT CMake_DEFAULT_RECURSION_LIMIT) if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST}) set(CMake_DEFAULT_RECURSION_LIMIT 100) - elseif(MINGW) + elseif(MINGW OR MSYS) set(CMake_DEFAULT_RECURSION_LIMIT 400) elseif(WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM") set(CMake_DEFAULT_RECURSION_LIMIT 600) @@ -198,6 +198,8 @@ set(SRCS cmCMakePath.cxx cmCMakePresetsFile.cxx cmCMakePresetsFile.h + cmCMakePresetsFileInternal.h + cmCMakePresetsFileReadJSON.cxx cmCommandArgumentParserHelper.cxx cmCommonTargetGenerator.cxx cmCommonTargetGenerator.h @@ -785,8 +787,6 @@ if (WIN32) cmVisualStudioGeneratorOptions.cxx cmVisualStudio10TargetGenerator.h cmVisualStudio10TargetGenerator.cxx - cmVisualStudio10ToolsetOptions.h - cmVisualStudio10ToolsetOptions.cxx cmLocalVisualStudio10Generator.cxx cmLocalVisualStudio10Generator.h cmGlobalVisualStudio10Generator.h diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9057828..3cf01e4 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 20) -set(CMake_VERSION_PATCH 2) +set(CMake_VERSION_PATCH 20210507) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index c4bd7f1..1429c46 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -7,6 +7,8 @@ #include <sstream> #include <utility> +#include <cm/string_view> + #include "cmCPackComponentGroup.h" #include "cmCPackIFWCommon.h" #include "cmCPackIFWGenerator.h" @@ -30,44 +32,67 @@ cmCPackIFWPackage::DependenceStruct::DependenceStruct() = default; cmCPackIFWPackage::DependenceStruct::DependenceStruct( const std::string& dependence) { - // Search compare section - size_t pos = std::string::npos; - if ((pos = dependence.find("<=")) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual; - this->Compare.Value = dependence.substr(pos + 2); - } else if ((pos = dependence.find(">=")) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual; - this->Compare.Value = dependence.substr(pos + 2); - } else if ((pos = dependence.find('<')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareLess; - this->Compare.Value = dependence.substr(pos + 1); - } else if ((pos = dependence.find('=')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareEqual; - this->Compare.Value = dependence.substr(pos + 1); - } else if ((pos = dependence.find('>')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareGreater; - this->Compare.Value = dependence.substr(pos + 1); - } else if ((pos = dependence.find('-')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareNone; - this->Compare.Value = dependence.substr(pos + 1); - } - size_t dashPos = dependence.find('-'); - if (dashPos != std::string::npos) { - pos = dashPos; - } - this->Name = dependence.substr(0, pos); + // Preferred format is name and version are separated by a colon (:), but + // note that this is only supported with QtIFW 3.1 or later. Backward + // compatibility allows a hyphen (-) as a separator instead, but names then + // cannot contain a hyphen. + size_t pos; + if ((pos = dependence.find(':')) == std::string::npos) { + pos = dependence.find('-'); + } + + if (pos != std::string::npos) { + this->Name = dependence.substr(0, pos); + ++pos; + if (pos == dependence.size()) { + // Nothing after the separator. Treat this as no version constraint. + return; + } + + const auto versionPart = + cm::string_view(dependence.data() + pos, dependence.size() - pos); + + if (cmHasLiteralPrefix(versionPart, "<=")) { + this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual; + this->Compare.Value = std::string(versionPart.substr(2)); + } else if (cmHasLiteralPrefix(versionPart, ">=")) { + this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual; + this->Compare.Value = std::string(versionPart.substr(2)); + } else if (cmHasPrefix(versionPart, '<')) { + this->Compare.Type = cmCPackIFWPackage::CompareLess; + this->Compare.Value = std::string(versionPart.substr(1)); + } else if (cmHasPrefix(versionPart, '=')) { + this->Compare.Type = cmCPackIFWPackage::CompareEqual; + this->Compare.Value = std::string(versionPart.substr(1)); + } else if (cmHasPrefix(versionPart, '>')) { + this->Compare.Type = cmCPackIFWPackage::CompareGreater; + this->Compare.Value = std::string(versionPart.substr(1)); + } else { + // We found no operator but a version specification is still expected to + // follow. The default behavior is to treat this the same as =. We + // explicitly record that as our type (it simplifies our logic a little + // and is also clearer). + this->Compare.Type = cmCPackIFWPackage::CompareEqual; + this->Compare.Value = std::string(versionPart); + } + } else { + this->Name = dependence; + } } std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const { - if (this->Compare.Type == cmCPackIFWPackage::CompareNone) { - return this->Name; - } - std::string result = this->Name; - - if (this->Compare.Type != cmCPackIFWPackage::CompareNone || - !this->Compare.Value.empty()) { + if (this->Name.find('-') != std::string::npos) { + // When a name contains a hyphen, we must use a colon after the name to + // prevent the hyphen from being parsed by QtIFW as the separator between + // the name and the version. Note that a colon is only supported with + // QtIFW 3.1 or later. + result += ":"; + } else if (this->Compare.Type != cmCPackIFWPackage::CompareNone || + !this->Compare.Value.empty()) { + // No hyphen in the name and we know a version part will follow. Use a + // hyphen as a separator since this works for all QtIFW versions. result += "-"; } @@ -609,6 +634,9 @@ void cmCPackIFWPackage::GeneratePackageFile() } // Dependencies + const bool hyphensInNamesUnsupported = this->Generator && + !this->Generator->FrameworkVersion.empty() && this->IsVersionLess("3.1"); + bool warnUnsupportedNames = false; std::set<DependenceStruct> compDepSet; for (DependenceStruct* ad : this->AlienDependencies) { compDepSet.insert(*ad); @@ -620,9 +648,13 @@ void cmCPackIFWPackage::GeneratePackageFile() if (!compDepSet.empty()) { std::ostringstream dependencies; auto it = compDepSet.begin(); + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << it->NameWithCompare(); ++it; while (it != compDepSet.end()) { + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << "," << it->NameWithCompare(); ++it; } @@ -638,15 +670,28 @@ void cmCPackIFWPackage::GeneratePackageFile() if (!compAutoDepSet.empty()) { std::ostringstream dependencies; auto it = compAutoDepSet.begin(); + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << it->NameWithCompare(); ++it; while (it != compAutoDepSet.end()) { + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << "," << it->NameWithCompare(); ++it; } xout.Element("AutoDependOn", dependencies.str()); } + if (warnUnsupportedNames) { + cmCPackIFWLogger( + WARNING, + "The dependencies for component \"" + << this->Name << "\" specify names that contain hyphens. " + << "This requires QtIFW 3.1 or later, but you are using version " + << this->Generator->FrameworkVersion << std::endl); + } + // Licenses (copy to meta dir) std::vector<std::string> licenses = this->Licenses; for (size_t i = 1; i < licenses.size(); i += 2) { diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index 7fd12dd..d9234e6 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -2,14 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackArchiveGenerator.h" +#include <cstdlib> #include <cstring> #include <map> #include <ostream> #include <utility> #include <vector> -#include <cm3p/archive.h> - #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" @@ -154,15 +153,9 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( << (filename) << ">." << std::endl); \ return 0; \ } \ - cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat); \ + cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat, 0, \ + this->GetThreadCount()); \ do { \ - if (!this->SetArchiveOptions(&archive)) { \ - cmCPackLogger(cmCPackLog::LOG_ERROR, \ - "Problem to set archive options <" \ - << (filename) << ">, ERROR = " << (archive).GetError() \ - << std::endl); \ - return 0; \ - } \ if (!archive.Open()) { \ cmCPackLogger(cmCPackLog::LOG_ERROR, \ "Problem to open archive <" \ @@ -346,26 +339,16 @@ bool cmCPackArchiveGenerator::SupportsComponentInstallation() const return this->IsOn("CPACK_ARCHIVE_COMPONENT_INSTALL"); } -bool cmCPackArchiveGenerator::SetArchiveOptions(cmArchiveWrite* archive) +int cmCPackArchiveGenerator::GetThreadCount() const { -#if ARCHIVE_VERSION_NUMBER >= 3004000 - // Upstream fixed an issue with their integer parsing in 3.4.0 which would - // cause spurious errors to be raised from `strtoull`. - if (this->Compress == cmArchiveWrite::CompressXZ) { - const char* threads = "1"; - - // CPACK_ARCHIVE_THREADS overrides CPACK_THREADS - if (this->IsSet("CPACK_ARCHIVE_THREADS")) { - threads = this->GetOption("CPACK_ARCHIVE_THREADS"); - } else if (this->IsSet("CPACK_THREADS")) { - threads = this->GetOption("CPACK_THREADS"); - } + int threads = 1; - if (!archive->SetFilterOption("xz", "threads", threads)) { - return false; - } + // CPACK_ARCHIVE_THREADS overrides CPACK_THREADS + if (this->IsSet("CPACK_ARCHIVE_THREADS")) { + threads = std::atoi(this->GetOption("CPACK_ARCHIVE_THREADS")); + } else if (this->IsSet("CPACK_THREADS")) { + threads = std::atoi(this->GetOption("CPACK_THREADS")); } -#endif - return true; + return threads; } diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h index 5b40013..8a9bbc6 100644 --- a/Source/CPack/cmCPackArchiveGenerator.h +++ b/Source/CPack/cmCPackArchiveGenerator.h @@ -85,7 +85,7 @@ private: return this->OutputExtension.c_str(); } - bool SetArchiveOptions(cmArchiveWrite* archive); + int GetThreadCount() const; private: cmArchiveWrite::Compress Compress; diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index e7bcfac..006d66d 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -130,11 +130,6 @@ DebGenerator::DebGenerator( "Unrecognized number of threads: " << numThreads << std::endl); } - - if (this->NumThreads < 0) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Number of threads cannot be negative" << std::endl); - } } bool DebGenerator::generate() const @@ -172,7 +167,6 @@ void DebGenerator::generateControlFile() const unsigned long totalSize = 0; { - std::string dirName = cmStrCat(this->TemporaryDir, '/'); for (std::string const& file : this->PackageFiles) { totalSize += cmSystemTools::FileLength(file); } diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index cefb906..0d56e5f 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -273,6 +273,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, ? this->GetOption("CPACK_DMG_FORMAT") : "UDZO"; + const std::string cpack_dmg_filesystem = + this->GetOption("CPACK_DMG_FILESYSTEM") + ? this->GetOption("CPACK_DMG_FILESYSTEM") + : "HFS+"; + // Get optional arguments ... std::string cpack_license_file = this->GetOption("CPACK_RESOURCE_FILE_LICENSE") @@ -418,7 +423,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, temp_image_command << " -ov"; temp_image_command << " -srcfolder \"" << staging.str() << "\""; temp_image_command << " -volname \"" << cpack_dmg_volume_name << "\""; - temp_image_command << " -fs HFS+"; + temp_image_command << " -fs \"" << cpack_dmg_filesystem << "\""; temp_image_command << " -format " << temp_image_format; temp_image_command << " \"" << temp_image << "\""; diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 3db4162..cd2adaa 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -384,7 +384,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( for (std::string const& gf : this->files) { bool skip = false; std::string inFile = gf; - if (cmSystemTools::FileIsDirectory(gf)) { + if (cmSystemTools::FileIsDirectory(gf) && + !cmSystemTools::FileIsSymlink(gf)) { inFile += '/'; } for (cmsys::RegularExpression& reg : ignoreFilesRegex) { @@ -693,7 +694,7 @@ int cmCPackGenerator::RunPreinstallTarget( // Does this generator require pre-install? if (const char* preinstall = globalGenerator->GetPreinstallTargetName()) { std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand( - preinstall, buildConfig, "", false); + preinstall, buildConfig, "", "", false); cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Install command: " << buildCommand << std::endl); cmCPackLogger(cmCPackLog::LOG_OUTPUT, diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index f1cc677..6bd0d1b 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -437,7 +437,9 @@ int cmCPackNSISGenerator::InitializeInternal() } #endif - nsisPath = cmSystemTools::FindProgram("makensis", path, false); + this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLE", "makensis"); + nsisPath = cmSystemTools::FindProgram( + this->GetOption("CPACK_NSIS_EXECUTABLE"), path, false); if (nsisPath.empty()) { cmCPackLogger( diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index 3e36e8c..ad0a3e2 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -51,15 +51,16 @@ int cmCPackSTGZGenerator::PackageFiles() * so we must iterate over generated packages. */ for (std::string const& pfn : this->packageFileNames) { - retval &= cmSystemTools::SetPermissions(pfn.c_str(), + retval &= static_cast<bool>( + cmSystemTools::SetPermissions(pfn.c_str(), #if defined(_MSC_VER) || defined(__MINGW32__) - S_IREAD | S_IWRITE | S_IEXEC + S_IREAD | S_IWRITE | S_IEXEC #else - S_IRUSR | S_IWUSR | S_IXUSR | - S_IRGRP | S_IWGRP | S_IXGRP | - S_IROTH | S_IWOTH | S_IXOTH + S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | + S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | + S_IXOTH #endif - ); + )); } return retval; } diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 88e2871..483c316 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -27,6 +27,7 @@ void cmCTestBuildCommand::BindArguments() this->Bind("CONFIGURATION"_s, this->Configuration); this->Bind("FLAGS"_s, this->Flags); this->Bind("PROJECT_NAME"_s, this->ProjectName); + this->Bind("PARALLEL_LEVEL"_s, this->ParallelLevel); } cmCTestBuildCommand::~cmCTestBuildCommand() = default; @@ -98,8 +99,8 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() std::string dir = this->CTest->GetCTestConfiguration("BuildDirectory"); std::string buildCommand = this->GlobalGenerator->GenerateCMakeBuildCommand( - cmakeBuildTarget, cmakeBuildConfiguration, cmakeBuildAdditionalFlags, - this->Makefile->IgnoreErrorsCMP0061()); + cmakeBuildTarget, cmakeBuildConfiguration, this->ParallelLevel, + cmakeBuildAdditionalFlags, this->Makefile->IgnoreErrorsCMP0061()); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "SetMakeCommand:" << buildCommand << "\n", this->Quiet); diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h index 00dbcc4..1254dad 100644 --- a/Source/CTest/cmCTestBuildCommand.h +++ b/Source/CTest/cmCTestBuildCommand.h @@ -60,4 +60,5 @@ protected: std::string Configuration; std::string Flags; std::string ProjectName; + std::string ParallelLevel; }; diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx index 051c117..af495bb 100644 --- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx +++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx @@ -16,7 +16,7 @@ bool cmCTestEmptyBinaryDirectoryCommand::InitialPass( return false; } - if (!cmCTestScriptHandler::EmptyBinaryDirectory(args[0].c_str())) { + if (!cmCTestScriptHandler::EmptyBinaryDirectory(args[0])) { std::ostringstream ostr; ostr << "problem removing the binary directory: " << args[0]; this->SetError(ostr.str()); diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 91818bb..cc756d7 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -21,32 +21,47 @@ cmCTestGenericHandler::cmCTestGenericHandler() cmCTestGenericHandler::~cmCTestGenericHandler() = default; -void cmCTestGenericHandler::SetOption(const std::string& op, const char* value) +/* Modify the given `map`, setting key `op` to `value` if `value` + * is non-null, otherwise removing key `op` (if it exists). + */ +static void SetMapValue(cmCTestGenericHandler::t_StringToString& map, + const std::string& op, const char* value) { if (!value) { - auto remit = this->Options.find(op); - if (remit != this->Options.end()) { - this->Options.erase(remit); - } + map.erase(op); return; } - this->Options[op] = value; + map[op] = value; +} + +void cmCTestGenericHandler::SetOption(const std::string& op, const char* value) +{ + SetMapValue(this->Options, op, value); } void cmCTestGenericHandler::SetPersistentOption(const std::string& op, const char* value) { this->SetOption(op, value); - if (!value) { - auto remit = this->PersistentOptions.find(op); - if (remit != this->PersistentOptions.end()) { - this->PersistentOptions.erase(remit); - } - return; + SetMapValue(this->PersistentOptions, op, value); +} + +void cmCTestGenericHandler::AddMultiOption(const std::string& op, + const std::string& value) +{ + if (!value.empty()) { + this->MultiOptions[op].emplace_back(value); } +} - this->PersistentOptions[op] = value; +void cmCTestGenericHandler::AddPersistentMultiOption(const std::string& op, + const std::string& value) +{ + if (!value.empty()) { + this->MultiOptions[op].emplace_back(value); + this->PersistentMultiOptions[op].emplace_back(value); + } } void cmCTestGenericHandler::Initialize() @@ -68,6 +83,17 @@ const char* cmCTestGenericHandler::GetOption(const std::string& op) return remit->second.c_str(); } +std::vector<std::string> cmCTestGenericHandler::GetMultiOption( + const std::string& optionName) const +{ + // Avoid inserting a key, which MultiOptions[op] would do. + auto remit = this->MultiOptions.find(optionName); + if (remit == this->MultiOptions.end()) { + return {}; + } + return remit->second; +} + bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part, const char* name, cmGeneratedFileStream& xofs) diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 89d7596..6f44545 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -72,11 +72,41 @@ public: virtual ~cmCTestGenericHandler(); using t_StringToString = std::map<std::string, std::string>; + using t_StringToMultiString = + std::map<std::string, std::vector<std::string>>; + /** + * Options collect a single value from flags; passing the + * flag multiple times on the command-line *overwrites* values, + * and only the last one specified counts. Set an option to + * nullptr to "unset" it. + * + * The value is stored as a string. The values set for single + * and multi-options (see below) live in different spaces, + * so calling a single-getter for a key that has only been set + * as a multi-value will return nullptr. + */ void SetPersistentOption(const std::string& op, const char* value); void SetOption(const std::string& op, const char* value); const char* GetOption(const std::string& op); + /** + * Multi-Options collect one or more values from flags; passing + * the flag multiple times on the command-line *adds* values, + * rather than overwriting the previous values. + * + * Adding an empty value does nothing. + * + * The value is stored as a vector of strings. The values set for single + * (see above) and multi-options live in different spaces, + * so calling a multi-getter for a key that has only been set + * as a single-value will return an empty vector. + */ + void AddPersistentMultiOption(const std::string& optionName, + const std::string& value); + void AddMultiOption(const std::string& optionName, const std::string& value); + std::vector<std::string> GetMultiOption(const std::string& op) const; + void SetCommand(cmCTestCommand* command) { this->Command = command; } void SetSubmitIndex(int idx) { this->SubmitIndex = idx; } @@ -100,6 +130,8 @@ protected: cmCTest* CTest; t_StringToString Options; t_StringToString PersistentOptions; + t_StringToMultiString MultiOptions; + t_StringToMultiString PersistentMultiOptions; t_StringToString LogFileNames; cmCTestCommand* Command; diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx index d0e2974..37b3628 100644 --- a/Source/CTest/cmCTestMemCheckCommand.cxx +++ b/Source/CTest/cmCTestMemCheckCommand.cxx @@ -14,7 +14,7 @@ void cmCTestMemCheckCommand::BindArguments() this->Bind("DEFECT_COUNT"_s, this->DefectCount); } -cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler() +cmCTestTestHandler* cmCTestMemCheckCommand::InitializeActualHandler() { cmCTestMemCheckHandler* handler = this->CTest->GetMemCheckHandler(); handler->Initialize(); diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h index 6544f16..ee39e49 100644 --- a/Source/CTest/cmCTestMemCheckCommand.h +++ b/Source/CTest/cmCTestMemCheckCommand.h @@ -13,6 +13,7 @@ #include "cmCommand.h" class cmCTestGenericHandler; +class cmCTestTestHandler; /** \class cmCTestMemCheck * \brief Run a ctest script @@ -36,7 +37,7 @@ public: protected: void BindArguments() override; - cmCTestGenericHandler* InitializeActualHandler() override; + cmCTestTestHandler* InitializeActualHandler() override; void ProcessAdditionalValues(cmCTestGenericHandler* handler) override; diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 852f9d9..86a8e00 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -587,24 +587,24 @@ void cmCTestMultiProcessHandler::StartNextTests() onlyRunSerialTestsLeft = false; } } - cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, "); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "***** WAITING, "); if (this->SerialTestRunning) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Waiting for RUN_SERIAL test to finish."); } else if (onlyRunSerialTestsLeft) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Only RUN_SERIAL tests remain, awaiting available slot."); } else { /* clang-format off */ - cmCTestLog(this->CTest, HANDLER_OUTPUT, + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "System Load: " << systemLoad << ", " "Max Allowed Load: " << this->TestLoad << ", " "Smallest test " << testWithMinProcessors << " requires " << minProcessorsRequired); /* clang-format on */ } - cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "*****" << std::endl); // Wait between 1 and 5 seconds before trying again. unsigned int milliseconds = (cmSystemTools::RandomSeed() % 5 + 1) * 1000; diff --git a/Source/CTest/cmCTestRunScriptCommand.cxx b/Source/CTest/cmCTestRunScriptCommand.cxx index f59ca57..7661d4d 100644 --- a/Source/CTest/cmCTestRunScriptCommand.cxx +++ b/Source/CTest/cmCTestRunScriptCommand.cxx @@ -37,8 +37,8 @@ bool cmCTestRunScriptCommand::InitialPass(std::vector<std::string> const& args, ++i; } else { int ret; - cmCTestScriptHandler::RunScript(this->CTest, this->Makefile, - args[i].c_str(), !np, &ret); + cmCTestScriptHandler::RunScript(this->CTest, this->Makefile, args[i], + !np, &ret); this->Makefile->AddDefinition(returnVariable, std::to_string(ret)); } } diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 4808c36..d2cad39 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -4,7 +4,6 @@ #include <cstdio> #include <cstdlib> -#include <cstring> #include <map> #include <ratio> #include <sstream> @@ -91,7 +90,7 @@ void cmCTestScriptHandler::Initialize() cmCTestScriptHandler::~cmCTestScriptHandler() = default; // just adds an argument to the vector -void cmCTestScriptHandler::AddConfigurationScript(const char* script, +void cmCTestScriptHandler::AddConfigurationScript(const std::string& script, bool pscope) { this->ConfigurationScripts.emplace_back(script); @@ -676,7 +675,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard() // clear the binary directory? if (this->EmptyBinDir) { - if (!cmCTestScriptHandler::EmptyBinaryDirectory(this->BinaryDir.c_str())) { + if (!cmCTestScriptHandler::EmptyBinaryDirectory(this->BinaryDir)) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem removing the binary directory" << std::endl); } @@ -724,8 +723,8 @@ int cmCTestScriptHandler::RunConfigurationDashboard() // put the initial cache into the bin dir if (!this->InitialCache.empty()) { - if (!cmCTestScriptHandler::WriteInitialCache(this->BinaryDir.c_str(), - this->InitialCache.c_str())) { + if (!cmCTestScriptHandler::WriteInitialCache(this->BinaryDir, + this->InitialCache)) { this->RestoreBackupDirectories(); return 9; } @@ -812,8 +811,8 @@ int cmCTestScriptHandler::RunConfigurationDashboard() return 0; } -bool cmCTestScriptHandler::WriteInitialCache(const char* directory, - const char* text) +bool cmCTestScriptHandler::WriteInitialCache(const std::string& directory, + const std::string& text) { std::string cacheFile = cmStrCat(directory, "/CMakeCache.txt"); cmGeneratedFileStream fout(cacheFile); @@ -821,9 +820,7 @@ bool cmCTestScriptHandler::WriteInitialCache(const char* directory, return false; } - if (text != nullptr) { - fout.write(text, strlen(text)); - } + fout.write(text.data(), text.size()); // Make sure the operating system has finished writing the file // before closing it. This will ensure the file is finished before @@ -852,7 +849,7 @@ void cmCTestScriptHandler::RestoreBackupDirectories() } bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf, - const char* sname, bool InProcess, + const std::string& sname, bool InProcess, int* returnValue) { auto sh = cm::make_unique<cmCTestScriptHandler>(); @@ -866,10 +863,10 @@ bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf, return true; } -bool cmCTestScriptHandler::EmptyBinaryDirectory(const char* sname) +bool cmCTestScriptHandler::EmptyBinaryDirectory(const std::string& sname) { // try to avoid deleting root - if (!sname || strlen(sname) < 2) { + if (sname.size() < 2) { return false; } @@ -924,7 +921,7 @@ bool cmCTestScriptHandler::TryToRemoveBinaryDirectoryOnce( } } - return cmSystemTools::RemoveADirectory(directoryPath); + return static_cast<bool>(cmSystemTools::RemoveADirectory(directoryPath)); } cmDuration cmCTestScriptHandler::GetRemainingTimeAllowed() diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h index 8eb9658..b7764b2 100644 --- a/Source/CTest/cmCTestScriptHandler.h +++ b/Source/CTest/cmCTestScriptHandler.h @@ -62,7 +62,7 @@ public: /** * Add a script to run, and if is should run in the current process */ - void AddConfigurationScript(const char*, bool pscope); + void AddConfigurationScript(const std::string&, bool pscope); /** * Run a dashboard using a specified confiuration script @@ -72,19 +72,21 @@ public: /* * Run a script */ - static bool RunScript(cmCTest* ctest, cmMakefile* mf, const char* script, - bool InProcess, int* returnValue); + static bool RunScript(cmCTest* ctest, cmMakefile* mf, + const std::string& script, bool InProcess, + int* returnValue); int RunCurrentScript(); /* * Empty Binary Directory */ - static bool EmptyBinaryDirectory(const char* dir); + static bool EmptyBinaryDirectory(const std::string& dir); /* * Write an initial CMakeCache.txt from the given contents. */ - static bool WriteInitialCache(const char* directory, const char* text); + static bool WriteInitialCache(const std::string& directory, + const std::string& text); /* * Some elapsed time handling functions diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 4403733..67f4986 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -9,7 +9,6 @@ #include <cmext/string_view> #include "cmCTest.h" -#include "cmCTestGenericHandler.h" #include "cmCTestTestHandler.h" #include "cmDuration.h" #include "cmMakefile.h" @@ -36,6 +35,7 @@ void cmCTestTestCommand::BindArguments() this->Bind("TEST_LOAD"_s, this->TestLoad); this->Bind("RESOURCE_SPEC_FILE"_s, this->ResourceSpecFile); this->Bind("STOP_ON_FAILURE"_s, this->StopOnFailure); + this->Bind("OUTPUT_JUNIT"_s, this->OutputJUnit); } cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() @@ -60,7 +60,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() this->ResourceSpecFile = *resourceSpecFile; } - cmCTestGenericHandler* handler = this->InitializeActualHandler(); + cmCTestTestHandler* handler = this->InitializeActualHandler(); if (!this->Start.empty() || !this->End.empty() || !this->Stride.empty()) { handler->SetOption( "TestsToRunInformation", @@ -73,11 +73,11 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() handler->SetOption("IncludeRegularExpression", this->Include.c_str()); } if (!this->ExcludeLabel.empty()) { - handler->SetOption("ExcludeLabelRegularExpression", - this->ExcludeLabel.c_str()); + handler->AddMultiOption("ExcludeLabelRegularExpression", + this->ExcludeLabel); } if (!this->IncludeLabel.empty()) { - handler->SetOption("LabelRegularExpression", this->IncludeLabel.c_str()); + handler->AddMultiOption("LabelRegularExpression", this->IncludeLabel); } if (!this->ExcludeFixture.empty()) { handler->SetOption("ExcludeFixtureRegularExpression", @@ -140,11 +140,15 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() *labelsForSubprojects, this->Quiet); } + if (!this->OutputJUnit.empty()) { + handler->SetJUnitXMLFileName(this->OutputJUnit); + } + handler->SetQuiet(this->Quiet); return handler; } -cmCTestGenericHandler* cmCTestTestCommand::InitializeActualHandler() +cmCTestTestHandler* cmCTestTestCommand::InitializeActualHandler() { cmCTestTestHandler* handler = this->CTest->GetTestHandler(); handler->Initialize(); diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h index 624cd91..24e74e2 100644 --- a/Source/CTest/cmCTestTestCommand.h +++ b/Source/CTest/cmCTestTestCommand.h @@ -13,6 +13,7 @@ #include "cmCommand.h" class cmCTestGenericHandler; +class cmCTestTestHandler; /** \class cmCTestTest * \brief Run a ctest script @@ -40,7 +41,7 @@ public: protected: void BindArguments() override; - virtual cmCTestGenericHandler* InitializeActualHandler(); + virtual cmCTestTestHandler* InitializeActualHandler(); cmCTestGenericHandler* InitializeHandler() override; std::string Start; @@ -59,5 +60,6 @@ protected: std::string StopTime; std::string TestLoad; std::string ResourceSpecFile; + std::string OutputJUnit; bool StopOnFailure = false; }; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 1cb5d00..1596d4a 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -42,6 +42,7 @@ #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTimestamp.h" #include "cmWorkingDirectory.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -287,8 +288,6 @@ cmCTestTestHandler::cmCTestTestHandler() { this->UseUnion = false; - this->UseIncludeLabelRegExpFlag = false; - this->UseExcludeLabelRegExpFlag = false; this->UseIncludeRegExpFlag = false; this->UseExcludeRegExpFlag = false; this->UseExcludeRegExpFirst = false; @@ -301,6 +300,9 @@ cmCTestTestHandler::cmCTestTestHandler() this->LogFile = nullptr; + // Support for JUnit XML output. + this->JUnitXMLFileName = ""; + // regex to detect <DartMeasurement>...</DartMeasurement> this->DartStuff.compile("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)"); // regex to detect each individual <DartMeasurement>...</DartMeasurement> @@ -327,13 +329,11 @@ void cmCTestTestHandler::Initialize() this->TestsToRun.clear(); - this->UseIncludeLabelRegExpFlag = false; - this->UseExcludeLabelRegExpFlag = false; this->UseIncludeRegExpFlag = false; this->UseExcludeRegExpFlag = false; this->UseExcludeRegExpFirst = false; - this->IncludeLabelRegularExpression = ""; - this->ExcludeLabelRegularExpression = ""; + this->IncludeLabelRegularExpressions.clear(); + this->ExcludeLabelRegularExpressions.clear(); this->IncludeRegExp.clear(); this->ExcludeRegExp.clear(); this->ExcludeFixtureRegExp.clear(); @@ -460,6 +460,10 @@ int cmCTestTestHandler::ProcessHandler() return 1; } + if (!this->WriteJUnitXML()) { + return 1; + } + if (!this->PostProcessHandler()) { this->LogFile = nullptr; return -1; @@ -479,6 +483,22 @@ int cmCTestTestHandler::ProcessHandler() return 0; } +/* Given a multi-option value `parts`, compile those parts into + * regular expressions in `expressions`. Skip empty values. + * Returns true if there were any expressions. + */ +static bool BuildLabelRE(const std::vector<std::string>& parts, + std::vector<cmsys::RegularExpression>& expressions) +{ + expressions.clear(); + for (const auto& p : parts) { + if (!p.empty()) { + expressions.emplace_back(p); + } + } + return !expressions.empty(); +} + bool cmCTestTestHandler::ProcessOptions() { // Update internal data structure from generic one @@ -519,18 +539,11 @@ bool cmCTestTestHandler::ProcessOptions() this->CTest->SetStopOnFailure(true); } - const char* val; - val = this->GetOption("LabelRegularExpression"); - if (val) { - this->UseIncludeLabelRegExpFlag = true; - this->IncludeLabelRegExp = val; - } - val = this->GetOption("ExcludeLabelRegularExpression"); - if (val) { - this->UseExcludeLabelRegExpFlag = true; - this->ExcludeLabelRegExp = val; - } - val = this->GetOption("IncludeRegularExpression"); + BuildLabelRE(this->GetMultiOption("LabelRegularExpression"), + this->IncludeLabelRegularExpressions); + BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"), + this->ExcludeLabelRegularExpressions); + const char* val = this->GetOption("IncludeRegularExpression"); if (val) { this->UseIncludeRegExp(); this->SetIncludeRegExp(val); @@ -763,10 +776,40 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject) cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet); } +/** + * Check if the labels (from a test) match all the expressions. + * + * Each of the RE's must match at least one label + * (e.g. all of the REs must match **some** label, + * in order for the filter to apply to the test). + */ +static bool MatchLabelsAgainstFilterRE( + const std::vector<std::string>& labels, + const std::vector<cmsys::RegularExpression>& expressions) +{ + for (const auto& re : expressions) { + // check to see if the label regular expression matches + bool found = false; // assume it does not match + cmsys::RegularExpressionMatch match; + // loop over all labels and look for match + for (std::string const& l : labels) { + if (re.find(l.c_str(), match)) { + found = true; + break; + } + } + // if no match was found, exclude the test + if (!found) { + return false; + } + } + return true; +} + void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it) { // if not using Labels to filter then return - if (!this->UseIncludeLabelRegExpFlag) { + if (this->IncludeLabelRegularExpressions.empty()) { return; } // if there are no labels and we are filtering by labels @@ -775,16 +818,9 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it) it.IsInBasedOnREOptions = false; return; } - // check to see if the label regular expression matches - bool found = false; // assume it does not match - // loop over all labels and look for match - for (std::string const& l : it.Labels) { - if (this->IncludeLabelRegularExpression.find(l)) { - found = true; - } - } // if no match was found, exclude the test - if (!found) { + if (!MatchLabelsAgainstFilterRE(it.Labels, + this->IncludeLabelRegularExpressions)) { it.IsInBasedOnREOptions = false; } } @@ -792,7 +828,7 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it) void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it) { // if not using Labels to filter then return - if (!this->UseExcludeLabelRegExpFlag) { + if (this->ExcludeLabelRegularExpressions.empty()) { return; } // if there are no labels and we are excluding by labels @@ -800,16 +836,9 @@ void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it) if (it.Labels.empty()) { return; } - // check to see if the label regular expression matches - bool found = false; // assume it does not match - // loop over all labels and look for match - for (std::string const& l : it.Labels) { - if (this->ExcludeLabelRegularExpression.find(l)) { - found = true; - } - } // if match was found, exclude the test - if (found) { + if (MatchLabelsAgainstFilterRE(it.Labels, + this->ExcludeLabelRegularExpressions)) { it.IsInBasedOnREOptions = false; } } @@ -1704,19 +1733,11 @@ bool cmCTestTestHandler::ParseResourceGroupsProperty( bool cmCTestTestHandler::GetListOfTests() { - if (!this->IncludeLabelRegExp.empty()) { - this->IncludeLabelRegularExpression.compile( - this->IncludeLabelRegExp.c_str()); - } - if (!this->ExcludeLabelRegExp.empty()) { - this->ExcludeLabelRegularExpression.compile( - this->ExcludeLabelRegExp.c_str()); - } if (!this->IncludeRegExp.empty()) { - this->IncludeTestsRegularExpression.compile(this->IncludeRegExp.c_str()); + this->IncludeTestsRegularExpression.compile(this->IncludeRegExp); } if (!this->ExcludeRegExp.empty()) { - this->ExcludeTestsRegularExpression.compile(this->ExcludeRegExp.c_str()); + this->ExcludeTestsRegularExpression.compile(this->ExcludeRegExp); } cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Constructing a list of tests" << std::endl, this->Quiet); @@ -1868,7 +1889,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() std::string dirName = this->CTest->GetBinaryDir() + "/Testing/Temporary"; cmsys::Directory directory; - if (directory.Load(dirName) == 0) { + if (!directory.Load(dirName)) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to read the contents of " << dirName << std::endl); return; @@ -2444,3 +2465,125 @@ bool cmCTestTestHandler::cmCTestTestResourceRequirement::operator!=( { return !(*this == other); } + +void cmCTestTestHandler::SetJUnitXMLFileName(const std::string& filename) +{ + this->JUnitXMLFileName = filename; +} + +bool cmCTestTestHandler::WriteJUnitXML() +{ + if (this->JUnitXMLFileName.empty()) { + return true; + } + + // Open new XML file for writing. + cmGeneratedFileStream xmlfile; + xmlfile.SetTempExt("tmp"); + xmlfile.Open(this->JUnitXMLFileName); + if (!xmlfile) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Problem opening file: " << this->JUnitXMLFileName + << std::endl); + return false; + } + cmXMLWriter xml(xmlfile); + + // Iterate over the test results to get the number of tests that + // passed, failed, etc. + auto num_tests = 0; + auto num_passed = 0; + auto num_failed = 0; + auto num_notrun = 0; + auto num_disabled = 0; + SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end()); + for (cmCTestTestResult const& result : resultsSet) { + num_tests++; + if (result.Status == cmCTestTestHandler::COMPLETED) { + num_passed++; + } else if (result.Status == cmCTestTestHandler::NOT_RUN) { + if (result.CompletionStatus == "Disabled") { + num_disabled++; + } else { + num_notrun++; + } + } else { + num_failed++; + } + } + + // Write <testsuite> element. + xml.StartDocument(); + xml.StartElement("testsuite"); + + xml.Attribute("name", + cmCTest::SafeBuildIdField( + this->CTest->GetCTestConfiguration("BuildName"))); + xml.BreakAttributes(); + + xml.Attribute("tests", num_tests); + xml.Attribute("failures", num_failed); + + // CTest disabled => JUnit disabled + xml.Attribute("disabled", num_disabled); + + // Otherwise, CTest notrun => JUnit skipped. + // The distinction between JUnit disabled vs. skipped is that + // skipped tests can have a message associated with them + // (why the test was skipped). + xml.Attribute("skipped", num_notrun); + + xml.Attribute("hostname", this->CTest->GetCTestConfiguration("Site")); + xml.Attribute( + "time", + std::chrono::duration_cast<std::chrono::seconds>(this->ElapsedTestingTime) + .count()); + const std::time_t start_test_time_t = + std::chrono::system_clock::to_time_t(this->StartTestTime); + cmTimestamp cmts; + xml.Attribute("timestamp", + cmts.CreateTimestampFromTimeT(start_test_time_t, + "%Y-%m-%dT%H:%M:%S", false)); + + // Write <testcase> elements. + for (cmCTestTestResult const& result : resultsSet) { + xml.StartElement("testcase"); + xml.Attribute("name", result.Name); + xml.Attribute("classname", result.Name); + xml.Attribute("time", result.ExecutionTime.count()); + + std::string status; + if (result.Status == cmCTestTestHandler::COMPLETED) { + status = "run"; + } else if (result.Status == cmCTestTestHandler::NOT_RUN) { + if (result.CompletionStatus == "Disabled") { + status = "disabled"; + } else { + status = "notrun"; + } + } else { + status = "fail"; + } + xml.Attribute("status", status); + + if (status == "notrun") { + xml.StartElement("skipped"); + xml.Attribute("message", result.CompletionStatus); + xml.EndElement(); // </skipped> + } else if (status == "fail") { + xml.StartElement("failure"); + xml.Attribute("message", result.Reason); + xml.EndElement(); // </failure> + } + + // Note: compressed test output is unconditionally disabled when + // --output-junit is specified. + xml.Element("system-out", result.Output); + xml.EndElement(); // </testcase> + } + + xml.EndElement(); // </testsuite> + xml.EndDocument(); + + return true; +} diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index aa29eeb..6841624 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -209,6 +209,9 @@ public: using ListOfTests = std::vector<cmCTestTestProperties>; + // Support for writing test results in JUnit XML format. + void SetJUnitXMLFileName(const std::string& id); + protected: using SetOfTests = std::set<cmCTestTestHandler::cmCTestTestResult, cmCTestTestResultLess>; @@ -274,6 +277,11 @@ private: */ virtual void GenerateDartOutput(cmXMLWriter& xml); + /** + * Write test results in JUnit XML format + */ + bool WriteJUnitXML(); + void PrintLabelOrSubprojectSummary(bool isSubProject); /** @@ -320,20 +328,16 @@ private: std::vector<int> TestsToRun; - bool UseIncludeLabelRegExpFlag; - bool UseExcludeLabelRegExpFlag; bool UseIncludeRegExpFlag; bool UseExcludeRegExpFlag; bool UseExcludeRegExpFirst; - std::string IncludeLabelRegExp; - std::string ExcludeLabelRegExp; std::string IncludeRegExp; std::string ExcludeRegExp; std::string ExcludeFixtureRegExp; std::string ExcludeFixtureSetupRegExp; std::string ExcludeFixtureCleanupRegExp; - cmsys::RegularExpression IncludeLabelRegularExpression; - cmsys::RegularExpression ExcludeLabelRegularExpression; + std::vector<cmsys::RegularExpression> IncludeLabelRegularExpressions; + std::vector<cmsys::RegularExpression> ExcludeLabelRegularExpressions; cmsys::RegularExpression IncludeTestsRegularExpression; cmsys::RegularExpression ExcludeTestsRegularExpression; @@ -358,4 +362,6 @@ private: cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; int RepeatCount = 1; bool RerunFailed; + + std::string JUnitXMLFileName; }; diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake index 7917d41..f20572e 100644 --- a/Source/Checks/cm_cxx_features.cmake +++ b/Source/Checks/cm_cxx_features.cmake @@ -80,7 +80,9 @@ if(CMake_HAVE_CXX_MAKE_UNIQUE) set(CMake_HAVE_CXX_UNIQUE_PTR 1) endif() cm_check_cxx_feature(unique_ptr) -if (NOT CMAKE_CXX_STANDARD LESS "17") +if (NOT CMAKE_CXX_STANDARD LESS "17" + AND NOT MSYS # FIXME: RunCMake.cmake_path cases crash with MSYS std::filesystem + ) if (NOT CMAKE_CROSSCOMPILING OR CMAKE_CROSSCOMPILING_EMULATOR) cm_check_cxx_feature(filesystem TRY_RUN) else() diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt index 8f26b9a..9202bc1 100644 --- a/Source/CursesDialog/form/CMakeLists.txt +++ b/Source/CursesDialog/form/CMakeLists.txt @@ -5,7 +5,7 @@ project(CMAKE_FORM) # Disable warnings to avoid changing 3rd party code. if(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx index b8bc82c..5727992 100644 --- a/Source/LexerParser/cmCommandArgumentParser.cxx +++ b/Source/LexerParser/cmCommandArgumentParser.cxx @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30704 +#define YYBISON 30705 /* Bison version string. */ -#define YYBISON_VERSION "3.7.4" +#define YYBISON_VERSION "3.7.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -228,6 +228,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ @@ -325,9 +337,9 @@ typedef int yy_state_fast_t; /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif #if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ @@ -635,7 +647,7 @@ static const yytype_int8 yypgoto[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 11, 12, 13, 14, 15, 19, 20, 21, 22 + 0, 11, 12, 13, 14, 15, 19, 20, 21, 22 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -761,8 +773,8 @@ yy_symbol_value_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { FILE *yyoutput = yyo; - YYUSE (yyoutput); - YYUSE (yyscanner); + YY_USE (yyoutput); + YY_USE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT @@ -770,7 +782,7 @@ yy_symbol_value_print (FILE *yyo, YYPRINT (yyo, yytoknum[yykind], *yyvaluep); # endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1151,14 +1163,14 @@ static void yydestruct (const char *yymsg, yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner) { - YYUSE (yyvaluep); - YYUSE (yyscanner); + YY_USE (yyvaluep); + YY_USE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1433,7 +1445,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetResult((yyvsp[0].str)); } -#line 1437 "cmCommandArgumentParser.cxx" +#line 1449 "cmCommandArgumentParser.cxx" break; case 3: /* GoalWithOptionalBackSlash: Goal */ @@ -1441,7 +1453,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1445 "cmCommandArgumentParser.cxx" +#line 1457 "cmCommandArgumentParser.cxx" break; case 4: /* GoalWithOptionalBackSlash: Goal "\\" */ @@ -1449,7 +1461,7 @@ yyreduce: { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1453 "cmCommandArgumentParser.cxx" +#line 1465 "cmCommandArgumentParser.cxx" break; case 5: /* Goal: %empty */ @@ -1457,7 +1469,7 @@ yyreduce: { (yyval.str) = 0; } -#line 1461 "cmCommandArgumentParser.cxx" +#line 1473 "cmCommandArgumentParser.cxx" break; case 6: /* Goal: String Goal */ @@ -1465,7 +1477,7 @@ yyreduce: { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1469 "cmCommandArgumentParser.cxx" +#line 1481 "cmCommandArgumentParser.cxx" break; case 7: /* String: OuterText */ @@ -1473,7 +1485,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1477 "cmCommandArgumentParser.cxx" +#line 1489 "cmCommandArgumentParser.cxx" break; case 8: /* String: Variable */ @@ -1481,7 +1493,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1485 "cmCommandArgumentParser.cxx" +#line 1497 "cmCommandArgumentParser.cxx" break; case 9: /* OuterText: cal_NAME */ @@ -1489,7 +1501,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1493 "cmCommandArgumentParser.cxx" +#line 1505 "cmCommandArgumentParser.cxx" break; case 10: /* OuterText: "@" */ @@ -1497,7 +1509,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1501 "cmCommandArgumentParser.cxx" +#line 1513 "cmCommandArgumentParser.cxx" break; case 11: /* OuterText: "$" */ @@ -1505,7 +1517,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1509 "cmCommandArgumentParser.cxx" +#line 1521 "cmCommandArgumentParser.cxx" break; case 12: /* OuterText: "{" */ @@ -1513,7 +1525,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1517 "cmCommandArgumentParser.cxx" +#line 1529 "cmCommandArgumentParser.cxx" break; case 13: /* OuterText: "}" */ @@ -1521,7 +1533,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1525 "cmCommandArgumentParser.cxx" +#line 1537 "cmCommandArgumentParser.cxx" break; case 14: /* OuterText: cal_SYMBOL */ @@ -1529,7 +1541,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1533 "cmCommandArgumentParser.cxx" +#line 1545 "cmCommandArgumentParser.cxx" break; case 15: /* Variable: cal_ENVCURLY EnvVarName "}" */ @@ -1537,7 +1549,7 @@ yyreduce: { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1541 "cmCommandArgumentParser.cxx" +#line 1553 "cmCommandArgumentParser.cxx" break; case 16: /* Variable: cal_NCURLY MultipleIds "}" */ @@ -1545,7 +1557,7 @@ yyreduce: { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1549 "cmCommandArgumentParser.cxx" +#line 1561 "cmCommandArgumentParser.cxx" break; case 17: /* Variable: cal_DCURLY MultipleIds "}" */ @@ -1553,7 +1565,7 @@ yyreduce: { (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); } -#line 1557 "cmCommandArgumentParser.cxx" +#line 1569 "cmCommandArgumentParser.cxx" break; case 18: /* Variable: cal_ATNAME */ @@ -1561,7 +1573,7 @@ yyreduce: { (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); } -#line 1565 "cmCommandArgumentParser.cxx" +#line 1577 "cmCommandArgumentParser.cxx" break; case 19: /* EnvVarName: MultipleIds */ @@ -1569,7 +1581,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1573 "cmCommandArgumentParser.cxx" +#line 1585 "cmCommandArgumentParser.cxx" break; case 20: /* EnvVarName: cal_SYMBOL EnvVarName */ @@ -1577,7 +1589,7 @@ yyreduce: { (yyval.str) = (yyvsp[-1].str); } -#line 1581 "cmCommandArgumentParser.cxx" +#line 1593 "cmCommandArgumentParser.cxx" break; case 21: /* MultipleIds: %empty */ @@ -1585,7 +1597,7 @@ yyreduce: { (yyval.str) = 0; } -#line 1589 "cmCommandArgumentParser.cxx" +#line 1601 "cmCommandArgumentParser.cxx" break; case 22: /* MultipleIds: ID MultipleIds */ @@ -1593,7 +1605,7 @@ yyreduce: { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1597 "cmCommandArgumentParser.cxx" +#line 1609 "cmCommandArgumentParser.cxx" break; case 23: /* ID: cal_NAME */ @@ -1601,7 +1613,7 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1605 "cmCommandArgumentParser.cxx" +#line 1617 "cmCommandArgumentParser.cxx" break; case 24: /* ID: Variable */ @@ -1609,11 +1621,11 @@ yyreduce: { (yyval.str) = (yyvsp[0].str); } -#line 1613 "cmCommandArgumentParser.cxx" +#line 1625 "cmCommandArgumentParser.cxx" break; -#line 1617 "cmCommandArgumentParser.cxx" +#line 1629 "cmCommandArgumentParser.cxx" default: break; } diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h index 578f793..414c6dd 100644 --- a/Source/LexerParser/cmCommandArgumentParserTokens.h +++ b/Source/LexerParser/cmCommandArgumentParserTokens.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx index 27cc177..e6b3a7e 100644 --- a/Source/LexerParser/cmDependsJavaParser.cxx +++ b/Source/LexerParser/cmDependsJavaParser.cxx @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30704 +#define YYBISON 30705 /* Bison version string. */ -#define YYBISON_VERSION "3.7.4" +#define YYBISON_VERSION "3.7.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -456,6 +456,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ @@ -553,9 +565,9 @@ typedef int yy_state_fast_t; /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif #if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ @@ -1108,7 +1120,7 @@ static const yytype_int16 yypgoto[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 2, 156, 157, 158, 229, 112, 113, 75, 78, + 0, 2, 156, 157, 158, 229, 112, 113, 75, 78, 230, 231, 19, 20, 21, 22, 3, 4, 24, 30, 5, 31, 32, 33, 51, 52, 53, 54, 163, 164, 65, 66, 79, 67, 80, 96, 97, 98, 208, 209, @@ -1803,8 +1815,8 @@ yy_symbol_value_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { FILE *yyoutput = yyo; - YYUSE (yyoutput); - YYUSE (yyscanner); + YY_USE (yyoutput); + YY_USE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT @@ -1812,7 +1824,7 @@ yy_symbol_value_print (FILE *yyo, YYPRINT (yyo, yytoknum[yykind], *yyvaluep); # endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -2193,14 +2205,14 @@ static void yydestruct (const char *yymsg, yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner) { - YYUSE (yyvaluep); - YYUSE (yyscanner); + YY_USE (yyvaluep); + YY_USE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -2477,7 +2489,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2481 "cmDependsJavaParser.cxx" +#line 2493 "cmDependsJavaParser.cxx" break; case 3: /* Literal: IntegerLiteral */ @@ -2488,7 +2500,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2492 "cmDependsJavaParser.cxx" +#line 2504 "cmDependsJavaParser.cxx" break; case 4: /* Literal: jp_FLOATINGPOINTLITERAL */ @@ -2499,7 +2511,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2503 "cmDependsJavaParser.cxx" +#line 2515 "cmDependsJavaParser.cxx" break; case 5: /* Literal: jp_BOOLEANLITERAL */ @@ -2510,7 +2522,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2514 "cmDependsJavaParser.cxx" +#line 2526 "cmDependsJavaParser.cxx" break; case 6: /* Literal: jp_CHARACTERLITERAL */ @@ -2521,7 +2533,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2525 "cmDependsJavaParser.cxx" +#line 2537 "cmDependsJavaParser.cxx" break; case 7: /* Literal: jp_STRINGLITERAL */ @@ -2532,7 +2544,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2536 "cmDependsJavaParser.cxx" +#line 2548 "cmDependsJavaParser.cxx" break; case 8: /* Literal: jp_NULLLITERAL */ @@ -2543,7 +2555,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2547 "cmDependsJavaParser.cxx" +#line 2559 "cmDependsJavaParser.cxx" break; case 9: /* IntegerLiteral: jp_DECIMALINTEGERLITERAL */ @@ -2554,7 +2566,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2558 "cmDependsJavaParser.cxx" +#line 2570 "cmDependsJavaParser.cxx" break; case 10: /* IntegerLiteral: jp_HEXINTEGERLITERAL */ @@ -2565,7 +2577,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2569 "cmDependsJavaParser.cxx" +#line 2581 "cmDependsJavaParser.cxx" break; case 11: /* Type: PrimitiveType */ @@ -2576,7 +2588,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2580 "cmDependsJavaParser.cxx" +#line 2592 "cmDependsJavaParser.cxx" break; case 12: /* Type: ReferenceType */ @@ -2587,7 +2599,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2591 "cmDependsJavaParser.cxx" +#line 2603 "cmDependsJavaParser.cxx" break; case 13: /* PrimitiveType: jp_BYTE_TYPE */ @@ -2595,7 +2607,7 @@ yyreduce: { jpElementStart(0); } -#line 2599 "cmDependsJavaParser.cxx" +#line 2611 "cmDependsJavaParser.cxx" break; case 14: /* PrimitiveType: jp_SHORT_TYPE */ @@ -2603,7 +2615,7 @@ yyreduce: { jpElementStart(0); } -#line 2607 "cmDependsJavaParser.cxx" +#line 2619 "cmDependsJavaParser.cxx" break; case 15: /* PrimitiveType: jp_INT_TYPE */ @@ -2611,7 +2623,7 @@ yyreduce: { jpElementStart(0); } -#line 2615 "cmDependsJavaParser.cxx" +#line 2627 "cmDependsJavaParser.cxx" break; case 16: /* PrimitiveType: jp_LONG_TYPE */ @@ -2619,7 +2631,7 @@ yyreduce: { jpElementStart(0); } -#line 2623 "cmDependsJavaParser.cxx" +#line 2635 "cmDependsJavaParser.cxx" break; case 17: /* PrimitiveType: jp_CHAR_TYPE */ @@ -2627,7 +2639,7 @@ yyreduce: { jpElementStart(0); } -#line 2631 "cmDependsJavaParser.cxx" +#line 2643 "cmDependsJavaParser.cxx" break; case 18: /* PrimitiveType: jp_FLOAT_TYPE */ @@ -2635,7 +2647,7 @@ yyreduce: { jpElementStart(0); } -#line 2639 "cmDependsJavaParser.cxx" +#line 2651 "cmDependsJavaParser.cxx" break; case 19: /* PrimitiveType: jp_DOUBLE_TYPE */ @@ -2643,7 +2655,7 @@ yyreduce: { jpElementStart(0); } -#line 2647 "cmDependsJavaParser.cxx" +#line 2659 "cmDependsJavaParser.cxx" break; case 20: /* PrimitiveType: jp_BOOLEAN_TYPE */ @@ -2651,7 +2663,7 @@ yyreduce: { jpElementStart(0); } -#line 2655 "cmDependsJavaParser.cxx" +#line 2667 "cmDependsJavaParser.cxx" break; case 21: /* ReferenceType: ClassOrInterfaceType */ @@ -2662,7 +2674,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2666 "cmDependsJavaParser.cxx" +#line 2678 "cmDependsJavaParser.cxx" break; case 22: /* ReferenceType: ArrayType */ @@ -2673,7 +2685,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2677 "cmDependsJavaParser.cxx" +#line 2689 "cmDependsJavaParser.cxx" break; case 23: /* ClassOrInterfaceType: Name */ @@ -2685,7 +2697,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2689 "cmDependsJavaParser.cxx" +#line 2701 "cmDependsJavaParser.cxx" break; case 24: /* ClassType: ClassOrInterfaceType */ @@ -2696,7 +2708,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2700 "cmDependsJavaParser.cxx" +#line 2712 "cmDependsJavaParser.cxx" break; case 25: /* InterfaceType: ClassOrInterfaceType */ @@ -2707,7 +2719,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2711 "cmDependsJavaParser.cxx" +#line 2723 "cmDependsJavaParser.cxx" break; case 26: /* ArrayType: PrimitiveType Dims */ @@ -2718,7 +2730,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2722 "cmDependsJavaParser.cxx" +#line 2734 "cmDependsJavaParser.cxx" break; case 27: /* ArrayType: Name Dims */ @@ -2730,7 +2742,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2734 "cmDependsJavaParser.cxx" +#line 2746 "cmDependsJavaParser.cxx" break; case 28: /* Name: SimpleName */ @@ -2739,7 +2751,7 @@ yyreduce: jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2743 "cmDependsJavaParser.cxx" +#line 2755 "cmDependsJavaParser.cxx" break; case 29: /* Name: QualifiedName */ @@ -2748,7 +2760,7 @@ yyreduce: jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2752 "cmDependsJavaParser.cxx" +#line 2764 "cmDependsJavaParser.cxx" break; case 30: /* SimpleName: Identifier */ @@ -2757,7 +2769,7 @@ yyreduce: jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2761 "cmDependsJavaParser.cxx" +#line 2773 "cmDependsJavaParser.cxx" break; case 31: /* Identifier: jp_NAME */ @@ -2766,7 +2778,7 @@ yyreduce: jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2770 "cmDependsJavaParser.cxx" +#line 2782 "cmDependsJavaParser.cxx" break; case 32: /* Identifier: jp_DOLLAR jp_NAME */ @@ -2775,7 +2787,7 @@ yyreduce: jpElementStart(2); (yyval.str) = (yyvsp[0].str); } -#line 2779 "cmDependsJavaParser.cxx" +#line 2791 "cmDependsJavaParser.cxx" break; case 33: /* QualifiedName: Name jp_DOT Identifier */ @@ -2787,7 +2799,7 @@ yyreduce: yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); (yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine()); } -#line 2791 "cmDependsJavaParser.cxx" +#line 2803 "cmDependsJavaParser.cxx" break; case 34: /* QualifiedName: Name jp_DOT jp_CLASS */ @@ -2800,7 +2812,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2804 "cmDependsJavaParser.cxx" +#line 2816 "cmDependsJavaParser.cxx" break; case 35: /* QualifiedName: Name jp_DOT jp_THIS */ @@ -2813,7 +2825,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2817 "cmDependsJavaParser.cxx" +#line 2829 "cmDependsJavaParser.cxx" break; case 36: /* QualifiedName: SimpleType jp_DOT jp_CLASS */ @@ -2824,7 +2836,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2828 "cmDependsJavaParser.cxx" +#line 2840 "cmDependsJavaParser.cxx" break; case 37: /* SimpleType: PrimitiveType */ @@ -2835,7 +2847,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2839 "cmDependsJavaParser.cxx" +#line 2851 "cmDependsJavaParser.cxx" break; case 38: /* SimpleType: jp_VOID */ @@ -2846,7 +2858,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2850 "cmDependsJavaParser.cxx" +#line 2862 "cmDependsJavaParser.cxx" break; case 39: /* CompilationUnit: PackageDeclarationopt ImportDeclarations TypeDeclarations */ @@ -2857,7 +2869,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2861 "cmDependsJavaParser.cxx" +#line 2873 "cmDependsJavaParser.cxx" break; case 40: /* PackageDeclarationopt: %empty */ @@ -2867,7 +2879,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2871 "cmDependsJavaParser.cxx" +#line 2883 "cmDependsJavaParser.cxx" break; case 41: /* PackageDeclarationopt: PackageDeclaration */ @@ -2878,7 +2890,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2882 "cmDependsJavaParser.cxx" +#line 2894 "cmDependsJavaParser.cxx" break; case 42: /* ImportDeclarations: %empty */ @@ -2888,7 +2900,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2892 "cmDependsJavaParser.cxx" +#line 2904 "cmDependsJavaParser.cxx" break; case 43: /* ImportDeclarations: ImportDeclarations ImportDeclaration */ @@ -2899,7 +2911,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2903 "cmDependsJavaParser.cxx" +#line 2915 "cmDependsJavaParser.cxx" break; case 44: /* TypeDeclarations: %empty */ @@ -2909,7 +2921,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2913 "cmDependsJavaParser.cxx" +#line 2925 "cmDependsJavaParser.cxx" break; case 45: /* TypeDeclarations: TypeDeclarations TypeDeclaration */ @@ -2920,7 +2932,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2924 "cmDependsJavaParser.cxx" +#line 2936 "cmDependsJavaParser.cxx" break; case 46: /* PackageDeclaration: jp_PACKAGE Name jp_SEMICOL */ @@ -2934,7 +2946,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2938 "cmDependsJavaParser.cxx" +#line 2950 "cmDependsJavaParser.cxx" break; case 47: /* ImportDeclaration: SingleTypeImportDeclaration */ @@ -2945,7 +2957,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2949 "cmDependsJavaParser.cxx" +#line 2961 "cmDependsJavaParser.cxx" break; case 48: /* ImportDeclaration: TypeImportOnDemandDeclaration */ @@ -2956,7 +2968,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2960 "cmDependsJavaParser.cxx" +#line 2972 "cmDependsJavaParser.cxx" break; case 49: /* SingleTypeImportDeclaration: jp_IMPORT Name jp_SEMICOL */ @@ -2970,7 +2982,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2974 "cmDependsJavaParser.cxx" +#line 2986 "cmDependsJavaParser.cxx" break; case 50: /* TypeImportOnDemandDeclaration: jp_IMPORT Name jp_DOT jp_TIMES jp_SEMICOL */ @@ -2985,7 +2997,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2989 "cmDependsJavaParser.cxx" +#line 3001 "cmDependsJavaParser.cxx" break; case 51: /* TypeDeclaration: ClassDeclaration */ @@ -2996,7 +3008,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3000 "cmDependsJavaParser.cxx" +#line 3012 "cmDependsJavaParser.cxx" break; case 52: /* TypeDeclaration: InterfaceDeclaration */ @@ -3007,7 +3019,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3011 "cmDependsJavaParser.cxx" +#line 3023 "cmDependsJavaParser.cxx" break; case 53: /* TypeDeclaration: jp_SEMICOL */ @@ -3018,7 +3030,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3022 "cmDependsJavaParser.cxx" +#line 3034 "cmDependsJavaParser.cxx" break; case 54: /* Modifiers: Modifier */ @@ -3029,7 +3041,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3033 "cmDependsJavaParser.cxx" +#line 3045 "cmDependsJavaParser.cxx" break; case 55: /* Modifiers: Modifiers Modifier */ @@ -3040,7 +3052,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3044 "cmDependsJavaParser.cxx" +#line 3056 "cmDependsJavaParser.cxx" break; case 67: /* ClassHeader: Modifiersopt jp_CLASS Identifier */ @@ -3051,7 +3063,7 @@ yyreduce: yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3055 "cmDependsJavaParser.cxx" +#line 3067 "cmDependsJavaParser.cxx" break; case 68: /* ClassDeclaration: ClassHeader ClassBody */ @@ -3063,7 +3075,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3067 "cmDependsJavaParser.cxx" +#line 3079 "cmDependsJavaParser.cxx" break; case 69: /* ClassDeclaration: ClassHeader Interfaces ClassBody */ @@ -3075,7 +3087,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3079 "cmDependsJavaParser.cxx" +#line 3091 "cmDependsJavaParser.cxx" break; case 70: /* ClassDeclaration: ClassHeader Super ClassBody */ @@ -3087,7 +3099,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3091 "cmDependsJavaParser.cxx" +#line 3103 "cmDependsJavaParser.cxx" break; case 71: /* ClassDeclaration: ClassHeader Super Interfaces ClassBody */ @@ -3099,7 +3111,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3103 "cmDependsJavaParser.cxx" +#line 3115 "cmDependsJavaParser.cxx" break; case 72: /* Modifiersopt: %empty */ @@ -3109,7 +3121,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3113 "cmDependsJavaParser.cxx" +#line 3125 "cmDependsJavaParser.cxx" break; case 73: /* Modifiersopt: Modifiers */ @@ -3120,7 +3132,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3124 "cmDependsJavaParser.cxx" +#line 3136 "cmDependsJavaParser.cxx" break; case 74: /* Super: jp_EXTENDS ClassType */ @@ -3131,7 +3143,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3135 "cmDependsJavaParser.cxx" +#line 3147 "cmDependsJavaParser.cxx" break; case 75: /* Interfaces: jp_IMPLEMENTS InterfaceTypeList */ @@ -3142,7 +3154,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3146 "cmDependsJavaParser.cxx" +#line 3158 "cmDependsJavaParser.cxx" break; case 76: /* InterfaceTypeList: InterfaceType */ @@ -3153,7 +3165,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3157 "cmDependsJavaParser.cxx" +#line 3169 "cmDependsJavaParser.cxx" break; case 77: /* InterfaceTypeList: InterfaceTypeList jp_COMMA InterfaceType */ @@ -3164,7 +3176,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3168 "cmDependsJavaParser.cxx" +#line 3180 "cmDependsJavaParser.cxx" break; case 78: /* ClassBody: jp_CURLYSTART ClassBodyDeclarations jp_CURLYEND */ @@ -3175,7 +3187,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3179 "cmDependsJavaParser.cxx" +#line 3191 "cmDependsJavaParser.cxx" break; case 79: /* ClassBodyDeclarations: %empty */ @@ -3185,7 +3197,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3189 "cmDependsJavaParser.cxx" +#line 3201 "cmDependsJavaParser.cxx" break; case 80: /* ClassBodyDeclarations: ClassBodyDeclarations ClassBodyDeclaration */ @@ -3196,7 +3208,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3200 "cmDependsJavaParser.cxx" +#line 3212 "cmDependsJavaParser.cxx" break; case 81: /* ClassBodyDeclaration: ClassMemberDeclaration */ @@ -3207,7 +3219,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3211 "cmDependsJavaParser.cxx" +#line 3223 "cmDependsJavaParser.cxx" break; case 82: /* ClassBodyDeclaration: StaticInitializer */ @@ -3218,7 +3230,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3222 "cmDependsJavaParser.cxx" +#line 3234 "cmDependsJavaParser.cxx" break; case 83: /* ClassBodyDeclaration: ConstructorDeclaration */ @@ -3229,7 +3241,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3233 "cmDependsJavaParser.cxx" +#line 3245 "cmDependsJavaParser.cxx" break; case 84: /* ClassBodyDeclaration: TypeDeclaration */ @@ -3240,7 +3252,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3244 "cmDependsJavaParser.cxx" +#line 3256 "cmDependsJavaParser.cxx" break; case 85: /* ClassMemberDeclaration: FieldDeclaration */ @@ -3251,7 +3263,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3255 "cmDependsJavaParser.cxx" +#line 3267 "cmDependsJavaParser.cxx" break; case 86: /* ClassMemberDeclaration: MethodDeclaration */ @@ -3262,7 +3274,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3266 "cmDependsJavaParser.cxx" +#line 3278 "cmDependsJavaParser.cxx" break; case 87: /* FieldDeclaration: Modifiersopt Type VariableDeclarators jp_SEMICOL */ @@ -3270,7 +3282,7 @@ yyreduce: { jpElementStart(4); } -#line 3274 "cmDependsJavaParser.cxx" +#line 3286 "cmDependsJavaParser.cxx" break; case 88: /* VariableDeclarators: VariableDeclarator */ @@ -3281,7 +3293,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3285 "cmDependsJavaParser.cxx" +#line 3297 "cmDependsJavaParser.cxx" break; case 89: /* VariableDeclarators: VariableDeclarators jp_COMMA VariableDeclarator */ @@ -3292,7 +3304,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3296 "cmDependsJavaParser.cxx" +#line 3308 "cmDependsJavaParser.cxx" break; case 90: /* VariableDeclarator: VariableDeclaratorId */ @@ -3303,7 +3315,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3307 "cmDependsJavaParser.cxx" +#line 3319 "cmDependsJavaParser.cxx" break; case 91: /* VariableDeclarator: VariableDeclaratorId jp_EQUALS VariableInitializer */ @@ -3314,7 +3326,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3318 "cmDependsJavaParser.cxx" +#line 3330 "cmDependsJavaParser.cxx" break; case 92: /* VariableDeclaratorId: Identifier */ @@ -3326,7 +3338,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3330 "cmDependsJavaParser.cxx" +#line 3342 "cmDependsJavaParser.cxx" break; case 93: /* VariableDeclaratorId: VariableDeclaratorId jp_BRACKETSTART jp_BRACKETEND */ @@ -3337,7 +3349,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3341 "cmDependsJavaParser.cxx" +#line 3353 "cmDependsJavaParser.cxx" break; case 94: /* VariableInitializer: Expression */ @@ -3348,7 +3360,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3352 "cmDependsJavaParser.cxx" +#line 3364 "cmDependsJavaParser.cxx" break; case 95: /* VariableInitializer: ArrayInitializer */ @@ -3359,7 +3371,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3363 "cmDependsJavaParser.cxx" +#line 3375 "cmDependsJavaParser.cxx" break; case 96: /* MethodDeclaration: MethodHeader jp_SEMICOL */ @@ -3370,7 +3382,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3374 "cmDependsJavaParser.cxx" +#line 3386 "cmDependsJavaParser.cxx" break; case 97: /* MethodDeclaration: MethodHeader MethodBody */ @@ -3381,7 +3393,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3385 "cmDependsJavaParser.cxx" +#line 3397 "cmDependsJavaParser.cxx" break; case 98: /* MethodDeclaration: MethodHeader MethodBody jp_SEMICOL */ @@ -3392,7 +3404,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3396 "cmDependsJavaParser.cxx" +#line 3408 "cmDependsJavaParser.cxx" break; case 99: /* MethodHeader: Modifiersopt Type MethodDeclarator Throwsopt */ @@ -3404,7 +3416,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3408 "cmDependsJavaParser.cxx" +#line 3420 "cmDependsJavaParser.cxx" break; case 100: /* MethodHeader: Modifiersopt jp_VOID MethodDeclarator Throwsopt */ @@ -3416,7 +3428,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3420 "cmDependsJavaParser.cxx" +#line 3432 "cmDependsJavaParser.cxx" break; case 101: /* Throwsopt: %empty */ @@ -3427,7 +3439,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3431 "cmDependsJavaParser.cxx" +#line 3443 "cmDependsJavaParser.cxx" break; case 102: /* Throwsopt: Throws */ @@ -3439,7 +3451,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3443 "cmDependsJavaParser.cxx" +#line 3455 "cmDependsJavaParser.cxx" break; case 103: /* MethodDeclarator: Identifier jp_PARESTART FormalParameterListopt jp_PAREEND */ @@ -3452,7 +3464,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3456 "cmDependsJavaParser.cxx" +#line 3468 "cmDependsJavaParser.cxx" break; case 104: /* MethodDeclarator: MethodDeclarator jp_BRACKETSTART jp_BRACKETEND */ @@ -3461,7 +3473,7 @@ yyreduce: jpElementStart(3); } -#line 3465 "cmDependsJavaParser.cxx" +#line 3477 "cmDependsJavaParser.cxx" break; case 105: /* FormalParameterListopt: %empty */ @@ -3472,7 +3484,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3476 "cmDependsJavaParser.cxx" +#line 3488 "cmDependsJavaParser.cxx" break; case 107: /* FormalParameterList: FormalParameter */ @@ -3481,7 +3493,7 @@ yyreduce: jpElementStart(1); } -#line 3485 "cmDependsJavaParser.cxx" +#line 3497 "cmDependsJavaParser.cxx" break; case 108: /* FormalParameterList: FormalParameterList jp_COMMA FormalParameter */ @@ -3493,7 +3505,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3497 "cmDependsJavaParser.cxx" +#line 3509 "cmDependsJavaParser.cxx" break; case 109: /* FormalParameter: Modifiersopt Type VariableDeclaratorId */ @@ -3505,7 +3517,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3509 "cmDependsJavaParser.cxx" +#line 3521 "cmDependsJavaParser.cxx" break; case 110: /* Throws: jp_THROWS ClassTypeList */ @@ -3517,7 +3529,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3521 "cmDependsJavaParser.cxx" +#line 3533 "cmDependsJavaParser.cxx" break; case 111: /* ClassTypeList: ClassType */ @@ -3526,7 +3538,7 @@ yyreduce: jpElementStart(1); } -#line 3530 "cmDependsJavaParser.cxx" +#line 3542 "cmDependsJavaParser.cxx" break; case 112: /* ClassTypeList: ClassTypeList jp_COMMA ClassType */ @@ -3538,7 +3550,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3542 "cmDependsJavaParser.cxx" +#line 3554 "cmDependsJavaParser.cxx" break; case 113: /* MethodBody: Block */ @@ -3550,7 +3562,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3554 "cmDependsJavaParser.cxx" +#line 3566 "cmDependsJavaParser.cxx" break; case 114: /* StaticInitializer: jp_STATIC Block */ @@ -3562,7 +3574,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3566 "cmDependsJavaParser.cxx" +#line 3578 "cmDependsJavaParser.cxx" break; case 115: /* ConstructorDeclaration: Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody */ @@ -3574,7 +3586,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3578 "cmDependsJavaParser.cxx" +#line 3590 "cmDependsJavaParser.cxx" break; case 116: /* ConstructorDeclaration: Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody jp_SEMICOL */ @@ -3586,7 +3598,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3590 "cmDependsJavaParser.cxx" +#line 3602 "cmDependsJavaParser.cxx" break; case 117: /* ConstructorDeclarator: SimpleName jp_PARESTART FormalParameterListopt jp_PAREEND */ @@ -3599,7 +3611,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3603 "cmDependsJavaParser.cxx" +#line 3615 "cmDependsJavaParser.cxx" break; case 118: /* ConstructorBody: jp_CURLYSTART ExplicitConstructorInvocationopt BlockStatementsopt jp_CURLYEND */ @@ -3611,7 +3623,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3615 "cmDependsJavaParser.cxx" +#line 3627 "cmDependsJavaParser.cxx" break; case 119: /* ExplicitConstructorInvocationopt: %empty */ @@ -3622,7 +3634,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3626 "cmDependsJavaParser.cxx" +#line 3638 "cmDependsJavaParser.cxx" break; case 120: /* ExplicitConstructorInvocationopt: ExplicitConstructorInvocationopt ExplicitConstructorInvocation */ @@ -3634,7 +3646,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3638 "cmDependsJavaParser.cxx" +#line 3650 "cmDependsJavaParser.cxx" break; case 121: /* ExplicitConstructorInvocation: jp_THIS jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL */ @@ -3646,7 +3658,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3650 "cmDependsJavaParser.cxx" +#line 3662 "cmDependsJavaParser.cxx" break; case 122: /* ExplicitConstructorInvocation: jp_SUPER jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL */ @@ -3658,7 +3670,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3662 "cmDependsJavaParser.cxx" +#line 3674 "cmDependsJavaParser.cxx" break; case 123: /* InterfaceHeader: Modifiersopt jp_INTERFACE Identifier */ @@ -3669,7 +3681,7 @@ yyreduce: yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3673 "cmDependsJavaParser.cxx" +#line 3685 "cmDependsJavaParser.cxx" break; case 124: /* InterfaceDeclaration: InterfaceHeader ExtendsInterfacesopt InterfaceBody */ @@ -3681,7 +3693,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3685 "cmDependsJavaParser.cxx" +#line 3697 "cmDependsJavaParser.cxx" break; case 125: /* ExtendsInterfacesopt: %empty */ @@ -3691,7 +3703,7 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3695 "cmDependsJavaParser.cxx" +#line 3707 "cmDependsJavaParser.cxx" break; case 126: /* ExtendsInterfacesopt: ExtendsInterfaces */ @@ -3703,7 +3715,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3707 "cmDependsJavaParser.cxx" +#line 3719 "cmDependsJavaParser.cxx" break; case 127: /* ExtendsInterfaces: jp_EXTENDS InterfaceType */ @@ -3715,7 +3727,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3719 "cmDependsJavaParser.cxx" +#line 3731 "cmDependsJavaParser.cxx" break; case 128: /* ExtendsInterfaces: ExtendsInterfaces jp_COMMA InterfaceType */ @@ -3727,7 +3739,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3731 "cmDependsJavaParser.cxx" +#line 3743 "cmDependsJavaParser.cxx" break; case 129: /* InterfaceBody: jp_CURLYSTART InterfaceMemberDeclarations jp_CURLYEND */ @@ -3739,7 +3751,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3743 "cmDependsJavaParser.cxx" +#line 3755 "cmDependsJavaParser.cxx" break; case 130: /* InterfaceMemberDeclarations: %empty */ @@ -3750,7 +3762,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3754 "cmDependsJavaParser.cxx" +#line 3766 "cmDependsJavaParser.cxx" break; case 131: /* InterfaceMemberDeclarations: InterfaceMemberDeclarations InterfaceMemberDeclaration */ @@ -3761,7 +3773,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3765 "cmDependsJavaParser.cxx" +#line 3777 "cmDependsJavaParser.cxx" break; case 132: /* InterfaceMemberDeclaration: ConstantDeclaration */ @@ -3773,7 +3785,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3777 "cmDependsJavaParser.cxx" +#line 3789 "cmDependsJavaParser.cxx" break; case 133: /* InterfaceMemberDeclaration: AbstractMethodDeclaration */ @@ -3785,7 +3797,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3789 "cmDependsJavaParser.cxx" +#line 3801 "cmDependsJavaParser.cxx" break; case 134: /* InterfaceMemberDeclaration: ClassDeclaration */ @@ -3797,7 +3809,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3801 "cmDependsJavaParser.cxx" +#line 3813 "cmDependsJavaParser.cxx" break; case 135: /* InterfaceMemberDeclaration: ClassDeclaration jp_SEMICOL */ @@ -3808,7 +3820,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3812 "cmDependsJavaParser.cxx" +#line 3824 "cmDependsJavaParser.cxx" break; case 136: /* InterfaceMemberDeclaration: InterfaceDeclaration */ @@ -3820,7 +3832,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3824 "cmDependsJavaParser.cxx" +#line 3836 "cmDependsJavaParser.cxx" break; case 137: /* InterfaceMemberDeclaration: InterfaceDeclaration jp_SEMICOL */ @@ -3831,7 +3843,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3835 "cmDependsJavaParser.cxx" +#line 3847 "cmDependsJavaParser.cxx" break; case 138: /* ConstantDeclaration: FieldDeclaration */ @@ -3843,7 +3855,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3847 "cmDependsJavaParser.cxx" +#line 3859 "cmDependsJavaParser.cxx" break; case 139: /* AbstractMethodDeclaration: MethodHeader Semicols */ @@ -3855,7 +3867,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3859 "cmDependsJavaParser.cxx" +#line 3871 "cmDependsJavaParser.cxx" break; case 140: /* Semicols: jp_SEMICOL */ @@ -3867,7 +3879,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3871 "cmDependsJavaParser.cxx" +#line 3883 "cmDependsJavaParser.cxx" break; case 141: /* Semicols: Semicols jp_SEMICOL */ @@ -3879,7 +3891,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3883 "cmDependsJavaParser.cxx" +#line 3895 "cmDependsJavaParser.cxx" break; case 142: /* ArrayInitializer: jp_CURLYSTART VariableInitializersOptional jp_CURLYEND */ @@ -3891,7 +3903,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3895 "cmDependsJavaParser.cxx" +#line 3907 "cmDependsJavaParser.cxx" break; case 143: /* VariableInitializersOptional: %empty */ @@ -3902,7 +3914,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3906 "cmDependsJavaParser.cxx" +#line 3918 "cmDependsJavaParser.cxx" break; case 144: /* VariableInitializersOptional: VariableInitializers */ @@ -3914,7 +3926,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3918 "cmDependsJavaParser.cxx" +#line 3930 "cmDependsJavaParser.cxx" break; case 145: /* VariableInitializersOptional: VariableInitializers jp_COMMA */ @@ -3926,7 +3938,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3930 "cmDependsJavaParser.cxx" +#line 3942 "cmDependsJavaParser.cxx" break; case 146: /* VariableInitializers: VariableInitializer */ @@ -3938,7 +3950,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3942 "cmDependsJavaParser.cxx" +#line 3954 "cmDependsJavaParser.cxx" break; case 147: /* VariableInitializers: VariableInitializers jp_COMMA VariableInitializer */ @@ -3950,7 +3962,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3954 "cmDependsJavaParser.cxx" +#line 3966 "cmDependsJavaParser.cxx" break; case 148: /* Block: jp_CURLYSTART BlockStatementsopt jp_CURLYEND */ @@ -3961,7 +3973,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3965 "cmDependsJavaParser.cxx" +#line 3977 "cmDependsJavaParser.cxx" break; case 149: /* BlockStatementsopt: %empty */ @@ -3972,7 +3984,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3976 "cmDependsJavaParser.cxx" +#line 3988 "cmDependsJavaParser.cxx" break; case 150: /* BlockStatementsopt: BlockStatements */ @@ -3984,7 +3996,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3988 "cmDependsJavaParser.cxx" +#line 4000 "cmDependsJavaParser.cxx" break; case 151: /* BlockStatements: BlockStatement */ @@ -3996,7 +4008,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4000 "cmDependsJavaParser.cxx" +#line 4012 "cmDependsJavaParser.cxx" break; case 152: /* BlockStatements: BlockStatements BlockStatement */ @@ -4008,7 +4020,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4012 "cmDependsJavaParser.cxx" +#line 4024 "cmDependsJavaParser.cxx" break; case 153: /* BlockStatement: LocalVariableDeclarationStatement */ @@ -4020,7 +4032,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4024 "cmDependsJavaParser.cxx" +#line 4036 "cmDependsJavaParser.cxx" break; case 154: /* BlockStatement: Statement */ @@ -4032,7 +4044,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4036 "cmDependsJavaParser.cxx" +#line 4048 "cmDependsJavaParser.cxx" break; case 155: /* BlockStatement: ClassDeclaration */ @@ -4044,7 +4056,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4048 "cmDependsJavaParser.cxx" +#line 4060 "cmDependsJavaParser.cxx" break; case 156: /* LocalVariableDeclarationStatement: LocalVariableDeclaration jp_SEMICOL */ @@ -4056,7 +4068,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4060 "cmDependsJavaParser.cxx" +#line 4072 "cmDependsJavaParser.cxx" break; case 157: /* LocalVariableDeclaration: Modifiers Type VariableDeclarators */ @@ -4068,7 +4080,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4072 "cmDependsJavaParser.cxx" +#line 4084 "cmDependsJavaParser.cxx" break; case 158: /* LocalVariableDeclaration: Type VariableDeclarators */ @@ -4080,7 +4092,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4084 "cmDependsJavaParser.cxx" +#line 4096 "cmDependsJavaParser.cxx" break; case 159: /* Statement: StatementWithoutTrailingSubstatement */ @@ -4092,7 +4104,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4096 "cmDependsJavaParser.cxx" +#line 4108 "cmDependsJavaParser.cxx" break; case 160: /* Statement: LabeledStatement */ @@ -4104,7 +4116,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4108 "cmDependsJavaParser.cxx" +#line 4120 "cmDependsJavaParser.cxx" break; case 161: /* Statement: IfThenStatement */ @@ -4116,7 +4128,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4120 "cmDependsJavaParser.cxx" +#line 4132 "cmDependsJavaParser.cxx" break; case 162: /* Statement: IfThenElseStatement */ @@ -4128,7 +4140,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4132 "cmDependsJavaParser.cxx" +#line 4144 "cmDependsJavaParser.cxx" break; case 163: /* Statement: WhileStatement */ @@ -4140,7 +4152,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4144 "cmDependsJavaParser.cxx" +#line 4156 "cmDependsJavaParser.cxx" break; case 164: /* Statement: ForStatement */ @@ -4152,7 +4164,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4156 "cmDependsJavaParser.cxx" +#line 4168 "cmDependsJavaParser.cxx" break; case 165: /* StatementNoShortIf: StatementWithoutTrailingSubstatement */ @@ -4164,7 +4176,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4168 "cmDependsJavaParser.cxx" +#line 4180 "cmDependsJavaParser.cxx" break; case 166: /* StatementNoShortIf: LabeledStatementNoShortIf */ @@ -4176,7 +4188,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4180 "cmDependsJavaParser.cxx" +#line 4192 "cmDependsJavaParser.cxx" break; case 167: /* StatementNoShortIf: IfThenElseStatementNoShortIf */ @@ -4188,7 +4200,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4192 "cmDependsJavaParser.cxx" +#line 4204 "cmDependsJavaParser.cxx" break; case 168: /* StatementNoShortIf: WhileStatementNoShortIf */ @@ -4200,7 +4212,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4204 "cmDependsJavaParser.cxx" +#line 4216 "cmDependsJavaParser.cxx" break; case 169: /* StatementNoShortIf: ForStatementNoShortIf */ @@ -4212,7 +4224,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4216 "cmDependsJavaParser.cxx" +#line 4228 "cmDependsJavaParser.cxx" break; case 170: /* StatementWithoutTrailingSubstatement: Block */ @@ -4224,7 +4236,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4228 "cmDependsJavaParser.cxx" +#line 4240 "cmDependsJavaParser.cxx" break; case 171: /* StatementWithoutTrailingSubstatement: EmptyStatement */ @@ -4236,7 +4248,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4240 "cmDependsJavaParser.cxx" +#line 4252 "cmDependsJavaParser.cxx" break; case 172: /* StatementWithoutTrailingSubstatement: ExpressionStatement */ @@ -4248,7 +4260,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4252 "cmDependsJavaParser.cxx" +#line 4264 "cmDependsJavaParser.cxx" break; case 173: /* StatementWithoutTrailingSubstatement: SwitchStatement */ @@ -4260,7 +4272,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4264 "cmDependsJavaParser.cxx" +#line 4276 "cmDependsJavaParser.cxx" break; case 174: /* StatementWithoutTrailingSubstatement: DoStatement */ @@ -4272,7 +4284,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4276 "cmDependsJavaParser.cxx" +#line 4288 "cmDependsJavaParser.cxx" break; case 175: /* StatementWithoutTrailingSubstatement: BreakStatement */ @@ -4284,7 +4296,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4288 "cmDependsJavaParser.cxx" +#line 4300 "cmDependsJavaParser.cxx" break; case 176: /* StatementWithoutTrailingSubstatement: ContinueStatement */ @@ -4296,7 +4308,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4300 "cmDependsJavaParser.cxx" +#line 4312 "cmDependsJavaParser.cxx" break; case 177: /* StatementWithoutTrailingSubstatement: ReturnStatement */ @@ -4308,7 +4320,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4312 "cmDependsJavaParser.cxx" +#line 4324 "cmDependsJavaParser.cxx" break; case 178: /* StatementWithoutTrailingSubstatement: SynchronizedStatement */ @@ -4320,7 +4332,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4324 "cmDependsJavaParser.cxx" +#line 4336 "cmDependsJavaParser.cxx" break; case 179: /* StatementWithoutTrailingSubstatement: ThrowStatement */ @@ -4332,7 +4344,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4336 "cmDependsJavaParser.cxx" +#line 4348 "cmDependsJavaParser.cxx" break; case 180: /* StatementWithoutTrailingSubstatement: TryStatement */ @@ -4344,7 +4356,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4348 "cmDependsJavaParser.cxx" +#line 4360 "cmDependsJavaParser.cxx" break; case 181: /* StatementWithoutTrailingSubstatement: AssertStatement */ @@ -4356,7 +4368,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4360 "cmDependsJavaParser.cxx" +#line 4372 "cmDependsJavaParser.cxx" break; case 182: /* EmptyStatement: jp_SEMICOL */ @@ -4368,7 +4380,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4372 "cmDependsJavaParser.cxx" +#line 4384 "cmDependsJavaParser.cxx" break; case 183: /* LabeledStatement: Identifier jp_COLON Statement */ @@ -4381,7 +4393,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4385 "cmDependsJavaParser.cxx" +#line 4397 "cmDependsJavaParser.cxx" break; case 184: /* LabeledStatementNoShortIf: Identifier jp_COLON StatementNoShortIf */ @@ -4393,7 +4405,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4397 "cmDependsJavaParser.cxx" +#line 4409 "cmDependsJavaParser.cxx" break; case 185: /* ExpressionStatement: StatementExpression jp_SEMICOL */ @@ -4405,7 +4417,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4409 "cmDependsJavaParser.cxx" +#line 4421 "cmDependsJavaParser.cxx" break; case 186: /* StatementExpression: Assignment */ @@ -4417,7 +4429,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4421 "cmDependsJavaParser.cxx" +#line 4433 "cmDependsJavaParser.cxx" break; case 187: /* StatementExpression: PreIncrementExpression */ @@ -4429,7 +4441,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4433 "cmDependsJavaParser.cxx" +#line 4445 "cmDependsJavaParser.cxx" break; case 188: /* StatementExpression: PreDecrementExpression */ @@ -4441,7 +4453,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4445 "cmDependsJavaParser.cxx" +#line 4457 "cmDependsJavaParser.cxx" break; case 189: /* StatementExpression: PostIncrementExpression */ @@ -4453,7 +4465,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4457 "cmDependsJavaParser.cxx" +#line 4469 "cmDependsJavaParser.cxx" break; case 190: /* StatementExpression: PostDecrementExpression */ @@ -4465,7 +4477,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4469 "cmDependsJavaParser.cxx" +#line 4481 "cmDependsJavaParser.cxx" break; case 191: /* StatementExpression: MethodInvocation */ @@ -4477,7 +4489,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4481 "cmDependsJavaParser.cxx" +#line 4493 "cmDependsJavaParser.cxx" break; case 192: /* StatementExpression: ClassInstanceCreationExpression */ @@ -4489,7 +4501,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4493 "cmDependsJavaParser.cxx" +#line 4505 "cmDependsJavaParser.cxx" break; case 193: /* IfThenStatement: jp_IF jp_PARESTART Expression jp_PAREEND Statement */ @@ -4501,7 +4513,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4505 "cmDependsJavaParser.cxx" +#line 4517 "cmDependsJavaParser.cxx" break; case 194: /* IfThenElseStatement: jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE Statement */ @@ -4513,7 +4525,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4517 "cmDependsJavaParser.cxx" +#line 4529 "cmDependsJavaParser.cxx" break; case 195: /* IfThenElseStatementNoShortIf: jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE StatementNoShortIf */ @@ -4525,7 +4537,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4529 "cmDependsJavaParser.cxx" +#line 4541 "cmDependsJavaParser.cxx" break; case 196: /* SwitchStatement: jp_SWITCH jp_PARESTART Expression jp_PAREEND SwitchBlock */ @@ -4534,7 +4546,7 @@ yyreduce: jpElementStart(5); } -#line 4538 "cmDependsJavaParser.cxx" +#line 4550 "cmDependsJavaParser.cxx" break; case 197: /* SwitchBlock: jp_CURLYSTART SwitchBlockStatementGroups SwitchLabelsopt jp_CURLYEND */ @@ -4543,7 +4555,7 @@ yyreduce: jpElementStart(4); } -#line 4547 "cmDependsJavaParser.cxx" +#line 4559 "cmDependsJavaParser.cxx" break; case 198: /* SwitchLabelsopt: %empty */ @@ -4554,7 +4566,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4558 "cmDependsJavaParser.cxx" +#line 4570 "cmDependsJavaParser.cxx" break; case 199: /* SwitchLabelsopt: SwitchLabels */ @@ -4566,7 +4578,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4570 "cmDependsJavaParser.cxx" +#line 4582 "cmDependsJavaParser.cxx" break; case 200: /* SwitchBlockStatementGroups: %empty */ @@ -4577,7 +4589,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4581 "cmDependsJavaParser.cxx" +#line 4593 "cmDependsJavaParser.cxx" break; case 201: /* SwitchBlockStatementGroups: SwitchBlockStatementGroups SwitchBlockStatementGroup */ @@ -4589,7 +4601,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4593 "cmDependsJavaParser.cxx" +#line 4605 "cmDependsJavaParser.cxx" break; case 202: /* SwitchBlockStatementGroup: SwitchLabels BlockStatements */ @@ -4601,7 +4613,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4605 "cmDependsJavaParser.cxx" +#line 4617 "cmDependsJavaParser.cxx" break; case 203: /* SwitchLabels: SwitchLabel */ @@ -4613,7 +4625,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4617 "cmDependsJavaParser.cxx" +#line 4629 "cmDependsJavaParser.cxx" break; case 204: /* SwitchLabels: SwitchLabels SwitchLabel */ @@ -4625,7 +4637,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4629 "cmDependsJavaParser.cxx" +#line 4641 "cmDependsJavaParser.cxx" break; case 205: /* SwitchLabel: jp_CASE ConstantExpression jp_COLON */ @@ -4637,7 +4649,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4641 "cmDependsJavaParser.cxx" +#line 4653 "cmDependsJavaParser.cxx" break; case 206: /* SwitchLabel: jp_DEFAULT jp_COLON */ @@ -4649,7 +4661,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4653 "cmDependsJavaParser.cxx" +#line 4665 "cmDependsJavaParser.cxx" break; case 207: /* WhileStatement: jp_WHILE jp_PARESTART Expression jp_PAREEND Statement */ @@ -4658,7 +4670,7 @@ yyreduce: jpElementStart(5); } -#line 4662 "cmDependsJavaParser.cxx" +#line 4674 "cmDependsJavaParser.cxx" break; case 208: /* WhileStatementNoShortIf: jp_WHILE jp_PARESTART Expression jp_PAREEND StatementNoShortIf */ @@ -4667,7 +4679,7 @@ yyreduce: jpElementStart(5); } -#line 4671 "cmDependsJavaParser.cxx" +#line 4683 "cmDependsJavaParser.cxx" break; case 209: /* DoStatement: jp_DO Statement jp_WHILE jp_PARESTART Expression jp_PAREEND jp_SEMICOL */ @@ -4676,7 +4688,7 @@ yyreduce: jpElementStart(7); } -#line 4680 "cmDependsJavaParser.cxx" +#line 4692 "cmDependsJavaParser.cxx" break; case 210: /* ForStatement: jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND Statement */ @@ -4685,7 +4697,7 @@ yyreduce: jpElementStart(9); } -#line 4689 "cmDependsJavaParser.cxx" +#line 4701 "cmDependsJavaParser.cxx" break; case 211: /* ForUpdateopt: %empty */ @@ -4696,7 +4708,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4700 "cmDependsJavaParser.cxx" +#line 4712 "cmDependsJavaParser.cxx" break; case 212: /* ForUpdateopt: ForUpdate */ @@ -4708,7 +4720,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4712 "cmDependsJavaParser.cxx" +#line 4724 "cmDependsJavaParser.cxx" break; case 213: /* ForInitopt: %empty */ @@ -4719,7 +4731,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4723 "cmDependsJavaParser.cxx" +#line 4735 "cmDependsJavaParser.cxx" break; case 214: /* ForInitopt: ForInit */ @@ -4731,7 +4743,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4735 "cmDependsJavaParser.cxx" +#line 4747 "cmDependsJavaParser.cxx" break; case 215: /* ForStatementNoShortIf: jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND StatementNoShortIf */ @@ -4742,7 +4754,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4746 "cmDependsJavaParser.cxx" +#line 4758 "cmDependsJavaParser.cxx" break; case 216: /* Expressionopt: %empty */ @@ -4753,7 +4765,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4757 "cmDependsJavaParser.cxx" +#line 4769 "cmDependsJavaParser.cxx" break; case 217: /* Expressionopt: Expression */ @@ -4765,7 +4777,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4769 "cmDependsJavaParser.cxx" +#line 4781 "cmDependsJavaParser.cxx" break; case 218: /* ForInit: StatementExpressionList */ @@ -4777,7 +4789,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4781 "cmDependsJavaParser.cxx" +#line 4793 "cmDependsJavaParser.cxx" break; case 219: /* ForInit: LocalVariableDeclaration */ @@ -4789,7 +4801,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4793 "cmDependsJavaParser.cxx" +#line 4805 "cmDependsJavaParser.cxx" break; case 220: /* ForUpdate: StatementExpressionList */ @@ -4801,7 +4813,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4805 "cmDependsJavaParser.cxx" +#line 4817 "cmDependsJavaParser.cxx" break; case 221: /* StatementExpressionList: StatementExpression */ @@ -4813,7 +4825,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4817 "cmDependsJavaParser.cxx" +#line 4829 "cmDependsJavaParser.cxx" break; case 222: /* StatementExpressionList: StatementExpressionList jp_COMMA StatementExpression */ @@ -4825,7 +4837,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4829 "cmDependsJavaParser.cxx" +#line 4841 "cmDependsJavaParser.cxx" break; case 223: /* AssertStatement: jp_ASSERT Expression jp_SEMICOL */ @@ -4837,7 +4849,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4841 "cmDependsJavaParser.cxx" +#line 4853 "cmDependsJavaParser.cxx" break; case 224: /* AssertStatement: jp_ASSERT Expression jp_COLON Expression jp_SEMICOL */ @@ -4849,7 +4861,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4853 "cmDependsJavaParser.cxx" +#line 4865 "cmDependsJavaParser.cxx" break; case 225: /* BreakStatement: jp_BREAK Identifieropt jp_SEMICOL */ @@ -4862,7 +4874,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4866 "cmDependsJavaParser.cxx" +#line 4878 "cmDependsJavaParser.cxx" break; case 226: /* Identifieropt: %empty */ @@ -4873,7 +4885,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4877 "cmDependsJavaParser.cxx" +#line 4889 "cmDependsJavaParser.cxx" break; case 227: /* Identifieropt: Identifier */ @@ -4882,7 +4894,7 @@ yyreduce: jpElementStart(1); } -#line 4886 "cmDependsJavaParser.cxx" +#line 4898 "cmDependsJavaParser.cxx" break; case 228: /* ContinueStatement: jp_CONTINUE Identifieropt jp_SEMICOL */ @@ -4895,7 +4907,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4899 "cmDependsJavaParser.cxx" +#line 4911 "cmDependsJavaParser.cxx" break; case 229: /* ReturnStatement: jp_RETURN Expressionopt jp_SEMICOL */ @@ -4907,7 +4919,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4911 "cmDependsJavaParser.cxx" +#line 4923 "cmDependsJavaParser.cxx" break; case 230: /* ThrowStatement: jp_THROW Expression jp_SEMICOL */ @@ -4919,7 +4931,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4923 "cmDependsJavaParser.cxx" +#line 4935 "cmDependsJavaParser.cxx" break; case 231: /* SynchronizedStatement: jp_SYNCHRONIZED jp_PARESTART Expression jp_PAREEND Block */ @@ -4931,7 +4943,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4935 "cmDependsJavaParser.cxx" +#line 4947 "cmDependsJavaParser.cxx" break; case 232: /* TryStatement: jp_TRY Block Catches */ @@ -4943,7 +4955,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4947 "cmDependsJavaParser.cxx" +#line 4959 "cmDependsJavaParser.cxx" break; case 233: /* TryStatement: jp_TRY Block Catchesopt Finally */ @@ -4955,7 +4967,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4959 "cmDependsJavaParser.cxx" +#line 4971 "cmDependsJavaParser.cxx" break; case 234: /* Catchesopt: %empty */ @@ -4966,7 +4978,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4970 "cmDependsJavaParser.cxx" +#line 4982 "cmDependsJavaParser.cxx" break; case 235: /* Catchesopt: Catches */ @@ -4978,7 +4990,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4982 "cmDependsJavaParser.cxx" +#line 4994 "cmDependsJavaParser.cxx" break; case 236: /* Catches: CatchClause */ @@ -4990,7 +5002,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4994 "cmDependsJavaParser.cxx" +#line 5006 "cmDependsJavaParser.cxx" break; case 237: /* Catches: Catches CatchClause */ @@ -5002,7 +5014,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5006 "cmDependsJavaParser.cxx" +#line 5018 "cmDependsJavaParser.cxx" break; case 238: /* CatchClause: jp_CATCH jp_PARESTART FormalParameter jp_PAREEND Block */ @@ -5011,7 +5023,7 @@ yyreduce: jpElementStart(5); } -#line 5015 "cmDependsJavaParser.cxx" +#line 5027 "cmDependsJavaParser.cxx" break; case 239: /* Finally: jp_FINALLY Block */ @@ -5023,7 +5035,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5027 "cmDependsJavaParser.cxx" +#line 5039 "cmDependsJavaParser.cxx" break; case 240: /* Primary: PrimaryNoNewArray */ @@ -5035,7 +5047,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5039 "cmDependsJavaParser.cxx" +#line 5051 "cmDependsJavaParser.cxx" break; case 241: /* Primary: ArrayCreationExpression */ @@ -5047,7 +5059,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5051 "cmDependsJavaParser.cxx" +#line 5063 "cmDependsJavaParser.cxx" break; case 242: /* PrimaryNoNewArray: Literal */ @@ -5059,7 +5071,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5063 "cmDependsJavaParser.cxx" +#line 5075 "cmDependsJavaParser.cxx" break; case 243: /* PrimaryNoNewArray: jp_THIS */ @@ -5068,7 +5080,7 @@ yyreduce: jpElementStart(1); } -#line 5072 "cmDependsJavaParser.cxx" +#line 5084 "cmDependsJavaParser.cxx" break; case 244: /* PrimaryNoNewArray: jp_PARESTART Expression jp_PAREEND */ @@ -5080,7 +5092,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5084 "cmDependsJavaParser.cxx" +#line 5096 "cmDependsJavaParser.cxx" break; case 245: /* PrimaryNoNewArray: ClassInstanceCreationExpression */ @@ -5092,7 +5104,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5096 "cmDependsJavaParser.cxx" +#line 5108 "cmDependsJavaParser.cxx" break; case 246: /* PrimaryNoNewArray: FieldAccess */ @@ -5104,7 +5116,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5108 "cmDependsJavaParser.cxx" +#line 5120 "cmDependsJavaParser.cxx" break; case 247: /* PrimaryNoNewArray: MethodInvocation */ @@ -5116,7 +5128,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5120 "cmDependsJavaParser.cxx" +#line 5132 "cmDependsJavaParser.cxx" break; case 248: /* PrimaryNoNewArray: ArrayAccess */ @@ -5128,7 +5140,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5132 "cmDependsJavaParser.cxx" +#line 5144 "cmDependsJavaParser.cxx" break; case 249: /* ClassInstanceCreationExpression: New ClassType jp_PARESTART ArgumentListopt jp_PAREEND ClassBodyOpt */ @@ -5140,7 +5152,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5144 "cmDependsJavaParser.cxx" +#line 5156 "cmDependsJavaParser.cxx" break; case 250: /* ClassBodyOpt: %empty */ @@ -5151,7 +5163,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5155 "cmDependsJavaParser.cxx" +#line 5167 "cmDependsJavaParser.cxx" break; case 251: /* ClassBodyOpt: ClassBody */ @@ -5163,7 +5175,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5167 "cmDependsJavaParser.cxx" +#line 5179 "cmDependsJavaParser.cxx" break; case 252: /* ArgumentListopt: %empty */ @@ -5174,7 +5186,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5178 "cmDependsJavaParser.cxx" +#line 5190 "cmDependsJavaParser.cxx" break; case 253: /* ArgumentListopt: ArgumentList */ @@ -5186,7 +5198,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5190 "cmDependsJavaParser.cxx" +#line 5202 "cmDependsJavaParser.cxx" break; case 254: /* ArgumentList: Expression */ @@ -5198,7 +5210,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5202 "cmDependsJavaParser.cxx" +#line 5214 "cmDependsJavaParser.cxx" break; case 255: /* ArgumentList: ArgumentList jp_COMMA Expression */ @@ -5210,7 +5222,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5214 "cmDependsJavaParser.cxx" +#line 5226 "cmDependsJavaParser.cxx" break; case 256: /* ArrayCreationExpression: New PrimitiveType DimExprs Dimsopt */ @@ -5222,7 +5234,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5226 "cmDependsJavaParser.cxx" +#line 5238 "cmDependsJavaParser.cxx" break; case 257: /* ArrayCreationExpression: New ClassOrInterfaceType DimExprs Dimsopt */ @@ -5234,7 +5246,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5238 "cmDependsJavaParser.cxx" +#line 5250 "cmDependsJavaParser.cxx" break; case 258: /* ArrayCreationExpression: New PrimitiveType Dims ArrayInitializer */ @@ -5246,7 +5258,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5250 "cmDependsJavaParser.cxx" +#line 5262 "cmDependsJavaParser.cxx" break; case 259: /* ArrayCreationExpression: New ClassOrInterfaceType Dims ArrayInitializer */ @@ -5258,7 +5270,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5262 "cmDependsJavaParser.cxx" +#line 5274 "cmDependsJavaParser.cxx" break; case 260: /* Dimsopt: %empty */ @@ -5269,7 +5281,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5273 "cmDependsJavaParser.cxx" +#line 5285 "cmDependsJavaParser.cxx" break; case 261: /* Dimsopt: Dims */ @@ -5281,7 +5293,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5285 "cmDependsJavaParser.cxx" +#line 5297 "cmDependsJavaParser.cxx" break; case 262: /* DimExprs: DimExpr */ @@ -5293,7 +5305,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5297 "cmDependsJavaParser.cxx" +#line 5309 "cmDependsJavaParser.cxx" break; case 263: /* DimExprs: DimExprs DimExpr */ @@ -5305,7 +5317,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5309 "cmDependsJavaParser.cxx" +#line 5321 "cmDependsJavaParser.cxx" break; case 264: /* DimExpr: jp_BRACKETSTART Expression jp_BRACKETEND */ @@ -5317,7 +5329,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5321 "cmDependsJavaParser.cxx" +#line 5333 "cmDependsJavaParser.cxx" break; case 265: /* Dims: jp_BRACKETSTART jp_BRACKETEND */ @@ -5326,7 +5338,7 @@ yyreduce: jpElementStart(2); } -#line 5330 "cmDependsJavaParser.cxx" +#line 5342 "cmDependsJavaParser.cxx" break; case 266: /* Dims: Dims jp_BRACKETSTART jp_BRACKETEND */ @@ -5335,7 +5347,7 @@ yyreduce: jpElementStart(3); } -#line 5339 "cmDependsJavaParser.cxx" +#line 5351 "cmDependsJavaParser.cxx" break; case 267: /* FieldAccess: Primary jp_DOT Identifier */ @@ -5348,7 +5360,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5352 "cmDependsJavaParser.cxx" +#line 5364 "cmDependsJavaParser.cxx" break; case 268: /* FieldAccess: jp_SUPER jp_DOT Identifier */ @@ -5361,7 +5373,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5365 "cmDependsJavaParser.cxx" +#line 5377 "cmDependsJavaParser.cxx" break; case 269: /* FieldAccess: jp_THIS jp_DOT Identifier */ @@ -5374,7 +5386,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5378 "cmDependsJavaParser.cxx" +#line 5390 "cmDependsJavaParser.cxx" break; case 270: /* FieldAccess: Primary jp_DOT jp_THIS */ @@ -5387,7 +5399,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5391 "cmDependsJavaParser.cxx" +#line 5403 "cmDependsJavaParser.cxx" break; case 271: /* MethodInvocation: Name jp_PARESTART ArgumentListopt jp_PAREEND */ @@ -5400,7 +5412,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5404 "cmDependsJavaParser.cxx" +#line 5416 "cmDependsJavaParser.cxx" break; case 272: /* MethodInvocation: Primary jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */ @@ -5414,7 +5426,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5418 "cmDependsJavaParser.cxx" +#line 5430 "cmDependsJavaParser.cxx" break; case 273: /* MethodInvocation: jp_SUPER jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */ @@ -5427,7 +5439,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5431 "cmDependsJavaParser.cxx" +#line 5443 "cmDependsJavaParser.cxx" break; case 274: /* MethodInvocation: jp_THIS jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */ @@ -5440,7 +5452,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5444 "cmDependsJavaParser.cxx" +#line 5456 "cmDependsJavaParser.cxx" break; case 275: /* ArrayAccess: Name jp_BRACKETSTART Expression jp_BRACKETEND */ @@ -5453,7 +5465,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5457 "cmDependsJavaParser.cxx" +#line 5469 "cmDependsJavaParser.cxx" break; case 276: /* ArrayAccess: PrimaryNoNewArray jp_BRACKETSTART Expression jp_BRACKETEND */ @@ -5465,7 +5477,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5469 "cmDependsJavaParser.cxx" +#line 5481 "cmDependsJavaParser.cxx" break; case 277: /* PostfixExpression: Primary */ @@ -5477,7 +5489,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5481 "cmDependsJavaParser.cxx" +#line 5493 "cmDependsJavaParser.cxx" break; case 278: /* PostfixExpression: Name */ @@ -5489,7 +5501,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5493 "cmDependsJavaParser.cxx" +#line 5505 "cmDependsJavaParser.cxx" break; case 279: /* PostfixExpression: ArrayType jp_DOT jp_CLASS */ @@ -5501,7 +5513,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5505 "cmDependsJavaParser.cxx" +#line 5517 "cmDependsJavaParser.cxx" break; case 280: /* PostfixExpression: PostIncrementExpression */ @@ -5513,7 +5525,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5517 "cmDependsJavaParser.cxx" +#line 5529 "cmDependsJavaParser.cxx" break; case 281: /* PostfixExpression: PostDecrementExpression */ @@ -5525,7 +5537,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5529 "cmDependsJavaParser.cxx" +#line 5541 "cmDependsJavaParser.cxx" break; case 282: /* PostIncrementExpression: PostfixExpression jp_PLUSPLUS */ @@ -5537,7 +5549,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5541 "cmDependsJavaParser.cxx" +#line 5553 "cmDependsJavaParser.cxx" break; case 283: /* PostDecrementExpression: PostfixExpression jp_MINUSMINUS */ @@ -5549,7 +5561,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5553 "cmDependsJavaParser.cxx" +#line 5565 "cmDependsJavaParser.cxx" break; case 284: /* UnaryExpression: PreIncrementExpression */ @@ -5561,7 +5573,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5565 "cmDependsJavaParser.cxx" +#line 5577 "cmDependsJavaParser.cxx" break; case 285: /* UnaryExpression: PreDecrementExpression */ @@ -5573,7 +5585,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5577 "cmDependsJavaParser.cxx" +#line 5589 "cmDependsJavaParser.cxx" break; case 286: /* UnaryExpression: jp_PLUS UnaryExpression */ @@ -5585,7 +5597,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5589 "cmDependsJavaParser.cxx" +#line 5601 "cmDependsJavaParser.cxx" break; case 287: /* UnaryExpression: jp_MINUS UnaryExpression */ @@ -5597,7 +5609,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5601 "cmDependsJavaParser.cxx" +#line 5613 "cmDependsJavaParser.cxx" break; case 288: /* UnaryExpression: UnaryExpressionNotPlusMinus */ @@ -5609,7 +5621,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5613 "cmDependsJavaParser.cxx" +#line 5625 "cmDependsJavaParser.cxx" break; case 289: /* PreIncrementExpression: jp_PLUSPLUS UnaryExpression */ @@ -5621,7 +5633,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5625 "cmDependsJavaParser.cxx" +#line 5637 "cmDependsJavaParser.cxx" break; case 290: /* PreDecrementExpression: jp_MINUSMINUS UnaryExpression */ @@ -5633,7 +5645,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5637 "cmDependsJavaParser.cxx" +#line 5649 "cmDependsJavaParser.cxx" break; case 291: /* UnaryExpressionNotPlusMinus: PostfixExpression */ @@ -5645,7 +5657,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5649 "cmDependsJavaParser.cxx" +#line 5661 "cmDependsJavaParser.cxx" break; case 292: /* UnaryExpressionNotPlusMinus: jp_TILDE UnaryExpression */ @@ -5657,7 +5669,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5661 "cmDependsJavaParser.cxx" +#line 5673 "cmDependsJavaParser.cxx" break; case 293: /* UnaryExpressionNotPlusMinus: jp_EXCLAMATION UnaryExpression */ @@ -5669,7 +5681,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5673 "cmDependsJavaParser.cxx" +#line 5685 "cmDependsJavaParser.cxx" break; case 294: /* UnaryExpressionNotPlusMinus: CastExpression */ @@ -5681,7 +5693,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5685 "cmDependsJavaParser.cxx" +#line 5697 "cmDependsJavaParser.cxx" break; case 295: /* CastExpression: jp_PARESTART PrimitiveType Dimsopt jp_PAREEND UnaryExpression */ @@ -5693,7 +5705,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5697 "cmDependsJavaParser.cxx" +#line 5709 "cmDependsJavaParser.cxx" break; case 296: /* CastExpression: jp_PARESTART Expression jp_PAREEND UnaryExpressionNotPlusMinus */ @@ -5705,7 +5717,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5709 "cmDependsJavaParser.cxx" +#line 5721 "cmDependsJavaParser.cxx" break; case 297: /* CastExpression: jp_PARESTART Name Dims jp_PAREEND UnaryExpressionNotPlusMinus */ @@ -5714,7 +5726,7 @@ yyreduce: jpElementStart(5); } -#line 5718 "cmDependsJavaParser.cxx" +#line 5730 "cmDependsJavaParser.cxx" break; case 298: /* MultiplicativeExpression: UnaryExpression */ @@ -5726,7 +5738,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5730 "cmDependsJavaParser.cxx" +#line 5742 "cmDependsJavaParser.cxx" break; case 299: /* MultiplicativeExpression: MultiplicativeExpression jp_TIMES UnaryExpression */ @@ -5738,7 +5750,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5742 "cmDependsJavaParser.cxx" +#line 5754 "cmDependsJavaParser.cxx" break; case 300: /* MultiplicativeExpression: MultiplicativeExpression jp_DIVIDE UnaryExpression */ @@ -5750,7 +5762,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5754 "cmDependsJavaParser.cxx" +#line 5766 "cmDependsJavaParser.cxx" break; case 301: /* MultiplicativeExpression: MultiplicativeExpression jp_PERCENT UnaryExpression */ @@ -5762,7 +5774,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5766 "cmDependsJavaParser.cxx" +#line 5778 "cmDependsJavaParser.cxx" break; case 302: /* AdditiveExpression: MultiplicativeExpression */ @@ -5774,7 +5786,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5778 "cmDependsJavaParser.cxx" +#line 5790 "cmDependsJavaParser.cxx" break; case 303: /* AdditiveExpression: AdditiveExpression jp_PLUS MultiplicativeExpression */ @@ -5786,7 +5798,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5790 "cmDependsJavaParser.cxx" +#line 5802 "cmDependsJavaParser.cxx" break; case 304: /* AdditiveExpression: AdditiveExpression jp_MINUS MultiplicativeExpression */ @@ -5798,7 +5810,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5802 "cmDependsJavaParser.cxx" +#line 5814 "cmDependsJavaParser.cxx" break; case 305: /* ShiftExpression: AdditiveExpression */ @@ -5810,7 +5822,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5814 "cmDependsJavaParser.cxx" +#line 5826 "cmDependsJavaParser.cxx" break; case 306: /* ShiftExpression: ShiftExpression jp_LTLT AdditiveExpression */ @@ -5822,7 +5834,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5826 "cmDependsJavaParser.cxx" +#line 5838 "cmDependsJavaParser.cxx" break; case 307: /* ShiftExpression: ShiftExpression jp_GTGT AdditiveExpression */ @@ -5834,7 +5846,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5838 "cmDependsJavaParser.cxx" +#line 5850 "cmDependsJavaParser.cxx" break; case 308: /* ShiftExpression: ShiftExpression jp_GTGTGT AdditiveExpression */ @@ -5846,7 +5858,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5850 "cmDependsJavaParser.cxx" +#line 5862 "cmDependsJavaParser.cxx" break; case 309: /* RelationalExpression: ShiftExpression */ @@ -5858,7 +5870,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5862 "cmDependsJavaParser.cxx" +#line 5874 "cmDependsJavaParser.cxx" break; case 310: /* RelationalExpression: RelationalExpression jp_LESSTHAN ShiftExpression */ @@ -5870,7 +5882,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5874 "cmDependsJavaParser.cxx" +#line 5886 "cmDependsJavaParser.cxx" break; case 311: /* RelationalExpression: RelationalExpression jp_GREATER ShiftExpression */ @@ -5882,7 +5894,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5886 "cmDependsJavaParser.cxx" +#line 5898 "cmDependsJavaParser.cxx" break; case 312: /* RelationalExpression: RelationalExpression jp_LTEQUALS ShiftExpression */ @@ -5894,7 +5906,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5898 "cmDependsJavaParser.cxx" +#line 5910 "cmDependsJavaParser.cxx" break; case 313: /* RelationalExpression: RelationalExpression jp_GTEQUALS ShiftExpression */ @@ -5906,7 +5918,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5910 "cmDependsJavaParser.cxx" +#line 5922 "cmDependsJavaParser.cxx" break; case 314: /* RelationalExpression: RelationalExpression jp_INSTANCEOF ReferenceType */ @@ -5918,7 +5930,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5922 "cmDependsJavaParser.cxx" +#line 5934 "cmDependsJavaParser.cxx" break; case 315: /* EqualityExpression: RelationalExpression */ @@ -5930,7 +5942,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5934 "cmDependsJavaParser.cxx" +#line 5946 "cmDependsJavaParser.cxx" break; case 316: /* EqualityExpression: EqualityExpression jp_EQUALSEQUALS RelationalExpression */ @@ -5942,7 +5954,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5946 "cmDependsJavaParser.cxx" +#line 5958 "cmDependsJavaParser.cxx" break; case 317: /* EqualityExpression: EqualityExpression jp_EXCLAMATIONEQUALS RelationalExpression */ @@ -5954,7 +5966,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5958 "cmDependsJavaParser.cxx" +#line 5970 "cmDependsJavaParser.cxx" break; case 318: /* AndExpression: EqualityExpression */ @@ -5966,7 +5978,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5970 "cmDependsJavaParser.cxx" +#line 5982 "cmDependsJavaParser.cxx" break; case 319: /* AndExpression: AndExpression jp_AND EqualityExpression */ @@ -5978,7 +5990,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5982 "cmDependsJavaParser.cxx" +#line 5994 "cmDependsJavaParser.cxx" break; case 320: /* ExclusiveOrExpression: AndExpression */ @@ -5990,7 +6002,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5994 "cmDependsJavaParser.cxx" +#line 6006 "cmDependsJavaParser.cxx" break; case 321: /* ExclusiveOrExpression: ExclusiveOrExpression jp_CARROT AndExpression */ @@ -6002,7 +6014,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6006 "cmDependsJavaParser.cxx" +#line 6018 "cmDependsJavaParser.cxx" break; case 322: /* InclusiveOrExpression: ExclusiveOrExpression */ @@ -6014,7 +6026,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6018 "cmDependsJavaParser.cxx" +#line 6030 "cmDependsJavaParser.cxx" break; case 323: /* InclusiveOrExpression: InclusiveOrExpression jp_PIPE ExclusiveOrExpression */ @@ -6026,7 +6038,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6030 "cmDependsJavaParser.cxx" +#line 6042 "cmDependsJavaParser.cxx" break; case 324: /* ConditionalAndExpression: InclusiveOrExpression */ @@ -6038,7 +6050,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6042 "cmDependsJavaParser.cxx" +#line 6054 "cmDependsJavaParser.cxx" break; case 325: /* ConditionalAndExpression: ConditionalAndExpression jp_ANDAND InclusiveOrExpression */ @@ -6050,7 +6062,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6054 "cmDependsJavaParser.cxx" +#line 6066 "cmDependsJavaParser.cxx" break; case 326: /* ConditionalOrExpression: ConditionalAndExpression */ @@ -6062,7 +6074,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6066 "cmDependsJavaParser.cxx" +#line 6078 "cmDependsJavaParser.cxx" break; case 327: /* ConditionalOrExpression: ConditionalOrExpression jp_PIPEPIPE ConditionalAndExpression */ @@ -6074,7 +6086,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6078 "cmDependsJavaParser.cxx" +#line 6090 "cmDependsJavaParser.cxx" break; case 328: /* ConditionalExpression: ConditionalOrExpression */ @@ -6086,7 +6098,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6090 "cmDependsJavaParser.cxx" +#line 6102 "cmDependsJavaParser.cxx" break; case 329: /* ConditionalExpression: ConditionalOrExpression jp_QUESTION Expression jp_COLON ConditionalExpression */ @@ -6098,7 +6110,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6102 "cmDependsJavaParser.cxx" +#line 6114 "cmDependsJavaParser.cxx" break; case 330: /* AssignmentExpression: ConditionalExpression */ @@ -6110,7 +6122,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6114 "cmDependsJavaParser.cxx" +#line 6126 "cmDependsJavaParser.cxx" break; case 331: /* AssignmentExpression: Assignment */ @@ -6122,7 +6134,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6126 "cmDependsJavaParser.cxx" +#line 6138 "cmDependsJavaParser.cxx" break; case 332: /* Assignment: LeftHandSide AssignmentOperator AssignmentExpression */ @@ -6134,7 +6146,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6138 "cmDependsJavaParser.cxx" +#line 6150 "cmDependsJavaParser.cxx" break; case 333: /* LeftHandSide: Name */ @@ -6147,7 +6159,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6151 "cmDependsJavaParser.cxx" +#line 6163 "cmDependsJavaParser.cxx" break; case 334: /* LeftHandSide: FieldAccess */ @@ -6159,7 +6171,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6163 "cmDependsJavaParser.cxx" +#line 6175 "cmDependsJavaParser.cxx" break; case 335: /* LeftHandSide: ArrayAccess */ @@ -6171,7 +6183,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6175 "cmDependsJavaParser.cxx" +#line 6187 "cmDependsJavaParser.cxx" break; case 336: /* AssignmentOperator: jp_EQUALS */ @@ -6183,7 +6195,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6187 "cmDependsJavaParser.cxx" +#line 6199 "cmDependsJavaParser.cxx" break; case 337: /* AssignmentOperator: jp_TIMESEQUALS */ @@ -6195,7 +6207,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6199 "cmDependsJavaParser.cxx" +#line 6211 "cmDependsJavaParser.cxx" break; case 338: /* AssignmentOperator: jp_DIVIDEEQUALS */ @@ -6207,7 +6219,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6211 "cmDependsJavaParser.cxx" +#line 6223 "cmDependsJavaParser.cxx" break; case 339: /* AssignmentOperator: jp_PERCENTEQUALS */ @@ -6219,7 +6231,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6223 "cmDependsJavaParser.cxx" +#line 6235 "cmDependsJavaParser.cxx" break; case 340: /* AssignmentOperator: jp_PLUSEQUALS */ @@ -6231,7 +6243,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6235 "cmDependsJavaParser.cxx" +#line 6247 "cmDependsJavaParser.cxx" break; case 341: /* AssignmentOperator: jp_MINUSEQUALS */ @@ -6243,7 +6255,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6247 "cmDependsJavaParser.cxx" +#line 6259 "cmDependsJavaParser.cxx" break; case 342: /* AssignmentOperator: jp_LESLESEQUALS */ @@ -6255,7 +6267,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6259 "cmDependsJavaParser.cxx" +#line 6271 "cmDependsJavaParser.cxx" break; case 343: /* AssignmentOperator: jp_GTGTEQUALS */ @@ -6267,7 +6279,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6271 "cmDependsJavaParser.cxx" +#line 6283 "cmDependsJavaParser.cxx" break; case 344: /* AssignmentOperator: jp_GTGTGTEQUALS */ @@ -6279,7 +6291,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6283 "cmDependsJavaParser.cxx" +#line 6295 "cmDependsJavaParser.cxx" break; case 345: /* AssignmentOperator: jp_ANDEQUALS */ @@ -6291,7 +6303,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6295 "cmDependsJavaParser.cxx" +#line 6307 "cmDependsJavaParser.cxx" break; case 346: /* AssignmentOperator: jp_CARROTEQUALS */ @@ -6303,7 +6315,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6307 "cmDependsJavaParser.cxx" +#line 6319 "cmDependsJavaParser.cxx" break; case 347: /* AssignmentOperator: jp_PIPEEQUALS */ @@ -6315,7 +6327,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6319 "cmDependsJavaParser.cxx" +#line 6331 "cmDependsJavaParser.cxx" break; case 348: /* Expression: AssignmentExpression */ @@ -6327,7 +6339,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6331 "cmDependsJavaParser.cxx" +#line 6343 "cmDependsJavaParser.cxx" break; case 349: /* ConstantExpression: Expression */ @@ -6339,7 +6351,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6343 "cmDependsJavaParser.cxx" +#line 6355 "cmDependsJavaParser.cxx" break; case 350: /* New: jp_NEW */ @@ -6351,7 +6363,7 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6355 "cmDependsJavaParser.cxx" +#line 6367 "cmDependsJavaParser.cxx" break; case 351: /* New: Name jp_DOT jp_NEW */ @@ -6364,11 +6376,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6368 "cmDependsJavaParser.cxx" +#line 6380 "cmDependsJavaParser.cxx" break; -#line 6372 "cmDependsJavaParser.cxx" +#line 6384 "cmDependsJavaParser.cxx" default: break; } diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h index 4ae55fa..885cc66 100644 --- a/Source/LexerParser/cmDependsJavaParserTokens.h +++ b/Source/LexerParser/cmDependsJavaParserTokens.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx index b747d8b..d9b0ae3 100644 --- a/Source/LexerParser/cmExprParser.cxx +++ b/Source/LexerParser/cmExprParser.cxx @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30704 +#define YYBISON 30705 /* Bison version string. */ -#define YYBISON_VERSION "3.7.4" +#define YYBISON_VERSION "3.7.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -120,7 +120,11 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # endif #endif -#line 124 "cmExprParser.cxx" +#if defined(__NVCOMPILER) +# pragma diag_suppress 550 /* variable set but never used */ +#endif + +#line 128 "cmExprParser.cxx" # ifndef YY_CAST # ifdef __cplusplus @@ -218,6 +222,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ @@ -315,9 +331,9 @@ typedef int yy_state_fast_t; /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif #if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ @@ -544,9 +560,9 @@ static const yytype_int8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 81, 81, 86, 89, 94, 97, 102, 105, 110, - 113, 116, 121, 124, 127, 132, 135, 138, 144, 149, - 152, 155, 158, 163, 166 + 0, 85, 85, 90, 93, 98, 101, 106, 109, 114, + 117, 120, 125, 128, 131, 136, 139, 142, 148, 153, + 156, 159, 162, 167, 170 }; #endif @@ -629,7 +645,7 @@ static const yytype_int8 yypgoto[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 6, 7, 8, 9, 10, 11, 12, 13, 14 + 0, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -754,8 +770,8 @@ yy_symbol_value_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { FILE *yyoutput = yyo; - YYUSE (yyoutput); - YYUSE (yyscanner); + YY_USE (yyoutput); + YY_USE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT @@ -763,7 +779,7 @@ yy_symbol_value_print (FILE *yyo, YYPRINT (yyo, yytoknum[yykind], *yyvaluep); # endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1144,14 +1160,14 @@ static void yydestruct (const char *yymsg, yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner) { - YYUSE (yyvaluep); - YYUSE (yyscanner); + YY_USE (yyvaluep); + YY_USE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1421,194 +1437,194 @@ yyreduce: switch (yyn) { case 2: /* start: exp */ -#line 81 "cmExprParser.y" +#line 85 "cmExprParser.y" { cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number)); } -#line 1429 "cmExprParser.cxx" +#line 1445 "cmExprParser.cxx" break; case 3: /* exp: bitwiseor */ -#line 86 "cmExprParser.y" +#line 90 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1437 "cmExprParser.cxx" +#line 1453 "cmExprParser.cxx" break; case 4: /* exp: exp exp_OR bitwiseor */ -#line 89 "cmExprParser.y" +#line 93 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number); } -#line 1445 "cmExprParser.cxx" +#line 1461 "cmExprParser.cxx" break; case 5: /* bitwiseor: bitwisexor */ -#line 94 "cmExprParser.y" +#line 98 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1453 "cmExprParser.cxx" +#line 1469 "cmExprParser.cxx" break; case 6: /* bitwiseor: bitwiseor exp_XOR bitwisexor */ -#line 97 "cmExprParser.y" +#line 101 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number); } -#line 1461 "cmExprParser.cxx" +#line 1477 "cmExprParser.cxx" break; case 7: /* bitwisexor: bitwiseand */ -#line 102 "cmExprParser.y" +#line 106 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1469 "cmExprParser.cxx" +#line 1485 "cmExprParser.cxx" break; case 8: /* bitwisexor: bitwisexor exp_AND bitwiseand */ -#line 105 "cmExprParser.y" +#line 109 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number); } -#line 1477 "cmExprParser.cxx" +#line 1493 "cmExprParser.cxx" break; case 9: /* bitwiseand: shift */ -#line 110 "cmExprParser.y" +#line 114 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1485 "cmExprParser.cxx" +#line 1501 "cmExprParser.cxx" break; case 10: /* bitwiseand: bitwiseand exp_SHIFTLEFT shift */ -#line 113 "cmExprParser.y" +#line 117 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number); } -#line 1493 "cmExprParser.cxx" +#line 1509 "cmExprParser.cxx" break; case 11: /* bitwiseand: bitwiseand exp_SHIFTRIGHT shift */ -#line 116 "cmExprParser.y" +#line 120 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number); } -#line 1501 "cmExprParser.cxx" +#line 1517 "cmExprParser.cxx" break; case 12: /* shift: term */ -#line 121 "cmExprParser.y" +#line 125 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1509 "cmExprParser.cxx" +#line 1525 "cmExprParser.cxx" break; case 13: /* shift: shift exp_PLUS term */ -#line 124 "cmExprParser.y" +#line 128 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number); } -#line 1517 "cmExprParser.cxx" +#line 1533 "cmExprParser.cxx" break; case 14: /* shift: shift exp_MINUS term */ -#line 127 "cmExprParser.y" +#line 131 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number); } -#line 1525 "cmExprParser.cxx" +#line 1541 "cmExprParser.cxx" break; case 15: /* term: unary */ -#line 132 "cmExprParser.y" +#line 136 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1533 "cmExprParser.cxx" +#line 1549 "cmExprParser.cxx" break; case 16: /* term: term exp_TIMES unary */ -#line 135 "cmExprParser.y" +#line 139 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number); } -#line 1541 "cmExprParser.cxx" +#line 1557 "cmExprParser.cxx" break; case 17: /* term: term exp_DIVIDE unary */ -#line 138 "cmExprParser.y" +#line 142 "cmExprParser.y" { if (yyvsp[0].Number == 0) { throw std::overflow_error("divide by zero"); } (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number); } -#line 1552 "cmExprParser.cxx" +#line 1568 "cmExprParser.cxx" break; case 18: /* term: term exp_MOD unary */ -#line 144 "cmExprParser.y" +#line 148 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number); } -#line 1560 "cmExprParser.cxx" +#line 1576 "cmExprParser.cxx" break; case 19: /* unary: factor */ -#line 149 "cmExprParser.y" +#line 153 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1568 "cmExprParser.cxx" +#line 1584 "cmExprParser.cxx" break; case 20: /* unary: exp_PLUS unary */ -#line 152 "cmExprParser.y" +#line 156 "cmExprParser.y" { (yyval.Number) = + (yyvsp[0].Number); } -#line 1576 "cmExprParser.cxx" +#line 1592 "cmExprParser.cxx" break; case 21: /* unary: exp_MINUS unary */ -#line 155 "cmExprParser.y" +#line 159 "cmExprParser.y" { (yyval.Number) = - (yyvsp[0].Number); } -#line 1584 "cmExprParser.cxx" +#line 1600 "cmExprParser.cxx" break; case 22: /* unary: exp_NOT unary */ -#line 158 "cmExprParser.y" +#line 162 "cmExprParser.y" { (yyval.Number) = ~ (yyvsp[0].Number); } -#line 1592 "cmExprParser.cxx" +#line 1608 "cmExprParser.cxx" break; case 23: /* factor: exp_NUMBER */ -#line 163 "cmExprParser.y" +#line 167 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1600 "cmExprParser.cxx" +#line 1616 "cmExprParser.cxx" break; case 24: /* factor: exp_OPENPARENT exp exp_CLOSEPARENT */ -#line 166 "cmExprParser.y" +#line 170 "cmExprParser.y" { (yyval.Number) = (yyvsp[-1].Number); } -#line 1608 "cmExprParser.cxx" +#line 1624 "cmExprParser.cxx" break; -#line 1612 "cmExprParser.cxx" +#line 1628 "cmExprParser.cxx" default: break; } @@ -1833,7 +1849,7 @@ yyreturn: return yyresult; } -#line 171 "cmExprParser.y" +#line 175 "cmExprParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y index b49f482..fda2395 100644 --- a/Source/LexerParser/cmExprParser.y +++ b/Source/LexerParser/cmExprParser.y @@ -44,6 +44,10 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma clang diagnostic ignored "-Wused-but-marked-unused" # endif #endif + +#if defined(__NVCOMPILER) +# pragma diag_suppress 550 /* variable set but never used */ +#endif %} /* Generate a reentrant parser object. */ diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h index 2eb1fe9..67b03de 100644 --- a/Source/LexerParser/cmExprParserTokens.h +++ b/Source/LexerParser/cmExprParserTokens.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index dba2cac..0ea3d97 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30704 +#define YYBISON 30705 /* Bison version string. */ -#define YYBISON_VERSION "3.7.4" +#define YYBISON_VERSION "3.7.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -259,6 +259,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ @@ -356,9 +368,9 @@ typedef int yy_state_fast_t; /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif #if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ @@ -701,7 +713,7 @@ static const yytype_int8 yypgoto[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 1, 32, 33, 34, 35, 36, 37, 38, 39, + 0, 1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 44, 82 }; @@ -955,8 +967,8 @@ yy_symbol_value_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { FILE *yyoutput = yyo; - YYUSE (yyoutput); - YYUSE (yyscanner); + YY_USE (yyoutput); + YY_USE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT @@ -964,7 +976,7 @@ yy_symbol_value_print (FILE *yyo, YYPRINT (yyo, yytoknum[yykind], *yyvaluep); # endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1345,14 +1357,14 @@ static void yydestruct (const char *yymsg, yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner) { - YYUSE (yyvaluep); - YYUSE (yyscanner); + YY_USE (yyvaluep); + YY_USE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1627,7 +1639,7 @@ yyreduce: cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1631 "cmFortranParser.cxx" +#line 1643 "cmFortranParser.cxx" break; case 5: /* stmt: USE WORD other EOSTMT */ @@ -1637,7 +1649,7 @@ yyreduce: cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1641 "cmFortranParser.cxx" +#line 1653 "cmFortranParser.cxx" break; case 6: /* stmt: MODULE WORD other EOSTMT */ @@ -1651,7 +1663,7 @@ yyreduce: } free((yyvsp[-2].string)); } -#line 1655 "cmFortranParser.cxx" +#line 1667 "cmFortranParser.cxx" break; case 7: /* stmt: SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT */ @@ -1662,7 +1674,7 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1666 "cmFortranParser.cxx" +#line 1678 "cmFortranParser.cxx" break; case 8: /* stmt: SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT */ @@ -1674,7 +1686,7 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1678 "cmFortranParser.cxx" +#line 1690 "cmFortranParser.cxx" break; case 9: /* stmt: INTERFACE WORD other EOSTMT */ @@ -1684,7 +1696,7 @@ yyreduce: cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1688 "cmFortranParser.cxx" +#line 1700 "cmFortranParser.cxx" break; case 10: /* stmt: END INTERFACE other EOSTMT */ @@ -1693,7 +1705,7 @@ yyreduce: cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1697 "cmFortranParser.cxx" +#line 1709 "cmFortranParser.cxx" break; case 11: /* stmt: USE DCOLON WORD other EOSTMT */ @@ -1703,7 +1715,7 @@ yyreduce: cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1707 "cmFortranParser.cxx" +#line 1719 "cmFortranParser.cxx" break; case 12: /* stmt: USE COMMA WORD DCOLON WORD other EOSTMT */ @@ -1716,7 +1728,7 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1720 "cmFortranParser.cxx" +#line 1732 "cmFortranParser.cxx" break; case 13: /* stmt: INCLUDE STRING other EOSTMT */ @@ -1726,7 +1738,7 @@ yyreduce: cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1730 "cmFortranParser.cxx" +#line 1742 "cmFortranParser.cxx" break; case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */ @@ -1736,7 +1748,7 @@ yyreduce: cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1740 "cmFortranParser.cxx" +#line 1752 "cmFortranParser.cxx" break; case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */ @@ -1746,7 +1758,7 @@ yyreduce: cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1750 "cmFortranParser.cxx" +#line 1762 "cmFortranParser.cxx" break; case 16: /* stmt: include STRING other EOSTMT */ @@ -1756,7 +1768,7 @@ yyreduce: cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1760 "cmFortranParser.cxx" +#line 1772 "cmFortranParser.cxx" break; case 17: /* stmt: define WORD other EOSTMT */ @@ -1766,7 +1778,7 @@ yyreduce: cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1770 "cmFortranParser.cxx" +#line 1782 "cmFortranParser.cxx" break; case 18: /* stmt: undef WORD other EOSTMT */ @@ -1776,7 +1788,7 @@ yyreduce: cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1780 "cmFortranParser.cxx" +#line 1792 "cmFortranParser.cxx" break; case 19: /* stmt: ifdef WORD other EOSTMT */ @@ -1786,7 +1798,7 @@ yyreduce: cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1790 "cmFortranParser.cxx" +#line 1802 "cmFortranParser.cxx" break; case 20: /* stmt: ifndef WORD other EOSTMT */ @@ -1796,7 +1808,7 @@ yyreduce: cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1800 "cmFortranParser.cxx" +#line 1812 "cmFortranParser.cxx" break; case 21: /* stmt: if other EOSTMT */ @@ -1805,7 +1817,7 @@ yyreduce: cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1809 "cmFortranParser.cxx" +#line 1821 "cmFortranParser.cxx" break; case 22: /* stmt: elif other EOSTMT */ @@ -1814,7 +1826,7 @@ yyreduce: cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1818 "cmFortranParser.cxx" +#line 1830 "cmFortranParser.cxx" break; case 23: /* stmt: else other EOSTMT */ @@ -1823,7 +1835,7 @@ yyreduce: cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1827 "cmFortranParser.cxx" +#line 1839 "cmFortranParser.cxx" break; case 24: /* stmt: endif other EOSTMT */ @@ -1832,23 +1844,23 @@ yyreduce: cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1836 "cmFortranParser.cxx" +#line 1848 "cmFortranParser.cxx" break; case 48: /* misc_code: WORD */ #line 229 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1842 "cmFortranParser.cxx" +#line 1854 "cmFortranParser.cxx" break; case 55: /* misc_code: STRING */ #line 236 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1848 "cmFortranParser.cxx" +#line 1860 "cmFortranParser.cxx" break; -#line 1852 "cmFortranParser.cxx" +#line 1864 "cmFortranParser.cxx" default: break; } diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h index e250110..3a19cfb 100644 --- a/Source/LexerParser/cmFortranParserTokens.h +++ b/Source/LexerParser/cmFortranParserTokens.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/Source/Modules/FindLibUUID.cmake b/Source/Modules/FindLibUUID.cmake index 17f11c1..ca5b61d 100644 --- a/Source/Modules/FindLibUUID.cmake +++ b/Source/Modules/FindLibUUID.cmake @@ -40,7 +40,14 @@ They may be set by end users to point at LibUUID components. #]=======================================================================] #----------------------------------------------------------------------------- -if(CYGWIN) +if(MSYS) + # Note: on current version of MSYS2, linking to libuuid.dll.a doesn't + # import the right symbols sometimes. Fix this by linking directly + # to the DLL that provides the symbols, instead. + find_library(LibUUID_LIBRARY + NAMES msys-uuid-1.dll + ) +elseif(CYGWIN) # Note: on current version of Cygwin, linking to libuuid.dll.a doesn't # import the right symbols sometimes. Fix this by linking directly # to the DLL that provides the symbols, instead. diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index f593f83..6796e25 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -160,7 +160,7 @@ void QCMake::setPreset(const QString& name, bool setBinary) auto const& expandedPreset = this->CMakePresetsFile.ConfigurePresets[presetName].Expanded; if (expandedPreset) { - if (setBinary) { + if (setBinary && !expandedPreset->BinaryDir.empty()) { QString binaryDir = QString::fromLocal8Bit(expandedPreset->BinaryDir.data()); this->setBinaryDirectory(binaryDir); @@ -557,7 +557,7 @@ void QCMake::loadPresets() preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data())); preset.setToolset = !p.ToolsetStrategy || p.ToolsetStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set; - preset.enabled = it.Expanded && + preset.enabled = it.Expanded && it.Expanded->ConditionResult && std::find_if(this->AvailableGenerators.begin(), this->AvailableGenerators.end(), [&p](const cmake::GeneratorInfo& g) { diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index b685b73..54b2998 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -2,11 +2,16 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmArchiveWrite.h" -#include <cstdio> +#include <cstdlib> #include <cstring> #include <ctime> #include <iostream> +#include <limits> #include <sstream> +#include <string> +#include <thread> + +#include <cm/algorithm> #include <cm3p/archive.h> #include <cm3p/archive_entry.h> @@ -144,16 +149,36 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, cm_archive_error_string(this->Archive)); return; } + { - char sNumThreads[8]; - snprintf(sNumThreads, sizeof(sNumThreads), "%d", numThreads); - sNumThreads[7] = '\0'; // for safety +#if ARCHIVE_VERSION_NUMBER >= 3004000 + // Upstream fixed an issue with their integer parsing in 3.4.0 + // which would cause spurious errors to be raised from `strtoull`. + + if (numThreads < 1) { + int upperLimit = (numThreads == 0) ? std::numeric_limits<int>::max() + : std::abs(numThreads); + + numThreads = + cm::clamp<int>(std::thread::hardware_concurrency(), 1, upperLimit); + } + +# ifdef _AIX + // FIXME: Using more than 2 threads creates an empty archive. + // Enforce this limit pending further investigation. + numThreads = std::min(numThreads, 2); +# endif + + std::string sNumThreads = std::to_string(numThreads); + if (archive_write_set_filter_option(this->Archive, "xz", "threads", - sNumThreads) != ARCHIVE_OK) { + sNumThreads.c_str()) != + ARCHIVE_OK) { this->Error = cmStrCat("archive_compressor_xz_options: ", cm_archive_error_string(this->Archive)); return; } +#endif } break; @@ -425,16 +450,3 @@ bool cmArchiveWrite::AddData(const char* file, size_t size) } return true; } - -bool cmArchiveWrite::SetFilterOption(const char* module, const char* key, - const char* value) -{ - if (archive_write_set_filter_option(this->Archive, module, key, value) != - ARCHIVE_OK) { - this->Error = "archive_write_set_filter_option: "; - this->Error += cm_archive_error_string(this->Archive); - return false; - } - - return true; -} diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h index 34aafe9..260bd20 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -141,9 +141,6 @@ public: this->Gname = ""; } - //! Set an option on a filter; - bool SetFilterOption(const char* module, const char* key, const char* value); - private: bool Okay() const { return this->Error.empty(); } bool AddPath(const char* path, size_t skip, const char* prefix, diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index 2eaf315..56b080a 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -28,12 +28,14 @@ bool MainSignature(std::vector<std::string> const& args, std::string configuration; std::string project_name; std::string target; + std::string parallel; enum Doing { DoingNone, DoingConfiguration, DoingProjectName, - DoingTarget + DoingTarget, + DoingParallel }; Doing doing = DoingNone; for (unsigned int i = 1; i < args.size(); ++i) { @@ -43,6 +45,8 @@ bool MainSignature(std::vector<std::string> const& args, doing = DoingProjectName; } else if (args[i] == "TARGET") { doing = DoingTarget; + } else if (args[i] == "PARALLEL_LEVEL") { + doing = DoingParallel; } else if (doing == DoingConfiguration) { doing = DoingNone; configuration = args[i]; @@ -52,6 +56,9 @@ bool MainSignature(std::vector<std::string> const& args, } else if (doing == DoingTarget) { doing = DoingNone; target = args[i]; + } else if (doing == DoingParallel) { + doing = DoingNone; + parallel = args[i]; } else { status.SetError(cmStrCat("unknown argument \"", args[i], "\"")); return false; @@ -77,7 +84,7 @@ bool MainSignature(std::vector<std::string> const& args, } std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand( - target, configuration, "", mf.IgnoreErrorsCMP0061()); + target, configuration, parallel, "", mf.IgnoreErrorsCMP0061()); mf.AddDefinition(variable, makecommand); @@ -104,7 +111,7 @@ bool TwoArgsSignature(std::vector<std::string> const& args, } std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand( - "", configType, "", mf.IgnoreErrorsCMP0061()); + "", configType, "", "", mf.IgnoreErrorsCMP0061()); if (cacheValue) { return true; diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index dda3661..2f9972c 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -9,28 +9,17 @@ #include <iterator> #include <utility> -#include <cmext/string_view> +#include <cm/string_view> -#include <cm3p/json/reader.h> -#include <cm3p/json/value.h> +#include "cmsys/RegularExpression.hxx" -#include "cmsys/FStream.hxx" - -#include "cmJSONHelpers.h" +#include "cmCMakePresetsFileInternal.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#include "cmVersion.h" - -#define CHECK_OK(expr) \ - { \ - auto _result = expr; \ - if (_result != ReadFileResult::READ_OK) \ - return _result; \ - } -#define CHECK_EXPAND(out, field, expanders) \ +#define CHECK_EXPAND(out, field, expanders, version) \ { \ - switch (ExpandMacros(field, expanders)) { \ + switch (ExpandMacros(field, expanders, version)) { \ case ExpandMacroResult::Error: \ return false; \ case ExpandMacroResult::Ignore: \ @@ -50,673 +39,11 @@ enum class CycleStatus }; using ReadFileResult = cmCMakePresetsFile::ReadFileResult; -using CacheVariable = cmCMakePresetsFile::CacheVariable; using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset; using BuildPreset = cmCMakePresetsFile::BuildPreset; using TestPreset = cmCMakePresetsFile::TestPreset; -using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy; - -constexpr int MIN_VERSION = 1; -constexpr int MAX_VERSION = 2; - -struct CMakeVersion -{ - unsigned int Major = 0; - unsigned int Minor = 0; - unsigned int Patch = 0; -}; - -struct RootPresets -{ - CMakeVersion CMakeMinimumRequired; - std::vector<cmCMakePresetsFile::ConfigurePreset> ConfigurePresets; - std::vector<cmCMakePresetsFile::BuildPreset> BuildPresets; - std::vector<cmCMakePresetsFile::TestPreset> TestPresets; -}; - -cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error) -{ - return [error](std::nullptr_t& /*out*/, - const Json::Value* value) -> ReadFileResult { - if (!value) { - return ReadFileResult::READ_OK; - } - - if (!value->isObject()) { - return error; - } - - return ReadFileResult::READ_OK; - }; -} - -auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); - -auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>( - ReadFileResult::NO_VERSION, VersionIntHelper); - -auto const RootVersionHelper = - cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_ROOT) - .Bind("version"_s, VersionHelper, false); - -auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE); - -ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value) -{ - if (!value) { - out.clear(); - return ReadFileResult::READ_OK; - } - - if (value->isBool()) { - out = value->asBool() ? "TRUE" : "FALSE"; - return ReadFileResult::READ_OK; - } - - return VariableStringHelper(out, value); -} - -auto const VariableObjectHelper = - cmJSONObjectHelper<CacheVariable, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false) - .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false) - .Bind("value"_s, &CacheVariable::Value, VariableValueHelper); - -ReadFileResult VariableHelper(cm::optional<CacheVariable>& out, - const Json::Value* value) -{ - if (value->isBool()) { - out = CacheVariable{ - /*Type=*/"BOOL", - /*Value=*/value->asBool() ? "TRUE" : "FALSE", - }; - return ReadFileResult::READ_OK; - } - if (value->isString()) { - out = CacheVariable{ - /*Type=*/"", - /*Value=*/value->asString(), - }; - return ReadFileResult::READ_OK; - } - if (value->isObject()) { - out.emplace(); - return VariableObjectHelper(*out, value); - } - if (value->isNull()) { - out = cm::nullopt; - return ReadFileResult::READ_OK; - } - return ReadFileResult::INVALID_VARIABLE; -} - -auto const VariablesHelper = - cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper); - -auto const PresetStringHelper = cmJSONStringHelper<ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); - -ReadFileResult EnvironmentHelper(cm::optional<std::string>& out, - const Json::Value* value) -{ - if (!value || value->isNull()) { - out = cm::nullopt; - return ReadFileResult::READ_OK; - } - if (value->isString()) { - out = value->asString(); - return ReadFileResult::READ_OK; - } - return ReadFileResult::INVALID_PRESET; -} - -auto const EnvironmentMapHelper = - cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, - EnvironmentHelper); - -auto const PresetVectorStringHelper = - cmJSONVectorHelper<std::string, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, - PresetStringHelper); - -ReadFileResult PresetInheritsHelper(std::vector<std::string>& out, - const Json::Value* value) -{ - out.clear(); - if (!value) { - return ReadFileResult::READ_OK; - } - - if (value->isString()) { - out.push_back(value->asString()); - return ReadFileResult::READ_OK; - } - - return PresetVectorStringHelper(out, value); -} - -auto const PresetBoolHelper = cmJSONBoolHelper<ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); - -auto const PresetOptionalBoolHelper = - cmJSONOptionalHelper<bool, ReadFileResult>(ReadFileResult::READ_OK, - PresetBoolHelper); - -auto const PresetIntHelper = cmJSONIntHelper<ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); - -auto const PresetOptionalIntHelper = cmJSONOptionalHelper<int, ReadFileResult>( - ReadFileResult::READ_OK, PresetIntHelper); - -auto const PresetVectorIntHelper = cmJSONVectorHelper<int, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper); - -auto const PresetWarningsHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("dev"_s, &ConfigurePreset::WarnDev, PresetOptionalBoolHelper, false) - .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated, - PresetOptionalBoolHelper, false) - .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized, - PresetOptionalBoolHelper, false) - .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli, - PresetOptionalBoolHelper, false) - .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars, - PresetOptionalBoolHelper, false); - -auto const PresetErrorsHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("dev"_s, &ConfigurePreset::ErrorDev, PresetOptionalBoolHelper, false) - .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated, - PresetOptionalBoolHelper, false); - -auto const PresetDebugHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("output"_s, &ConfigurePreset::DebugOutput, PresetOptionalBoolHelper, - false) - .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile, - PresetOptionalBoolHelper, false) - .Bind("find"_s, &ConfigurePreset::DebugFind, PresetOptionalBoolHelper, - false); - -ReadFileResult ArchToolsetStrategyHelper( - cm::optional<ArchToolsetStrategy>& out, const Json::Value* value) -{ - if (!value) { - out = cm::nullopt; - return ReadFileResult::READ_OK; - } - - if (!value->isString()) { - return ReadFileResult::INVALID_PRESET; - } - - if (value->asString() == "set") { - out = ArchToolsetStrategy::Set; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "external") { - out = ArchToolsetStrategy::External; - return ReadFileResult::READ_OK; - } - - return ReadFileResult::INVALID_PRESET; -} - -std::function<ReadFileResult(ConfigurePreset&, const Json::Value*)> -ArchToolsetHelper( - std::string ConfigurePreset::*valueField, - cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField) -{ - auto const objectHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("value", valueField, PresetStringHelper, false) - .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false); - return [valueField, strategyField, objectHelper]( - ConfigurePreset& out, const Json::Value* value) -> ReadFileResult { - if (!value) { - (out.*valueField).clear(); - out.*strategyField = cm::nullopt; - return ReadFileResult::READ_OK; - } - - if (value->isString()) { - out.*valueField = value->asString(); - out.*strategyField = cm::nullopt; - return ReadFileResult::READ_OK; - } - - if (value->isObject()) { - return objectHelper(out, value); - } - - return ReadFileResult::INVALID_PRESET; - }; -} - -auto const ArchitectureHelper = ArchToolsetHelper( - &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy); -auto const ToolsetHelper = ArchToolsetHelper( - &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy); - -auto const ConfigurePresetHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper) - .Bind("inherits"_s, &ConfigurePreset::Inherits, PresetInheritsHelper, - false) - .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false) - .Bind<std::nullptr_t>("vendor"_s, nullptr, - VendorHelper(ReadFileResult::INVALID_PRESET), false) - .Bind("displayName"_s, &ConfigurePreset::DisplayName, PresetStringHelper, - false) - .Bind("description"_s, &ConfigurePreset::Description, PresetStringHelper, - false) - .Bind("generator"_s, &ConfigurePreset::Generator, PresetStringHelper, - false) - .Bind("architecture"_s, ArchitectureHelper, false) - .Bind("toolset"_s, ToolsetHelper, false) - .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper, - false) - .Bind<std::string>("cmakeExecutable"_s, nullptr, PresetStringHelper, false) - .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables, - VariablesHelper, false) - .Bind("environment"_s, &ConfigurePreset::Environment, EnvironmentMapHelper, - false) - .Bind("warnings"_s, PresetWarningsHelper, false) - .Bind("errors"_s, PresetErrorsHelper, false) - .Bind("debug"_s, PresetDebugHelper, false); - -auto const BuildPresetHelper = - cmJSONObjectHelper<BuildPreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("name"_s, &BuildPreset::Name, PresetStringHelper) - .Bind("inherits"_s, &BuildPreset::Inherits, PresetInheritsHelper, false) - .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false) - .Bind<std::nullptr_t>("vendor"_s, nullptr, - VendorHelper(ReadFileResult::INVALID_PRESET), false) - .Bind("displayName"_s, &BuildPreset::DisplayName, PresetStringHelper, - false) - .Bind("description"_s, &BuildPreset::Description, PresetStringHelper, - false) - .Bind("environment"_s, &BuildPreset::Environment, EnvironmentMapHelper, - false) - .Bind("configurePreset"_s, &BuildPreset::ConfigurePreset, - PresetStringHelper, false) - .Bind("inheritConfigureEnvironment"_s, - &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper, - false) - .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false) - .Bind("targets"_s, &BuildPreset::Targets, PresetVectorStringHelper, false) - .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper, - false) - .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper, - false) - .Bind("verbose"_s, &BuildPreset::Verbose, PresetOptionalBoolHelper, false) - .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions, - PresetVectorStringHelper, false); - -ReadFileResult TestPresetOutputVerbosityHelper( - TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value) -{ - if (!value) { - out = TestPreset::OutputOptions::VerbosityEnum::Default; - return ReadFileResult::READ_OK; - } - - if (!value->isString()) { - return ReadFileResult::INVALID_PRESET; - } - - if (value->asString() == "default") { - out = TestPreset::OutputOptions::VerbosityEnum::Default; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "verbose") { - out = TestPreset::OutputOptions::VerbosityEnum::Verbose; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "extra") { - out = TestPreset::OutputOptions::VerbosityEnum::Extra; - return ReadFileResult::READ_OK; - } - - return ReadFileResult::INVALID_PRESET; -} - -auto const TestPresetOptionalOutputVerbosityHelper = - cmJSONOptionalHelper<TestPreset::OutputOptions::VerbosityEnum, - ReadFileResult>(ReadFileResult::READ_OK, - TestPresetOutputVerbosityHelper); - -auto const TestPresetOptionalOutputHelper = - cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>( - ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::OutputOptions, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress, - PresetOptionalBoolHelper, false) - .Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity, - TestPresetOptionalOutputVerbosityHelper, false) - .Bind("debug"_s, &TestPreset::OutputOptions::Debug, - PresetOptionalBoolHelper, false) - .Bind("outputOnFailure"_s, &TestPreset::OutputOptions::OutputOnFailure, - PresetOptionalBoolHelper, false) - .Bind("quiet"_s, &TestPreset::OutputOptions::Quiet, - PresetOptionalBoolHelper, false) - .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile, - PresetStringHelper, false) - .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary, - PresetOptionalBoolHelper, false) - .Bind("subprojectSummary"_s, - &TestPreset::OutputOptions::SubprojectSummary, - PresetOptionalBoolHelper, false) - .Bind("maxPassedTestOutputSize"_s, - &TestPreset::OutputOptions::MaxPassedTestOutputSize, - PresetOptionalIntHelper, false) - .Bind("maxFailedTestOutputSize"_s, - &TestPreset::OutputOptions::MaxFailedTestOutputSize, - PresetOptionalIntHelper, false) - .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth, - PresetOptionalIntHelper, false)); - -auto const TestPresetOptionalFilterIncludeIndexObjectHelper = - cmJSONOptionalHelper<TestPreset::IncludeOptions::IndexOptions, - ReadFileResult>( - ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::IncludeOptions::IndexOptions, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) - .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start, - PresetOptionalIntHelper, false) - .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End, - PresetOptionalIntHelper, false) - .Bind("stride"_s, &TestPreset::IncludeOptions::IndexOptions::Stride, - PresetOptionalIntHelper, false) - .Bind("specificTests"_s, - &TestPreset::IncludeOptions::IndexOptions::SpecificTests, - PresetVectorIntHelper, false)); - -ReadFileResult TestPresetOptionalFilterIncludeIndexHelper( - cm::optional<TestPreset::IncludeOptions::IndexOptions>& out, - const Json::Value* value) -{ - if (!value) { - out = cm::nullopt; - return ReadFileResult::READ_OK; - } - - if (value->isString()) { - out.emplace(); - out->IndexFile = value->asString(); - return ReadFileResult::READ_OK; - } - - if (value->isObject()) { - return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value); - } - - return ReadFileResult::INVALID_PRESET; -} - -auto const TestPresetOptionalFilterIncludeHelper = - cmJSONOptionalHelper<TestPreset::IncludeOptions, ReadFileResult>( - ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::IncludeOptions, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) - .Bind("name"_s, &TestPreset::IncludeOptions::Name, PresetStringHelper, - false) - .Bind("label"_s, &TestPreset::IncludeOptions::Label, PresetStringHelper, - false) - .Bind("index"_s, &TestPreset::IncludeOptions::Index, - TestPresetOptionalFilterIncludeIndexHelper, false) - .Bind("useUnion"_s, &TestPreset::IncludeOptions::UseUnion, - PresetOptionalBoolHelper, false)); - -auto const TestPresetOptionalFilterExcludeFixturesHelper = - cmJSONOptionalHelper<TestPreset::ExcludeOptions::FixturesOptions, - ReadFileResult>( - ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExcludeOptions::FixturesOptions, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) - .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any, - PresetStringHelper, false) - .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup, - PresetStringHelper, false) - .Bind("cleanup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Cleanup, - PresetStringHelper, false)); - -auto const TestPresetOptionalFilterExcludeHelper = - cmJSONOptionalHelper<TestPreset::ExcludeOptions, ReadFileResult>( - ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExcludeOptions, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) - .Bind("name"_s, &TestPreset::ExcludeOptions::Name, PresetStringHelper, - false) - .Bind("label"_s, &TestPreset::ExcludeOptions::Label, PresetStringHelper, - false) - .Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures, - TestPresetOptionalFilterExcludeFixturesHelper, false)); - -ReadFileResult TestPresetExecutionShowOnlyHelper( - TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value) -{ - if (!value || !value->isString()) { - return ReadFileResult::INVALID_PRESET; - } - - if (value->asString() == "human") { - out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "json-v1") { - out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1; - return ReadFileResult::READ_OK; - } - - return ReadFileResult::INVALID_PRESET; -} - -auto const TestPresetOptionalExecutionShowOnlyHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions::ShowOnlyEnum, - ReadFileResult>(ReadFileResult::READ_OK, - TestPresetExecutionShowOnlyHelper); - -ReadFileResult TestPresetExecutionModeHelper( - TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out, - const Json::Value* value) -{ - if (!value) { - return ReadFileResult::READ_OK; - } - - if (!value->isString()) { - return ReadFileResult::INVALID_PRESET; - } - - if (value->asString() == "until-fail") { - out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "until-pass") { - out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "after-timeout") { - out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout; - return ReadFileResult::READ_OK; - } - - return ReadFileResult::INVALID_PRESET; -} - -auto const TestPresetOptionalExecutionRepeatHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions::RepeatOptions, - ReadFileResult>( - ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExecutionOptions::RepeatOptions, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) - .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode, - TestPresetExecutionModeHelper, true) - .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count, - PresetIntHelper, true)); - -ReadFileResult TestPresetExecutionNoTestsActionHelper( - TestPreset::ExecutionOptions::NoTestsActionEnum& out, - const Json::Value* value) -{ - if (!value) { - out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default; - return ReadFileResult::READ_OK; - } - - if (!value->isString()) { - return ReadFileResult::INVALID_PRESET; - } - - if (value->asString() == "default") { - out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "error") { - out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "ignore") { - out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore; - return ReadFileResult::READ_OK; - } - - return ReadFileResult::INVALID_PRESET; -} - -auto const TestPresetOptionalExecutionNoTestsActionHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions::NoTestsActionEnum, - ReadFileResult>(ReadFileResult::READ_OK, - TestPresetExecutionNoTestsActionHelper); - -auto const TestPresetExecutionHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions, ReadFileResult>( - ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExecutionOptions, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) - .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure, - PresetOptionalBoolHelper, false) - .Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover, - PresetOptionalBoolHelper, false) - .Bind("jobs"_s, &TestPreset::ExecutionOptions::Jobs, - PresetOptionalIntHelper, false) - .Bind("resourceSpecFile"_s, - &TestPreset::ExecutionOptions::ResourceSpecFile, - PresetStringHelper, false) - .Bind("testLoad"_s, &TestPreset::ExecutionOptions::TestLoad, - PresetOptionalIntHelper, false) - .Bind("showOnly"_s, &TestPreset::ExecutionOptions::ShowOnly, - TestPresetOptionalExecutionShowOnlyHelper, false) - .Bind("repeat"_s, &TestPreset::ExecutionOptions::Repeat, - TestPresetOptionalExecutionRepeatHelper, false) - .Bind("interactiveDebugging"_s, - &TestPreset::ExecutionOptions::InteractiveDebugging, - PresetOptionalBoolHelper, false) - .Bind("scheduleRandom"_s, &TestPreset::ExecutionOptions::ScheduleRandom, - PresetOptionalBoolHelper, false) - .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout, - PresetOptionalIntHelper, false) - .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction, - TestPresetOptionalExecutionNoTestsActionHelper, false)); - -auto const TestPresetFilterHelper = - cmJSONOptionalHelper<TestPreset::FilterOptions, ReadFileResult>( - ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::FilterOptions, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) - .Bind("include"_s, &TestPreset::FilterOptions::Include, - TestPresetOptionalFilterIncludeHelper, false) - .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude, - TestPresetOptionalFilterExcludeHelper, false)); - -auto const TestPresetHelper = - cmJSONObjectHelper<TestPreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("name"_s, &TestPreset::Name, PresetStringHelper) - .Bind("inherits"_s, &TestPreset::Inherits, PresetInheritsHelper, false) - .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false) - .Bind<std::nullptr_t>("vendor"_s, nullptr, - VendorHelper(ReadFileResult::INVALID_PRESET), false) - .Bind("displayName"_s, &TestPreset::DisplayName, PresetStringHelper, false) - .Bind("description"_s, &TestPreset::Description, PresetStringHelper, false) - .Bind("environment"_s, &TestPreset::Environment, EnvironmentMapHelper, - false) - .Bind("configurePreset"_s, &TestPreset::ConfigurePreset, - PresetStringHelper, false) - .Bind("inheritConfigureEnvironment"_s, - &TestPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper, - false) - .Bind("configuration"_s, &TestPreset::Configuration, PresetStringHelper, - false) - .Bind("overwriteConfigurationFile"_s, - &TestPreset::OverwriteConfigurationFile, PresetVectorStringHelper, - false) - .Bind("output"_s, &TestPreset::Output, TestPresetOptionalOutputHelper, - false) - .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false) - .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper, - false); - -auto const ConfigurePresetsHelper = - cmJSONVectorHelper<ConfigurePreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - ConfigurePresetHelper); - -auto const BuildPresetsHelper = - cmJSONVectorHelper<BuildPreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - BuildPresetHelper); - -auto const TestPresetsHelper = cmJSONVectorHelper<TestPreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper); - -auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); - -auto const CMakeVersionHelper = - cmJSONObjectHelper<CMakeVersion, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false) - .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false) - .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false) - .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false); - -auto const RootPresetsHelper = - cmJSONObjectHelper<RootPresets, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false) - .Bind<int>("version"_s, nullptr, VersionHelper) - .Bind("configurePresets"_s, &RootPresets::ConfigurePresets, - ConfigurePresetsHelper, false) - .Bind("buildPresets"_s, &RootPresets::BuildPresets, BuildPresetsHelper, - false) - .Bind("testPresets"_s, &RootPresets::TestPresets, TestPresetsHelper, false) - .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired, - CMakeVersionHelper, false) - .Bind<std::nullptr_t>("vendor"_s, nullptr, - VendorHelper(ReadFileResult::INVALID_ROOT), false); +using ExpandMacroResult = cmCMakePresetsFileInternal::ExpandMacroResult; +using MacroExpander = cmCMakePresetsFileInternal::MacroExpander; void InheritString(std::string& child, const std::string& parent) { @@ -751,7 +78,7 @@ void InheritVector(std::vector<T>& child, const std::vector<T>& parent) template <class T> ReadFileResult VisitPreset( T& preset, std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets, - std::map<std::string, CycleStatus> cycleStatus) + std::map<std::string, CycleStatus> cycleStatus, int version) { switch (cycleStatus[preset.Name]) { case CycleStatus::InProgress: @@ -781,7 +108,7 @@ ReadFileResult VisitPreset( return ReadFileResult::USER_PRESET_INHERITANCE; } - auto result = VisitPreset(parentPreset, presets, cycleStatus); + auto result = VisitPreset(parentPreset, presets, cycleStatus, version); if (result != ReadFileResult::READ_OK) { return result; } @@ -791,9 +118,17 @@ ReadFileResult VisitPreset( for (auto const& v : parentPreset.Environment) { preset.Environment.insert(v); } + + if (!preset.ConditionEvaluator) { + preset.ConditionEvaluator = parentPreset.ConditionEvaluator; + } } - CHECK_OK(preset.VisitPresetAfterInherit()) + if (preset.ConditionEvaluator && preset.ConditionEvaluator->IsNull()) { + preset.ConditionEvaluator.reset(); + } + + CHECK_OK(preset.VisitPresetAfterInherit(version)) cycleStatus[preset.Name] = CycleStatus::Verified; return ReadFileResult::READ_OK; @@ -801,7 +136,8 @@ ReadFileResult VisitPreset( template <class T> ReadFileResult ComputePresetInheritance( - std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets) + std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets, + const cmCMakePresetsFile& file) { std::map<std::string, CycleStatus> cycleStatus; for (auto const& it : presets) { @@ -809,7 +145,9 @@ ReadFileResult ComputePresetInheritance( } for (auto& it : presets) { - auto result = VisitPreset<T>(it.second.Unexpanded, presets, cycleStatus); + auto& preset = it.second.Unexpanded; + auto result = + VisitPreset<T>(preset, presets, cycleStatus, file.GetVersion(preset)); if (result != ReadFileResult::READ_OK) { return result; } @@ -839,24 +177,17 @@ bool IsValidMacroNamespace(const std::string& str) [&str](const char* prefix) -> bool { return str == prefix; }); } -enum class ExpandMacroResult -{ - Ok, - Ignore, - Error, -}; - -using MacroExpander = std::function<ExpandMacroResult( - const std::string&, const std::string&, std::string&)>; - ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, - const std::vector<MacroExpander>& macroExpanders); + const std::vector<MacroExpander>& macroExpanders, + int version); ExpandMacroResult ExpandMacros( - std::string& out, const std::vector<MacroExpander>& macroExpanders); -ExpandMacroResult ExpandMacro( - std::string& out, const std::string& macroNamespace, - const std::string& macroName, - const std::vector<MacroExpander>& macroExpanders); + std::string& out, const std::vector<MacroExpander>& macroExpanders, + int version); +ExpandMacroResult ExpandMacro(std::string& out, + const std::string& macroNamespace, + const std::string& macroName, + const std::vector<MacroExpander>& macroExpanders, + int version); bool ExpandMacros(const cmCMakePresetsFile& file, const ConfigurePreset& preset, @@ -864,7 +195,7 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const std::vector<MacroExpander>& macroExpanders) { std::string binaryDir = preset.BinaryDir; - CHECK_EXPAND(out, binaryDir, macroExpanders) + CHECK_EXPAND(out, binaryDir, macroExpanders, file.GetVersion(preset)) if (!cmSystemTools::FileIsFullPath(binaryDir)) { binaryDir = cmStrCat(file.SourceDir, '/', binaryDir); @@ -872,69 +203,95 @@ bool ExpandMacros(const cmCMakePresetsFile& file, out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir); cmSystemTools::ConvertToUnixSlashes(out->BinaryDir); + if (!preset.InstallDir.empty()) { + std::string installDir = preset.InstallDir; + CHECK_EXPAND(out, installDir, macroExpanders, file.GetVersion(preset)) + + if (!cmSystemTools::FileIsFullPath(installDir)) { + installDir = cmStrCat(file.SourceDir, '/', installDir); + } + out->InstallDir = cmSystemTools::CollapseFullPath(installDir); + cmSystemTools::ConvertToUnixSlashes(out->InstallDir); + } + + if (!preset.ToolchainFile.empty()) { + std::string toolchain = preset.ToolchainFile; + CHECK_EXPAND(out, toolchain, macroExpanders, file.GetVersion(preset)) + out->ToolchainFile = toolchain; + } + for (auto& variable : out->CacheVariables) { if (variable.second) { - CHECK_EXPAND(out, variable.second->Value, macroExpanders) + CHECK_EXPAND(out, variable.second->Value, macroExpanders, + file.GetVersion(preset)) } } return true; } -bool ExpandMacros(const cmCMakePresetsFile&, const BuildPreset&, +bool ExpandMacros(const cmCMakePresetsFile& file, const BuildPreset& preset, cm::optional<BuildPreset>& out, const std::vector<MacroExpander>& macroExpanders) { for (auto& target : out->Targets) { - CHECK_EXPAND(out, target, macroExpanders) + CHECK_EXPAND(out, target, macroExpanders, file.GetVersion(preset)) } for (auto& nativeToolOption : out->NativeToolOptions) { - CHECK_EXPAND(out, nativeToolOption, macroExpanders) + CHECK_EXPAND(out, nativeToolOption, macroExpanders, + file.GetVersion(preset)) } return true; } -bool ExpandMacros(const cmCMakePresetsFile&, const TestPreset&, +bool ExpandMacros(const cmCMakePresetsFile& file, const TestPreset& preset, cm::optional<TestPreset>& out, const std::vector<MacroExpander>& macroExpanders) { for (auto& overwrite : out->OverwriteConfigurationFile) { - CHECK_EXPAND(out, overwrite, macroExpanders); + CHECK_EXPAND(out, overwrite, macroExpanders, file.GetVersion(preset)); } if (out->Output) { - CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders) + CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders, + file.GetVersion(preset)) } if (out->Filter) { if (out->Filter->Include) { - CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders) - CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders) + CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders, + file.GetVersion(preset)) + CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders, + file.GetVersion(preset)) if (out->Filter->Include->Index) { CHECK_EXPAND(out, out->Filter->Include->Index->IndexFile, - macroExpanders); + macroExpanders, file.GetVersion(preset)); } } if (out->Filter->Exclude) { - CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders) - CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders) + CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders, + file.GetVersion(preset)) + CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders, + file.GetVersion(preset)) if (out->Filter->Exclude->Fixtures) { - CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders) + CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders, + file.GetVersion(preset)) CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Setup, - macroExpanders) + macroExpanders, file.GetVersion(preset)) CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Cleanup, - macroExpanders) + macroExpanders, file.GetVersion(preset)) } } } if (out->Execution) { - CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders) + CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders, + file.GetVersion(preset)) } return true; @@ -955,8 +312,8 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, MacroExpander defaultMacroExpander = [&file, &preset](const std::string& macroNamespace, - const std::string& macroName, - std::string& macroOut) -> ExpandMacroResult { + const std::string& macroName, std::string& macroOut, + int version) -> ExpandMacroResult { if (macroNamespace.empty()) { if (macroName == "sourceDir") { macroOut += file.SourceDir; @@ -985,6 +342,13 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, macroOut += '$'; return ExpandMacroResult::Ok; } + if (macroName == "hostSystemName") { + if (version < 3) { + return ExpandMacroResult::Error; + } + macroOut += cmSystemTools::GetSystemName(); + return ExpandMacroResult::Ok; + } } return ExpandMacroResult::Ignore; @@ -993,11 +357,12 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, MacroExpander environmentMacroExpander = [¯oExpanders, &out, &envCycles]( const std::string& macroNamespace, const std::string& macroName, - std::string& result) -> ExpandMacroResult { + std::string& result, int version) -> ExpandMacroResult { if (macroNamespace == "env" && !macroName.empty() && out) { auto v = out->Environment.find(macroName); if (v != out->Environment.end() && v->second) { - auto e = VisitEnv(*v->second, envCycles[macroName], macroExpanders); + auto e = + VisitEnv(*v->second, envCycles[macroName], macroExpanders, version); if (e != ExpandMacroResult::Ok) { return e; } @@ -1025,7 +390,8 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, for (auto& v : out->Environment) { if (v.second) { - switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders)) { + switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders, + file.GetVersion(preset))) { case ExpandMacroResult::Error: return false; case ExpandMacroResult::Ignore: @@ -1037,11 +403,25 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, } } + if (preset.ConditionEvaluator) { + cm::optional<bool> result; + if (!preset.ConditionEvaluator->Evaluate( + macroExpanders, file.GetVersion(preset), result)) { + return false; + } + if (!result) { + out.reset(); + return true; + } + out->ConditionResult = *result; + } + return ExpandMacros(file, preset, out, macroExpanders); } ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, - const std::vector<MacroExpander>& macroExpanders) + const std::vector<MacroExpander>& macroExpanders, + int version) { if (status == CycleStatus::Verified) { return ExpandMacroResult::Ok; @@ -1051,7 +431,7 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, } status = CycleStatus::InProgress; - auto e = ExpandMacros(value, macroExpanders); + auto e = ExpandMacros(value, macroExpanders, version); if (e != ExpandMacroResult::Ok) { return e; } @@ -1060,7 +440,8 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, } ExpandMacroResult ExpandMacros( - std::string& out, const std::vector<MacroExpander>& macroExpanders) + std::string& out, const std::vector<MacroExpander>& macroExpanders, + int version) { std::string result; std::string macroNamespace; @@ -1107,8 +488,8 @@ ExpandMacroResult ExpandMacros( case State::MacroName: if (c == '}') { - auto e = - ExpandMacro(result, macroNamespace, macroName, macroExpanders); + auto e = ExpandMacro(result, macroNamespace, macroName, + macroExpanders, version); if (e != ExpandMacroResult::Ok) { return e; } @@ -1140,10 +521,11 @@ ExpandMacroResult ExpandMacros( ExpandMacroResult ExpandMacro(std::string& out, const std::string& macroNamespace, const std::string& macroName, - const std::vector<MacroExpander>& macroExpanders) + const std::vector<MacroExpander>& macroExpanders, + int version) { for (auto const& macroExpander : macroExpanders) { - auto result = macroExpander(macroNamespace, macroName, out); + auto result = macroExpander(macroNamespace, macroName, out, version); if (result != ExpandMacroResult::Ignore) { return result; } @@ -1157,6 +539,98 @@ ExpandMacroResult ExpandMacro(std::string& out, } } +bool cmCMakePresetsFileInternal::EqualsCondition::Evaluate( + const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const +{ + std::string lhs = this->Lhs; + CHECK_EXPAND(out, lhs, expanders, version); + + std::string rhs = this->Rhs; + CHECK_EXPAND(out, rhs, expanders, version); + + out = (lhs == rhs); + return true; +} + +bool cmCMakePresetsFileInternal::InListCondition::Evaluate( + const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const +{ + std::string str = this->String; + CHECK_EXPAND(out, str, expanders, version); + + for (auto item : this->List) { + CHECK_EXPAND(out, item, expanders, version); + if (str == item) { + out = true; + return true; + } + } + + out = false; + return true; +} + +bool cmCMakePresetsFileInternal::MatchesCondition::Evaluate( + const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const +{ + std::string str = this->String; + CHECK_EXPAND(out, str, expanders, version); + std::string regexStr = this->Regex; + CHECK_EXPAND(out, regexStr, expanders, version); + + cmsys::RegularExpression regex; + if (!regex.compile(regexStr)) { + return false; + } + + out = regex.find(str); + return true; +} + +bool cmCMakePresetsFileInternal::AnyAllOfCondition::Evaluate( + const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const +{ + for (auto const& condition : this->Conditions) { + cm::optional<bool> result; + if (!condition->Evaluate(expanders, version, result)) { + out.reset(); + return false; + } + + if (!result) { + out.reset(); + return true; + } + + if (result == this->StopValue) { + out = result; + return true; + } + } + + out = !this->StopValue; + return true; +} + +bool cmCMakePresetsFileInternal::NotCondition::Evaluate( + const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const +{ + out.reset(); + if (!this->SubCondition->Evaluate(expanders, version, out)) { + out.reset(); + return false; + } + if (out) { + *out = !*out; + } + return true; +} + cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit( const cmCMakePresetsFile::Preset& parentPreset) @@ -1174,6 +648,8 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit( preset.ToolsetStrategy = parent.ToolsetStrategy; } InheritString(preset.BinaryDir, parent.BinaryDir); + InheritString(preset.InstallDir, parent.InstallDir); + InheritString(preset.ToolchainFile, parent.ToolchainFile); InheritOptionalValue(preset.WarnDev, parent.WarnDev); InheritOptionalValue(preset.ErrorDev, parent.ErrorDev); InheritOptionalValue(preset.WarnDeprecated, parent.WarnDeprecated); @@ -1201,16 +677,19 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetBeforeInherit() } cmCMakePresetsFile::ReadFileResult -cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit() +cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit(int version) { auto& preset = *this; if (!preset.Hidden) { - if (preset.Generator.empty()) { - return ReadFileResult::INVALID_PRESET; - } - if (preset.BinaryDir.empty()) { - return ReadFileResult::INVALID_PRESET; + if (version < 3) { + if (preset.Generator.empty()) { + return ReadFileResult::INVALID_PRESET; + } + if (preset.BinaryDir.empty()) { + return ReadFileResult::INVALID_PRESET; + } } + if (preset.WarnDev == false && preset.ErrorDev == true) { return ReadFileResult::INVALID_PRESET; } @@ -1246,7 +725,7 @@ cmCMakePresetsFile::BuildPreset::VisitPresetInherit( } cmCMakePresetsFile::ReadFileResult -cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit() +cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit(int /* version */) { auto& preset = *this; if (!preset.Hidden && preset.ConfigurePreset.empty()) { @@ -1356,7 +835,7 @@ cmCMakePresetsFile::TestPreset::VisitPresetInherit( } cmCMakePresetsFile::ReadFileResult -cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit() +cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit(int /* version */) { auto& preset = *this; if (!preset.Hidden && preset.ConfigurePreset.empty()) { @@ -1417,9 +896,9 @@ cmCMakePresetsFile::ReadProjectPresetsInternal(bool allowNoFiles) : ReadFileResult::FILE_NOT_FOUND; } - CHECK_OK(ComputePresetInheritance(this->ConfigurePresets)) - CHECK_OK(ComputePresetInheritance(this->BuildPresets)) - CHECK_OK(ComputePresetInheritance(this->TestPresets)) + CHECK_OK(ComputePresetInheritance(this->ConfigurePresets, *this)) + CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this)) + CHECK_OK(ComputePresetInheritance(this->TestPresets, *this)) for (auto& it : this->ConfigurePresets) { if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) { @@ -1510,111 +989,21 @@ const char* cmCMakePresetsFile::ResultToString(ReadFileResult result) "support."; case ReadFileResult::INVALID_CONFIGURE_PRESET: return "Invalid \"configurePreset\" field"; + case ReadFileResult::INSTALL_PREFIX_UNSUPPORTED: + return "File version must be 3 or higher for installDir preset " + "support."; + case ReadFileResult::INVALID_CONDITION: + return "Invalid preset condition"; + case ReadFileResult::CONDITION_UNSUPPORTED: + return "File version must be 3 or higher for condition support"; + case ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED: + return "File version must be 3 or higher for toolchainFile preset " + "support."; } return "Unknown error"; } -cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile( - const std::string& filename, bool user) -{ - cmsys::ifstream fin(filename.c_str()); - if (!fin) { - return ReadFileResult::FILE_NOT_FOUND; - } - // If there's a BOM, toss it. - cmsys::FStream::ReadBOM(fin); - - Json::Value root; - Json::CharReaderBuilder builder; - Json::CharReaderBuilder::strictMode(&builder.settings_); - if (!Json::parseFromStream(builder, fin, &root, nullptr)) { - return ReadFileResult::JSON_PARSE_ERROR; - } - - int v = 0; - auto result = RootVersionHelper(v, &root); - if (result != ReadFileResult::READ_OK) { - return result; - } - if (v < MIN_VERSION || v > MAX_VERSION) { - return ReadFileResult::UNRECOGNIZED_VERSION; - } - - // Support for build and test presets added in version 2. - if (v < 2 && - (root.isMember("buildPresets") || root.isMember("testPresets"))) { - return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED; - } - - RootPresets presets; - if ((result = RootPresetsHelper(presets, &root)) != - ReadFileResult::READ_OK) { - return result; - } - - unsigned int currentMajor = cmVersion::GetMajorVersion(); - unsigned int currentMinor = cmVersion::GetMinorVersion(); - unsigned int currentPatch = cmVersion::GetPatchVersion(); - auto const& required = presets.CMakeMinimumRequired; - if (required.Major > currentMajor || - (required.Major == currentMajor && - (required.Minor > currentMinor || - (required.Minor == currentMinor && - (required.Patch > currentPatch))))) { - return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION; - } - - for (auto& preset : presets.ConfigurePresets) { - preset.User = user; - if (preset.Name.empty()) { - return ReadFileResult::INVALID_PRESET; - } - - PresetPair<ConfigurePreset> presetPair; - presetPair.Unexpanded = preset; - presetPair.Expanded = cm::nullopt; - if (!this->ConfigurePresets - .emplace(std::make_pair(preset.Name, presetPair)) - .second) { - return ReadFileResult::DUPLICATE_PRESETS; - } - this->ConfigurePresetOrder.push_back(preset.Name); - } - - for (auto& preset : presets.BuildPresets) { - preset.User = user; - if (preset.Name.empty()) { - return ReadFileResult::INVALID_PRESET; - } - - PresetPair<BuildPreset> presetPair; - presetPair.Unexpanded = preset; - presetPair.Expanded = cm::nullopt; - if (!this->BuildPresets.emplace(preset.Name, presetPair).second) { - return ReadFileResult::DUPLICATE_PRESETS; - } - this->BuildPresetOrder.push_back(preset.Name); - } - - for (auto& preset : presets.TestPresets) { - preset.User = user; - if (preset.Name.empty()) { - return ReadFileResult::INVALID_PRESET; - } - - PresetPair<TestPreset> presetPair; - presetPair.Unexpanded = preset; - presetPair.Expanded = cm::nullopt; - if (!this->TestPresets.emplace(preset.Name, presetPair).second) { - return ReadFileResult::DUPLICATE_PRESETS; - } - this->TestPresetOrder.push_back(preset.Name); - } - - return ReadFileResult::READ_OK; -} - void cmCMakePresetsFile::ClearPresets() { this->ConfigurePresets.clear(); @@ -1666,7 +1055,7 @@ void cmCMakePresetsFile::PrintConfigurePresetList( for (auto const& p : this->ConfigurePresetOrder) { auto const& preset = this->ConfigurePresets.at(p); if (!preset.Unexpanded.Hidden && preset.Expanded && - filter(preset.Unexpanded)) { + preset.Expanded->ConditionResult && filter(preset.Unexpanded)) { presets.push_back( static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded)); } @@ -1683,7 +1072,8 @@ void cmCMakePresetsFile::PrintBuildPresetList() const std::vector<const cmCMakePresetsFile::Preset*> presets; for (auto const& p : this->BuildPresetOrder) { auto const& preset = this->BuildPresets.at(p); - if (!preset.Unexpanded.Hidden && preset.Expanded) { + if (!preset.Unexpanded.Hidden && preset.Expanded && + preset.Expanded->ConditionResult) { presets.push_back( static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded)); } @@ -1700,7 +1090,8 @@ void cmCMakePresetsFile::PrintTestPresetList() const std::vector<const cmCMakePresetsFile::Preset*> presets; for (auto const& p : this->TestPresetOrder) { auto const& preset = this->TestPresets.at(p); - if (!preset.Unexpanded.Hidden && preset.Expanded) { + if (!preset.Unexpanded.Hidden && preset.Expanded && + preset.Expanded->ConditionResult) { presets.push_back( static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded)); } diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h index 3067d5e..7aa9b6a 100644 --- a/Source/cmCMakePresetsFile.h +++ b/Source/cmCMakePresetsFile.h @@ -2,8 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once +#include "cmConfigure.h" // IWYU pragma: keep + #include <functional> #include <map> +#include <memory> #include <string> #include <utility> #include <vector> @@ -33,6 +36,10 @@ public: INVALID_MACRO_EXPANSION, BUILD_TEST_PRESETS_UNSUPPORTED, INVALID_CONFIGURE_PRESET, + INSTALL_PREFIX_UNSUPPORTED, + INVALID_CONDITION, + CONDITION_UNSUPPORTED, + TOOLCHAIN_FILE_UNSUPPORTED, }; enum class ArchToolsetStrategy @@ -48,6 +55,8 @@ public: std::string Value; }; + class Condition; + class Preset { public: @@ -70,6 +79,9 @@ public: std::string DisplayName; std::string Description; + std::shared_ptr<Condition> ConditionEvaluator; + bool ConditionResult = true; + std::map<std::string, cm::optional<std::string>> Environment; virtual ReadFileResult VisitPresetInherit(const Preset& parent) = 0; @@ -78,7 +90,7 @@ public: return ReadFileResult::READ_OK; } - virtual ReadFileResult VisitPresetAfterInherit() + virtual ReadFileResult VisitPresetAfterInherit(int /* version */) { return ReadFileResult::READ_OK; } @@ -102,7 +114,9 @@ public: cm::optional<ArchToolsetStrategy> ArchitectureStrategy; std::string Toolset; cm::optional<ArchToolsetStrategy> ToolsetStrategy; + std::string ToolchainFile; std::string BinaryDir; + std::string InstallDir; std::map<std::string, cm::optional<CacheVariable>> CacheVariables; @@ -120,7 +134,7 @@ public: ReadFileResult VisitPresetInherit(const Preset& parent) override; ReadFileResult VisitPresetBeforeInherit() override; - ReadFileResult VisitPresetAfterInherit() override; + ReadFileResult VisitPresetAfterInherit(int version) override; }; class BuildPreset : public Preset @@ -146,7 +160,7 @@ public: std::vector<std::string> NativeToolOptions; ReadFileResult VisitPresetInherit(const Preset& parent) override; - ReadFileResult VisitPresetAfterInherit() override; + ReadFileResult VisitPresetAfterInherit(int /* version */) override; }; class TestPreset : public Preset @@ -273,7 +287,7 @@ public: cm::optional<ExecutionOptions> Execution; ReadFileResult VisitPresetInherit(const Preset& parent) override; - ReadFileResult VisitPresetAfterInherit() override; + ReadFileResult VisitPresetAfterInherit(int /* version */) override; }; template <class T> @@ -293,6 +307,13 @@ public: std::vector<std::string> TestPresetOrder; std::string SourceDir; + int Version; + int UserVersion; + + int GetVersion(const Preset& preset) const + { + return preset.User ? this->UserVersion : this->Version; + } static std::string GetFilename(const std::string& sourceDir); static std::string GetUserFilename(const std::string& sourceDir); diff --git a/Source/cmCMakePresetsFileInternal.h b/Source/cmCMakePresetsFileInternal.h new file mode 100644 index 0000000..3269276 --- /dev/null +++ b/Source/cmCMakePresetsFileInternal.h @@ -0,0 +1,112 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include <memory> + +#include "cmCMakePresetsFile.h" + +#define CHECK_OK(expr) \ + { \ + auto _result = expr; \ + if (_result != ReadFileResult::READ_OK) \ + return _result; \ + } + +namespace cmCMakePresetsFileInternal { +enum class ExpandMacroResult +{ + Ok, + Ignore, + Error, +}; + +using MacroExpander = std::function<ExpandMacroResult( + const std::string&, const std::string&, std::string&, int version)>; +} + +class cmCMakePresetsFile::Condition +{ +public: + virtual ~Condition() = default; + + virtual bool Evaluate( + const std::vector<cmCMakePresetsFileInternal::MacroExpander>& expanders, + int version, cm::optional<bool>& out) const = 0; + virtual bool IsNull() const { return false; } +}; + +namespace cmCMakePresetsFileInternal { + +class NullCondition : public cmCMakePresetsFile::Condition +{ + bool Evaluate(const std::vector<MacroExpander>& /*expanders*/, + int /*version*/, cm::optional<bool>& out) const override + { + out = true; + return true; + } + + bool IsNull() const override { return true; } +}; + +class ConstCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector<MacroExpander>& /*expanders*/, + int /*version*/, cm::optional<bool>& out) const override + { + out = this->Value; + return true; + } + + bool Value; +}; + +class EqualsCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const override; + + std::string Lhs; + std::string Rhs; +}; + +class InListCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const override; + + std::string String; + std::vector<std::string> List; +}; + +class MatchesCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const override; + + std::string String; + std::string Regex; +}; + +class AnyAllOfCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const override; + + std::vector<std::unique_ptr<Condition>> Conditions; + bool StopValue; +}; + +class NotCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector<MacroExpander>& expanders, int version, + cm::optional<bool>& out) const override; + + std::unique_ptr<Condition> SubCondition; +}; +} diff --git a/Source/cmCMakePresetsFileReadJSON.cxx b/Source/cmCMakePresetsFileReadJSON.cxx new file mode 100644 index 0000000..909a78b --- /dev/null +++ b/Source/cmCMakePresetsFileReadJSON.cxx @@ -0,0 +1,1029 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include <functional> +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include <cm/memory> +#include <cm/optional> +#include <cmext/string_view> + +#include <cm3p/json/reader.h> +#include <cm3p/json/value.h> + +#include "cmsys/FStream.hxx" + +#include "cmCMakePresetsFile.h" +#include "cmCMakePresetsFileInternal.h" +#include "cmJSONHelpers.h" +#include "cmVersion.h" + +namespace { +using ReadFileResult = cmCMakePresetsFile::ReadFileResult; +using CacheVariable = cmCMakePresetsFile::CacheVariable; +using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset; +using BuildPreset = cmCMakePresetsFile::BuildPreset; +using TestPreset = cmCMakePresetsFile::TestPreset; +using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy; + +constexpr int MIN_VERSION = 1; +constexpr int MAX_VERSION = 3; + +struct CMakeVersion +{ + unsigned int Major = 0; + unsigned int Minor = 0; + unsigned int Patch = 0; +}; + +struct RootPresets +{ + CMakeVersion CMakeMinimumRequired; + std::vector<cmCMakePresetsFile::ConfigurePreset> ConfigurePresets; + std::vector<cmCMakePresetsFile::BuildPreset> BuildPresets; + std::vector<cmCMakePresetsFile::TestPreset> TestPresets; +}; + +std::unique_ptr<cmCMakePresetsFileInternal::NotCondition> InvertCondition( + std::unique_ptr<cmCMakePresetsFile::Condition> condition) +{ + auto retval = cm::make_unique<cmCMakePresetsFileInternal::NotCondition>(); + retval->SubCondition = std::move(condition); + return retval; +} + +auto const ConditionStringHelper = cmJSONStringHelper<ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION); + +auto const ConditionBoolHelper = cmJSONBoolHelper<ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION); + +auto const ConditionStringListHelper = + cmJSONVectorHelper<std::string, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, + ConditionStringHelper); + +auto const ConstConditionHelper = + cmJSONObjectHelper<cmCMakePresetsFileInternal::ConstCondition, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) + .Bind("value"_s, &cmCMakePresetsFileInternal::ConstCondition::Value, + ConditionBoolHelper, true); + +auto const EqualsConditionHelper = + cmJSONObjectHelper<cmCMakePresetsFileInternal::EqualsCondition, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) + .Bind("lhs"_s, &cmCMakePresetsFileInternal::EqualsCondition::Lhs, + ConditionStringHelper, true) + .Bind("rhs"_s, &cmCMakePresetsFileInternal::EqualsCondition::Rhs, + ConditionStringHelper, true); + +auto const InListConditionHelper = + cmJSONObjectHelper<cmCMakePresetsFileInternal::InListCondition, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) + .Bind("string"_s, &cmCMakePresetsFileInternal::InListCondition::String, + ConditionStringHelper, true) + .Bind("list"_s, &cmCMakePresetsFileInternal::InListCondition::List, + ConditionStringListHelper, true); + +auto const MatchesConditionHelper = + cmJSONObjectHelper<cmCMakePresetsFileInternal::MatchesCondition, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) + .Bind("string"_s, &cmCMakePresetsFileInternal::MatchesCondition::String, + ConditionStringHelper, true) + .Bind("regex"_s, &cmCMakePresetsFileInternal::MatchesCondition::Regex, + ConditionStringHelper, true); + +ReadFileResult SubConditionHelper( + std::unique_ptr<cmCMakePresetsFile::Condition>& out, + const Json::Value* value); + +auto const ListConditionVectorHelper = + cmJSONVectorHelper<std::unique_ptr<cmCMakePresetsFile::Condition>, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, + SubConditionHelper); +auto const AnyAllOfConditionHelper = + cmJSONObjectHelper<cmCMakePresetsFileInternal::AnyAllOfCondition, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) + .Bind("conditions"_s, + &cmCMakePresetsFileInternal::AnyAllOfCondition::Conditions, + ListConditionVectorHelper); + +auto const NotConditionHelper = + cmJSONObjectHelper<cmCMakePresetsFileInternal::NotCondition, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) + .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) + .Bind("condition"_s, + &cmCMakePresetsFileInternal::NotCondition::SubCondition, + SubConditionHelper); + +ReadFileResult ConditionHelper( + std::unique_ptr<cmCMakePresetsFile::Condition>& out, + const Json::Value* value) +{ + if (!value) { + out.reset(); + return ReadFileResult::READ_OK; + } + + if (value->isBool()) { + auto c = cm::make_unique<cmCMakePresetsFileInternal::ConstCondition>(); + c->Value = value->asBool(); + out = std::move(c); + return ReadFileResult::READ_OK; + } + + if (value->isNull()) { + out = cm::make_unique<cmCMakePresetsFileInternal::NullCondition>(); + return ReadFileResult::READ_OK; + } + + if (value->isObject()) { + if (!value->isMember("type")) { + return ReadFileResult::INVALID_CONDITION; + } + + if (!(*value)["type"].isString()) { + return ReadFileResult::INVALID_CONDITION; + } + auto type = (*value)["type"].asString(); + + if (type == "const") { + auto c = cm::make_unique<cmCMakePresetsFileInternal::ConstCondition>(); + CHECK_OK(ConstConditionHelper(*c, value)); + out = std::move(c); + return ReadFileResult::READ_OK; + } + + if (type == "equals" || type == "notEquals") { + auto c = cm::make_unique<cmCMakePresetsFileInternal::EqualsCondition>(); + CHECK_OK(EqualsConditionHelper(*c, value)); + out = std::move(c); + if (type == "notEquals") { + out = InvertCondition(std::move(out)); + } + return ReadFileResult::READ_OK; + } + + if (type == "inList" || type == "notInList") { + auto c = cm::make_unique<cmCMakePresetsFileInternal::InListCondition>(); + CHECK_OK(InListConditionHelper(*c, value)); + out = std::move(c); + if (type == "notInList") { + out = InvertCondition(std::move(out)); + } + return ReadFileResult::READ_OK; + } + + if (type == "matches" || type == "notMatches") { + auto c = cm::make_unique<cmCMakePresetsFileInternal::MatchesCondition>(); + CHECK_OK(MatchesConditionHelper(*c, value)); + out = std::move(c); + if (type == "notMatches") { + out = InvertCondition(std::move(out)); + } + return ReadFileResult::READ_OK; + } + + if (type == "anyOf" || type == "allOf") { + auto c = + cm::make_unique<cmCMakePresetsFileInternal::AnyAllOfCondition>(); + c->StopValue = (type == "anyOf"); + CHECK_OK(AnyAllOfConditionHelper(*c, value)); + out = std::move(c); + return ReadFileResult::READ_OK; + } + + if (type == "not") { + auto c = cm::make_unique<cmCMakePresetsFileInternal::NotCondition>(); + CHECK_OK(NotConditionHelper(*c, value)); + out = std::move(c); + return ReadFileResult::READ_OK; + } + } + + return ReadFileResult::INVALID_CONDITION; +} + +ReadFileResult PresetConditionHelper( + std::shared_ptr<cmCMakePresetsFile::Condition>& out, + const Json::Value* value) +{ + std::unique_ptr<cmCMakePresetsFile::Condition> ptr; + auto result = ConditionHelper(ptr, value); + out = std::move(ptr); + return result; +} + +ReadFileResult SubConditionHelper( + std::unique_ptr<cmCMakePresetsFile::Condition>& out, + const Json::Value* value) +{ + std::unique_ptr<cmCMakePresetsFile::Condition> ptr; + auto result = ConditionHelper(ptr, value); + if (ptr && ptr->IsNull()) { + return ReadFileResult::INVALID_CONDITION; + } + out = std::move(ptr); + return result; +} + +cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error) +{ + return [error](std::nullptr_t& /*out*/, + const Json::Value* value) -> ReadFileResult { + if (!value) { + return ReadFileResult::READ_OK; + } + + if (!value->isObject()) { + return error; + } + + return ReadFileResult::READ_OK; + }; +} + +auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); + +auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>( + ReadFileResult::NO_VERSION, VersionIntHelper); + +auto const RootVersionHelper = + cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_ROOT) + .Bind("version"_s, VersionHelper, false); + +auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE); + +ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value) +{ + if (!value) { + out.clear(); + return ReadFileResult::READ_OK; + } + + if (value->isBool()) { + out = value->asBool() ? "TRUE" : "FALSE"; + return ReadFileResult::READ_OK; + } + + return VariableStringHelper(out, value); +} + +auto const VariableObjectHelper = + cmJSONObjectHelper<CacheVariable, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false) + .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false) + .Bind("value"_s, &CacheVariable::Value, VariableValueHelper); + +ReadFileResult VariableHelper(cm::optional<CacheVariable>& out, + const Json::Value* value) +{ + if (value->isBool()) { + out = CacheVariable{ + /*Type=*/"BOOL", + /*Value=*/value->asBool() ? "TRUE" : "FALSE", + }; + return ReadFileResult::READ_OK; + } + if (value->isString()) { + out = CacheVariable{ + /*Type=*/"", + /*Value=*/value->asString(), + }; + return ReadFileResult::READ_OK; + } + if (value->isObject()) { + out.emplace(); + return VariableObjectHelper(*out, value); + } + if (value->isNull()) { + out = cm::nullopt; + return ReadFileResult::READ_OK; + } + return ReadFileResult::INVALID_VARIABLE; +} + +auto const VariablesHelper = + cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper); + +auto const PresetStringHelper = cmJSONStringHelper<ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); + +ReadFileResult EnvironmentHelper(cm::optional<std::string>& out, + const Json::Value* value) +{ + if (!value || value->isNull()) { + out = cm::nullopt; + return ReadFileResult::READ_OK; + } + if (value->isString()) { + out = value->asString(); + return ReadFileResult::READ_OK; + } + return ReadFileResult::INVALID_PRESET; +} + +auto const EnvironmentMapHelper = + cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, + EnvironmentHelper); + +auto const PresetVectorStringHelper = + cmJSONVectorHelper<std::string, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, + PresetStringHelper); + +ReadFileResult PresetInheritsHelper(std::vector<std::string>& out, + const Json::Value* value) +{ + out.clear(); + if (!value) { + return ReadFileResult::READ_OK; + } + + if (value->isString()) { + out.push_back(value->asString()); + return ReadFileResult::READ_OK; + } + + return PresetVectorStringHelper(out, value); +} + +auto const PresetBoolHelper = cmJSONBoolHelper<ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); + +auto const PresetOptionalBoolHelper = + cmJSONOptionalHelper<bool, ReadFileResult>(ReadFileResult::READ_OK, + PresetBoolHelper); + +auto const PresetIntHelper = cmJSONIntHelper<ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); + +auto const PresetOptionalIntHelper = cmJSONOptionalHelper<int, ReadFileResult>( + ReadFileResult::READ_OK, PresetIntHelper); + +auto const PresetVectorIntHelper = cmJSONVectorHelper<int, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper); + +auto const PresetWarningsHelper = + cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("dev"_s, &ConfigurePreset::WarnDev, PresetOptionalBoolHelper, false) + .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated, + PresetOptionalBoolHelper, false) + .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized, + PresetOptionalBoolHelper, false) + .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli, + PresetOptionalBoolHelper, false) + .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars, + PresetOptionalBoolHelper, false); + +auto const PresetErrorsHelper = + cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("dev"_s, &ConfigurePreset::ErrorDev, PresetOptionalBoolHelper, false) + .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated, + PresetOptionalBoolHelper, false); + +auto const PresetDebugHelper = + cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("output"_s, &ConfigurePreset::DebugOutput, PresetOptionalBoolHelper, + false) + .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile, + PresetOptionalBoolHelper, false) + .Bind("find"_s, &ConfigurePreset::DebugFind, PresetOptionalBoolHelper, + false); + +ReadFileResult ArchToolsetStrategyHelper( + cm::optional<ArchToolsetStrategy>& out, const Json::Value* value) +{ + if (!value) { + out = cm::nullopt; + return ReadFileResult::READ_OK; + } + + if (!value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "set") { + out = ArchToolsetStrategy::Set; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "external") { + out = ArchToolsetStrategy::External; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +std::function<ReadFileResult(ConfigurePreset&, const Json::Value*)> +ArchToolsetHelper( + std::string ConfigurePreset::*valueField, + cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField) +{ + auto const objectHelper = + cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("value", valueField, PresetStringHelper, false) + .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false); + return [valueField, strategyField, objectHelper]( + ConfigurePreset& out, const Json::Value* value) -> ReadFileResult { + if (!value) { + (out.*valueField).clear(); + out.*strategyField = cm::nullopt; + return ReadFileResult::READ_OK; + } + + if (value->isString()) { + out.*valueField = value->asString(); + out.*strategyField = cm::nullopt; + return ReadFileResult::READ_OK; + } + + if (value->isObject()) { + return objectHelper(out, value); + } + + return ReadFileResult::INVALID_PRESET; + }; +} + +auto const ArchitectureHelper = ArchToolsetHelper( + &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy); +auto const ToolsetHelper = ArchToolsetHelper( + &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy); + +auto const ConfigurePresetHelper = + cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper) + .Bind("inherits"_s, &ConfigurePreset::Inherits, PresetInheritsHelper, + false) + .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false) + .Bind<std::nullptr_t>("vendor"_s, nullptr, + VendorHelper(ReadFileResult::INVALID_PRESET), false) + .Bind("displayName"_s, &ConfigurePreset::DisplayName, PresetStringHelper, + false) + .Bind("description"_s, &ConfigurePreset::Description, PresetStringHelper, + false) + .Bind("generator"_s, &ConfigurePreset::Generator, PresetStringHelper, + false) + .Bind("architecture"_s, ArchitectureHelper, false) + .Bind("toolset"_s, ToolsetHelper, false) + .Bind("toolchainFile"_s, &ConfigurePreset::ToolchainFile, + PresetStringHelper, false) + .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper, + false) + .Bind("installDir"_s, &ConfigurePreset::InstallDir, PresetStringHelper, + false) + .Bind<std::string>("cmakeExecutable"_s, nullptr, PresetStringHelper, false) + .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables, + VariablesHelper, false) + .Bind("environment"_s, &ConfigurePreset::Environment, EnvironmentMapHelper, + false) + .Bind("warnings"_s, PresetWarningsHelper, false) + .Bind("errors"_s, PresetErrorsHelper, false) + .Bind("debug"_s, PresetDebugHelper, false) + .Bind("condition"_s, &ConfigurePreset::ConditionEvaluator, + PresetConditionHelper, false); + +auto const BuildPresetHelper = + cmJSONObjectHelper<BuildPreset, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("name"_s, &BuildPreset::Name, PresetStringHelper) + .Bind("inherits"_s, &BuildPreset::Inherits, PresetInheritsHelper, false) + .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false) + .Bind<std::nullptr_t>("vendor"_s, nullptr, + VendorHelper(ReadFileResult::INVALID_PRESET), false) + .Bind("displayName"_s, &BuildPreset::DisplayName, PresetStringHelper, + false) + .Bind("description"_s, &BuildPreset::Description, PresetStringHelper, + false) + .Bind("environment"_s, &BuildPreset::Environment, EnvironmentMapHelper, + false) + .Bind("configurePreset"_s, &BuildPreset::ConfigurePreset, + PresetStringHelper, false) + .Bind("inheritConfigureEnvironment"_s, + &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper, + false) + .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false) + .Bind("targets"_s, &BuildPreset::Targets, PresetVectorStringHelper, false) + .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper, + false) + .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper, + false) + .Bind("verbose"_s, &BuildPreset::Verbose, PresetOptionalBoolHelper, false) + .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions, + PresetVectorStringHelper, false) + .Bind("condition"_s, &BuildPreset::ConditionEvaluator, + PresetConditionHelper, false); + +ReadFileResult TestPresetOutputVerbosityHelper( + TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value) +{ + if (!value) { + out = TestPreset::OutputOptions::VerbosityEnum::Default; + return ReadFileResult::READ_OK; + } + + if (!value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "default") { + out = TestPreset::OutputOptions::VerbosityEnum::Default; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "verbose") { + out = TestPreset::OutputOptions::VerbosityEnum::Verbose; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "extra") { + out = TestPreset::OutputOptions::VerbosityEnum::Extra; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const TestPresetOptionalOutputVerbosityHelper = + cmJSONOptionalHelper<TestPreset::OutputOptions::VerbosityEnum, + ReadFileResult>(ReadFileResult::READ_OK, + TestPresetOutputVerbosityHelper); + +auto const TestPresetOptionalOutputHelper = + cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>( + ReadFileResult::READ_OK, + cmJSONObjectHelper<TestPreset::OutputOptions, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress, + PresetOptionalBoolHelper, false) + .Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity, + TestPresetOptionalOutputVerbosityHelper, false) + .Bind("debug"_s, &TestPreset::OutputOptions::Debug, + PresetOptionalBoolHelper, false) + .Bind("outputOnFailure"_s, &TestPreset::OutputOptions::OutputOnFailure, + PresetOptionalBoolHelper, false) + .Bind("quiet"_s, &TestPreset::OutputOptions::Quiet, + PresetOptionalBoolHelper, false) + .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile, + PresetStringHelper, false) + .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary, + PresetOptionalBoolHelper, false) + .Bind("subprojectSummary"_s, + &TestPreset::OutputOptions::SubprojectSummary, + PresetOptionalBoolHelper, false) + .Bind("maxPassedTestOutputSize"_s, + &TestPreset::OutputOptions::MaxPassedTestOutputSize, + PresetOptionalIntHelper, false) + .Bind("maxFailedTestOutputSize"_s, + &TestPreset::OutputOptions::MaxFailedTestOutputSize, + PresetOptionalIntHelper, false) + .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth, + PresetOptionalIntHelper, false)); + +auto const TestPresetOptionalFilterIncludeIndexObjectHelper = + cmJSONOptionalHelper<TestPreset::IncludeOptions::IndexOptions, + ReadFileResult>( + ReadFileResult::READ_OK, + cmJSONObjectHelper<TestPreset::IncludeOptions::IndexOptions, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_PRESET) + .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start, + PresetOptionalIntHelper, false) + .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End, + PresetOptionalIntHelper, false) + .Bind("stride"_s, &TestPreset::IncludeOptions::IndexOptions::Stride, + PresetOptionalIntHelper, false) + .Bind("specificTests"_s, + &TestPreset::IncludeOptions::IndexOptions::SpecificTests, + PresetVectorIntHelper, false)); + +ReadFileResult TestPresetOptionalFilterIncludeIndexHelper( + cm::optional<TestPreset::IncludeOptions::IndexOptions>& out, + const Json::Value* value) +{ + if (!value) { + out = cm::nullopt; + return ReadFileResult::READ_OK; + } + + if (value->isString()) { + out.emplace(); + out->IndexFile = value->asString(); + return ReadFileResult::READ_OK; + } + + if (value->isObject()) { + return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value); + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const TestPresetOptionalFilterIncludeHelper = + cmJSONOptionalHelper<TestPreset::IncludeOptions, ReadFileResult>( + ReadFileResult::READ_OK, + cmJSONObjectHelper<TestPreset::IncludeOptions, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + .Bind("name"_s, &TestPreset::IncludeOptions::Name, PresetStringHelper, + false) + .Bind("label"_s, &TestPreset::IncludeOptions::Label, PresetStringHelper, + false) + .Bind("index"_s, &TestPreset::IncludeOptions::Index, + TestPresetOptionalFilterIncludeIndexHelper, false) + .Bind("useUnion"_s, &TestPreset::IncludeOptions::UseUnion, + PresetOptionalBoolHelper, false)); + +auto const TestPresetOptionalFilterExcludeFixturesHelper = + cmJSONOptionalHelper<TestPreset::ExcludeOptions::FixturesOptions, + ReadFileResult>( + ReadFileResult::READ_OK, + cmJSONObjectHelper<TestPreset::ExcludeOptions::FixturesOptions, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_PRESET) + .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any, + PresetStringHelper, false) + .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup, + PresetStringHelper, false) + .Bind("cleanup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Cleanup, + PresetStringHelper, false)); + +auto const TestPresetOptionalFilterExcludeHelper = + cmJSONOptionalHelper<TestPreset::ExcludeOptions, ReadFileResult>( + ReadFileResult::READ_OK, + cmJSONObjectHelper<TestPreset::ExcludeOptions, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + .Bind("name"_s, &TestPreset::ExcludeOptions::Name, PresetStringHelper, + false) + .Bind("label"_s, &TestPreset::ExcludeOptions::Label, PresetStringHelper, + false) + .Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures, + TestPresetOptionalFilterExcludeFixturesHelper, false)); + +ReadFileResult TestPresetExecutionShowOnlyHelper( + TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value) +{ + if (!value || !value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "human") { + out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "json-v1") { + out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const TestPresetOptionalExecutionShowOnlyHelper = + cmJSONOptionalHelper<TestPreset::ExecutionOptions::ShowOnlyEnum, + ReadFileResult>(ReadFileResult::READ_OK, + TestPresetExecutionShowOnlyHelper); + +ReadFileResult TestPresetExecutionModeHelper( + TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out, + const Json::Value* value) +{ + if (!value) { + return ReadFileResult::READ_OK; + } + + if (!value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "until-fail") { + out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "until-pass") { + out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "after-timeout") { + out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const TestPresetOptionalExecutionRepeatHelper = + cmJSONOptionalHelper<TestPreset::ExecutionOptions::RepeatOptions, + ReadFileResult>( + ReadFileResult::READ_OK, + cmJSONObjectHelper<TestPreset::ExecutionOptions::RepeatOptions, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_PRESET) + .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode, + TestPresetExecutionModeHelper, true) + .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count, + PresetIntHelper, true)); + +ReadFileResult TestPresetExecutionNoTestsActionHelper( + TestPreset::ExecutionOptions::NoTestsActionEnum& out, + const Json::Value* value) +{ + if (!value) { + out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default; + return ReadFileResult::READ_OK; + } + + if (!value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "default") { + out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "error") { + out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "ignore") { + out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const TestPresetOptionalExecutionNoTestsActionHelper = + cmJSONOptionalHelper<TestPreset::ExecutionOptions::NoTestsActionEnum, + ReadFileResult>(ReadFileResult::READ_OK, + TestPresetExecutionNoTestsActionHelper); + +auto const TestPresetExecutionHelper = + cmJSONOptionalHelper<TestPreset::ExecutionOptions, ReadFileResult>( + ReadFileResult::READ_OK, + cmJSONObjectHelper<TestPreset::ExecutionOptions, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure, + PresetOptionalBoolHelper, false) + .Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover, + PresetOptionalBoolHelper, false) + .Bind("jobs"_s, &TestPreset::ExecutionOptions::Jobs, + PresetOptionalIntHelper, false) + .Bind("resourceSpecFile"_s, + &TestPreset::ExecutionOptions::ResourceSpecFile, + PresetStringHelper, false) + .Bind("testLoad"_s, &TestPreset::ExecutionOptions::TestLoad, + PresetOptionalIntHelper, false) + .Bind("showOnly"_s, &TestPreset::ExecutionOptions::ShowOnly, + TestPresetOptionalExecutionShowOnlyHelper, false) + .Bind("repeat"_s, &TestPreset::ExecutionOptions::Repeat, + TestPresetOptionalExecutionRepeatHelper, false) + .Bind("interactiveDebugging"_s, + &TestPreset::ExecutionOptions::InteractiveDebugging, + PresetOptionalBoolHelper, false) + .Bind("scheduleRandom"_s, &TestPreset::ExecutionOptions::ScheduleRandom, + PresetOptionalBoolHelper, false) + .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout, + PresetOptionalIntHelper, false) + .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction, + TestPresetOptionalExecutionNoTestsActionHelper, false)); + +auto const TestPresetFilterHelper = + cmJSONOptionalHelper<TestPreset::FilterOptions, ReadFileResult>( + ReadFileResult::READ_OK, + cmJSONObjectHelper<TestPreset::FilterOptions, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + .Bind("include"_s, &TestPreset::FilterOptions::Include, + TestPresetOptionalFilterIncludeHelper, false) + .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude, + TestPresetOptionalFilterExcludeHelper, false)); + +auto const TestPresetHelper = + cmJSONObjectHelper<TestPreset, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("name"_s, &TestPreset::Name, PresetStringHelper) + .Bind("inherits"_s, &TestPreset::Inherits, PresetInheritsHelper, false) + .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false) + .Bind<std::nullptr_t>("vendor"_s, nullptr, + VendorHelper(ReadFileResult::INVALID_PRESET), false) + .Bind("displayName"_s, &TestPreset::DisplayName, PresetStringHelper, false) + .Bind("description"_s, &TestPreset::Description, PresetStringHelper, false) + .Bind("environment"_s, &TestPreset::Environment, EnvironmentMapHelper, + false) + .Bind("configurePreset"_s, &TestPreset::ConfigurePreset, + PresetStringHelper, false) + .Bind("inheritConfigureEnvironment"_s, + &TestPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper, + false) + .Bind("configuration"_s, &TestPreset::Configuration, PresetStringHelper, + false) + .Bind("overwriteConfigurationFile"_s, + &TestPreset::OverwriteConfigurationFile, PresetVectorStringHelper, + false) + .Bind("output"_s, &TestPreset::Output, TestPresetOptionalOutputHelper, + false) + .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false) + .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper, + false) + .Bind("condition"_s, &TestPreset::ConditionEvaluator, + PresetConditionHelper, false); + +auto const ConfigurePresetsHelper = + cmJSONVectorHelper<ConfigurePreset, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, + ConfigurePresetHelper); + +auto const BuildPresetsHelper = + cmJSONVectorHelper<BuildPreset, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, + BuildPresetHelper); + +auto const TestPresetsHelper = cmJSONVectorHelper<TestPreset, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper); + +auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); + +auto const CMakeVersionHelper = + cmJSONObjectHelper<CMakeVersion, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false) + .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false) + .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false) + .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false); + +auto const RootPresetsHelper = + cmJSONObjectHelper<RootPresets, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false) + .Bind<int>("version"_s, nullptr, VersionHelper) + .Bind("configurePresets"_s, &RootPresets::ConfigurePresets, + ConfigurePresetsHelper, false) + .Bind("buildPresets"_s, &RootPresets::BuildPresets, BuildPresetsHelper, + false) + .Bind("testPresets"_s, &RootPresets::TestPresets, TestPresetsHelper, false) + .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired, + CMakeVersionHelper, false) + .Bind<std::nullptr_t>("vendor"_s, nullptr, + VendorHelper(ReadFileResult::INVALID_ROOT), false); +} + +cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile( + const std::string& filename, bool user) +{ + cmsys::ifstream fin(filename.c_str()); + if (!fin) { + return ReadFileResult::FILE_NOT_FOUND; + } + // If there's a BOM, toss it. + cmsys::FStream::ReadBOM(fin); + + Json::Value root; + Json::CharReaderBuilder builder; + Json::CharReaderBuilder::strictMode(&builder.settings_); + if (!Json::parseFromStream(builder, fin, &root, nullptr)) { + return ReadFileResult::JSON_PARSE_ERROR; + } + + int v = 0; + auto result = RootVersionHelper(v, &root); + if (result != ReadFileResult::READ_OK) { + return result; + } + if (v < MIN_VERSION || v > MAX_VERSION) { + return ReadFileResult::UNRECOGNIZED_VERSION; + } + if (user) { + this->UserVersion = v; + } else { + this->Version = v; + } + + // Support for build and test presets added in version 2. + if (v < 2 && + (root.isMember("buildPresets") || root.isMember("testPresets"))) { + return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED; + } + + RootPresets presets; + if ((result = RootPresetsHelper(presets, &root)) != + ReadFileResult::READ_OK) { + return result; + } + + unsigned int currentMajor = cmVersion::GetMajorVersion(); + unsigned int currentMinor = cmVersion::GetMinorVersion(); + unsigned int currentPatch = cmVersion::GetPatchVersion(); + auto const& required = presets.CMakeMinimumRequired; + if (required.Major > currentMajor || + (required.Major == currentMajor && + (required.Minor > currentMinor || + (required.Minor == currentMinor && + (required.Patch > currentPatch))))) { + return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION; + } + + for (auto& preset : presets.ConfigurePresets) { + preset.User = user; + if (preset.Name.empty()) { + return ReadFileResult::INVALID_PRESET; + } + + PresetPair<ConfigurePreset> presetPair; + presetPair.Unexpanded = preset; + presetPair.Expanded = cm::nullopt; + if (!this->ConfigurePresets + .emplace(std::make_pair(preset.Name, presetPair)) + .second) { + return ReadFileResult::DUPLICATE_PRESETS; + } + + // Support for installDir presets added in version 3. + if (v < 3 && !preset.InstallDir.empty()) { + return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED; + } + + // Support for conditions added in version 3. + if (v < 3 && preset.ConditionEvaluator) { + return ReadFileResult::CONDITION_UNSUPPORTED; + } + + // Support for toolchainFile presets added in version 3. + if (v < 3 && !preset.ToolchainFile.empty()) { + return ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED; + } + + this->ConfigurePresetOrder.push_back(preset.Name); + } + + for (auto& preset : presets.BuildPresets) { + preset.User = user; + if (preset.Name.empty()) { + return ReadFileResult::INVALID_PRESET; + } + + PresetPair<BuildPreset> presetPair; + presetPair.Unexpanded = preset; + presetPair.Expanded = cm::nullopt; + if (!this->BuildPresets.emplace(preset.Name, presetPair).second) { + return ReadFileResult::DUPLICATE_PRESETS; + } + + // Support for conditions added in version 3. + if (v < 3 && preset.ConditionEvaluator) { + return ReadFileResult::CONDITION_UNSUPPORTED; + } + + this->BuildPresetOrder.push_back(preset.Name); + } + + for (auto& preset : presets.TestPresets) { + preset.User = user; + if (preset.Name.empty()) { + return ReadFileResult::INVALID_PRESET; + } + + PresetPair<TestPreset> presetPair; + presetPair.Unexpanded = preset; + presetPair.Expanded = cm::nullopt; + if (!this->TestPresets.emplace(preset.Name, presetPair).second) { + return ReadFileResult::DUPLICATE_PRESETS; + } + + // Support for conditions added in version 3. + if (v < 3 && preset.ConditionEvaluator) { + return ReadFileResult::CONDITION_UNSUPPORTED; + } + + this->TestPresetOrder.push_back(preset.Name); + } + + return ReadFileResult::READ_OK; +} diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 620ba19..79a3925 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -4,7 +4,6 @@ #include <algorithm> #include <cctype> -#include <cerrno> #include <chrono> #include <cstdio> #include <cstdlib> @@ -2070,6 +2069,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } i++; this->Impl->TestDir = std::string(args[i]); + } else if (this->CheckArgument(arg, "--output-junit"_s)) { + if (i >= args.size() - 1) { + errormsg = "'--output-junit' requires an argument"; + return false; + } + i++; + this->Impl->TestHandler.SetJUnitXMLFileName(std::string(args[i])); + // Turn test output compression off. + // This makes it easier to include test output in the resulting + // JUnit XML report. + this->Impl->CompressTestOutput = false; } cm::string_view noTestsPrefix = "--no-tests="; @@ -2108,17 +2118,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } else if (this->CheckArgument(arg, "-L"_s, "--label-regex") && i < args.size() - 1) { i++; - this->GetTestHandler()->SetPersistentOption("LabelRegularExpression", - args[i].c_str()); - this->GetMemCheckHandler()->SetPersistentOption("LabelRegularExpression", - args[i].c_str()); + this->GetTestHandler()->AddPersistentMultiOption("LabelRegularExpression", + args[i]); + this->GetMemCheckHandler()->AddPersistentMultiOption( + "LabelRegularExpression", args[i]); } else if (this->CheckArgument(arg, "-LE"_s, "--label-exclude") && i < args.size() - 1) { i++; - this->GetTestHandler()->SetPersistentOption( - "ExcludeLabelRegularExpression", args[i].c_str()); - this->GetMemCheckHandler()->SetPersistentOption( - "ExcludeLabelRegularExpression", args[i].c_str()); + this->GetTestHandler()->AddPersistentMultiOption( + "ExcludeLabelRegularExpression", args[i]); + this->GetMemCheckHandler()->AddPersistentMultiOption( + "ExcludeLabelRegularExpression", args[i]); } else if (this->CheckArgument(arg, "-E"_s, "--exclude-regex") && @@ -2221,7 +2231,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args, cmCTestScriptHandler* ch = this->GetScriptHandler(); // -SR is an internal argument, -SP should be ignored when it is passed if (!SRArgumentSpecified) { - ch->AddConfigurationScript(args[i].c_str(), false); + ch->AddConfigurationScript(args[i], false); } } @@ -2231,7 +2241,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args, this->Impl->RunConfigurationScript = true; i++; cmCTestScriptHandler* ch = this->GetScriptHandler(); - ch->AddConfigurationScript(args[i].c_str(), true); + ch->AddConfigurationScript(args[i], true); } if (this->CheckArgument(arg, "-S"_s, "--script") && i < args.size() - 1) { @@ -2240,7 +2250,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args, cmCTestScriptHandler* ch = this->GetScriptHandler(); // -SR is an internal argument, -S should be ignored when it is passed if (!SRArgumentSpecified) { - ch->AddConfigurationScript(args[i].c_str(), true); + ch->AddConfigurationScript(args[i], true); } } } @@ -2268,6 +2278,15 @@ void cmCTest::SetPersistentOptionIfNotEmpty(const std::string& value, } } +void cmCTest::AddPersistentMultiOptionIfNotEmpty(const std::string& value, + const std::string& optionName) +{ + if (!value.empty()) { + this->GetTestHandler()->AddPersistentMultiOption(optionName, value); + this->GetMemCheckHandler()->AddPersistentMultiOption(optionName, value); + } +} + bool cmCTest::SetArgsFromPreset(const std::string& presetName, bool listPresets) { @@ -2310,6 +2329,13 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, return false; } + if (!expandedPreset->ConditionResult) { + cmSystemTools::Error(cmStrCat("Cannot use disabled test preset in ", + workingDirectory, ": \"", presetName, '"')); + settingsFile.PrintTestPresetList(); + return false; + } + auto configurePresetPair = settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset); if (configurePresetPair == settingsFile.ConfigurePresets.end()) { @@ -2412,7 +2438,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, if (expandedPreset->Filter->Include) { this->SetPersistentOptionIfNotEmpty( expandedPreset->Filter->Include->Name, "IncludeRegularExpression"); - this->SetPersistentOptionIfNotEmpty( + this->AddPersistentMultiOptionIfNotEmpty( expandedPreset->Filter->Include->Label, "LabelRegularExpression"); if (expandedPreset->Filter->Include->Index) { @@ -2445,7 +2471,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, if (expandedPreset->Filter->Exclude) { this->SetPersistentOptionIfNotEmpty( expandedPreset->Filter->Exclude->Name, "ExcludeRegularExpression"); - this->SetPersistentOptionIfNotEmpty( + this->AddPersistentMultiOptionIfNotEmpty( expandedPreset->Filter->Exclude->Label, "ExcludeLabelRegularExpression"); @@ -2826,9 +2852,10 @@ int cmCTest::ExecuteTests() cmCTestLog(this, OUTPUT, "Internal ctest changing into directory: " << workDir << std::endl); - if (cmSystemTools::ChangeDirectory(workDir) != 0) { + cmsys::Status status = cmSystemTools::ChangeDirectory(workDir); + if (!status) { auto msg = "Failed to change working directory to \"" + workDir + - "\" : " + std::strerror(errno) + "\n"; + "\" : " + status.GetString() + "\n"; cmCTestLog(this, ERROR_MESSAGE, msg); return 1; } diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 4669a1c..392eb1c 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -463,6 +463,8 @@ public: private: void SetPersistentOptionIfNotEmpty(const std::string& value, const std::string& optionName); + void AddPersistentMultiOptionIfNotEmpty(const std::string& value, + const std::string& optionName); int GenerateNotesFile(const std::string& files); diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h index 495dc69..b14cfc2 100644 --- a/Source/cmCommandLineArgument.h +++ b/Source/cmCommandLineArgument.h @@ -112,6 +112,10 @@ struct cmCommandLineArgument } } if (parseState == ParseMode::Valid) { + if (possible_value[0] == ' ') { + possible_value.remove_prefix(1); + } + parseState = this->StoreCall(std::string(possible_value), std::forward<CallState>(state)...) ? ParseMode::Valid diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 6225a4a..5473316 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -701,6 +701,10 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item, this->AddTargetItem(lib, tgt); this->AddLibraryRuntimeInfo(lib.Value, tgt); + if (tgt && tgt->GetType() == cmStateEnums::SHARED_LIBRARY && + this->Target->IsDLLPlatform()) { + this->AddRuntimeDLL(tgt); + } } } else { // This is not a CMake target. Use the name given. @@ -728,6 +732,13 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item, void cmComputeLinkInformation::AddSharedDepItem(BT<std::string> const& item, const cmGeneratorTarget* tgt) { + // Record dependencies on DLLs. + if (tgt && tgt->GetType() == cmStateEnums::SHARED_LIBRARY && + this->Target->IsDLLPlatform() && + this->SharedDependencyMode != SharedDepModeLink) { + this->AddRuntimeDLL(tgt); + } + // If dropping shared library dependencies, ignore them. if (this->SharedDependencyMode == SharedDepModeNone) { return; @@ -799,6 +810,14 @@ void cmComputeLinkInformation::AddSharedDepItem(BT<std::string> const& item, } } +void cmComputeLinkInformation::AddRuntimeDLL(cmGeneratorTarget const* tgt) +{ + if (std::find(this->RuntimeDLLs.begin(), this->RuntimeDLLs.end(), tgt) == + this->RuntimeDLLs.end()) { + this->RuntimeDLLs.emplace_back(tgt); + } +} + void cmComputeLinkInformation::ComputeLinkTypeInfo() { // Check whether archives may actually be shared libraries. diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 9fec702..4acb99f 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -64,6 +64,10 @@ public: std::string GetRPathString(bool for_install) const; std::string GetChrpathString() const; std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked() const; + std::vector<cmGeneratorTarget const*> const& GetRuntimeDLLs() const + { + return this->RuntimeDLLs; + } std::string const& GetLibLinkFileFlag() const { @@ -81,6 +85,7 @@ private: void AddItem(BT<std::string> const& item, const cmGeneratorTarget* tgt); void AddSharedDepItem(BT<std::string> const& item, cmGeneratorTarget const* tgt); + void AddRuntimeDLL(cmGeneratorTarget const* tgt); // Output information. ItemVector Items; @@ -89,6 +94,7 @@ private: std::vector<std::string> FrameworkPaths; std::vector<std::string> RuntimeSearchPath; std::set<cmGeneratorTarget const*> SharedLibrariesLinked; + std::vector<cmGeneratorTarget const*> RuntimeDLLs; // Context information. cmGeneratorTarget const* const Target; diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 62bc526..f99592c 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -654,10 +654,10 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (argP1 != newArgs.end() && argP2 != newArgs.end() && this->IsKeyword(keyIS_NEWER_THAN, *argP1)) { int fileIsNewer = 0; - bool success = cmSystemTools::FileTimeCompare( + cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare( arg->GetValue(), (argP2)->GetValue(), &fileIsNewer); this->HandleBinaryOp( - (!success || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg, + (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg, newArgs, argP1, argP2); } diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 6672aa6..5399fd0 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -8,6 +8,7 @@ #include <sstream> #include <utility> +#include <cm/string_view> #include <cmext/string_view> #include "cmsys/Directory.hxx" @@ -217,6 +218,7 @@ std::string const kCMAKE_POSITION_INDEPENDENT_CODE = std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT"; std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE"; std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK"; +std::string const kCMAKE_ARMClang_CMP0123 = "CMAKE_ARMClang_CMP0123"; std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES = "CMAKE_TRY_COMPILE_OSX_ARCHITECTURES"; std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = @@ -552,6 +554,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, fprintf(fout, "cmake_policy(SET CMP0104 OLD)\n"); } + /* Set ARMClang cpu/arch policy to match outer project. */ + if (cmProp cmp0123 = + this->Makefile->GetDefinition(kCMAKE_ARMClang_CMP0123)) { + fprintf(fout, "cmake_policy(SET CMP0123 %s)\n", + *cmp0123 == "NEW"_s ? "NEW" : "OLD"); + } + std::string projectLangs; for (std::string const& li : testLangs) { projectLangs += " " + li; @@ -1015,17 +1024,21 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir) // cannot delete them immediately. Try a few times. cmSystemTools::WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry(); - while (!cmSystemTools::RemoveFile(fullPath) && --retry.Count && - cmSystemTools::FileExists(fullPath)) { + cmsys::Status status; + while (!((status = cmSystemTools::RemoveFile(fullPath))) && + --retry.Count && cmSystemTools::FileExists(fullPath)) { cmSystemTools::Delay(retry.Delay); } if (retry.Count == 0) #else - if (!cmSystemTools::RemoveFile(fullPath)) + cmsys::Status status = cmSystemTools::RemoveFile(fullPath); + if (!status) #endif { - std::string m = "Remove failed on file: " + fullPath; - cmSystemTools::ReportLastSystemError(m.c_str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The file:\n ", fullPath, + "\ncould not be removed:\n ", status.GetString())); } } } diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx index 3001ae0..a2fac73 100644 --- a/Source/cmCreateTestSourceList.cxx +++ b/Source/cmCreateTestSourceList.cxx @@ -90,10 +90,15 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args, std::replace(func_name.begin(), func_name.end(), ' ', '_'); std::replace(func_name.begin(), func_name.end(), '/', '_'); std::replace(func_name.begin(), func_name.end(), ':', '_'); + bool already_declared = + std::find(tests_func_name.begin(), tests_func_name.end(), func_name) != + tests_func_name.end(); tests_func_name.push_back(func_name); - forwardDeclareCode += "int "; - forwardDeclareCode += func_name; - forwardDeclareCode += "(int, char*[]);\n"; + if (!already_declared) { + forwardDeclareCode += "int "; + forwardDeclareCode += func_name; + forwardDeclareCode += "(int, char*[]);\n"; + } } std::string functionMapCode; diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 4329caf..1054beb 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -139,11 +139,21 @@ std::vector<std::string> EvaluateOutputs(std::vector<std::string> const& paths, } return outputs; } + +std::string EvaluateDepfile(std::string const& path, + cmGeneratorExpression const& ge, + cmLocalGenerator* lg, std::string const& config) +{ + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(path); + return cge->Evaluate(lg, config); +} } cmCustomCommandGenerator::cmCustomCommandGenerator( cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg, - bool transformDepfile, cm::optional<std::string> crossConfig) + bool transformDepfile, cm::optional<std::string> crossConfig, + std::function<std::string(const std::string&, const std::string&)> + computeInternalDepfile) : CC(&cc) , OutputConfig(crossConfig ? *crossConfig : config) , CommandConfig(std::move(config)) @@ -151,7 +161,15 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( , OldStyle(cc.GetEscapeOldStyle()) , MakeVars(cc.GetEscapeAllowMakeVars()) , EmulatorsWithArguments(cc.GetCommandLines().size()) + , ComputeInternalDepfile(std::move(computeInternalDepfile)) { + if (!this->ComputeInternalDepfile) { + this->ComputeInternalDepfile = + [this](const std::string& cfg, const std::string& file) -> std::string { + return this->GetInternalDepfileName(cfg, file); + }; + } + cmGeneratorExpression ge(cc.GetBacktrace()); const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines(); @@ -208,6 +226,9 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( case cmDepfileFormat::VsTlog: argv.emplace_back("vstlog"); break; + case cmDepfileFormat::MakeDepfile: + argv.emplace_back("makedepfile"); + break; } argv.push_back(this->LG->GetSourceDirectory()); argv.push_back(this->LG->GetCurrentSourceDirectory()); @@ -381,9 +402,20 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, } } +std::string cmCustomCommandGenerator::GetDepfile() const +{ + const auto& depfile = this->CC->GetDepfile(); + if (depfile.empty()) { + return ""; + } + + cmGeneratorExpression ge(this->CC->GetBacktrace()); + return EvaluateDepfile(depfile, ge, this->LG, this->OutputConfig); +} + std::string cmCustomCommandGenerator::GetFullDepfile() const { - std::string depfile = this->CC->GetDepfile(); + std::string depfile = this->GetDepfile(); if (depfile.empty()) { return ""; } @@ -394,17 +426,14 @@ std::string cmCustomCommandGenerator::GetFullDepfile() const return cmSystemTools::CollapseFullPath(depfile); } -std::string cmCustomCommandGenerator::GetInternalDepfile() const +std::string cmCustomCommandGenerator::GetInternalDepfileName( + const std::string& /*config*/, const std::string& depfile) { - std::string depfile = this->GetFullDepfile(); - if (depfile.empty()) { - return ""; - } - cmCryptoHash hash(cmCryptoHash::AlgoSHA256); std::string extension; switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) { case cmDepfileFormat::GccDepfile: + case cmDepfileFormat::MakeDepfile: extension = ".d"; break; case cmDepfileFormat::VsTlog: @@ -415,6 +444,16 @@ std::string cmCustomCommandGenerator::GetInternalDepfile() const hash.HashString(depfile), extension); } +std::string cmCustomCommandGenerator::GetInternalDepfile() const +{ + std::string depfile = this->GetFullDepfile(); + if (depfile.empty()) { + return ""; + } + + return this->ComputeInternalDepfile(this->OutputConfig, depfile); +} + const char* cmCustomCommandGenerator::GetComment() const { return this->CC->GetComment(); diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 4be5b3f..e70909a 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <functional> #include <set> #include <string> #include <utility> @@ -19,6 +20,8 @@ class cmLocalGenerator; class cmCustomCommandGenerator { + std::string GetInternalDepfileName(const std::string&, const std::string&); + cmCustomCommand const* CC; std::string OutputConfig; std::string CommandConfig; @@ -32,15 +35,19 @@ class cmCustomCommandGenerator std::vector<std::string> Depends; std::string WorkingDirectory; std::set<BT<std::pair<std::string, bool>>> Utilities; + std::function<std::string(const std::string&, const std::string&)> + ComputeInternalDepfile; void FillEmulatorsWithArguments(); std::vector<std::string> GetCrossCompilingEmulator(unsigned int c) const; const char* GetArgv0Location(unsigned int c) const; public: - cmCustomCommandGenerator(cmCustomCommand const& cc, std::string config, - cmLocalGenerator* lg, bool transformDepfile = true, - cm::optional<std::string> crossConfig = {}); + cmCustomCommandGenerator( + cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg, + bool transformDepfile = true, cm::optional<std::string> crossConfig = {}, + std::function<std::string(const std::string&, const std::string&)> + computeInternalDepfile = {}); cmCustomCommandGenerator(const cmCustomCommandGenerator&) = delete; cmCustomCommandGenerator(cmCustomCommandGenerator&&) = default; cmCustomCommandGenerator& operator=(const cmCustomCommandGenerator&) = @@ -57,6 +64,7 @@ public: std::vector<std::string> const& GetDepends() const; std::set<BT<std::pair<std::string, bool>>> const& GetUtilities() const; bool HasOnlyEmptyCommandLines() const; + std::string GetDepfile() const; std::string GetFullDepfile() const; std::string GetInternalDepfile() const; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 7015a01..0409f97 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -924,13 +924,13 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) // Isolate the file policy level. // Support CMake versions as far back as 2.6 but also support using NEW - // policy settings for up to CMake 3.18 (this upper limit may be reviewed + // policy settings for up to CMake 3.19 (this upper limit may be reviewed // and increased from time to time). This reduces the opportunity for CMake // warnings when an older export file is later used with newer CMake // versions. /* clang-format off */ os << "cmake_policy(PUSH)\n" - << "cmake_policy(VERSION 2.6...3.18)\n"; + << "cmake_policy(VERSION 2.6...3.19)\n"; /* clang-format on */ } diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index ccfd727..5fbbef7 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -655,7 +655,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const xml.EndElement(); // extension } else { std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME"); - if (systemName == "CYGWIN") { + if (systemName == "CYGWIN" || systemName == "MSYS") { xml.StartElement("extension"); xml.Attribute("id", "org.eclipse.cdt.core.Cygwin_PE"); xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser"); diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index a92f6e3..52965bb 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -435,7 +435,8 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes( lg->GetIncludeDirectories(includes, target, language, config); std::string includesString = - lg->GetIncludeFlags(includes, target, language, true, false, config); + lg->GetIncludeFlags(includes, target, language, config, false, + cmLocalGenerator::IncludePathStyle::Absolute); return includesString; } diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx index d2a9bec..d529f52 100644 --- a/Source/cmFileAPI.cxx +++ b/Source/cmFileAPI.cxx @@ -686,7 +686,7 @@ std::string cmFileAPI::NoSupportedVersion( // The "codemodel" object kind. -static unsigned int const CodeModelV2Minor = 2; +static unsigned int const CodeModelV2Minor = 3; void cmFileAPI::BuildClientRequestCodeModel( ClientRequest& r, std::vector<RequestVersion> const& versions) diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 9061109..6b8757c 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -20,11 +20,16 @@ #include <cm3p/json/value.h> #include "cmCryptoHash.h" +#include "cmExportSet.h" #include "cmFileAPI.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmInstallDirectoryGenerator.h" +#include "cmInstallExportGenerator.h" +#include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" +#include "cmInstallScriptGenerator.h" #include "cmInstallSubdirectoryGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" @@ -42,81 +47,13 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" +#include "cmTargetExport.h" #include "cmake.h" namespace { -class Codemodel -{ - cmFileAPI& FileAPI; - unsigned long Version; - - Json::Value DumpPaths(); - Json::Value DumpConfigurations(); - Json::Value DumpConfiguration(std::string const& config); - -public: - Codemodel(cmFileAPI& fileAPI, unsigned long version); - Json::Value Dump(); -}; - -class CodemodelConfig -{ - cmFileAPI& FileAPI; - unsigned long Version; - std::string const& Config; - std::string TopSource; - std::string TopBuild; - - struct Directory - { - cmStateSnapshot Snapshot; - cmLocalGenerator const* LocalGenerator = nullptr; - Json::Value TargetIndexes = Json::arrayValue; - Json::ArrayIndex ProjectIndex; - bool HasInstallRule = false; - }; - std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder> - DirectoryMap; - std::vector<Directory> Directories; - - struct Project - { - cmStateSnapshot Snapshot; - static const Json::ArrayIndex NoParentIndex = - static_cast<Json::ArrayIndex>(-1); - Json::ArrayIndex ParentIndex = NoParentIndex; - Json::Value ChildIndexes = Json::arrayValue; - Json::Value DirectoryIndexes = Json::arrayValue; - Json::Value TargetIndexes = Json::arrayValue; - }; - std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder> - ProjectMap; - std::vector<Project> Projects; - - void ProcessDirectories(); - - Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg); - Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s); - - Json::ArrayIndex AddProject(cmStateSnapshot s); - - Json::Value DumpTargets(); - Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti); - - Json::Value DumpDirectories(); - Json::Value DumpDirectory(Directory& d); - - Json::Value DumpProjects(); - Json::Value DumpProject(Project& p); - - Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s); - -public: - CodemodelConfig(cmFileAPI& fileAPI, unsigned long version, - std::string const& config); - Json::Value Dump(); -}; +using TargetIndexMapType = + std::unordered_map<cmGeneratorTarget const*, Json::ArrayIndex>; std::string RelativeIfUnder(std::string const& top, std::string const& in) { @@ -131,16 +68,6 @@ std::string RelativeIfUnder(std::string const& top, std::string const& in) return out; } -std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild) -{ - cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256); - std::string path = RelativeIfUnder( - topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory()); - std::string hash = hasher.HashString(path); - hash.resize(20, '0'); - return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash; -} - class JBTIndex { public: @@ -290,6 +217,91 @@ Json::Value BacktraceData::Dump() return backtraceGraph; } +class Codemodel +{ + cmFileAPI& FileAPI; + unsigned long Version; + + Json::Value DumpPaths(); + Json::Value DumpConfigurations(); + Json::Value DumpConfiguration(std::string const& config); + +public: + Codemodel(cmFileAPI& fileAPI, unsigned long version); + Json::Value Dump(); +}; + +class CodemodelConfig +{ + cmFileAPI& FileAPI; + unsigned long Version; + std::string const& Config; + std::string TopSource; + std::string TopBuild; + + struct Directory + { + cmStateSnapshot Snapshot; + cmLocalGenerator const* LocalGenerator = nullptr; + Json::Value TargetIndexes = Json::arrayValue; + Json::ArrayIndex ProjectIndex; + bool HasInstallRule = false; + }; + std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder> + DirectoryMap; + std::vector<Directory> Directories; + + struct Project + { + cmStateSnapshot Snapshot; + static const Json::ArrayIndex NoParentIndex = + static_cast<Json::ArrayIndex>(-1); + Json::ArrayIndex ParentIndex = NoParentIndex; + Json::Value ChildIndexes = Json::arrayValue; + Json::Value DirectoryIndexes = Json::arrayValue; + Json::Value TargetIndexes = Json::arrayValue; + }; + std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder> + ProjectMap; + std::vector<Project> Projects; + + TargetIndexMapType TargetIndexMap; + + void ProcessDirectories(); + + Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg); + Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s); + + Json::ArrayIndex AddProject(cmStateSnapshot s); + + Json::Value DumpTargets(); + Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti); + + Json::Value DumpDirectories(); + Json::Value DumpDirectory(Directory& d); + Json::Value DumpDirectoryObject(Directory& d); + + Json::Value DumpProjects(); + Json::Value DumpProject(Project& p); + + Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s); + +public: + CodemodelConfig(cmFileAPI& fileAPI, unsigned long version, + std::string const& config); + Json::Value Dump(); +}; + +std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild) +{ + cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256); + std::string path = RelativeIfUnder( + topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory()); + std::string hash = hasher.HashString(path); + hash.resize(20, '0'); + return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash; +} + struct CompileData { struct IncludeEntry @@ -367,6 +379,31 @@ struct hash<CompileData> } // namespace std namespace { +class DirectoryObject +{ + cmLocalGenerator const* LG = nullptr; + std::string const& Config; + TargetIndexMapType& TargetIndexMap; + std::string TopSource; + std::string TopBuild; + BacktraceData Backtraces; + + void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt); + + Json::Value DumpPaths(); + Json::Value DumpInstallers(); + Json::Value DumpInstaller(cmInstallGenerator* gen); + Json::Value DumpInstallerExportTargets(cmExportSet* exp); + Json::Value DumpInstallerPath(std::string const& top, + std::string const& fromPathIn, + std::string const& toPath); + +public: + DirectoryObject(cmLocalGenerator const* lg, std::string const& config, + TargetIndexMapType& targetIndexMap); + Json::Value Dump(); +}; + class Target { cmGeneratorTarget* GT; @@ -663,6 +700,8 @@ Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt, target["projectIndex"] = pi; this->Projects[pi].TargetIndexes.append(ti); + this->TargetIndexMap[gt] = ti; + return target; } @@ -677,7 +716,7 @@ Json::Value CodemodelConfig::DumpDirectories() Json::Value CodemodelConfig::DumpDirectory(Directory& d) { - Json::Value directory = Json::objectValue; + Json::Value directory = this->DumpDirectoryObject(d); std::string sourceDir = d.Snapshot.GetDirectory().GetCurrentSource(); directory["source"] = RelativeIfUnder(this->TopSource, sourceDir); @@ -717,6 +756,31 @@ Json::Value CodemodelConfig::DumpDirectory(Directory& d) return directory; } +Json::Value CodemodelConfig::DumpDirectoryObject(Directory& d) +{ + std::string prefix = "directory"; + std::string sourceDirRel = RelativeIfUnder( + this->TopSource, d.Snapshot.GetDirectory().GetCurrentSource()); + std::string buildDirRel = RelativeIfUnder( + this->TopBuild, d.Snapshot.GetDirectory().GetCurrentBinary()); + if (!cmSystemTools::FileIsFullPath(buildDirRel)) { + prefix = cmStrCat(prefix, '-', buildDirRel); + } else if (!cmSystemTools::FileIsFullPath(sourceDirRel)) { + prefix = cmStrCat(prefix, '-', sourceDirRel); + } + for (char& c : prefix) { + if (c == '/' || c == '\\') { + c = '.'; + } + } + if (!this->Config.empty()) { + prefix += "-" + this->Config; + } + + DirectoryObject dir(d.LocalGenerator, this->Config, this->TargetIndexMap); + return this->FileAPI.MaybeJsonFile(dir.Dump(), prefix); +} + Json::Value CodemodelConfig::DumpProjects() { Json::Value projects = Json::arrayValue; @@ -760,6 +824,246 @@ Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s) return minimumCMakeVersion; } +DirectoryObject::DirectoryObject(cmLocalGenerator const* lg, + std::string const& config, + TargetIndexMapType& targetIndexMap) + : LG(lg) + , Config(config) + , TargetIndexMap(targetIndexMap) + , TopSource(lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory()) + , TopBuild( + lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory()) + , Backtraces(this->TopSource) +{ +} + +Json::Value DirectoryObject::Dump() +{ + Json::Value directoryObject = Json::objectValue; + directoryObject["paths"] = this->DumpPaths(); + directoryObject["installers"] = this->DumpInstallers(); + directoryObject["backtraceGraph"] = this->Backtraces.Dump(); + return directoryObject; +} + +void DirectoryObject::AddBacktrace(Json::Value& object, + cmListFileBacktrace const& bt) +{ + if (JBTIndex backtrace = this->Backtraces.Add(bt)) { + object["backtrace"] = backtrace.Index; + } +} + +Json::Value DirectoryObject::DumpPaths() +{ + Json::Value paths = Json::objectValue; + + std::string const& sourceDir = this->LG->GetCurrentSourceDirectory(); + paths["source"] = RelativeIfUnder(this->TopSource, sourceDir); + + std::string const& buildDir = this->LG->GetCurrentBinaryDirectory(); + paths["build"] = RelativeIfUnder(this->TopBuild, buildDir); + + return paths; +} + +Json::Value DirectoryObject::DumpInstallers() +{ + Json::Value installers = Json::arrayValue; + for (const auto& gen : this->LG->GetMakefile()->GetInstallGenerators()) { + Json::Value installer = this->DumpInstaller(gen.get()); + if (!installer.empty()) { + installers.append(std::move(installer)); // NOLINT(*) + } + } + return installers; +} + +Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) +{ + Json::Value installer = Json::objectValue; + + // Exclude subdirectory installers. They are implementation details. + if (dynamic_cast<cmInstallSubdirectoryGenerator*>(gen)) { + return installer; + } + + // Exclude installers not used in this configuration. + if (!gen->InstallsForConfig(this->Config)) { + return installer; + } + + // Add fields specific to each kind of install generator. + if (auto* installTarget = dynamic_cast<cmInstallTargetGenerator*>(gen)) { + cmInstallTargetGenerator::Files const& files = + installTarget->GetFiles(this->Config); + if (files.From.empty()) { + return installer; + } + + installer["type"] = "target"; + installer["destination"] = installTarget->GetDestination(this->Config); + installer["targetId"] = + TargetId(installTarget->GetTarget(), this->TopBuild); + installer["targetIndex"] = + this->TargetIndexMap[installTarget->GetTarget()]; + + std::string fromDir = files.FromDir; + if (!fromDir.empty()) { + fromDir.push_back('/'); + } + + std::string toDir = files.ToDir; + if (!toDir.empty()) { + toDir.push_back('/'); + } + + Json::Value paths = Json::arrayValue; + for (size_t i = 0; i < files.From.size(); ++i) { + std::string const& fromPath = cmStrCat(fromDir, files.From[i]); + std::string const& toPath = cmStrCat(toDir, files.To[i]); + paths.append(this->DumpInstallerPath(this->TopBuild, fromPath, toPath)); + } + installer["paths"] = std::move(paths); + + if (installTarget->GetOptional()) { + installer["isOptional"] = true; + } + + if (installTarget->IsImportLibrary()) { + installer["targetIsImportLibrary"] = true; + } + + switch (files.NamelinkMode) { + case cmInstallTargetGenerator::NamelinkModeNone: + break; + case cmInstallTargetGenerator::NamelinkModeOnly: + installer["targetInstallNamelink"] = "only"; + break; + case cmInstallTargetGenerator::NamelinkModeSkip: + installer["targetInstallNamelink"] = "skip"; + break; + } + + // FIXME: Parse FilePermissions to provide structured information. + // FIXME: Thread EXPORT name through from install() call. + } else if (auto* installFiles = + dynamic_cast<cmInstallFilesGenerator*>(gen)) { + std::vector<std::string> const& files = + installFiles->GetFiles(this->Config); + if (files.empty()) { + return installer; + } + + installer["type"] = "file"; + installer["destination"] = installFiles->GetDestination(this->Config); + Json::Value paths = Json::arrayValue; + std::string const& rename = installFiles->GetRename(this->Config); + if (!rename.empty() && files.size() == 1) { + paths.append(this->DumpInstallerPath(this->TopSource, files[0], rename)); + } else { + for (std::string const& file : installFiles->GetFiles(this->Config)) { + paths.append(RelativeIfUnder(this->TopSource, file)); + } + } + installer["paths"] = std::move(paths); + if (installFiles->GetOptional()) { + installer["isOptional"] = true; + } + // FIXME: Parse FilePermissions to provide structured information. + } else if (auto* installDir = + dynamic_cast<cmInstallDirectoryGenerator*>(gen)) { + std::vector<std::string> const& dirs = + installDir->GetDirectories(this->Config); + if (dirs.empty()) { + return installer; + } + + installer["type"] = "directory"; + installer["destination"] = installDir->GetDestination(this->Config); + Json::Value paths = Json::arrayValue; + for (std::string const& dir : dirs) { + if (cmHasLiteralSuffix(dir, "/")) { + paths.append(this->DumpInstallerPath( + this->TopSource, dir.substr(0, dir.size() - 1), ".")); + } else { + paths.append(this->DumpInstallerPath( + this->TopSource, dir, cmSystemTools::GetFilenameName(dir))); + } + } + installer["paths"] = std::move(paths); + if (installDir->GetOptional()) { + installer["isOptional"] = true; + } + // FIXME: Parse FilePermissions, DirPermissions, and LiteralArguments. + // to provide structured information. + } else if (auto* installExport = + dynamic_cast<cmInstallExportGenerator*>(gen)) { + installer["type"] = "export"; + installer["destination"] = installExport->GetDestination(); + cmExportSet* exportSet = installExport->GetExportSet(); + installer["exportName"] = exportSet->GetName(); + installer["exportTargets"] = this->DumpInstallerExportTargets(exportSet); + Json::Value paths = Json::arrayValue; + paths.append( + RelativeIfUnder(this->TopBuild, installExport->GetMainImportFile())); + installer["paths"] = std::move(paths); + } else if (auto* installScript = + dynamic_cast<cmInstallScriptGenerator*>(gen)) { + if (installScript->IsCode()) { + installer["type"] = "code"; + } else { + installer["type"] = "script"; + installer["scriptFile"] = RelativeIfUnder( + this->TopSource, installScript->GetScript(this->Config)); + } + } + + // Add fields common to all install generators. + installer["component"] = gen->GetComponent(); + if (gen->GetExcludeFromAll()) { + installer["isExcludeFromAll"] = true; + } + this->AddBacktrace(installer, gen->GetBacktrace()); + + return installer; +} + +Json::Value DirectoryObject::DumpInstallerExportTargets(cmExportSet* exp) +{ + Json::Value targets = Json::arrayValue; + for (auto const& targetExport : exp->GetTargetExports()) { + Json::Value target = Json::objectValue; + target["id"] = TargetId(targetExport->Target, this->TopBuild); + target["index"] = this->TargetIndexMap[targetExport->Target]; + targets.append(std::move(target)); // NOLINT(*) + } + return targets; +} + +Json::Value DirectoryObject::DumpInstallerPath(std::string const& top, + std::string const& fromPathIn, + std::string const& toPath) +{ + Json::Value installPath; + + std::string fromPath = RelativeIfUnder(top, fromPathIn); + + // If toPath is the last component of fromPath, use just fromPath. + if (toPath.find_first_of('/') == std::string::npos && + cmHasSuffix(fromPath, toPath) && + (fromPath.size() == toPath.size() || + fromPath[fromPath.size() - toPath.size() - 1] == '/')) { + installPath = fromPath; + } else { + installPath = Json::objectValue; + installPath["from"] = fromPath; + installPath["to"] = toPath; + } + + return installPath; +} + Target::Target(cmGeneratorTarget* gt, std::string const& config) : GT(gt) , Config(config) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 4a28238..1088347 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1246,9 +1246,12 @@ bool HandleRealPathCommand(std::vector<std::string> const& args, struct Arguments { std::string BaseDirectory; + bool ExpandTilde = false; }; - static auto const parser = cmArgumentParser<Arguments>{}.Bind( - "BASE_DIRECTORY"_s, &Arguments::BaseDirectory); + static auto const parser = + cmArgumentParser<Arguments>{} + .Bind("BASE_DIRECTORY"_s, &Arguments::BaseDirectory) + .Bind("EXPAND_TILDE"_s, &Arguments::ExpandTilde); std::vector<std::string> unparsedArguments; std::vector<std::string> keywordsMissingValue; @@ -1270,7 +1273,21 @@ bool HandleRealPathCommand(std::vector<std::string> const& args, arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory(); } - cmCMakePath path(args[1]); + auto input = args[1]; + if (arguments.ExpandTilde && !input.empty()) { + if (input[0] == '~' && (input.length() == 1 || input[1] == '/')) { + std::string home; + if ( +#if defined(_WIN32) && !defined(__CYGWIN__) + cmSystemTools::GetEnv("USERPROFILE", home) || +#endif + cmSystemTools::GetEnv("HOME", home)) { + input.replace(0, 1, home); + } + } + } + + cmCMakePath path(input, cmCMakePath::auto_format); path = path.Absolute(arguments.BaseDirectory).Normal(); auto realPath = cmSystemTools::GetRealPath(path.GenericString()); @@ -1313,8 +1330,9 @@ bool HandleRelativePathCommand(std::vector<std::string> const& args, bool HandleRename(std::vector<std::string> const& args, cmExecutionStatus& status) { - if (args.size() != 3) { - status.SetError("RENAME given incorrect number of arguments."); + if (args.size() < 3) { + status.SetError("RENAME must be called with at least two additional " + "arguments"); return false; } @@ -1330,21 +1348,148 @@ bool HandleRename(std::vector<std::string> const& args, cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]); } - if (!cmSystemTools::RenameFile(oldname, newname)) { - std::string err = cmSystemTools::GetLastSystemError(); - status.SetError(cmStrCat("RENAME failed to rename\n ", oldname, - "\nto\n ", newname, "\nbecause: ", err, "\n")); + struct Arguments + { + bool NoReplace = false; + std::string Result; + }; + + static auto const parser = cmArgumentParser<Arguments>{} + .Bind("NO_REPLACE"_s, &Arguments::NoReplace) + .Bind("RESULT"_s, &Arguments::Result); + + std::vector<std::string> unconsumedArgs; + Arguments const arguments = + parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs); + if (!unconsumedArgs.empty()) { + status.SetError("RENAME unknown argument:\n " + unconsumedArgs.front()); return false; } - return true; + + std::string err; + switch (cmSystemTools::RenameFile(oldname, newname, + arguments.NoReplace + ? cmSystemTools::Replace::No + : cmSystemTools::Replace::Yes, + &err)) { + case cmSystemTools::RenameResult::Success: + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, "0"); + } + return true; + case cmSystemTools::RenameResult::NoReplace: + if (!arguments.Result.empty()) { + err = "NO_REPLACE"; + } else { + err = "path not replaced"; + } + CM_FALLTHROUGH; + case cmSystemTools::RenameResult::Failure: + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, err); + return true; + } + break; + } + status.SetError(cmStrCat("RENAME failed to rename\n ", oldname, "\nto\n ", + newname, "\nbecause: ", err, "\n")); + return false; } -bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse, - cmExecutionStatus& status) +bool HandleCopyFile(std::vector<std::string> const& args, + cmExecutionStatus& status) { + if (args.size() < 3) { + status.SetError("COPY_FILE must be called with at least two additional " + "arguments"); + return false; + } - std::string message; + // Compute full path for old and new names. + std::string oldname = args[1]; + if (!cmsys::SystemTools::FileIsFullPath(oldname)) { + oldname = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]); + } + std::string newname = args[2]; + if (!cmsys::SystemTools::FileIsFullPath(newname)) { + newname = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]); + } + + struct Arguments + { + bool OnlyIfDifferent = false; + std::string Result; + }; + + static auto const parser = + cmArgumentParser<Arguments>{} + .Bind("ONLY_IF_DIFFERENT"_s, &Arguments::OnlyIfDifferent) + .Bind("RESULT"_s, &Arguments::Result); + + std::vector<std::string> unconsumedArgs; + Arguments const arguments = + parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs); + if (!unconsumedArgs.empty()) { + status.SetError("COPY_FILE unknown argument:\n " + + unconsumedArgs.front()); + return false; + } + + bool result = true; + if (cmsys::SystemTools::FileIsDirectory(oldname)) { + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, + "cannot copy a directory"); + } else { + status.SetError( + cmStrCat("COPY_FILE cannot copy a directory\n ", oldname)); + result = false; + } + return result; + } + if (cmsys::SystemTools::FileIsDirectory(newname)) { + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, + "cannot copy to a directory"); + } else { + status.SetError( + cmStrCat("COPY_FILE cannot copy to a directory\n ", newname)); + result = false; + } + return result; + } + cmSystemTools::CopyWhen when; + if (arguments.OnlyIfDifferent) { + when = cmSystemTools::CopyWhen::OnlyIfDifferent; + } else { + when = cmSystemTools::CopyWhen::Always; + } + + std::string err; + if (cmSystemTools::CopySingleFile(oldname, newname, when, &err) == + cmSystemTools::CopyResult::Success) { + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, "0"); + } + } else { + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, err); + } else { + status.SetError(cmStrCat("COPY_FILE failed to copy\n ", oldname, + "\nto\n ", newname, "\nbecause: ", err, "\n")); + result = false; + } + } + + return result; +} + +bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse, + cmExecutionStatus& status) +{ for (std::string const& arg : cmMakeRange(args).advance(1)) // Get rid of subcommand { @@ -2818,16 +2963,21 @@ bool HandleCreateLinkCommand(std::vector<std::string> const& args, // Check if the command requires a symbolic link. if (arguments.Symbolic) { - completed = cmSystemTools::CreateSymlink(fileName, newFileName, &result); + completed = static_cast<bool>( + cmSystemTools::CreateSymlink(fileName, newFileName, &result)); } else { - completed = cmSystemTools::CreateLink(fileName, newFileName, &result); + completed = static_cast<bool>( + cmSystemTools::CreateLink(fileName, newFileName, &result)); } // Check if copy-on-error is enabled in the arguments. if (!completed && arguments.CopyOnError) { - completed = cmsys::SystemTools::CopyFileAlways(fileName, newFileName); - if (!completed) { - result = "Copy failed: " + cmSystemTools::GetLastSystemError(); + cmsys::Status copied = + cmsys::SystemTools::CopyFileAlways(fileName, newFileName); + if (copied) { + completed = true; + } else { + result = "Copy failed: " + copied.GetString(); } } @@ -3569,6 +3719,7 @@ bool cmFileCommand(std::vector<std::string> const& args, { "GLOB_RECURSE"_s, HandleGlobRecurseCommand }, { "MAKE_DIRECTORY"_s, HandleMakeDirectoryCommand }, { "RENAME"_s, HandleRename }, + { "COPY_FILE"_s, HandleCopyFile }, { "REMOVE"_s, HandleRemove }, { "REMOVE_RECURSE"_s, HandleRemoveRecurse }, { "COPY"_s, HandleCopyCommand }, diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 49b1bd7..d85ba8f 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -374,7 +374,7 @@ void cmFindLibraryHelper::AddName(std::string const& name) regex += "(\\.[0-9]+\\.[0-9]+)?"; } regex += "$"; - entry.Regex.compile(regex.c_str()); + entry.Regex.compile(regex); this->Names.push_back(std::move(entry)); } diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index bcacb15..4845a6d 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -17,6 +17,7 @@ #include <utility> #include <cm/memory> +#include <cm/optional> #include <cm/string_view> #include <cmext/string_view> @@ -25,7 +26,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" +#include "cmPolicies.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -113,9 +114,11 @@ bool cmForEachFunctionBlocker::ReplayItems( // At end of for each execute recorded commands // store the old value - std::string oldDef; - if (cmProp d = mf.GetDefinition(this->Args.front())) { - oldDef = *d; + cm::optional<std::string> oldDef; + if (mf.GetPolicyStatus(cmPolicies::CMP0124) != cmPolicies::NEW) { + oldDef = mf.GetSafeDefinition(this->Args.front()); + } else if (mf.IsNormalDefinitionSet(this->Args.front())) { + oldDef = *mf.GetDefinition(this->Args.front()); } auto restore = false; @@ -131,9 +134,14 @@ bool cmForEachFunctionBlocker::ReplayItems( } if (restore) { - // restore the variable to its prior value - mf.AddDefinition(this->Args.front(), oldDef); + if (oldDef) { + // restore the variable to its prior value + mf.AddDefinition(this->Args.front(), *oldDef); + } else { + mf.RemoveDefinition(this->Args.front()); + } } + return true; } @@ -185,10 +193,15 @@ bool cmForEachFunctionBlocker::ReplayZipLists( assert("Sanity check" && iterationVars.size() == values.size()); // Store old values for iteration variables - std::map<std::string, std::string> oldDefs; + std::map<std::string, cm::optional<std::string>> oldDefs; for (auto i = 0u; i < values.size(); ++i) { - if (cmProp d = mf.GetDefinition(iterationVars[i])) { - oldDefs.emplace(iterationVars[i], *d); + const auto& varName = iterationVars[i]; + if (mf.GetPolicyStatus(cmPolicies::CMP0124) != cmPolicies::NEW) { + oldDefs.emplace(varName, mf.GetSafeDefinition(varName)); + } else if (mf.IsNormalDefinitionSet(varName)) { + oldDefs.emplace(varName, *mf.GetDefinition(varName)); + } else { + oldDefs.emplace(varName, cm::nullopt); } } @@ -226,7 +239,11 @@ bool cmForEachFunctionBlocker::ReplayZipLists( // Restore the variables to its prior value if (restore) { for (auto const& p : oldDefs) { - mf.AddDefinition(p.first, p.second); + if (p.second) { + mf.AddDefinition(p.first, *p.second); + } else { + mf.RemoveDefinition(p.first); + } } } return true; diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 43f384a..06778b1 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -42,6 +42,11 @@ cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name, #else static_cast<void>(encoding); #endif + if (encoding == codecvt::UTF8_WITH_BOM) { + // Write the BOM encoding header into the file + char magic[] = { char(0xEF), char(0xBB), char(0xBF) }; + this->write(magic, 3); + } } cmGeneratedFileStream::~cmGeneratedFileStream() diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index e40316e..7125170 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -14,6 +14,7 @@ #include <utility> #include <cm/iterator> +#include <cm/optional> #include <cm/string_view> #include <cm/vector> #include <cmext/algorithm> @@ -23,6 +24,7 @@ #include "cmsys/String.h" #include "cmAlgorithms.h" +#include "cmComputeLinkInformation.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionDAGChecker.h" @@ -1627,8 +1629,8 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode type != cmStateEnums::OBJECT_LIBRARY) { std::ostringstream e; e << "Objects of target \"" << tgtName - << "\" referenced but is not an allowed library types (EXECUTABLE, " - << "STATIC, SHARED, MODULE, OBJECT)."; + << "\" referenced but is not one of the allowed target types " + << "(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT)."; reportError(context, content->GetOriginalExpression(), e.str()); return std::string(); } @@ -1687,6 +1689,54 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode } } targetObjectsNode; +static const struct TargetRuntimeDllsNode : public cmGeneratorExpressionNode +{ + TargetRuntimeDllsNode() {} // NOLINT(modernize-use-equals-default) + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override + { + std::string tgtName = parameters.front(); + cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName); + if (!gt) { + std::ostringstream e; + e << "Objects of target \"" << tgtName + << "\" referenced but no such target exists."; + reportError(context, content->GetOriginalExpression(), e.str()); + return std::string(); + } + cmStateEnums::TargetType type = gt->GetType(); + if (type != cmStateEnums::EXECUTABLE && + type != cmStateEnums::SHARED_LIBRARY && + type != cmStateEnums::MODULE_LIBRARY) { + std::ostringstream e; + e << "Objects of target \"" << tgtName + << "\" referenced but is not one of the allowed target types " + << "(EXECUTABLE, SHARED, MODULE)."; + reportError(context, content->GetOriginalExpression(), e.str()); + return std::string(); + } + + if (auto* cli = gt->GetLinkInformation(context->Config)) { + std::vector<std::string> dllPaths; + auto const& dlls = cli->GetRuntimeDLLs(); + + for (auto const& dll : dlls) { + if (auto loc = dll->MaybeGetLocation(context->Config)) { + dllPaths.emplace_back(*loc); + } + } + + return cmJoin(dllPaths, ";"); + } + + return ""; + } +} targetRuntimeDllsNode; + static const struct CompileFeaturesNode : public cmGeneratorExpressionNode { CompileFeaturesNode() {} // NOLINT(modernize-use-equals-default) @@ -2603,6 +2653,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "TARGET_EXISTS", &targetExistsNode }, { "TARGET_NAME_IF_EXISTS", &targetNameIfExistsNode }, { "TARGET_GENEX_EVAL", &targetGenexEvalNode }, + { "TARGET_RUNTIME_DLLS", &targetRuntimeDllsNode }, { "GENEX_EVAL", &genexEvalNode }, { "BUILD_INTERFACE", &buildInterfaceNode }, { "INSTALL_INTERFACE", &installInterfaceNode }, diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index efac06a..365f8b8 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1062,6 +1062,20 @@ const std::string& cmGeneratorTarget::GetLocation( return location; } +cm::optional<std::string> cmGeneratorTarget::MaybeGetLocation( + std::string const& config) const +{ + cm::optional<std::string> location; + if (cmGeneratorTarget::ImportInfo const* imp = this->GetImportInfo(config)) { + if (!imp->Location.empty()) { + location = imp->Location; + } + } else { + location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact); + } + return location; +} + std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreBuildCommands() const { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 8fe70ab..2935e0b 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -14,6 +14,8 @@ #include <utility> #include <vector> +#include <cm/optional> + #include "cmLinkItem.h" #include "cmListFileCache.h" #include "cmPolicies.h" @@ -50,6 +52,9 @@ public: bool CanCompileSources() const; const std::string& GetLocation(const std::string& config) const; + /** Get the full path to the target's main artifact, if known. */ + cm::optional<std::string> MaybeGetLocation(std::string const& config) const; + std::vector<cmCustomCommand> const& GetPreBuildCommands() const; std::vector<cmCustomCommand> const& GetPreLinkCommands() const; std::vector<cmCustomCommand> const& GetPostBuildCommands() const; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index ab76260..55fba79 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2077,7 +2077,7 @@ bool cmGlobalGenerator::Open(const std::string& bindir, std::string cmGlobalGenerator::GenerateCMakeBuildCommand( const std::string& target, const std::string& config, - const std::string& native, bool ignoreErrors) + const std::string& parallel, const std::string& native, bool ignoreErrors) { std::string makeCommand = cmSystemTools::GetCMakeCommand(); makeCommand = @@ -2087,6 +2087,11 @@ std::string cmGlobalGenerator::GenerateCMakeBuildCommand( makeCommand += config; makeCommand += "\""; } + if (!parallel.empty()) { + makeCommand += " --parallel \""; + makeCommand += parallel; + makeCommand += "\""; + } if (!target.empty()) { makeCommand += " --target \""; makeCommand += target; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 590de26..fee0359 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -249,9 +249,13 @@ public: virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const; - /** Generate a "cmake --build" call for a given target and config. */ + /** + * Generate a "cmake --build" call for a given target, config and parallel + * level. + */ std::string GenerateCMakeBuildCommand(const std::string& target, const std::string& config, + const std::string& parallel, const std::string& native, bool ignoreErrors); diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index 36f583f..313f39b 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -2,7 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalNMakeMakefileGenerator.h" +#include "cmsys/RegularExpression.hxx" + #include "cmDocumentationEntry.h" +#include "cmDuration.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmState.h" @@ -34,6 +37,44 @@ void cmGlobalNMakeMakefileGenerator::EnableLanguage( this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } +bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf) +{ + if (!this->cmGlobalGenerator::FindMakeProgram(mf)) { + return false; + } + if (cmProp nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) { + std::vector<std::string> command; + command.emplace_back(*nmakeCommand); + command.emplace_back("-?"); + std::string out; + std::string err; + if (!cmSystemTools::RunSingleCommand(command, &out, &err, nullptr, nullptr, + cmSystemTools::OUTPUT_NONE, + cmDuration(30))) { + mf->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("Running\n '", cmJoin(command, "' '"), + "'\n" + "failed with:\n ", + err)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + cmsys::RegularExpression regex( + "Program Maintenance Utility Version ([1-9][0-9.]+)"); + if (regex.find(err)) { + this->NMakeVersion = regex.match(1); + this->CheckNMakeFeatures(); + } + } + return true; +} + +void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures() +{ + this->NMakeSupportsUTF8 = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NMakeVersion.c_str(), "9"); +} + void cmGlobalNMakeMakefileGenerator::GetDocumentation( cmDocumentationEntry& entry) { diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index abe64ff..402b89f 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -31,7 +31,7 @@ public: /** Get encoding used by generator for makefile files */ codecvt::Encoding GetMakefileEncoding() const override { - return codecvt::ANSI; + return this->NMakeSupportsUTF8 ? codecvt::UTF8_WITH_BOM : codecvt::ANSI; } /** Get the documentation entry for this generator. */ @@ -55,6 +55,11 @@ protected: void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override; private: + bool NMakeSupportsUTF8 = false; + std::string NMakeVersion; + bool FindMakeProgram(cmMakefile* mf) override; + void CheckNMakeFeatures(); + void PrintCompilerAdvice(std::ostream& os, std::string const& lang, const char* envVar) const override; }; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index c502fb8..6937639 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -9,6 +9,7 @@ #include <cm/iterator> #include <cm/memory> +#include <cm/string_view> #include <cmext/algorithm> #include <cmext/memory> @@ -503,14 +504,7 @@ std::unique_ptr<cmLocalGenerator> cmGlobalNinjaGenerator::CreateLocalGenerator( codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const { -#ifdef _WIN32 - // Ninja on Windows does not support non-ANSI characters. - // https://github.com/ninja-build/ninja/issues/1195 - return codecvt::ANSI; -#else - // No encoding conversion needed on other platforms. - return codecvt::None; -#endif + return this->NinjaExpectedEncoding; } void cmGlobalNinjaGenerator::GetDocumentation(cmDocumentationEntry& entry) @@ -732,6 +726,61 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() this->NinjaSupportsMetadataOnRegeneration = !cmSystemTools::VersionCompare( cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), RequiredNinjaVersionForMetadataOnRegeneration().c_str()); +#ifdef _WIN32 + this->NinjaSupportsCodePage = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForCodePage().c_str()); + if (this->NinjaSupportsCodePage) { + this->CheckNinjaCodePage(); + } else { + this->NinjaExpectedEncoding = codecvt::ANSI; + } +#endif +} + +void cmGlobalNinjaGenerator::CheckNinjaCodePage() +{ + std::vector<std::string> command{ this->NinjaCommand, "-t", "wincodepage" }; + std::string output; + std::string error; + int result; + if (!cmSystemTools::RunSingleCommand(command, &output, &error, &result, + nullptr, cmSystemTools::OUTPUT_NONE)) { + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("Running\n '", + cmJoin(command, "' '"), + "'\n" + "failed with:\n ", + error)); + cmSystemTools::SetFatalErrorOccured(); + } else if (result == 0) { + std::istringstream outputStream(output); + std::string line; + bool found = false; + while (cmSystemTools::GetLineFromStream(outputStream, line)) { + if (cmHasLiteralPrefix(line, "Build file encoding: ")) { + cm::string_view lineView(line); + cm::string_view encoding = + lineView.substr(cmStrLen("Build file encoding: ")); + if (encoding == "UTF-8") { + // Ninja expects UTF-8. We use that internally. No conversion needed. + this->NinjaExpectedEncoding = codecvt::None; + } else { + this->NinjaExpectedEncoding = codecvt::ANSI; + } + found = true; + break; + } + } + if (!found) { + this->GetCMakeInstance()->IssueMessage( + MessageType::WARNING, + "Could not determine Ninja's code page, defaulting to UTF-8"); + this->NinjaExpectedEncoding = codecvt::None; + } + } else { + this->NinjaExpectedEncoding = codecvt::ANSI; + } } bool cmGlobalNinjaGenerator::CheckLanguages( diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 0c919ef..9f31708 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -388,6 +388,7 @@ public: { return "1.10.2"; } + static std::string RequiredNinjaVersionForCodePage() { return "1.11"; } bool SupportsConsolePool() const; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; @@ -474,6 +475,7 @@ private: std::string GetEditCacheCommand() const override; bool FindMakeProgram(cmMakefile* mf) override; void CheckNinjaFeatures(); + void CheckNinjaCodePage(); bool CheckLanguages(std::vector<std::string> const& languages, cmMakefile* mf) const override; bool CheckFortran(cmMakefile* mf) const; @@ -568,6 +570,9 @@ private: bool NinjaSupportsUnconditionalRecompactTool = false; bool NinjaSupportsMultipleOutputs = false; bool NinjaSupportsMetadataOnRegeneration = false; + bool NinjaSupportsCodePage = false; + + codecvt::Encoding NinjaExpectedEncoding = codecvt::None; bool DiagnosedCxxModuleSupport = false; diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index badce2e..6c52ce0 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -231,6 +231,23 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( return false; } + if (!this->CustomFlagTableDir.empty() && + !(cmSystemTools::FileIsFullPath(this->CustomFlagTableDir) && + cmSystemTools::FileIsDirectory(this->CustomFlagTableDir))) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset\n" + " customFlagTableDir=" << this->CustomFlagTableDir << "\n" + "that is not an absolute path to an existing directory."; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + if (cmHasLiteralPrefix(this->GetPlatformToolsetString(), "v140")) { // The GenerateDebugInformation link setting for the v140 toolset // in VS 2015 was originally an enum with "No" and "Debug" values, @@ -263,8 +280,8 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( bcDir = this->VCTargetsPath + "/BuildCustomizations"; } else { bcDir = this->GetPlatformToolsetCudaCustomDirString() + - "CUDAVisualStudioIntegration\\extras\\" - "visual_studio_integration\\MSBuildExtensions"; + this->GetPlatformToolsetCudaVSIntegrationSubdirString() + + "extras\\visual_studio_integration\\MSBuildExtensions"; cmSystemTools::ConvertToUnixSlashes(bcDir); } cmsys::Glob gl; @@ -470,11 +487,27 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( if (this->GeneratorToolsetCudaCustomDir.back() != '\\') { this->GeneratorToolsetCudaCustomDir.push_back('\\'); } + /* check for legacy toolkit folder structure */ + if (cmsys::SystemTools::FileIsDirectory( + cmStrCat(this->GeneratorToolsetCudaCustomDir, "nvcc"))) { + this->GeneratorToolsetCudaNvccSubdir = "nvcc\\"; + } + if (cmsys::SystemTools::FileIsDirectory( + cmStrCat(this->GeneratorToolsetCudaCustomDir, + "CUDAVisualStudioIntegration"))) { + this->GeneratorToolsetCudaVSIntegrationSubdir = + "CUDAVisualStudioIntegration\\"; + } } else { this->GeneratorToolsetCuda = value; } return true; } + if (key == "customFlagTableDir") { + this->CustomFlagTableDir = value; + cmSystemTools::ConvertToUnixSlashes(this->CustomFlagTableDir); + return true; + } if (key == "version") { this->GeneratorToolsetVersion = value; return true; @@ -787,6 +820,18 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDirString() const return this->GeneratorToolsetCudaCustomDir; } +std::string const& +cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaNvccSubdirString() const +{ + return this->GeneratorToolsetCudaNvccSubdir; +} + +std::string const& cmGlobalVisualStudio10Generator:: + GetPlatformToolsetCudaVSIntegrationSubdirString() const +{ + return this->GeneratorToolsetCudaVSIntegrationSubdir; +} + cmGlobalVisualStudio10Generator::AuxToolset cmGlobalVisualStudio10Generator::FindAuxToolset(std::string&, std::string&) const @@ -991,6 +1036,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) cmd.push_back(this->GetMSBuildCommand()); cmd.push_back(vcxproj); cmd.push_back("/p:Configuration=Debug"); + cmd.push_back(cmStrCat("/p:Platform=", this->GetPlatformName())); cmd.push_back(std::string("/p:VisualStudioVersion=") + this->GetIDEVersion()); std::string out; @@ -1349,137 +1395,262 @@ static cmIDEFlagTable const* cmLoadFlagTableJson( return ret; } -static std::string cmGetFlagTableName(std::string const& toolsetName, - std::string const& table) +cm::optional<std::string> cmGlobalVisualStudio10Generator::FindFlagTable( + cm::string_view toolsetName, cm::string_view table) const { - return cmSystemTools::GetCMakeRoot() + "/Templates/MSBuild/FlagTables/" + - toolsetName + "_" + table + ".json"; + if (!this->CustomFlagTableDir.empty()) { + std::string customFlagTableFile = + cmStrCat(this->CustomFlagTableDir, '/', this->GetPlatformName(), '_', + toolsetName, '_', table, ".json"); + if (cmSystemTools::FileExists(customFlagTableFile)) { + return customFlagTableFile; + } + customFlagTableFile = + cmStrCat(this->CustomFlagTableDir, '/', this->GetPlatformName(), '_', + table, ".json"); + if (cmSystemTools::FileExists(customFlagTableFile)) { + return customFlagTableFile; + } + } + std::string fullPath = + cmStrCat(cmSystemTools::GetCMakeRoot(), "/Templates/MSBuild/FlagTables/", + toolsetName, '_', table, ".json"); + if (cmSystemTools::FileExists(fullPath)) { + return fullPath; + } + return {}; } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( - std::string const& optionsName, std::string const& toolsetName, - std::string const& defaultName, std::string const& table) const + std::string const& toolSpecificName, std::string const& defaultName, + std::string const& table) const { - cmIDEFlagTable const* ret = nullptr; + cmMakefile* mf = this->GetCurrentMakefile(); std::string filename; - if (!optionsName.empty()) { - filename = cmGetFlagTableName(optionsName, table); - ret = cmLoadFlagTableJson(filename); + if (!toolSpecificName.empty()) { + if (cm::optional<std::string> found = + this->FindFlagTable(toolSpecificName, table)) { + filename = std::move(*found); + } else { + mf->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("JSON flag table for ", table, + " not found for toolset ", toolSpecificName)); + return nullptr; + } } else { - filename = cmGetFlagTableName(toolsetName, table); - if (cmSystemTools::FileExists(filename)) { - ret = cmLoadFlagTableJson(filename); + std::string const& genericName = + this->CanonicalToolsetName(this->GetPlatformToolsetString()); + cm::optional<std::string> found = this->FindFlagTable(genericName, table); + if (!found) { + found = this->FindFlagTable(defaultName, table); + } + if (found) { + filename = std::move(*found); } else { - filename = cmGetFlagTableName(defaultName, table); - ret = cmLoadFlagTableJson(filename); + mf->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("JSON flag table for ", table, + " not found for toolset ", genericName, " ", + defaultName)); + return nullptr; } } - if (!ret) { - cmMakefile* mf = this->GetCurrentMakefile(); - - std::ostringstream e; - /* clang-format off */ - e << "JSON flag table \"" << filename << - "\" could not be loaded.\n"; - /* clang-format on */ - mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + if (cmIDEFlagTable const* ret = cmLoadFlagTableJson(filename)) { + return ret; } - return ret; + + mf->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("JSON flag table could not be loaded:\n ", filename)); + return nullptr; } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetClFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultCLFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "CL"); + return LoadFlagTable(this->GetClFlagTableName(), + this->DefaultCLFlagTableName, "CL"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetCSharpFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultCSharpFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "CSharp"); + return LoadFlagTable(this->GetCSharpFlagTableName(), + this->DefaultCSharpFlagTableName, "CSharp"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetRcFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultRCFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "RC"); + return LoadFlagTable(this->GetRcFlagTableName(), + this->DefaultRCFlagTableName, "RC"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetLibFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultLibFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "LIB"); + return LoadFlagTable(this->GetLibFlagTableName(), + this->DefaultLibFlagTableName, "LIB"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetLinkFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultLinkFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "Link"); + return LoadFlagTable(this->GetLinkFlagTableName(), + this->DefaultLinkFlagTableName, "Link"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const { - std::string toolsetName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultCudaFlagTableName); - return LoadFlagTable("", toolsetName, defaultName, "Cuda"); + return LoadFlagTable(std::string(), this->DefaultCudaFlagTableName, "Cuda"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() const { - std::string toolsetName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultCudaHostFlagTableName); - return LoadFlagTable("", toolsetName, defaultName, "CudaHost"); + return LoadFlagTable(std::string(), this->DefaultCudaHostFlagTableName, + "CudaHost"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetMasmFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultMasmFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "MASM"); + return LoadFlagTable(this->GetMasmFlagTableName(), + this->DefaultMasmFlagTableName, "MASM"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const { - std::string toolsetName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultNasmFlagTableName); - return LoadFlagTable("", toolsetName, defaultName, "NASM"); + return LoadFlagTable(std::string(), this->DefaultNasmFlagTableName, "NASM"); +} + +std::string cmGlobalVisualStudio10Generator::GetClFlagTableName() const +{ + std::string const& toolset = this->GetPlatformToolsetString(); + std::string const useToolset = this->CanonicalToolsetName(toolset); + + if (toolset == "v142") { + return "v142"; + } else if (toolset == "v141") { + return "v141"; + } else if (useToolset == "v140") { + return "v140"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName() const +{ + std::string const& toolset = this->GetPlatformToolsetString(); + std::string const useToolset = this->CanonicalToolsetName(toolset); + + if (useToolset == "v142") { + return "v142"; + } else if (useToolset == "v141") { + return "v141"; + } else if (useToolset == "v140") { + return "v140"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName() const +{ + std::string const& toolset = this->GetPlatformToolsetString(); + std::string const useToolset = this->CanonicalToolsetName(toolset); + + if ((useToolset == "v140") || (useToolset == "v141") || + (useToolset == "v142")) { + return "v14"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName() const +{ + std::string const& toolset = this->GetPlatformToolsetString(); + std::string const useToolset = this->CanonicalToolsetName(toolset); + + if ((useToolset == "v140") || (useToolset == "v141") || + (useToolset == "v142")) { + return "v14"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName() const +{ + std::string const& toolset = this->GetPlatformToolsetString(); + std::string const useToolset = this->CanonicalToolsetName(toolset); + + if (useToolset == "v142") { + return "v142"; + } else if (useToolset == "v141") { + return "v141"; + } else if (useToolset == "v140") { + return "v140"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName() const +{ + std::string const& toolset = this->GetPlatformToolsetString(); + std::string const useToolset = this->CanonicalToolsetName(toolset); + + if ((useToolset == "v140") || (useToolset == "v141") || + (useToolset == "v142")) { + return "v14"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::CanonicalToolsetName( + std::string const& toolset) const +{ + std::size_t length = toolset.length(); + + if (cmHasLiteralSuffix(toolset, "_xp")) { + length -= 3; + } + + return toolset.substr(0, length); } diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 8d30ef8..2596720 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -5,8 +5,10 @@ #include <memory> #include <set> +#include <cm/optional> +#include <cm/string_view> + #include "cmGlobalVisualStudio8Generator.h" -#include "cmVisualStudio10ToolsetOptions.h" /** \class cmGlobalVisualStudio10Generator * \brief Write a Unix makefiles. @@ -76,6 +78,13 @@ public: const char* GetPlatformToolsetCudaCustomDir() const; std::string const& GetPlatformToolsetCudaCustomDirString() const; + /** The nvcc subdirectory of a custom cuda install directory */ + std::string const& GetPlatformToolsetCudaNvccSubdirString() const; + + /** The visual studio integration subdirectory of a custom cuda install + * directory */ + std::string const& GetPlatformToolsetCudaVSIntegrationSubdirString() const; + /** Return whether we need to use No/Debug instead of false/true for GenerateDebugInformation. */ bool GetPlatformToolsetNeedsDebugEnum() const @@ -176,8 +185,7 @@ protected: std::string const& GetMSBuildCommand(); - cmIDEFlagTable const* LoadFlagTable(std::string const& optionsName, - std::string const& toolsetName, + cmIDEFlagTable const* LoadFlagTable(std::string const& toolSpecificName, std::string const& defaultName, std::string const& table) const; @@ -187,6 +195,8 @@ protected: std::string GeneratorToolsetCustomVCTargetsDir; std::string GeneratorToolsetCuda; std::string GeneratorToolsetCudaCustomDir; + std::string GeneratorToolsetCudaNvccSubdir; + std::string GeneratorToolsetCudaVSIntegrationSubdir; std::string DefaultPlatformToolset; std::string DefaultPlatformToolsetHostArchitecture; std::string DefaultAndroidToolset; @@ -230,7 +240,6 @@ private: std::string MSBuildCommand; bool MSBuildCommandInitialized; - cmVisualStudio10ToolsetOptions ToolsetOptions; std::set<std::string> AndroidExecutableWarnings; virtual std::string FindMSBuildCommand(); std::string FindDevEnvCommand() override; @@ -242,6 +251,19 @@ private: bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); + std::string GetClFlagTableName() const; + std::string GetCSharpFlagTableName() const; + std::string GetRcFlagTableName() const; + std::string GetLibFlagTableName() const; + std::string GetLinkFlagTableName() const; + std::string GetMasmFlagTableName() const; + std::string CanonicalToolsetName(std::string const& toolset) const; + + cm::optional<std::string> FindFlagTable(cm::string_view toolsetName, + cm::string_view table) const; + + std::string CustomFlagTableDir; + std::string CustomVCTargetsPath; std::string VCTargetsPath; bool FindVCTargetsPath(cmMakefile* mf); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index d6cc423..d6909c3 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -17,6 +17,7 @@ #include "cmsys/RegularExpression.hxx" +#include "cmCMakePath.h" #include "cmComputeLinkInformation.h" #include "cmCryptoHash.h" #include "cmCustomCommand.h" @@ -991,7 +992,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES), *sf); } - lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true)); + lg->AppendFlags(flags, + lg->GetIncludeFlags(includes, gtgt, lang, std::string())); cmXCodeObject* buildFile = this->CreateXCodeBuildFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf); @@ -1863,9 +1865,20 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase( std::set<std::string> allConfigInputs; std::set<std::string> allConfigOutputs; + cmXCodeObject* buildPhase = + this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase, + cmStrCat(gt->GetName(), ':', sf->GetFullPath())); + + auto depfilesDirectory = cmStrCat( + gt->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/CMakeFiles/d/"); + auto depfilesPrefix = cmStrCat(depfilesDirectory, buildPhase->GetId(), "."); + std::string shellScript = "set -e\n"; for (std::string const& configName : this->CurrentConfigurationTypes) { - cmCustomCommandGenerator ccg(cc, configName, this->CurrentLocalGenerator); + cmCustomCommandGenerator ccg( + cc, configName, this->CurrentLocalGenerator, true, {}, + [&depfilesPrefix](const std::string& config, const std::string&) + -> std::string { return cmStrCat(depfilesPrefix, config, ".d"); }); std::vector<std::string> realDepends; realDepends.reserve(ccg.GetDepends().size()); for (auto const& d : ccg.GetDepends()) { @@ -1885,9 +1898,22 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase( "\"; then :\n", this->ConstructScript(ccg), "fi\n"); } - cmXCodeObject* buildPhase = - this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase, - cmStrCat(gt->GetName(), ':', sf->GetFullPath())); + if (!cc.GetDepfile().empty()) { + buildPhase->AddAttribute( + "dependencyFile", + this->CreateString(cmStrCat(depfilesDirectory, buildPhase->GetId(), + ".$(CONFIGURATION).d"))); + // to avoid spurious errors during first build, create empty dependency + // files + cmSystemTools::MakeDirectory(depfilesDirectory); + for (std::string const& configName : this->CurrentConfigurationTypes) { + auto file = cmStrCat(depfilesPrefix, configName, ".d"); + if (!cmSystemTools::FileExists(file)) { + cmSystemTools::Touch(file, true); + } + } + } + buildPhase->AddAttribute("buildActionMask", this->CreateString("2147483647")); cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); @@ -2187,9 +2213,33 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( } } makefileStream << "\n\n"; + + auto depfilesDirectory = + cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), + "/CMakeFiles/d/"); + for (auto const& command : commands) { - cmCustomCommandGenerator ccg(command, configName, - this->CurrentLocalGenerator); + cmCustomCommandGenerator ccg( + command, configName, this->CurrentLocalGenerator, true, {}, + [this, &depfilesDirectory](const std::string& config, + const std::string& file) -> std::string { + return cmStrCat( + depfilesDirectory, + this->GetObjectId(cmXCodeObject::PBXShellScriptBuildPhase, file), + ".", config, ".d"); + }); + + auto depfile = ccg.GetInternalDepfile(); + if (!depfile.empty()) { + makefileStream << "include " + << cmSystemTools::ConvertToOutputPath(depfile) << "\n\n"; + + cmSystemTools::MakeDirectory(depfilesDirectory); + if (!cmSystemTools::FileExists(depfile)) { + cmSystemTools::Touch(depfile, true); + } + } + std::vector<std::string> realDepends; realDepends.reserve(ccg.GetDepends().size()); for (auto const& d : ccg.GetDepends()) { @@ -2695,7 +2745,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // GNU assembly files (#16449) for (auto const& language : languages) { std::string includeFlags = this->CurrentLocalGenerator->GetIncludeFlags( - includes, gtgt, language, true, false, configName); + includes, gtgt, language, configName); if (!includeFlags.empty()) { cflags[language] += " " + includeFlags; @@ -3727,7 +3777,10 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) } } -void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) +void cmGlobalXCodeGenerator::AddEmbeddedObjects( + cmXCodeObject* target, const std::string& copyFilesBuildPhaseName, + const std::string& embedPropertyName, const std::string& dstSubfolderSpec, + int actionsOnByDefault) { cmGeneratorTarget* gt = target->GetTarget(); if (!gt) { @@ -3743,7 +3796,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) if (!(isFrameworkTarget || isBundleTarget || isCFBundleTarget)) { return; } - cmProp files = gt->GetProperty("XCODE_EMBED_FRAMEWORKS"); + cmProp files = gt->GetProperty(embedPropertyName); if (!files) { return; } @@ -3751,16 +3804,15 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) // Create an "Embedded Frameworks" build phase auto* copyFilesBuildPhase = this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); - std::string copyFilesBuildPhaseName = "Embed Frameworks"; - std::string destinationFrameworks = "10"; copyFilesBuildPhase->SetComment(copyFilesBuildPhaseName); copyFilesBuildPhase->AddAttribute("buildActionMask", this->CreateString("2147483647")); copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", - this->CreateString(destinationFrameworks)); + this->CreateString(dstSubfolderSpec)); copyFilesBuildPhase->AddAttribute( "name", this->CreateString(copyFilesBuildPhaseName)); - if (cmProp fwEmbedPath = gt->GetProperty("XCODE_EMBED_FRAMEWORKS_PATH")) { + if (cmProp fwEmbedPath = + gt->GetProperty(cmStrCat(embedPropertyName, "_PATH"))) { copyFilesBuildPhase->AddAttribute("dstPath", this->CreateString(*fwEmbedPath)); } else { @@ -3774,10 +3826,10 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) for (std::string const& relFile : relFiles) { cmXCodeObject* buildFile{ nullptr }; std::string filePath = relFile; - auto* genTarget = FindGeneratorTarget(relFile); + auto* genTarget = this->FindGeneratorTarget(relFile); if (genTarget) { // This is a target - get it's product path reference - auto* xcTarget = FindXCodeTarget(genTarget); + auto* xcTarget = this->FindXCodeTarget(genTarget); if (!xcTarget) { cmSystemTools::Error("Can not find a target for " + genTarget->GetName()); @@ -3791,18 +3843,18 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) " is missing product reference"); continue; } - auto it = FileRefToEmbedBuildFileMap.find(fileRefObject); - if (it == FileRefToEmbedBuildFileMap.end()) { + auto it = this->FileRefToEmbedBuildFileMap.find(fileRefObject); + if (it == this->FileRefToEmbedBuildFileMap.end()) { buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); buildFile->AddAttribute("fileRef", fileRefObject); - FileRefToEmbedBuildFileMap[fileRefObject] = buildFile; + this->FileRefToEmbedBuildFileMap[fileRefObject] = buildFile; } else { buildFile = it->second; } } else if (cmSystemTools::IsPathToFramework(relFile)) { // This is a regular string path - create file reference - auto it = EmbeddedLibRefs.find(relFile); - if (it == EmbeddedLibRefs.end()) { + auto it = this->EmbeddedLibRefs.find(relFile); + if (it == this->EmbeddedLibRefs.end()) { cmXCodeObject* fileRef = this->CreateXCodeFileReferenceFromPath(relFile, gt, "", nullptr); if (fileRef) { @@ -3828,16 +3880,25 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); - const auto& rmHeadersProp = - gt->GetSafeProperty("XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY"); - if (cmIsOn(rmHeadersProp)) { + + bool removeHeaders = actionsOnByDefault & RemoveHeadersOnCopyByDefault; + if (auto prop = gt->GetProperty( + cmStrCat(embedPropertyName, "_REMOVE_HEADERS_ON_COPY"))) { + removeHeaders = cmIsOn(*prop); + } + if (removeHeaders) { attrs->AddObject(this->CreateString("RemoveHeadersOnCopy")); } - const auto& codeSignProp = - gt->GetSafeProperty("XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY"); - if (cmIsOn(codeSignProp)) { + + bool codeSign = actionsOnByDefault & CodeSignOnCopyByDefault; + if (auto prop = + gt->GetProperty(cmStrCat(embedPropertyName, "_CODE_SIGN_ON_COPY"))) { + codeSign = cmIsOn(*prop); + } + if (codeSign) { attrs->AddObject(this->CreateString("CodeSignOnCopy")); } + settings->AddAttributeIfNotEmpty("ATTRIBUTES", attrs); buildFile->AddAttributeIfNotEmpty("settings", settings); if (!buildFiles->HasObject(buildFile)) { @@ -3846,11 +3907,30 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) } copyFilesBuildPhase->AddAttribute("files", buildFiles); auto* buildPhases = target->GetAttribute("buildPhases"); - // Insert embed build phase right before the post-build command + // Embed-something build phases must be inserted before the post-build + // command because that command is expected to be last buildPhases->InsertObject(buildPhases->GetObjectCount() - 1, copyFilesBuildPhase); } +void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) +{ + static const auto dstSubfolderSpec = "10"; + + this->AddEmbeddedObjects(target, "Embed Frameworks", + "XCODE_EMBED_FRAMEWORKS", dstSubfolderSpec, + NoActionOnCopyByDefault); +} + +void cmGlobalXCodeGenerator::AddEmbeddedAppExtensions(cmXCodeObject* target) +{ + static const auto dstSubfolderSpec = "13"; + + this->AddEmbeddedObjects(target, "Embed App Extensions", + "XCODE_EMBED_APP_EXTENSIONS", dstSubfolderSpec, + RemoveHeadersOnCopyByDefault); +} + bool cmGlobalXCodeGenerator::CreateGroups( std::vector<cmLocalGenerator*>& generators) { @@ -4230,6 +4310,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( for (auto t : targets) { this->AddDependAndLinkInformation(t); this->AddEmbeddedFrameworks(t); + this->AddEmbeddedAppExtensions(t); // Inherit project-wide values for any target-specific search paths. this->InheritBuildSettingAttribute(t, "HEADER_SEARCH_PATHS"); this->InheritBuildSettingAttribute(t, "SYSTEM_HEADER_SEARCH_PATHS"); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 1ab56e2..a7b1814 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -14,6 +14,7 @@ #include <cm/string_view> #include "cmGlobalGenerator.h" +#include "cmTransformDepfile.h" #include "cmXCodeObject.h" class cmCustomCommand; @@ -111,6 +112,17 @@ public: bool ShouldStripResourcePath(cmMakefile*) const override; + /** + * Used to determine if this generator supports DEPFILE option. + */ + bool SupportsCustomCommandDepfile() const override { return true; } + virtual cm::optional<cmDepfileFormat> DepfileFormat() const override + { + return this->XcodeBuildSystem == BuildSystem::One + ? cmDepfileFormat::MakeDepfile + : cmDepfileFormat::GccDepfile; + } + bool SetSystemName(std::string const& s, cmMakefile* mf) override; bool SetGeneratorToolset(std::string const& ts, bool build, cmMakefile* mf) override; @@ -132,6 +144,13 @@ protected: } private: + enum EmbedActionFlags + { + NoActionOnCopyByDefault = 0, + CodeSignOnCopyByDefault = 1, + RemoveHeadersOnCopyByDefault = 2, + }; + bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); bool ProcessGeneratorToolsetField(std::string const& key, std::string const& value, cmMakefile* mf); @@ -196,7 +215,13 @@ private: const char* attribute); cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt); void AddDependAndLinkInformation(cmXCodeObject* target); + void AddEmbeddedObjects(cmXCodeObject* target, + const std::string& copyFilesBuildPhaseName, + const std::string& embedPropertyName, + const std::string& dstSubfolderSpec, + int actionsOnByDefault); void AddEmbeddedFrameworks(cmXCodeObject* target); + void AddEmbeddedAppExtensions(cmXCodeObject* target); void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target, cmXCodeObject* buildSettings, const std::string& configName); diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index bef785d..eb214fa 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -338,6 +338,7 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles( // Add the names based on the current namelink mode. if (haveNamelink) { + files.NamelinkMode = this->NamelinkMode; // With a namelink we need to check the mode. if (this->NamelinkMode == NamelinkModeOnly) { // Install the namelink only. diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 8c5d444..84fce42 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -39,7 +39,6 @@ public: NamelinkModeSkip }; void SetNamelinkMode(NamelinkModeType mode) { this->NamelinkMode = mode; } - NamelinkModeType GetNamelinkMode() const { return this->NamelinkMode; } std::string GetInstallFilename(const std::string& config) const; @@ -82,6 +81,7 @@ public: // Prefix for all files in To. std::string ToDir; + NamelinkModeType NamelinkMode = NamelinkModeNone; bool NoTweak = false; bool UseSourcePermissions = false; cmInstallType Type = cmInstallType(); diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h index a63347d..6690aef 100644 --- a/Source/cmJSONHelpers.h +++ b/Source/cmJSONHelpers.h @@ -239,7 +239,7 @@ cmJSONHelper<std::vector<T>, E> cmJSONVectorFilterHelper(E success, E fail, if (!filter(t)) { continue; } - out.push_back(t); + out.push_back(std::move(t)); } return success; }; diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index fdddb45..09cd88e 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -4,9 +4,7 @@ #include <algorithm> #include <cassert> -#include <cstddef> #include <cstdio> -#include <cstdlib> // required for atoi #include <functional> #include <iterator> #include <set> @@ -36,6 +34,42 @@ namespace { +bool GetIndexArg(const std::string& arg, int* idx, cmMakefile& mf) +{ + long value; + if (!cmStrToLong(arg, &value)) { + switch (mf.GetPolicyStatus(cmPolicies::CMP0121)) { + case cmPolicies::WARN: { + // Default is to warn and use old behavior OLD behavior is to allow + // compatibility, so issue a warning and use the previous behavior. + std::string warn = + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0121), + " Invalid list index \"", arg, "\"."); + mf.IssueMessage(MessageType::AUTHOR_WARNING, warn); + break; + } + case cmPolicies::OLD: + // OLD behavior is to allow compatibility, so just ignore the + // situation. + break; + case cmPolicies::NEW: + return false; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + std::string msg = + cmStrCat(cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0121), + " Invalid list index \"", arg, "\"."); + mf.IssueMessage(MessageType::FATAL_ERROR, msg); + break; + } + } + + // Truncation is happening here, but it had always been happening here. + *idx = static_cast<int>(value); + + return true; +} + bool FilterRegex(std::vector<std::string> const& args, bool includeMatches, std::string const& listName, std::vector<std::string>& varArgsExpanded, @@ -154,7 +188,11 @@ bool HandleGetCommand(std::vector<std::string> const& args, const char* sep = ""; size_t nitem = varArgsExpanded.size(); for (cc = 2; cc < args.size() - 1; cc++) { - int item = atoi(args[cc].c_str()); + int item; + if (!GetIndexArg(args[cc], &item, status.GetMakefile())) { + status.SetError(cmStrCat("index: ", args[cc], " is not a valid index")); + return false; + } value += sep; sep = ";"; if (item < 0) { @@ -362,7 +400,11 @@ bool HandleInsertCommand(std::vector<std::string> const& args, const std::string& listName = args[1]; // expand the variable - int item = atoi(args[2].c_str()); + int item; + if (!GetIndexArg(args[2], &item, status.GetMakefile())) { + status.SetError(cmStrCat("index: ", args[2], " is not a valid index")); + return false; + } std::vector<std::string> varArgsExpanded; if ((!GetList(varArgsExpanded, listName, status.GetMakefile()) || varArgsExpanded.empty()) && @@ -1282,8 +1324,16 @@ bool HandleSublistCommand(std::vector<std::string> const& args, return true; } - const int start = atoi(args[2].c_str()); - const int length = atoi(args[3].c_str()); + int start; + int length; + if (!GetIndexArg(args[2], &start, status.GetMakefile())) { + status.SetError(cmStrCat("index: ", args[2], " is not a valid index")); + return false; + } + if (!GetIndexArg(args[3], &length, status.GetMakefile())) { + status.SetError(cmStrCat("index: ", args[3], " is not a valid index")); + return false; + } using size_type = decltype(varArgsExpanded)::size_type; @@ -1338,7 +1388,11 @@ bool HandleRemoveAtCommand(std::vector<std::string> const& args, std::vector<size_t> removed; size_t nitem = varArgsExpanded.size(); for (cc = 2; cc < args.size(); ++cc) { - int item = atoi(args[cc].c_str()); + int item; + if (!GetIndexArg(args[cc], &item, status.GetMakefile())) { + status.SetError(cmStrCat("index: ", args[cc], " is not a valid index")); + return false; + } if (item < 0) { item = static_cast<int>(nitem) + item; } diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 1464a14..5c3a034 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -7,6 +7,10 @@ #include <sstream> #include <utility> +#ifdef _WIN32 +# include <cmsys/Encoding.hxx> +#endif + #include "cmListFileLexer.h" #include "cmMessageType.h" #include "cmMessenger.h" @@ -83,9 +87,15 @@ bool cmListFileParser::ParseFile(const char* filename) { this->FileName = filename; +#ifdef _WIN32 + std::string expandedFileName = cmsys::Encoding::ToNarrow( + cmSystemTools::ConvertToWindowsExtendedPath(filename)); + filename = expandedFileName.c_str(); +#endif + // Open the file. cmListFileLexer_BOM bom; - if (!cmListFileLexer_SetFileName(this->Lexer, this->FileName, &bom)) { + if (!cmListFileLexer_SetFileName(this->Lexer, filename, &bom)) { this->IssueFileOpenError("cmListFileCache: error can not open file."); return false; } diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 2981ef8..2456db9 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -90,6 +90,9 @@ struct LoadedCommandImpl : cmLoadedCommandInfo { if (this->Destructor) { SignalHandlerGuard guard(this->Name); +#if defined(__NVCOMPILER) + static_cast<void>(guard); // convince compiler var is used +#endif this->Destructor(this); } if (this->Error != nullptr) { @@ -103,12 +106,18 @@ struct LoadedCommandImpl : cmLoadedCommandInfo int DoInitialPass(cmMakefile* mf, int argc, char* argv[]) { SignalHandlerGuard guard(this->Name); +#if defined(__NVCOMPILER) + static_cast<void>(guard); // convince compiler var is used +#endif return this->InitialPass(this, mf, argc, argv); } void DoFinalPass(cmMakefile* mf) { SignalHandlerGuard guard(this->Name); +#if defined(__NVCOMPILER) + static_cast<void>(guard); // convince compiler var is used +#endif this->FinalPass(this, mf); } }; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 73b6fbc..21a9a44 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -838,16 +838,16 @@ cmProp cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target, } std::string cmLocalGenerator::ConvertToIncludeReference( - std::string const& path, OutputFormat format, bool forceFullPaths) + std::string const& path, IncludePathStyle pathStyle, OutputFormat format) { - static_cast<void>(forceFullPaths); + static_cast<void>(pathStyle); return this->ConvertToOutputForExisting(path, format); } std::string cmLocalGenerator::GetIncludeFlags( - const std::vector<std::string>& includeDirs, cmGeneratorTarget* target, - const std::string& lang, bool forceFullPaths, bool forResponseFile, - const std::string& config) + std::vector<std::string> const& includeDirs, cmGeneratorTarget* target, + std::string const& lang, std::string const& config, bool forResponseFile, + IncludePathStyle pathStyle) { if (lang.empty()) { return ""; @@ -923,7 +923,7 @@ std::string cmLocalGenerator::GetIncludeFlags( flagUsed = true; } std::string includePath = - this->ConvertToIncludeReference(i, shellFormat, forceFullPaths); + this->ConvertToIncludeReference(i, pathStyle, shellFormat); if (quotePaths && !includePath.empty() && includePath.front() != '\"') { includeFlags << "\""; } @@ -1527,12 +1527,12 @@ void cmLocalGenerator::GetTargetFlags( } if (target->IsWin32Executable(config)) { - exeFlags += - this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE"); + exeFlags += this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", linkLanguage, "_CREATE_WIN32_EXE")); exeFlags += " "; } else { - exeFlags += - this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE"); + exeFlags += this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", linkLanguage, "_CREATE_CONSOLE_EXE")); exeFlags += " "; } @@ -1877,7 +1877,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, std::vector<std::string> archs; target->GetAppleArchs(config, archs); if (!archs.empty() && - (lang == "C" || lang == "CXX" || lang == "OBJ" || lang == "OBJCXX" || + (lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX" || lang == "ASM")) { for (std::string const& arch : archs) { if (filterArch.empty() || filterArch == arch) { @@ -2701,8 +2701,9 @@ void cmLocalGenerator::CopyPchCompilePdb( } file << "foreach(retry RANGE 1 30)\n"; - file << " if (EXISTS \"" << from_file << "\" AND \"" << from_file - << " \" IS_NEWER_THAN \"" << dest_file << "\")\n"; + file << " if (EXISTS \"" << from_file << "\" AND (NOT EXISTS \"" + << dest_file << "\" OR NOT \"" << dest_file << " \" IS_NEWER_THAN \"" + << from_file << "\"))\n"; file << " execute_process(COMMAND ${CMAKE_COMMAND} -E copy"; file << " \"" << from_file << "\"" << " \"" << to_dir << "\" RESULT_VARIABLE result " diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index e48849a..f597120 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -171,13 +171,19 @@ public: cmGeneratorTarget* target, const std::string& config, const std::string& lang); + + enum class IncludePathStyle + { + Default, + Absolute, + }; + //! Get the include flags for the current makefile and language - std::string GetIncludeFlags(const std::vector<std::string>& includes, - cmGeneratorTarget* target, - const std::string& lang, - bool forceFullPaths = false, - bool forResponseFile = false, - const std::string& config = ""); + std::string GetIncludeFlags( + std::vector<std::string> const& includes, cmGeneratorTarget* target, + std::string const& lang, std::string const& config, + bool forResponseFile = false, + IncludePathStyle pathStyle = IncludePathStyle::Default); using GeneratorTargetVector = std::vector<std::unique_ptr<cmGeneratorTarget>>; @@ -256,11 +262,6 @@ public: bool GetRealDependency(const std::string& name, const std::string& config, std::string& dep); - virtual std::string ConvertToIncludeReference( - std::string const& path, - cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL, - bool forceFullPaths = false); - /** Called from command-line hook to clear dependencies. */ virtual void ClearDependencies(cmMakefile* /* mf */, bool /* verbose */) {} @@ -557,6 +558,13 @@ public: cmProp GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop); protected: + // The default implementation ignores the IncludePathStyle and always + // uses absolute paths. A generator may override this to use relative + // paths in some cases. + virtual std::string ConvertToIncludeReference( + std::string const& path, IncludePathStyle pathStyle, + cmOutputConverter::OutputFormat format); + //! put all the libraries for a target on into the given stream void OutputLinkLibraries(cmComputeLinkInformation* pcli, cmLinkLineComputer* linkLineComputer, diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 51ad993..588f70b 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -97,9 +97,12 @@ void cmLocalNinjaGenerator::Generate() // contains any non-ASCII characters and dependency checking will fail. // As a workaround, leave the msvc_deps_prefix UTF-8 encoded even though // the rest of the file is ANSI encoded. - if (GetConsoleOutputCP() == CP_UTF8 && GetACP() != CP_UTF8) { + if (GetConsoleOutputCP() == CP_UTF8 && GetACP() != CP_UTF8 && + this->GetGlobalGenerator()->GetMakefileEncoding() != codecvt::None) { this->GetRulesFileStream().WriteRaw(showIncludesPrefix); } else { + // Ninja 1.11 and above uses the UTF-8 code page if it's supported, so + // in that case we can write it normally without using raw bytes. this->GetRulesFileStream() << showIncludesPrefix; } #else @@ -202,10 +205,10 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator() // Virtual protected methods. std::string cmLocalNinjaGenerator::ConvertToIncludeReference( - std::string const& path, cmOutputConverter::OutputFormat format, - bool forceFullPaths) + std::string const& path, IncludePathStyle pathStyle, + cmOutputConverter::OutputFormat format) { - if (forceFullPaths) { + if (pathStyle == IncludePathStyle::Absolute) { return this->ConvertToOutputFormat( cmSystemTools::CollapseFullPath(path, this->GetCurrentBinaryDirectory()), format); @@ -407,7 +410,8 @@ void cmLocalNinjaGenerator::AppendCustomCommandDeps( } std::string cmLocalNinjaGenerator::WriteCommandScript( - std::vector<std::string> const& cmdLines, std::string const& customStep, + std::vector<std::string> const& cmdLines, std::string const& outputConfig, + std::string const& commandConfig, std::string const& customStep, cmGeneratorTarget const* target) const { std::string scriptPath; @@ -416,9 +420,13 @@ std::string cmLocalNinjaGenerator::WriteCommandScript( } else { scriptPath = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles"); } + scriptPath += this->GetGlobalNinjaGenerator()->ConfigDirectory(outputConfig); cmSystemTools::MakeDirectory(scriptPath); scriptPath += '/'; scriptPath += customStep; + if (this->GlobalGenerator->IsMultiConfig()) { + scriptPath += cmStrCat('-', commandConfig); + } #ifdef _WIN32 scriptPath += ".bat"; #else @@ -461,7 +469,8 @@ std::string cmLocalNinjaGenerator::WriteCommandScript( } std::string cmLocalNinjaGenerator::BuildCommandLine( - std::vector<std::string> const& cmdLines, std::string const& customStep, + std::vector<std::string> const& cmdLines, std::string const& outputConfig, + std::string const& commandConfig, std::string const& customStep, cmGeneratorTarget const* target) const { // If we have no commands but we need to build a command anyway, use noop. @@ -480,8 +489,8 @@ std::string cmLocalNinjaGenerator::BuildCommandLine( cmdLinesTotal += cmd.length() + 6; } if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) { - std::string const scriptPath = - this->WriteCommandScript(cmdLines, customStep, target); + std::string const scriptPath = this->WriteCommandScript( + cmdLines, outputConfig, commandConfig, customStep, target); std::string cmd #ifndef _WIN32 = "/bin/sh " @@ -667,7 +676,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( cmCryptoHash hash(cmCryptoHash::AlgoSHA256); customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7); - std::string depfile = cc->GetDepfile(); + std::string depfile = ccg.GetDepfile(); if (!depfile.empty()) { switch (cc->GetCMP0116Status()) { case cmPolicies::WARN: @@ -694,7 +703,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( } gg->WriteCustomCommandBuild( - this->BuildCommandLine(cmdLines, customStep), + this->BuildCommandLine(cmdLines, ccg.GetOutputConfig(), fileConfig, + customStep), this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0], depfile, cc->GetJobPool(), cc->GetUsesTerminal(), /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, fileConfig, diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 5b850f3..a73fa27 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -12,6 +12,7 @@ #include "cmListFileCache.h" #include "cmLocalCommonGenerator.h" +#include "cmLocalGenerator.h" #include "cmNinjaTypes.h" #include "cmOutputConverter.h" @@ -60,7 +61,8 @@ public: } std::string BuildCommandLine( - std::vector<std::string> const& cmdLines, + std::vector<std::string> const& cmdLines, std::string const& outputConfig, + std::string const& commandConfig, std::string const& customStep = std::string(), cmGeneratorTarget const* target = nullptr) const; @@ -91,9 +93,8 @@ public: protected: std::string ConvertToIncludeReference( - std::string const& path, - cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL, - bool forceFullPaths = false) override; + std::string const& path, IncludePathStyle pathStyle, + cmOutputConverter::OutputFormat format) override; private: cmGeneratedFileStream& GetImplFileStream(const std::string& config) const; @@ -119,6 +120,8 @@ private: std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg); std::string WriteCommandScript(std::vector<std::string> const& cmdLines, + std::string const& outputConfig, + std::string const& commandConfig, std::string const& customStep, cmGeneratorTarget const* target) const; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 78cae0e..dba8560 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1222,7 +1222,7 @@ void cmMakefile::AddCustomCommandOldStyle( // Each output must get its own copy of this rule. cmsys::RegularExpression sourceFiles( - "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|mpp|cu|m|mm|" + "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|mpp|ixx|cppm|cu|m|mm|" "rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|" "hm|hpp|hxx|in|txx|inl)$"); @@ -2507,6 +2507,20 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const return def != nullptr; } +bool cmMakefile::IsNormalDefinitionSet(const std::string& name) const +{ + cmProp def = this->StateSnapshot.GetDefinition(name); +#ifndef CMAKE_BOOTSTRAP + if (cmVariableWatch* vv = this->GetVariableWatch()) { + if (!def) { + vv->VariableAccessed( + name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, nullptr, this); + } + } +#endif + return def != nullptr; +} + cmProp cmMakefile::GetDefinition(const std::string& name) const { cmProp def = this->StateSnapshot.GetDefinition(name); @@ -4393,7 +4407,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, // Deprecate old policies, especially those that require a lot // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0075 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0081 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 71d765c..3c07808 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -486,6 +486,7 @@ public: const std::string& GetSafeDefinition(const std::string&) const; const std::string& GetRequiredDefinition(const std::string& name) const; bool IsDefinitionSet(const std::string&) const; + bool IsNormalDefinitionSet(const std::string&) const; bool GetDefExpandList(const std::string& name, std::vector<std::string>& out, bool emptyArgs = false) const; /** diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 1750e37..6783341 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -384,11 +384,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) if (this->GeneratorTarget->IsWin32Executable( this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) { this->LocalGenerator->AppendFlags( - linkFlags, this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE")); + linkFlags, + this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", linkLanguage, "_CREATE_WIN32_EXE"))); } else { this->LocalGenerator->AppendFlags( linkFlags, - this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE")); + this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", linkLanguage, "_CREATE_CONSOLE_EXE"))); } // Add symbol export flags if necessary. diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index ce64e2c..5e4f03d 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -780,9 +780,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( vars.Target = target.c_str(); vars.LinkLibraries = linkLibs.c_str(); vars.ObjectsQuoted = buildObjs.c_str(); + std::string targetOutSOName; if (this->GeneratorTarget->HasSOName(this->GetConfigName())) { vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage); - vars.TargetSOName = this->TargetNames.SharedObject.c_str(); + targetOutSOName = this->LocalGenerator->ConvertToOutputFormat( + this->TargetNames.SharedObject.c_str(), cmOutputConverter::SHELL); + vars.TargetSOName = targetOutSOName.c_str(); } vars.LinkFlags = linkFlags.c_str(); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 4918bf6..5b6c58d 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -854,7 +854,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( vars.Defines = definesString.c_str(); std::string includesString = this->LocalGenerator->GetIncludeFlags( - includes, this->GeneratorTarget, lang, true, false, config); + includes, this->GeneratorTarget, lang, config); this->LocalGenerator->AppendFlags(includesString, "$(" + lang + "_INCLUDES)"); vars.Includes = includesString.c_str(); @@ -2058,7 +2058,8 @@ std::string cmMakefileTargetGenerator::CreateResponseFile( // Create the response file. std::string responseFileNameFull = cmStrCat(this->TargetBuildDirectoryFull, '/', name); - cmGeneratedFileStream responseStream(responseFileNameFull); + cmGeneratedFileStream responseStream( + responseFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); responseStream.SetCopyIfDifferent(true); responseStream << options << "\n"; @@ -2195,8 +2196,8 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, lang, this->GetConfigName()); std::string includeFlags = this->LocalGenerator->GetIncludeFlags( - includes, this->GeneratorTarget, lang, false, useResponseFile, - this->GetConfigName()); + includes, this->GeneratorTarget, lang, this->GetConfigName(), + useResponseFile); if (includeFlags.empty()) { return; } diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 49e5e4c..1b514b8 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -287,7 +287,8 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule( // If there is no ranlib the command will be ":". Skip it. cm::erase_if(linkCmds, cmNinjaRemoveNoOpCommands()); - rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(linkCmds, config, config); // Write the linker rule with response file if needed. rule.Comment = @@ -310,7 +311,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules( cmNinjaRule rule(this->LanguageLinkerCudaDeviceRule(config)); rule.Command = this->GetLocalGenerator()->BuildCommandLine( { cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_DEVICE_LINKER"), - " -arch=$ARCH $REGISTER -o=$out $in") }); + " -arch=$ARCH $REGISTER -o=$out $in") }, + config, config); rule.Comment = "Rule for CUDA device linking."; rule.Description = "Linking CUDA $out"; this->GetGlobalGenerator()->AddRule(rule); @@ -336,7 +338,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules( compileCmd, vars); rule.Name = this->LanguageLinkerCudaDeviceCompileRule(config); - rule.Command = this->GetLocalGenerator()->BuildCommandLine({ compileCmd }); + rule.Command = this->GetLocalGenerator()->BuildCommandLine({ compileCmd }, + config, config); rule.Comment = "Rule for compiling CUDA device stubs."; rule.Description = "Compiling CUDA device stub $out"; this->GetGlobalGenerator()->AddRule(rule); @@ -345,7 +348,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules( rule.Command = this->GetLocalGenerator()->BuildCommandLine( { cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_FATBINARY"), " -64 -cmdline=--compile-only -compress-all -link " - "--embedded-fatbin=$out $PROFILES") }); + "--embedded-fatbin=$out $PROFILES") }, + config, config); rule.Comment = "Rule for CUDA fatbinaries."; rule.Description = "Creating fatbinary $out"; this->GetGlobalGenerator()->AddRule(rule); @@ -475,7 +479,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, linkCmds.insert(linkCmds.begin(), "$PRE_LINK"); linkCmds.emplace_back("$POST_BUILD"); - rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(linkCmds, config, config); // Write the linker rule with response file if needed. rule.Comment = @@ -500,7 +505,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, std::vector<std::string> cmd; cmd.push_back(cmakeCommand + " -E cmake_symlink_executable $in $out"); cmd.emplace_back("$POST_BUILD"); - rule.Command = this->GetLocalGenerator()->BuildCommandLine(cmd); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(cmd, config, config); } rule.Description = "Creating executable symlink $out"; rule.Comment = "Rule for creating executable symlink."; @@ -512,7 +518,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, cmd.push_back(cmakeCommand + " -E cmake_symlink_library $in $SONAME $out"); cmd.emplace_back("$POST_BUILD"); - rule.Command = this->GetLocalGenerator()->BuildCommandLine(cmd); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(cmd, config, config); } rule.Description = "Creating library symlink $out"; rule.Comment = "Rule for creating library symlink."; @@ -868,7 +875,8 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement( if (genTarget->HasSOName(config)) { vars["SONAME_FLAG"] = this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage(config)); - vars["SONAME"] = tgtNames.SharedObject; + vars["SONAME"] = localGen.ConvertToOutputFormat(tgtNames.SharedObject, + cmOutputConverter::SHELL); if (genTarget->GetType() == cmStateEnums::SHARED_LIBRARY) { std::string install_dir = this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(config); @@ -1176,7 +1184,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( } if (gt->HasSOName(config)) { vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage(config)); - vars["SONAME"] = tgtNames.SharedObject; + vars["SONAME"] = localGen.ConvertToOutputFormat(tgtNames.SharedObject, + cmOutputConverter::SHELL); if (targetType == cmStateEnums::SHARED_LIBRARY) { std::string install_dir = gt->GetInstallNameDirForBuildTree(config); if (!install_dir.empty()) { @@ -1310,10 +1319,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( preLinkCmdLines.push_back("cd " + homeOutDir); } - vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link", - this->GeneratorTarget); - std::string postBuildCmdLine = localGen.BuildCommandLine( - postBuildCmdLines, "post-build", this->GeneratorTarget); + vars["PRE_LINK"] = localGen.BuildCommandLine( + preLinkCmdLines, config, fileConfig, "pre-link", this->GeneratorTarget); + std::string postBuildCmdLine = + localGen.BuildCommandLine(postBuildCmdLines, config, fileConfig, + "post-build", this->GeneratorTarget); cmNinjaVars symlinkVars; bool const symlinkNeeded = diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 672b579..f7777fc 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -263,9 +263,10 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags, language, config); // Add include directory flags. std::string includeFlags = this->LocalGenerator->GetIncludeFlags( - includes, this->GeneratorTarget, language, - language == "RC", // full include paths for RC needed by cmcldeps - false, config); + includes, this->GeneratorTarget, language, config, false, + // full include paths for RC needed by cmcldeps + language == "RC" ? cmLocalGenerator::IncludePathStyle::Absolute + : cmLocalGenerator::IncludePathStyle::Default); if (this->GetGlobalGenerator()->IsGCCOnWindows()) { std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/'); } @@ -324,7 +325,8 @@ std::string cmNinjaTargetGenerator::ComputeIncludes( } std::string includesString = this->LocalGenerator->GetIncludeFlags( - includes, this->GeneratorTarget, language, true, false, config); + includes, this->GeneratorTarget, language, config, false, + cmLocalGenerator::IncludePathStyle::Absolute); this->LocalGenerator->AppendFlags(includesString, this->GetIncludes(language, config)); @@ -537,7 +539,8 @@ cmNinjaRule GetScanRule( cmRulePlaceholderExpander::RuleVariables const& vars, const std::string& responseFlag, const std::string& flags, cmRulePlaceholderExpander* const rulePlaceholderExpander, - cmLocalNinjaGenerator* generator, std::vector<std::string> scanCmds) + cmLocalNinjaGenerator* generator, std::vector<std::string> scanCmds, + const std::string& outputConfig) { cmNinjaRule rule(ruleName); // Scanning always uses a depfile for preprocessor dependencies. @@ -578,7 +581,8 @@ cmNinjaRule GetScanRule( for (std::string& scanCmd : scanCmds) { rulePlaceholderExpander->ExpandRuleVariables(generator, scanCmd, scanVars); } - rule.Command = generator->BuildCommandLine(scanCmds); + rule.Command = + generator->BuildCommandLine(scanCmds, outputConfig, outputConfig); return rule; } @@ -670,7 +674,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, auto scanRule = GetScanRule( scanRuleName, vars, responseFlag, flags, rulePlaceholderExpander.get(), - this->GetLocalGenerator(), std::move(scanCommands)); + this->GetLocalGenerator(), std::move(scanCommands), config); scanRule.Comment = cmStrCat("Rule for generating ", lang, " dependencies."); @@ -700,7 +704,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, auto scanRule = GetScanRule( scanRuleName, vars, "", flags, rulePlaceholderExpander.get(), - this->GetLocalGenerator(), std::move(scanCommands)); + this->GetLocalGenerator(), std::move(scanCommands), config); // Write the rule for generating dependencies for the given language. scanRule.Comment = cmStrCat("Rule for generating ", lang, @@ -732,7 +736,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, ddModmapArg, " --dd=$out @", rule.RspFile); ddCmds.emplace_back(std::move(ccmd)); } - rule.Command = this->GetLocalGenerator()->BuildCommandLine(ddCmds); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(ddCmds, config, config); } rule.Comment = cmStrCat("Rule to generate ninja dyndep files for ", lang, '.'); @@ -928,7 +933,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, vars); } - rule.Command = this->GetLocalGenerator()->BuildCommandLine(compileCmds); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(compileCmds, config, config); // Write the rule for compiling file of the given language. rule.Comment = cmStrCat("Rule for compiling ", lang, " files."); @@ -1246,7 +1252,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->ExportObjectCompileCommand( language, sourceFileName, objectDir, objectFileName, objectFileDir, - vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]); + vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config); objBuild.Outputs.push_back(objectFileName); if (firstForConfig) { @@ -1379,8 +1385,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( cmSystemTools::GetParentDirectory(source->GetFullPath())); std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags( - sourceDirectory, this->GeneratorTarget, language, false, false, - config); + sourceDirectory, this->GeneratorTarget, language, config, false, + cmLocalGenerator::IncludePathStyle::Default); vars["INCLUDES"] = cmStrCat(sourceDirectoryFlag, ' ', vars["INCLUDES"]); } @@ -1617,7 +1623,8 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( std::string const& language, std::string const& sourceFileName, std::string const& objectDir, std::string const& objectFileName, std::string const& objectFileDir, std::string const& flags, - std::string const& defines, std::string const& includes) + std::string const& defines, std::string const& includes, + std::string const& outputConfig) { if (!this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS")) { return; @@ -1679,8 +1686,8 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( compileObjectVars); } - std::string cmdLine = - this->GetLocalGenerator()->BuildCommandLine(compileCmds); + std::string cmdLine = this->GetLocalGenerator()->BuildCommandLine( + compileCmds, outputConfig, outputConfig); this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName); } diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 79dc622..3a28cef 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -162,7 +162,8 @@ protected: std::string const& language, std::string const& sourceFileName, std::string const& objectDir, std::string const& objectFileName, std::string const& objectFileDir, std::string const& flags, - std::string const& defines, std::string const& includes); + std::string const& defines, std::string const& includes, + std::string const& outputConfig); void AdditionalCleanFiles(const std::string& config); diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 92c5b52..7a04c47 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -139,8 +139,8 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements( gg->WriteBuild(this->GetCommonFileStream(), phonyBuild); } } else { - std::string command = - lg->BuildCommandLine(commands, "utility", this->GeneratorTarget); + std::string command = lg->BuildCommandLine( + commands, config, fileConfig, "utility", this->GeneratorTarget); std::string desc; cmProp echoStr = genTarget->GetProperty("EchoString"); if (echoStr) { diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 0369af0..68f40a9 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -359,7 +359,7 @@ void cmOrderDirectories::SetLinkExtensionInfo( std::string const& removeExtRegex) { this->LinkExtensions = linkExtensions; - this->RemoveLibraryExtension.compile(removeExtRegex.c_str()); + this->RemoveLibraryExtension.compile(removeExtRegex); } void cmOrderDirectories::CollectOriginalDirectories() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 2194b0f..0ff12d5 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -359,7 +359,20 @@ class cmMakefile; 3, 20, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0120, \ "The WriteCompilerDetectionHeader module is removed.", 3, 20, 0, \ - cmPolicies::WARN) + cmPolicies::WARN) \ + SELECT(POLICY, CMP0121, \ + "The list() command now validates parsing of index arguments.", 3, \ + 21, 0, cmPolicies::WARN) \ + SELECT( \ + POLICY, CMP0122, \ + "UseSWIG use standard library name conventions for csharp language.", 3, \ + 21, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0123, \ + "ARMClang cpu/arch compile and link flags must be set explicitly.", \ + 3, 21, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0124, \ + "foreach() loop variables are only available in the loop scope.", 3, \ + 21, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index ed32de9..acdb09f 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -59,6 +59,11 @@ bool cmProjectCommand(std::vector<std::string> const& args, mf.AddDefinition("PROJECT_NAME", projectName); + mf.AddDefinitionBool("PROJECT_IS_TOP_LEVEL", mf.IsRootMakefile()); + mf.AddCacheDefinition(projectName + "_IS_TOP_LEVEL", + mf.IsRootMakefile() ? "ON" : "OFF", + "Value Computed by CMake", cmStateEnums::STATIC); + // Set the CMAKE_PROJECT_NAME 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 diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index f8d18f2..153cb6d 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -119,7 +119,8 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( target->GetSafeProperty(this->kw().AUTORCC_EXECUTABLE); // We support Qt4, Qt5 and Qt6 - auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target.get()); + auto qtVersion = + cmQtAutoGenInitializer::GetQtVersion(target.get(), mocExec); bool const validQt = (qtVersion.first.Major == 4) || (qtVersion.first.Major == 5) || (qtVersion.first.Major == 6); diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index a1816f1..148591c 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -6,8 +6,8 @@ #include <deque> #include <initializer_list> #include <map> -#include <ostream> #include <set> +#include <sstream> // for basic_ios, istringstream #include <string> #include <unordered_set> #include <utility> @@ -294,6 +294,17 @@ bool InfoWriter::Save(std::string const& filename) return fileStream.Close(); } +void AddAutogenExecutableToDependencies( + cmQtAutoGenInitializer::GenVarsT const& genVars, + std::vector<std::string>& dependencies) +{ + if (genVars.ExecutableTarget != nullptr) { + dependencies.push_back(genVars.ExecutableTarget->Target->GetName()); + } else if (!genVars.Executable.empty()) { + dependencies.push_back(genVars.Executable); + } +} + } // End of unnamed namespace cmQtAutoGenInitializer::cmQtAutoGenInitializer( @@ -419,12 +430,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets() cmSystemTools::ConvertToUnixSlashes(this->Dir.Work); // Include directory - this->ConfigFileNames(this->Dir.Include, - cmStrCat(this->Dir.Build, "/include"), ""); - this->Dir.IncludeGenExp = this->Dir.Include.Default; - if (this->MultiConfig) { - this->Dir.IncludeGenExp += "_$<CONFIG>"; - } + this->ConfigFileNamesAndGenex(this->Dir.Include, this->Dir.IncludeGenExp, + cmStrCat(this->Dir.Build, "/include"), ""); } // Moc, Uic and _autogen target settings @@ -575,15 +582,9 @@ bool cmQtAutoGenInitializer::InitMoc() cmStrCat(this->Dir.Build, "/mocs_compilation.cpp"); this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default; } else { - this->ConfigFileNames(this->Moc.CompilationFile, - cmStrCat(this->Dir.Build, "/mocs_compilation"), - ".cpp"); - if (this->MultiConfig) { - this->Moc.CompilationFileGenex = - cmStrCat(this->Dir.Build, "/mocs_compilation_$<CONFIG>.cpp"_s); - } else { - this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default; - } + this->ConfigFileNamesAndGenex( + this->Moc.CompilationFile, this->Moc.CompilationFileGenex, + cmStrCat(this->Dir.Build, "/mocs_compilation"_s), ".cpp"_s); } // Moc predefs @@ -935,9 +936,35 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (!skipUic) { // Check if the .ui file has uic options std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS); - if (!uicOpts.empty()) { - this->Uic.UiFiles.emplace_back(fullPath, cmExpandedList(uicOpts)); + if (uicOpts.empty()) { + this->Uic.UiFilesNoOptions.emplace_back(fullPath); + } else { + this->Uic.UiFilesWithOptions.emplace_back(fullPath, + cmExpandedList(uicOpts)); } + + auto uiHeaderRelativePath = cmSystemTools::RelativePath( + this->LocalGen->GetCurrentSourceDirectory(), + cmSystemTools::GetFilenamePath(fullPath)); + + // Avoid creating a path containing adjacent slashes + if (!uiHeaderRelativePath.empty() && + uiHeaderRelativePath.back() != '/') { + uiHeaderRelativePath += '/'; + } + + auto uiHeaderFilePath = cmStrCat( + '/', uiHeaderRelativePath, "ui_"_s, + cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s); + + ConfigString uiHeader; + std::string uiHeaderGenex; + this->ConfigFileNamesAndGenex( + uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s), + uiHeaderFilePath); + + this->Uic.UiHeaders.emplace_back( + std::make_pair(uiHeader, uiHeaderGenex)); } else { // Register skipped .ui file this->Uic.SkipUi.insert(fullPath); @@ -1091,6 +1118,13 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() autogenByproducts.push_back(this->Moc.CompilationFileGenex); } + if (this->Uic.Enabled) { + for (const auto& file : this->Uic.UiHeaders) { + this->AddGeneratedSource(file.first, this->Uic); + autogenByproducts.push_back(file.second); + } + } + // Compose target comment std::string autogenComment; { @@ -1149,6 +1183,42 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() this->Makefile); } + if (!this->Uic.UiFilesNoOptions.empty() || + !this->Uic.UiFilesWithOptions.empty()) { + // Add a generated timestamp file + ConfigString timestampFile; + std::string timestampFileGenex; + ConfigFileNamesAndGenex(timestampFile, timestampFileGenex, + cmStrCat(this->Dir.Build, "/autouic"_s), + ".stamp"_s); + this->AddGeneratedSource(timestampFile, this->Uic); + + // Add a step in the pre-build command to touch the timestamp file + commandLines.push_back( + cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", "touch", + timestampFileGenex })); + + // UIC needs to be re-run if any of the known UI files change or the + // executable itself has been updated + auto uicDependencies = this->Uic.UiFilesNoOptions; + for (auto const& uiFile : this->Uic.UiFilesWithOptions) { + uicDependencies.push_back(uiFile.first); + } + AddAutogenExecutableToDependencies(this->Uic, uicDependencies); + + // Add a rule file to cause the target to build if a dependency has + // changed, which will trigger the pre-build command to run autogen + std::string no_main_dependency; + cmCustomCommandLines no_command_lines; + this->LocalGen->AddCustomCommandToOutput( + timestampFileGenex, uicDependencies, no_main_dependency, + no_command_lines, /*comment=*/"", this->Dir.Work.c_str(), + /*cmp0116=*/cmPolicies::NEW, /*replace=*/false, + /*escapeOldStyle=*/false, /*uses_terminal=*/false, + /*command_expand_lists=*/false, /*depfile=*/"", /*job_pool=*/"", + stdPipesUTF8); + } + // Add the pre-build command directly to bypass the OBJECT_LIBRARY // rejection in cmMakefile::AddCustomCommandToTarget because we know // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. @@ -1241,16 +1311,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() dependencies.clear(); dependencies.push_back(timestampTargetName); - if (this->Moc.ExecutableTarget != nullptr) { - dependencies.push_back(this->Moc.ExecutableTarget->Target->GetName()); - } else if (!this->Moc.Executable.empty()) { - dependencies.push_back(this->Moc.Executable); - } - if (this->Uic.ExecutableTarget != nullptr) { - dependencies.push_back(this->Uic.ExecutableTarget->Target->GetName()); - } else if (!this->Uic.Executable.empty()) { - dependencies.push_back(this->Uic.Executable); - } + AddAutogenExecutableToDependencies(this->Moc, dependencies); + AddAutogenExecutableToDependencies(this->Uic, dependencies); // Create the custom command that outputs the timestamp file. const char timestampFileName[] = "timestamp"; @@ -1589,7 +1651,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end()); info.SetArray("UIC_SKIP", uic_skip); - info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFiles, + info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFilesWithOptions, [](Json::Value& jval, UicT::UiFileT const& uiFile) { jval.resize(2u); jval[0u] = uiFile.first; @@ -1749,6 +1811,18 @@ void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString, } } +void cmQtAutoGenInitializer::ConfigFileNamesAndGenex( + ConfigString& configString, std::string& genex, cm::string_view const prefix, + cm::string_view const suffix) +{ + this->ConfigFileNames(configString, prefix, suffix); + if (this->MultiConfig) { + genex = cmStrCat(prefix, "_$<CONFIG>"_s, suffix); + } else { + genex = configString.Default; + } +} + void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString) { this->AddCleanFile(configString.Default); @@ -1759,8 +1833,63 @@ void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString) } } +static cmQtAutoGen::IntegerVersion parseMocVersion(std::string str) +{ + cmQtAutoGen::IntegerVersion result; + + static const std::string prelude = "moc "; + size_t pos = str.find(prelude); + if (pos == std::string::npos) { + return result; + } + + str.erase(0, prelude.size() + pos); + std::istringstream iss(str); + std::string major; + std::string minor; + if (!std::getline(iss, major, '.') || !std::getline(iss, minor, '.')) { + return result; + } + + result.Major = static_cast<unsigned int>(std::stoi(major)); + result.Minor = static_cast<unsigned int>(std::stoi(minor)); + return result; +} + +static cmQtAutoGen::IntegerVersion GetMocVersion( + const std::string& mocExecutablePath) +{ + std::string capturedStdOut; + int exitCode; + if (!cmSystemTools::RunSingleCommand({ mocExecutablePath, "--version" }, + &capturedStdOut, nullptr, &exitCode, + nullptr, cmSystemTools::OUTPUT_NONE)) { + return {}; + } + + if (exitCode != 0) { + return {}; + } + + return parseMocVersion(capturedStdOut); +} + +static std::string FindMocExecutableFromMocTarget(cmMakefile* makefile, + unsigned int qtMajorVersion) +{ + std::string result; + const std::string mocTargetName = + "Qt" + std::to_string(qtMajorVersion) + "::moc"; + cmTarget* mocTarget = makefile->FindTargetToUse(mocTargetName); + if (mocTarget) { + result = mocTarget->GetSafeProperty("IMPORTED_LOCATION"); + } + return result; +} + std::pair<cmQtAutoGen::IntegerVersion, unsigned int> -cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) +cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target, + std::string mocExecutable) { // Converts a char ptr to an unsigned int value auto toUInt = [](const char* const input) -> unsigned int { @@ -1835,6 +1964,21 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) } } } + + if (res.first.Major == 0) { + // We could not get the version number from variables or directory + // properties. This might happen if the find_package call for Qt is wrapped + // in a function. Try to find the moc executable path from the available + // targets and call "moc --version" to get the Qt version. + if (mocExecutable.empty()) { + mocExecutable = + FindMocExecutableFromMocTarget(target->Makefile, res.second); + } + if (!mocExecutable.empty()) { + res.first = GetMocVersion(mocExecutable); + } + } + return res; } diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index f7e126d..e76817b 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -98,9 +98,11 @@ public: , GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){}; }; - /** @return The detected Qt version and the required Qt major version. */ + /** @param mocExecutable The file path to the moc executable. Will be used as + fallback to query the version + @return The detected Qt version and the required Qt major version. */ static std::pair<IntegerVersion, unsigned int> GetQtVersion( - cmGeneratorTarget const* genTarget); + cmGeneratorTarget const* genTarget, std::string mocExecutable); cmQtAutoGenInitializer(cmQtAutoGenGlobalInitializer* globalInitializer, cmGeneratorTarget* genTarget, @@ -141,6 +143,8 @@ private: void ConfigFileNames(ConfigString& configString, cm::string_view prefix, cm::string_view suffix); + void ConfigFileNamesAndGenex(ConfigString& configString, std::string& genex, + cm::string_view prefix, cm::string_view suffix); void ConfigFileClean(ConfigString& configString); std::string GetMocBuildPath(MUFile const& muf); @@ -236,9 +240,12 @@ private: : GenVarsT(GenT::UIC){}; std::set<std::string> SkipUi; - std::vector<UiFileT> UiFiles; + std::vector<std::string> UiFilesNoOptions; + std::vector<UiFileT> UiFilesWithOptions; ConfigStrings<std::vector<std::string>> Options; std::vector<std::string> SearchPaths; + std::vector<std::pair<ConfigString /*ui header*/, std::string /*genex*/>> + UiHeaders; } Uic; /** rcc variables. */ diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 6e88e26..568926e 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -116,7 +116,7 @@ bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename) bool success = true; std::string const dirName = cmSystemTools::GetFilenamePath(filename); if (!dirName.empty()) { - success = cmSystemTools::MakeDirectory(dirName); + success = static_cast<bool>(cmSystemTools::MakeDirectory(dirName)); } return success; } diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index f583162..f5c195f 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -1588,14 +1588,14 @@ bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi( }; // Vicinity of the source - if (findUi(cmStrCat(sourceDirPrefix, this->UiName))) { - return true; - } if (!includePrefix.empty()) { if (findUi(cmStrCat(sourceDirPrefix, includePrefix, this->UiName))) { return true; } } + if (findUi(cmStrCat(sourceDirPrefix, this->UiName))) { + return true; + } // Additional AUTOUIC search paths auto const& searchPaths = this->UicConst().SearchPaths; if (!searchPaths.empty()) { @@ -2723,6 +2723,9 @@ void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap) std::string cmQtAutoMocUicT::CollapseFullPathTS(std::string const& path) const { std::lock_guard<std::mutex> guard(this->CMakeLibMutex_); +#if defined(__NVCOMPILER) + static_cast<void>(guard); // convince compiler var is used +#endif return cmSystemTools::CollapseFullPath(path, this->ProjectDirs().CurrentSource); } @@ -2962,6 +2965,9 @@ std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile( const char* filePath) { std::lock_guard<std::mutex> guard(this->CMakeLibMutex_); +#if defined(__NVCOMPILER) + static_cast<void>(guard); // convince compiler var is used +#endif auto const content = cmReadGccDepfile(filePath); if (!content || content->empty()) { return {}; diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 76a5ded..32ed687 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -175,7 +175,7 @@ private: #define CM_HEADER_REGEX "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$" #define CM_SOURCE_REGEX \ - "\\.(C|F|M|c|c\\+\\+|cc|cpp|mpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|" \ + "\\.(C|F|M|c|c\\+\\+|cc|cpp|mpp|cxx|ixx|cppm|cu|f|f90|for|fpp|ftn|m|mm|" \ "rc|def|r|odl|idl|hpj|bat)$" #define CM_PCH_REGEX "cmake_pch(_[^.]+)?\\.(h|hxx)$" diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index bf6925e..280e508 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -308,8 +308,9 @@ struct StanardLevelComputer std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping = { { "C", - StanardLevelComputer{ "C", std::vector<int>{ 90, 99, 11 }, - std::vector<std::string>{ "90", "99", "11" } } }, + StanardLevelComputer{ + "C", std::vector<int>{ 90, 99, 11, 17, 23 }, + std::vector<std::string>{ "90", "99", "11", "17", "23" } } }, { "CXX", StanardLevelComputer{ "CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 }, diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h index b871f5f..417f14d 100644 --- a/Source/cmStandardLexer.h +++ b/Source/cmStandardLexer.h @@ -50,6 +50,11 @@ # endif #endif +#if defined(__NVCOMPILER) +# pragma diag_suppress 111 /* statement is unreachable */ +# pragma diag_suppress 550 /* variable set but never used */ +#endif + /* Make sure isatty is available. */ #if defined(_WIN32) && !defined(__CYGWIN__) # include <io.h> diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 1e20abb..fbf47ef 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -16,16 +16,9 @@ #include "cmState.h" #include "cmStateDirectory.h" #include "cmStatePrivate.h" +#include "cmSystemTools.h" #include "cmVersion.h" -#if !defined(_WIN32) -# include <sys/utsname.h> -#endif - -#if defined(__CYGWIN__) -# include "cmSystemTools.h" -#endif - cmStateSnapshot::cmStateSnapshot(cmState* state) : State(state) { @@ -292,34 +285,26 @@ void InitializeContentFromParent(T& parentContent, T& thisContent, void cmStateSnapshot::SetDefaultDefinitions() { -/* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set. - With CMake must separate between target and host platform. In most cases - the tests for WIN32, UNIX and APPLE will be for the target system, so an - additional set of variables for the host system is required -> - CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE. - WIN32, UNIX and APPLE are now set in the platform files in - Modules/Platforms/. - To keep cmake scripts (-P) and custom language and compiler modules - working, these variables are still also set here in this place, but they - will be reset in CMakeSystemSpecificInformation.cmake before the platform - files are executed. */ -#if defined(_WIN32) - this->SetDefinition("WIN32", "1"); - this->SetDefinition("CMAKE_HOST_WIN32", "1"); - this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Windows"); -#else - this->SetDefinition("UNIX", "1"); - this->SetDefinition("CMAKE_HOST_UNIX", "1"); - -# if defined(__ANDROID__) - this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Android"); -# else - struct utsname uts_name; - if (uname(&uts_name) >= 0) { - this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname); + /* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set. + With CMake must separate between target and host platform. In most cases + the tests for WIN32, UNIX and APPLE will be for the target system, so an + additional set of variables for the host system is required -> + CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE. + WIN32, UNIX and APPLE are now set in the platform files in + Modules/Platforms/. + To keep cmake scripts (-P) and custom language and compiler modules + working, these variables are still also set here in this place, but they + will be reset in CMakeSystemSpecificInformation.cmake before the platform + files are executed. */ + cm::string_view hostSystemName = cmSystemTools::GetSystemName(); + this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", hostSystemName); + if (hostSystemName == "Windows") { + this->SetDefinition("WIN32", "1"); + this->SetDefinition("CMAKE_HOST_WIN32", "1"); + } else { + this->SetDefinition("UNIX", "1"); + this->SetDefinition("CMAKE_HOST_UNIX", "1"); } -# endif -#endif #if defined(__CYGWIN__) std::string legacy; if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) && diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 23fc3e0..5fa309d 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -241,7 +241,7 @@ bool RegexMatch(std::vector<std::string> const& args, status.GetMakefile().ClearMatches(); // Compile the regular expression. cmsys::RegularExpression re; - if (!re.compile(regex.c_str())) { + if (!re.compile(regex)) { std::string e = "sub-command REGEX, mode MATCH failed to compile regex \"" + regex + "\"."; @@ -283,7 +283,7 @@ bool RegexMatchAll(std::vector<std::string> const& args, status.GetMakefile().ClearMatches(); // Compile the regular expression. cmsys::RegularExpression re; - if (!re.compile(regex.c_str())) { + if (!re.compile(regex)) { std::string e = "sub-command REGEX, mode MATCHALL failed to compile regex \"" + regex + "\"."; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index c1ce7ec..9e46dab 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -86,6 +86,7 @@ # include <unistd.h> # include <sys/time.h> +# include <sys/types.h> #endif #if defined(_WIN32) && \ @@ -101,6 +102,10 @@ # include <malloc.h> /* for malloc/free on QNX */ #endif +#if !defined(_WIN32) && !defined(__ANDROID__) +# include <sys/utsname.h> +#endif + namespace { cmSystemTools::InterruptCallback s_InterruptCallback; @@ -951,21 +956,87 @@ void cmSystemTools::InitializeLibUV() #ifdef _WIN32 namespace { -bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname) +bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname, + cmSystemTools::Replace replace) { // Not only ignore any previous error, but clear any memory of it. SetLastError(0); - // Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file. - return MoveFileExW(oldname.c_str(), newname.c_str(), - MOVEFILE_REPLACE_EXISTING); + DWORD flags = 0; + if (replace == cmSystemTools::Replace::Yes) { + // Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file. + flags = flags | MOVEFILE_REPLACE_EXISTING; + } + + return MoveFileExW(oldname.c_str(), newname.c_str(), flags); } } #endif +bool cmSystemTools::CopySingleFile(const std::string& oldname, + const std::string& newname) +{ + return cmSystemTools::CopySingleFile(oldname, newname, CopyWhen::Always) == + CopyResult::Success; +} + +cmSystemTools::CopyResult cmSystemTools::CopySingleFile( + std::string const& oldname, std::string const& newname, CopyWhen when, + std::string* err) +{ + switch (when) { + case CopyWhen::Always: + break; + case CopyWhen::OnlyIfDifferent: + if (!FilesDiffer(oldname, newname)) { + return CopyResult::Success; + } + break; + } + + mode_t perm = 0; + cmsys::Status perms = SystemTools::GetPermissions(oldname, perm); + + // If files are the same do not copy + if (SystemTools::SameFile(oldname, newname)) { + return CopyResult::Success; + } + + cmsys::Status status; + status = cmsys::SystemTools::CloneFileContent(oldname, newname); + if (!status) { + // if cloning did not succeed, fall back to blockwise copy + status = cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname); + } + if (!status) { + if (err) { + *err = status.GetString(); + } + return CopyResult::Failure; + } + if (perms) { + status = SystemTools::SetPermissions(newname, perm); + if (!status) { + if (err) { + *err = status.GetString(); + } + return CopyResult::Failure; + } + } + return CopyResult::Success; +} + bool cmSystemTools::RenameFile(const std::string& oldname, const std::string& newname) { + return cmSystemTools::RenameFile(oldname, newname, Replace::Yes) == + RenameResult::Success; +} + +cmSystemTools::RenameResult cmSystemTools::RenameFile( + std::string const& oldname, std::string const& newname, Replace replace, + std::string* err) +{ #ifdef _WIN32 # ifndef INVALID_FILE_ATTRIBUTES # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) @@ -987,7 +1058,7 @@ bool cmSystemTools::RenameFile(const std::string& oldname, oldname_wstr, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); DWORD move_last_error = 0; - while (!cmMoveFile(oldname_wstr, newname_wstr) && --retry.Count) { + while (!cmMoveFile(oldname_wstr, newname_wstr, replace) && --retry.Count) { move_last_error = GetLastError(); // There was no error ==> the operation is not yet complete. @@ -1003,7 +1074,13 @@ bool cmSystemTools::RenameFile(const std::string& oldname, // 3) Windows Explorer has an associated directory already opened. if (move_last_error != ERROR_ACCESS_DENIED && move_last_error != ERROR_SHARING_VIOLATION) { - return false; + if (replace == Replace::No && move_last_error == ERROR_ALREADY_EXISTS) { + return RenameResult::NoReplace; + } + if (err) { + *err = cmsys::Status::Windows(move_last_error).GetString(); + } + return RenameResult::Failure; } DWORD const attrs = GetFileAttributesW(newname_wstr.c_str()); @@ -1027,10 +1104,37 @@ bool cmSystemTools::RenameFile(const std::string& oldname, save_restore_file_attributes.SetPath(newname_wstr); } SetLastError(move_last_error); - return retry.Count > 0; + if (retry.Count > 0) { + return RenameResult::Success; + } + if (replace == Replace::No && GetLastError() == ERROR_ALREADY_EXISTS) { + return RenameResult::NoReplace; + } + if (err) { + *err = cmsys::Status::Windows_GetLastError().GetString(); + } + return RenameResult::Failure; #else - /* On UNIX we have an OS-provided call to do this atomically. */ - return rename(oldname.c_str(), newname.c_str()) == 0; + // On UNIX we have OS-provided calls to create 'newname' atomically. + if (replace == Replace::No) { + if (link(oldname.c_str(), newname.c_str()) == 0) { + return RenameResult::Success; + } + if (errno == EEXIST) { + return RenameResult::NoReplace; + } + if (err) { + *err = cmsys::Status::POSIX_errno().GetString(); + } + return RenameResult::Failure; + } + if (rename(oldname.c_str(), newname.c_str()) == 0) { + return RenameResult::Success; + } + if (err) { + *err = cmsys::Status::POSIX_errno().GetString(); + } + return RenameResult::Failure; #endif } @@ -1693,7 +1797,7 @@ bool copy_data(struct archive* ar, struct archive* aw) return false; } } -# if !defined(__clang__) && !defined(__HP_aCC) +# if !defined(__clang__) && !defined(__NVCOMPILER) && !defined(__HP_aCC) return false; /* this should not happen but it quiets some compilers */ # endif } @@ -3021,7 +3125,7 @@ bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir) } return false; #else - return cmSystemTools::RemoveADirectory(dir); + return static_cast<bool>(cmSystemTools::RemoveADirectory(dir)); #endif } @@ -3054,9 +3158,9 @@ std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes) return out; } -bool cmSystemTools::CreateSymlink(const std::string& origName, - const std::string& newName, - std::string* errorMessage) +cmsys::Status cmSystemTools::CreateSymlink(std::string const& origName, + std::string const& newName, + std::string* errorMessage) { uv_fs_t req; int flags = 0; @@ -3067,7 +3171,9 @@ bool cmSystemTools::CreateSymlink(const std::string& origName, #endif int err = uv_fs_symlink(nullptr, &req, origName.c_str(), newName.c_str(), flags, nullptr); + cmsys::Status status; if (err) { + status = cmsys::Status::POSIX(-err); std::string e = "failed to create symbolic link '" + newName + "': " + uv_strerror(err); if (errorMessage) { @@ -3075,20 +3181,20 @@ bool cmSystemTools::CreateSymlink(const std::string& origName, } else { cmSystemTools::Error(e); } - return false; } - - return true; + return status; } -bool cmSystemTools::CreateLink(const std::string& origName, - const std::string& newName, - std::string* errorMessage) +cmsys::Status cmSystemTools::CreateLink(std::string const& origName, + std::string const& newName, + std::string* errorMessage) { uv_fs_t req; int err = uv_fs_link(nullptr, &req, origName.c_str(), newName.c_str(), nullptr); + cmsys::Status status; if (err) { + status = cmsys::Status::POSIX(-err); std::string e = "failed to create link '" + newName + "': " + uv_strerror(err); if (errorMessage) { @@ -3096,8 +3202,53 @@ bool cmSystemTools::CreateLink(const std::string& origName, } else { cmSystemTools::Error(e); } - return false; } + return status; +} - return true; +cm::string_view cmSystemTools::GetSystemName() +{ +#if defined(_WIN32) + return "Windows"; +#elif defined(__ANDROID__) + return "Android"; +#else + static struct utsname uts_name; + static bool initialized = false; + static cm::string_view systemName; + if (initialized) { + return systemName; + } + if (uname(&uts_name) >= 0) { + initialized = true; + systemName = uts_name.sysname; + + if (cmIsOff(systemName)) { + systemName = "UnknownOS"; + } + + // fix for BSD/OS, remove the / + static const cmsys::RegularExpression bsdOsRegex("BSD.OS"); + cmsys::RegularExpressionMatch match; + if (bsdOsRegex.find(uts_name.sysname, match)) { + systemName = "BSDOS"; + } + + // fix for GNU/kFreeBSD, remove the GNU/ + if (systemName.find("kFreeBSD") != cm::string_view::npos) { + systemName = "kFreeBSD"; + } + + // fix for CYGWIN and MSYS which have windows version in them + if (systemName.find("CYGWIN") != cm::string_view::npos) { + systemName = "CYGWIN"; + } + + if (systemName.find("MSYS") != cm::string_view::npos) { + systemName = "MSYS"; + } + return systemName; + } + return ""; +#endif } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 5bbbb0c..0aecf71 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -12,6 +12,7 @@ #include <cm/string_view> #include "cmsys/Process.h" +#include "cmsys/Status.hxx" // IWYU pragma: export #include "cmsys/SystemTools.hxx" // IWYU pragma: export #include "cmCryptoHash.h" @@ -128,10 +129,43 @@ public: static bool SimpleGlob(const std::string& glob, std::vector<std::string>& files, int type = 0); + enum class CopyWhen + { + Always, + OnlyIfDifferent, + }; + enum class CopyResult + { + Success, + Failure, + }; + + /** Copy a file. */ + static bool CopySingleFile(const std::string& oldname, + const std::string& newname); + static CopyResult CopySingleFile(std::string const& oldname, + std::string const& newname, CopyWhen when, + std::string* err = nullptr); + + enum class Replace + { + Yes, + No, + }; + enum class RenameResult + { + Success, + NoReplace, + Failure, + }; + /** Rename a file or directory within a single disk volume (atomic if possible). */ static bool RenameFile(const std::string& oldname, const std::string& newname); + static RenameResult RenameFile(std::string const& oldname, + std::string const& newname, Replace replace, + std::string* err = nullptr); //! Rename a file if contents are different, delete the source otherwise static void MoveFileIfDifferent(const std::string& source, @@ -455,15 +489,18 @@ public: /** Create a symbolic link if the platform supports it. Returns whether creation succeeded. */ - static bool CreateSymlink(const std::string& origName, - const std::string& newName, - std::string* errorMessage = nullptr); + static cmsys::Status CreateSymlink(std::string const& origName, + std::string const& newName, + std::string* errorMessage = nullptr); /** Create a hard link if the platform supports it. Returns whether creation succeeded. */ - static bool CreateLink(const std::string& origName, - const std::string& newName, - std::string* errorMessage = nullptr); + static cmsys::Status CreateLink(std::string const& origName, + std::string const& newName, + std::string* errorMessage = nullptr); + + /** Get the system name. */ + static cm::string_view GetSystemName(); private: static bool s_ForceUnixPaths; diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx index 78aa4b2..6e0366c 100644 --- a/Source/cmTransformDepfile.cxx +++ b/Source/cmTransformDepfile.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTransformDepfile.h" +#include <functional> #include <string> #include <type_traits> #include <utility> @@ -13,6 +14,7 @@ #include "cmGccDepfileReader.h" #include "cmGccDepfileReaderTypes.h" +#include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmSystemTools.h" @@ -34,10 +36,19 @@ void WriteFilenameGcc(cmsys::ofstream& fout, const std::string& filename) } } -void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg, - const cmGccDepfileContent& content) +void WriteDepfile(cmDepfileFormat format, cmsys::ofstream& fout, + const cmLocalGenerator& lg, + const cmGccDepfileContent& content) { const auto& binDir = lg.GetBinaryDirectory(); + std::function<std::string(const std::string&)> formatPath = + [&lg, &binDir](const std::string& path) -> std::string { + return lg.MaybeConvertToRelativePath(binDir, path); + }; + if (lg.GetGlobalGenerator()->GetName() == "Xcode") { + // full paths must be preserved for Xcode compliance + formatPath = [](const std::string& path) -> std::string { return path; }; + } for (auto const& dep : content) { bool first = true; @@ -46,15 +57,27 @@ void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg, fout << " \\\n "; } first = false; - WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, rule)); + WriteFilenameGcc(fout, formatPath(rule)); } fout << ':'; for (auto const& path : dep.paths) { fout << " \\\n "; - WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, path)); + WriteFilenameGcc(fout, formatPath(path)); } fout << '\n'; } + + if (format == cmDepfileFormat::MakeDepfile) { + // In this case, phony targets must be added for all dependencies + fout << "\n"; + for (auto const& dep : content) { + for (auto const& path : dep.paths) { + fout << "\n"; + WriteFilenameGcc(fout, formatPath(path)); + fout << ":\n"; + } + } + } } // tlog format : always windows paths on Windows regardless the generator @@ -112,7 +135,8 @@ bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg, } switch (format) { case cmDepfileFormat::GccDepfile: - WriteGccDepfile(fout, lg, content); + case cmDepfileFormat::MakeDepfile: + WriteDepfile(format, fout, lg, content); break; case cmDepfileFormat::VsTlog: WriteVsTlog(fout, lg, content); diff --git a/Source/cmTransformDepfile.h b/Source/cmTransformDepfile.h index c43a45f..c31e4ab 100644 --- a/Source/cmTransformDepfile.h +++ b/Source/cmTransformDepfile.h @@ -8,6 +8,7 @@ enum class cmDepfileFormat { GccDepfile, VsTlog, + MakeDepfile }; class cmLocalGenerator; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 965ac3e..ba0cf9c 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -545,7 +545,7 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element( "CudaToolkitCustomDir", this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString() + - "nvcc"); + this->GlobalGenerator->GetPlatformToolsetCudaNvccSubdirString()); } } @@ -654,8 +654,9 @@ void cmVisualStudio10TargetGenerator::Generate() std::string cudaPath = customDir.empty() ? "$(VCTargetsPath)\\BuildCustomizations\\" : customDir + - "CUDAVisualStudioIntegration\\extras\\" - "visual_studio_integration\\MSBuildExtensions\\"; + this->GlobalGenerator + ->GetPlatformToolsetCudaVSIntegrationSubdirString() + + "extras\\visual_studio_integration\\MSBuildExtensions\\"; Elem(e1, "Import") .Attribute("Project", std::move(cudaPath) + "CUDA " + @@ -747,8 +748,9 @@ void cmVisualStudio10TargetGenerator::Generate() std::string cudaPath = customDir.empty() ? "$(VCTargetsPath)\\BuildCustomizations\\" : customDir + - "CUDAVisualStudioIntegration\\extras\\" - "visual_studio_integration\\MSBuildExtensions\\"; + this->GlobalGenerator + ->GetPlatformToolsetCudaVSIntegrationSubdirString() + + "extras\\visual_studio_integration\\MSBuildExtensions\\"; Elem(e1, "Import") .Attribute("Project", std::move(cudaPath) + "CUDA " + @@ -2275,6 +2277,20 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) std::back_inserter(exclude_configs)); Elem e2(e1, tool); + bool isCSharp = (si.Source->GetLanguage() == "CSharp"); + if (isCSharp && exclude_configs.size() > 0) { + std::stringstream conditions; + bool firstConditionSet{ false }; + for (const auto& ci : include_configs) { + if (firstConditionSet) { + conditions << " Or "; + } + conditions << "('$(Configuration)|$(Platform)'=='" + + this->Configurations[ci] + "|" + this->Platform + "')"; + firstConditionSet = true; + } + e2.Attribute("Condition", conditions.str()); + } this->WriteSource(e2, si.Source); bool useNativeUnityBuild = false; @@ -2319,7 +2335,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { e2.Element("PrecompiledHeader", "NotUsing"); } - if (!exclude_configs.empty()) { + if (!isCSharp && !exclude_configs.empty()) { this->WriteExcludeFromBuild(e2, exclude_configs); } } @@ -5035,7 +5051,9 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink( { // For out of source files, we first check if a matching source group // for this file exists, otherwise we check if the path relative to current - // source- or binary-dir is used within the link and return that + // source- or binary-dir is used within the link and return that. + // In case of .cs files we can't do that automatically for files in the + // binary directory, because this leads to compilation errors. std::string link; std::string sourceGroupedFile; std::string const& fullFileName = source->GetFullPath(); @@ -5057,7 +5075,8 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink( link = sourceGroupedFile; } else if (cmHasPrefix(fullFileName, srcDir)) { link = fullFileName.substr(srcDir.length() + 1); - } else if (cmHasPrefix(fullFileName, binDir)) { + } else if (!cmHasSuffix(fullFileName, ".cs") && + cmHasPrefix(fullFileName, binDir)) { link = fullFileName.substr(binDir.length() + 1); } else if (cmProp l = source->GetProperty("VS_CSHARP_Link")) { link = *l; diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx deleted file mode 100644 index 7fc33e6..0000000 --- a/Source/cmVisualStudio10ToolsetOptions.cxx +++ /dev/null @@ -1,143 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmVisualStudio10ToolsetOptions.h" - -#include "cmAlgorithms.h" -#include "cmIDEFlagTable.h" -#include "cmVisualStudioGeneratorOptions.h" - -std::string cmVisualStudio10ToolsetOptions::GetClFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if (toolset == "v142") { - return "v142"; - } else if (toolset == "v141") { - return "v141"; - } else if (useToolset == "v140") { - return "v140"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetCSharpFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if (useToolset == "v142") { - return "v142"; - } else if (useToolset == "v141") { - return "v141"; - } else if (useToolset == "v140") { - return "v140"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetRcFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if ((useToolset == "v140") || (useToolset == "v141") || - (useToolset == "v142")) { - return "v14"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetLibFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if ((useToolset == "v140") || (useToolset == "v141") || - (useToolset == "v142")) { - return "v14"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetLinkFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if (useToolset == "v142") { - return "v142"; - } else if (useToolset == "v141") { - return "v141"; - } else if (useToolset == "v140") { - return "v140"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetMasmFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if ((useToolset == "v140") || (useToolset == "v141") || - (useToolset == "v142")) { - return "v14"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetToolsetName( - std::string const& name, std::string const& toolset) const -{ - static_cast<void>(name); - std::size_t length = toolset.length(); - - if (cmHasLiteralSuffix(toolset, "_xp")) { - length -= 3; - } - - return toolset.substr(0, length); -} diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h deleted file mode 100644 index 85cc2b6..0000000 --- a/Source/cmVisualStudio10ToolsetOptions.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#pragma once - -#include "cmConfigure.h" // IWYU pragma: keep - -#include <string> - -/** \class cmVisualStudio10ToolsetOptions - * \brief Retrieves toolset options for MSBuild. - * - * cmVisualStudio10ToolsetOptions manages toolsets within MSBuild - */ -class cmVisualStudio10ToolsetOptions -{ -public: - std::string GetClFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetCSharpFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetRcFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetLibFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetLinkFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetMasmFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetToolsetName(std::string const& name, - std::string const& toolset) const; -}; diff --git a/Source/cmWorkingDirectory.cxx b/Source/cmWorkingDirectory.cxx index 5700b1c..12fae12 100644 --- a/Source/cmWorkingDirectory.cxx +++ b/Source/cmWorkingDirectory.cxx @@ -19,7 +19,7 @@ cmWorkingDirectory::~cmWorkingDirectory() bool cmWorkingDirectory::SetDirectory(std::string const& newdir) { - if (cmSystemTools::ChangeDirectory(newdir) == 0) { + if (cmSystemTools::ChangeDirectory(newdir)) { this->ResultCode = 0; return true; } diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx index 15f83e0..216d3f0 100644 --- a/Source/cm_codecvt.cxx +++ b/Source/cm_codecvt.cxx @@ -31,6 +31,7 @@ codecvt::codecvt(Encoding e) // We don't know which ANSI encoding to use for other platforms than // Windows so we don't do any conversion there case codecvt::UTF8: + case codecvt::UTF8_WITH_BOM: // Assume internal encoding is UTF-8 case codecvt::None: // No encoding diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx index 1860211..b73204f 100644 --- a/Source/cm_codecvt.hxx +++ b/Source/cm_codecvt.hxx @@ -14,6 +14,7 @@ public: { None, UTF8, + UTF8_WITH_BOM, ANSI }; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 4d03821..4130f5f 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -28,6 +28,7 @@ #include "cm_sys_stat.h" +#include "cmCMakePath.h" #include "cmCMakePresetsFile.h" #include "cmCommandLineArgument.h" #include "cmCommands.h" @@ -208,9 +209,9 @@ cmake::cmake(Role role, cmState::Mode mode) }; // The "c" extension MUST precede the "C" extension. - setupExts( - this->CLikeSourceFileExtensions, - { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "mpp", "m", "M", "mm" }); + setupExts(this->CLikeSourceFileExtensions, + { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "mpp", "m", "M", + "mm", "ixx", "cppm" }); setupExts(this->HeaderFileExtensions, { "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" }); setupExts(this->CudaFileExtensions, { "cu" }); @@ -493,6 +494,31 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) return true; }; + auto PrefixLambda = [&](std::string const& path, cmake* state) -> bool { + const std::string var = "CMAKE_INSTALL_PREFIX"; + cmStateEnums::CacheEntryType type = cmStateEnums::PATH; + cmCMakePath absolutePath(path); + if (absolutePath.IsAbsolute()) { +#ifndef CMAKE_BOOTSTRAP + state->UnprocessedPresetVariables.erase(var); +#endif + state->ProcessCacheArg(var, path, type); + return true; + } + cmSystemTools::Error("Absolute paths are required for --install-prefix"); + return false; + }; + + auto ToolchainLambda = [&](std::string const& path, cmake* state) -> bool { + const std::string var = "CMAKE_TOOLCHAIN_FILE"; + cmStateEnums::CacheEntryType type = cmStateEnums::FILEPATH; +#ifndef CMAKE_BOOTSTRAP + state->UnprocessedPresetVariables.erase(var); +#endif + state->ProcessCacheArg(var, path, type); + return true; + }; + std::vector<CommandArgument> arguments = { CommandArgument{ "-D", "-D must be followed with VAR=VALUE.", CommandArgument::Values::One, DefineLambda }, @@ -511,8 +537,14 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) state->ReadListFile(args, path); return true; } }, + CommandArgument{ "-P", "-P must be followed by a file name.", CommandArgument::Values::One, ScriptLambda }, + CommandArgument{ "--toolchain", "No file specified for --toolchain", + CommandArgument::Values::One, ToolchainLambda }, + CommandArgument{ "--install-prefix", + "No install directory specified for --install-prefix", + CommandArgument::Values::One, PrefixLambda }, CommandArgument{ "--find-package", CommandArgument::Values::Zero, [&](std::string const&, cmake*) -> bool { findPackageMode = true; @@ -649,7 +681,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) this->GlobalGenerator->CreateGenerationObjects(); const auto& lg = this->GlobalGenerator->LocalGenerators[0]; std::string includeFlags = - lg->GetIncludeFlags(includeDirs, nullptr, language); + lg->GetIncludeFlags(includeDirs, nullptr, language, std::string()); std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS"); printf("%s %s\n", includeFlags.c_str(), definitions.c_str()); @@ -815,6 +847,11 @@ void cmake::SetArgs(const std::vector<std::string>& args) CommandArgument::Values::One, PlatformLambda }, CommandArgument{ "-T", "No toolset specified for -T", CommandArgument::Values::One, ToolsetLamda }, + CommandArgument{ "--toolchain", "No file specified for --toolchain", + CommandArgument::Values::One, IgnoreAndTrueLambda }, + CommandArgument{ "--install-prefix", + "No install directory specified for --install-prefix", + CommandArgument::Values::One, IgnoreAndTrueLambda }, CommandArgument{ "--check-build-system", CommandArgument::Values::Two, [](std::string const& value, cmake* state) -> bool { @@ -1194,11 +1231,17 @@ void cmake::SetArgs(const std::vector<std::string>& args) "\": Invalid macro expansion")); return; } + if (!expandedPreset->ConditionResult) { + cmSystemTools::Error(cmStrCat("Could not use disabled preset \"", + preset->second.Unexpanded.Name, "\"")); + return; + } - if (!this->State->IsCacheLoaded() && !haveBArg) { + if (!this->State->IsCacheLoaded() && !haveBArg && + !expandedPreset->BinaryDir.empty()) { this->SetHomeOutputDirectory(expandedPreset->BinaryDir); } - if (!this->GlobalGenerator) { + if (!this->GlobalGenerator && !expandedPreset->Generator.empty()) { if (!this->CreateAndSetGlobalGenerator(expandedPreset->Generator, false)) { return; @@ -1207,6 +1250,21 @@ void cmake::SetArgs(const std::vector<std::string>& args) this->UnprocessedPresetVariables = expandedPreset->CacheVariables; this->UnprocessedPresetEnvironment = expandedPreset->Environment; + if (!expandedPreset->InstallDir.empty() && + this->State->GetInitializedCacheValue("CMAKE_INSTALL_PREFIX") == + nullptr) { + this->UnprocessedPresetVariables["CMAKE_INSTALL_PREFIX"] = { + "PATH", expandedPreset->InstallDir + }; + } + if (!expandedPreset->ToolchainFile.empty() && + this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE") == + nullptr) { + this->UnprocessedPresetVariables["CMAKE_TOOLCHAIN_FILE"] = { + "FILEPATH", expandedPreset->ToolchainFile + }; + } + if (!expandedPreset->ArchitectureStrategy || expandedPreset->ArchitectureStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set) { @@ -3023,12 +3081,16 @@ static bool cmakeCheckStampFile(const std::string& stampName) cmsys::ofstream stamp(stampTemp.c_str()); stamp << "# CMake generation timestamp file for this directory.\n"; } - if (cmSystemTools::RenameFile(stampTemp, stampName)) { + std::string err; + if (cmSystemTools::RenameFile(stampTemp, stampName, + cmSystemTools::Replace::Yes, &err) == + cmSystemTools::RenameResult::Success) { // CMake does not need to re-run because the stamp file is up-to-date. return true; } cmSystemTools::RemoveFile(stampTemp); - cmSystemTools::Error("Cannot restore timestamp " + stampName); + cmSystemTools::Error( + cmStrCat("Cannot restore timestamp \"", stampName, "\": ", err)); return false; } @@ -3133,6 +3195,14 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets, return 1; } + if (!expandedPreset->ConditionResult) { + cmSystemTools::Error(cmStrCat("Cannot use disabled build preset in ", + this->GetHomeDirectory(), ": \"", + presetName, '"')); + settingsFile.PrintBuildPresetList(); + return 1; + } + auto configurePresetPair = settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset); if (configurePresetPair == settingsFile.ConfigurePresets.end()) { @@ -3159,7 +3229,9 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets, return 1; } - dir = expandedConfigurePreset->BinaryDir; + if (!expandedConfigurePreset->BinaryDir.empty()) { + dir = expandedConfigurePreset->BinaryDir; + } this->UnprocessedPresetEnvironment = expandedPreset->Environment; this->ProcessPresetEnvironment(); diff --git a/Source/cmake.h b/Source/cmake.h index 82e028c..9b29098 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -712,6 +712,10 @@ private: "Specify toolset name if supported by generator." }, \ { "-A <platform-name>", \ "Specify platform name if supported by generator." }, \ + { "--toolchain <file>", \ + "Specify toolchain file [CMAKE_TOOLCHAIN_FILE]." }, \ + { "--install-prefix <directory>", \ + "Specify install directory [CMAKE_INSTALL_PREFIX]." }, \ { "-Wdev", "Enable developer warnings." }, \ { "-Wno-dev", "Suppress developer warnings." }, \ { "-Werror=dev", "Make developer warnings errors." }, \ @@ -739,6 +743,8 @@ private: F(c_std_90) \ F(c_std_99) \ F(c_std_11) \ + F(c_std_17) \ + F(c_std_23) \ FOR_EACH_C90_FEATURE(F) \ FOR_EACH_C99_FEATURE(F) \ FOR_EACH_C11_FEATURE(F) diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 6713cc3..2c2ae4d 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -74,7 +74,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, std::vector<std::string>::const_iterator argEnd); namespace { -void CMakeCommandUsage(const char* program) +void CMakeCommandUsage(std::string const& program) { std::ostringstream errorStream; @@ -704,7 +704,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, } else if (args[2] == "--ignore-eol") { filesDiffer = cmsys::SystemTools::TextFilesDiffer(args[3], args[4]); } else { - CMakeCommandUsage(args[0].c_str()); + CMakeCommandUsage(args[0]); return 2; } @@ -1085,7 +1085,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, std::string const& directory = args[2]; if (!cmSystemTools::FileExists(directory)) { cmSystemTools::Error("Directory does not exist for chdir command: " + - args[2]); + directory); return 1; } @@ -1152,7 +1152,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, << "\n"; return 1; } - if (!cmSystemTools::CreateSymlink(args[2], args[3])) { + if (!cmSystemTools::CreateSymlink(args[2], destinationFileName)) { return 1; } return 0; @@ -1161,12 +1161,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, // Command to create a hard link. Fails on platforms not // supporting them. if (args[1] == "create_hardlink" && args.size() == 4) { - const char* SouceFileName = args[2].c_str(); - const char* destinationFileName = args[3].c_str(); + std::string const& sourceFileName = args[2]; + std::string const& destinationFileName = args[3]; - if (!cmSystemTools::FileExists(SouceFileName)) { + if (!cmSystemTools::FileExists(sourceFileName)) { std::cerr << "failed to create hard link because source path '" - << SouceFileName << "' does not exist \n"; + << sourceFileName << "' does not exist \n"; return 1; } @@ -1180,7 +1180,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, return 1; } - if (!cmSystemTools::CreateLink(args[2], args[3])) { + if (!cmSystemTools::CreateLink(sourceFileName, destinationFileName)) { return 1; } return 0; @@ -1527,6 +1527,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, format = cmDepfileFormat::GccDepfile; } else if (args[3] == "vstlog") { format = cmDepfileFormat::VsTlog; + } else if (args[3] == "makedepfile") { + format = cmDepfileFormat::MakeDepfile; } else { return 1; } @@ -1560,7 +1562,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, } } - CMakeCommandUsage(args[0].c_str()); + CMakeCommandUsage(args[0]); return 1; } @@ -1601,14 +1603,18 @@ int cmcmd::SymlinkLibrary(std::vector<std::string> const& args) cmSystemTools::ConvertToUnixSlashes(soName); cmSystemTools::ConvertToUnixSlashes(name); if (soName != realName) { - if (!cmcmd::SymlinkInternal(realName, soName)) { - cmSystemTools::ReportLastSystemError("cmake_symlink_library"); + cmsys::Status status = cmcmd::SymlinkInternal(realName, soName); + if (!status) { + cmSystemTools::Error( + cmStrCat("cmake_symlink_library: System Error: ", status.GetString())); result = 1; } } if (name != soName) { - if (!cmcmd::SymlinkInternal(soName, name)) { - cmSystemTools::ReportLastSystemError("cmake_symlink_library"); + cmsys::Status status = cmcmd::SymlinkInternal(soName, name); + if (!status) { + cmSystemTools::Error( + cmStrCat("cmake_symlink_library: System Error: ", status.GetString())); result = 1; } } @@ -1621,15 +1627,18 @@ int cmcmd::SymlinkExecutable(std::vector<std::string> const& args) std::string const& realName = args[2]; std::string const& name = args[3]; if (name != realName) { - if (!cmcmd::SymlinkInternal(realName, name)) { - cmSystemTools::ReportLastSystemError("cmake_symlink_executable"); + cmsys::Status status = cmcmd::SymlinkInternal(realName, name); + if (!status) { + cmSystemTools::Error(cmStrCat("cmake_symlink_executable: System Error: ", + status.GetString())); result = 1; } } return result; } -bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link) +cmsys::Status cmcmd::SymlinkInternal(std::string const& file, + std::string const& link) { if (cmSystemTools::FileExists(link) || cmSystemTools::FileIsSymlink(link)) { cmSystemTools::RemoveFile(link); diff --git a/Source/cmcmd.h b/Source/cmcmd.h index a2e0b1e..ba78edb 100644 --- a/Source/cmcmd.h +++ b/Source/cmcmd.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cmsys/Status.hxx" + #include "cmCryptoHash.h" class cmConsoleBuf; @@ -28,8 +30,8 @@ protected: cmCryptoHash::Algo algo); static int SymlinkLibrary(std::vector<std::string> const& args); static int SymlinkExecutable(std::vector<std::string> const& args); - static bool SymlinkInternal(std::string const& file, - std::string const& link); + static cmsys::Status SymlinkInternal(std::string const& file, + std::string const& link); static int ExecuteEchoColor(std::vector<std::string> const& args); static int ExecuteLinkScript(std::vector<std::string> const& args); static int WindowsCEEnvironment(const char* version, diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 3c331d3..cad27fa 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -50,13 +50,15 @@ static const char* cmDocumentationOptions[][2] = { "given number of jobs." }, { "-Q,--quiet", "Make ctest quiet." }, { "-O <file>, --output-log <file>", "Output to log file" }, + { "--output-junit <file>", "Output test results to JUnit XML file." }, { "-N,--show-only[=format]", "Disable actual execution of tests. The optional 'format' defines the " "format of the test information and can be 'human' for the current text " "format or 'json-v1' for json format. Defaults to 'human'." }, { "-L <regex>, --label-regex <regex>", - "Run tests with labels matching " - "regular expression." }, + "Run tests with labels matching regular expression. " + "With multiple -L, run tests where each " + "regular expression matches at least one label." }, { "-R <regex>, --tests-regex <regex>", "Run tests matching regular " "expression." }, @@ -64,8 +66,9 @@ static const char* cmDocumentationOptions[][2] = { "Exclude tests matching regular " "expression." }, { "-LE <regex>, --label-exclude <regex>", - "Exclude tests with labels " - "matching regular expression." }, + "Exclude tests with labels matching regular expression. " + "With multiple -LE, exclude tests where each " + "regular expression matches at least one label." }, { "-FA <regex>, --fixture-exclude-any <regex>", "Do not automatically " "add any tests for " diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index b0a8542..ef615b3 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -98,6 +98,16 @@ foreach(p endif() endforeach() +# Some configure checks depend upon the deployment target. Clear checks when +# the deployment target changes. +if (APPLE) + if (NOT CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL KWSYS_LAST_OSX_DEPLOYMENT_TARGET) + unset(KWSYS_CXX_HAS_UTIMENSAT CACHE) + endif () + set(KWSYS_LAST_OSX_DEPLOYMENT_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}" + CACHE INTERNAL "remember the last deployment target to trigger configure rechecks") +endif () + #----------------------------------------------------------------------------- # If a namespace is not specified, use "kwsys" and enable testing. # This should be the case only when kwsys is not included inside @@ -142,6 +152,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR) set(KWSYS_USE_MD5 1) set(KWSYS_USE_Process 1) set(KWSYS_USE_RegularExpression 1) + set(KWSYS_USE_Status 1) set(KWSYS_USE_System 1) set(KWSYS_USE_SystemTools 1) set(KWSYS_USE_CommandLineArguments 1) @@ -157,6 +168,7 @@ if(KWSYS_USE_SystemTools) set(KWSYS_USE_Directory 1) set(KWSYS_USE_FStream 1) set(KWSYS_USE_Encoding 1) + set(KWSYS_USE_Status 1) endif() if(KWSYS_USE_Glob) set(KWSYS_USE_Directory 1) @@ -177,6 +189,7 @@ if(KWSYS_USE_System) endif() if(KWSYS_USE_Directory) set(KWSYS_USE_Encoding 1) + set(KWSYS_USE_Status 1) endif() if(KWSYS_USE_DynamicLoader) set(KWSYS_USE_Encoding 1) @@ -630,7 +643,7 @@ set(KWSYS_HXX_FILES Configure String) # Add selected C++ classes. set(cppclasses Directory DynamicLoader Encoding Glob RegularExpression SystemTools - CommandLineArguments FStream SystemInformation ConsoleBuf + CommandLineArguments FStream SystemInformation ConsoleBuf Status ) foreach(cpp ${cppclasses}) if(KWSYS_USE_${cpp}) @@ -963,6 +976,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR) # C++ tests set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testConfigure.cxx + testStatus.cxx testSystemTools.cxx testCommandLineArguments.cxx testCommandLineArguments1.cxx diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx index 0c2190a..2e8aa83 100644 --- a/Source/kwsys/Directory.cxx +++ b/Source/kwsys/Directory.cxx @@ -94,7 +94,7 @@ void Directory::Clear() namespace KWSYS_NAMESPACE { -bool Directory::Load(const std::string& name, std::string* errorMessage) +Status Directory::Load(std::string const& name, std::string* errorMessage) { this->Clear(); intptr_t srchHandle; @@ -121,7 +121,11 @@ bool Directory::Load(const std::string& name, std::string* errorMessage) delete[] buf; if (srchHandle == -1) { - return 0; + Status status = Status::POSIX_errno(); + if (errorMessage) { + *errorMessage = status.GetString(); + } + return status; } // Loop through names @@ -129,7 +133,14 @@ bool Directory::Load(const std::string& name, std::string* errorMessage) this->Internal->Files.push_back(Encoding::ToNarrow(data.name)); } while (_wfindnext(srchHandle, &data) != -1); this->Internal->Path = name; - return _findclose(srchHandle) != -1; + if (_findclose(srchHandle) == -1) { + Status status = Status::POSIX_errno(); + if (errorMessage) { + *errorMessage = status.GetString(); + } + return status; + } + return Status::Success(); } unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, @@ -152,6 +163,20 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, delete[] buf; if (srchHandle == -1) { + if (errorMessage) { + if (unsigned int errorId = GetLastError()) { + LPSTR message = nullptr; + DWORD size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&message, 0, nullptr); + *errorMessage = std::string(message, size); + LocalFree(message); + } else { + *errorMessage = "Unknown error."; + } + } return 0; } @@ -192,7 +217,7 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, namespace KWSYS_NAMESPACE { -bool Directory::Load(const std::string& name, std::string* errorMessage) +Status Directory::Load(std::string const& name, std::string* errorMessage) { this->Clear(); @@ -203,7 +228,7 @@ bool Directory::Load(const std::string& name, std::string* errorMessage) if (errorMessage != nullptr) { *errorMessage = std::string(strerror(errno)); } - return false; + return Status::POSIX_errno(); } errno = 0; @@ -214,12 +239,12 @@ bool Directory::Load(const std::string& name, std::string* errorMessage) if (errorMessage != nullptr) { *errorMessage = std::string(strerror(errno)); } - return false; + return Status::POSIX_errno(); } this->Internal->Path = name; closedir(dir); - return true; + return Status::Success(); } unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in index 7bc9db0..d501116 100644 --- a/Source/kwsys/Directory.hxx.in +++ b/Source/kwsys/Directory.hxx.in @@ -4,6 +4,7 @@ #define @KWSYS_NAMESPACE@_Directory_hxx #include <@KWSYS_NAMESPACE@/Configure.h> +#include <@KWSYS_NAMESPACE@/Status.hxx> #include <string> @@ -32,10 +33,9 @@ public: /** * Load the specified directory and load the names of the files - * in that directory. 0 is returned if the directory can not be - * opened, 1 if it is opened. + * in that directory. */ - bool Load(const std::string&, std::string* errorMessage = nullptr); + Status Load(std::string const&, std::string* errorMessage = nullptr); /** * Return the number of files in the current directory. diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in index e8474e2..fd39775 100644 --- a/Source/kwsys/Glob.hxx.in +++ b/Source/kwsys/Glob.hxx.in @@ -54,6 +54,9 @@ public: Glob(); ~Glob(); + Glob(const Glob&) = delete; + void operator=(const Glob&) = delete; + //! Find all files that match the pattern. bool FindFiles(const std::string& inexpr, GlobMessages* messages = nullptr); @@ -124,10 +127,6 @@ protected: std::vector<std::string> VisitedSymlinks; bool ListDirs; bool RecurseListDirs; - -private: - Glob(const Glob&) = delete; - void operator=(const Glob&) = delete; }; } // namespace @KWSYS_NAMESPACE@ diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index e1e7721..5ae846a 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -122,6 +122,10 @@ static inline void kwsysProcess_usleep(unsigned int msec) /* The maximum amount to read from a pipe at a time. */ #define KWSYSPE_PIPE_BUFFER_SIZE 1024 +#if defined(__NVCOMPILER) +# pragma diag_suppress 550 /* variable set but never used (in FD_ZERO) */ +#endif + /* Keep track of times using a signed representation. Switch to the native (possibly unsigned) representation only when calling native functions. */ diff --git a/Source/kwsys/Status.cxx b/Source/kwsys/Status.cxx new file mode 100644 index 0000000..503d1e1 --- /dev/null +++ b/Source/kwsys/Status.cxx @@ -0,0 +1,60 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Status.hxx) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "Status.hxx.in" +#endif + +#include <cerrno> +#include <cstring> +#include <string> + +#if defined(_WIN32) +# include <windows.h> +#endif + +namespace KWSYS_NAMESPACE { + +Status Status::POSIX_errno() +{ + return Status::POSIX(errno); +} + +#ifdef _WIN32 +Status Status::Windows_GetLastError() +{ + return Status::Windows(GetLastError()); +} +#endif + +std::string Status::GetString() const +{ + std::string err; + switch (this->Kind_) { + case Kind::Success: + err = "Success"; + break; + case Kind::POSIX: + err = strerror(this->POSIX_); + break; +#ifdef _WIN32 + case Kind::Windows: { + LPSTR message = NULL; + DWORD size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, this->Windows_, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&message, 0, NULL); + err = std::string(message, size); + LocalFree(message); + } break; +#endif + }; + return err; +} + +} // namespace KWSYS_NAMESPACE diff --git a/Source/kwsys/Status.hxx.in b/Source/kwsys/Status.hxx.in new file mode 100644 index 0000000..feb5b84 --- /dev/null +++ b/Source/kwsys/Status.hxx.in @@ -0,0 +1,101 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ +#ifndef @KWSYS_NAMESPACE@_Status_hxx +#define @KWSYS_NAMESPACE@_Status_hxx + +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +#include <string> + +namespace @KWSYS_NAMESPACE@ { + +/** \class Status + * \brief OS-specific status of a system operation. + */ +class @KWSYS_NAMESPACE@_EXPORT Status +{ +public: + enum class Kind + { + Success, + POSIX, +#ifdef _WIN32 + Windows, +#endif + }; + + /** Construct with kind "Success". */ + Status() = default; + + /** Construct with kind "Success". */ + static Status Success() { return Status(); } + + /** Construct with kind "POSIX" using given errno-style value. */ + static Status POSIX(int e) + { + Status s(Kind::POSIX); + s.POSIX_ = e; + return s; + } + + /** Construct with kind "POSIX" using errno. */ + static Status POSIX_errno(); + +#ifdef _WIN32 + /** Construct with kind "Windows" using given GetLastError()-style value. */ + static Status Windows(unsigned int e) + { + Status s(Kind::Windows); + s.Windows_ = e; + return s; + } + + /** Construct with kind "Windows" using GetLastError(). */ + static Status Windows_GetLastError(); +#endif + + /** Return true on "Success", false otherwise. */ + explicit operator bool() const { return this->Kind_ == Kind::Success; } + + /** Return the kind of status. */ + Kind GetKind() const { return this->Kind_; } + + /** If the kind is "POSIX", returns the errno-style value. + Otherwise, returns 0. */ + int GetPOSIX() const + { + return this->Kind_ == Kind::POSIX ? this->POSIX_ : 0; + } + +#ifdef _WIN32 + /** If the kind is "Windows", returns the GetLastError()-style value. + Otherwise, returns 0. */ + int GetWindows() const + { + return this->Kind_ == Kind::Windows ? this->Windows_ : 0; + } +#endif + + /** Return a human-readable description of the status. */ + std::string GetString() const; + +private: + Status(Kind kind) + : Kind_(kind) + { + } + + Kind Kind_ = Kind::Success; + + union + { + int POSIX_; +#ifdef _WIN32 + unsigned int Windows_; +#endif + }; +}; + +} // namespace @KWSYS_NAMESPACE@ + +#endif diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 7743eab..117ff8d 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -3472,6 +3472,10 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() // We want to record the total number of cores in this->NumberOfPhysicalCPU // (checking only the first proc) std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores"); + if (Cores.empty()) { + // Linux Sparc is different + Cores = this->ExtractValueFromCpuInfoFile(buffer, "ncpus probed"); + } auto NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str()); NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u); this->NumberOfPhysicalCPU = @@ -3490,6 +3494,9 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() if (this->NumberOfPhysicalCPU <= 0) { this->NumberOfPhysicalCPU = 1; } + if (this->NumberOfLogicalCPU == 0) { + this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; + } // LogicalProcessorsPerPhysical>1 => SMT. this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU; @@ -3503,8 +3510,18 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() else { // Linux Sparc: CPU speed is in Hz and encoded in hexadecimal CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer, "Cpu0ClkTck"); - this->CPUSpeedInMHz = - static_cast<float>(strtoull(CPUSpeed.c_str(), nullptr, 16)) / 1000000.0f; + if (!CPUSpeed.empty()) { + this->CPUSpeedInMHz = + static_cast<float>(strtoull(CPUSpeed.c_str(), nullptr, 16)) / + 1000000.0f; + } else { + // if the kernel is build as Sparc32 it's in decimal, note the different + // case + CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer, "CPU0ClkTck"); + this->CPUSpeedInMHz = + static_cast<float>(strtoull(CPUSpeed.c_str(), nullptr, 10)) / + 1000000.0f; + } } #endif diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 6144d9c..2518845 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -244,7 +244,7 @@ inline int Chdir(const std::string& dir) return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str()); } inline void Realpath(const std::string& path, std::string& resolved_path, - std::string* errorMessage = 0) + std::string* errorMessage = nullptr) { std::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path); wchar_t* ptemp; @@ -882,21 +882,24 @@ FILE* SystemTools::Fopen(const std::string& file, const char* mode) #endif } -bool SystemTools::MakeDirectory(const char* path, const mode_t* mode) +Status SystemTools::MakeDirectory(const char* path, const mode_t* mode) { if (!path) { - return false; + return Status::POSIX(EINVAL); } return SystemTools::MakeDirectory(std::string(path), mode); } -bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode) +Status SystemTools::MakeDirectory(std::string const& path, const mode_t* mode) { - if (SystemTools::PathExists(path)) { - return SystemTools::FileIsDirectory(path); - } if (path.empty()) { - return false; + return Status::POSIX(EINVAL); + } + if (SystemTools::PathExists(path)) { + if (SystemTools::FileIsDirectory(path)) { + return Status::Success(); + } + return Status::POSIX(EEXIST); } std::string dir = path; SystemTools::ConvertToUnixSlashes(dir); @@ -914,15 +917,11 @@ bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode) ++pos; } topdir = dir; - if (Mkdir(topdir, mode) != 0) { - // if it is some other error besides directory exists - // then return false - if (errno != EEXIST) { - return false; - } + if (Mkdir(topdir, mode) != 0 && errno != EEXIST) { + return Status::POSIX_errno(); } - return true; + return Status::Success(); } // replace replace with with as many times as it shows up in source. @@ -1411,18 +1410,18 @@ int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf) #endif } -bool SystemTools::Touch(const std::string& filename, bool create) +Status SystemTools::Touch(std::string const& filename, bool create) { if (!SystemTools::FileExists(filename)) { if (create) { FILE* file = Fopen(filename, "a+b"); if (file) { fclose(file); - return true; + return Status::Success(); } - return false; + return Status::POSIX_errno(); } else { - return true; + return Status::Success(); } } #if defined(_WIN32) && !defined(__CYGWIN__) @@ -1430,31 +1429,32 @@ bool SystemTools::Touch(const std::string& filename, bool create) FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); if (!h) { - return false; + return Status::Windows_GetLastError(); } FILETIME mtime; GetSystemTimeAsFileTime(&mtime); if (!SetFileTime(h, 0, 0, &mtime)) { + Status status = Status::Windows_GetLastError(); CloseHandle(h); - return false; + return status; } CloseHandle(h); #elif KWSYS_CXX_HAS_UTIMENSAT // utimensat is only available on newer Unixes and macOS 10.13+ if (utimensat(AT_FDCWD, filename.c_str(), nullptr, 0) < 0) { - return false; + return Status::POSIX_errno(); } #else // fall back to utimes if (utimes(filename.c_str(), nullptr) < 0) { - return false; + return Status::POSIX_errno(); } #endif - return true; + return Status::Success(); } -bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2, - int* result) +Status SystemTools::FileTimeCompare(std::string const& f1, + std::string const& f2, int* result) { // Default to same time. *result = 0; @@ -1462,11 +1462,11 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2, // POSIX version. Use stat function to get file modification time. struct stat s1; if (stat(f1.c_str(), &s1) != 0) { - return false; + return Status::POSIX_errno(); } struct stat s2; if (stat(f2.c_str(), &s2) != 0) { - return false; + return Status::POSIX_errno(); } # if KWSYS_CXX_STAT_HAS_ST_MTIM // Compare using nanosecond resolution. @@ -1504,17 +1504,17 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2, WIN32_FILE_ATTRIBUTE_DATA f2d; if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f1).c_str(), GetFileExInfoStandard, &f1d)) { - return false; + return Status::Windows_GetLastError(); } if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f2).c_str(), GetFileExInfoStandard, &f2d)) { - return false; + return Status::Windows_GetLastError(); } // Compare the file times using resolution provided by system call. *result = (int)CompareFileTime(&f1d.ftLastWriteTime, &f2d.ftLastWriteTime); #endif - return true; + return Status::Success(); } // Return a capitalized string (i.e the first letter is uppercased, all other @@ -2129,8 +2129,8 @@ static std::string FileInDir(const std::string& source, const std::string& dir) return new_destination + '/' + SystemTools::GetFilenameName(source); } -bool SystemTools::CopyFileIfDifferent(const std::string& source, - const std::string& destination) +Status SystemTools::CopyFileIfDifferent(std::string const& source, + std::string const& destination) { // special check for a destination that is a directory // FilesDiffer does not handle file to directory compare @@ -2147,7 +2147,7 @@ bool SystemTools::CopyFileIfDifferent(const std::string& source, } } // at this point the files must be the same so return true - return true; + return Status::Success(); } #define KWSYS_ST_BUFFER 4096 @@ -2273,16 +2273,13 @@ bool SystemTools::TextFilesDiffer(const std::string& path1, return false; } -/** - * Blockwise copy source to destination file - */ -static bool CopyFileContentBlockwise(const std::string& source, - const std::string& destination) +Status SystemTools::CopyFileContentBlockwise(std::string const& source, + std::string const& destination) { // Open files kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); if (!fin) { - return false; + return Status::POSIX_errno(); } // try and remove the destination file so that read only destination files @@ -2294,7 +2291,7 @@ static bool CopyFileContentBlockwise(const std::string& source, kwsys::ofstream fout(destination.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); if (!fout) { - return false; + return Status::POSIX_errno(); } // This copy loop is very sensitive on certain platforms with @@ -2323,10 +2320,10 @@ static bool CopyFileContentBlockwise(const std::string& source, fout.close(); if (!fout) { - return false; + return Status::POSIX_errno(); } - return true; + return Status::Success(); } /** @@ -2341,13 +2338,13 @@ static bool CopyFileContentBlockwise(const std::string& source, * - The underlying filesystem does not support file cloning * - An unspecified error occurred */ -static bool CloneFileContent(const std::string& source, - const std::string& destination) +Status SystemTools::CloneFileContent(std::string const& source, + std::string const& destination) { #if defined(__linux) && defined(FICLONE) int in = open(source.c_str(), O_RDONLY); if (in < 0) { - return false; + return Status::POSIX_errno(); } SystemTools::RemoveFile(destination); @@ -2355,38 +2352,42 @@ static bool CloneFileContent(const std::string& source, int out = open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (out < 0) { + Status status = Status::POSIX_errno(); close(in); - return false; + return status; } - int result = ioctl(out, FICLONE, in); + Status status = Status::Success(); + if (ioctl(out, FICLONE, in) < 0) { + status = Status::POSIX_errno(); + } close(in); close(out); - if (result < 0) { - return false; - } - - return true; + return status; #else (void)source; (void)destination; - return false; + return Status::POSIX(ENOSYS); #endif } /** * Copy a file named by "source" to the file named by "destination". */ -bool SystemTools::CopyFileAlways(const std::string& source, - const std::string& destination) +Status SystemTools::CopyFileAlways(std::string const& source, + std::string const& destination) { + Status status; mode_t perm = 0; - bool perms = SystemTools::GetPermissions(source, perm); + Status perms = SystemTools::GetPermissions(source, perm); std::string real_destination = destination; if (SystemTools::FileIsDirectory(source)) { - SystemTools::MakeDirectory(destination); + status = SystemTools::MakeDirectory(destination); + if (!status) { + return status; + } } else { // If destination is a directory, try to create a file with the same // name as the source in that directory. @@ -2403,30 +2404,34 @@ bool SystemTools::CopyFileAlways(const std::string& source, } // If files are the same do not copy if (SystemTools::SameFile(source, real_destination)) { - return true; + return status; } // Create destination directory - - SystemTools::MakeDirectory(destination_dir); - - if (!CloneFileContent(source, real_destination)) { - // if cloning did not succeed, fall back to blockwise copy - if (!CopyFileContentBlockwise(source, real_destination)) { - return false; + if (!destination_dir.empty()) { + status = SystemTools::MakeDirectory(destination_dir); + if (!status) { + return status; } } + + status = SystemTools::CloneFileContent(source, real_destination); + // if cloning did not succeed, fall back to blockwise copy + if (!status) { + status = SystemTools::CopyFileContentBlockwise(source, real_destination); + } + if (!status) { + return status; + } } if (perms) { - if (!SystemTools::SetPermissions(real_destination, perm)) { - return false; - } + status = SystemTools::SetPermissions(real_destination, perm); } - return true; + return status; } -bool SystemTools::CopyAFile(const std::string& source, - const std::string& destination, bool always) +Status SystemTools::CopyAFile(std::string const& source, + std::string const& destination, bool always) { if (always) { return SystemTools::CopyFileAlways(source, destination); @@ -2439,18 +2444,21 @@ bool SystemTools::CopyAFile(const std::string& source, * Copy a directory content from "source" directory to the directory named by * "destination". */ -bool SystemTools::CopyADirectory(const std::string& source, - const std::string& destination, bool always) +Status SystemTools::CopyADirectory(std::string const& source, + std::string const& destination, bool always) { + Status status; Directory dir; - if (dir.Load(source) == 0) { - return false; + status = dir.Load(source); + if (!status) { + return status; } - size_t fileNum; - if (!SystemTools::MakeDirectory(destination)) { - return false; + status = SystemTools::MakeDirectory(destination); + if (!status) { + return status; } - for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { + + for (size_t fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 && strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..") != 0) { std::string fullPath = source; @@ -2460,18 +2468,20 @@ bool SystemTools::CopyADirectory(const std::string& source, std::string fullDestPath = destination; fullDestPath += "/"; fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum)); - if (!SystemTools::CopyADirectory(fullPath, fullDestPath, always)) { - return false; + status = SystemTools::CopyADirectory(fullPath, fullDestPath, always); + if (!status) { + return status; } } else { - if (!SystemTools::CopyAFile(fullPath, destination, always)) { - return false; + status = SystemTools::CopyAFile(fullPath, destination, always); + if (!status) { + return status; } } } } - return true; + return status; } // return size of file; also returns zero if no file exists @@ -2553,26 +2563,26 @@ std::string SystemTools::GetLastSystemError() return strerror(e); } -bool SystemTools::RemoveFile(const std::string& source) +Status SystemTools::RemoveFile(std::string const& source) { #ifdef _WIN32 std::wstring const& ws = Encoding::ToWindowsExtendedPath(source); if (DeleteFileW(ws.c_str())) { - return true; + return Status::Success(); } DWORD err = GetLastError(); if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) { - return true; + return Status::Success(); } if (err != ERROR_ACCESS_DENIED) { - return false; + return Status::Windows(err); } /* The file may be read-only. Try adding write permission. */ mode_t mode; if (!SystemTools::GetPermissions(source, mode) || !SystemTools::SetPermissions(source, S_IWRITE)) { SetLastError(err); - return false; + return Status::Windows(err); } const DWORD DIRECTORY_SOFT_LINK_ATTRS = @@ -2581,26 +2591,29 @@ bool SystemTools::RemoveFile(const std::string& source) if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & DIRECTORY_SOFT_LINK_ATTRS) == DIRECTORY_SOFT_LINK_ATTRS && RemoveDirectoryW(ws.c_str())) { - return true; + return Status::Success(); } if (DeleteFileW(ws.c_str()) || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND) { - return true; + return Status::Success(); } /* Try to restore the original permissions. */ SystemTools::SetPermissions(source, mode); SetLastError(err); - return false; + return Status::Windows(err); #else - return unlink(source.c_str()) == 0 || errno == ENOENT; + if (unlink(source.c_str()) != 0 && errno != ENOENT) { + return Status::POSIX_errno(); + } + return Status::Success(); #endif } -bool SystemTools::RemoveADirectory(const std::string& source) +Status SystemTools::RemoveADirectory(std::string const& source) { // Add write permission to the directory so we can modify its // content to remove files and directories from it. - mode_t mode; + mode_t mode = 0; if (SystemTools::GetPermissions(source, mode)) { #if defined(_WIN32) && !defined(__CYGWIN__) mode |= S_IWRITE; @@ -2610,8 +2623,13 @@ bool SystemTools::RemoveADirectory(const std::string& source) SystemTools::SetPermissions(source, mode); } + Status status; Directory dir; - dir.Load(source); + status = dir.Load(source); + if (!status) { + return status; + } + size_t fileNum; for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 && @@ -2621,18 +2639,23 @@ bool SystemTools::RemoveADirectory(const std::string& source) fullPath += dir.GetFile(static_cast<unsigned long>(fileNum)); if (SystemTools::FileIsDirectory(fullPath) && !SystemTools::FileIsSymlink(fullPath)) { - if (!SystemTools::RemoveADirectory(fullPath)) { - return false; + status = SystemTools::RemoveADirectory(fullPath); + if (!status) { + return status; } } else { - if (!SystemTools::RemoveFile(fullPath)) { - return false; + status = SystemTools::RemoveFile(fullPath); + if (!status) { + return status; } } } } - return (Rmdir(source) == 0); + if (Rmdir(source) != 0) { + status = Status::POSIX_errno(); + } + return status; } /** @@ -3026,44 +3049,49 @@ bool SystemTools::FileIsFIFO(const std::string& name) } #if defined(_WIN32) && !defined(__CYGWIN__) -bool SystemTools::CreateSymlink(const std::string&, const std::string&) +Status SystemTools::CreateSymlink(std::string const&, std::string const&) { - return false; + return Status::Windows(ERROR_NOT_SUPPORTED); } #else -bool SystemTools::CreateSymlink(const std::string& origName, - const std::string& newName) +Status SystemTools::CreateSymlink(std::string const& origName, + std::string const& newName) { - return symlink(origName.c_str(), newName.c_str()) >= 0; + if (symlink(origName.c_str(), newName.c_str()) < 0) { + return Status::POSIX_errno(); + } + return Status::Success(); } #endif #if defined(_WIN32) && !defined(__CYGWIN__) -bool SystemTools::ReadSymlink(const std::string&, std::string&) +Status SystemTools::ReadSymlink(std::string const&, std::string&) { - return false; + return Status::Windows(ERROR_NOT_SUPPORTED); } #else -bool SystemTools::ReadSymlink(const std::string& newName, - std::string& origName) +Status SystemTools::ReadSymlink(std::string const& newName, + std::string& origName) { char buf[KWSYS_SYSTEMTOOLS_MAXPATH + 1]; int count = static_cast<int>( readlink(newName.c_str(), buf, KWSYS_SYSTEMTOOLS_MAXPATH)); - if (count >= 0) { - // Add null-terminator. - buf[count] = 0; - origName = buf; - return true; - } else { - return false; + if (count < 0) { + return Status::POSIX_errno(); } + // Add null-terminator. + buf[count] = 0; + origName = buf; + return Status::Success(); } #endif -int SystemTools::ChangeDirectory(const std::string& dir) +Status SystemTools::ChangeDirectory(std::string const& dir) { - return Chdir(dir); + if (Chdir(dir) < 0) { + return Status::POSIX_errno(); + } + return Status::Success(); } std::string SystemTools::GetCurrentWorkingDirectory() @@ -3929,7 +3957,7 @@ bool SystemTools::FileIsFullPath(const char* in_name) bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len) { -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) // On Windows, the name must be at least two characters long. if (len < 2) { return false; @@ -3960,7 +3988,8 @@ bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len) return false; } -bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath) +Status SystemTools::GetShortPath(std::string const& path, + std::string& shortPath) { #if defined(_WIN32) && !defined(__CYGWIN__) std::string tempPath = path; // create a buffer @@ -3980,14 +4009,14 @@ bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath) } if (ret == 0) { - return false; + return Status::Windows_GetLastError(); } else { shortPath = Encoding::ToNarrow(&buffer[0]); - return true; + return Status::Success(); } #else shortPath = path; - return true; + return Status::Success(); #endif } @@ -4088,21 +4117,21 @@ int SystemTools::GetTerminalWidth() return width; } -bool SystemTools::GetPermissions(const char* file, mode_t& mode) +Status SystemTools::GetPermissions(const char* file, mode_t& mode) { if (!file) { - return false; + return Status::POSIX(EINVAL); } return SystemTools::GetPermissions(std::string(file), mode); } -bool SystemTools::GetPermissions(const std::string& file, mode_t& mode) +Status SystemTools::GetPermissions(std::string const& file, mode_t& mode) { #if defined(_WIN32) DWORD attr = GetFileAttributesW(Encoding::ToWindowsExtendedPath(file).c_str()); if (attr == INVALID_FILE_ATTRIBUTES) { - return false; + return Status::Windows_GetLastError(); } if ((attr & FILE_ATTRIBUTE_READONLY) != 0) { mode = (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6)); @@ -4125,27 +4154,27 @@ bool SystemTools::GetPermissions(const std::string& file, mode_t& mode) #else struct stat st; if (stat(file.c_str(), &st) < 0) { - return false; + return Status::POSIX_errno(); } mode = st.st_mode; #endif - return true; + return Status::Success(); } -bool SystemTools::SetPermissions(const char* file, mode_t mode, - bool honor_umask) +Status SystemTools::SetPermissions(const char* file, mode_t mode, + bool honor_umask) { if (!file) { - return false; + return Status::POSIX(EINVAL); } return SystemTools::SetPermissions(std::string(file), mode, honor_umask); } -bool SystemTools::SetPermissions(const std::string& file, mode_t mode, - bool honor_umask) +Status SystemTools::SetPermissions(std::string const& file, mode_t mode, + bool honor_umask) { if (!SystemTools::PathExists(file)) { - return false; + return Status::POSIX(ENOENT); } if (honor_umask) { mode_t currentMask = umask(0); @@ -4158,10 +4187,10 @@ bool SystemTools::SetPermissions(const std::string& file, mode_t mode, if (chmod(file.c_str(), mode) < 0) #endif { - return false; + return Status::POSIX_errno(); } - return true; + return Status::Success(); } std::string SystemTools::GetParentDirectory(const std::string& fileOrDir) diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 74dc176..e5d115e 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -4,6 +4,7 @@ #define @KWSYS_NAMESPACE@_SystemTools_hxx #include <@KWSYS_NAMESPACE@/Configure.hxx> +#include <@KWSYS_NAMESPACE@/Status.hxx> #include <iosfwd> #include <map> @@ -339,7 +340,7 @@ public: /** Change the modification time or create a file */ - static bool Touch(const std::string& filename, bool create); + static Status Touch(std::string const& filename, bool create); /** * Compare file modification times. @@ -347,8 +348,8 @@ public: * When true is returned, result has -1, 0, +1 for * f1 older, same, or newer than f2. */ - static bool FileTimeCompare(const std::string& f1, const std::string& f2, - int* result); + static Status FileTimeCompare(std::string const& f1, std::string const& f2, + int* result); /** * Get the file extension (including ".") needed for an executable @@ -507,7 +508,7 @@ public: * For windows return the short path for the given path, * Unix just a pass through */ - static bool GetShortPath(const std::string& path, std::string& result); + static Status GetShortPath(std::string const& path, std::string& result); /** * Read line from file. Make sure to read a full line and truncates it if @@ -553,16 +554,16 @@ public: * can make a full path even if none of the directories existed * prior to calling this function. */ - static bool MakeDirectory(const char* path, const mode_t* mode = nullptr); - static bool MakeDirectory(const std::string& path, - const mode_t* mode = nullptr); + static Status MakeDirectory(const char* path, const mode_t* mode = nullptr); + static Status MakeDirectory(std::string const& path, + const mode_t* mode = nullptr); /** * Copy the source file to the destination file only * if the two files differ. */ - static bool CopyFileIfDifferent(const std::string& source, - const std::string& destination); + static Status CopyFileIfDifferent(std::string const& source, + std::string const& destination); /** * Compare the contents of two files. Return true if different @@ -578,6 +579,17 @@ public: const std::string& path2); /** + * Blockwise copy source to destination file + */ + static Status CopyFileContentBlockwise(std::string const& source, + std::string const& destination); + /** + * Clone the source file to the destination file + */ + static Status CloneFileContent(std::string const& source, + std::string const& destination); + + /** * Return true if the two files are the same file */ static bool SameFile(const std::string& file1, const std::string& file2); @@ -585,16 +597,16 @@ public: /** * Copy a file. */ - static bool CopyFileAlways(const std::string& source, - const std::string& destination); + static Status CopyFileAlways(std::string const& source, + std::string const& destination); /** * Copy a file. If the "always" argument is true the file is always * copied. If it is false, the file is copied only if it is new or * has changed. */ - static bool CopyAFile(const std::string& source, - const std::string& destination, bool always = true); + static Status CopyAFile(std::string const& source, + std::string const& destination, bool always = true); /** * Copy content directory to another directory with all files and @@ -602,19 +614,19 @@ public: * always copied. If it is false, only files that have changed or * are new are copied. */ - static bool CopyADirectory(const std::string& source, - const std::string& destination, - bool always = true); + static Status CopyADirectory(std::string const& source, + std::string const& destination, + bool always = true); /** * Remove a file */ - static bool RemoveFile(const std::string& source); + static Status RemoveFile(std::string const& source); /** * Remove a directory */ - static bool RemoveADirectory(const std::string& source); + static Status RemoveADirectory(std::string const& source); /** * Get the maximum full file path length @@ -708,14 +720,14 @@ public: * Create a symbolic link if the platform supports it. Returns whether * creation succeeded. */ - static bool CreateSymlink(const std::string& origName, - const std::string& newName); + static Status CreateSymlink(std::string const& origName, + std::string const& newName); /** * Read the contents of a symbolic link. Returns whether reading * succeeded. */ - static bool ReadSymlink(const std::string& newName, std::string& origName); + static Status ReadSymlink(std::string const& newName, std::string& origName); /** * Try to locate the file 'filename' in the directory 'dir'. @@ -765,12 +777,12 @@ public: * WARNING: A non-thread-safe method is currently used to get the umask * if a honor_umask parameter is set to true. */ - static bool GetPermissions(const char* file, mode_t& mode); - static bool GetPermissions(const std::string& file, mode_t& mode); - static bool SetPermissions(const char* file, mode_t mode, - bool honor_umask = false); - static bool SetPermissions(const std::string& file, mode_t mode, - bool honor_umask = false); + static Status GetPermissions(const char* file, mode_t& mode); + static Status GetPermissions(std::string const& file, mode_t& mode); + static Status SetPermissions(const char* file, mode_t mode, + bool honor_umask = false); + static Status SetPermissions(std::string const& file, mode_t mode, + bool honor_umask = false); /** ----------------------------------------------------------------- * Time Manipulation Routines @@ -867,7 +879,7 @@ public: /** * Change directory to the directory specified */ - static int ChangeDirectory(const std::string& dir); + static Status ChangeDirectory(std::string const& dir); /** * Get the result of strerror(errno) diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c index 4d1b46c..20bb5fe 100644 --- a/Source/kwsys/Terminal.c +++ b/Source/kwsys/Terminal.c @@ -10,7 +10,7 @@ #endif /* Configure support for this platform. */ -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) # define KWSYS_TERMINAL_SUPPORT_CONSOLE #endif #if !defined(_WIN32) @@ -173,6 +173,14 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, } } + /* Disable color according to http://bixense.com/clicolors/ convention. */ + { + const char* clicolor = getenv("CLICOLOR"); + if (clicolor && strcmp(clicolor, "0") == 0) { + return 0; + } + } + /* GNU make 4.1+ may tell us that its output is destined for a TTY. */ { const char* termout = getenv("MAKE_TERMOUT"); diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx index eb3ca32..06a22dc 100644 --- a/Source/kwsys/testDirectory.cxx +++ b/Source/kwsys/testDirectory.cxx @@ -88,7 +88,7 @@ int _nonExistentDirectoryTest() errorMessage = "foo"; // Increment res failure if directory lists - res += testdir.Load(testdirpath, &errorMessage); + res += testdir.Load(testdirpath, &errorMessage) ? 1 : 0; #if !defined(_WIN32) || defined(__CYGWIN__) // Increment res failure if errorMessage is unmodified res += (errorMessage == "foo"); @@ -120,7 +120,7 @@ int _copyDirectoryTest() std::cerr << destination << " shouldn't exist before test" << std::endl; return 2; } - const bool copysuccess = SystemTools::CopyADirectory(source, destination); + const Status copysuccess = SystemTools::CopyADirectory(source, destination); const bool destinationexists = SystemTools::PathExists(destination); if (copysuccess) { std::cerr << "CopyADirectory should have returned false" << std::endl; diff --git a/Source/kwsys/testStatus.cxx b/Source/kwsys/testStatus.cxx new file mode 100644 index 0000000..f85ef42 --- /dev/null +++ b/Source/kwsys/testStatus.cxx @@ -0,0 +1,117 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying +file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Status.hxx) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "Status.hxx.in" +#endif + +#include <cerrno> +#include <iostream> + +#ifdef _WIN32 +# include <windows.h> +#endif + +int testStatus(int, char* []) +{ + bool res = true; + { + kwsys::Status status; + if (status.GetKind() != kwsys::Status::Kind::Success) { + std::cerr << "Status default constructor does not produce Success\n"; + res = false; + } + + status = kwsys::Status::Success(); + if (status.GetKind() != kwsys::Status::Kind::Success) { + std::cerr << "Status Success constructor does not produce Success\n"; + res = false; + } + if (!status) { + std::cerr << "Status Success kind is not true\n"; + res = false; + } + if (status.GetPOSIX() != 0) { + std::cerr << "Status Success kind does not return POSIX 0\n"; + res = false; + } +#ifdef _WIN32 + if (status.GetWindows() != 0) { + std::cerr << "Status Success kind does not return Windows 0\n"; + res = false; + } +#endif + if (status.GetString() != "Success") { + std::cerr << "Status Success kind does not return \"Success\" string\n"; + res = false; + } + + status = kwsys::Status::POSIX(EINVAL); + if (status.GetKind() != kwsys::Status::Kind::POSIX) { + std::cerr << "Status POSIX constructor does not produce POSIX\n"; + res = false; + } + if (status) { + std::cerr << "Status POSIX kind is not false\n"; + res = false; + } + if (status.GetPOSIX() != EINVAL) { + std::cerr << "Status POSIX kind does not preserve POSIX value\n"; + res = false; + } +#ifdef _WIN32 + if (status.GetWindows() != 0) { + std::cerr << "Status POSIX kind does not return Windows 0\n"; + res = false; + } +#endif + if (status.GetString().empty()) { + std::cerr << "Status POSIX kind returns empty string\n"; + res = false; + } + errno = ENOENT; + status = kwsys::Status::POSIX_errno(); + if (status.GetPOSIX() != ENOENT) { + std::cerr << "Status POSIX_errno did not use errno\n"; + res = false; + } + errno = 0; + +#ifdef _WIN32 + status = kwsys::Status::Windows(ERROR_INVALID_PARAMETER); + if (status.GetKind() != kwsys::Status::Kind::Windows) { + std::cerr << "Status Windows constructor does not produce Windows\n"; + res = false; + } + if (status) { + std::cerr << "Status Windows kind is not false\n"; + res = false; + } + if (status.GetWindows() != ERROR_INVALID_PARAMETER) { + std::cerr << "Status Windows kind does not preserve Windows value\n"; + res = false; + } + if (status.GetPOSIX() != 0) { + std::cerr << "Status Windows kind does not return POSIX 0\n"; + res = false; + } + if (status.GetString().empty()) { + std::cerr << "Status Windows kind returns empty string\n"; + res = false; + } + + SetLastError(ERROR_FILE_NOT_FOUND); + status = kwsys::Status::Windows_GetLastError(); + if (status.GetWindows() != ERROR_FILE_NOT_FOUND) { + std::cerr << "Status Windows_GetLastError did not use GetLastError()\n"; + res = false; + } + SetLastError(ERROR_SUCCESS); +#endif + } + return res ? 0 : 1; +} diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index cfa420d..04f66ff 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -290,15 +290,17 @@ static bool CheckFileOperations() res = false; } + std::cerr << std::oct; // Reset umask -#if defined(_WIN32) && !defined(__CYGWIN__) +#ifdef __MSYS__ + mode_t fullMask = S_IWRITE; +#elif defined(_WIN32) && !defined(__CYGWIN__) // NOTE: Windows doesn't support toggling _S_IREAD. mode_t fullMask = _S_IWRITE; #else // On a normal POSIX platform, we can toggle all permissions. mode_t fullMask = S_IRWXU | S_IRWXG | S_IRWXO; #endif - mode_t orig_umask = umask(fullMask); // Test file permissions without umask mode_t origPerm, thisPerm; @@ -370,6 +372,7 @@ static bool CheckFileOperations() res = false; } + mode_t orig_umask = umask(fullMask); // Test setting file permissions while honoring umask if (!kwsys::SystemTools::SetPermissions(testNewFile, fullMask, true)) { std::cerr << "Problem with SetPermissions (3) for: " << testNewFile @@ -496,6 +499,7 @@ static bool CheckFileOperations() } #endif + std::cerr << std::dec; return res; } @@ -1093,7 +1097,7 @@ static bool CheckCopyFileIfDifferent() ret = false; continue; } - std::string bdata = readFile("file_b"); + std::string bdata = readFile(cptarget); if (diff_test_cases[i].a != bdata) { std::cerr << "Incorrect CopyFileIfDifferent file contents in test case " << i + 1 << "." << std::endl; |