diff options
Diffstat (limited to 'Source')
244 files changed, 5165 insertions, 3677 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index c57f713..564e647 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -1,6 +1,11 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. +# To ensure maximum portability across various compilers and platforms +# deactivate any compiler extensions +set(CMAKE_C_EXTENSIONS FALSE) +set(CMAKE_CXX_EXTENSIONS FALSE) + include(CheckIncludeFile) # Check if we can build support for ELF parsing. if(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD") @@ -354,6 +359,7 @@ set(SRCS cmMakefileTargetGenerator.cxx cmMakefileExecutableTargetGenerator.cxx cmMakefileLibraryTargetGenerator.cxx + cmMakefileProfilingData.cxx cmMakefileUtilityTargetGenerator.cxx cmMessageType.h cmMessenger.cxx @@ -484,6 +490,8 @@ set(SRCS cmBuildCommand.h cmBuildNameCommand.cxx cmBuildNameCommand.h + cmCMakeCommand.cxx + cmCMakeCommand.h cmCMakeHostSystemInformationCommand.cxx cmCMakeHostSystemInformationCommand.h cmCMakeMinimumRequired.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index de3f050..be61586 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 17) -set(CMake_VERSION_PATCH 0) +set(CMake_VERSION_PATCH 20200403) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index 509ac65..2806c61 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -544,10 +544,7 @@ std::string cmCPackIFWGenerator::GetGroupPackageName( if (group->ParentGroup) { cmCPackIFWPackage* package = this->GetGroupPackage(group->ParentGroup); bool dot = !this->ResolveDuplicateNames; - if (dot && name.substr(0, package->Name.size()) == package->Name) { - dot = false; - } - if (dot) { + if (dot && !cmHasPrefix(name, package->Name)) { name = package->Name + "." + name; } } @@ -576,10 +573,7 @@ std::string cmCPackIFWGenerator::GetComponentPackageName( return package->Name; } bool dot = !this->ResolveDuplicateNames; - if (dot && name.substr(0, package->Name.size()) == package->Name) { - dot = false; - } - if (dot) { + if (dot && !cmHasPrefix(name, package->Name)) { name = package->Name + "." + name; } } diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index 9a9cd56..56a74c5 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -55,8 +55,7 @@ cmCPackIFWPackage::DependenceStruct::DependenceStruct( if (dashPos != std::string::npos) { pos = dashPos; } - this->Name = - pos == std::string::npos ? dependence : dependence.substr(0, pos); + this->Name = dependence.substr(0, pos); } std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx index 21d27a0..bdaf779 100644 --- a/Source/CPack/OSXScriptLauncher.cxx +++ b/Source/CPack/OSXScriptLauncher.cxx @@ -5,6 +5,8 @@ #include <string> #include <vector> +#include <cm/memory> + #include <CoreFoundation/CoreFoundation.h> #include "cmsys/FStream.hxx" @@ -26,7 +28,6 @@ int main(int argc, char* argv[]) CFStringRef fileName; CFBundleRef appBundle; CFURLRef scriptFileURL; - UInt8* path; // get CF URL for script if (!(appBundle = CFBundleGetMainBundle())) { @@ -41,13 +42,15 @@ int main(int argc, char* argv[]) } // create path string - if (!(path = new UInt8[PATH_MAX])) { + auto path = cm::make_unique<UInt8[]>(PATH_MAX); + if (!path) { return 1; } // get the file system path of the url as a cstring // in an encoding suitable for posix apis - if (!CFURLGetFileSystemRepresentation(scriptFileURL, true, path, PATH_MAX)) { + if (!CFURLGetFileSystemRepresentation(scriptFileURL, true, path.get(), + PATH_MAX)) { DebugError("CFURLGetFileSystemRepresentation failed"); return 1; } @@ -55,10 +58,10 @@ int main(int argc, char* argv[]) // dispose of the CF variable CFRelease(scriptFileURL); - std::string fullScriptPath = reinterpret_cast<char*>(path); - delete[] path; + std::string fullScriptPath = reinterpret_cast<char*>(path.get()); + path.reset(); - if (!cmsys::SystemTools::FileExists(fullScriptPath.c_str())) { + if (!cmsys::SystemTools::FileExists(fullScriptPath)) { return 1; } @@ -80,7 +83,6 @@ int main(int argc, char* argv[]) cmsysProcess_SetTimeout(cp, 0); cmsysProcess_Execute(cp); - std::vector<char> tempOutput; char* data; int length; while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) { diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index e71a38f..e481d13 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -4,6 +4,7 @@ #include <algorithm> +#include <cm/memory> #include <cm/string_view> #include "cmsys/Directory.hxx" @@ -35,22 +36,16 @@ #include "cmCMakeToWixPath.h" cmCPackWIXGenerator::cmCPackWIXGenerator() - : Patch(0) - , ComponentGuidType(cmWIXSourceWriter::WIX_GENERATED_GUID) + : ComponentGuidType(cmWIXSourceWriter::WIX_GENERATED_GUID) { } -cmCPackWIXGenerator::~cmCPackWIXGenerator() -{ - if (this->Patch) { - delete this->Patch; - } -} +cmCPackWIXGenerator::~cmCPackWIXGenerator() = default; int cmCPackWIXGenerator::InitializeInternal() { componentPackageMethod = ONE_PACKAGE; - this->Patch = new cmWIXPatch(this->Logger); + this->Patch = cm::make_unique<cmWIXPatch>(this->Logger); return this->Superclass::InitializeInternal(); } @@ -103,7 +98,7 @@ bool cmCPackWIXGenerator::RunCandleCommand(std::string const& sourceFile, command << " -ext " << QuotePath(ext); } - if (sourceFile.rfind(this->CPackTopLevel, 0) != 0) { + if (!cmHasSuffix(sourceFile, this->CPackTopLevel)) { command << " " << QuotePath("-I" + this->CPackTopLevel); } @@ -355,8 +350,7 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile() std::vector<std::string> options = GetOptions(); for (std::string const& name : options) { - if (name.length() > prefix.length() && - name.substr(0, prefix.length()) == prefix) { + if (cmHasPrefix(name, prefix)) { std::string id = name.substr(prefix.length()); std::string value = GetOption(name.c_str()); @@ -1104,14 +1098,14 @@ std::string cmCPackWIXGenerator::CreateHashedId( cmCryptoHash sha1(cmCryptoHash::AlgoSHA1); std::string const hash = sha1.HashString(path); - std::string identifier = cmStrCat(cm::string_view(hash).substr(0, 7), '_'); - const size_t maxFileNameLength = 52; + std::string identifier = + cmStrCat(cm::string_view(hash).substr(0, 7), '_', + cm::string_view(normalizedFilename).substr(0, maxFileNameLength)); + + // if the name was truncated if (normalizedFilename.length() > maxFileNameLength) { - identifier += normalizedFilename.substr(0, maxFileNameLength - 3); identifier += "..."; - } else { - identifier += normalizedFilename; } return identifier; diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index d193348..d5a16ec 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -4,6 +4,7 @@ #define cmCPackWIXGenerator_h #include <map> +#include <memory> #include <string> #include "cmCPackGenerator.h" @@ -24,6 +25,8 @@ public: cmCPackTypeMacro(cmCPackWIXGenerator, cmCPackGenerator); cmCPackWIXGenerator(); + cmCPackWIXGenerator(const cmCPackWIXGenerator&) = delete; + const cmCPackWIXGenerator& operator=(const cmCPackWIXGenerator&) = delete; ~cmCPackWIXGenerator(); protected: @@ -157,7 +160,7 @@ private: std::string CPackTopLevel; - cmWIXPatch* Patch; + std::unique_ptr<cmWIXPatch> Patch; cmWIXSourceWriter::GuidType ComponentGuidType; }; diff --git a/Source/CPack/WiX/cmWIXAccessControlList.cxx b/Source/CPack/WiX/cmWIXAccessControlList.cxx index 3668b46..9685a7f 100644 --- a/Source/CPack/WiX/cmWIXAccessControlList.cxx +++ b/Source/CPack/WiX/cmWIXAccessControlList.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmWIXAccessControlList.h" +#include <cm/string_view> + #include "cmCPackGenerator.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -35,12 +37,13 @@ void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry) return; } - std::string user_and_domain = entry.substr(0, pos); - std::string permission_string = entry.substr(pos + 1); + cm::string_view enview(entry); + cm::string_view user_and_domain = enview.substr(0, pos); + cm::string_view permission_string = enview.substr(pos + 1); pos = user_and_domain.find('@'); - std::string user; - std::string domain; + cm::string_view user; + cm::string_view domain; if (pos != std::string::npos) { user = user_and_domain.substr(0, pos); domain = user_and_domain.substr(pos + 1); @@ -51,9 +54,9 @@ void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry) std::vector<std::string> permissions = cmTokenize(permission_string, ","); this->SourceWriter.BeginElement("Permission"); - this->SourceWriter.AddAttribute("User", user); + this->SourceWriter.AddAttribute("User", std::string(user)); if (!domain.empty()) { - this->SourceWriter.AddAttribute("Domain", domain); + this->SourceWriter.AddAttribute("Domain", std::string(domain)); } for (std::string const& permission : permissions) { this->EmitBooleanAttribute(entry, cmTrimWhitespace(permission)); diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx index c0d879a..b4085d5 100644 --- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx @@ -1,5 +1,10 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ +#if defined(__CYGWIN__) +// For S_IWRITE symbol +# define _DEFAULT_SOURCE +#endif + #include "cmWIXFilesSourceWriter.h" #include "cm_sys_stat.h" diff --git a/Source/CPack/WiX/cmWIXPatch.cxx b/Source/CPack/WiX/cmWIXPatch.cxx index ca232f9..122ffaf 100644 --- a/Source/CPack/WiX/cmWIXPatch.cxx +++ b/Source/CPack/WiX/cmWIXPatch.cxx @@ -41,7 +41,7 @@ void cmWIXPatch::ApplyFragment(std::string const& id, void cmWIXPatch::ApplyElementChildren(const cmWIXPatchElement& element, cmWIXSourceWriter& writer) { - for (cmWIXPatchNode* node : element.children) { + for (const auto& node : element.children) { switch (node->type()) { case cmWIXPatchNode::ELEMENT: ApplyElement(dynamic_cast<const cmWIXPatchElement&>(*node), writer); diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx index fd9103b..5588d2d 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.cxx +++ b/Source/CPack/WiX/cmWIXPatchParser.cxx @@ -2,6 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmWIXPatchParser.h" +#include <utility> + +#include <cm/memory> + #include "cm_expat.h" #include "cmCPackGenerator.h" @@ -20,12 +24,8 @@ cmWIXPatchNode::~cmWIXPatchNode() { } -cmWIXPatchElement::~cmWIXPatchElement() -{ - for (cmWIXPatchNode* child : children) { - delete child; - } -} +cmWIXPatchElement::cmWIXPatchElement() = default; +cmWIXPatchElement::~cmWIXPatchElement() = default; cmWIXPatchParser::cmWIXPatchParser(fragment_map_t& fragments, cmCPackLog* logger) @@ -54,8 +54,7 @@ void cmWIXPatchParser::StartElement(const std::string& name, const char** atts) } else if (State == INSIDE_FRAGMENT) { cmWIXPatchElement& parent = *ElementStack.back(); - cmWIXPatchElement* element = new cmWIXPatchElement; - parent.children.push_back(element); + auto element = cm::make_unique<cmWIXPatchElement>(); element->name = name; @@ -66,7 +65,8 @@ void cmWIXPatchParser::StartElement(const std::string& name, const char** atts) element->attributes[key] = value; } - ElementStack.push_back(element); + ElementStack.push_back(element.get()); + parent.children.push_back(std::move(element)); } } @@ -130,10 +130,10 @@ void cmWIXPatchParser::CharacterDataHandler(const char* data, int length) std::string::size_type last = text.find_last_not_of(whitespace); if (first != std::string::npos && last != std::string::npos) { - cmWIXPatchText* text_node = new cmWIXPatchText; + auto text_node = cm::make_unique<cmWIXPatchText>(); text_node->text = text.substr(first, last - first + 1); - parent.children.push_back(text_node); + parent.children.push_back(std::move(text_node)); } } } diff --git a/Source/CPack/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h index 87dd892..8d5d2ad 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.h +++ b/Source/CPack/WiX/cmWIXPatchParser.h @@ -4,6 +4,7 @@ #define cmCPackWIXPatchParser_h #include <map> +#include <memory> #include <vector> #include "cmCPackLog.h" @@ -33,9 +34,14 @@ struct cmWIXPatchElement : cmWIXPatchNode { virtual Type type(); + cmWIXPatchElement(); + + cmWIXPatchElement(const cmWIXPatchElement&) = delete; + const cmWIXPatchElement& operator=(const cmWIXPatchElement&) = delete; + ~cmWIXPatchElement(); - using child_list_t = std::vector<cmWIXPatchNode*>; + using child_list_t = std::vector<std::unique_ptr<cmWIXPatchNode>>; using attributes_t = std::map<std::string, std::string>; std::string name; diff --git a/Source/CPack/cmCPackLog.cxx b/Source/CPack/cmCPackLog.cxx index ca675fd..49e4113 100644 --- a/Source/CPack/cmCPackLog.cxx +++ b/Source/CPack/cmCPackLog.cxx @@ -4,54 +4,38 @@ #include <iostream> +#include <cm/memory> + #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" cmCPackLog::cmCPackLog() { - this->Verbose = false; - this->Debug = false; - this->Quiet = false; - this->NewLine = true; - - this->LastTag = cmCPackLog::NOTAG; this->DefaultOutput = &std::cout; this->DefaultError = &std::cerr; - - this->LogOutput = nullptr; - this->LogOutputCleanup = false; } -cmCPackLog::~cmCPackLog() -{ - this->SetLogOutputStream(nullptr); -} +cmCPackLog::~cmCPackLog() = default; void cmCPackLog::SetLogOutputStream(std::ostream* os) { - if (this->LogOutputCleanup && this->LogOutput) { - delete this->LogOutput; - } - this->LogOutputCleanup = false; + this->LogOutputStream.reset(); this->LogOutput = os; } bool cmCPackLog::SetLogOutputFile(const char* fname) { - cmGeneratedFileStream* cg = nullptr; + this->LogOutputStream.reset(); if (fname) { - cg = new cmGeneratedFileStream(fname); - } - if (cg && !*cg) { - delete cg; - cg = nullptr; + this->LogOutputStream = cm::make_unique<cmGeneratedFileStream>(fname); } - this->SetLogOutputStream(cg); - if (!cg) { - return false; + if (this->LogOutputStream && !*this->LogOutputStream) { + this->LogOutputStream.reset(); } - this->LogOutputCleanup = true; - return true; + + this->LogOutput = this->LogOutputStream.get(); + + return this->LogOutput != nullptr; } void cmCPackLog::Log(int tag, const char* file, int line, const char* msg, diff --git a/Source/CPack/cmCPackLog.h b/Source/CPack/cmCPackLog.h index 1cb1643..68ffcce 100644 --- a/Source/CPack/cmCPackLog.h +++ b/Source/CPack/cmCPackLog.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <ostream> #include <string> @@ -97,13 +98,13 @@ public: void SetErrorPrefix(std::string const& pfx) { this->ErrorPrefix = pfx; } private: - bool Verbose; - bool Debug; - bool Quiet; + bool Verbose = false; + bool Debug = false; + bool Quiet = false; - bool NewLine; + bool NewLine = true; - int LastTag; + int LastTag = cmCPackLog::NOTAG; std::string Prefix; std::string OutputPrefix; @@ -112,13 +113,11 @@ private: std::string WarningPrefix; std::string ErrorPrefix; - std::ostream* DefaultOutput; - std::ostream* DefaultError; + std::ostream* DefaultOutput = nullptr; + std::ostream* DefaultError = nullptr; - std::string LogOutputFileName; - std::ostream* LogOutput; - // Do we need to cleanup log output stream - bool LogOutputCleanup; + std::ostream* LogOutput = nullptr; + std::unique_ptr<std::ostream> LogOutputStream; }; class cmCPackLogWrite diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 363f536..9afdc62 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -68,7 +68,7 @@ int cmCPackNSISGenerator::PackageFiles() // Use the custom component install directory if we have one if (pos != std::string::npos) { - const std::string componentName = fileN.substr(0, pos); + auto componentName = cm::string_view(fileN).substr(0, pos); outputDir = CustomComponentInstallDirectory(componentName); } else { outputDir = CustomComponentInstallDirectory(fileN); @@ -103,7 +103,7 @@ int cmCPackNSISGenerator::PackageFiles() componentName = fileN.substr(0, slash); // Strip off the component part of the path. - fileN = fileN.substr(slash + 1); + fileN.erase(0, slash + 1); } } std::replace(fileN.begin(), fileN.end(), '/', '\\'); @@ -453,12 +453,12 @@ int cmCPackNSISGenerator::InitializeInternal() } if (versionRex.find(output)) { double nsisVersion = atof(versionRex.match(1).c_str()); - double minNSISVersion = 2.09; + double minNSISVersion = 3.0; cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: " << nsisVersion << std::endl); if (nsisVersion < minNSISVersion) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "CPack requires NSIS Version 2.09 or greater. " + "CPack requires NSIS Version 3.0 or greater. " "NSIS found on the system was: " << nsisVersion << std::endl); return 0; @@ -672,7 +672,7 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( const std::string componentOutputDir = CustomComponentInstallDirectory(component->Name); - componentCode += " SetOutPath \"" + componentOutputDir + "\"\n"; + componentCode += cmStrCat(" SetOutPath \"", componentOutputDir, "\"\n"); // Create the actual installation commands if (component->IsDownloaded) { @@ -921,12 +921,11 @@ std::string cmCPackNSISGenerator::CreateComponentGroupDescription( } std::string cmCPackNSISGenerator::CustomComponentInstallDirectory( - const std::string& componentName) + cm::string_view componentName) { - const char* outputDir = - this->GetOption("CPACK_NSIS_" + componentName + "_INSTALL_DIRECTORY"); - const std::string componentOutputDir = (outputDir ? outputDir : "$INSTDIR"); - return componentOutputDir; + const char* outputDir = this->GetOption( + cmStrCat("CPACK_NSIS_", componentName, "_INSTALL_DIRECTORY")); + return outputDir ? outputDir : "$INSTDIR"; } std::string cmCPackNSISGenerator::TranslateNewlines(std::string str) diff --git a/Source/CPack/cmCPackNSISGenerator.h b/Source/CPack/cmCPackNSISGenerator.h index 0af37af..88cba45 100644 --- a/Source/CPack/cmCPackNSISGenerator.h +++ b/Source/CPack/cmCPackNSISGenerator.h @@ -10,6 +10,8 @@ #include <string> #include <vector> +#include <cm/string_view> + #include "cmCPackGenerator.h" class cmCPackComponent; @@ -75,8 +77,7 @@ protected: /// Returns the custom install directory if available for the specified /// component, otherwise $INSTDIR is returned. - std::string CustomComponentInstallDirectory( - const std::string& componentName); + std::string CustomComponentInstallDirectory(cm::string_view componentName); /// Translations any newlines found in the string into \\r\\n, so that the /// resulting string can be used within NSIS. diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index dc31623..2e5bde2 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -85,7 +85,7 @@ int cpackDefinitionArgument(const char* argument, const char* cValue, return 0; } std::string key = value.substr(0, pos); - value = value.substr(pos + 1); + value.erase(0, pos + 1); def->Map[key] = value; cmCPack_Log(def->Log, cmCPackLog::LOG_DEBUG, "Set CPack variable: " << key << " to \"" << value << "\"" diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 5e29386..db426b2 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -379,7 +379,7 @@ int cmCTestBuildAndTestHandler::ProcessCommandLineArguments( const std::vector<std::string>& allArgs) { // --build-and-test options - if (currentArg.find("--build-and-test", 0) == 0 && + if (cmHasLiteralPrefix(currentArg, "--build-and-test") && idx < allArgs.size() - 1) { if (idx + 2 < allArgs.size()) { idx++; @@ -397,25 +397,29 @@ int cmCTestBuildAndTestHandler::ProcessCommandLineArguments( return 0; } } - if (currentArg.find("--build-target", 0) == 0 && idx < allArgs.size() - 1) { + if (cmHasLiteralPrefix(currentArg, "--build-target") && + idx < allArgs.size() - 1) { idx++; this->BuildTargets.push_back(allArgs[idx]); } - if (currentArg.find("--build-nocmake", 0) == 0) { + if (cmHasLiteralPrefix(currentArg, "--build-nocmake")) { this->BuildNoCMake = true; } - if (currentArg.find("--build-run-dir", 0) == 0 && idx < allArgs.size() - 1) { + if (cmHasLiteralPrefix(currentArg, "--build-run-dir") && + idx < allArgs.size() - 1) { idx++; this->BuildRunDir = allArgs[idx]; } - if (currentArg.find("--build-two-config", 0) == 0) { + if (cmHasLiteralPrefix(currentArg, "--build-two-config")) { this->BuildTwoConfig = true; } - if (currentArg.find("--build-exe-dir", 0) == 0 && idx < allArgs.size() - 1) { + if (cmHasLiteralPrefix(currentArg, "--build-exe-dir") && + idx < allArgs.size() - 1) { idx++; this->ExecutableDirectory = allArgs[idx]; } - if (currentArg.find("--test-timeout", 0) == 0 && idx < allArgs.size() - 1) { + if (cmHasLiteralPrefix(currentArg, "--test-timeout") && + idx < allArgs.size() - 1) { idx++; this->Timeout = cmDuration(atof(allArgs[idx].c_str())); } @@ -431,31 +435,33 @@ int cmCTestBuildAndTestHandler::ProcessCommandLineArguments( idx++; this->BuildGeneratorToolset = allArgs[idx]; } - if (currentArg.find("--build-project", 0) == 0 && idx < allArgs.size() - 1) { + if (cmHasLiteralPrefix(currentArg, "--build-project") && + idx < allArgs.size() - 1) { idx++; this->BuildProject = allArgs[idx]; } - if (currentArg.find("--build-makeprogram", 0) == 0 && + if (cmHasLiteralPrefix(currentArg, "--build-makeprogram") && idx < allArgs.size() - 1) { idx++; this->BuildMakeProgram = allArgs[idx]; } - if (currentArg.find("--build-config-sample", 0) == 0 && + if (cmHasLiteralPrefix(currentArg, "--build-config-sample") && idx < allArgs.size() - 1) { idx++; this->ConfigSample = allArgs[idx]; } - if (currentArg.find("--build-noclean", 0) == 0) { + if (cmHasLiteralPrefix(currentArg, "--build-noclean")) { this->BuildNoClean = true; } - if (currentArg.find("--build-options", 0) == 0) { + if (cmHasLiteralPrefix(currentArg, "--build-options")) { while (idx + 1 < allArgs.size() && allArgs[idx + 1] != "--build-target" && allArgs[idx + 1] != "--test-command") { ++idx; this->BuildOptions.push_back(allArgs[idx]); } } - if (currentArg.find("--test-command", 0) == 0 && idx < allArgs.size() - 1) { + if (cmHasLiteralPrefix(currentArg, "--test-command") && + idx < allArgs.size() - 1) { ++idx; this->TestCommand = allArgs[idx]; while (idx + 1 < allArgs.size()) { diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 03a3fd3..90c5b2a 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -386,24 +386,20 @@ int cmCTestBuildHandler::ProcessHandler() if (this->CTest->GetCTestConfiguration("SourceDirectory").size() > 20) { std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory") + "/"; - for (cc = srcdir.size() - 2; cc > 0; cc--) { - if (srcdir[cc] == '/') { - srcdir = srcdir.substr(0, cc + 1); - break; - } + cc = srcdir.rfind('/', srcdir.size() - 2); + if (cc != std::string::npos) { + srcdir.resize(cc + 1); + this->SimplifySourceDir = std::move(srcdir); } - this->SimplifySourceDir = srcdir; } if (this->CTest->GetCTestConfiguration("BuildDirectory").size() > 20) { std::string bindir = this->CTest->GetCTestConfiguration("BuildDirectory") + "/"; - for (cc = bindir.size() - 2; cc > 0; cc--) { - if (bindir[cc] == '/') { - bindir = bindir.substr(0, cc + 1); - break; - } + cc = bindir.rfind('/', bindir.size() - 2); + if (cc != std::string::npos) { + bindir.resize(cc + 1); + this->SimplifyBuildDir = std::move(bindir); } - this->SimplifyBuildDir = bindir; } // Ok, let's do the build diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 2c8f119..daa10c9 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -680,8 +680,9 @@ void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile* mf) // #ifdef _WIN32 # define fnc(s) cmSystemTools::LowerCase(s) +# define fnc_prefix(s, t) fnc(s.substr(0, t.size())) == fnc(t) #else -# define fnc(s) s +# define fnc_prefix(s, t) cmHasPrefix(s, t) #endif bool IsFileInDir(const std::string& infile, const std::string& indir) @@ -689,8 +690,8 @@ bool IsFileInDir(const std::string& infile, const std::string& indir) std::string file = cmSystemTools::CollapseFullPath(infile); std::string dir = cmSystemTools::CollapseFullPath(indir); - return file.size() > dir.size() && - fnc(file.substr(0, dir.size())) == fnc(dir) && file[dir.size()] == '/'; + return file.size() > dir.size() && fnc_prefix(file, dir) && + file[dir.size()] == '/'; } int cmCTestCoverageHandler::HandlePHPCoverage( @@ -1709,29 +1710,26 @@ int cmCTestCoverageHandler::HandleTracePyCoverage( // Read the coverage count from the beginning of the Trace.py output // line - std::string prefix = nl.substr(0, 6); - if (prefix[5] != ' ' && prefix[5] != ':') { - // This is a hack. We should really do something more elaborate - prefix = nl.substr(0, 7); - if (prefix[6] != ' ' && prefix[6] != ':') { - prefix = nl.substr(0, 8); - if (prefix[7] != ' ' && prefix[7] != ':') { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Currently the limit is maximum coverage of 999999" - << std::endl); - } + std::string::size_type pos; + int cov = 0; + // This is a hack. We should really do something more elaborate + for (pos = 5; pos < 8; pos++) { + if (nl[pos] == ' ') { + // This line does not have ':' so no coverage here. That said, + // Trace.py does not handle not covered lines versus comments etc. + // So, this will be set to 0. + break; + } + if (nl[pos] == ':') { + cov = atoi(nl.substr(0, pos - 1).c_str()); + break; } } - int cov = atoi(prefix.c_str()); - if (prefix[prefix.size() - 1] != ':') { - // This line does not have ':' so no coverage here. That said, - // Trace.py does not handle not covered lines versus comments etc. - // So, this will be set to 0. - cov = 0; + if (pos == 8) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Currently the limit is maximum coverage of 999999" + << std::endl); } - cmCTestOptionalLog( - this->CTest, DEBUG, - "Prefix: " << prefix << " cov: " << cov << std::endl, this->Quiet); // Read the line number starting at the 10th character of the gcov // output line long lineIdx = cnt; diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 3f3c107..568b091 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -6,6 +6,7 @@ #include <cstdio> #include <cstdlib> #include <ctime> +#include <utility> #include <vector> #include "cmsys/FStream.hxx" @@ -193,7 +194,8 @@ bool cmCTestGIT::UpdateByFetchAndReset() if (line.find("\tnot-for-merge\t") == std::string::npos) { std::string::size_type pos = line.find('\t'); if (pos != std::string::npos) { - sha1 = line.substr(0, pos); + sha1 = std::move(line); + sha1.resize(pos); } } } diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 2192843..50c963d 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -12,13 +12,13 @@ #include <iomanip> #include <iostream> #include <list> -#include <memory> #include <sstream> #include <stack> #include <unordered_map> #include <utility> #include <vector> +#include <cm/memory> #include <cmext/algorithm> #include "cmsys/FStream.hxx" @@ -172,7 +172,8 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) this->EraseTest(test); this->RunningCount += GetProcessorsUsed(test); - cmCTestRunTest* testRun = new cmCTestRunTest(*this); + auto testRun = cm::make_unique<cmCTestRunTest>(*this); + if (this->RepeatMode != cmCTest::Repeat::Never) { testRun->SetRepeatMode(this->RepeatMode); testRun->SetNumberOfRuns(this->RepeatCount); @@ -229,28 +230,25 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) e << "\n"; } e << "Resource spec file:\n\n " << this->TestHandler->ResourceSpecFile; - testRun->StartFailure(e.str(), "Insufficient resources"); - this->FinishTestProcess(testRun, false); + cmCTestRunTest::StartFailure(std::move(testRun), e.str(), + "Insufficient resources"); return false; } cmWorkingDirectory workdir(this->Properties[test]->Directory); if (workdir.Failed()) { - testRun->StartFailure("Failed to change working directory to " + - this->Properties[test]->Directory + " : " + - std::strerror(workdir.GetLastResult()), - "Failed to change working directory"); - } else { - if (testRun->StartTest(this->Completed, this->Total)) { - // Ownership of 'testRun' has moved to another structure. - // When the test finishes, FinishTestProcess will be called. - return true; - } + cmCTestRunTest::StartFailure(std::move(testRun), + "Failed to change working directory to " + + this->Properties[test]->Directory + " : " + + std::strerror(workdir.GetLastResult()), + "Failed to change working directory"); + return false; } - // Pass ownership of 'testRun'. - this->FinishTestProcess(testRun, false); - return false; + // Ownership of 'testRun' has moved to another structure. + // When the test finishes, FinishTestProcess will be called. + return cmCTestRunTest::StartTest(std::move(testRun), this->Completed, + this->Total); } bool cmCTestMultiProcessHandler::AllocateResources(int index) @@ -540,7 +538,8 @@ void cmCTestMultiProcessHandler::StartNextTests() if (this->SerialTestRunning) { break; } - // We can only start a RUN_SERIAL test if no other tests are also running. + // We can only start a RUN_SERIAL test if no other tests are also + // running. if (this->Properties[test]->RunSerial && this->RunningCount > 0) { continue; } @@ -618,8 +617,8 @@ void cmCTestMultiProcessHandler::OnTestLoadRetryCB(uv_timer_t* timer) self->StartNextTests(); } -void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, - bool started) +void cmCTestMultiProcessHandler::FinishTestProcess( + std::unique_ptr<cmCTestRunTest> runner, bool started) { this->Completed++; @@ -631,7 +630,8 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, this->SetStopTimePassed(); } if (started) { - if (!this->StopTimePassed && runner->StartAgain(this->Completed)) { + if (!this->StopTimePassed && + cmCTestRunTest::StartAgain(std::move(runner), this->Completed)) { this->Completed--; // remove the completed test because run again return; } @@ -659,7 +659,7 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, } properties->Affinity.clear(); - delete runner; + runner.reset(); if (started) { this->StartNextTests(); } diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 5b429d4..c3686bc 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> +#include <memory> #include <set> #include <string> #include <vector> @@ -124,7 +125,7 @@ protected: // Removes the checkpoint file void MarkFinished(); void EraseTest(int index); - void FinishTestProcess(cmCTestRunTest* runner, bool started); + void FinishTestProcess(std::unique_ptr<cmCTestRunTest> runner, bool started); static void OnTestLoadRetryCB(uv_timer_t* timer); diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index ec54960..7d0f69b 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -314,23 +314,27 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) return passed || skipped; } -bool cmCTestRunTest::StartAgain(size_t completed) +bool cmCTestRunTest::StartAgain(std::unique_ptr<cmCTestRunTest> runner, + size_t completed) { - if (!this->RunAgain) { + auto* testRun = runner.get(); + + if (!testRun->RunAgain) { return false; } - this->RunAgain = false; // reset + testRun->RunAgain = false; // reset + testRun->TestProcess = cm::make_unique<cmProcess>(std::move(runner)); // change to tests directory - cmWorkingDirectory workdir(this->TestProperties->Directory); + cmWorkingDirectory workdir(testRun->TestProperties->Directory); if (workdir.Failed()) { - this->StartFailure("Failed to change working directory to " + - this->TestProperties->Directory + " : " + - std::strerror(workdir.GetLastResult()), - "Failed to change working directory"); + testRun->StartFailure("Failed to change working directory to " + + testRun->TestProperties->Directory + " : " + + std::strerror(workdir.GetLastResult()), + "Failed to change working directory"); return true; } - this->StartTest(completed, this->TotalNumberOfTests); + testRun->StartTest(completed, testRun->TotalNumberOfTests); return true; } @@ -382,6 +386,18 @@ void cmCTestRunTest::MemCheckPostProcess() handler->PostProcessTest(this->TestResult, this->Index); } +void cmCTestRunTest::StartFailure(std::unique_ptr<cmCTestRunTest> runner, + std::string const& output, + std::string const& detail) +{ + auto* testRun = runner.get(); + + testRun->TestProcess = cm::make_unique<cmProcess>(std::move(runner)); + testRun->StartFailure(output, detail); + + testRun->FinalizeTest(false); +} + void cmCTestRunTest::StartFailure(std::string const& output, std::string const& detail) { @@ -413,7 +429,6 @@ void cmCTestRunTest::StartFailure(std::string const& output, this->TestResult.Path = this->TestProperties->Directory; this->TestResult.Output = output; this->TestResult.FullCommandLine.clear(); - this->TestProcess = cm::make_unique<cmProcess>(*this); } std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const @@ -437,6 +452,21 @@ std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const return outputStream.str(); } +bool cmCTestRunTest::StartTest(std::unique_ptr<cmCTestRunTest> runner, + size_t completed, size_t total) +{ + auto* testRun = runner.get(); + + testRun->TestProcess = cm::make_unique<cmProcess>(std::move(runner)); + + if (!testRun->StartTest(completed, total)) { + testRun->FinalizeTest(false); + return false; + } + + return true; +} + // Starts the execution of a test. Returns once it has started bool cmCTestRunTest::StartTest(size_t completed, size_t total) { @@ -468,7 +498,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) if (this->TestProperties->Disabled) { this->TestResult.CompletionStatus = "Disabled"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; - this->TestProcess = cm::make_unique<cmProcess>(*this); this->TestResult.Output = "Disabled"; this->TestResult.FullCommandLine.clear(); return false; @@ -482,7 +511,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) // its arguments are irrelevant. This matters for the case where a fixture // dependency might be creating the executable we want to run. if (!this->FailedDependencies.empty()) { - this->TestProcess = cm::make_unique<cmProcess>(*this); std::string msg = "Failed test dependencies:"; for (std::string const& failedDep : this->FailedDependencies) { msg += " " + failedDep; @@ -499,7 +527,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) this->ComputeArguments(); std::vector<std::string>& args = this->TestProperties->Args; if (args.size() >= 2 && args[1] == "NOT_AVAILABLE") { - this->TestProcess = cm::make_unique<cmProcess>(*this); std::string msg; if (this->CTest->GetConfigType().empty()) { msg = "Test not available without configuration. (Missing \"-C " @@ -521,7 +548,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) for (std::string const& file : this->TestProperties->RequiredFiles) { if (!cmSystemTools::FileExists(file)) { // Required file was not found - this->TestProcess = cm::make_unique<cmProcess>(*this); *this->TestHandler->LogFile << "Unable to find required file: " << file << std::endl; cmCTestLog(this->CTest, ERROR_MESSAGE, @@ -537,7 +563,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) if (this->ActualCommand.empty()) { // if the command was not found create a TestResult object // that has that information - this->TestProcess = cm::make_unique<cmProcess>(*this); *this->TestHandler->LogFile << "Unable to find executable: " << args[1] << std::endl; cmCTestLog(this->CTest, ERROR_MESSAGE, @@ -649,7 +674,6 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, std::vector<std::string>* environment, std::vector<size_t>* affinity) { - this->TestProcess = cm::make_unique<cmProcess>(*this); this->TestProcess->SetId(this->Index); this->TestProcess->SetWorkingDirectory(this->TestProperties->Directory); this->TestProcess->SetCommand(this->ActualCommand); @@ -816,7 +840,8 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) "Testing " << this->TestProperties->Name << " ... "); } -void cmCTestRunTest::FinalizeTest() +void cmCTestRunTest::FinalizeTest(bool started) { - this->MultiTestHandler.FinishTestProcess(this, true); + this->MultiTestHandler.FinishTestProcess(this->TestProcess->GetRunner(), + started); } diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 4988839..b1d188a 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -65,6 +65,15 @@ public: // Read and store output. Returns true if it must be called again. void CheckOutput(std::string const& line); + static bool StartTest(std::unique_ptr<cmCTestRunTest> runner, + size_t completed, size_t total); + static bool StartAgain(std::unique_ptr<cmCTestRunTest> runner, + size_t completed); + + static void StartFailure(std::unique_ptr<cmCTestRunTest> runner, + std::string const& output, + std::string const& detail); + // launch the test process, return whether it started correctly bool StartTest(size_t completed, size_t total); // capture and report the test results @@ -74,8 +83,6 @@ public: void ComputeWeightedCost(); - bool StartAgain(size_t completed); - void StartFailure(std::string const& output, std::string const& detail); cmCTest* GetCTest() const { return this->CTest; } @@ -84,7 +91,7 @@ public: const std::vector<std::string>& GetArguments() { return this->Arguments; } - void FinalizeTest(); + void FinalizeTest(bool started = true); bool TimedOutForStopTime() const { return this->TimeoutIsForStopTime; } diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 7803e37..4fa4dc0 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -6,7 +6,6 @@ #include <cstdlib> #include <cstring> #include <map> -#include <memory> #include <ratio> #include <sstream> #include <utility> @@ -51,22 +50,7 @@ #define CTEST_INITIAL_CMAKE_OUTPUT_FILE_NAME "CTestInitialCMakeOutput.log" -cmCTestScriptHandler::cmCTestScriptHandler() -{ - this->Backup = false; - this->EmptyBinDir = false; - this->EmptyBinDirOnce = false; - this->Makefile = nullptr; - this->ParentMakefile = nullptr; - this->CMake = nullptr; - this->GlobalGenerator = nullptr; - - this->ScriptStartTime = std::chrono::steady_clock::time_point(); - - // the *60 is because the settings are in minutes but GetTime is seconds - this->MinimumInterval = 30 * 60; - this->ContinuousDuration = -1; -} +cmCTestScriptHandler::cmCTestScriptHandler() = default; void cmCTestScriptHandler::Initialize() { @@ -95,22 +79,15 @@ void cmCTestScriptHandler::Initialize() // what time in seconds did this script start running this->ScriptStartTime = std::chrono::steady_clock::time_point(); - delete this->Makefile; - this->Makefile = nullptr; + this->Makefile.reset(); this->ParentMakefile = nullptr; - delete this->GlobalGenerator; - this->GlobalGenerator = nullptr; + this->GlobalGenerator.reset(); - delete this->CMake; + this->CMake.reset(); } -cmCTestScriptHandler::~cmCTestScriptHandler() -{ - delete this->Makefile; - delete this->GlobalGenerator; - delete this->CMake; -} +cmCTestScriptHandler::~cmCTestScriptHandler() = default; // just adds an argument to the vector void cmCTestScriptHandler::AddConfigurationScript(const char* script, @@ -247,23 +224,20 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) void cmCTestScriptHandler::CreateCMake() { // create a cmake instance to read the configuration script - if (this->CMake) { - delete this->CMake; - delete this->GlobalGenerator; - delete this->Makefile; - } - this->CMake = new cmake(cmake::RoleScript, cmState::CTest); + this->CMake = cm::make_unique<cmake>(cmake::RoleScript, cmState::CTest); this->CMake->SetHomeDirectory(""); this->CMake->SetHomeOutputDirectory(""); this->CMake->GetCurrentSnapshot().SetDefaultDefinitions(); this->CMake->AddCMakePaths(); - this->GlobalGenerator = new cmGlobalGenerator(this->CMake); + this->GlobalGenerator = + cm::make_unique<cmGlobalGenerator>(this->CMake.get()); cmStateSnapshot snapshot = this->CMake->GetCurrentSnapshot(); std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); snapshot.GetDirectory().SetCurrentSource(cwd); snapshot.GetDirectory().SetCurrentBinary(cwd); - this->Makefile = new cmMakefile(this->GlobalGenerator, snapshot); + this->Makefile = + cm::make_unique<cmMakefile>(this->GlobalGenerator.get(), snapshot); if (this->ParentMakefile) { this->Makefile->SetRecursionDepth( this->ParentMakefile->GetRecursionDepth()); @@ -310,12 +284,14 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) // if the argument has a , in it then it needs to be broken into the fist // argument (which is the script) and the second argument which will be // passed into the scripts as S_ARG - std::string script = total_script_arg; + std::string script; std::string script_arg; const std::string::size_type comma_pos = total_script_arg.find(','); if (comma_pos != std::string::npos) { script = total_script_arg.substr(0, comma_pos); script_arg = total_script_arg.substr(comma_pos + 1); + } else { + script = total_script_arg; } // make sure the file exists if (!cmSystemTools::FileExists(script)) { @@ -878,7 +854,7 @@ bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf, const char* sname, bool InProcess, int* returnValue) { - cmCTestScriptHandler* sh = new cmCTestScriptHandler(); + auto sh = cm::make_unique<cmCTestScriptHandler>(); sh->SetCTestInstance(ctest); sh->ParentMakefile = mf; sh->AddConfigurationScript(sname, InProcess); @@ -886,7 +862,6 @@ bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf, if (returnValue) { *returnValue = res; } - delete sh; return true; } diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h index d003199..ebb7905 100644 --- a/Source/CTest/cmCTestScriptHandler.h +++ b/Source/CTest/cmCTestScriptHandler.h @@ -101,12 +101,14 @@ public: cmDuration GetRemainingTimeAllowed(); cmCTestScriptHandler(); + cmCTestScriptHandler(const cmCTestScriptHandler&) = delete; + const cmCTestScriptHandler& operator=(const cmCTestScriptHandler&) = delete; ~cmCTestScriptHandler() override; void Initialize() override; void CreateCMake(); - cmake* GetCMake() { return this->CMake; } + cmake* GetCMake() { return this->CMake.get(); } void SetRunCurrentScript(bool value); @@ -143,9 +145,9 @@ private: bool ShouldRunCurrentScript; - bool Backup; - bool EmptyBinDir; - bool EmptyBinDirOnce; + bool Backup = false; + bool EmptyBinDir = false; + bool EmptyBinDirOnce = false; std::string SourceDir; std::string BinaryDir; @@ -161,16 +163,18 @@ private: std::string CMOutFile; std::vector<std::string> ExtraUpdates; - double MinimumInterval; - double ContinuousDuration; + // the *60 is because the settings are in minutes but GetTime is seconds + double MinimumInterval = 30 * 60; + double ContinuousDuration = -1; // what time in seconds did this script start running - std::chrono::steady_clock::time_point ScriptStartTime; + std::chrono::steady_clock::time_point ScriptStartTime = + std::chrono::steady_clock::time_point(); - cmMakefile* Makefile; - cmMakefile* ParentMakefile; - cmGlobalGenerator* GlobalGenerator; - cmake* CMake; + std::unique_ptr<cmMakefile> Makefile; + cmMakefile* ParentMakefile = nullptr; + std::unique_ptr<cmGlobalGenerator> GlobalGenerator; + std::unique_ptr<cmake> CMake; }; #endif diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 22ab48f..811a7e8 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -260,11 +260,10 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( cmCTestScriptHandler* ch = this->CTest->GetScriptHandler(); cmake* cm = ch->GetCMake(); if (cm) { - const char* subproject = - cm->GetState()->GetGlobalProperty("SubProject"); + cmProp subproject = cm->GetState()->GetGlobalProperty("SubProject"); if (subproject) { upload_as += "&subproject="; - upload_as += ctest_curl.Escape(subproject); + upload_as += ctest_curl.Escape(*subproject); } } } @@ -506,18 +505,19 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, curl.SetTimeOutSeconds(SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT); curl.SetHttpHeaders(this->HttpHeaders); std::string url = this->CTest->GetSubmitURL(); - std::string fields; - std::string::size_type pos = url.find('?'); - if (pos != std::string::npos) { - fields = url.substr(pos + 1); - url = url.substr(0, pos); - } if (!cmHasLiteralPrefix(url, "http://") && !cmHasLiteralPrefix(url, "https://")) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Only http and https are supported for CDASH_UPLOAD\n"); return -1; } + + std::string fields; + std::string::size_type pos = url.find('?'); + if (pos != std::string::npos) { + fields = url.substr(pos + 1); + url.erase(pos); + } bool internalTest = cmIsOn(this->GetOption("InternalTest")); // Get RETRY_COUNT and RETRY_DELAY values if they were set. @@ -555,11 +555,11 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, // a "&subproject=subprojectname" to the first POST. cmCTestScriptHandler* ch = this->CTest->GetScriptHandler(); cmake* cm = ch->GetCMake(); - const char* subproject = cm->GetState()->GetGlobalProperty("SubProject"); + cmProp subproject = cm->GetState()->GetGlobalProperty("SubProject"); // TODO: Encode values for a URL instead of trusting caller. std::ostringstream str; if (subproject) { - str << "subproject=" << curl.Escape(subproject) << "&"; + str << "subproject=" << curl.Escape(*subproject) << "&"; } auto timeNow = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 4f324ea..1feac3a 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -18,12 +18,14 @@ #include <utility> #include <cm/memory> +#include <cm/string_view> #include "cmsys/FStream.hxx" #include <cmsys/Base64.h> #include <cmsys/Directory.hxx> #include <cmsys/RegularExpression.hxx> +#include "cm_static_string_view.hxx" #include "cm_utf8.h" #include "cmAlgorithms.h" @@ -1267,7 +1269,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed, this->StartTestTime = std::chrono::system_clock::now(); auto elapsed_time_start = std::chrono::steady_clock::now(); - cmCTestMultiProcessHandler* parallel = new cmCTestMultiProcessHandler; + auto parallel = cm::make_unique<cmCTestMultiProcessHandler>(); parallel->SetCTest(this->CTest); parallel->SetParallelLevel(this->CTest->GetParallelLevel()); parallel->SetTestHandler(this); @@ -1338,7 +1340,6 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed, } else { parallel->RunTests(); } - delete parallel; this->EndTest = this->CTest->CurrentTime(); this->EndTestTime = std::chrono::system_clock::now(); this->ElapsedTestingTime = @@ -1894,7 +1895,8 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() continue; } - int val = atoi(line.substr(0, pos).c_str()); + line.erase(pos); + int val = atoi(line.c_str()); this->TestsToRun.push_back(val); } ifs.close(); @@ -2016,13 +2018,13 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, | std::ios::binary #endif ); - unsigned char* file_buffer = new unsigned char[len + 1]; - ifs.read(reinterpret_cast<char*>(file_buffer), len); - unsigned char* encoded_buffer = new unsigned char[static_cast<int>( - static_cast<double>(len) * 1.5 + 5.0)]; + auto file_buffer = cm::make_unique<unsigned char[]>(len + 1); + ifs.read(reinterpret_cast<char*>(file_buffer.get()), len); + auto encoded_buffer = cm::make_unique<unsigned char[]>( + static_cast<int>(static_cast<double>(len) * 1.5 + 5.0)); - size_t rlen = - cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1); + size_t rlen = cmsysBase64_Encode(file_buffer.get(), len, + encoded_buffer.get(), 1); xml.StartElement("NamedMeasurement"); xml.Attribute(measurementfile.match(1).c_str(), @@ -2039,8 +2041,6 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, } xml.Element("Value", ostr.str()); xml.EndElement(); // NamedMeasurement - delete[] file_buffer; - delete[] encoded_buffer; } } else { int idx = 4; @@ -2085,19 +2085,18 @@ void cmCTestTestHandler::SetTestsToRunInformation(const char* in) if (cmSystemTools::FileExists(in)) { cmsys::ifstream fin(in); unsigned long filelen = cmSystemTools::FileLength(in); - char* buff = new char[filelen + 1]; - fin.getline(buff, filelen); + auto buff = cm::make_unique<char[]>(filelen + 1); + fin.getline(buff.get(), filelen); buff[fin.gcount()] = 0; - this->TestsToRunString = buff; - delete[] buff; + this->TestsToRunString = buff.get(); } } -bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length) +void cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length) { if (!length || length >= output.size() || output.find("CTEST_FULL_OUTPUT") != std::string::npos) { - return true; + return; } // Truncate at given length but do not break in the middle of a multi-byte @@ -2118,7 +2117,7 @@ bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length) ++current; } } - output = output.substr(0, current - begin); + output.erase(current - begin); // Append truncation message. std::ostringstream msg; @@ -2128,7 +2127,6 @@ bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length) "of " << length << " bytes.\n"; output += msg.str(); - return true; } bool cmCTestTestHandler::SetTestsProperties( @@ -2149,16 +2147,16 @@ bool cmCTestTestHandler::SetTestsProperties( } ++it; // skip PROPERTIES for (; it != args.end(); ++it) { - std::string key = *it; + std::string const& key = *it; ++it; if (it == args.end()) { break; } - std::string val = *it; + std::string const& val = *it; for (std::string const& t : tests) { for (cmCTestTestProperties& rt : this->TestList) { if (t == rt.Name) { - if (key == "_BACKTRACE_TRIPLES") { + if (key == "_BACKTRACE_TRIPLES"_s) { std::vector<std::string> triples; // allow empty args in the triples cmExpandList(val, triples, true); @@ -2182,91 +2180,70 @@ bool cmCTestTestHandler::SetTestsProperties( rt.Backtrace = rt.Backtrace.Push(fc); } } - } - if (key == "WILL_FAIL") { + } else if (key == "WILL_FAIL"_s) { rt.WillFail = cmIsOn(val); - } - if (key == "DISABLED") { + } else if (key == "DISABLED"_s) { rt.Disabled = cmIsOn(val); - } - if (key == "ATTACHED_FILES") { + } else if (key == "ATTACHED_FILES"_s) { cmExpandList(val, rt.AttachedFiles); - } - if (key == "ATTACHED_FILES_ON_FAIL") { + } else if (key == "ATTACHED_FILES_ON_FAIL"_s) { cmExpandList(val, rt.AttachOnFail); - } - if (key == "RESOURCE_LOCK") { + } else if (key == "RESOURCE_LOCK"_s) { std::vector<std::string> lval = cmExpandedList(val); rt.LockedResources.insert(lval.begin(), lval.end()); - } - if (key == "FIXTURES_SETUP") { + } else if (key == "FIXTURES_SETUP"_s) { std::vector<std::string> lval = cmExpandedList(val); rt.FixturesSetup.insert(lval.begin(), lval.end()); - } - if (key == "FIXTURES_CLEANUP") { + } else if (key == "FIXTURES_CLEANUP"_s) { std::vector<std::string> lval = cmExpandedList(val); rt.FixturesCleanup.insert(lval.begin(), lval.end()); - } - if (key == "FIXTURES_REQUIRED") { + } else if (key == "FIXTURES_REQUIRED"_s) { std::vector<std::string> lval = cmExpandedList(val); rt.FixturesRequired.insert(lval.begin(), lval.end()); - } - if (key == "TIMEOUT") { + } else if (key == "TIMEOUT"_s) { rt.Timeout = cmDuration(atof(val.c_str())); rt.ExplicitTimeout = true; - } - if (key == "COST") { + } else if (key == "COST"_s) { rt.Cost = static_cast<float>(atof(val.c_str())); - } - if (key == "REQUIRED_FILES") { + } else if (key == "REQUIRED_FILES"_s) { cmExpandList(val, rt.RequiredFiles); - } - if (key == "RUN_SERIAL") { + } else if (key == "RUN_SERIAL"_s) { rt.RunSerial = cmIsOn(val); - } - if (key == "FAIL_REGULAR_EXPRESSION") { + } else if (key == "FAIL_REGULAR_EXPRESSION"_s) { std::vector<std::string> lval = cmExpandedList(val); for (std::string const& cr : lval) { rt.ErrorRegularExpressions.emplace_back(cr, cr); } - } - if (key == "SKIP_REGULAR_EXPRESSION") { + } else if (key == "SKIP_REGULAR_EXPRESSION"_s) { std::vector<std::string> lval = cmExpandedList(val); for (std::string const& cr : lval) { rt.SkipRegularExpressions.emplace_back(cr, cr); } - } - if (key == "PROCESSORS") { + } else if (key == "PROCESSORS"_s) { rt.Processors = atoi(val.c_str()); if (rt.Processors < 1) { rt.Processors = 1; } - } - if (key == "PROCESSOR_AFFINITY") { + } else if (key == "PROCESSOR_AFFINITY"_s) { rt.WantAffinity = cmIsOn(val); - } - if (key == "RESOURCE_GROUPS") { + } else if (key == "RESOURCE_GROUPS"_s) { if (!ParseResourceGroupsProperty(val, rt.ResourceGroups)) { return false; } - } - if (key == "SKIP_RETURN_CODE") { + } else if (key == "SKIP_RETURN_CODE"_s) { rt.SkipReturnCode = atoi(val.c_str()); if (rt.SkipReturnCode < 0 || rt.SkipReturnCode > 255) { rt.SkipReturnCode = -1; } - } - if (key == "DEPENDS") { + } else if (key == "DEPENDS"_s) { cmExpandList(val, rt.Depends); - } - if (key == "ENVIRONMENT") { + } else if (key == "ENVIRONMENT"_s) { cmExpandList(val, rt.Environment); - } - if (key == "LABELS") { + } else if (key == "LABELS"_s) { std::vector<std::string> Labels = cmExpandedList(val); rt.Labels.insert(rt.Labels.end(), Labels.begin(), Labels.end()); // sort the array @@ -2274,8 +2251,7 @@ bool cmCTestTestHandler::SetTestsProperties( // remove duplicates auto new_end = std::unique(rt.Labels.begin(), rt.Labels.end()); rt.Labels.erase(new_end, rt.Labels.end()); - } - if (key == "MEASUREMENT") { + } else if (key == "MEASUREMENT"_s) { size_t pos = val.find_first_of('='); if (pos != std::string::npos) { std::string mKey = val.substr(0, pos); @@ -2284,17 +2260,14 @@ bool cmCTestTestHandler::SetTestsProperties( } else { rt.Measurements[val] = "1"; } - } - if (key == "PASS_REGULAR_EXPRESSION") { + } else if (key == "PASS_REGULAR_EXPRESSION"_s) { std::vector<std::string> lval = cmExpandedList(val); for (std::string const& cr : lval) { rt.RequiredRegularExpressions.emplace_back(cr, cr); } - } - if (key == "WORKING_DIRECTORY") { + } else if (key == "WORKING_DIRECTORY"_s) { rt.Directory = val; - } - if (key == "TIMEOUT_AFTER_MATCH") { + } else if (key == "TIMEOUT_AFTER_MATCH"_s) { std::vector<std::string> propArgs = cmExpandedList(val); if (propArgs.size() != 2) { cmCTestLog(this->CTest, WARNING, @@ -2334,16 +2307,16 @@ bool cmCTestTestHandler::SetDirectoryProperties( } ++it; // skip PROPERTIES for (; it != args.end(); ++it) { - std::string key = *it; + std::string const& key = *it; ++it; if (it == args.end()) { break; } - std::string val = *it; + std::string const& val = *it; for (cmCTestTestProperties& rt : this->TestList) { std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); if (cwd == rt.Directory) { - if (key == "LABELS") { + if (key == "LABELS"_s) { std::vector<std::string> DirectoryLabels = cmExpandedList(val); rt.Labels.insert(rt.Labels.end(), DirectoryLabels.begin(), DirectoryLabels.end()); diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index b1c8755..8a49ec2 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -235,7 +235,7 @@ protected: void AttachFiles(cmXMLWriter& xml, cmCTestTestResult& result); //! Clean test output to specified length - bool CleanTestOutput(std::string& output, size_t length); + void CleanTestOutput(std::string& output, size_t length); cmDuration ElapsedTestingTime; diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 6026c69..452d714 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -38,7 +38,7 @@ void cmCTestVC::SetSourceDirectory(std::string const& dir) this->SourceDirectory = dir; } -bool cmCTestVC::InitialCheckout(const char* command) +bool cmCTestVC::InitialCheckout(const std::string& command) { cmCTestLog(this->CTest, HANDLER_OUTPUT, " First perform the initial checkout: " << command << "\n"); diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h index 2a4765d..3037e01 100644 --- a/Source/CTest/cmCTestVC.h +++ b/Source/CTest/cmCTestVC.h @@ -36,7 +36,7 @@ public: std::string GetNightlyTime(); /** Prepare the work tree. */ - bool InitialCheckout(const char* command); + bool InitialCheckout(const std::string& command); /** Perform cleanup operations on the work tree. */ void Cleanup(); diff --git a/Source/CTest/cmParseCacheCoverage.cxx b/Source/CTest/cmParseCacheCoverage.cxx index 8c4da75..1a5e7c5 100644 --- a/Source/CTest/cmParseCacheCoverage.cxx +++ b/Source/CTest/cmParseCacheCoverage.cxx @@ -19,7 +19,7 @@ cmParseCacheCoverage::cmParseCacheCoverage( { } -bool cmParseCacheCoverage::LoadCoverageData(const char* d) +bool cmParseCacheCoverage::LoadCoverageData(std::string const& d) { // load all the .mcov files in the specified directory cmsys::Directory dir; @@ -155,7 +155,7 @@ bool cmParseCacheCoverage::ReadCMCovFile(const char* file) // if we have a routine name, check for end of routine else { // Totals in arg 0 marks the end of a routine - if (separateLine[0].substr(0, 6) == "Totals") { + if (cmHasLiteralPrefix(separateLine[0], "Totals")) { routine.clear(); // at the end of this routine filepath.clear(); continue; // move to next line diff --git a/Source/CTest/cmParseCacheCoverage.h b/Source/CTest/cmParseCacheCoverage.h index e89b9e4..3b554f3 100644 --- a/Source/CTest/cmParseCacheCoverage.h +++ b/Source/CTest/cmParseCacheCoverage.h @@ -26,7 +26,7 @@ public: protected: // implement virtual from parent - bool LoadCoverageData(const char* dir) override; + bool LoadCoverageData(std::string const& dir) override; // remove files with no coverage void RemoveUnCoveredFiles(); // Read a single mcov file diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx index 05da84e..711a856 100644 --- a/Source/CTest/cmParseCoberturaCoverage.cxx +++ b/Source/CTest/cmParseCoberturaCoverage.cxx @@ -67,7 +67,7 @@ protected: // Check if this is an absolute path that falls within our // source or binary directories. for (std::string const& filePath : FilePaths) { - if (filename.find(filePath) == 0) { + if (cmHasPrefix(filename, filePath)) { this->CurFileName = filename; break; } diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx index 1dc5b70..14417cc 100644 --- a/Source/CTest/cmParseGTMCoverage.cxx +++ b/Source/CTest/cmParseGTMCoverage.cxx @@ -19,7 +19,7 @@ cmParseGTMCoverage::cmParseGTMCoverage(cmCTestCoverageHandlerContainer& cont, { } -bool cmParseGTMCoverage::LoadCoverageData(const char* d) +bool cmParseGTMCoverage::LoadCoverageData(std::string const& d) { // load all the .mcov files in the specified directory cmsys::Directory dir; diff --git a/Source/CTest/cmParseGTMCoverage.h b/Source/CTest/cmParseGTMCoverage.h index fe0ae0b..41cc7f5 100644 --- a/Source/CTest/cmParseGTMCoverage.h +++ b/Source/CTest/cmParseGTMCoverage.h @@ -25,7 +25,7 @@ public: protected: // implement virtual from parent - bool LoadCoverageData(const char* dir) override; + bool LoadCoverageData(std::string const& dir) override; // Read a single mcov file bool ReadMCovFile(const char* f); // find out what line in a mumps file (filepath) the given entry point diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx index b16f101..dc3064d 100644 --- a/Source/CTest/cmParseMumpsCoverage.cxx +++ b/Source/CTest/cmParseMumpsCoverage.cxx @@ -39,9 +39,9 @@ bool cmParseMumpsCoverage::ReadCoverageFile(const char* file) std::string type = line.substr(0, pos); std::string path = line.substr(pos + 1); if (type == "packages") { - this->LoadPackages(path.c_str()); + this->LoadPackages(path); } else if (type == "coverage_dir") { - this->LoadCoverageData(path.c_str()); + this->LoadCoverageData(path); } else { cmCTestLog(this->CTest, ERROR_MESSAGE, "Parse Error in Mumps coverage file :\n" @@ -105,7 +105,7 @@ void cmParseMumpsCoverage::InitializeMumpsFile(std::string& file) } } -bool cmParseMumpsCoverage::LoadPackages(const char* d) +bool cmParseMumpsCoverage::LoadPackages(std::string const& d) { cmsys::Glob glob; glob.RecurseOn(); @@ -113,7 +113,8 @@ bool cmParseMumpsCoverage::LoadPackages(const char* d) glob.FindFiles(pat); for (std::string& file : glob.GetFiles()) { std::string name = cmSystemTools::GetFilenameName(file); - this->RoutineToDirectory[name.substr(0, name.size() - 2)] = file; + name.erase(name.size() - 2); + this->RoutineToDirectory[name] = file; // initialize each file, this is left out until CDash is fixed // to handle large numbers of files this->InitializeMumpsFile(file); diff --git a/Source/CTest/cmParseMumpsCoverage.h b/Source/CTest/cmParseMumpsCoverage.h index 2c54495..8c08702 100644 --- a/Source/CTest/cmParseMumpsCoverage.h +++ b/Source/CTest/cmParseMumpsCoverage.h @@ -29,10 +29,10 @@ public: protected: // sub classes will use this to // load all coverage files found in the given directory - virtual bool LoadCoverageData(const char* d) = 0; + virtual bool LoadCoverageData(std::string const& d) = 0; // search the package directory for mumps files and fill // in the RoutineToDirectory map - bool LoadPackages(const char* dir); + bool LoadPackages(std::string const& dir); // initialize the coverage information for a single mumps file void InitializeMumpsFile(std::string& file); // Find mumps file for routine diff --git a/Source/CTest/cmParsePHPCoverage.cxx b/Source/CTest/cmParsePHPCoverage.cxx index a494b92..044f518 100644 --- a/Source/CTest/cmParsePHPCoverage.cxx +++ b/Source/CTest/cmParsePHPCoverage.cxx @@ -3,6 +3,8 @@ #include <cstdlib> #include <cstring> +#include <cm/memory> + #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" @@ -142,17 +144,15 @@ bool cmParsePHPCoverage::ReadFileInformation(std::istream& in) int size = 0; if (this->ReadInt(in, size)) { size++; // add one for null termination - char* s = new char[size + 1]; + auto s = cm::make_unique<char[]>(size + 1); // read open quote if (in.get(c) && c != '"') { - delete[] s; return false; } // read the string data - in.read(s, size - 1); + in.read(s.get(), size - 1); s[size - 1] = 0; - std::string fileName = s; - delete[] s; + std::string fileName = s.get(); // read close quote if (in.get(c) && c != '"') { cmCTestLog(this->CTest, ERROR_MESSAGE, diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index cdf899c..2742fd7 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -5,6 +5,7 @@ #include <csignal> #include <iostream> #include <string> +#include <utility> #include <cmext/algorithm> @@ -18,12 +19,11 @@ #if defined(_WIN32) # include "cm_kwiml.h" #endif -#include <utility> #define CM_PROCESS_BUF_SIZE 65536 -cmProcess::cmProcess(cmCTestRunTest& runner) - : Runner(runner) +cmProcess::cmProcess(std::unique_ptr<cmCTestRunTest> runner) + : Runner(std::move(runner)) , Conv(cmProcessOutput::UTF8, CM_PROCESS_BUF_SIZE) { this->Timeout = cmDuration::zero(); @@ -69,7 +69,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) cm::uv_timer_ptr timer; int status = timer.init(loop, this); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error initializing timer: " << uv_strerror(status) << std::endl); return false; @@ -84,7 +84,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) int fds[2] = { -1, -1 }; status = cmGetPipes(fds); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error initializing pipe: " << uv_strerror(status) << std::endl); return false; @@ -127,7 +127,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) uv_read_start(pipe_reader, &cmProcess::OnAllocateCB, &cmProcess::OnReadCB); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error starting read events: " << uv_strerror(status) << std::endl); return false; @@ -135,7 +135,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) status = this->Process.spawn(loop, options, this); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Process not started\n " << this->Command << "\n[" << uv_strerror(status) << "]\n"); return false; @@ -152,7 +152,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) void cmProcess::StartTimer() { - auto properties = this->Runner.GetTestProperties(); + auto properties = this->Runner->GetTestProperties(); auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(this->Timeout); @@ -222,7 +222,7 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) cm::append(this->Output, strdata); while (this->Output.GetLine(line)) { - this->Runner.CheckOutput(line); + this->Runner->CheckOutput(line); line.clear(); } @@ -236,20 +236,20 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) // The process will provide no more data. if (nread != UV_EOF) { auto error = static_cast<int>(nread); - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error reading stream: " << uv_strerror(error) << std::endl); } // Look for partial last lines. if (this->Output.GetLast(line)) { - this->Runner.CheckOutput(line); + this->Runner->CheckOutput(line); } this->ReadHandleClosed = true; this->PipeReader.reset(); if (this->ProcessHandleClosed) { uv_timer_stop(this->Timer); - this->Runner.FinalizeTest(); + this->Finish(); } } @@ -291,7 +291,7 @@ void cmProcess::OnTimeout() // Our on-exit handler already ran but did not finish the test // because we were still reading output. We've just dropped // our read handler, so we need to finish the test now. - this->Runner.FinalizeTest(); + this->Finish(); } } @@ -321,6 +321,16 @@ void cmProcess::OnExit(int64_t exit_status, int term_signal) // Record exit information. this->ExitValue = exit_status; this->Signal = term_signal; + + this->ProcessHandleClosed = true; + if (this->ReadHandleClosed) { + uv_timer_stop(this->Timer); + this->Finish(); + } +} + +void cmProcess::Finish() +{ this->TotalTime = std::chrono::steady_clock::now() - this->StartTime; // Because of a processor clock scew the runtime may become slightly // negative. If someone changed the system clock while the process was @@ -329,12 +339,7 @@ void cmProcess::OnExit(int64_t exit_status, int term_signal) if (this->TotalTime <= cmDuration::zero()) { this->TotalTime = cmDuration::zero(); } - - this->ProcessHandleClosed = true; - if (this->ReadHandleClosed) { - uv_timer_stop(this->Timer); - this->Runner.FinalizeTest(); - } + this->Runner->FinalizeTest(); } cmProcess::State cmProcess::GetProcessStatus() diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index 2c24f2d..526c920 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -6,7 +6,9 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <chrono> +#include <memory> #include <string> +#include <utility> #include <vector> #include <stddef.h> @@ -28,7 +30,7 @@ class cmCTestRunTest; class cmProcess { public: - explicit cmProcess(cmCTestRunTest& runner); + explicit cmProcess(std::unique_ptr<cmCTestRunTest> runner); ~cmProcess(); void SetCommand(std::string const& command); void SetCommandArguments(std::vector<std::string> const& arg); @@ -70,6 +72,11 @@ public: Exception GetExitException(); std::string GetExitExceptionString(); + std::unique_ptr<cmCTestRunTest> GetRunner() + { + return std::move(this->Runner); + } + private: cmDuration Timeout; std::chrono::steady_clock::time_point StartTime; @@ -82,7 +89,7 @@ private: cm::uv_timer_ptr Timer; std::vector<char> Buf; - cmCTestRunTest& Runner; + std::unique_ptr<cmCTestRunTest> Runner; cmProcessOutput Conv; int Signal = 0; cmProcess::State ProcessState = cmProcess::State::Starting; @@ -101,6 +108,7 @@ private: void OnAllocate(size_t suggested_size, uv_buf_t* buf); void StartTimer(); + void Finish(); class Buffer : public std::vector<char> { diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake index c16286c..3b00dfb 100644 --- a/Source/Checks/cm_cxx_features.cmake +++ b/Source/Checks/cm_cxx_features.cmake @@ -32,8 +32,6 @@ function(cm_check_cxx_feature name) string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\] warning: [^\n]*" "" check_output "${check_output}") # Filter out ld warnings. string(REGEX REPLACE "[^\n]*ld: warning: [^\n]*" "" check_output "${check_output}") - # Filter out CUDA installation warnings. - string(REGEX REPLACE "[^\n]*clang: warning: Unknown CUDA version[^\n]*" "" check_output "${check_output}") # If using the feature causes warnings, treat it as broken/unavailable. if(check_output MATCHES "(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]") set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE) diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 01fce85..9a26db5 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -16,6 +16,7 @@ #include "cmDocumentation.h" #include "cmDocumentationEntry.h" // IWYU pragma: keep #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -111,8 +112,8 @@ int main(int argc, char const* const* argv) std::string cacheDir = cmSystemTools::GetCurrentWorkingDirectory(); for (i = 1; i < args.size(); ++i) { - std::string arg = args[i]; - if (arg.find("-B", 0) == 0) { + std::string const& arg = args[i]; + if (cmHasPrefix(arg, "-B")) { cacheDir = arg.substr(2); } } diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx index 4d3131b..9250fbc 100644 --- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx +++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx @@ -48,42 +48,42 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite( this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, " "); } - const char* value = state->GetCacheEntryValue(key); + cmProp value = state->GetCacheEntryValue(key); assert(value); switch (state->GetCacheEntryType(key)) { case cmStateEnums::BOOL: { auto bw = cm::make_unique<cmCursesBoolWidget>(this->EntryWidth, 1, 1, 1); - bw->SetValueAsBool(cmIsOn(value)); + bw->SetValueAsBool(cmIsOn(*value)); this->Entry = std::move(bw); break; } case cmStateEnums::PATH: { auto pw = cm::make_unique<cmCursesPathWidget>(this->EntryWidth, 1, 1, 1); - pw->SetString(value); + pw->SetString(*value); this->Entry = std::move(pw); break; } case cmStateEnums::FILEPATH: { auto fpw = cm::make_unique<cmCursesFilePathWidget>(this->EntryWidth, 1, 1, 1); - fpw->SetString(value); + fpw->SetString(*value); this->Entry = std::move(fpw); break; } case cmStateEnums::STRING: { - const char* stringsProp = state->GetCacheEntryProperty(key, "STRINGS"); + cmProp stringsProp = state->GetCacheEntryProperty(key, "STRINGS"); if (stringsProp) { auto ow = cm::make_unique<cmCursesOptionsWidget>(this->EntryWidth, 1, 1, 1); - for (std::string const& opt : cmExpandedList(stringsProp)) { + for (std::string const& opt : cmExpandedList(*stringsProp)) { ow->AddOption(opt); } - ow->SetOption(value); + ow->SetOption(*value); this->Entry = std::move(ow); } else { auto sw = cm::make_unique<cmCursesStringWidget>(this->EntryWidth, 1, 1, 1); - sw->SetString(value); + sw->SetString(*value); this->Entry = std::move(sw); } break; diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 2c92835..7752a68 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -161,7 +161,7 @@ void cmCursesMainForm::RePost() // If normal mode, count only non-advanced entries this->NumberOfVisibleEntries = 0; for (cmCursesCacheEntryComposite& entry : this->Entries) { - const char* existingValue = + cmProp existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue()); bool advanced = this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool( @@ -182,7 +182,7 @@ void cmCursesMainForm::RePost() // Assign fields for (cmCursesCacheEntryComposite& entry : this->Entries) { - const char* existingValue = + cmProp existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue()); bool advanced = this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool( @@ -241,7 +241,7 @@ void cmCursesMainForm::Render(int left, int top, int width, int height) // If normal, display only non-advanced entries this->NumberOfVisibleEntries = 0; for (cmCursesCacheEntryComposite& entry : this->Entries) { - const char* existingValue = + cmProp existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue()); bool advanced = this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool( @@ -259,7 +259,7 @@ void cmCursesMainForm::Render(int left, int top, int width, int height) bool isNewPage; int i = 0; for (cmCursesCacheEntryComposite& entry : this->Entries) { - const char* existingValue = + cmProp existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue()); bool advanced = this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool( @@ -405,11 +405,12 @@ void cmCursesMainForm::UpdateStatusBar(cm::optional<std::string> message) // Get the help string of the current entry // and add it to the help string auto cmakeState = this->CMakeInstance->GetState(); - const char* existingValue = cmakeState->GetCacheEntryValue(labelValue); + cmProp existingValue = cmakeState->GetCacheEntryValue(labelValue); if (existingValue) { - auto help = cmakeState->GetCacheEntryProperty(labelValue, "HELPSTRING"); + cmProp help = + cmakeState->GetCacheEntryProperty(labelValue, "HELPSTRING"); if (help) { - bar += help; + bar += *help; } } } @@ -616,10 +617,10 @@ void cmCursesMainForm::FillCacheManagerFromUI() { for (cmCursesCacheEntryComposite& entry : this->Entries) { const std::string& cacheKey = entry.Key; - const char* existingValue = + cmProp existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(cacheKey); if (existingValue) { - std::string oldValue = existingValue; + std::string oldValue = *existingValue; std::string newValue = entry.Entry->GetValue(); std::string fixedOldValue; std::string fixedNewValue; @@ -802,9 +803,9 @@ void cmCursesMainForm::HandleInput() cmCursesWidget* lbl = reinterpret_cast<cmCursesWidget*>( field_userptr(this->Fields[findex - 2])); const char* curField = lbl->GetValue(); - const char* helpString = nullptr; + cmProp helpString = nullptr; - const char* existingValue = + cmProp existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(curField); if (existingValue) { helpString = this->CMakeInstance->GetState()->GetCacheEntryProperty( @@ -813,7 +814,7 @@ void cmCursesMainForm::HandleInput() if (helpString) { this->HelpMessage[1] = cmStrCat("Current option is: ", curField, '\n', - "Help string for this option is: ", helpString, '\n'); + "Help string for this option is: ", *helpString, '\n'); } else { this->HelpMessage[1] = ""; } diff --git a/Source/LexerParser/cmListFileLexer.c b/Source/LexerParser/cmListFileLexer.c index 15dcda0..ec7424c 100644 --- a/Source/LexerParser/cmListFileLexer.c +++ b/Source/LexerParser/cmListFileLexer.c @@ -2787,7 +2787,7 @@ int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text) /*--------------------------------------------------------------------------*/ cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer) { - if (!lexer->file) { + if (!lexer->file && !lexer->string_buffer) { return 0; } if (cmListFileLexer_yylex(lexer->scanner, lexer)) { @@ -2801,21 +2801,13 @@ cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer) /*--------------------------------------------------------------------------*/ long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer) { - if (lexer->file) { - return lexer->line; - } else { - return 0; - } + return lexer->line; } /*--------------------------------------------------------------------------*/ long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer) { - if (lexer->file) { - return lexer->column; - } else { - return 0; - } + return lexer->column; } /*--------------------------------------------------------------------------*/ diff --git a/Source/LexerParser/cmListFileLexer.in.l b/Source/LexerParser/cmListFileLexer.in.l index fdf14d2..94cf8a5 100644 --- a/Source/LexerParser/cmListFileLexer.in.l +++ b/Source/LexerParser/cmListFileLexer.in.l @@ -500,7 +500,7 @@ int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text) /*--------------------------------------------------------------------------*/ cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer) { - if (!lexer->file) { + if (!lexer->file && !lexer->string_buffer) { return 0; } if (cmListFileLexer_yylex(lexer->scanner, lexer)) { @@ -514,21 +514,13 @@ cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer) /*--------------------------------------------------------------------------*/ long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer) { - if (lexer->file) { - return lexer->line; - } else { - return 0; - } + return lexer->line; } /*--------------------------------------------------------------------------*/ long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer) { - if (lexer->file) { - return lexer->column; - } else { - return 0; - } + return lexer->column; } /*--------------------------------------------------------------------------*/ diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index ee81a7d..9d928b2 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -201,8 +201,7 @@ int main(int argc, char** argv) cmSystemTools::CollapseFullPath(args[1].toLocal8Bit().data()); // check if argument is a directory containing CMakeCache.txt - std::string buildFilePath = - cmSystemTools::CollapseFullPath("CMakeCache.txt", filePath.c_str()); + std::string buildFilePath = cmStrCat(filePath, "/CMakeCache.txt"); // check if argument is a CMakeCache.txt file if (cmSystemTools::GetFilenameName(filePath) == "CMakeCache.txt" && @@ -211,8 +210,7 @@ int main(int argc, char** argv) } // check if argument is a directory containing CMakeLists.txt - std::string srcFilePath = - cmSystemTools::CollapseFullPath("CMakeLists.txt", filePath.c_str()); + std::string srcFilePath = cmStrCat(filePath, "/CMakeLists.txt"); if (cmSystemTools::FileExists(buildFilePath.c_str())) { dialog.setBinaryDirectory(QString::fromLocal8Bit( diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 436a904..276bf64 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "CMakeSetupDialog.h" +#include <cm/memory> + #include <QCloseEvent> #include <QCoreApplication> #include <QDesktopServices> @@ -39,23 +41,21 @@ QCMakeThread::QCMakeThread(QObject* p) : QThread(p) - , CMakeInstance(nullptr) { } QCMake* QCMakeThread::cmakeInstance() const { - return this->CMakeInstance; + return this->CMakeInstance.get(); } void QCMakeThread::run() { - this->CMakeInstance = new QCMake; + this->CMakeInstance = cm::make_unique<QCMake>(); // emit that this cmake thread is ready for use emit this->cmakeInitialized(); this->exec(); - delete this->CMakeInstance; - this->CMakeInstance = nullptr; + this->CMakeInstance.reset(); } CMakeSetupDialog::CMakeSetupDialog() @@ -1206,7 +1206,7 @@ void CMakeSetupDialog::setSearchFilter(const QString& str) void CMakeSetupDialog::doOutputContextMenu(QPoint pt) { - QMenu* menu = this->Output->createStandardContextMenu(); + std::unique_ptr<QMenu> menu(this->Output->createStandardContextMenu()); menu->addSeparator(); menu->addAction(tr("Find..."), this, SLOT(doOutputFindDialog()), @@ -1220,7 +1220,6 @@ void CMakeSetupDialog::doOutputContextMenu(QPoint pt) QKeySequence(Qt::Key_F8)); menu->exec(this->Output->mapToGlobal(pt)); - delete menu; } void CMakeSetupDialog::doOutputFindDialog() diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h index f23aee6..d1e2035 100644 --- a/Source/QtDialog/CMakeSetupDialog.h +++ b/Source/QtDialog/CMakeSetupDialog.h @@ -3,6 +3,8 @@ #ifndef CMakeSetupDialog_h #define CMakeSetupDialog_h +#include <memory> + #include "QCMake.h" #include <QEventLoop> #include <QMainWindow> @@ -143,7 +145,7 @@ signals: protected: virtual void run(); - QCMake* CMakeInstance; + std::unique_ptr<QCMake> CMakeInstance; }; #endif // CMakeSetupDialog_h diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx index ca28b19..3c24b9b 100644 --- a/Source/QtDialog/FirstConfigure.cxx +++ b/Source/QtDialog/FirstConfigure.cxx @@ -10,8 +10,12 @@ #include "Compilers.h" -StartCompilerSetup::StartCompilerSetup(QWidget* p) +StartCompilerSetup::StartCompilerSetup(QString defaultGeneratorPlatform, + QString defaultGeneratorToolset, + QWidget* p) : QWizardPage(p) + , DefaultGeneratorPlatform(std::move(defaultGeneratorPlatform)) + , DefaultGeneratorToolset(std::move(defaultGeneratorToolset)) { QVBoxLayout* l = new QVBoxLayout(this); l->addWidget(new QLabel(tr("Specify the generator for this project"))); @@ -68,6 +72,10 @@ QFrame* StartCompilerSetup::CreateToolsetWidgets() Toolset = new QLineEdit(frame); l->addWidget(Toolset); + // Default to CMAKE_GENERATOR_TOOLSET env var if set + if (!DefaultGeneratorToolset.isEmpty()) { + this->Toolset->setText(DefaultGeneratorToolset); + } return frame; } @@ -199,6 +207,14 @@ void StartCompilerSetup::onGeneratorChanged(QString const& name) this->PlatformOptions->addItems(platform_list); PlatformFrame->show(); + + // Default to generator platform from environment + if (!DefaultGeneratorPlatform.isEmpty()) { + int platform_index = platforms.indexOf(DefaultGeneratorPlatform); + if (platform_index != -1) { + this->PlatformOptions->setCurrentIndex(platform_index); + } + } } else { PlatformFrame->hide(); } @@ -421,8 +437,26 @@ void ToolchainCompilerSetup::setToolchainFile(const QString& t) FirstConfigure::FirstConfigure() { + const char* env_generator = std::getenv("CMAKE_GENERATOR"); + const char* env_generator_platform = nullptr; + const char* env_generator_toolset = nullptr; + if (env_generator && std::strlen(env_generator)) { + mDefaultGenerator = env_generator; + env_generator_platform = std::getenv("CMAKE_GENERATOR_PLATFORM"); + env_generator_toolset = std::getenv("CMAKE_GENERATOR_TOOLSET"); + } + + if (!env_generator_platform) { + env_generator_platform = ""; + } + + if (!env_generator_toolset) { + env_generator_toolset = ""; + } + // this->setOption(QWizard::HaveFinishButtonOnEarlyPages, true); - this->mStartCompilerSetupPage = new StartCompilerSetup(this); + this->mStartCompilerSetupPage = new StartCompilerSetup( + env_generator_platform, env_generator_toolset, this); this->setPage(Start, this->mStartCompilerSetupPage); QObject::connect(this->mStartCompilerSetupPage, SIGNAL(selectionChanged()), this, SLOT(restart())); @@ -504,6 +538,17 @@ void FirstConfigure::loadFromSettings() this->mCrossCompilerSetupPage->setIncludeMode( settings.value("IncludeMode", 0).toInt()); settings.endGroup(); + + // environment variables take precedence over application settings because... + // - they're harder to set + // - settings always exist after the program is run once, so the environment + // variables would never be used otherwise + // - platform and toolset are populated only from environment variables, so + // this prevents them from being taken from environment, while the + // generator is taken from application settings + if (!mDefaultGenerator.isEmpty()) { + this->mStartCompilerSetupPage->setCurrentGenerator(mDefaultGenerator); + } } void FirstConfigure::saveToSettings() diff --git a/Source/QtDialog/FirstConfigure.h b/Source/QtDialog/FirstConfigure.h index d1db5bf..c26f489 100644 --- a/Source/QtDialog/FirstConfigure.h +++ b/Source/QtDialog/FirstConfigure.h @@ -29,7 +29,8 @@ class StartCompilerSetup : public QWizardPage { Q_OBJECT public: - StartCompilerSetup(QWidget* p); + StartCompilerSetup(QString defaultGeneratorPlatform, + QString defaultGeneratorToolset, QWidget* p); ~StartCompilerSetup(); void setGenerators(std::vector<cmake::GeneratorInfo> const& gens); void setCurrentGenerator(const QString& gen); @@ -64,6 +65,7 @@ protected: QStringList GeneratorsSupportingPlatform; QMultiMap<QString, QString> GeneratorSupportedPlatforms; QMap<QString, QString> GeneratorDefaultPlatform; + QString DefaultGeneratorPlatform, DefaultGeneratorToolset; private: QFrame* CreateToolsetWidgets(); @@ -197,6 +199,7 @@ protected: NativeCompilerSetup* mNativeCompilerSetupPage; CrossCompilerSetup* mCrossCompilerSetupPage; ToolchainCompilerSetup* mToolchainCompilerSetupPage; + QString mDefaultGenerator; }; #endif // FirstConfigure_h diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 3b5dc04..776af81 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "QCMake.h" +#include <cm/memory> + #include <QCoreApplication> #include <QDir> @@ -35,7 +37,8 @@ QCMake::QCMake(QObject* p) cmSystemTools::SetStderrCallback( [this](std::string const& msg) { this->stderrCallback(msg); }); - this->CMakeInstance = new cmake(cmake::RoleProject, cmState::Project); + this->CMakeInstance = + cm::make_unique<cmake>(cmake::RoleProject, cmState::Project); this->CMakeInstance->SetCMakeEditCommand( cmSystemTools::GetCMakeGUICommand()); this->CMakeInstance->SetProgressCallback( @@ -55,11 +58,7 @@ QCMake::QCMake(QObject* p) } } -QCMake::~QCMake() -{ - delete this->CMakeInstance; - // cmDynamicLoader::FlushCache(); -} +QCMake::~QCMake() = default; void QCMake::loadCache(const QString& dir) { @@ -101,29 +100,28 @@ void QCMake::setBinaryDirectory(const QString& _dir) QCMakePropertyList props = this->properties(); emit this->propertiesChanged(props); - const char* homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"); + cmProp homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"); if (homeDir) { - setSourceDirectory(QString::fromLocal8Bit(homeDir)); + setSourceDirectory(QString::fromLocal8Bit(homeDir->c_str())); } - const char* gen = state->GetCacheEntryValue("CMAKE_GENERATOR"); + cmProp gen = state->GetCacheEntryValue("CMAKE_GENERATOR"); if (gen) { const std::string* extraGen = state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR"); std::string curGen = cmExternalMakefileProjectGenerator::CreateFullGeneratorName( - gen, extraGen ? *extraGen : ""); + *gen, extraGen ? *extraGen : ""); this->setGenerator(QString::fromLocal8Bit(curGen.c_str())); } - const char* platform = - state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); + cmProp platform = state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); if (platform) { - this->setPlatform(QString::fromLocal8Bit(platform)); + this->setPlatform(QString::fromLocal8Bit(platform->c_str())); } - const char* toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); + cmProp toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); if (toolset) { - this->setToolset(QString::fromLocal8Bit(toolset)); + this->setToolset(QString::fromLocal8Bit(toolset->c_str())); } checkOpenPossible(); @@ -304,27 +302,28 @@ QCMakePropertyList QCMake::properties() const continue; } - const char* cachedValue = state->GetCacheEntryValue(key); + cmProp cachedValue = state->GetCacheEntryValue(key); QCMakeProperty prop; prop.Key = QString::fromLocal8Bit(key.c_str()); - prop.Help = - QString::fromLocal8Bit(state->GetCacheEntryProperty(key, "HELPSTRING")); - prop.Value = QString::fromLocal8Bit(cachedValue); + if (cmProp hs = state->GetCacheEntryProperty(key, "HELPSTRING")) { + prop.Help = QString::fromLocal8Bit(hs->c_str()); + } + prop.Value = QString::fromLocal8Bit(cachedValue->c_str()); prop.Advanced = state->GetCacheEntryPropertyAsBool(key, "ADVANCED"); if (t == cmStateEnums::BOOL) { prop.Type = QCMakeProperty::BOOL; - prop.Value = cmIsOn(cachedValue); + prop.Value = cmIsOn(*cachedValue); } else if (t == cmStateEnums::PATH) { prop.Type = QCMakeProperty::PATH; } else if (t == cmStateEnums::FILEPATH) { prop.Type = QCMakeProperty::FILEPATH; } else if (t == cmStateEnums::STRING) { prop.Type = QCMakeProperty::STRING; - const char* stringsProperty = - state->GetCacheEntryProperty(key, "STRINGS"); + cmProp stringsProperty = state->GetCacheEntryProperty(key, "STRINGS"); if (stringsProperty) { - prop.Strings = QString::fromLocal8Bit(stringsProperty).split(";"); + prop.Strings = + QString::fromLocal8Bit(stringsProperty->c_str()).split(";"); } } @@ -486,7 +485,7 @@ void QCMake::setWarnUnusedMode(bool value) void QCMake::checkOpenPossible() { - auto data = this->BinaryDirectory.toLocal8Bit().data(); + std::string data = this->BinaryDirectory.toLocal8Bit().data(); auto possible = this->CMakeInstance->Open(data, true); emit openPossible(possible); } diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h index fa4451b..110a971 100644 --- a/Source/QtDialog/QCMake.h +++ b/Source/QtDialog/QCMake.h @@ -12,6 +12,7 @@ # pragma warning(disable : 4512) #endif +#include <memory> #include <vector> #include <QAtomicInt> @@ -165,7 +166,7 @@ signals: void openPossible(bool possible); protected: - cmake* CMakeInstance; + std::unique_ptr<cmake> CMakeInstance; bool interruptCallback(); void progressCallback(std::string const& msg, float percent); diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 0b2750d..fdfd4c0 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -352,14 +352,14 @@ bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename, line.c_str()); return false; } - const std::string sym = line.substr(0, sym_end); const char sym_type = line[sym_end + 1]; + line.resize(sym_end); switch (sym_type) { case 'D': - dataSymbols.insert(sym); + dataSymbols.insert(line); break; case 'T': - symbols.insert(sym); + symbols.insert(line); break; } } diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx index 35eabaf..83d6306 100644 --- a/Source/cmAddSubDirectoryCommand.cxx +++ b/Source/cmAddSubDirectoryCommand.cxx @@ -4,6 +4,8 @@ #include <cstring> +#include <cm/string_view> + #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmRange.h" @@ -86,7 +88,8 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, if (binLen > 0 && bin.back() == '/') { --binLen; } - binPath = bin.substr(0, binLen) + srcPath.substr(srcLen); + binPath = cmStrCat(cm::string_view(bin).substr(0, binLen), + cm::string_view(srcPath).substr(srcLen)); } else { // Use the binary directory specified. // Interpret a relative path with respect to the current binary directory. diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index 289bb72..d6f7500e 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -6,6 +6,8 @@ #include <cstddef> #include <utility> +#include <cm/string_view> + #include "cmsys/Directory.hxx" #include "cmExecutionStatus.h" @@ -50,11 +52,10 @@ bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args, // Split the filename into base and extension std::string::size_type dotpos = file.rfind('.'); if (dotpos != std::string::npos) { - std::string ext = file.substr(dotpos + 1); - std::string base = file.substr(0, dotpos); + auto ext = cm::string_view(file).substr(dotpos + 1); // Process only source files auto cm = mf.GetCMakeInstance(); - if (!base.empty() && cm->IsSourceExtension(ext)) { + if (dotpos > 0 && cm->IsSourceExtension(ext)) { std::string fullname = cmStrCat(templateDirectory, '/', file); // add the file as a class file so // depends can be done diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx index 0dea825..9ce403d 100644 --- a/Source/cmBinUtilsLinuxELFLinker.cxx +++ b/Source/cmBinUtilsLinuxELFLinker.cxx @@ -6,6 +6,7 @@ #include <sstream> #include <cm/memory> +#include <cm/string_view> #include <cmsys/RegularExpression.hxx> @@ -26,14 +27,16 @@ static std::string ReplaceOrigin(const std::string& rpath, cmsys::RegularExpressionMatch match; if (originRegex.find(rpath.c_str(), match)) { - std::string begin = rpath.substr(0, match.start(1)); - std::string end = rpath.substr(match.end(1)); - return begin + origin + end; + cm::string_view pathv(rpath); + auto begin = pathv.substr(0, match.start(1)); + auto end = pathv.substr(match.end(1)); + return cmStrCat(begin, origin, end); } if (originCurlyRegex.find(rpath.c_str(), match)) { - std::string begin = rpath.substr(0, match.start()); - std::string end = rpath.substr(match.end()); - return begin + origin + end; + cm::string_view pathv(rpath); + auto begin = pathv.substr(0, match.start()); + auto end = pathv.substr(match.end()); + return cmStrCat(begin, origin, end); } return rpath; } diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index 49c9439..b82fb9a 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -108,7 +108,7 @@ bool TwoArgsSignature(std::vector<std::string> const& args, if (cacheValue) { return true; } - mf.AddCacheDefinition(define, makecommand.c_str(), + mf.AddCacheDefinition(define, makecommand, "Command used to build entire project " "from the command line.", cmStateEnums::STRING); diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index 3e517dc..ad4d665 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -28,7 +28,7 @@ bool cmBuildNameCommand(std::vector<std::string> const& args, std::replace(cv.begin(), cv.end(), '/', '_'); std::replace(cv.begin(), cv.end(), '(', '_'); std::replace(cv.begin(), cv.end(), ')', '_'); - mf.AddCacheDefinition(args[0], cv.c_str(), "Name of build.", + mf.AddCacheDefinition(args[0], cv, "Name of build.", cmStateEnums::STRING); } return true; @@ -54,7 +54,7 @@ bool cmBuildNameCommand(std::vector<std::string> const& args, std::replace(buildname.begin(), buildname.end(), '(', '_'); std::replace(buildname.begin(), buildname.end(), ')', '_'); - mf.AddCacheDefinition(args[0], buildname.c_str(), "Name of build.", + mf.AddCacheDefinition(args[0], buildname, "Name of build.", cmStateEnums::STRING); return true; } diff --git a/Source/cmCMakeCommand.cxx b/Source/cmCMakeCommand.cxx new file mode 100644 index 0000000..c11a003 --- /dev/null +++ b/Source/cmCMakeCommand.cxx @@ -0,0 +1,68 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCMakeCommand.h" + +#include <algorithm> +#include <cstddef> + +#include "cmExecutionStatus.h" +#include "cmListFileCache.h" +#include "cmMakefile.h" +#include "cmRange.h" +#include "cmStringAlgorithms.h" + +bool cmCMakeCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.empty()) { + status.SetError("called with incorrect number of arguments"); + return false; + } + + cmMakefile& makefile = status.GetMakefile(); + cmListFileContext context = makefile.GetExecutionContext(); + + bool result = false; + + if (args[0] == "INVOKE") { + if (args.size() == 1) { + status.SetError("called with incorrect number of arguments"); + return false; + } + + // First argument is the name of the function to call + cmListFileFunction func; + func.Name = args[1]; + func.Line = context.Line; + + // The rest of the arguments are passed to the function call above + func.Arguments.resize(args.size() - 1); + for (size_t i = 2; i < args.size(); ++i) { + cmListFileArgument lfarg; + lfarg.Line = context.Line; + lfarg.Value = args[i]; + func.Arguments.emplace_back(lfarg); + } + + result = makefile.ExecuteCommand(func, status); + } else if (args[0] == "EVAL") { + if (args.size() < 2) { + status.SetError("called with incorrect number of arguments"); + return false; + } + + auto code_iter = std::find(args.begin(), args.end(), "CODE"); + if (code_iter == args.end()) { + status.SetError("called without CODE argument"); + return false; + } + + const std::string code = cmJoin(cmMakeRange(++code_iter, args.end()), " "); + result = makefile.ReadListFileAsString( + code, cmStrCat(context.FilePath, ":", context.Line, ":EVAL")); + } else { + status.SetError("called with unknown meta-operation"); + } + + return result; +} diff --git a/Source/cmCMakeCommand.h b/Source/cmCMakeCommand.h new file mode 100644 index 0000000..cf9f4c3 --- /dev/null +++ b/Source/cmCMakeCommand.h @@ -0,0 +1,20 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCMakeCommand_h +#define cmCMakeCommand_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <string> +#include <vector> + +class cmExecutionStatus; + +/** + * \brief Calls a scripted or build-in command + * + */ +bool cmCMakeCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); + +#endif diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index b5c7e96..874efa5 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -488,24 +488,8 @@ struct cmCPluginAPISourceFile // Keep a map from real cmSourceFile instances stored in a makefile to // the CPluginAPI proxy source file. -class cmCPluginAPISourceFileMap - : public std::map<cmSourceFile*, cmCPluginAPISourceFile*> -{ -public: - using derived = std::map<cmSourceFile*, cmCPluginAPISourceFile*>; - using iterator = derived::iterator; - using value_type = derived::value_type; - cmCPluginAPISourceFileMap() = default; - ~cmCPluginAPISourceFileMap() - { - for (auto const& i : *this) { - delete i.second; - } - } - cmCPluginAPISourceFileMap(const cmCPluginAPISourceFileMap&) = delete; - cmCPluginAPISourceFileMap& operator=(const cmCPluginAPISourceFileMap&) = - delete; -}; +using cmCPluginAPISourceFileMap = + std::map<cmSourceFile*, std::unique_ptr<cmCPluginAPISourceFile>>; cmCPluginAPISourceFileMap cmCPluginAPISourceFiles; void* CCONV cmCreateSourceFile(void) @@ -536,7 +520,7 @@ void CCONV* cmGetSource(void* arg, const char* name) auto i = cmCPluginAPISourceFiles.find(rsf); if (i == cmCPluginAPISourceFiles.end()) { // Create a proxy source file object for this source. - cmCPluginAPISourceFile* sf = new cmCPluginAPISourceFile; + auto sf = cm::make_unique<cmCPluginAPISourceFile>(); sf->RealSourceFile = rsf; sf->FullPath = rsf->ResolveFullPath(); sf->SourceName = @@ -545,10 +529,9 @@ void CCONV* cmGetSource(void* arg, const char* name) cmSystemTools::GetFilenameLastExtension(sf->FullPath); // Store the proxy in the map so it can be re-used and deleted later. - cmCPluginAPISourceFileMap::value_type entry(rsf, sf); - i = cmCPluginAPISourceFiles.insert(entry).first; + i = cmCPluginAPISourceFiles.emplace(rsf, std::move(sf)).first; } - return i->second; + return i->second.get(); } return nullptr; } @@ -569,15 +552,16 @@ void* CCONV cmAddSource(void* arg, void* arg2) } // Create the proxy for the real source file. - cmCPluginAPISourceFile* sf = new cmCPluginAPISourceFile; + auto sf = cm::make_unique<cmCPluginAPISourceFile>(); sf->RealSourceFile = rsf; sf->FullPath = osf->FullPath; sf->SourceName = osf->SourceName; sf->SourceExtension = osf->SourceExtension; // Store the proxy in the map so it can be re-used and deleted later. - cmCPluginAPISourceFiles[rsf] = sf; - return sf; + auto value = sf.get(); + cmCPluginAPISourceFiles[rsf] = std::move(sf); + return value; } const char* CCONV cmSourceFileGetSourceName(void* arg) @@ -601,7 +585,8 @@ const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop) if (!strcmp(prop, "LOCATION")) { return sf->FullPath.c_str(); } - return sf->Properties.GetPropertyValue(prop); + cmProp retVal = sf->Properties.GetPropertyValue(prop); + return retVal ? retVal->c_str() : nullptr; } int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop) @@ -791,8 +776,9 @@ void CCONV DefineSourceFileProperty(void* arg, const char* name, const char* longDocs, int chained) { cmMakefile* mf = static_cast<cmMakefile*>(arg); - mf->GetState()->DefineProperty(name, cmProperty::SOURCE_FILE, briefDocs, - longDocs, chained != 0); + mf->GetState()->DefineProperty(name, cmProperty::SOURCE_FILE, + briefDocs ? briefDocs : "", + longDocs ? longDocs : "", chained != 0); } } // close the extern "C" scope diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 04f75bd..c5505f9 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -16,6 +16,10 @@ #include <utility> #include <vector> +#include <cm/memory> +#include <cm/string_view> +#include <cmext/algorithm> + #include "cmsys/Base64.h" #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" @@ -32,8 +36,7 @@ # include <unistd.h> // IWYU pragma: keep #endif -#include <cm/memory> -#include <cmext/algorithm> +#include "cm_static_string_view.hxx" #include "cmCTestBuildAndTestHandler.h" #include "cmCTestBuildHandler.h" @@ -201,7 +204,7 @@ struct cmCTest::Private int SubmitIndex = 0; - cmGeneratedFileStream* OutputLogFile = nullptr; + std::unique_ptr<cmGeneratedFileStream> OutputLogFile; int OutputLogFileLastTag = -1; bool OutputTestOutputOnTestFailure = false; @@ -271,9 +274,10 @@ bool cmCTest::GetTomorrowTag() const return this->Impl->TomorrowTag; } -std::string cmCTest::CleanString(const std::string& str) +std::string cmCTest::CleanString(const std::string& str, + std::string::size_type spos) { - std::string::size_type spos = str.find_first_not_of(" \n\t\r\f\v"); + spos = str.find_first_not_of(" \n\t\r\f\v", spos); std::string::size_type epos = str.find_last_not_of(" \n\t\r\f\v"); if (spos == std::string::npos) { return std::string(); @@ -362,10 +366,7 @@ cmCTest::cmCTest() cmSystemTools::EnableVSConsoleOutput(); } -cmCTest::~cmCTest() -{ - delete this->Impl->OutputLogFile; -} +cmCTest::~cmCTest() = default; int cmCTest::GetParallelLevel() const { @@ -727,7 +728,7 @@ bool cmCTest::UpdateCTestConfiguration() continue; } while (fin && (line.back() == '\\')) { - line = line.substr(0, line.size() - 1); + line.resize(line.size() - 1); buffer[0] = 0; fin.getline(buffer, 1023); buffer[1023] = 0; @@ -741,7 +742,7 @@ bool cmCTest::UpdateCTestConfiguration() continue; } std::string key = line.substr(0, cpos); - std::string value = cmCTest::CleanString(line.substr(cpos + 1)); + std::string value = cmCTest::CleanString(line, cpos + 1); this->Impl->CTestConfiguration[key] = value; } fin.close(); @@ -1442,16 +1443,15 @@ void cmCTest::AddSiteProperties(cmXMLWriter& xml) return; } // This code should go when cdash is changed to use labels only - const char* subproject = cm->GetState()->GetGlobalProperty("SubProject"); + cmProp subproject = cm->GetState()->GetGlobalProperty("SubProject"); if (subproject) { xml.StartElement("Subproject"); - xml.Attribute("name", subproject); - const char* labels = + xml.Attribute("name", *subproject); + cmProp labels = ch->GetCMake()->GetState()->GetGlobalProperty("SubProjectLabels"); if (labels) { xml.StartElement("Labels"); - std::string l = labels; - std::vector<std::string> args = cmExpandedList(l); + std::vector<std::string> args = cmExpandedList(*labels); for (std::string const& i : args) { xml.Element("Label", i); } @@ -1461,10 +1461,10 @@ void cmCTest::AddSiteProperties(cmXMLWriter& xml) } // This code should stay when cdash only does label based sub-projects - const char* label = cm->GetState()->GetGlobalProperty("Label"); + cmProp label = cm->GetState()->GetGlobalProperty("Label"); if (label) { xml.StartElement("Labels"); - xml.Element("Label", label); + xml.Element("Label", *label); xml.EndElement(); } } @@ -1816,10 +1816,10 @@ void cmCTest::ErrorMessageUnknownDashDValue(std::string& val) << " ctest -D NightlyMemoryCheck" << std::endl); } -bool cmCTest::CheckArgument(const std::string& arg, const char* varg1, +bool cmCTest::CheckArgument(const std::string& arg, cm::string_view varg1, const char* varg2) { - return (varg1 && arg == varg1) || (varg2 && arg == varg2); + return (arg == varg1) || (varg2 && arg == varg2); } // Processes one command line argument (and its arguments if any) @@ -1829,21 +1829,21 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, std::string& errormsg) { std::string arg = args[i]; - if (this->CheckArgument(arg, "-F")) { + if (this->CheckArgument(arg, "-F"_s)) { this->Impl->Failover = true; - } - if (this->CheckArgument(arg, "-j", "--parallel") && i < args.size() - 1) { + } else if (this->CheckArgument(arg, "-j"_s, "--parallel") && + i < args.size() - 1) { i++; int plevel = atoi(args[i].c_str()); this->SetParallelLevel(plevel); this->Impl->ParallelLevelSetInCli = true; - } else if (arg.find("-j") == 0) { + } else if (cmHasPrefix(arg, "-j")) { int plevel = atoi(arg.substr(2).c_str()); this->SetParallelLevel(plevel); this->Impl->ParallelLevelSetInCli = true; } - if (this->CheckArgument(arg, "--repeat-until-fail")) { + else if (this->CheckArgument(arg, "--repeat-until-fail"_s)) { if (i >= args.size() - 1) { errormsg = "'--repeat-until-fail' requires an argument"; return false; @@ -1855,8 +1855,8 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, i++; long repeat = 1; if (!cmStrToLong(args[i], &repeat)) { - errormsg = - "'--repeat-until-fail' given non-integer value '" + args[i] + "'"; + errormsg = cmStrCat("'--repeat-until-fail' given non-integer value '", + args[i], "'"); return false; } this->Impl->RepeatCount = static_cast<int>(repeat); @@ -1865,7 +1865,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } } - if (this->CheckArgument(arg, "--repeat")) { + else if (this->CheckArgument(arg, "--repeat"_s)) { if (i >= args.size() - 1) { errormsg = "'--repeat' requires an argument"; return false; @@ -1893,12 +1893,12 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } } } else { - errormsg = "'--repeat' given invalid value '" + args[i] + "'"; + errormsg = cmStrCat("'--repeat' given invalid value '", args[i], "'"); return false; } } - if (this->CheckArgument(arg, "--test-load") && i < args.size() - 1) { + else if (this->CheckArgument(arg, "--test-load"_s) && i < args.size() - 1) { i++; unsigned long load; if (cmStrToULong(args[i], &load)) { @@ -1909,76 +1909,66 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } } - if (this->CheckArgument(arg, "--no-compress-output")) { + else if (this->CheckArgument(arg, "--no-compress-output"_s)) { this->Impl->CompressTestOutput = false; } - if (this->CheckArgument(arg, "--print-labels")) { + else if (this->CheckArgument(arg, "--print-labels"_s)) { this->Impl->PrintLabels = true; } - if (this->CheckArgument(arg, "--http1.0")) { + else if (this->CheckArgument(arg, "--http1.0"_s)) { this->Impl->UseHTTP10 = true; } - if (this->CheckArgument(arg, "--timeout") && i < args.size() - 1) { + else if (this->CheckArgument(arg, "--timeout"_s) && i < args.size() - 1) { i++; auto timeout = cmDuration(atof(args[i].c_str())); this->Impl->GlobalTimeout = timeout; } - if (this->CheckArgument(arg, "--stop-time") && i < args.size() - 1) { + else if (this->CheckArgument(arg, "--stop-time"_s) && i < args.size() - 1) { i++; this->SetStopTime(args[i]); } - if (this->CheckArgument(arg, "-C", "--build-config") && - i < args.size() - 1) { + else if (this->CheckArgument(arg, "-C"_s, "--build-config") && + i < args.size() - 1) { i++; this->SetConfigType(args[i].c_str()); } - if (this->CheckArgument(arg, "--debug")) { + else if (this->CheckArgument(arg, "--debug"_s)) { this->Impl->Debug = true; this->Impl->ShowLineNumbers = true; - } - if (this->CheckArgument(arg, "--group") && i < args.size() - 1) { + } else if (this->CheckArgument(arg, "--group"_s) && i < args.size() - 1) { i++; this->Impl->SpecificGroup = args[i]; } // This is an undocumented / deprecated option. // "Track" has been renamed to "Group". - if (this->CheckArgument(arg, "--track") && i < args.size() - 1) { + else if (this->CheckArgument(arg, "--track"_s) && i < args.size() - 1) { i++; this->Impl->SpecificGroup = args[i]; - } - if (this->CheckArgument(arg, "--show-line-numbers")) { + } else if (this->CheckArgument(arg, "--show-line-numbers"_s)) { this->Impl->ShowLineNumbers = true; - } - if (this->CheckArgument(arg, "--no-label-summary")) { + } else if (this->CheckArgument(arg, "--no-label-summary"_s)) { this->Impl->LabelSummary = false; - } - if (this->CheckArgument(arg, "--no-subproject-summary")) { + } else if (this->CheckArgument(arg, "--no-subproject-summary"_s)) { this->Impl->SubprojectSummary = false; - } - if (this->CheckArgument(arg, "-Q", "--quiet")) { + } else if (this->CheckArgument(arg, "-Q"_s, "--quiet")) { this->Impl->Quiet = true; - } - if (this->CheckArgument(arg, "--progress")) { + } else if (this->CheckArgument(arg, "--progress"_s)) { this->Impl->TestProgressOutput = true; - } - if (this->CheckArgument(arg, "-V", "--verbose")) { + } else if (this->CheckArgument(arg, "-V"_s, "--verbose")) { this->Impl->Verbose = true; - } - if (this->CheckArgument(arg, "-VV", "--extra-verbose")) { + } else if (this->CheckArgument(arg, "-VV"_s, "--extra-verbose")) { this->Impl->ExtraVerbose = true; this->Impl->Verbose = true; - } - if (this->CheckArgument(arg, "--output-on-failure")) { + } else if (this->CheckArgument(arg, "--output-on-failure"_s)) { this->Impl->OutputTestOutputOnTestFailure = true; - } - if (this->CheckArgument(arg, "--test-output-size-passed") && - i < args.size() - 1) { + } else if (this->CheckArgument(arg, "--test-output-size-passed"_s) && + i < args.size() - 1) { i++; long outputSize; if (cmStrToLong(args[i], &outputSize)) { @@ -1988,9 +1978,8 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, "Invalid value for '--test-output-size-passed': " << args[i] << "\n"); } - } - if (this->CheckArgument(arg, "--test-output-size-failed") && - i < args.size() - 1) { + } else if (this->CheckArgument(arg, "--test-output-size-failed"_s) && + i < args.size() - 1) { i++; long outputSize; if (cmStrToLong(args[i], &outputSize)) { @@ -2000,11 +1989,9 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, "Invalid value for '--test-output-size-failed': " << args[i] << "\n"); } - } - if (this->CheckArgument(arg, "-N", "--show-only")) { + } else if (this->CheckArgument(arg, "-N"_s, "--show-only")) { this->Impl->ShowOnly = true; - } - if (cmHasLiteralPrefix(arg, "--show-only=")) { + } else if (cmHasLiteralPrefix(arg, "--show-only=")) { this->Impl->ShowOnly = true; // Check if a specific format is requested. Defaults to human readable @@ -2022,27 +2009,26 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } } - if (this->CheckArgument(arg, "-O", "--output-log") && i < args.size() - 1) { + else if (this->CheckArgument(arg, "-O"_s, "--output-log") && + i < args.size() - 1) { i++; this->SetOutputLogFileName(args[i].c_str()); } - if (this->CheckArgument(arg, "--tomorrow-tag")) { + else if (this->CheckArgument(arg, "--tomorrow-tag"_s)) { this->Impl->TomorrowTag = true; - } - if (this->CheckArgument(arg, "--force-new-ctest-process")) { + } else if (this->CheckArgument(arg, "--force-new-ctest-process"_s)) { this->Impl->ForceNewCTestProcess = true; - } - if (this->CheckArgument(arg, "-W", "--max-width") && i < args.size() - 1) { + } else if (this->CheckArgument(arg, "-W"_s, "--max-width") && + i < args.size() - 1) { i++; this->Impl->MaxTestNameWidth = atoi(args[i].c_str()); - } - if (this->CheckArgument(arg, "--interactive-debug-mode") && - i < args.size() - 1) { + } else if (this->CheckArgument(arg, "--interactive-debug-mode"_s) && + i < args.size() - 1) { i++; this->Impl->InteractiveDebugMode = cmIsOn(args[i]); - } - if (this->CheckArgument(arg, "--submit-index") && i < args.size() - 1) { + } else if (this->CheckArgument(arg, "--submit-index"_s) && + i < args.size() - 1) { i++; this->Impl->SubmitIndex = atoi(args[i].c_str()); if (this->Impl->SubmitIndex < 0) { @@ -2050,24 +2036,27 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } } - if (this->CheckArgument(arg, "--overwrite") && i < args.size() - 1) { + else if (this->CheckArgument(arg, "--overwrite"_s) && i < args.size() - 1) { i++; this->AddCTestConfigurationOverwrite(args[i]); - } - if (this->CheckArgument(arg, "-A", "--add-notes") && i < args.size() - 1) { + } else if (this->CheckArgument(arg, "-A"_s, "--add-notes") && + i < args.size() - 1) { this->Impl->ProduceXML = true; this->SetTest("Notes"); i++; this->SetNotesFiles(args[i].c_str()); + return true; } - const std::string noTestsPrefix = "--no-tests="; + cm::string_view noTestsPrefix = "--no-tests="; if (cmHasPrefix(arg, noTestsPrefix)) { - const std::string noTestsMode = arg.substr(noTestsPrefix.length()); + cm::string_view noTestsMode = + cm::string_view(arg).substr(noTestsPrefix.length()); if (noTestsMode == "error") { this->Impl->NoTestsMode = cmCTest::NoTests::Error; } else if (noTestsMode != "ignore") { - errormsg = "'--no-tests=' given unknown value '" + noTestsMode + "'"; + errormsg = + cmStrCat("'--no-tests=' given unknown value '", noTestsMode, '\''); return false; } else { this->Impl->NoTestsMode = cmCTest::NoTests::Ignore; @@ -2075,34 +2064,32 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } // options that control what tests are run - if (this->CheckArgument(arg, "-I", "--tests-information") && - i < args.size() - 1) { + else if (this->CheckArgument(arg, "-I"_s, "--tests-information") && + i < args.size() - 1) { i++; this->GetTestHandler()->SetPersistentOption("TestsToRunInformation", args[i].c_str()); this->GetMemCheckHandler()->SetPersistentOption("TestsToRunInformation", args[i].c_str()); - } - if (this->CheckArgument(arg, "-U", "--union")) { + } else if (this->CheckArgument(arg, "-U"_s, "--union")) { this->GetTestHandler()->SetPersistentOption("UseUnion", "true"); this->GetMemCheckHandler()->SetPersistentOption("UseUnion", "true"); - } - if (this->CheckArgument(arg, "-R", "--tests-regex") && i < args.size() - 1) { + } else if (this->CheckArgument(arg, "-R"_s, "--tests-regex") && + i < args.size() - 1) { i++; this->GetTestHandler()->SetPersistentOption("IncludeRegularExpression", args[i].c_str()); this->GetMemCheckHandler()->SetPersistentOption("IncludeRegularExpression", args[i].c_str()); - } - if (this->CheckArgument(arg, "-L", "--label-regex") && i < args.size() - 1) { + } 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()); - } - if (this->CheckArgument(arg, "-LE", "--label-exclude") && - i < args.size() - 1) { + } else if (this->CheckArgument(arg, "-LE"_s, "--label-exclude") && + i < args.size() - 1) { i++; this->GetTestHandler()->SetPersistentOption( "ExcludeLabelRegularExpression", args[i].c_str()); @@ -2110,8 +2097,8 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, "ExcludeLabelRegularExpression", args[i].c_str()); } - if (this->CheckArgument(arg, "-E", "--exclude-regex") && - i < args.size() - 1) { + else if (this->CheckArgument(arg, "-E"_s, "--exclude-regex") && + i < args.size() - 1) { i++; this->GetTestHandler()->SetPersistentOption("ExcludeRegularExpression", args[i].c_str()); @@ -2119,24 +2106,22 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, args[i].c_str()); } - if (this->CheckArgument(arg, "-FA", "--fixture-exclude-any") && - i < args.size() - 1) { + else if (this->CheckArgument(arg, "-FA"_s, "--fixture-exclude-any") && + i < args.size() - 1) { i++; this->GetTestHandler()->SetPersistentOption( "ExcludeFixtureRegularExpression", args[i].c_str()); this->GetMemCheckHandler()->SetPersistentOption( "ExcludeFixtureRegularExpression", args[i].c_str()); - } - if (this->CheckArgument(arg, "-FS", "--fixture-exclude-setup") && - i < args.size() - 1) { + } else if (this->CheckArgument(arg, "-FS"_s, "--fixture-exclude-setup") && + i < args.size() - 1) { i++; this->GetTestHandler()->SetPersistentOption( "ExcludeFixtureSetupRegularExpression", args[i].c_str()); this->GetMemCheckHandler()->SetPersistentOption( "ExcludeFixtureSetupRegularExpression", args[i].c_str()); - } - if (this->CheckArgument(arg, "-FC", "--fixture-exclude-cleanup") && - i < args.size() - 1) { + } else if (this->CheckArgument(arg, "-FC"_s, "--fixture-exclude-cleanup") && + i < args.size() - 1) { i++; this->GetTestHandler()->SetPersistentOption( "ExcludeFixtureCleanupRegularExpression", args[i].c_str()); @@ -2144,8 +2129,8 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, "ExcludeFixtureCleanupRegularExpression", args[i].c_str()); } - if (this->CheckArgument(arg, "--resource-spec-file") && - i < args.size() - 1) { + else if (this->CheckArgument(arg, "--resource-spec-file"_s) && + i < args.size() - 1) { i++; this->GetTestHandler()->SetPersistentOption("ResourceSpecFile", args[i].c_str()); @@ -2153,7 +2138,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, args[i].c_str()); } - if (this->CheckArgument(arg, "--rerun-failed")) { + else if (this->CheckArgument(arg, "--rerun-failed"_s)) { this->GetTestHandler()->SetPersistentOption("RerunFailed", "true"); this->GetMemCheckHandler()->SetPersistentOption("RerunFailed", "true"); } @@ -2205,7 +2190,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args, bool& SRArgumentSpecified) { std::string arg = args[i]; - if (this->CheckArgument(arg, "-SP", "--script-new-process") && + if (this->CheckArgument(arg, "-SP"_s, "--script-new-process") && i < args.size() - 1) { this->Impl->RunConfigurationScript = true; i++; @@ -2216,7 +2201,8 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args, } } - if (this->CheckArgument(arg, "-SR", "--script-run") && i < args.size() - 1) { + if (this->CheckArgument(arg, "-SR"_s, "--script-run") && + i < args.size() - 1) { SRArgumentSpecified = true; this->Impl->RunConfigurationScript = true; i++; @@ -2224,7 +2210,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args, ch->AddConfigurationScript(args[i].c_str(), true); } - if (this->CheckArgument(arg, "-S", "--script") && i < args.size() - 1) { + if (this->CheckArgument(arg, "-S"_s, "--script") && i < args.size() - 1) { this->Impl->RunConfigurationScript = true; i++; cmCTestScriptHandler* ch = this->GetScriptHandler(); @@ -2274,7 +2260,8 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) // --dashboard: handle a request for a dashboard std::string arg = args[i]; - if (this->CheckArgument(arg, "-D", "--dashboard") && i < args.size() - 1) { + if (this->CheckArgument(arg, "-D"_s, "--dashboard") && + i < args.size() - 1) { this->Impl->ProduceXML = true; i++; std::string targ = args[i]; @@ -2310,7 +2297,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) } // --extra-submit - if (this->CheckArgument(arg, "--extra-submit") && i < args.size() - 1) { + if (this->CheckArgument(arg, "--extra-submit"_s) && i < args.size() - 1) { this->Impl->ProduceXML = true; this->SetTest("Submit"); i++; @@ -2320,12 +2307,13 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) } // --build-and-test options - if (this->CheckArgument(arg, "--build-and-test") && i < args.size() - 1) { + if (this->CheckArgument(arg, "--build-and-test"_s) && + i < args.size() - 1) { cmakeAndTest = true; } // --schedule-random - if (this->CheckArgument(arg, "--schedule-random")) { + if (this->CheckArgument(arg, "--schedule-random"_s)) { this->Impl->ScheduleType = "Random"; } @@ -2380,7 +2368,7 @@ bool cmCTest::HandleTestActionArgument(const char* ctestExec, size_t& i, { bool success = true; std::string arg = args[i]; - if (this->CheckArgument(arg, "-T", "--test-action") && + if (this->CheckArgument(arg, "-T"_s, "--test-action") && (i < args.size() - 1)) { this->Impl->ProduceXML = true; i++; @@ -2412,15 +2400,15 @@ bool cmCTest::HandleTestModelArgument(const char* ctestExec, size_t& i, { bool success = true; std::string arg = args[i]; - if (this->CheckArgument(arg, "-M", "--test-model") && + if (this->CheckArgument(arg, "-M"_s, "--test-model") && (i < args.size() - 1)) { i++; std::string const& str = args[i]; - if (cmSystemTools::LowerCase(str) == "nightly") { + if (cmSystemTools::LowerCase(str) == "nightly"_s) { this->SetTestModel(cmCTest::NIGHTLY); - } else if (cmSystemTools::LowerCase(str) == "continuous") { + } else if (cmSystemTools::LowerCase(str) == "continuous"_s) { this->SetTestModel(cmCTest::CONTINUOUS); - } else if (cmSystemTools::LowerCase(str) == "experimental") { + } else if (cmSystemTools::LowerCase(str) == "experimental"_s) { this->SetTestModel(cmCTest::EXPERIMENTAL); } else { success = false; @@ -2687,7 +2675,7 @@ std::string cmCTest::GetShortPathToFile(const char* cfname) path = "./" + *res; if (path.back() == '/') { - path = path.substr(0, path.size() - 1); + path.resize(path.size() - 1); } } @@ -2738,7 +2726,7 @@ std::string cmCTest::GetSubmitURL() std::string site = this->GetCTestConfiguration("DropSite"); std::string location = this->GetCTestConfiguration("DropLocation"); - url = cmStrCat(method.empty() ? "http" : method, "://"); + url = cmStrCat(method.empty() ? "http" : method, "://"_s); if (!user.empty()) { url += user; if (!password.empty()) { @@ -3086,12 +3074,10 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args, void cmCTest::SetOutputLogFileName(const char* name) { - if (this->Impl->OutputLogFile) { - delete this->Impl->OutputLogFile; - this->Impl->OutputLogFile = nullptr; - } if (name) { - this->Impl->OutputLogFile = new cmGeneratedFileStream(name); + this->Impl->OutputLogFile = cm::make_unique<cmGeneratedFileStream>(name); + } else { + this->Impl->OutputLogFile.reset(); } } diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 7f8f913..984be13 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -13,6 +13,8 @@ #include <string> #include <vector> +#include <cm/string_view> + #include "cmDuration.h" #include "cmProcessOutput.h" @@ -140,7 +142,8 @@ public: std::string GetTestModelString(); static int GetTestModelFromString(const char* str); - static std::string CleanString(const std::string& str); + static std::string CleanString(const std::string& str, + std::string::size_type spos = 0); std::string GetCTestConfiguration(const std::string& name); void SetCTestConfiguration(const char* name, const char* value, bool suppress = false); @@ -506,8 +509,8 @@ private: std::vector<std::string> const& files); /** Check if the argument is the one specified */ - bool CheckArgument(const std::string& arg, const char* varg1, - const char* varg2 = nullptr); + static bool CheckArgument(const std::string& arg, cm::string_view varg1, + const char* varg2 = nullptr); /** Output errors from a test */ void OutputTestErrors(std::vector<char> const& process_output); diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index dc9aba1..31a8692 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -77,7 +77,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, } while (realbuffer[0] == '/' && realbuffer[1] == '/') { if ((realbuffer[2] == '\\') && (realbuffer[3] == 'n')) { - helpString += "\n"; + helpString += '\n'; helpString += &realbuffer[4]; } else { helpString += &realbuffer[2]; @@ -117,20 +117,20 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, } } else { std::ostringstream error; - error << "Parse error in cache file " << cacheFile; - error << " on line " << lineno << ". Offending entry: " << realbuffer; + error << "Parse error in cache file " << cacheFile << " on line " + << lineno << ". Offending entry: " << realbuffer; cmSystemTools::Error(error.str()); } } this->CacheMajorVersion = 0; this->CacheMinorVersion = 0; - if (const std::string* cmajor = + if (cmProp cmajor = this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) { unsigned int v = 0; if (sscanf(cmajor->c_str(), "%u", &v) == 1) { this->CacheMajorVersion = v; } - if (const std::string* cminor = + if (cmProp cminor = this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) { if (sscanf(cminor->c_str(), "%u", &v) == 1) { this->CacheMinorVersion = v; @@ -150,8 +150,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, } // check to make sure the cache directory has not // been moved - const std::string* oldDir = - this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); + cmProp oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); if (internal && oldDir) { std::string currentcwd = path; std::string oldcwd = *oldDir; @@ -159,8 +158,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, currentcwd += "/CMakeCache.txt"; oldcwd += "/CMakeCache.txt"; if (!cmSystemTools::SameFile(oldcwd, currentcwd)) { - const std::string* dir = - this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); + cmProp dir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); std::ostringstream message; message << "The current CMakeCache.txt directory " << currentcwd << " is different than the directory " << (dir ? *dir : "") @@ -210,7 +208,7 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i, cmMessenger* messenger) { for (const char** p = cmCacheManager::PersistentProperties; *p; ++p) { - if (const char* value = i.GetProperty(*p)) { + if (cmProp value = i.GetProperty(*p)) { std::string helpstring = cmStrCat(*p, " property for variable: ", i.GetName()); cmCacheManager::OutputHelpString(os, helpstring); @@ -218,9 +216,9 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i, std::string key = cmStrCat(i.GetName(), '-', *p); cmCacheManager::OutputKey(os, key); os << ":INTERNAL="; - cmCacheManager::OutputValue(os, value); - os << "\n"; - cmCacheManager::OutputNewlineTruncationWarning(os, key, value, + cmCacheManager::OutputValue(os, *value); + os << '\n'; + cmCacheManager::OutputNewlineTruncationWarning(os, key, *value, messenger); } } @@ -270,31 +268,29 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) /* clang-format off */ fout << "# This is the CMakeCache file.\n" - << "# For build in directory: " << currentcwd << "\n" - << "# It was generated by CMake: " - << cmSystemTools::GetCMakeCommand() << std::endl; + "# For build in directory: " << currentcwd << "\n" + "# It was generated by CMake: " + << cmSystemTools::GetCMakeCommand() + << "\n" + "# You can edit this file to change values found and used by cmake." + "\n" + "# If you do not want to change any of the values, simply exit the " + "editor.\n" + "# If you do want to change a value, simply edit, save, and exit " + "the editor.\n" + "# The syntax for the file is as follows:\n" + "# KEY:TYPE=VALUE\n" + "# KEY is the name of a variable in the cache.\n" + "# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!." + "\n" + "# VALUE is the current value for the KEY.\n" + "\n" + "########################\n" + "# EXTERNAL cache entries\n" + "########################\n" + "\n"; /* clang-format on */ - /* clang-format off */ - fout << "# You can edit this file to change values found and used by cmake." - << std::endl - << "# If you do not want to change any of the values, simply exit the " - "editor." << std::endl - << "# If you do want to change a value, simply edit, save, and exit " - "the editor." << std::endl - << "# The syntax for the file is as follows:\n" - << "# KEY:TYPE=VALUE\n" - << "# KEY is the name of a variable in the cache.\n" - << "# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT " - "TYPE!." << std::endl - << "# VALUE is the current value for the KEY.\n\n"; - /* clang-format on */ - - fout << "########################\n"; - fout << "# EXTERNAL cache entries\n"; - fout << "########################\n"; - fout << "\n"; - for (auto const& i : this->Cache) { CacheEntry const& ce = i.second; cmStateEnums::CacheEntryType t = ce.Type; @@ -305,26 +301,26 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) */ } else if (t != cmStateEnums::INTERNAL) { // Format is key:type=value - if (const char* help = ce.GetProperty("HELPSTRING")) { - cmCacheManager::OutputHelpString(fout, help); + if (cmProp help = ce.GetProperty("HELPSTRING")) { + cmCacheManager::OutputHelpString(fout, *help); } else { cmCacheManager::OutputHelpString(fout, "Missing description"); } cmCacheManager::OutputKey(fout, i.first); - fout << ":" << cmState::CacheEntryTypeToString(t) << "="; + fout << ':' << cmState::CacheEntryTypeToString(t) << '='; cmCacheManager::OutputValue(fout, ce.Value); - fout << "\n"; + fout << '\n'; cmCacheManager::OutputNewlineTruncationWarning(fout, i.first, ce.Value, messenger); - fout << "\n"; + fout << '\n'; } } - fout << "\n"; - fout << "########################\n"; - fout << "# INTERNAL cache entries\n"; - fout << "########################\n"; - fout << "\n"; + fout << "\n" + "########################\n" + "# INTERNAL cache entries\n" + "########################\n" + "\n"; for (cmCacheManager::CacheIterator i = this->NewIterator(); !i.IsAtEnd(); i.Next()) { @@ -336,18 +332,18 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) this->WritePropertyEntries(fout, i, messenger); if (t == cmStateEnums::INTERNAL) { // Format is key:type=value - if (const char* help = i.GetProperty("HELPSTRING")) { - cmCacheManager::OutputHelpString(fout, help); + if (cmProp help = i.GetProperty("HELPSTRING")) { + cmCacheManager::OutputHelpString(fout, *help); } cmCacheManager::OutputKey(fout, i.GetName()); - fout << ":" << cmState::CacheEntryTypeToString(t) << "="; + fout << ':' << cmState::CacheEntryTypeToString(t) << '='; cmCacheManager::OutputValue(fout, i.GetValue()); - fout << "\n"; + fout << '\n'; cmCacheManager::OutputNewlineTruncationWarning(fout, i.GetName(), i.GetValue(), messenger); } } - fout << "\n"; + fout << '\n'; fout.Close(); std::string checkCacheFile = cmStrCat(path, "/CMakeFiles"); cmSystemTools::MakeDirectory(checkCacheFile); @@ -385,7 +381,9 @@ void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key) { // support : in key name by double quoting const char* q = - (key.find(':') != std::string::npos || key.find("//") == 0) ? "\"" : ""; + (key.find(':') != std::string::npos || cmHasLiteralPrefix(key, "//")) + ? "\"" + : ""; fout << q << key << q; } @@ -430,7 +428,7 @@ void cmCacheManager::OutputHelpString(std::ostream& fout, fout << "\\n"; } oneLine = helpString.substr(pos, i - pos); - fout << oneLine << "\n"; + fout << oneLine << '\n'; pos = i; } } @@ -452,7 +450,7 @@ void cmCacheManager::OutputWarningComment(std::ostream& fout, fout << "\\n"; } oneLine = message.substr(pos, i - pos); - fout << oneLine << "\n"; + fout << oneLine << '\n'; pos = i; } } @@ -508,8 +506,7 @@ cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator() return { *this, nullptr }; } -const std::string* cmCacheManager::GetInitializedCacheValue( - const std::string& key) const +cmProp cmCacheManager::GetInitializedCacheValue(const std::string& key) const { auto i = this->Cache.find(key); if (i != this->Cache.end() && i->second.Initialized) { @@ -520,17 +517,17 @@ const std::string* cmCacheManager::GetInitializedCacheValue( void cmCacheManager::PrintCache(std::ostream& out) const { - out << "=================================================" << std::endl; - out << "CMakeCache Contents:" << std::endl; + out << "=================================================\n" + "CMakeCache Contents:\n"; for (auto const& i : this->Cache) { if (i.second.Type != cmStateEnums::INTERNAL) { - out << i.first << " = " << i.second.Value << std::endl; + out << i.first << " = " << i.second.Value << '\n'; } } - out << "\n\n"; - out << "To change values in the CMakeCache, " << std::endl - << "edit CMakeCache.txt in your output directory.\n"; - out << "=================================================" << std::endl; + out << "\n\n" + "To change values in the CMakeCache, \n" + "edit CMakeCache.txt in your output directory.\n" + "=================================================\n"; } void cmCacheManager::AddCacheEntry(const std::string& key, const char* value, @@ -619,14 +616,13 @@ std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const return this->Properties.GetKeys(); } -const char* cmCacheManager::CacheEntry::GetProperty( - const std::string& prop) const +cmProp cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const { if (prop == "TYPE") { - return cmState::CacheEntryTypeToString(this->Type).c_str(); + return &cmState::CacheEntryTypeToString(this->Type); } if (prop == "VALUE") { - return this->Value.c_str(); + return &this->Value; } return this->Properties.GetPropertyValue(prop); } @@ -662,7 +658,7 @@ void cmCacheManager::CacheEntry::AppendProperty(const std::string& prop, } } -const char* cmCacheManager::CacheIterator::GetProperty( +cmProp cmCacheManager::CacheIterator::GetProperty( const std::string& prop) const { if (!this->IsAtEnd()) { @@ -691,8 +687,8 @@ void cmCacheManager::CacheIterator::AppendProperty(const std::string& p, bool cmCacheManager::CacheIterator::GetPropertyAsBool( const std::string& prop) const { - if (const char* value = this->GetProperty(prop)) { - return cmIsOn(value); + if (cmProp value = this->GetProperty(prop)) { + return cmIsOn(*value); } return false; } diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index d8be991..3db76a9 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -37,7 +37,7 @@ private: cmStateEnums::CacheEntryType Type = cmStateEnums::UNINITIALIZED; cmPropertyMap Properties; std::vector<std::string> GetPropertyList() const; - const char* GetProperty(const std::string&) const; + cmProp GetProperty(const std::string&) const; void SetProperty(const std::string& property, const char* value); void AppendProperty(const std::string& property, const std::string& value, bool asString = false); @@ -54,7 +54,7 @@ public: void Next(); std::string GetName() const { return this->Position->first; } std::vector<std::string> GetPropertyList() const; - const char* GetProperty(const std::string&) const; + cmProp GetProperty(const std::string&) const; bool GetPropertyAsBool(const std::string&) const; bool PropertyExists(const std::string&) const; void SetProperty(const std::string& property, const char* value); @@ -121,19 +121,19 @@ public: int GetSize() { return static_cast<int>(this->Cache.size()); } //! Get a value from the cache given a key - const std::string* GetInitializedCacheValue(const std::string& key) const; + cmProp GetInitializedCacheValue(const std::string& key) const; - const char* GetCacheEntryValue(const std::string& key) + cmProp GetCacheEntryValue(const std::string& key) { cmCacheManager::CacheIterator it = this->GetCacheIterator(key); if (it.IsAtEnd()) { return nullptr; } - return it.GetValue().c_str(); + return &it.GetValue(); } - const char* GetCacheEntryProperty(std::string const& key, - std::string const& propName) + cmProp GetCacheEntryProperty(std::string const& key, + std::string const& propName) { return this->GetCacheIterator(key).GetProperty(propName); } diff --git a/Source/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx index 9e152ff..94b6e18 100644 --- a/Source/cmCallVisualStudioMacro.cxx +++ b/Source/cmCallVisualStudioMacro.cxx @@ -43,8 +43,7 @@ static bool LogErrorsAsMessages; if (LogErrorsAsMessages) { \ std::ostringstream _hresult_oss; \ _hresult_oss.flags(std::ios::hex); \ - _hresult_oss << context << " failed HRESULT, hr = 0x" << hr \ - << std::endl; \ + _hresult_oss << context << " failed HRESULT, hr = 0x" << hr << '\n'; \ _hresult_oss.flags(std::ios::dec); \ _hresult_oss << __FILE__ << "(" << __LINE__ << ")"; \ cmSystemTools::Message(_hresult_oss.str()); \ @@ -98,32 +97,37 @@ HRESULT InstanceCallMacro(IDispatch* vsIDE, const std::string& macro, DISPATCH_METHOD, ¶ms, &result, &excep, &arg); std::ostringstream oss; - oss << std::endl; - oss << "Invoke(ExecuteCommand)" << std::endl; - oss << " Macro: " << macro << std::endl; - oss << " Args: " << args << std::endl; + /* clang-format off */ + oss << "\nInvoke(ExecuteCommand)\n" + " Macro: " << macro << "\n" + " Args: " << args << '\n'; + /* clang-format on */ if (DISP_E_EXCEPTION == hr) { - oss << "DISP_E_EXCEPTION EXCEPINFO:" << excep.wCode << std::endl; - oss << " wCode: " << excep.wCode << std::endl; - oss << " wReserved: " << excep.wReserved << std::endl; + /* clang-format off */ + oss << "DISP_E_EXCEPTION EXCEPINFO:" << excep.wCode << "\n" + " wCode: " << excep.wCode << "\n" + " wReserved: " << excep.wReserved << '\n'; + /* clang-format on */ if (excep.bstrSource) { oss << " bstrSource: " << (const char*)(_bstr_t)excep.bstrSource - << std::endl; + << '\n'; } if (excep.bstrDescription) { oss << " bstrDescription: " - << (const char*)(_bstr_t)excep.bstrDescription << std::endl; + << (const char*)(_bstr_t)excep.bstrDescription << '\n'; } if (excep.bstrHelpFile) { oss << " bstrHelpFile: " << (const char*)(_bstr_t)excep.bstrHelpFile - << std::endl; + << '\n'; } - oss << " dwHelpContext: " << excep.dwHelpContext << std::endl; - oss << " pvReserved: " << excep.pvReserved << std::endl; - oss << " pfnDeferredFillIn: " - << reinterpret_cast<void*>(excep.pfnDeferredFillIn) << std::endl; - oss << " scode: " << excep.scode << std::endl; + /* clang-format off */ + oss << " dwHelpContext: " << excep.dwHelpContext << "\n" + " pvReserved: " << excep.pvReserved << "\n" + " pfnDeferredFillIn: " + << reinterpret_cast<void*>(excep.pfnDeferredFillIn) << "\n" + " scode: " << excep.scode << '\n'; + /* clang-format on */ } std::string exstr(oss.str()); diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index 613ae06..379836a 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -5,6 +5,9 @@ #include <cstring> #include <iostream> #include <sstream> +#include <utility> + +#include <cm/memory> #include "cmCommandArgumentLexer.h" #include "cmMakefile.h" @@ -40,10 +43,10 @@ const char* cmCommandArgumentParserHelper::AddString(const std::string& str) if (str.empty()) { return ""; } - char* stVal = new char[str.size() + 1]; - strcpy(stVal, str.c_str()); - this->Variables.push_back(stVal); - return stVal; + auto stVal = cm::make_unique<char[]>(str.size() + 1); + strcpy(stVal.get(), str.c_str()); + this->Variables.push_back(std::move(stVal)); + return this->Variables.back().get(); } const char* cmCommandArgumentParserHelper::ExpandSpecialVariable( @@ -136,11 +139,11 @@ const char* cmCommandArgumentParserHelper::CombineUnions(const char* in1, return in1; } size_t len = strlen(in1) + strlen(in2) + 1; - char* out = new char[len]; - strcpy(out, in1); - strcat(out, in2); - this->Variables.push_back(out); - return out; + auto out = cm::make_unique<char[]>(len); + strcpy(out.get(), in1); + strcat(out.get(), in2); + this->Variables.push_back(std::move(out)); + return this->Variables.back().get(); } void cmCommandArgumentParserHelper::AllocateParserType( @@ -153,11 +156,11 @@ void cmCommandArgumentParserHelper::AllocateParserType( if (len == 0) { return; } - char* out = new char[len + 1]; - memcpy(out, str, len); - out[len] = 0; - pt->str = out; - this->Variables.push_back(out); + auto out = cm::make_unique<char[]>(len + 1); + memcpy(out.get(), str, len); + out.get()[len] = 0; + pt->str = out.get(); + this->Variables.push_back(std::move(out)); } bool cmCommandArgumentParserHelper::HandleEscapeSymbol( @@ -235,10 +238,7 @@ int cmCommandArgumentParserHelper::ParseString(const char* str, int verb) void cmCommandArgumentParserHelper::CleanupParser() { - for (char* var : this->Variables) { - delete[] var; - } - this->Variables.erase(this->Variables.begin(), this->Variables.end()); + this->Variables.clear(); } int cmCommandArgumentParserHelper::LexInput(char* buf, int maxlen) diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h index 25e6892..b46edcb 100644 --- a/Source/cmCommandArgumentParserHelper.h +++ b/Source/cmCommandArgumentParserHelper.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <string> #include <vector> @@ -69,7 +70,7 @@ private: void CleanupParser(); void SetError(std::string const& msg); - std::vector<char*> Variables; + std::vector<std::unique_ptr<char[]>> Variables; const cmMakefile* Makefile; std::string Result; std::string ErrorString; diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 896b6a9..28b4267 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -91,6 +91,7 @@ # include "cmAddLinkOptionsCommand.h" # include "cmAuxSourceDirectoryCommand.h" # include "cmBuildNameCommand.h" +# include "cmCMakeCommand.h" # include "cmCMakeHostSystemInformationCommand.h" # include "cmExportCommand.h" # include "cmExportLibraryDependenciesCommand.h" @@ -196,6 +197,7 @@ void GetScriptingCommands(cmState* state) "match the opening WHILE command."); #if !defined(CMAKE_BOOTSTRAP) + state->AddBuiltinCommand("cmake_command", cmCMakeCommand); state->AddBuiltinCommand("cmake_host_system_information", cmCMakeHostSystemInformationCommand); state->AddBuiltinCommand("load_cache", cmLoadCacheCommand); diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 11570d6..8d27699 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1200,7 +1200,8 @@ void cmComputeLinkInformation::AddUserItem(BT<std::string> const& item, // CMP0003 so put it in OldUserFlagItems, if it is not a -l // or -Wl,-l (-framework -pthread), then allow it without a // CMP0003 as -L will not affect those other linker flags - if (item.Value.find("-l") == 0 || item.Value.find("-Wl,-l") == 0) { + if (cmHasLiteralPrefix(item.Value, "-l") || + cmHasLiteralPrefix(item.Value, "-Wl,-l")) { // This is a linker option provided by the user. this->OldUserFlagItems.push_back(item.Value); } @@ -1796,11 +1797,11 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // support or if using the link path as an rpath. if (use_build_rpath) { std::string d = ri; - if (!rootPath.empty() && d.find(rootPath) == 0) { - d = d.substr(rootPath.size()); - } else if (stagePath && *stagePath && d.find(stagePath) == 0) { - std::string suffix = d.substr(strlen(stagePath)); - d = cmStrCat(installPrefix, '/', suffix); + if (!rootPath.empty() && cmHasPrefix(d, rootPath)) { + d.erase(0, rootPath.size()); + } else if (stagePath && *stagePath && cmHasPrefix(d, stagePath)) { + d.erase(0, strlen(stagePath)); + d = cmStrCat(installPrefix, '/', d); cmSystemTools::ConvertToUnixSlashes(d); } else if (use_relative_build_rpath) { // If expansion of the $ORIGIN token is supported and permitted per @@ -1827,11 +1828,11 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, !cmSystemTools::IsSubDirectory(ri, topSourceDir) && !cmSystemTools::IsSubDirectory(ri, topBinaryDir)) { std::string d = ri; - if (!rootPath.empty() && d.find(rootPath) == 0) { - d = d.substr(rootPath.size()); - } else if (stagePath && *stagePath && d.find(stagePath) == 0) { - std::string suffix = d.substr(strlen(stagePath)); - d = cmStrCat(installPrefix, '/', suffix); + if (!rootPath.empty() && cmHasPrefix(d, rootPath)) { + d.erase(0, rootPath.size()); + } else if (stagePath && *stagePath && cmHasPrefix(d, stagePath)) { + d.erase(0, strlen(stagePath)); + d = cmStrCat(installPrefix, '/', d); cmSystemTools::ConvertToUnixSlashes(d); } if (emitted.insert(d).second) { diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index a98a608..41f5346 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -198,6 +198,20 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) std::vector<std::string> const& configs = depender->Makefile->GetGeneratorConfigs(); for (std::string const& it : configs) { + cmLinkImplementation const* impl = depender->GetLinkImplementation(it); + + // A target should not depend on itself. + emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace())); + emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace())); + for (cmLinkImplItem const& lib : impl->Libraries) { + // Don't emit the same library twice for this target. + if (emitted.insert(lib).second) { + this->AddTargetDepend(depender_index, lib, true, false); + this->AddInterfaceDepends(depender_index, lib, it, emitted); + } + } + + // Add dependencies on object libraries not otherwise handled above. std::vector<cmSourceFile const*> objectFiles; depender->GetExternalObjects(objectFiles, it); for (cmSourceFile const* o : objectFiles) { @@ -222,19 +236,6 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) } } } - - cmLinkImplementation const* impl = depender->GetLinkImplementation(it); - - // A target should not depend on itself. - emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace())); - emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace())); - for (cmLinkImplItem const& lib : impl->Libraries) { - // Don't emit the same library twice for this target. - if (emitted.insert(lib).second) { - this->AddTargetDepend(depender_index, lib, true, false); - this->AddInterfaceDepends(depender_index, lib, it, emitted); - } - } } } diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index fda687f..bf11022 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -494,12 +494,12 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, if (this->IsKeyword(keyDEFINED, *arg) && argP1 != newArgs.end()) { size_t argP1len = argP1->GetValue().size(); bool bdef = false; - if (argP1len > 4 && argP1->GetValue().substr(0, 4) == "ENV{" && + if (argP1len > 4 && cmHasLiteralPrefix(argP1->GetValue(), "ENV{") && argP1->GetValue().operator[](argP1len - 1) == '}') { std::string env = argP1->GetValue().substr(4, argP1len - 5); bdef = cmSystemTools::HasEnv(env); } else if (argP1len > 6 && - argP1->GetValue().substr(0, 6) == "CACHE{" && + cmHasLiteralPrefix(argP1->GetValue(), "CACHE{") && argP1->GetValue().operator[](argP1len - 1) == '}') { std::string cache = argP1->GetValue().substr(6, argP1len - 7); bdef = diff --git a/Source/cmConvertMSBuildXMLToJSON.py b/Source/cmConvertMSBuildXMLToJSON.py index 02074ba..2be3781 100644 --- a/Source/cmConvertMSBuildXMLToJSON.py +++ b/Source/cmConvertMSBuildXMLToJSON.py @@ -35,12 +35,14 @@ def vsflags(*args): return values -def read_msbuild_xml(path, values={}): +def read_msbuild_xml(path, values=None): """Reads the MS Build XML file at the path and returns its contents. Keyword arguments: values -- The map to append the contents to (default {}) """ + if values is None: + values = {} # Attempt to read the file contents try: @@ -76,12 +78,15 @@ def read_msbuild_xml(path, values={}): return values -def read_msbuild_json(path, values=[]): +def read_msbuild_json(path, values=None): """Reads the MS Build JSON file at the path and returns its contents. Keyword arguments: values -- The list to append the contents to (default []) """ + if values is None: + values = [] + if not os.path.exists(path): logging.info('Could not find MS Build JSON file at %s', path) return values diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index da04396..9c26f61 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -101,29 +101,23 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, this->SrcFileSignature = true; cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE; - const char* tt = - this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE"); - if (!isTryRun && tt && *tt) { - if (strcmp(tt, cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) == - 0) { + const std::string* tt = + this->Makefile->GetDef("CMAKE_TRY_COMPILE_TARGET_TYPE"); + if (!isTryRun && tt && !tt->empty()) { + if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) { targetType = cmStateEnums::EXECUTABLE; - } else if (strcmp(tt, - cmState::GetTargetTypeName( - cmStateEnums::STATIC_LIBRARY)) == 0) { + } else if (*tt == + cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY)) { targetType = cmStateEnums::STATIC_LIBRARY; } else { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, - std::string("Invalid value '") + tt + - "' for " - "CMAKE_TRY_COMPILE_TARGET_TYPE. Only " - "'" + - cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE) + - "' and " - "'" + - cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY) + - "' " - "are allowed."); + cmStrCat("Invalid value '", *tt, + "' for CMAKE_TRY_COMPILE_TARGET_TYPE. Only '", + cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE), + "' and '", + cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY), + "' are allowed.")); return -1; } } @@ -296,12 +290,10 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, default: this->Makefile->IssueMessage( MessageType::FATAL_ERROR, - "Only libraries may be used as try_compile or try_run IMPORTED " - "LINK_LIBRARIES. Got " + - std::string(tgt->GetName()) + - " of " - "type " + - cmState::GetTargetTypeName(tgt->GetType()) + "."); + cmStrCat("Only libraries may be used as try_compile or try_run " + "IMPORTED LINK_LIBRARIES. Got ", + tgt->GetName(), " of type ", + cmState::GetTargetTypeName(tgt->GetType()), ".")); return -1; } if (tgt->IsImported()) { diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx index f4e4fda..4e2d9b0 100644 --- a/Source/cmDefinePropertyCommand.cxx +++ b/Source/cmDefinePropertyCommand.cxx @@ -95,7 +95,7 @@ bool cmDefinePropertyCommand(std::vector<std::string> const& args, // Actually define the property. status.GetMakefile().GetState()->DefineProperty( - PropertyName, scope, BriefDocs.c_str(), FullDocs.c_str(), inherited); + PropertyName, scope, BriefDocs, FullDocs, inherited); return true; } diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 129a5f7..d4e8da6 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDepends.h" -#include <sstream> #include <utility> #include "cmsys/FStream.hxx" @@ -81,16 +80,14 @@ void cmDepends::Clear(const std::string& file) { // Print verbose output. if (this->Verbose) { - std::ostringstream msg; - msg << "Clearing dependencies in \"" << file << "\"." << std::endl; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout( + cmStrCat("Clearing dependencies in \"", file, "\".\n")); } // Write an empty dependency file. cmGeneratedFileStream depFileStream(file); depFileStream << "# Empty dependencies file\n" - << "# This may be replaced when dependencies are built." - << std::endl; + "# This may be replaced when dependencies are built.\n"; } bool cmDepends::WriteDependencies(const std::set<std::string>& /*unused*/, @@ -172,10 +169,9 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends, // Print verbose output. if (this->Verbose) { - std::ostringstream msg; - msg << "Dependee \"" << dependee << "\" does not exist for depender \"" - << depender << "\"." << std::endl; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout(cmStrCat("Dependee \"", dependee, + "\" does not exist for depender \"", + depender, "\".\n")); } } else if (dependerExists) { // The dependee and depender both exist. Compare file times. @@ -185,10 +181,9 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends, // Print verbose output. if (this->Verbose) { - std::ostringstream msg; - msg << "Dependee \"" << dependee << "\" is newer than depender \"" - << depender << "\"." << std::endl; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout(cmStrCat("Dependee \"", dependee, + "\" is newer than depender \"", + depender, "\".\n")); } } } else { @@ -200,11 +195,9 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends, // Print verbose output. if (this->Verbose) { - std::ostringstream msg; - msg << "Dependee \"" << dependee - << "\" is newer than depends file \"" << internalDependsFileName - << "\"." << std::endl; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout(cmStrCat("Dependee \"", dependee, + "\" is newer than depends file \"", + internalDependsFileName, "\".\n")); } } } diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index e30d959..01bb6ed 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -212,17 +212,17 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, // convert the dependencies to paths relative to the home output // directory. We must do the same here. std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i); - internalDepends << obj_i << std::endl; + internalDepends << obj_i << '\n'; for (std::string const& dep : dependencies) { makeDepends << obj_m << ": " << cmSystemTools::ConvertToOutputPath( this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep)) - << std::endl; - internalDepends << " " << dep << std::endl; + << '\n'; + internalDepends << ' ' << dep << '\n'; } - makeDepends << std::endl; + makeDepends << '\n'; return true; } @@ -264,19 +264,19 @@ void cmDependsC::ReadCacheFile() // file doesn't exist, check that the regular expressions // haven't changed else if (!res) { - if (line.find(INCLUDE_REGEX_LINE_MARKER) == 0) { + if (cmHasLiteralPrefix(line, INCLUDE_REGEX_LINE_MARKER)) { if (line != this->IncludeRegexLineString) { return; } - } else if (line.find(INCLUDE_REGEX_SCAN_MARKER) == 0) { + } else if (cmHasLiteralPrefix(line, INCLUDE_REGEX_SCAN_MARKER)) { if (line != this->IncludeRegexScanString) { return; } - } else if (line.find(INCLUDE_REGEX_COMPLAIN_MARKER) == 0) { + } else if (cmHasLiteralPrefix(line, INCLUDE_REGEX_COMPLAIN_MARKER)) { if (line != this->IncludeRegexComplainString) { return; } - } else if (line.find(INCLUDE_REGEX_TRANSFORM_MARKER) == 0) { + } else if (cmHasLiteralPrefix(line, INCLUDE_REGEX_TRANSFORM_MARKER)) { if (line != this->IncludeRegexTransformString) { return; } @@ -312,17 +312,17 @@ void cmDependsC::WriteCacheFile() const for (auto const& fileIt : this->FileCache) { if (fileIt.second.Used) { - cacheOut << fileIt.first << std::endl; + cacheOut << fileIt.first << '\n'; for (UnscannedEntry const& inc : fileIt.second.UnscannedEntries) { - cacheOut << inc.FileName << std::endl; + cacheOut << inc.FileName << '\n'; if (inc.QuotedLocation.empty()) { - cacheOut << "-" << std::endl; + cacheOut << '-' << '\n'; } else { - cacheOut << inc.QuotedLocation << std::endl; + cacheOut << inc.QuotedLocation << '\n'; } } - cacheOut << std::endl; + cacheOut << '\n'; } } } diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 3692202..666306c 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -102,10 +102,7 @@ cmDependsFortran::cmDependsFortran(cmLocalGenerator* lg) this->SModExt = mf->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT"); } -cmDependsFortran::~cmDependsFortran() -{ - delete this->Internal; -} +cmDependsFortran::~cmDependsFortran() = default; bool cmDependsFortran::WriteDependencies(const std::set<std::string>& sources, const std::string& obj, @@ -188,7 +185,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, fiStream << "provides\n"; std::set<std::string> const& provides = this->Internal->TargetProvides; for (std::string const& i : provides) { - fiStream << " " << i << "\n"; + fiStream << ' ' << i << '\n'; } // Create a script to clean the modules. @@ -205,14 +202,14 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, std::string mod_lower = cmStrCat(mod_dir, '/'); cmFortranModuleAppendUpperLower(i, mod_upper, mod_lower); std::string stamp = cmStrCat(stamp_dir, '/', i, ".stamp"); - fcStream << "\n"; - fcStream << " \"" + fcStream << "\n" + " \"" << this->MaybeConvertToRelativePath(currentBinDir, mod_lower) - << "\"\n"; - fcStream << " \"" + << "\"\n" + " \"" << this->MaybeConvertToRelativePath(currentBinDir, mod_upper) - << "\"\n"; - fcStream << " \"" + << "\"\n" + " \"" << this->MaybeConvertToRelativePath(currentBinDir, stamp) << "\"\n"; } @@ -329,16 +326,15 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, std::string binDir = this->LocalGenerator->GetBinaryDirectory(); std::string obj_i = this->MaybeConvertToRelativePath(binDir, obj); std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i); - internalDepends << obj_i << std::endl; - internalDepends << " " << src << std::endl; + internalDepends << obj_i << "\n " << src << '\n'; for (std::string const& i : info.Includes) { makeDepends << obj_m << ": " << cmSystemTools::ConvertToOutputPath( this->MaybeConvertToRelativePath(binDir, i)) - << std::endl; - internalDepends << " " << i << std::endl; + << '\n'; + internalDepends << ' ' << i << '\n'; } - makeDepends << std::endl; + makeDepends << '\n'; // Write module requirements to the output stream. for (std::string const& i : info.Requires) { @@ -357,7 +353,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, // This module is known. Depend on its timestamp file. std::string stampFile = cmSystemTools::ConvertToOutputPath( this->MaybeConvertToRelativePath(binDir, required->second)); - makeDepends << obj_m << ": " << stampFile << "\n"; + makeDepends << obj_m << ": " << stampFile << '\n'; } else { // This module is not known to CMake. Try to locate it where // the compiler will and depend on that. @@ -365,7 +361,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, if (this->FindModule(i, module)) { module = cmSystemTools::ConvertToOutputPath( this->MaybeConvertToRelativePath(binDir, module)); - makeDepends << obj_m << ": " << module << "\n"; + makeDepends << obj_m << ": " << module << '\n'; } } } @@ -394,7 +390,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, cmSystemTools::ConvertToOutputPath(stampFile); makeDepends << obj_m << ".provides.build" - << ": " << stampFileForMake << "\n"; + << ": " << stampFileForMake << '\n'; // Note that when cmake_copy_f90_mod finds that a module file // and the corresponding stamp file have no differences, the stamp // file is not updated. In such case the stamp file will be always @@ -402,15 +398,15 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, // on each new build. This is expected behavior for incremental // builds and can not be changed without preforming recursive make // calls that would considerably slow down the building process. - makeDepends << stampFileForMake << ": " << obj_m << "\n"; + makeDepends << stampFileForMake << ": " << obj_m << '\n'; makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << modFile - << " " << stampFileForShell; + << ' ' << stampFileForShell; cmMakefile* mf = this->LocalGenerator->GetMakefile(); const char* cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID"); if (cid && *cid) { - makeDepends << " " << cid; + makeDepends << ' ' << cid; } - makeDepends << "\n"; + makeDepends << '\n'; } makeDepends << obj_m << ".provides.build:\n"; // After copying the modules update the timestamp file. diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index 0485115..e3e0d05 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <set> #include <string> #include <vector> @@ -84,7 +85,7 @@ protected: std::set<std::string> PPDefinitions; // Internal implementation details. - cmDependsFortranInternals* Internal = nullptr; + std::unique_ptr<cmDependsFortranInternals> Internal; private: std::string MaybeConvertToRelativePath(std::string const& base, diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx index 516bbbf..fc1bbdd 100644 --- a/Source/cmDependsJavaParserHelper.cxx +++ b/Source/cmDependsJavaParserHelper.cxx @@ -8,6 +8,7 @@ #include <iostream> #include <utility> +#include <cm/memory> #include <cm/string_view> #include "cmsys/FStream.hxx" @@ -169,10 +170,11 @@ void cmDependsJavaParserHelper::AllocateParserType( return; } this->UnionsAvailable++; - pt->str = new char[len + 1]; + auto up = cm::make_unique<char[]>(len + 1); + pt->str = up.get(); strncpy(pt->str, str, len); pt->str[len] = 0; - this->Allocates.push_back(pt->str); + this->Allocates.push_back(std::move(up)); } void cmDependsJavaParserHelper::StartClass(const char* cls) @@ -275,10 +277,7 @@ int cmDependsJavaParserHelper::ParseString(const char* str, int verb) void cmDependsJavaParserHelper::CleanupParser() { - for (char* allocate : this->Allocates) { - delete[] allocate; - } - this->Allocates.erase(this->Allocates.begin(), this->Allocates.end()); + this->Allocates.clear(); } int cmDependsJavaParserHelper::LexInput(char* buf, int maxlen) diff --git a/Source/cmDependsJavaParserHelper.h b/Source/cmDependsJavaParserHelper.h index a673b5b..c545ee2 100644 --- a/Source/cmDependsJavaParserHelper.h +++ b/Source/cmDependsJavaParserHelper.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <string> #include <vector> @@ -81,7 +82,7 @@ private: int CurrentDepth; int Verbose; - std::vector<char*> Allocates; + std::vector<std::unique_ptr<char[]>> Allocates; void PrintClasses(); diff --git a/Source/cmDynamicLoader.cxx b/Source/cmDynamicLoader.cxx index 0b72a94..a3731c1 100644 --- a/Source/cmDynamicLoader.cxx +++ b/Source/cmDynamicLoader.cxx @@ -6,6 +6,7 @@ #include <string> #include <utility> +namespace { class cmDynamicLoaderCache { public: @@ -15,14 +16,15 @@ public: cmsys::DynamicLoader::LibraryHandle& /*p*/); bool FlushCache(const char* path); void FlushCache(); - static cmDynamicLoaderCache* GetInstance(); + static cmDynamicLoaderCache& GetInstance(); private: std::map<std::string, cmsys::DynamicLoader::LibraryHandle> CacheMap; - static cmDynamicLoaderCache* Instance; + static cmDynamicLoaderCache Instance; }; -cmDynamicLoaderCache* cmDynamicLoaderCache::Instance = nullptr; +cmDynamicLoaderCache cmDynamicLoaderCache::Instance; +} cmDynamicLoaderCache::~cmDynamicLoaderCache() = default; @@ -64,15 +66,11 @@ void cmDynamicLoaderCache::FlushCache() for (auto const& it : this->CacheMap) { cmsys::DynamicLoader::CloseLibrary(it.second); } - delete cmDynamicLoaderCache::Instance; - cmDynamicLoaderCache::Instance = nullptr; + this->CacheMap.clear(); } -cmDynamicLoaderCache* cmDynamicLoaderCache::GetInstance() +cmDynamicLoaderCache& cmDynamicLoaderCache::GetInstance() { - if (!cmDynamicLoaderCache::Instance) { - cmDynamicLoaderCache::Instance = new cmDynamicLoaderCache; - } return cmDynamicLoaderCache::Instance; } @@ -80,15 +78,15 @@ cmsys::DynamicLoader::LibraryHandle cmDynamicLoader::OpenLibrary( const char* libname) { cmsys::DynamicLoader::LibraryHandle lh; - if (cmDynamicLoaderCache::GetInstance()->GetCacheFile(libname, lh)) { + if (cmDynamicLoaderCache::GetInstance().GetCacheFile(libname, lh)) { return lh; } lh = cmsys::DynamicLoader::OpenLibrary(libname); - cmDynamicLoaderCache::GetInstance()->CacheFile(libname, lh); + cmDynamicLoaderCache::GetInstance().CacheFile(libname, lh); return lh; } void cmDynamicLoader::FlushCache() { - cmDynamicLoaderCache::GetInstance()->FlushCache(); + cmDynamicLoaderCache::GetInstance().FlushCache(); } diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 5be5bce..08a0f7e 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -61,6 +61,8 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, bool ErrorQuiet = false; bool OutputStripTrailingWhitespace = false; bool ErrorStripTrailingWhitespace = false; + bool EchoOutputVariable = false; + bool EchoErrorVariable = false; std::string Encoding; }; @@ -83,7 +85,9 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, &Arguments::OutputStripTrailingWhitespace) .Bind("ERROR_STRIP_TRAILING_WHITESPACE"_s, &Arguments::ErrorStripTrailingWhitespace) - .Bind("ENCODING"_s, &Arguments::Encoding); + .Bind("ENCODING"_s, &Arguments::Encoding) + .Bind("ECHO_OUTPUT_VARIABLE"_s, &Arguments::EchoOutputVariable) + .Bind("ECHO_ERROR_VARIABLE"_s, &Arguments::EchoErrorVariable); std::vector<std::string> unparsedArguments; std::vector<std::string> keywordsMissingValue; @@ -241,28 +245,32 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) { // Put the output in the right place. if (p == cmsysProcess_Pipe_STDOUT && !arguments.OutputQuiet) { - if (arguments.OutputVariable.empty()) { + if (arguments.OutputVariable.empty() || arguments.EchoOutputVariable) { processOutput.DecodeText(data, length, strdata, 1); cmSystemTools::Stdout(strdata); - } else { + } + if (!arguments.OutputVariable.empty()) { cmExecuteProcessCommandAppend(tempOutput, data, length); } } else if (p == cmsysProcess_Pipe_STDERR && !arguments.ErrorQuiet) { - if (arguments.ErrorVariable.empty()) { + if (arguments.ErrorVariable.empty() || arguments.EchoErrorVariable) { processOutput.DecodeText(data, length, strdata, 2); cmSystemTools::Stderr(strdata); - } else { + } + if (!arguments.ErrorVariable.empty()) { cmExecuteProcessCommandAppend(tempError, data, length); } } } - if (!arguments.OutputQuiet && arguments.OutputVariable.empty()) { + if (!arguments.OutputQuiet && + (arguments.OutputVariable.empty() || arguments.EchoOutputVariable)) { processOutput.DecodeText(std::string(), strdata, 1); if (!strdata.empty()) { cmSystemTools::Stdout(strdata); } } - if (!arguments.ErrorQuiet && arguments.ErrorVariable.empty()) { + if (!arguments.ErrorQuiet && + (arguments.ErrorVariable.empty() || arguments.EchoErrorVariable)) { processOutput.DecodeText(std::string(), strdata, 2); if (!strdata.empty()) { cmSystemTools::Stderr(strdata); diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index 561e830..a2b4d60 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -118,13 +118,13 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( } else { bool relpath = false; if (type == cmExportBuildAndroidMKGenerator::INSTALL) { - relpath = lib.substr(0, 3) == "../"; + relpath = cmHasLiteralPrefix(lib, "../"); } // check for full path or if it already has a -l, or // in the case of an install check for relative paths // if it is full or a link library then use string directly if (cmSystemTools::FileIsFullPath(lib) || - lib.substr(0, 2) == "-l" || relpath) { + cmHasLiteralPrefix(lib, "-l") || relpath) { ldlibs += " " + lib; // if it is not a path and does not have a -l then add -l } else if (!lib.empty()) { diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index e49c174..f31759d 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -24,6 +24,7 @@ #include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -183,6 +184,28 @@ bool cmExportCommand(std::vector<std::string> const& args, return false; } + // if cmExportBuildFileGenerator is already defined for the file + // and APPEND is not specified, if CMP0103 is OLD ignore previous definition + // else raise an error + if (gg->GetExportedTargetsFile(fname) != nullptr) { + switch (mf.GetPolicyStatus(cmPolicies::CMP0103)) { + case cmPolicies::WARN: + mf.IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0103), '\n', + "export() command already specified for the file\n ", + arguments.Filename, "\nDid you miss 'APPEND' keyword?")); + CM_FALLTHROUGH; + case cmPolicies::OLD: + break; + default: + status.SetError(cmStrCat("command already specified for the file\n ", + arguments.Filename, + "\nDid you miss 'APPEND' keyword?")); + return false; + } + } + // Setup export file generation. std::unique_ptr<cmExportBuildFileGenerator> ebfg = nullptr; if (android) { diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 6441e6f..ea31417 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -276,8 +276,7 @@ static bool checkInterfaceDirs(const std::string& prepro, << "\"\nhowever it is also " "a subdirectory of the " << (inBinary ? "build" : "source") << " tree:\n \"" - << (inBinary ? topBinaryDir : topSourceDir) << "\"" - << std::endl; + << (inBinary ? topBinaryDir : topSourceDir) << "\"\n"; target->GetLocalGenerator()->IssueMessage( MessageType::AUTHOR_WARNING, s.str()); CM_FALLTHROUGH; @@ -1116,7 +1115,7 @@ void cmExportFileGenerator::GenerateMissingTargetsCheckCode( return; } /* clang-format off */ - os << "# Make sure the targets which have been exported in some other \n" + os << "# Make sure the targets which have been exported in some other\n" "# export set exist.\n" "unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n" "foreach(_target "; @@ -1215,9 +1214,9 @@ bool cmExportFileGenerator::PopulateExportProperties( std::string& errorMessage) { auto& targetProperties = gte->Target->GetProperties(); - if (const char* exportProperties = + if (cmProp exportProperties = targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) { - for (auto& prop : cmExpandedList(exportProperties)) { + for (auto& prop : cmExpandedList(*exportProperties)) { /* Black list reserved properties */ if (cmHasLiteralPrefix(prop, "IMPORTED_") || cmHasLiteralPrefix(prop, "INTERFACE_")) { @@ -1228,15 +1227,15 @@ bool cmExportFileGenerator::PopulateExportProperties( errorMessage = e.str(); return false; } - auto propertyValue = targetProperties.GetPropertyValue(prop); + cmProp propertyValue = targetProperties.GetPropertyValue(prop); if (propertyValue == nullptr) { // Asked to export a property that isn't defined on the target. Do not // consider this an error, there's just nothing to export. continue; } std::string evaluatedValue = cmGeneratorExpression::Preprocess( - propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions); - if (evaluatedValue != propertyValue) { + *propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions); + if (evaluatedValue != *propertyValue) { std::ostringstream e; e << "Target \"" << gte->Target->GetName() << "\" contains property \"" << prop << "\" in EXPORT_PROPERTIES but this property contains a " @@ -1244,7 +1243,7 @@ bool cmExportFileGenerator::PopulateExportProperties( errorMessage = e.str(); return false; } - properties[prop] = propertyValue; + properties[prop] = *propertyValue; } } return true; diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx index 9702e0e..80f776e 100644 --- a/Source/cmExportInstallAndroidMKGenerator.cxx +++ b/Source/cmExportInstallAndroidMKGenerator.cxx @@ -66,7 +66,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode( os << "LOCAL_MODULE := "; os << targetName << "\n"; os << "LOCAL_SRC_FILES := $(_IMPORT_PREFIX)/"; - os << target->Target->GetProperty("__dest") << "/"; + os << target->Target->GetSafeProperty("__dest") << "/"; std::string config; if (!this->Configurations.empty()) { config = this->Configurations[0]; diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index 6011ba4..be63278 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -23,6 +23,8 @@ class cmListFileBacktrace; +using cmProp = const std::string*; + static void FinalAction(cmMakefile& makefile, std::string const& filename, bool append) { @@ -95,8 +97,8 @@ static void FinalAction(cmMakefile& makefile, std::string const& filename, // Handle simple output name changes. This command is // deprecated so we do not support full target name // translation (which requires per-configuration info). - if (const char* outname = libtgt->GetProperty("OUTPUT_NAME")) { - lib = outname; + if (cmProp outname = libtgt->GetProperty("OUTPUT_NAME")) { + lib = *outname; } } valueOld += lib; diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 3df6a5c..807ebed 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -97,9 +97,9 @@ void cmExportTryCompileFileGenerator::PopulateProperties( properties[p] = target->GetProperty(p); - if (p.find("IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 || - p.find("IMPORTED_LINK_DEPENDENT_LIBRARIES") == 0 || - p.find("INTERFACE_LINK_LIBRARIES") == 0) { + if (cmHasLiteralPrefix(p, "IMPORTED_LINK_INTERFACE_LIBRARIES") || + cmHasLiteralPrefix(p, "IMPORTED_LINK_DEPENDENT_LIBRARIES") || + cmHasLiteralPrefix(p, "INTERFACE_LINK_LIBRARIES")) { std::string evalResult = this->FindTargets(p, target, std::string(), emitted); diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index b710467..42fd0ea 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -218,7 +218,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // Convert for (std::string const& listFile : listFiles) { // don't put cmake's own files into the project (#12110): - if (listFile.find(cmSystemTools::GetCMakeRoot()) == 0) { + if (cmHasPrefix(listFile, cmSystemTools::GetCMakeRoot())) { continue; } @@ -301,11 +301,11 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( case cmStateEnums::UTILITY: // Add all utility targets, except the Nightly/Continuous/ // Experimental-"sub"targets as e.g. NightlyStart - if (((targetName.find("Nightly") == 0) && + if ((cmHasLiteralPrefix(targetName, "Nightly") && (targetName != "Nightly")) || - ((targetName.find("Continuous") == 0) && + (cmHasLiteralPrefix(targetName, "Continuous") && (targetName != "Continuous")) || - ((targetName.find("Experimental") == 0) && + (cmHasLiteralPrefix(targetName, "Experimental") && (targetName != "Experimental"))) { break; } diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 78cabce..1c5bcaa 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -187,10 +187,10 @@ void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile() return; } - fout << "eclipse.preferences.version=1" << std::endl; + fout << "eclipse.preferences.version=1\n"; const char* encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING"); if (encoding) { - fout << "encoding/<project>=" << encoding << std::endl; + fout << "encoding/<project>=" << encoding << '\n'; } } @@ -255,8 +255,8 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, // The variable is in the env, but not in the cache. Use it and put it // in the cache valueToUse = envVarValue; - mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), - cacheEntryName.c_str(), cmStateEnums::STRING, true); + mf->AddCacheDefinition(cacheEntryName, valueToUse, cacheEntryName.c_str(), + cmStateEnums::STRING, true); mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); } else if (!envVarSet && cacheValue != nullptr) { // It is already in the cache, but not in the env, so use it from the cache @@ -270,7 +270,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, valueToUse = *cacheValue; if (valueToUse.find(envVarValue) == std::string::npos) { valueToUse = envVarValue; - mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), + mf->AddCacheDefinition(cacheEntryName, valueToUse, cacheEntryName.c_str(), cmStateEnums::STRING, true); mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); @@ -415,9 +415,9 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() xml.Element("nature", n); } - if (const char* extraNaturesProp = + if (cmProp extraNaturesProp = mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_NATURES")) { - std::vector<std::string> extraNatures = cmExpandedList(extraNaturesProp); + std::vector<std::string> extraNatures = cmExpandedList(*extraNaturesProp); for (std::string const& n : extraNatures) { xml.Element("nature", n); } @@ -754,11 +754,11 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const emmited.clear(); for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { - if (const char* cdefs = + if (cmProp cdefs = lgen->GetMakefile()->GetProperty("COMPILE_DEFINITIONS")) { // Expand the list. std::vector<std::string> defs; - cmGeneratorExpression::Split(cdefs, defs); + cmGeneratorExpression::Split(*cdefs, defs); for (std::string const& d : defs) { if (cmGeneratorExpression::Find(d) != std::string::npos) { @@ -936,11 +936,11 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const case cmStateEnums::UTILITY: // Add all utility targets, except the Nightly/Continuous/ // Experimental-"sub"targets as e.g. NightlyStart - if (((targetName.find("Nightly") == 0) && + if ((cmHasLiteralPrefix(targetName, "Nightly") && (targetName != "Nightly")) || - ((targetName.find("Continuous") == 0) && + (cmHasLiteralPrefix(targetName, "Continuous") && (targetName != "Continuous")) || - ((targetName.find("Experimental") == 0) && + (cmHasLiteralPrefix(targetName, "Experimental") && (targetName != "Experimental"))) { break; } @@ -1033,9 +1033,9 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const xml.EndElement(); // storageModule // Append additional cproject contents without applying any XML formatting - if (const char* extraCProjectContents = + if (cmProp extraCProjectContents = mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_CPROJECT_CONTENTS")) { - fout << extraCProjectContents; + fout << *extraCProjectContents; } xml.EndElement(); // cproject diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index 3a22846..271bbee 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -144,11 +144,11 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator& lg, case cmStateEnums::UTILITY: // Add all utility targets, except the Nightly/Continuous/ // Experimental-"sub"targets as e.g. NightlyStart - if (((targetName.find("Nightly") == 0) && + if ((cmHasLiteralPrefix(targetName, "Nightly") && (targetName != "Nightly")) || - ((targetName.find("Continuous") == 0) && + (cmHasLiteralPrefix(targetName, "Continuous") && (targetName != "Continuous")) || - ((targetName.find("Experimental") == 0) && + (cmHasLiteralPrefix(targetName, "Experimental") && (targetName != "Experimental"))) { break; } diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 413449c..5b136e2 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -199,11 +199,11 @@ void cmExtraSublimeTextGenerator::AppendAllTargets( case cmStateEnums::UTILITY: // Add all utility targets, except the Nightly/Continuous/ // Experimental-"sub"targets as e.g. NightlyStart - if (((targetName.find("Nightly") == 0) && + if ((cmHasLiteralPrefix(targetName, "Nightly") && (targetName != "Nightly")) || - ((targetName.find("Continuous") == 0) && + (cmHasLiteralPrefix(targetName, "Continuous") && (targetName != "Continuous")) || - ((targetName.find("Experimental") == 0) && + (cmHasLiteralPrefix(targetName, "Experimental") && (targetName != "Experimental"))) { break; } diff --git a/Source/cmFileAPICache.cxx b/Source/cmFileAPICache.cxx index ef77795..5d2ddf9 100644 --- a/Source/cmFileAPICache.cxx +++ b/Source/cmFileAPICache.cxx @@ -67,7 +67,7 @@ Json::Value Cache::DumpEntry(std::string const& name) entry["name"] = name; entry["type"] = cmState::CacheEntryTypeToString(this->State->GetCacheEntryType(name)); - entry["value"] = this->State->GetCacheEntryValue(name); + entry["value"] = this->State->GetSafeCacheEntryValue(name); Json::Value properties = this->DumpEntryProperties(name); if (!properties.empty()) { @@ -94,7 +94,8 @@ Json::Value Cache::DumpEntryProperty(std::string const& name, { Json::Value property = Json::objectValue; property["name"] = prop; - property["value"] = this->State->GetCacheEntryProperty(name, prop); + cmProp p = this->State->GetCacheEntryProperty(name, prop); + property["value"] = p ? *p : ""; return property; } } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 79110ab..4603b13 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -8,6 +8,7 @@ #include <cmath> #include <cstdio> #include <cstdlib> +#include <iterator> #include <map> #include <set> #include <sstream> @@ -33,12 +34,14 @@ #include "cmFileInstaller.h" #include "cmFileLockPool.h" #include "cmFileTimes.h" +#include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmHexFileConverter.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmNewLineStyle.h" #include "cmPolicies.h" #include "cmRange.h" #include "cmRuntimeDependencyArchive.h" @@ -47,6 +50,7 @@ #include "cmSubcommandTable.h" #include "cmSystemTools.h" #include "cmTimestamp.h" +#include "cmWorkingDirectory.h" #include "cmake.h" #if !defined(CMAKE_BOOTSTRAP) @@ -2323,12 +2327,9 @@ bool HandleLockCommand(std::vector<std::string> const& args, path += "/cmake.lock"; } - if (!cmsys::SystemTools::FileIsFullPath(path)) { - path = status.GetMakefile().GetCurrentSourceDirectory() + "/" + path; - } - // Unify path (remove '//', '/../', ...) - path = cmSystemTools::CollapseFullPath(path); + path = cmSystemTools::CollapseFullPath( + path, status.GetMakefile().GetCurrentSourceDirectory()); // Create file and directories if needed std::string parentDir = cmSystemTools::GetParentDirectory(path); @@ -2776,6 +2777,325 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, return true; } +bool HandleConfigureCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() < 5) { + status.SetError("Incorrect arguments to CONFIGURE subcommand."); + return false; + } + if (args[1] != "OUTPUT") { + status.SetError("Incorrect arguments to CONFIGURE subcommand."); + return false; + } + if (args[3] != "CONTENT") { + status.SetError("Incorrect arguments to CONFIGURE subcommand."); + return false; + } + + std::string errorMessage; + cmNewLineStyle newLineStyle; + if (!newLineStyle.ReadFromArguments(args, errorMessage)) { + status.SetError(cmStrCat("CONFIGURE ", errorMessage)); + return false; + } + + bool escapeQuotes = false; + bool atOnly = false; + for (unsigned int i = 5; i < args.size(); ++i) { + if (args[i] == "@ONLY") { + atOnly = true; + } else if (args[i] == "ESCAPE_QUOTES") { + escapeQuotes = true; + } else if (args[i] == "NEWLINE_STYLE" || args[i] == "LF" || + args[i] == "UNIX" || args[i] == "CRLF" || args[i] == "WIN32" || + args[i] == "DOS") { + /* Options handled by NewLineStyle member above. */ + } else { + status.SetError( + cmStrCat("CONFIGURE Unrecognized argument \"", args[i], "\"")); + return false; + } + } + + // Check for generator expressions + const std::string input = args[4]; + std::string outputFile = args[2]; + + std::string::size_type pos = input.find_first_of("<>"); + if (pos != std::string::npos) { + status.SetError(cmStrCat("CONFIGURE called with CONTENT containing a \"", + input[pos], + "\". This character is not allowed.")); + return false; + } + + pos = outputFile.find_first_of("<>"); + if (pos != std::string::npos) { + status.SetError(cmStrCat("CONFIGURE called with OUTPUT containing a \"", + outputFile[pos], + "\". This character is not allowed.")); + return false; + } + + cmMakefile& makeFile = status.GetMakefile(); + if (!makeFile.CanIWriteThisFile(outputFile)) { + cmSystemTools::Error("Attempt to write file: " + outputFile + + " into a source directory."); + return false; + } + + cmSystemTools::ConvertToUnixSlashes(outputFile); + + // Re-generate if non-temporary outputs are missing. + // when we finalize the configuration we will remove all + // output files that now don't exist. + makeFile.AddCMakeOutputFile(outputFile); + + // Create output directory + const std::string::size_type slashPos = outputFile.rfind('/'); + if (slashPos != std::string::npos) { + const std::string path = outputFile.substr(0, slashPos); + cmSystemTools::MakeDirectory(path); + } + + std::string newLineCharacters; + bool open_with_binary_flag = false; + if (newLineStyle.IsValid()) { + open_with_binary_flag = true; + newLineCharacters = newLineStyle.GetCharacters(); + } + + cmGeneratedFileStream fout; + fout.Open(outputFile, false, open_with_binary_flag); + if (!fout) { + cmSystemTools::Error("Could not open file for write in copy operation " + + outputFile); + cmSystemTools::ReportLastSystemError(""); + return false; + } + fout.SetCopyIfDifferent(true); + + // copy intput to output and expand variables from input at the same time + std::stringstream sin(input, std::ios::in); + std::string inLine; + std::string outLine; + while (cmSystemTools::GetLineFromStream(sin, inLine)) { + outLine.clear(); + makeFile.ConfigureString(inLine, outLine, atOnly, escapeQuotes); + fout << outLine << newLineCharacters; + } + + // close file before attempting to copy + fout.close(); + + return true; +} + +bool HandleArchiveCreateCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + struct Arguments + { + std::string Output; + std::string Format; + std::string Type; + std::string MTime; + bool Verbose = false; + std::vector<std::string> Files; + std::vector<std::string> Directories; + }; + + static auto const parser = cmArgumentParser<Arguments>{} + .Bind("OUTPUT"_s, &Arguments::Output) + .Bind("FORMAT"_s, &Arguments::Format) + .Bind("TYPE"_s, &Arguments::Type) + .Bind("MTIME"_s, &Arguments::MTime) + .Bind("VERBOSE"_s, &Arguments::Verbose) + .Bind("FILES"_s, &Arguments::Files) + .Bind("DIRECTORY"_s, &Arguments::Directories); + + std::vector<std::string> unrecognizedArguments; + std::vector<std::string> keywordsMissingValues; + auto parsedArgs = + parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments, + &keywordsMissingValues); + auto argIt = unrecognizedArguments.begin(); + if (argIt != unrecognizedArguments.end()) { + status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + const std::vector<std::string> LIST_ARGS = { + "OUTPUT", "FORMAT", "TYPE", "MTIME", "FILES", "DIRECTORY", + }; + auto kwbegin = keywordsMissingValues.cbegin(); + auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS); + if (kwend != kwbegin) { + status.SetError(cmStrCat("Keywords missing values:\n ", + cmJoin(cmMakeRange(kwbegin, kwend), "\n "))); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + const char* knownFormats[] = { + "7zip", "gnutar", "pax", "paxr", "raw", "zip" + }; + + if (!parsedArgs.Format.empty() && + !cmContains(knownFormats, parsedArgs.Format)) { + status.SetError( + cmStrCat("archive format ", parsedArgs.Format, " not supported")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + const char* zipFileFormats[] = { "7zip", "zip" }; + if (!parsedArgs.Type.empty() && + cmContains(zipFileFormats, parsedArgs.Format)) { + status.SetError(cmStrCat("archive format ", parsedArgs.Format, + " does not support TYPE arguments")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + static std::map<std::string, cmSystemTools::cmTarCompression> + compressionTypeMap = { { "None", cmSystemTools::TarCompressNone }, + { "BZip2", cmSystemTools::TarCompressBZip2 }, + { "GZip", cmSystemTools::TarCompressGZip }, + { "XZ", cmSystemTools::TarCompressXZ }, + { "Zstd", cmSystemTools::TarCompressZstd } }; + + std::string const& outFile = parsedArgs.Output; + std::vector<std::string> files = parsedArgs.Files; + std::copy(parsedArgs.Directories.begin(), parsedArgs.Directories.end(), + std::back_inserter(files)); + + cmSystemTools::cmTarCompression compress = cmSystemTools::TarCompressNone; + auto typeIt = compressionTypeMap.find(parsedArgs.Type); + if (typeIt != compressionTypeMap.end()) { + compress = typeIt->second; + } else if (!parsedArgs.Type.empty()) { + status.SetError( + cmStrCat("compression type ", parsedArgs.Type, " is not supported")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (files.empty()) { + status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, + "No files or directories specified"); + } + + if (!cmSystemTools::CreateTar(outFile, files, compress, parsedArgs.Verbose, + parsedArgs.MTime, parsedArgs.Format)) { + status.SetError(cmStrCat("failed to compress: ", outFile)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + return true; +} + +bool HandleArchiveExtractCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + struct Arguments + { + std::string Input; + bool Verbose = false; + bool ListOnly = false; + std::string Destination; + std::vector<std::string> Files; + std::vector<std::string> Directories; + }; + + static auto const parser = cmArgumentParser<Arguments>{} + .Bind("INPUT"_s, &Arguments::Input) + .Bind("VERBOSE"_s, &Arguments::Verbose) + .Bind("LIST_ONLY"_s, &Arguments::ListOnly) + .Bind("DESTINATION"_s, &Arguments::Destination) + .Bind("FILES"_s, &Arguments::Files) + .Bind("DIRECTORY"_s, &Arguments::Directories); + + std::vector<std::string> unrecognizedArguments; + std::vector<std::string> keywordsMissingValues; + auto parsedArgs = + parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments, + &keywordsMissingValues); + auto argIt = unrecognizedArguments.begin(); + if (argIt != unrecognizedArguments.end()) { + status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + const std::vector<std::string> LIST_ARGS = { + "INPUT", + "DESTINATION", + "FILES", + "DIRECTORY", + }; + auto kwbegin = keywordsMissingValues.cbegin(); + auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS); + if (kwend != kwbegin) { + status.SetError(cmStrCat("Keywords missing values:\n ", + cmJoin(cmMakeRange(kwbegin, kwend), "\n "))); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + std::string inFile = parsedArgs.Input; + std::vector<std::string> files = parsedArgs.Files; + std::copy(parsedArgs.Directories.begin(), parsedArgs.Directories.end(), + std::back_inserter(files)); + + if (parsedArgs.ListOnly) { + if (!cmSystemTools::ListTar(inFile, files, parsedArgs.Verbose)) { + status.SetError(cmStrCat("failed to list: ", inFile)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + } else { + std::string destDir = cmSystemTools::GetCurrentWorkingDirectory(); + if (!parsedArgs.Destination.empty()) { + if (cmSystemTools::FileIsFullPath(parsedArgs.Destination)) { + destDir = parsedArgs.Destination; + } else { + destDir = cmStrCat(destDir, "/", parsedArgs.Destination); + } + + if (!cmSystemTools::MakeDirectory(destDir)) { + status.SetError(cmStrCat("failed to create directory: ", destDir)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (!cmSystemTools::FileIsFullPath(inFile)) { + inFile = + cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), "/", inFile); + } + } + + cmWorkingDirectory workdir(destDir); + if (workdir.Failed()) { + status.SetError( + cmStrCat("failed to change working directory to: ", destDir)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (!cmSystemTools::ExtractTar(inFile, files, parsedArgs.Verbose)) { + status.SetError(cmStrCat("failed to extract: ", inFile)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + } + + return true; +} + } // namespace bool cmFileCommand(std::vector<std::string> const& args, @@ -2829,6 +3149,9 @@ bool cmFileCommand(std::vector<std::string> const& args, { "READ_SYMLINK"_s, HandleReadSymlinkCommand }, { "CREATE_LINK"_s, HandleCreateLinkCommand }, { "GET_RUNTIME_DEPENDENCIES"_s, HandleGetRuntimeDependenciesCommand }, + { "CONFIGURE"_s, HandleConfigureCommand }, + { "ARCHIVE_CREATE"_s, HandleArchiveCreateCommand }, + { "ARCHIVE_EXTRACT"_s, HandleArchiveExtractCommand }, }; return subcommand(args[0], args, status); diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index bec99bb..b5553b8 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -22,10 +22,6 @@ class cmExecutionStatus; cmFindBase::cmFindBase(cmExecutionStatus& status) : cmFindCommon(status) { - this->AlreadyInCache = false; - this->AlreadyInCacheWithoutMetaInfo = false; - this->NamesPerDir = false; - this->NamesPerDirAllowed = false; } bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) @@ -115,6 +111,10 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) } else if (args[j] == "NO_SYSTEM_PATH") { doing = DoingNone; this->NoDefaultPath = true; + } else if (args[j] == "REQUIRED") { + doing = DoingNone; + this->Required = true; + newStyle = true; } else if (this->CheckCommonArgument(args[j])) { doing = DoingNone; } else { @@ -296,7 +296,7 @@ bool cmFindBase::CheckForVariableInCache() if (const char* cacheValue = this->Makefile->GetDefinition(this->VariableName)) { cmState* state = this->Makefile->GetState(); - const char* cacheEntry = state->GetCacheEntryValue(this->VariableName); + cmProp cacheEntry = state->GetCacheEntryValue(this->VariableName); bool found = !cmIsNOTFOUND(cacheValue); bool cached = cacheEntry != nullptr; if (found) { @@ -312,9 +312,9 @@ bool cmFindBase::CheckForVariableInCache() return true; } if (cached) { - const char* hs = + cmProp hs = state->GetCacheEntryProperty(this->VariableName, "HELPSTRING"); - this->VariableDocumentation = hs ? hs : "(none)"; + this->VariableDocumentation = hs ? *hs : "(none)"; } } return false; diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h index fce0b11..4cbf09e 100644 --- a/Source/cmFindBase.h +++ b/Source/cmFindBase.h @@ -44,14 +44,16 @@ protected: std::string VariableDocumentation; std::string VariableName; std::vector<std::string> Names; - bool NamesPerDir; - bool NamesPerDirAllowed; + bool NamesPerDir = false; + bool NamesPerDirAllowed = false; // CMAKE_*_PATH CMAKE_SYSTEM_*_PATH FRAMEWORK|LIBRARY|INCLUDE|PROGRAM std::string EnvironmentPath; // LIB,INCLUDE - bool AlreadyInCache; - bool AlreadyInCacheWithoutMetaInfo; + bool AlreadyInCache = false; + bool AlreadyInCacheWithoutMetaInfo = false; + + bool Required = false; private: // Add pieces of the search. diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index d5a4bde..31f1201 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -12,6 +12,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -75,15 +76,22 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn) std::string const library = this->FindLibrary(); if (!library.empty()) { // Save the value in the cache - this->Makefile->AddCacheDefinition(this->VariableName, library.c_str(), + this->Makefile->AddCacheDefinition(this->VariableName, library, this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); return true; } std::string notfound = this->VariableName + "-NOTFOUND"; - this->Makefile->AddCacheDefinition(this->VariableName, notfound.c_str(), + this->Makefile->AddCacheDefinition(this->VariableName, notfound, this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); + if (this->Required) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "Could not find " + this->VariableName + + " using the following names: " + cmJoin(this->Names, ", ")); + cmSystemTools::SetFatalErrorOccured(); + } return true; } diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 297c72b..e996327 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -1060,8 +1060,8 @@ bool cmFindPackageCommand::FindConfig() cmStrCat("The directory containing a CMake configuration file for ", this->Name, '.'); // We force the value since we do not get here if it was already set. - this->Makefile->AddCacheDefinition(this->Variable, init.c_str(), - help.c_str(), cmStateEnums::PATH, true); + this->Makefile->AddCacheDefinition(this->Variable, init, help.c_str(), + cmStateEnums::PATH, true); return found; } @@ -1114,12 +1114,10 @@ bool cmFindPackageCommand::ReadListFile(const std::string& f, void cmFindPackageCommand::AppendToFoundProperty(bool found) { std::vector<std::string> foundContents; - const char* foundProp = + cmProp foundProp = this->Makefile->GetState()->GetGlobalProperty("PACKAGES_FOUND"); - if (foundProp && *foundProp) { - std::string tmp = foundProp; - - cmExpandList(tmp, foundContents, false); + if (foundProp && !foundProp->empty()) { + cmExpandList(*foundProp, foundContents, false); auto nameIt = std::find(foundContents.begin(), foundContents.end(), this->Name); if (nameIt != foundContents.end()) { @@ -1128,12 +1126,10 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found) } std::vector<std::string> notFoundContents; - const char* notFoundProp = + cmProp notFoundProp = this->Makefile->GetState()->GetGlobalProperty("PACKAGES_NOT_FOUND"); - if (notFoundProp && *notFoundProp) { - std::string tmp = notFoundProp; - - cmExpandList(tmp, notFoundContents, false); + if (notFoundProp && !notFoundProp->empty()) { + cmExpandList(*notFoundProp, notFoundContents, false); auto nameIt = std::find(notFoundContents.begin(), notFoundContents.end(), this->Name); if (nameIt != notFoundContents.end()) { diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index 908f0c1..4bab469 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -5,6 +5,7 @@ #include "cmsys/Glob.hxx" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -43,14 +44,21 @@ bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn) std::string result = this->FindHeader(); if (!result.empty()) { this->Makefile->AddCacheDefinition( - this->VariableName, result.c_str(), this->VariableDocumentation.c_str(), + this->VariableName, result, this->VariableDocumentation.c_str(), (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH); return true; } this->Makefile->AddCacheDefinition( - this->VariableName, (this->VariableName + "-NOTFOUND").c_str(), + this->VariableName, this->VariableName + "-NOTFOUND", this->VariableDocumentation.c_str(), (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH); + if (this->Required) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "Could not find " + this->VariableName + + " using the following files: " + cmJoin(this->Names, ", ")); + cmSystemTools::SetFatalErrorOccured(); + } return true; } diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 3e49172..4b88bea 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -3,6 +3,7 @@ #include "cmFindProgramCommand.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -127,15 +128,22 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn) std::string const result = FindProgram(); if (!result.empty()) { // Save the value in the cache - this->Makefile->AddCacheDefinition(this->VariableName, result.c_str(), + this->Makefile->AddCacheDefinition(this->VariableName, result, this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); return true; } this->Makefile->AddCacheDefinition( - this->VariableName, (this->VariableName + "-NOTFOUND").c_str(), + this->VariableName, this->VariableName + "-NOTFOUND", this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); + if (this->Required) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "Could not find " + this->VariableName + + " using the following names: " + cmJoin(this->Names, ", ")); + cmSystemTools::SetFatalErrorOccured(); + } return true; } diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 2af04b6..f76e205 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -180,6 +180,7 @@ int cmGeneratedFileStreamBase::CompressFile(std::string const& oldname, } FILE* ifs = cmsys::SystemTools::Fopen(oldname, "r"); if (!ifs) { + gzclose(gf); return 0; } size_t res; diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 81d1e46..6e293d5 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -32,12 +32,6 @@ std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse( new cmCompiledGeneratorExpression(this->Backtrace, std::move(input))); } -std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse( - const char* input) const -{ - return this->Parse(std::string(input ? input : "")); -} - std::string cmGeneratorExpression::Evaluate( std::string input, cmLocalGenerator* lg, const std::string& config, cmGeneratorTarget const* headTarget, @@ -52,17 +46,6 @@ std::string cmGeneratorExpression::Evaluate( return input; } -std::string cmGeneratorExpression::Evaluate( - const char* input, cmLocalGenerator* lg, const std::string& config, - cmGeneratorTarget const* headTarget, - cmGeneratorExpressionDAGChecker* dagChecker, - cmGeneratorTarget const* currentTarget, std::string const& language) -{ - return input ? Evaluate(std::string(input), lg, config, headTarget, - dagChecker, currentTarget, language) - : ""; -} - const std::string& cmCompiledGeneratorExpression::Evaluate( cmLocalGenerator* lg, const std::string& config, const cmGeneratorTarget* headTarget, @@ -103,6 +86,8 @@ const std::string& cmCompiledGeneratorExpression::EvaluateWithContext( if (!context.HadError) { this->HadContextSensitiveCondition = context.HadContextSensitiveCondition; this->HadHeadSensitiveCondition = context.HadHeadSensitiveCondition; + this->HadLinkLanguageSensitiveCondition = + context.HadLinkLanguageSensitiveCondition; this->SourceSensitiveTargets = context.SourceSensitiveTargets; } @@ -119,6 +104,7 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( , Quiet(false) , HadContextSensitiveCondition(false) , HadHeadSensitiveCondition(false) + , HadLinkLanguageSensitiveCondition(false) { cmGeneratorExpressionLexer l; std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(this->Input); diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index c4be3a1..75bba02 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -42,8 +42,6 @@ public: std::unique_ptr<cmCompiledGeneratorExpression> Parse( std::string input) const; - std::unique_ptr<cmCompiledGeneratorExpression> Parse( - const char* input) const; static std::string Evaluate( std::string input, cmLocalGenerator* lg, const std::string& config, @@ -51,12 +49,6 @@ public: cmGeneratorExpressionDAGChecker* dagChecker = nullptr, cmGeneratorTarget const* currentTarget = nullptr, std::string const& language = std::string()); - static std::string Evaluate( - const char* input, cmLocalGenerator* lg, const std::string& config, - cmGeneratorTarget const* headTarget = nullptr, - cmGeneratorExpressionDAGChecker* dagChecker = nullptr, - cmGeneratorTarget const* currentTarget = nullptr, - std::string const& language = std::string()); enum PreprocessContext { @@ -137,6 +129,10 @@ public: { return this->HadHeadSensitiveCondition; } + bool GetHadLinkLanguageSensitiveCondition() const + { + return this->HadLinkLanguageSensitiveCondition; + } std::set<cmGeneratorTarget const*> GetSourceSensitiveTargets() const { return this->SourceSensitiveTargets; @@ -178,6 +174,7 @@ private: mutable std::string Output; mutable bool HadContextSensitiveCondition; mutable bool HadHeadSensitiveCondition; + mutable bool HadLinkLanguageSensitiveCondition; mutable std::set<cmGeneratorTarget const*> SourceSensitiveTargets; }; diff --git a/Source/cmGeneratorExpressionContext.cxx b/Source/cmGeneratorExpressionContext.cxx index 6d97331..42cbe2a 100644 --- a/Source/cmGeneratorExpressionContext.cxx +++ b/Source/cmGeneratorExpressionContext.cxx @@ -19,6 +19,7 @@ cmGeneratorExpressionContext::cmGeneratorExpressionContext( , HadError(false) , HadContextSensitiveCondition(false) , HadHeadSensitiveCondition(false) + , HadLinkLanguageSensitiveCondition(false) , EvaluateForBuildsystem(evaluateForBuildsystem) { } diff --git a/Source/cmGeneratorExpressionContext.h b/Source/cmGeneratorExpressionContext.h index 4709fa0..bceff12 100644 --- a/Source/cmGeneratorExpressionContext.h +++ b/Source/cmGeneratorExpressionContext.h @@ -40,6 +40,7 @@ struct cmGeneratorExpressionContext bool HadError; bool HadContextSensitiveCondition; bool HadHeadSensitiveCondition; + bool HadLinkLanguageSensitiveCondition; bool EvaluateForBuildsystem; }; diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 643ba34..c860c75 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -6,6 +6,10 @@ #include <sstream> #include <utility> +#include <cm/string_view> + +#include "cm_static_string_view.hxx" + #include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorTarget.h" @@ -154,8 +158,8 @@ bool cmGeneratorExpressionDAGChecker::GetTransitivePropertiesOnly() bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression() { - return this->Property.find("TARGET_GENEX_EVAL:") == 0 || - this->Property.find("GENEX_EVAL:", 0) == 0; + return cmHasLiteralPrefix(this->Property, "TARGET_GENEX_EVAL:") || + cmHasLiteralPrefix(this->Property, "GENEX_EVAL:"); } bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression() @@ -170,6 +174,21 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression() return top->Property == "INTERFACE_POSITION_INDEPENDENT_CODE"; } +bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression() +{ + const cmGeneratorExpressionDAGChecker* top = this; + const cmGeneratorExpressionDAGChecker* parent = this->Parent; + while (parent) { + top = parent; + parent = parent->Parent; + } + + cm::string_view property(top->Property); + + return property == "LINK_DIRECTORIES"_s || property == "LINK_OPTIONS"_s || + property == "LINK_DEPENDS"_s; +} + bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries( cmGeneratorTarget const* tgt) { @@ -180,18 +199,17 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries( parent = parent->Parent; } - const char* prop = top->Property.c_str(); + cm::string_view prop(top->Property); if (tgt) { - return top->Target == tgt && strcmp(prop, "LINK_LIBRARIES") == 0; + return top->Target == tgt && prop == "LINK_LIBRARIES"_s; } - return (strcmp(prop, "LINK_LIBRARIES") == 0 || - strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0 || - strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 || - cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") || - cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_")) || - strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0; + return prop == "LINK_LIBRARIES"_s || prop == "LINK_INTERFACE_LIBRARIES"_s || + prop == "IMPORTED_LINK_INTERFACE_LIBRARIES"_s || + cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") || + cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_") || + prop == "INTERFACE_LINK_LIBRARIES"_s; } cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index f2c49bb..2a06596 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -68,6 +68,7 @@ struct cmGeneratorExpressionDAGChecker bool EvaluatingGenexExpression(); bool EvaluatingPICExpression(); + bool EvaluatingLinkExpression(); bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr); #define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 14478c2..dfc354d 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -62,6 +62,9 @@ std::string cmGeneratorExpressionNode::EvaluateDependentExpression( if (cge->GetHadHeadSensitiveCondition()) { context->HadHeadSensitiveCondition = true; } + if (cge->GetHadLinkLanguageSensitiveCondition()) { + context->HadLinkLanguageSensitiveCondition = true; + } return result; } @@ -904,11 +907,11 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode } if (context->CurrentTarget && context->CurrentTarget->IsImported()) { - const char* loc = nullptr; - const char* imp = nullptr; + cmProp loc = nullptr; + cmProp imp = nullptr; std::string suffix; - if (context->CurrentTarget->Target->GetMappedConfig( - context->Config, &loc, &imp, suffix)) { + if (context->CurrentTarget->Target->GetMappedConfig(context->Config, loc, + imp, suffix)) { // This imported target has an appropriate location // for this (possibly mapped) config. // Check if there is a proper config mapping for the tested config. @@ -1039,6 +1042,150 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode } } languageAndIdNode; +static const struct LinkLanguageNode : public cmGeneratorExpressionNode +{ + LinkLanguageNode() {} // NOLINT(modernize-use-equals-default) + + int NumExpectedParameters() const override { return ZeroOrMoreParameters; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!context->HeadTarget || !dagChecker || + !(dagChecker->EvaluatingLinkExpression() || + dagChecker->EvaluatingLinkLibraries())) { + reportError(context, content->GetOriginalExpression(), + "$<LINK_LANGUAGE:...> may only be used with binary targets " + "to specify link libraries, link directories, link options " + "and link depends."); + return std::string(); + } + if (dagChecker->EvaluatingLinkLibraries() && parameters.empty()) { + reportError( + context, content->GetOriginalExpression(), + "$<LINK_LANGUAGE> is not supported in link libraries expression."); + return std::string(); + } + + cmGlobalGenerator* gg = context->LG->GetGlobalGenerator(); + std::string genName = gg->GetName(); + if (genName.find("Makefiles") == std::string::npos && + genName.find("Ninja") == std::string::npos && + genName.find("Visual Studio") == std::string::npos && + genName.find("Xcode") == std::string::npos && + genName.find("Watcom WMake") == std::string::npos) { + reportError(context, content->GetOriginalExpression(), + "$<LINK_LANGUAGE:...> not supported for this generator."); + return std::string(); + } + + if (dagChecker->EvaluatingLinkLibraries()) { + context->HadHeadSensitiveCondition = true; + context->HadLinkLanguageSensitiveCondition = true; + } + + if (parameters.empty()) { + return context->Language; + } + + for (auto& param : parameters) { + if (context->Language == param) { + return "1"; + } + } + return "0"; + } +} linkLanguageNode; + +namespace { +struct LinkerId +{ + static std::string Evaluate(const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + const std::string& lang) + { + std::string const& linkerId = + context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang + + "_COMPILER_ID"); + if (parameters.empty()) { + return linkerId; + } + if (linkerId.empty()) { + return parameters.front().empty() ? "1" : "0"; + } + static cmsys::RegularExpression linkerIdValidator("^[A-Za-z0-9_]*$"); + + for (auto& param : parameters) { + if (!linkerIdValidator.find(param)) { + reportError(context, content->GetOriginalExpression(), + "Expression syntax not recognized."); + return std::string(); + } + + if (param == linkerId) { + return "1"; + } + } + return "0"; + } +}; +} + +static const struct LinkLanguageAndIdNode : public cmGeneratorExpressionNode +{ + LinkLanguageAndIdNode() {} // NOLINT(modernize-use-equals-default) + + int NumExpectedParameters() const override { return TwoOrMoreParameters; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!context->HeadTarget || !dagChecker || + !(dagChecker->EvaluatingLinkExpression() || + dagChecker->EvaluatingLinkLibraries())) { + reportError( + context, content->GetOriginalExpression(), + "$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets " + "to specify link libraries, link directories, link options, and link " + "depends."); + return std::string(); + } + + cmGlobalGenerator* gg = context->LG->GetGlobalGenerator(); + std::string genName = gg->GetName(); + if (genName.find("Makefiles") == std::string::npos && + genName.find("Ninja") == std::string::npos && + genName.find("Visual Studio") == std::string::npos && + genName.find("Xcode") == std::string::npos && + genName.find("Watcom WMake") == std::string::npos) { + reportError( + context, content->GetOriginalExpression(), + "$<LINK_LANG_AND_ID:lang,id> not supported for this generator."); + return std::string(); + } + + if (dagChecker->EvaluatingLinkLibraries()) { + context->HadHeadSensitiveCondition = true; + context->HadLinkLanguageSensitiveCondition = true; + } + + const std::string& lang = context->Language; + if (lang == parameters.front()) { + std::vector<std::string> idParameter((parameters.cbegin() + 1), + parameters.cend()); + return LinkerId::Evaluate(idParameter, context, content, lang); + } + return "0"; + } +} linkLanguageAndIdNode; + std::string getLinkedTargetsContent( cmGeneratorTarget const* target, std::string const& prop, cmGeneratorExpressionContext* context, @@ -1418,11 +1565,11 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode std::vector<std::string> objects; if (gt->IsImported()) { - const char* loc = nullptr; - const char* imp = nullptr; + cmProp loc = nullptr; + cmProp imp = nullptr; std::string suffix; - if (gt->Target->GetMappedConfig(context->Config, &loc, &imp, suffix)) { - cmExpandList(loc, objects); + if (gt->Target->GetMappedConfig(context->Config, loc, imp, suffix)) { + cmExpandList(*loc, objects); } context->HadContextSensitiveCondition = true; } else { @@ -2314,6 +2461,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "LINK_ONLY", &linkOnlyNode }, { "COMPILE_LANG_AND_ID", &languageAndIdNode }, { "COMPILE_LANGUAGE", &languageNode }, + { "LINK_LANG_AND_ID", &linkLanguageAndIdNode }, + { "LINK_LANGUAGE", &linkLanguageNode }, { "SHELL_PATH", &shellPathNode } }; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index ba2e314..e81b619 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -17,6 +17,7 @@ #include <cm/memory> #include <cm/string_view> +#include <cmext/algorithm> #include "cmsys/RegularExpression.hxx" @@ -51,11 +52,11 @@ class cmMessenger; template <> -const char* cmTargetPropertyComputer::GetSources<cmGeneratorTarget>( +cmProp cmTargetPropertyComputer::GetSources<cmGeneratorTarget>( cmGeneratorTarget const* tgt, cmMessenger* /* messenger */, cmListFileBacktrace const& /* context */) { - return tgt->GetSourcesProperty().c_str(); + return &tgt->GetSourcesProperty(); } template <> @@ -308,6 +309,13 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) this->SourceEntries, true); this->PolicyMap = t->GetPolicyMap(); + + // Get hard-coded linker language + if (this->Target->GetProperty("HAS_CXX")) { + this->LinkerLanguage = "CXX"; + } else { + this->LinkerLanguage = this->Target->GetSafeProperty("LINKER_LANGUAGE"); + } } cmGeneratorTarget::~cmGeneratorTarget() = default; @@ -368,14 +376,15 @@ const char* cmGeneratorTarget::GetProperty(const std::string& prop) const this->GetBacktrace())) { return nullptr; } - if (const char* result = cmTargetPropertyComputer::GetProperty( + if (cmProp result = cmTargetPropertyComputer::GetProperty( this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) { - return result; + return result->c_str(); } if (cmSystemTools::GetFatalErrorOccured()) { return nullptr; } - return this->Target->GetProperty(prop); + cmProp retval = this->Target->GetProperty(prop); + return retval ? retval->c_str() : nullptr; } const char* cmGeneratorTarget::GetSafeProperty(const std::string& prop) const @@ -531,15 +540,43 @@ std::string cmGeneratorTarget::GetFileSuffix( std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const { const char* postfix = nullptr; + std::string frameworkPostfix; if (!config.empty()) { std::string configProp = cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX"); postfix = this->GetProperty(configProp); - // Mac application bundles and frameworks have no postfix. + + // Mac application bundles and frameworks have no regular postfix like + // libraries do. if (!this->IsImported() && postfix && (this->IsAppBundleOnApple() || this->IsFrameworkOnApple())) { postfix = nullptr; } + + // Frameworks created by multi config generators can have a special + // framework postfix. + frameworkPostfix = GetFrameworkMultiConfigPostfix(config); + if (!frameworkPostfix.empty()) { + postfix = frameworkPostfix.c_str(); + } + } + return postfix ? postfix : std::string(); +} + +std::string cmGeneratorTarget::GetFrameworkMultiConfigPostfix( + const std::string& config) const +{ + const char* postfix = nullptr; + if (!config.empty()) { + std::string configProp = cmStrCat("FRAMEWORK_MULTI_CONFIG_POSTFIX_", + cmSystemTools::UpperCase(config)); + postfix = this->GetProperty(configProp); + + if (!this->IsImported() && postfix && + (this->IsFrameworkOnApple() && + !GetGlobalGenerator()->IsMultiConfig())) { + postfix = nullptr; + } } return postfix ? postfix : std::string(); } @@ -1246,6 +1283,86 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( } namespace { +std::string AddSwiftInterfaceIncludeDirectories( + const cmGeneratorTarget* root, const cmGeneratorTarget* target, + const std::string& config, cmGeneratorExpressionDAGChecker* context) +{ + cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, + "Swift_MODULE_DIRECTORY", nullptr, + context }; + switch (dag.Check()) { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: + dag.ReportError(nullptr, + "$<TARGET_PROPERTY:" + target->GetName() + + ",Swift_MODULE_DIRECTORY>"); + return ""; + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: + // No error. We just skip cyclic references. + return ""; + case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: + // No error. We have already seen this transitive property. + return ""; + case cmGeneratorExpressionDAGChecker::DAG: + break; + } + + std::string directories; + if (const auto* interface = + target->GetLinkInterfaceLibraries(config, root, true)) { + for (const cmLinkItem& library : interface->Libraries) { + if (const cmGeneratorTarget* dependency = library.Target) { + if (cmContains(dependency->GetAllConfigCompileLanguages(), "Swift")) { + std::string value = + dependency->GetSafeProperty("Swift_MODULE_DIRECTORY"); + if (value.empty()) { + value = + dependency->GetLocalGenerator()->GetCurrentBinaryDirectory(); + } + + if (!directories.empty()) { + directories += ";"; + } + directories += value; + } + } + } + } + return directories; +} + +void AddSwiftImplicitIncludeDirectories( + const cmGeneratorTarget* target, const std::string& config, + std::vector<EvaluatedTargetPropertyEntry>& entries) +{ + if (const auto* libraries = target->GetLinkImplementationLibraries(config)) { + cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, + "Swift_MODULE_DIRECTORY", nullptr, + nullptr }; + + for (const cmLinkImplItem& library : libraries->Libraries) { + if (const cmGeneratorTarget* dependency = library.Target) { + if (cmContains(dependency->GetAllConfigCompileLanguages(), "Swift")) { + EvaluatedTargetPropertyEntry entry{ library, library.Backtrace }; + + if (const char* val = + dependency->GetProperty("Swift_MODULE_DIRECTORY")) { + entry.Values.emplace_back(val); + } else { + entry.Values.emplace_back( + dependency->GetLocalGenerator()->GetCurrentBinaryDirectory()); + } + + cmExpandList(AddSwiftInterfaceIncludeDirectories(target, dependency, + config, &dag), + entry.Values); + + entries.emplace_back(std::move(entry)); + } + } + } + } +} + void AddInterfaceEntries(cmGeneratorTarget const* headTarget, std::string const& config, std::string const& prop, std::string const& lang, @@ -1907,7 +2024,7 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir( if (cmGeneratorTarget::ImportInfo const* info = this->GetImportInfo(config)) { if (!info->NoSOName && !info->SOName.empty()) { - if (info->SOName.find("@rpath/") == 0) { + if (cmHasLiteralPrefix(info->SOName, "@rpath/")) { install_name_is_rpath = true; } } else { @@ -2024,7 +2141,7 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const return cmSystemTools::GetFilenameName(info->Location); } // Use the soname given if any. - if (info->SOName.find("@rpath/") == 0) { + if (cmHasLiteralPrefix(info->SOName, "@rpath/")) { return info->SOName.substr(6); } return info->SOName; @@ -2223,11 +2340,12 @@ public: cmTargetCollectLinkLanguages(cmGeneratorTarget const* target, std::string config, std::unordered_set<std::string>& languages, - cmGeneratorTarget const* head) + cmGeneratorTarget const* head, bool secondPass) : Config(std::move(config)) , Languages(languages) , HeadTarget(head) , Target(target) + , SecondPass(secondPass) { this->Visited.insert(target); } @@ -2269,11 +2387,14 @@ public: if (!this->Visited.insert(item.Target).second) { return; } - cmLinkInterface const* iface = - item.Target->GetLinkInterface(this->Config, this->HeadTarget); + cmLinkInterface const* iface = item.Target->GetLinkInterface( + this->Config, this->HeadTarget, this->SecondPass); if (!iface) { return; } + if (iface->HadLinkLanguageSensitiveCondition) { + this->HadLinkLanguageSensitiveCondition = true; + } for (std::string const& language : iface->Languages) { this->Languages.insert(language); @@ -2284,12 +2405,19 @@ public: } } + bool GetHadLinkLanguageSensitiveCondition() + { + return HadLinkLanguageSensitiveCondition; + } + private: std::string Config; std::unordered_set<std::string>& Languages; cmGeneratorTarget const* HeadTarget; const cmGeneratorTarget* Target; std::set<cmGeneratorTarget const*> Visited; + bool SecondPass; + bool HadLinkLanguageSensitiveCondition = false; }; cmGeneratorTarget::LinkClosure const* cmGeneratorTarget::GetLinkClosure( @@ -2320,7 +2448,7 @@ public: { this->GG = this->Target->GetLocalGenerator()->GetGlobalGenerator(); } - void Consider(const char* lang) + void Consider(const std::string& lang) { int preference = this->GG->GetLinkerPreference(lang); if (preference > this->Preference) { @@ -2353,40 +2481,36 @@ public: } }; -void cmGeneratorTarget::ComputeLinkClosure(const std::string& config, - LinkClosure& lc) const +bool cmGeneratorTarget::ComputeLinkClosure(const std::string& config, + LinkClosure& lc, + bool secondPass) const { // Get languages built in this target. std::unordered_set<std::string> languages; - cmLinkImplementation const* impl = this->GetLinkImplementation(config); + cmLinkImplementation const* impl = + this->GetLinkImplementation(config, secondPass); assert(impl); - for (std::string const& li : impl->Languages) { - languages.insert(li); - } + languages.insert(impl->Languages.cbegin(), impl->Languages.cend()); // Add interface languages from linked targets. - cmTargetCollectLinkLanguages cll(this, config, languages, this); + // cmTargetCollectLinkLanguages cll(this, config, languages, this, + // secondPass); + cmTargetCollectLinkLanguages cll(this, config, languages, this, secondPass); for (cmLinkImplItem const& lib : impl->Libraries) { cll.Visit(lib); } // Store the transitive closure of languages. - for (std::string const& lang : languages) { - lc.Languages.push_back(lang); - } + cm::append(lc.Languages, languages); // Choose the language whose linker should be used. - if (this->GetProperty("HAS_CXX")) { - lc.LinkerLanguage = "CXX"; - } else if (const char* linkerLang = this->GetProperty("LINKER_LANGUAGE")) { - lc.LinkerLanguage = linkerLang; - } else { + if (secondPass || lc.LinkerLanguage.empty()) { // Find the language with the highest preference value. cmTargetSelectLinker tsl(this); // First select from the languages compiled directly in this target. for (std::string const& l : impl->Languages) { - tsl.Consider(l.c_str()); + tsl.Consider(l); } // Now consider languages that propagate from linked targets. @@ -2394,12 +2518,50 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config, std::string propagates = "CMAKE_" + lang + "_LINKER_PREFERENCE_PROPAGATES"; if (this->Makefile->IsOn(propagates)) { - tsl.Consider(lang.c_str()); + tsl.Consider(lang); } } lc.LinkerLanguage = tsl.Choose(); } + + return impl->HadLinkLanguageSensitiveCondition || + cll.GetHadLinkLanguageSensitiveCondition(); +} + +void cmGeneratorTarget::ComputeLinkClosure(const std::string& config, + LinkClosure& lc) const +{ + bool secondPass = false; + + { + LinkClosure linkClosure; + linkClosure.LinkerLanguage = this->LinkerLanguage; + + // Get languages built in this target. + secondPass = this->ComputeLinkClosure(config, linkClosure, false); + this->LinkerLanguage = linkClosure.LinkerLanguage; + if (!secondPass) { + lc = std::move(linkClosure); + } + } + + if (secondPass) { + LinkClosure linkClosure; + + this->ComputeLinkClosure(config, linkClosure, secondPass); + lc = std::move(linkClosure); + + // linker language must not be changed between the two passes + if (this->LinkerLanguage != lc.LinkerLanguage) { + std::ostringstream e; + e << "Evaluation of $<LINK_LANGUAGE:...> or $<LINK_LAND_AND_ID:...> " + "changes\nthe linker language for target \"" + << this->GetName() << "\" (from '" << this->LinkerLanguage << "' to '" + << lc.LinkerLanguage << "') which is invalid."; + cmSystemTools::Error(e.str()); + } + } } void cmGeneratorTarget::GetFullNameComponents( @@ -3096,6 +3258,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( EvaluateTargetPropertyEntries(this, config, lang, &dagChecker, this->IncludeDirectoriesEntries); + if (lang == "Swift") { + AddSwiftImplicitIncludeDirectories(this, config, entries); + } + AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang, &dagChecker, entries); @@ -3616,9 +3782,16 @@ std::string cmGeneratorTarget::GetPchCreateCompileOptions( if (inserted.second) { std::string& createOptionList = inserted.first->second; + if (this->GetPropertyAsBool("PCH_WARN_INVALID")) { + createOptionList = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_INVALID_PCH")); + } + const std::string createOptVar = cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_CREATE_PCH"); - createOptionList = this->Makefile->GetSafeDefinition(createOptVar); + + createOptionList = cmStrCat( + createOptionList, ";", this->Makefile->GetSafeDefinition(createOptVar)); const std::string pchHeader = this->GetPchHeader(config, language); const std::string pchFile = this->GetPchFile(config, language); @@ -3637,9 +3810,16 @@ std::string cmGeneratorTarget::GetPchUseCompileOptions( if (inserted.second) { std::string& useOptionList = inserted.first->second; + if (this->GetPropertyAsBool("PCH_WARN_INVALID")) { + useOptionList = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_INVALID_PCH")); + } + const std::string useOptVar = cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_USE_PCH"); - useOptionList = this->Makefile->GetSafeDefinition(useOptVar); + + useOptionList = cmStrCat(useOptionList, ";", + this->Makefile->GetSafeDefinition(useOptVar)); const std::string pchHeader = this->GetPchHeader(config, language); const std::string pchFile = this->GetPchFile(config, language); @@ -4188,8 +4368,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames( targetNames.Real += this->GetFrameworkVersion(); targetNames.Real += "/"; } - targetNames.Real += targetNames.Base; - targetNames.SharedObject = targetNames.Real; + targetNames.Real += targetNames.Base + suffix; + targetNames.SharedObject = targetNames.Real + suffix; } else { // The library's soname. this->ComputeVersionedName(targetNames.SharedObject, prefix, @@ -4364,7 +4544,15 @@ void cmGeneratorTarget::GetFullNameInternal( outBase += this->GetOutputName(config, artifact); // Append the per-configuration postfix. - outBase += configPostfix; + // When using Xcode, the postfix should be part of the suffix rather than the + // base, because the suffix ends up being used in Xcode's EXECUTABLE_SUFFIX + // attribute. + if (this->IsFrameworkOnApple() && + GetGlobalGenerator()->GetName() == "Xcode") { + targetSuffix = configPostfix.c_str(); + } else { + outBase += configPostfix; + } // Name shared libraries with their version number on some platforms. if (const char* soversion = this->GetProperty("SOVERSION")) { @@ -5492,7 +5680,8 @@ void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, void cmGeneratorTarget::ExpandLinkItems( std::string const& prop, std::string const& value, std::string const& config, cmGeneratorTarget const* headTarget, bool usage_requirements_only, - std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const + std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition, + bool& hadLinkLanguageSensitiveCondition) const { // Keep this logic in sync with ComputeLinkImplementationLibraries. cmGeneratorExpression ge; @@ -5504,19 +5693,28 @@ void cmGeneratorTarget::ExpandLinkItems( } std::vector<std::string> libs; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); - cmExpandList( - cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, this), - libs); + cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget, + &dagChecker, this, headTarget->LinkerLanguage), + libs); this->LookupLinkItems(libs, cge->GetBacktrace(), items); hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); + hadLinkLanguageSensitiveCondition = + cge->GetHadLinkLanguageSensitiveCondition(); } cmLinkInterface const* cmGeneratorTarget::GetLinkInterface( const std::string& config, cmGeneratorTarget const* head) const { + return this->GetLinkInterface(config, head, false); +} + +cmLinkInterface const* cmGeneratorTarget::GetLinkInterface( + const std::string& config, cmGeneratorTarget const* head, + bool secondPass) const +{ // Imported targets have their own link interface. if (this->IsImported()) { - return this->GetImportLinkInterface(config, head, false); + return this->GetImportLinkInterface(config, head, false, secondPass); } // Link interfaces are not supported for executables that do not @@ -5529,6 +5727,10 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface( // Lookup any existing link interface for this configuration. cmHeadToLinkInterfaceMap& hm = this->GetHeadToLinkInterfaceMap(config); + if (secondPass) { + hm.erase(head); + } + // If the link interface does not depend on the head target // then return the one we computed first. if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) { @@ -5543,7 +5745,7 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface( if (!iface.AllDone) { iface.AllDone = true; if (iface.Exists) { - this->ComputeLinkInterface(config, iface, head); + this->ComputeLinkInterface(config, iface, head, secondPass); } } @@ -5554,6 +5756,13 @@ void cmGeneratorTarget::ComputeLinkInterface( const std::string& config, cmOptionalLinkInterface& iface, cmGeneratorTarget const* headTarget) const { + this->ComputeLinkInterface(config, iface, headTarget, false); +} + +void cmGeneratorTarget::ComputeLinkInterface( + const std::string& config, cmOptionalLinkInterface& iface, + cmGeneratorTarget const* headTarget, bool secondPass) const +{ if (iface.Explicit) { if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->GetType() == cmStateEnums::STATIC_LIBRARY || @@ -5565,7 +5774,8 @@ void cmGeneratorTarget::ComputeLinkInterface( emitted.insert(lib); } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - cmLinkImplementation const* impl = this->GetLinkImplementation(config); + cmLinkImplementation const* impl = + this->GetLinkImplementation(config, secondPass); for (cmLinkImplItem const& lib : impl->Libraries) { if (emitted.insert(lib).second) { if (lib.Target) { @@ -5595,7 +5805,7 @@ void cmGeneratorTarget::ComputeLinkInterface( if (this->LinkLanguagePropagatesToDependents()) { // Targets using this archive need its language runtime libraries. if (cmLinkImplementation const* impl = - this->GetLinkImplementation(config)) { + this->GetLinkImplementation(config, secondPass)) { iface.Languages = impl->Languages; } } @@ -5991,7 +6201,8 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // The interface libraries have been explicitly set. this->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, headTarget, usage_requirements_only, iface.Libraries, - iface.HadHeadSensitiveCondition); + iface.HadHeadSensitiveCondition, + iface.HadLinkLanguageSensitiveCondition); } else if (!cmp0022NEW) // If CMP0022 is NEW then the plain tll signature sets the // INTERFACE_LINK_LIBRARIES, so if we get here then the project @@ -6011,9 +6222,11 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; if (const char* newExplicitLibraries = this->GetProperty(newProp)) { bool hadHeadSensitiveConditionDummy = false; + bool hadLinkLanguageSensitiveConditionDummy = false; this->ExpandLinkItems(newProp, newExplicitLibraries, config, headTarget, usage_requirements_only, ifaceLibs, - hadHeadSensitiveConditionDummy); + hadHeadSensitiveConditionDummy, + hadLinkLanguageSensitiveConditionDummy); } if (ifaceLibs != iface.Libraries) { std::string oldLibraries = cmJoin(impl->Libraries, ";"); @@ -6050,7 +6263,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( const std::string& config, cmGeneratorTarget const* headTarget, - bool usage_requirements_only) const + bool usage_requirements_only, bool secondPass) const { cmGeneratorTarget::ImportInfo const* info = this->GetImportInfo(config); if (!info) { @@ -6063,6 +6276,10 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( ? this->GetHeadToLinkInterfaceUsageRequirementsMap(config) : this->GetHeadToLinkInterfaceMap(config)); + if (secondPass) { + hm.erase(headTarget); + } + // If the link interface does not depend on the head target // then return the one we computed first. if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) { @@ -6076,7 +6293,8 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( cmExpandList(info->Languages, iface.Languages); this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, headTarget, usage_requirements_only, iface.Libraries, - iface.HadHeadSensitiveCondition); + iface.HadHeadSensitiveCondition, + iface.HadLinkLanguageSensitiveCondition); std::vector<std::string> deps = cmExpandedList(info->SharedDeps); this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps); } @@ -6132,10 +6350,10 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Initialize members. info.NoSOName = false; - const char* loc = nullptr; - const char* imp = nullptr; + cmProp loc = nullptr; + cmProp imp = nullptr; std::string suffix; - if (!this->Target->GetMappedConfig(desired_config, &loc, &imp, suffix)) { + if (!this->Target->GetMappedConfig(desired_config, loc, imp, suffix)) { return; } @@ -6162,7 +6380,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, } if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { if (loc) { - info.LibName = loc; + info.LibName = *loc; } return; } @@ -6172,7 +6390,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the location. if (loc) { - info.Location = loc; + info.Location = *loc; } else { std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix); if (const char* config_location = this->GetProperty(impProp)) { @@ -6205,7 +6423,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the import library. if (imp) { - info.ImportLibrary = imp; + info.ImportLibrary = *imp; } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->IsExecutableWithExports()) { std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); @@ -6281,6 +6499,12 @@ cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap( const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation( const std::string& config) const { + return this->GetLinkImplementation(config, false); +} + +const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation( + const std::string& config, bool secondPass) const +{ // There is no link implementation for imported targets. if (this->IsImported()) { return nullptr; @@ -6288,6 +6512,9 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation( std::string CONFIG = cmSystemTools::UpperCase(config); cmOptionalLinkImplementation& impl = this->LinkImplMap[CONFIG][this]; + if (secondPass) { + impl = cmOptionalLinkImplementation(); + } if (!impl.LibrariesDone) { impl.LibrariesDone = true; this->ComputeLinkImplementationLibraries(config, impl, this); @@ -6585,11 +6812,15 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cmGeneratorExpression ge(*btIt); std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le); std::string const& evaluated = - cge->Evaluate(this->LocalGenerator, config, head, &dagChecker); + cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr, + this->LinkerLanguage); cmExpandList(evaluated, llibs); if (cge->GetHadHeadSensitiveCondition()) { impl.HadHeadSensitiveCondition = true; } + if (cge->GetHadLinkLanguageSensitiveCondition()) { + impl.HadLinkLanguageSensitiveCondition = true; + } for (std::string const& lib : llibs) { if (this->IsLinkLookupScope(lib, lg)) { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index d81bb3d..12d30c5 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -357,7 +357,6 @@ public: }; LinkClosure const* GetLinkClosure(const std::string& config) const; - void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const; cmLinkImplementation const* GetLinkImplementation( const std::string& config) const; @@ -589,6 +588,9 @@ public: /** Get target file postfix */ std::string GetFilePostfix(const std::string& config) const; + /** Get framework multi-config-specific postfix */ + std::string GetFrameworkMultiConfigPostfix(const std::string& config) const; + /** Clears cached meta data for local and external source files. * The meta data will be recomputed on demand. */ @@ -816,6 +818,7 @@ private: std::string& outPrefix, std::string& outBase, std::string& outSuffix) const; + mutable std::string LinkerLanguage; using LinkClosureMapType = std::map<std::string, LinkClosure>; mutable LinkClosureMapType LinkClosureMap; @@ -850,6 +853,10 @@ private: void CheckPropertyCompatibility(cmComputeLinkInformation& info, const std::string& config) const; + void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const; + bool ComputeLinkClosure(const std::string& config, LinkClosure& lc, + bool secondPass) const; + struct LinkImplClosure : public std::vector<cmGeneratorTarget const*> { bool Done = false; @@ -868,6 +875,17 @@ private: std::string GetLinkInterfaceDependentStringAsBoolProperty( const std::string& p, const std::string& config) const; + friend class cmTargetCollectLinkLanguages; + cmLinkInterface const* GetLinkInterface(const std::string& config, + const cmGeneratorTarget* headTarget, + bool secondPass) const; + void ComputeLinkInterface(const std::string& config, + cmOptionalLinkInterface& iface, + const cmGeneratorTarget* head, + bool secondPass) const; + cmLinkImplementation const* GetLinkImplementation(const std::string& config, + bool secondPass) const; + // Cache import information from properties for each configuration. struct ImportInfo { @@ -894,9 +912,10 @@ private: the link dependencies of this target. */ std::string CheckCMP0004(std::string const& item) const; - cmLinkInterface const* GetImportLinkInterface( - const std::string& config, const cmGeneratorTarget* head, - bool usage_requirements_only) const; + cmLinkInterface const* GetImportLinkInterface(const std::string& config, + const cmGeneratorTarget* head, + bool usage_requirements_only, + bool secondPass = false) const; using KindedSourcesMapType = std::map<std::string, KindedSources>; mutable KindedSourcesMapType KindedSourcesMap; @@ -940,7 +959,8 @@ private: const cmGeneratorTarget* headTarget, bool usage_requirements_only, std::vector<cmLinkItem>& items, - bool& hadHeadSensitiveCondition) const; + bool& hadHeadSensitiveCondition, + bool& hadLinkLanguageSensitiveCondition) const; void LookupLinkItems(std::vector<std::string> const& names, cmListFileBacktrace const& bt, std::vector<cmLinkItem>& items) const; diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx index ff4e312..0480876 100644 --- a/Source/cmGetCMakePropertyCommand.cxx +++ b/Source/cmGetCMakePropertyCommand.cxx @@ -23,25 +23,25 @@ bool cmGetCMakePropertyCommand(std::vector<std::string> const& args, std::string output = "NOTFOUND"; if (args[1] == "VARIABLES") { - if (const char* varsProp = status.GetMakefile().GetProperty("VARIABLES")) { - output = varsProp; + if (cmProp varsProp = status.GetMakefile().GetProperty("VARIABLES")) { + output = *varsProp; } } else if (args[1] == "MACROS") { output.clear(); - if (const char* macrosProp = status.GetMakefile().GetProperty("MACROS")) { - output = macrosProp; + if (cmProp macrosProp = status.GetMakefile().GetProperty("MACROS")) { + output = *macrosProp; } } else if (args[1] == "COMPONENTS") { const std::set<std::string>* components = status.GetMakefile().GetGlobalGenerator()->GetInstallComponents(); output = cmJoin(*components, ";"); } else { - const char* prop = nullptr; + cmProp prop = nullptr; if (!args[1].empty()) { prop = status.GetMakefile().GetState()->GetGlobalProperty(args[1]); } if (prop) { - output = prop; + output = *prop; } } diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index 64438d5..2833977 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -7,7 +7,6 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" namespace { @@ -37,14 +36,8 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args, "DIRECTORY argument provided without subsequent arguments"); return false; } - std::string sd = *i; - // make sure the start dir is a full path - if (!cmSystemTools::FileIsFullPath(sd)) { - sd = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', *i); - } - - // The local generators are associated with collapsed paths. - sd = cmSystemTools::CollapseFullPath(sd); + std::string sd = cmSystemTools::CollapseFullPath( + *i, status.GetMakefile().GetCurrentSourceDirectory()); // lookup the makefile from the directory name dir = status.GetMakefile().GetGlobalGenerator()->FindMakefile(sd); @@ -92,7 +85,9 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args, break; } } - prop = dir->GetProperty(*i); + if (cmProp p = dir->GetProperty(*i)) { + prop = p->c_str(); + } } StoreResult(status.GetMakefile(), variable, prop); return true; diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index 7d91a75..811421a 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -120,11 +120,11 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args, if (args.size() >= 4 && args.back() == "CACHE") { if (!programArgs.empty() && !storeArgs.empty()) { status.GetMakefile().AddCacheDefinition( - storeArgs, programArgs.c_str(), "", + storeArgs, programArgs, "", args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING); } status.GetMakefile().AddCacheDefinition( - args.front(), result.c_str(), "", + args.front(), result, "", args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING); } else { if (!programArgs.empty() && !storeArgs.empty()) { diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 947d893..c3ac672 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -241,8 +241,9 @@ bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name, // Get the property. cmake* cm = status.GetMakefile().GetCMakeInstance(); + cmProp p = cm->GetState()->GetGlobalProperty(propertyName); return StoreResult(infoType, status.GetMakefile(), variable, - cm->GetState()->GetGlobalProperty(propertyName)); + p ? p->c_str() : nullptr); } bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name, @@ -256,14 +257,8 @@ bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name, if (!name.empty()) { // Construct the directory name. Interpret relative paths with // respect to the current directory. - std::string dir = name; - if (!cmSystemTools::FileIsFullPath(dir)) { - dir = - cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', name); - } - - // The local generators are associated with collapsed paths. - dir = cmSystemTools::CollapseFullPath(dir); + std::string dir = cmSystemTools::CollapseFullPath( + name, status.GetMakefile().GetCurrentSourceDirectory()); // Lookup the generator. mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir); @@ -294,8 +289,9 @@ bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name, } // Get the property. + cmProp p = mf->GetProperty(propertyName); return StoreResult(infoType, status.GetMakefile(), variable, - mf->GetProperty(propertyName)); + p ? p->c_str() : nullptr); } bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, @@ -315,7 +311,7 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, } return StoreResult(infoType, status.GetMakefile(), variable, nullptr); } - const char* prop_cstr = nullptr; + cmProp prop_cstr = nullptr; cmListFileBacktrace bt = status.GetMakefile().GetBacktrace(); cmMessenger* messenger = status.GetMakefile().GetMessenger(); if (cmTargetPropertyComputer::PassesWhitelist( @@ -325,7 +321,8 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, prop_cstr = target->GetProperty(propertyName); } } - return StoreResult(infoType, status.GetMakefile(), variable, prop_cstr); + return StoreResult(infoType, status.GetMakefile(), variable, + prop_cstr ? prop_cstr->c_str() : nullptr); } status.SetError(cmStrCat("could not find TARGET ", name, ". Perhaps it has not yet been created.")); @@ -393,12 +390,13 @@ bool HandleCacheMode(cmExecutionStatus& status, const std::string& name, return false; } - const char* value = nullptr; + cmProp value = nullptr; if (status.GetMakefile().GetState()->GetCacheEntryValue(name)) { value = status.GetMakefile().GetState()->GetCacheEntryProperty( name, propertyName); } - StoreResult(infoType, status.GetMakefile(), variable, value); + StoreResult(infoType, status.GetMakefile(), variable, + value ? value->c_str() : nullptr); return true; } diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index 7f5df9c..6b850d1 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -34,7 +34,7 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args, prop_exists = true; } } else if (!args[2].empty()) { - const char* prop_cstr = nullptr; + cmProp prop_cstr = nullptr; cmListFileBacktrace bt = mf.GetBacktrace(); cmMessenger* messenger = mf.GetMessenger(); if (cmTargetPropertyComputer::PassesWhitelist(tgt->GetType(), args[2], @@ -45,7 +45,7 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args, } } if (prop_cstr) { - prop = prop_cstr; + prop = *prop_cstr; prop_exists = true; } } diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 5e2248e..deb722f 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -165,13 +165,15 @@ void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout, outpath = this->GeneratorTarget->GetDirectory(config); outpath = this->LocalGenerator->MaybeConvertToRelativePath(rootpath, outpath); - fout << " :binDirRelative=\"" << outpath << "\"" << std::endl; - fout << " -o \"" << this->TargetNameReal << "\"" << std::endl; + /* clang-format off */ + fout << " :binDirRelative=\"" << outpath << "\"\n" + " -o \"" << this->TargetNameReal << "\"\n"; + /* clang-format on */ } // set target object file destination outpath = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - fout << " :outputDirRelative=\"" << outpath << "\"" << std::endl; + fout << " :outputDirRelative=\"" << outpath << "\"\n"; } void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, @@ -180,15 +182,12 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, auto i = this->FlagsByLanguage.find(language); if (i == this->FlagsByLanguage.end()) { std::string flags; - const char* lang = language.c_str(); - - this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, lang, - config); - - this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, lang, - config); + this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, + language, config); + this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, + language, config); this->LocalGenerator->AddVisibilityPresetFlags( - flags, this->GeneratorTarget, lang); + flags, this->GeneratorTarget, language); // Append old-style preprocessor definition flags. if (this->Makefile->GetDefineFlags() != " ") { @@ -197,8 +196,8 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, } // Add target-specific flags. - this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, lang, - config); + this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, + language, config); std::map<std::string, std::string>::value_type entry(language, flags); i = this->FlagsByLanguage.insert(entry).first; @@ -211,13 +210,12 @@ std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language, auto i = this->DefinesByLanguage.find(language); if (i == this->DefinesByLanguage.end()) { std::set<std::string> defines; - const char* lang = language.c_str(); // Add preprocessor definitions for this target and configuration. this->LocalGenerator->GetTargetDefines(this->GeneratorTarget, config, language, defines); std::string definesString; - this->LocalGenerator->JoinDefines(defines, definesString, lang); + this->LocalGenerator->JoinDefines(defines, definesString, language); std::map<std::string, std::string>::value_type entry(language, definesString); @@ -235,8 +233,8 @@ void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::ostream& fout, if (!flagsByLangI->second.empty()) { std::vector<std::string> ghsCompFlags = cmSystemTools::ParseArguments(flagsByLangI->second); - for (auto& f : ghsCompFlags) { - fout << " " << f << std::endl; + for (const std::string& f : ghsCompFlags) { + fout << " " << f << '\n'; } } } @@ -249,7 +247,7 @@ void cmGhsMultiTargetGenerator::WriteCompilerDefinitions( this->GeneratorTarget->GetCompileDefinitions(compileDefinitions, config, language); for (std::string const& compileDefinition : compileDefinitions) { - fout << " -D" << compileDefinition << std::endl; + fout << " -D" << compileDefinition << '\n'; } } @@ -262,7 +260,7 @@ void cmGhsMultiTargetGenerator::WriteIncludes(std::ostream& fout, language, config); for (std::string const& include : includes) { - fout << " -I\"" << include << "\"" << std::endl; + fout << " -I\"" << include << "\"\n"; } } @@ -290,15 +288,15 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, // write out link options std::vector<std::string> lopts = cmSystemTools::ParseArguments(linkFlags); - for (auto& l : lopts) { - fout << " " << l << std::endl; + for (const std::string& l : lopts) { + fout << " " << l << '\n'; } // write out link search paths // must be quoted for paths that contain spaces std::vector<std::string> lpath = cmSystemTools::ParseArguments(linkPath); - for (auto& l : lpath) { - fout << " -L\"" << l << "\"" << std::endl; + for (const std::string& l : lpath) { + fout << " -L\"" << l << "\"\n"; } // write out link libs @@ -307,12 +305,12 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, std::vector<std::string> llibs = cmSystemTools::ParseArguments(linkLibraries); - for (auto& l : llibs) { + for (const std::string& l : llibs) { if (l.compare(0, 2, "-l") == 0) { - fout << " \"" << l << "\"" << std::endl; + fout << " \"" << l << "\"\n"; } else { std::string rl = cmSystemTools::CollapseFullPath(l, cbd); - fout << " -l\"" << rl << "\"" << std::endl; + fout << " -l\"" << rl << "\"\n"; } } } @@ -353,13 +351,12 @@ void cmGhsMultiTargetGenerator::WriteBuildEventsHelper( this->WriteCustomCommandsHelper(f, ccg); f.Close(); if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) { - fout << " :" << cmd << "=\"" << fname << "\"" << std::endl; + fout << " :" << cmd << "=\"" << fname << "\"\n"; } else { - fout << fname << std::endl; - fout << " :outputName=\"" << fname << ".rule\"" << std::endl; + fout << fname << "\n :outputName=\"" << fname << ".rule\"\n"; } for (auto& byp : ccg.GetByproducts()) { - fout << " :extraOutputFile=\"" << byp << "\"" << std::endl; + fout << " :extraOutputFile=\"" << byp << "\"\n"; } } } @@ -451,8 +448,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( // push back the custom commands for (auto const& c : cmdLines) { - fout << c << std::endl; - fout << check_error << std::endl; + fout << c << '\n' << check_error << '\n'; } } @@ -463,8 +459,8 @@ void cmGhsMultiTargetGenerator::WriteSourceProperty( const char* prop = sf->GetProperty(propName); if (prop) { std::vector<std::string> list = cmExpandedList(prop); - for (auto& p : list) { - fout << " " << propFlag << p << std::endl; + for (const std::string& p : list) { + fout << " " << propFlag << p << '\n'; } } } @@ -483,7 +479,7 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) /* for each source file assign it to its group */ std::map<std::string, std::vector<cmSourceFile*>> groupFiles; std::set<std::string> groupNames; - for (auto& sf : sources) { + for (cmSourceFile* sf : sources) { cmSourceGroup* sourceGroup = this->Makefile->FindSourceGroup(sf->ResolveFullPath(), sourceGroups); std::string gn = sourceGroup->GetFullName(); @@ -579,12 +575,12 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) if (useProjectFile) { if (sg.empty()) { - *fout << "{comment} Others" << std::endl; + *fout << "{comment} Others" << '\n'; } else { - *fout << "{comment} " << sg << std::endl; + *fout << "{comment} " << sg << '\n'; } } else if (sg.empty()) { - *fout << "{comment} Others" << std::endl; + *fout << "{comment} Others\n"; } if (sg != "CMake Rules") { @@ -612,7 +608,7 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) compile = false; } - *fout << comment << fname << std::endl; + *fout << comment << fname << '\n'; if (compile) { if ("ld" != si->GetExtension() && "int" != si->GetExtension() && "bsp" != si->GetExtension()) { @@ -628,7 +624,7 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) std::string objectName = this->GeneratorTarget->GetObjectName(si); if (!objectName.empty() && this->GeneratorTarget->HasExplicitObjectName(si)) { - *fout << " -o " << objectName << std::endl; + *fout << " -o " << objectName << '\n'; } } } @@ -695,14 +691,14 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandLine( */ bool specifyExtra = true; for (auto& out : ccg.GetOutputs()) { - fout << fname << std::endl; - fout << " :outputName=\"" << out << "\"" << std::endl; + fout << fname << '\n'; + fout << " :outputName=\"" << out << "\"\n"; if (specifyExtra) { for (auto& byp : ccg.GetByproducts()) { - fout << " :extraOutputFile=\"" << byp << "\"" << std::endl; + fout << " :extraOutputFile=\"" << byp << "\"\n"; } for (auto& dep : ccg.GetDepends()) { - fout << " :depends=\"" << dep << "\"" << std::endl; + fout << " :depends=\"" << dep << "\"\n"; } specifyExtra = false; } @@ -717,7 +713,7 @@ void cmGhsMultiTargetGenerator::WriteObjectLangOverride( std::string sourceLangProp(rawLangProp); std::string const& extension = sourceFile->GetExtension(); if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) { - fout << " -dotciscxx" << std::endl; + fout << " -dotciscxx\n"; } } } @@ -730,7 +726,7 @@ bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp() } std::vector<cmSourceFile*> sources; this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName); - for (auto& sf : sources) { + for (const cmSourceFile* sf : sources) { if ("int" == sf->GetExtension()) { return true; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 6a2d4c7..ccbbf53 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -246,11 +246,10 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, cmSystemTools::ConvertToUnixSlashes(cnameString); cmSystemTools::ConvertToUnixSlashes(pathString); if (cnameString != pathString) { - const char* cvars = - this->GetCMakeInstance()->GetState()->GetGlobalProperty( - "__CMAKE_DELETE_CACHE_CHANGE_VARS_"); + cmProp cvars = this->GetCMakeInstance()->GetState()->GetGlobalProperty( + "__CMAKE_DELETE_CACHE_CHANGE_VARS_"); if (cvars) { - changeVars += cvars; + changeVars += *cvars; changeVars += ";"; } changeVars += langComp; @@ -445,8 +444,8 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) cmSystemTools::GetShortPath(makeProgram, makeProgram); cmSystemTools::SplitProgramPath(makeProgram, dir, file); makeProgram = cmStrCat(dir, '/', saveFile); - mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(), - "make program", cmStateEnums::FILEPATH); + mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram, "make program", + cmStateEnums::FILEPATH); } return true; } @@ -1679,8 +1678,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() for (std::string const& c : configs) { std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c)); - if (const char* val = mf->GetProperty(defPropName)) { - t->AppendProperty(defPropName, val); + if (cmProp val = mf->GetProperty(defPropName)) { + t->AppendProperty(defPropName, *val); } } } @@ -1791,14 +1790,13 @@ void cmGlobalGenerator::CheckTargetProperties() } } std::vector<std::string> incs; - const char* incDirProp = - target.second.GetProperty("INCLUDE_DIRECTORIES"); + cmProp incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES"); if (!incDirProp) { continue; } std::string incDirs = cmGeneratorExpression::Preprocess( - incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions); + *incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions); cmExpandList(incDirs, incs); @@ -2674,13 +2672,13 @@ void cmGlobalGenerator::AddGlobalTarget_Install( } } -const char* cmGlobalGenerator::GetPredefinedTargetsFolder() +std::string cmGlobalGenerator::GetPredefinedTargetsFolder() { - const char* prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty( + cmProp prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty( "PREDEFINED_TARGETS_FOLDER"); if (prop) { - return prop; + return *prop; } return "CMakePredefinedTargets"; @@ -2688,13 +2686,13 @@ const char* cmGlobalGenerator::GetPredefinedTargetsFolder() bool cmGlobalGenerator::UseFolderProperty() const { - const char* prop = + cmProp prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty("USE_FOLDERS"); // If this property is defined, let the setter turn this on or off... // if (prop) { - return cmIsOn(prop); + return cmIsOn(*prop); } // By default, this feature is OFF, since it is not supported in the @@ -3036,7 +3034,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) #ifndef CMAKE_BOOTSTRAP // Check whether labels are enabled for this target. const char* targetLabels = target->GetProperty("LABELS"); - const char* directoryLabels = + cmProp directoryLabels = target->Target->GetMakefile()->GetProperty("LABELS"); const char* cmakeDirectoryLabels = target->Target->GetMakefile()->GetDefinition("CMAKE_DIRECTORY_LABELS"); @@ -3070,7 +3068,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) std::vector<std::string> cmakeDirectoryLabelsList; if (directoryLabels) { - cmExpandList(directoryLabels, directoryLabelsList); + cmExpandList(*directoryLabels, directoryLabelsList); } if (cmakeDirectoryLabels) { diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 7dc4822..70e43b5 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -588,7 +588,7 @@ protected: cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const; - const char* GetPredefinedTargetsFolder(); + std::string GetPredefinedTargetsFolder(); private: using TargetMap = std::unordered_map<std::string, cmTarget*>; diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index bb9dd37..289a035 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -9,6 +9,7 @@ #include <utility> #include <cm/memory> +#include <cm/string> #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" @@ -90,7 +91,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, /* store the full toolset for later use * -- already done if -T<toolset> was specified */ - mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsp.c_str(), + mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsp, "Location of generator toolset.", cmStateEnums::INTERNAL); } @@ -112,8 +113,8 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, } /* store the toolset that is being used for this build */ - mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(), - "build program to use", cmStateEnums::INTERNAL, true); + mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild, "build program to use", + cmStateEnums::INTERNAL, true); mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsp); @@ -132,7 +133,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, /* store the platform name for later use * -- already done if -A<arch> was specified */ - mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch.c_str(), + mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch, "Name of generator platform.", cmStateEnums::INTERNAL); } else { @@ -166,7 +167,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, if (cmIsOff(bspName) && platform.find("integrity") != std::string::npos) { bspName = "sim" + arch; /* write back the calculate name for next time */ - mf->AddCacheDefinition("GHS_BSP_NAME", bspName.c_str(), + mf->AddCacheDefinition("GHS_BSP_NAME", bspName, "Name of GHS target platform.", cmStateEnums::STRING, true); std::string m = cmStrCat( @@ -253,14 +254,15 @@ void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd, void cmGlobalGhsMultiGenerator::WriteFileHeader(std::ostream& fout) { - fout << "#!gbuild" << std::endl; - fout << "#" << std::endl - << "# CMAKE generated file: DO NOT EDIT!" << std::endl - << "# Generated by \"" << GetActualName() << "\"" - << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "." - << cmVersion::GetMinorVersion() << std::endl - << "#" << std::endl - << std::endl; + /* clang-format off */ + fout << "#!gbuild\n" + "#\n" + "# CMAKE generated file: DO NOT EDIT!\n" + "# Generated by \"" << GetActualName() << "\"" + " Generator, CMake Version " << cmVersion::GetMajorVersion() << '.' + << cmVersion::GetMinorVersion() << "\n" + "#\n\n"; + /* clang-format on */ } void cmGlobalGhsMultiGenerator::WriteCustomRuleBOD(std::ostream& fout) @@ -268,36 +270,36 @@ void cmGlobalGhsMultiGenerator::WriteCustomRuleBOD(std::ostream& fout) fout << "Commands {\n" " Custom_Rule_Command {\n" " name = \"Custom Rule Command\"\n" - " exec = \""; + " exec = \"" #ifdef _WIN32 - fout << "cmd.exe"; + "cmd.exe" #else - fout << "/bin/sh"; + "/bin/sh" #endif - fout << "\"\n" + "\"\n" " options = {\"SpecialOptions\"}\n" " }\n" - "}\n"; + "}\n" - fout << "\n\n"; - fout << "FileTypes {\n" + "\n\n" + "FileTypes {\n" " CmakeRule {\n" " name = \"Custom Rule\"\n" " action = \"&Run\"\n" - " extensions = {\""; + " extensions = {\"" #ifdef _WIN32 - fout << "bat"; + "bat" #else - fout << "sh"; + "sh" #endif - fout << "\"}\n" + "\"}\n" " grepable = false\n" " command = \"Custom Rule Command\"\n" - " commandLine = \"$COMMAND "; + " commandLine = \"$COMMAND " #ifdef _WIN32 - fout << "/c"; + "/c" #endif - fout << " $INPUTFILE\"\n" + " $INPUTFILE\"\n" " progress = \"Processing Custom Rule\"\n" " promoteToFirstPass = true\n" " outputType = \"None\"\n" @@ -327,13 +329,13 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout, this->WriteHighLevelDirectives(root, fout); GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fout); - fout << "# Top Level Project File" << std::endl; + fout << "# Top Level Project File\n"; // Specify BSP option if supplied by user const char* bspName = this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME"); if (!cmIsOff(bspName)) { - fout << " -bsp " << bspName << std::endl; + fout << " -bsp " << bspName << '\n'; } // Specify OS DIR if supplied by user @@ -348,14 +350,14 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout, } else { fout << osDirOption; } - fout << "\"" << this->OsDir << "\"" << std::endl; + fout << "\"" << this->OsDir << "\"\n"; } } void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout, std::string& all_target) { - fout << "CMakeFiles/" << all_target << " [Project]" << std::endl; + fout << "CMakeFiles/" << all_target << " [Project]\n"; // All known targets for (cmGeneratorTarget const* target : this->ProjectTargets) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY || @@ -366,7 +368,7 @@ void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout, continue; } fout << "CMakeFiles/" << target->GetName() + ".tgt" + FILE_EXTENSION - << " [Project]" << std::endl; + << " [Project]\n"; } } @@ -390,7 +392,7 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine( std::string projFile = dir + projName + FILE_EXTENSION; fout << projFile; - fout << " " << projType << std::endl; + fout << ' ' << projType << '\n'; } else { /* Should never happen */ std::string message = @@ -612,14 +614,14 @@ cmGlobalGhsMultiGenerator::GenerateBuildCommand( void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout, cmLocalGenerator* root) { - fout << "macro PROJ_NAME=" << root->GetProjectName() << std::endl; + fout << "macro PROJ_NAME=" << root->GetProjectName() << '\n'; char const* ghsGpjMacros = this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS"); if (nullptr != ghsGpjMacros) { std::vector<std::string> expandedList = cmExpandedList(std::string(ghsGpjMacros)); for (std::string const& arg : expandedList) { - fout << "macro " << arg << std::endl; + fout << "macro " << arg << '\n'; } } } @@ -642,30 +644,27 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives( tgt = cmStrCat((a ? a : ""), '_', (p ? p : ""), ".tgt"); } - fout << "primaryTarget=" << tgt << std::endl; - fout << "customization=" << root->GetBinaryDirectory() - << "/CMakeFiles/custom_rule.bod" << std::endl; - fout << "customization=" << root->GetBinaryDirectory() - << "/CMakeFiles/custom_target.bod" << std::endl; + /* clang-format off */ + fout << "primaryTarget=" << tgt << "\n" + "customization=" << root->GetBinaryDirectory() + << "/CMakeFiles/custom_rule.bod\n" + "customization=" << root->GetBinaryDirectory() + << "/CMakeFiles/custom_target.bod" << '\n'; + /* clang-format on */ char const* const customization = this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION"); if (nullptr != customization && strlen(customization) > 0) { - fout << "customization=" << this->TrimQuotes(customization) << std::endl; + fout << "customization=" + << cmGlobalGhsMultiGenerator::TrimQuotes(customization) << '\n'; this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION"); } } -std::string cmGlobalGhsMultiGenerator::TrimQuotes(std::string const& str) +std::string cmGlobalGhsMultiGenerator::TrimQuotes(std::string str) { - std::string result; - result.reserve(str.size()); - for (const char* ch = str.c_str(); *ch != '\0'; ++ch) { - if (*ch != '"') { - result += *ch; - } - } - return result; + cm::erase(str, '"'); + return str; } bool cmGlobalGhsMultiGenerator::TargetCompare::operator()( diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index b82e9f5..12ca8b6 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -111,7 +111,7 @@ private: std::vector<cmLocalGenerator*>& generators, std::string& all_target); - std::string TrimQuotes(std::string const& str); + static std::string TrimQuotes(std::string str); std::string OsDir; static const char* DEFAULT_BUILD_PROGRAM; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index f4d102e..062f8e9 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -46,7 +46,8 @@ #include "cmake.h" const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja"; -const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja"; +const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = + "CMakeFiles/rules.ninja"; const char* cmGlobalNinjaGenerator::INDENT = " "; #ifdef _WIN32 std::string const cmGlobalNinjaGenerator::SHELL_NOOP = "cd ."; @@ -147,15 +148,15 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, { // Make sure there is a rule. if (build.Rule.empty()) { - cmSystemTools::Error("No rule for WriteBuild! called with comment: " + - build.Comment); + cmSystemTools::Error(cmStrCat( + "No rule for WriteBuild! called with comment: ", build.Comment)); return; } // Make sure there is at least one output file. if (build.Outputs.empty()) { - cmSystemTools::Error( - "No output files for WriteBuild! called with comment: " + build.Comment); + cmSystemTools::Error(cmStrCat( + "No output files for WriteBuild! called with comment: ", build.Comment)); return; } @@ -166,7 +167,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, { // Write explicit outputs for (std::string const& output : build.Outputs) { - buildStr += " " + EncodePath(output); + buildStr += cmStrCat(' ', EncodePath(output)); if (this->ComputingUnknownDependencies) { this->CombinedBuildOutputs.insert(output); } @@ -175,14 +176,13 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, if (!build.ImplicitOuts.empty()) { buildStr += " |"; for (std::string const& implicitOut : build.ImplicitOuts) { - buildStr += " " + EncodePath(implicitOut); + buildStr += cmStrCat(' ', EncodePath(implicitOut)); } } - buildStr += ":"; + buildStr += ':'; // Write the rule. - buildStr += " "; - buildStr += build.Rule; + buildStr += cmStrCat(' ', build.Rule); } std::string arguments; @@ -191,14 +191,14 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, // Write explicit dependencies. for (std::string const& explicitDep : build.ExplicitDeps) { - arguments += " " + EncodePath(explicitDep); + arguments += cmStrCat(' ', EncodePath(explicitDep)); } // Write implicit dependencies. if (!build.ImplicitDeps.empty()) { arguments += " |"; for (std::string const& implicitDep : build.ImplicitDeps) { - arguments += " " + EncodePath(implicitDep); + arguments += cmStrCat(' ', EncodePath(implicitDep)); } } @@ -206,11 +206,11 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, if (!build.OrderOnlyDeps.empty()) { arguments += " ||"; for (std::string const& orderOnlyDep : build.OrderOnlyDeps) { - arguments += " " + EncodePath(orderOnlyDep); + arguments += cmStrCat(' ', EncodePath(orderOnlyDep)); } } - arguments += "\n"; + arguments += '\n'; } // Write the variables bound to this build statement. @@ -309,7 +309,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( void cmGlobalNinjaGenerator::AddMacOSXContentRule() { cmNinjaRule rule("COPY_OSX_CONTENT"); - rule.Command = CMakeCmd() + " -E copy $in $out"; + rule.Command = cmStrCat(CMakeCmd(), " -E copy $in $out"); rule.Description = "Copying OS X Content $out"; rule.Comment = "Rule for copying OS X bundle content file."; this->AddRule(rule); @@ -334,23 +334,24 @@ void cmGlobalNinjaGenerator::WriteRule(std::ostream& os, // -- Parameter checks // Make sure the rule has a name. if (rule.Name.empty()) { - cmSystemTools::Error("No name given for WriteRule! called with comment: " + - rule.Comment); + cmSystemTools::Error(cmStrCat( + "No name given for WriteRule! called with comment: ", rule.Comment)); return; } // Make sure a command is given. if (rule.Command.empty()) { - cmSystemTools::Error( - "No command given for WriteRule! called with comment: " + rule.Comment); + cmSystemTools::Error(cmStrCat( + "No command given for WriteRule! called with comment: ", rule.Comment)); return; } // Make sure response file content is given if (!rule.RspFile.empty() && rule.RspContent.empty()) { - cmSystemTools::Error("rspfile but no rspfile_content given for WriteRule! " - "called with comment: " + - rule.Comment); + cmSystemTools::Error( + cmStrCat("rspfile but no rspfile_content given for WriteRule! " + "called with comment: ", + rule.Comment)); return; } @@ -392,9 +393,9 @@ void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os, { // Make sure we have a name. if (name.empty()) { - cmSystemTools::Error("No name given for WriteVariable! called " - "with comment: " + - comment); + cmSystemTools::Error(cmStrCat("No name given for WriteVariable! called " + "with comment: ", + comment)); return; } @@ -558,11 +559,11 @@ void cmGlobalNinjaGenerator::CleanMetaData() nullptr, cmSystemTools::OUTPUT_NONE)) { this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, - "Running\n '" + - cmJoin(command, "' '") + - "'\n" - "failed with:\n " + - error); + cmStrCat("Running\n '", + cmJoin(command, "' '"), + "'\n" + "failed with:\n ", + error)); cmSystemTools::SetFatalErrorOccured(); } }; @@ -626,10 +627,10 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) nullptr, cmSystemTools::OUTPUT_NONE)) { mf->IssueMessage(MessageType::FATAL_ERROR, - "Running\n '" + cmJoin(command, "' '") + - "'\n" - "failed with:\n " + - error); + cmStrCat("Running\n '", cmJoin(command, "' '"), + "'\n" + "failed with:\n ", + error)); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -713,7 +714,7 @@ bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const /* clang-format off */ e << "The Ninja generator does not support Fortran using Ninja version\n" - " " + this->NinjaVersion + "\n" + " " << this->NinjaVersion << "\n" "due to lack of required features. " "Kitware has implemented the required features and they have been " "merged to upstream ninja for inclusion in Ninja 1.10 and higher. " @@ -998,7 +999,8 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand( std::string buildFileDir = this->GetCMakeInstance()->GetHomeOutputDirectory(); if (!this->CompileCommandsStream) { - std::string buildFilePath = buildFileDir + "/compile_commands.json"; + std::string buildFilePath = + cmStrCat(buildFileDir, "/compile_commands.json"); if (this->ComputingUnknownDependencies) { this->CombinedBuildOutputs.insert( this->NinjaOutputPath("compile_commands.json")); @@ -1007,9 +1009,9 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand( // Get a stream where to generate things. this->CompileCommandsStream = cm::make_unique<cmGeneratedFileStream>(buildFilePath); - *this->CompileCommandsStream << "["; + *this->CompileCommandsStream << "[\n"; } else { - *this->CompileCommandsStream << "," << std::endl; + *this->CompileCommandsStream << ",\n"; } std::string sourceFileName = sourceFile; @@ -1019,7 +1021,7 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand( } /* clang-format off */ - *this->CompileCommandsStream << "\n{\n" + *this->CompileCommandsStream << "{\n" << R"( "directory": ")" << cmGlobalGenerator::EscapeJSON(buildFileDir) << "\",\n" << R"( "command": ")" @@ -1064,8 +1066,8 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies() std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget( cmGeneratorTarget const* target, const std::string& config) { - return "cmake_object_order_depends_target_" + target->GetName() + "_" + - config; + return cmStrCat("cmake_object_order_depends_target_", target->GetName(), '_', + config); } void cmGlobalNinjaGenerator::AppendTargetOutputs( @@ -1103,8 +1105,8 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( case cmStateEnums::GLOBAL_TARGET: case cmStateEnums::UTILITY: { std::string path = - target->GetLocalGenerator()->GetCurrentBinaryDirectory() + - std::string("/") + target->GetName(); + cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', + target->GetName()); std::string output = this->ConvertToNinjaPath(path); if (target->Target->IsPerConfig()) { output = this->BuildAlias(output, config); @@ -1128,8 +1130,8 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( for (BT<std::pair<std::string, bool>> const& util : target->GetUtilities()) { std::string d = - target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + - util.Value.first; + cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', + util.Value.first); outputs.push_back(this->BuildAlias(this->ConvertToNinjaPath(d), config)); } } else { @@ -1356,12 +1358,13 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) // Setup target cmNinjaDeps configDeps; - build.Comment = "Folder: " + currentBinaryDir; + build.Comment = cmStrCat("Folder: ", currentBinaryDir); build.Outputs.emplace_back(); + std::string const buildDirAllTarget = + this->ConvertToNinjaPath(cmStrCat(currentBinaryDir, "/all")); for (auto const& config : configs) { build.ExplicitDeps.clear(); - build.Outputs.front() = this->BuildAlias( - this->ConvertToNinjaPath(currentBinaryDir + "/all"), config); + build.Outputs.front() = this->BuildAlias(buildDirAllTarget, config); configDeps.emplace_back(build.Outputs.front()); for (DirectoryTarget::Target const& t : dt.Targets) { if (!t.ExcludeFromAll) { @@ -1371,7 +1374,7 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) for (DirectoryTarget::Dir const& d : dt.Children) { if (!d.ExcludeFromAll) { build.ExplicitDeps.emplace_back(this->BuildAlias( - this->ConvertToNinjaPath(d.Path + "/all"), config)); + this->ConvertToNinjaPath(cmStrCat(d.Path, "/all")), config)); } } // Write target @@ -1385,21 +1388,18 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) // Add shortcut target if (this->IsMultiConfig()) { for (auto const& config : configs) { - build.ExplicitDeps = { this->BuildAlias( - this->ConvertToNinjaPath(currentBinaryDir + "/all"), config) }; - build.Outputs.front() = - this->ConvertToNinjaPath(currentBinaryDir + "/all"); + build.ExplicitDeps = { this->BuildAlias(buildDirAllTarget, config) }; + build.Outputs.front() = buildDirAllTarget; this->WriteBuild(*this->GetConfigFileStream(config), build); } if (!this->DefaultFileConfig.empty()) { build.ExplicitDeps.clear(); for (auto const& config : this->DefaultConfigs) { - build.ExplicitDeps.push_back(this->BuildAlias( - this->ConvertToNinjaPath(currentBinaryDir + "/all"), config)); + build.ExplicitDeps.push_back( + this->BuildAlias(buildDirAllTarget, config)); } - build.Outputs.front() = - this->ConvertToNinjaPath(currentBinaryDir + "/all"); + build.Outputs.front() = buildDirAllTarget; this->WriteBuild(*this->GetDefaultFileStream(), build); } } @@ -1408,11 +1408,10 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) if (this->EnableCrossConfigBuild()) { build.ExplicitDeps.clear(); for (auto const& config : this->CrossConfigs) { - build.ExplicitDeps.push_back(this->BuildAlias( - this->ConvertToNinjaPath(currentBinaryDir + "/all"), config)); + build.ExplicitDeps.push_back( + this->BuildAlias(buildDirAllTarget, config)); } - build.Outputs.front() = this->BuildAlias( - this->ConvertToNinjaPath(currentBinaryDir + "/all"), "all"); + build.Outputs.front() = this->BuildAlias(buildDirAllTarget, "all"); this->WriteBuild(os, build); } } @@ -1624,7 +1623,8 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) cmNinjaBuild phonyBuild("phony"); phonyBuild.Comment = "Phony target to force glob verification run."; - phonyBuild.Outputs.push_back(cm->GetGlobVerifyScript() + "_force"); + phonyBuild.Outputs.push_back( + cmStrCat(cm->GetGlobVerifyScript(), "_force")); this->WriteBuild(os, phonyBuild); reBuild.Variables["restat"] = "1"; @@ -1815,7 +1815,7 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) // Write rule { cmNinjaRule rule("CLEAN"); - rule.Command = NinjaCmd() + " $FILE_ARG -t clean $TARGETS"; + rule.Command = cmStrCat(NinjaCmd(), " $FILE_ARG -t clean $TARGETS"); rule.Description = "Cleaning all built files..."; rule.Comment = "Rule for cleaning all built files."; WriteRule(*this->RulesFileStream, rule); @@ -1929,7 +1929,7 @@ void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os) { { cmNinjaRule rule("HELP"); - rule.Command = NinjaCmd() + " -t targets"; + rule.Command = cmStrCat(NinjaCmd(), " -t targets"); rule.Description = "All primary targets available:"; rule.Comment = "Rule for printing all primary targets available."; WriteRule(*this->RulesFileStream, rule); @@ -1956,7 +1956,7 @@ std::string cmGlobalNinjaGenerator::NinjaOutputPath( if (!this->HasOutputPathPrefix() || cmSystemTools::FileIsFullPath(path)) { return path; } - return this->OutputPathPrefix + path; + return cmStrCat(this->OutputPathPrefix, path); } void cmGlobalNinjaGenerator::StripNinjaOutputPathPrefixAsSuffix( @@ -2084,7 +2084,8 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg, } else if (cmHasLiteralPrefix(arg, "--lang=")) { arg_lang = arg.substr(7); } else { - cmSystemTools::Error("-E cmake_ninja_depends unknown argument: " + arg); + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_depends unknown argument: ", arg)); return 1; } } @@ -2155,7 +2156,8 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg, cmGeneratedFileStream ddif(arg_ddi); ddif << ddi; if (!ddif) { - cmSystemTools::Error("-E cmake_ninja_depends failed to write " + arg_ddi); + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_depends failed to write ", arg_ddi)); return 1; } return 0; @@ -2201,7 +2203,8 @@ std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran( std::set<std::string> defines; cmFortranParser parser(fc, includes, defines, finfo); if (!cmFortranParser_FilePush(&parser, arg_pp.c_str())) { - cmSystemTools::Error("-E cmake_ninja_depends failed to open " + arg_pp); + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_depends failed to open ", arg_pp)); return nullptr; } if (cmFortran_yyparse(parser.Scanner) != 0) { @@ -2304,7 +2307,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( Json::Value tm = Json::objectValue; for (cmDyndepObjectInfo const& object : objects) { for (std::string const& p : object.Provides) { - std::string const mod = module_dir + p; + std::string const mod = cmStrCat(module_dir, p); mod_files[p] = mod; tm[p] = mod; } @@ -2340,8 +2343,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( // Store the map of modules provided by this target in a file for // use by dependents that reference this target in linked-target-dirs. - std::string const target_mods_file = - cmSystemTools::GetFilenamePath(arg_dd) + "/" + arg_lang + "Modules.json"; + std::string const target_mods_file = cmStrCat( + cmSystemTools::GetFilenamePath(arg_dd), '/', arg_lang, "Modules.json"); cmGeneratedFileStream tmf(target_mods_file); tmf << tm; @@ -2374,7 +2377,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, cmHasLiteralSuffix(arg, ".ddi")) { arg_ddis.push_back(arg); } else { - cmSystemTools::Error("-E cmake_ninja_dyndep unknown argument: " + arg); + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep unknown argument: ", arg)); return 1; } } @@ -2410,7 +2414,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, std::string const dir_top_src = tdi["dir-top-src"].asString(); std::string module_dir = tdi["module-dir"].asString(); if (!module_dir.empty() && !cmHasLiteralSuffix(module_dir, "/")) { - module_dir += "/"; + module_dir += '/'; } std::vector<std::string> linked_target_dirs; Json::Value const& tdi_linked_target_dirs = tdi["linked-target-dirs"]; @@ -2438,9 +2442,7 @@ void cmGlobalNinjaGenerator::AppendDirectoryForConfig( const std::string& suffix, std::string& dir) { if (!config.empty() && this->IsMultiConfig()) { - dir += prefix; - dir += config; - dir += suffix; + dir += cmStrCat(prefix, config, suffix); } } diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 90c9ef0..582877f 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -41,7 +41,6 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3(cmake* cm) #else this->UseLinkScript = true; #endif - this->CommandDatabase = nullptr; this->IncludeDirective = "include"; this->DefineWindowsNULL = false; @@ -49,6 +48,8 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3(cmake* cm) this->UnixCD = true; } +cmGlobalUnixMakefileGenerator3::~cmGlobalUnixMakefileGenerator3() = default; + void cmGlobalUnixMakefileGenerator3::EnableLanguage( std::vector<std::string> const& languages, cmMakefile* mf, bool optional) { @@ -157,10 +158,9 @@ void cmGlobalUnixMakefileGenerator3::Generate() this->WriteMainMakefile2(); this->WriteMainCMakefile(); - if (this->CommandDatabase != nullptr) { - *this->CommandDatabase << std::endl << "]"; - delete this->CommandDatabase; - this->CommandDatabase = nullptr; + if (this->CommandDatabase) { + *this->CommandDatabase << "\n]"; + this->CommandDatabase.reset(); } } @@ -168,26 +168,26 @@ void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand( const std::string& sourceFile, const std::string& workingDirectory, const std::string& compileCommand) { - if (this->CommandDatabase == nullptr) { + if (!this->CommandDatabase) { std::string commandDatabaseName = this->GetCMakeInstance()->GetHomeOutputDirectory() + "/compile_commands.json"; - this->CommandDatabase = new cmGeneratedFileStream(commandDatabaseName); - *this->CommandDatabase << "[" << std::endl; + this->CommandDatabase = + cm::make_unique<cmGeneratedFileStream>(commandDatabaseName); + *this->CommandDatabase << "[\n"; } else { - *this->CommandDatabase << "," << std::endl; + *this->CommandDatabase << ",\n"; } - *this->CommandDatabase << "{" << std::endl + *this->CommandDatabase << "{\n" << R"( "directory": ")" << cmGlobalGenerator::EscapeJSON(workingDirectory) - << "\"," << std::endl + << "\",\n" << R"( "command": ")" << cmGlobalGenerator::EscapeJSON(compileCommand) - << "\"," << std::endl + << "\",\n" << R"( "file": ")" - << cmGlobalGenerator::EscapeJSON(sourceFile) << "\"" - << std::endl - << "}"; + << cmGlobalGenerator::EscapeJSON(sourceFile) + << "\"\n}"; } void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() @@ -343,19 +343,18 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() const std::string& binDir = lg.GetBinaryDirectory(); // CMake must rerun if a byproduct is missing. - { - cmakefileStream << "# Byproducts of CMake generate step:\n" - << "set(CMAKE_MAKEFILE_PRODUCTS\n"; - for (std::string const& outfile : lg.GetMakefile()->GetOutputFiles()) { + cmakefileStream << "# Byproducts of CMake generate step:\n" + << "set(CMAKE_MAKEFILE_PRODUCTS\n"; + + // add in any byproducts and all the directory information files + std::string tmpStr; + for (const auto& localGen : this->LocalGenerators) { + for (std::string const& outfile : + localGen->GetMakefile()->GetOutputFiles()) { cmakefileStream << " \"" << lg.MaybeConvertToRelativePath(binDir, outfile) << "\"\n"; } - } - - // add in all the directory information files - std::string tmpStr; - for (const auto& localGen : this->LocalGenerators) { tmpStr = cmStrCat(localGen->GetCurrentBinaryDirectory(), "/CMakeFiles/CMakeDirectoryInformation.cmake"); cmakefileStream << " \"" @@ -674,10 +673,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( } bool targetMessages = true; - if (const char* tgtMsg = + if (cmProp tgtMsg = this->GetCMakeInstance()->GetState()->GetGlobalProperty( "TARGET_MESSAGES")) { - targetMessages = cmIsOn(tgtMsg); + targetMessages = cmIsOn(*tgtMsg); } if (targetMessages) { @@ -697,9 +696,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # in target - progCmd << lg.ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(progress.Dir), - cmOutputConverter::SHELL); + progCmd << lg.ConvertToOutputFormat(progress.Dir, + cmOutputConverter::SHELL); // std::set<cmGeneratorTarget const*> emitted; progCmd << " " @@ -711,9 +709,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( { std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0 - progCmd << lg.ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(progress.Dir), - cmOutputConverter::SHELL); + progCmd << lg.ConvertToOutputFormat(progress.Dir, + cmOutputConverter::SHELL); progCmd << " 0"; commands.push_back(progCmd.str()); } diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 340a7ef..19b2b85 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -68,6 +68,13 @@ public: new cmGlobalGeneratorSimpleFactory<cmGlobalUnixMakefileGenerator3>()); } + ~cmGlobalUnixMakefileGenerator3() override; + + cmGlobalUnixMakefileGenerator3(const cmGlobalUnixMakefileGenerator3&) = + delete; + cmGlobalUnixMakefileGenerator3& operator=( + const cmGlobalUnixMakefileGenerator3&) = delete; + //! Get the name for the generator. std::string GetName() const override { @@ -232,7 +239,7 @@ protected: std::set<cmGeneratorTarget const*>& emitted); size_t CountProgressMarksInAll(const cmLocalGenerator& lg); - cmGeneratedFileStream* CommandDatabase; + std::unique_ptr<cmGeneratedFileStream> CommandDatabase; private: const char* GetBuildIgnoreErrorsFlag() const override { return "-i"; } diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index ccb6c50..5166de6 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -19,6 +19,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmVersion.h" #include "cmVisualStudioSlnData.h" #include "cmVisualStudioSlnParser.h" @@ -313,7 +314,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( version.clear(); } - if (version.find(this->GetPlatformToolsetString()) != 0) { + if (!cmHasPrefix(version, this->GetPlatformToolsetString())) { std::ostringstream e; /* clang-format off */ e << diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 9799124..4b8010a 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -128,7 +128,7 @@ void cmGlobalVisualStudio7Generator::EnableLanguage( // does not know about. std::string extraPath; if (cmSystemTools::GetEnv("CMAKE_MSVCIDE_RUN_PATH", extraPath)) { - mf->AddCacheDefinition("CMAKE_MSVCIDE_RUN_PATH", extraPath.c_str(), + mf->AddCacheDefinition("CMAKE_MSVCIDE_RUN_PATH", extraPath, "Saved environment variable CMAKE_MSVCIDE_RUN_PATH", cmStateEnums::STATIC); } @@ -505,13 +505,13 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections( const std::vector<std::string> propKeys = root->GetMakefile()->GetPropertyKeys(); for (std::string const& it : propKeys) { - if (it.find("VS_GLOBAL_SECTION_") == 0) { + if (cmHasLiteralPrefix(it, "VS_GLOBAL_SECTION_")) { std::string sectionType; std::string name = it.substr(18); - if (name.find("PRE_") == 0) { + if (cmHasLiteralPrefix(name, "PRE_")) { name = name.substr(4); sectionType = "preSolution"; - } else if (name.find("POST_") == 0) { + } else if (cmHasLiteralPrefix(name, "POST_")) { name = name.substr(5); sectionType = "postSolution"; } else @@ -526,8 +526,8 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections( extensibilityAddInsOverridden = true; } fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n"; - std::vector<std::string> keyValuePairs = - cmExpandedList(root->GetMakefile()->GetProperty(it)); + cmProp p = root->GetMakefile()->GetProperty(it); + std::vector<std::string> keyValuePairs = cmExpandedList(p ? *p : ""); for (std::string const& itPair : keyValuePairs) { const std::string::size_type posEqual = itPair.find('='); if (posEqual != std::string::npos) { @@ -676,7 +676,8 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( for (std::string const& i : configs) { const char* propertyValue = target->Target->GetMakefile()->GetDefinition(propertyName); - if (cmIsOn(cmGeneratorExpression::Evaluate( + if (propertyValue && + cmIsOn(cmGeneratorExpression::Evaluate( propertyValue, target->GetLocalGenerator(), i))) { activeConfigs.insert(i); } diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 1c62fbd..fa0e935 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -275,23 +275,31 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations( bool cmGlobalVisualStudio8Generator::NeedsDeploy( cmGeneratorTarget const& target, const char* config) const { - cmStateEnums::TargetType type = target.GetType(); - bool noDeploy = DeployInhibited(target, config); - return !noDeploy && - (type == cmStateEnums::EXECUTABLE || - type == cmStateEnums::SHARED_LIBRARY) && - this->TargetSystemSupportsDeployment(); -} + cmStateEnums::TargetType const type = target.GetType(); + if (type != cmStateEnums::EXECUTABLE && + type != cmStateEnums::SHARED_LIBRARY) { + // deployment only valid on executables and shared libraries. + return false; + } -bool cmGlobalVisualStudio8Generator::DeployInhibited( - cmGeneratorTarget const& target, const char* config) const -{ - bool rVal = false; - if (const char* prop = target.GetProperty("VS_NO_SOLUTION_DEPLOY")) { - rVal = cmIsOn( + if (const char* prop = target.GetProperty("VS_SOLUTION_DEPLOY")) { + // If set, it dictates behavior + return cmIsOn( cmGeneratorExpression::Evaluate(prop, target.LocalGenerator, config)); } - return rVal; + + // To be deprecated, disable deployment even if target supports it. + if (const char* prop = target.GetProperty("VS_NO_SOLUTION_DEPLOY")) { + if (cmIsOn(cmGeneratorExpression::Evaluate(prop, target.LocalGenerator, + config))) { + // If true, always disable deployment + return false; + } + } + + // Legacy behavior, enabled deployment based on 'hard-coded' target + // platforms. + return this->TargetSystemSupportsDeployment(); } bool cmGlobalVisualStudio8Generator::TargetSystemSupportsDeployment() const diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index 8f8e33b..6ce67d3 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -57,10 +57,6 @@ protected: virtual bool NeedsDeploy(cmGeneratorTarget const& target, const char* config) const; - /** Returns true if deployment has been disabled in cmake file. */ - bool DeployInhibited(cmGeneratorTarget const& target, - const char* config) const; - /** Returns true if the target system support debugging deployment. */ virtual bool TargetSystemSupportsDeployment() const; diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 1ec1559..d2f9760 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -507,9 +507,9 @@ std::string cmGlobalVisualStudioGenerator::GetUtilityDepend( std::string cmGlobalVisualStudioGenerator::GetStartupProjectName( cmLocalGenerator const* root) const { - const char* n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT"); - if (n && *n) { - std::string startup = n; + cmProp n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT"); + if (n && !n->empty()) { + std::string startup = *n; if (this->FindTarget(startup)) { return startup; } else { diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index e0005a4..e74d618 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -8,6 +8,7 @@ #include <cstring> #include <iomanip> #include <sstream> +#include <utility> #include <cm/memory> #include <cmext/algorithm> @@ -33,6 +34,7 @@ #include "cmSourceGroup.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmXCode21Object.h" @@ -642,7 +644,8 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( << "\n"; } -static bool objectIdLessThan(cmXCodeObject* l, cmXCodeObject* r) +static bool objectIdLessThan(const std::unique_ptr<cmXCodeObject>& l, + const std::unique_ptr<cmXCodeObject>& r) { return l->GetId() < r->GetId(); } @@ -656,9 +659,6 @@ void cmGlobalXCodeGenerator::SortXCodeObjects() void cmGlobalXCodeGenerator::ClearXCodeObjects() { this->TargetDoneSet.clear(); - for (auto& obj : this->XCodeObjects) { - delete obj; - } this->XCodeObjects.clear(); this->XCodeObjectIDs.clear(); this->XCodeObjectMap.clear(); @@ -668,7 +668,7 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects() this->FileRefs.clear(); } -void cmGlobalXCodeGenerator::addObject(cmXCodeObject* obj) +void cmGlobalXCodeGenerator::addObject(std::unique_ptr<cmXCodeObject> obj) { if (obj->GetType() == cmXCodeObject::OBJECT) { const std::string& id = obj->GetId(); @@ -683,22 +683,24 @@ void cmGlobalXCodeGenerator::addObject(cmXCodeObject* obj) this->XCodeObjectIDs.insert(id); } - this->XCodeObjects.push_back(obj); + this->XCodeObjects.push_back(std::move(obj)); } cmXCodeObject* cmGlobalXCodeGenerator::CreateObject( cmXCodeObject::PBXType ptype) { - cmXCodeObject* obj = new cmXCode21Object(ptype, cmXCodeObject::OBJECT); - this->addObject(obj); - return obj; + auto obj = cm::make_unique<cmXCode21Object>(ptype, cmXCodeObject::OBJECT); + auto ptr = obj.get(); + this->addObject(std::move(obj)); + return ptr; } cmXCodeObject* cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type) { - cmXCodeObject* obj = new cmXCodeObject(cmXCodeObject::None, type); - this->addObject(obj); - return obj; + auto obj = cm::make_unique<cmXCodeObject>(cmXCodeObject::None, type); + auto ptr = obj.get(); + this->addObject(std::move(obj)); + return ptr; } cmXCodeObject* cmGlobalXCodeGenerator::CreateString(const std::string& s) @@ -1859,7 +1861,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY || gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) { this->CurrentLocalGenerator->GetStaticLibraryFlags( - extraLinkOptions, cmSystemTools::UpperCase(configName), llang, gtgt); + extraLinkOptions, configName, llang, gtgt); } else { const char* targetLinkFlags = gtgt->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { @@ -2406,12 +2408,13 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // Convert "XCODE_ATTRIBUTE_*" properties directly. { for (auto const& prop : gtgt->GetPropertyKeys()) { - if (prop.find("XCODE_ATTRIBUTE_") == 0) { + if (cmHasLiteralPrefix(prop, "XCODE_ATTRIBUTE_")) { std::string attribute = prop.substr(16); this->FilterConfigurationAttribute(configName, attribute); if (!attribute.empty()) { + const char* pr = gtgt->GetProperty(prop); std::string processed = cmGeneratorExpression::Evaluate( - gtgt->GetProperty(prop), this->CurrentLocalGenerator, configName); + pr ? pr : "", this->CurrentLocalGenerator, configName); buildSettings->AddAttribute(attribute, this->CreateString(processed)); } @@ -3141,12 +3144,12 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( // Put this last so it can override existing settings // Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly. for (const auto& var : this->CurrentMakefile->GetDefinitions()) { - if (var.find("CMAKE_XCODE_ATTRIBUTE_") == 0) { + if (cmHasLiteralPrefix(var, "CMAKE_XCODE_ATTRIBUTE_")) { std::string attribute = var.substr(22); this->FilterConfigurationAttribute(config.first, attribute); if (!attribute.empty()) { std::string processed = cmGeneratorExpression::Evaluate( - this->CurrentMakefile->GetDefinition(var), + this->CurrentMakefile->GetSafeDefinition(var), this->CurrentLocalGenerator, config.first); buildSettingsForCfg->AddAttribute(attribute, this->CreateString(processed)); @@ -3390,7 +3393,7 @@ bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( // collect all tests for the targets std::map<std::string, cmXCodeScheme::TestObjects> testables; - for (auto obj : this->XCodeObjects) { + for (const auto& obj : this->XCodeObjects) { if (obj->GetType() != cmXCodeObject::OBJECT || obj->GetIsA() != cmXCodeObject::PBXNativeTarget) { continue; @@ -3405,7 +3408,7 @@ bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( continue; } - testables[testee].push_back(obj); + testables[testee].push_back(obj.get()); } // generate scheme @@ -3414,14 +3417,14 @@ bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( // Since the lowest available Xcode version for testing was 6.4, // I'm setting this as a limit then if (this->XcodeVersion >= 64) { - for (auto obj : this->XCodeObjects) { + for (const auto& obj : this->XCodeObjects) { if (obj->GetType() == cmXCodeObject::OBJECT && (obj->GetIsA() == cmXCodeObject::PBXNativeTarget || obj->GetIsA() == cmXCodeObject::PBXAggregateTarget) && (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() || obj->GetTarget()->GetPropertyAsBool("XCODE_GENERATE_SCHEME"))) { const std::string& targetName = obj->GetTarget()->GetName(); - cmXCodeScheme schm(root, obj, testables[targetName], + cmXCodeScheme schm(root, obj.get(), testables[targetName], this->CurrentConfigurationTypes, this->XcodeVersion); schm.WriteXCodeSharedScheme(xcProjDir, @@ -3693,15 +3696,14 @@ bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation( bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const { - const char* epnValue = - this->GetCMakeInstance()->GetState()->GetGlobalProperty( - "XCODE_EMIT_EFFECTIVE_PLATFORM_NAME"); + cmProp epnValue = this->GetCMakeInstance()->GetState()->GetGlobalProperty( + "XCODE_EMIT_EFFECTIVE_PLATFORM_NAME"); if (!epnValue) { return mf->PlatformIsAppleEmbedded(); } - return cmIsOn(epnValue); + return cmIsOn(*epnValue); } bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index df68f80..e380f1c 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -37,6 +37,10 @@ public: unsigned int version_number); static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); + cmGlobalXCodeGenerator(const cmGlobalXCodeGenerator&) = delete; + const cmGlobalXCodeGenerator& operator=(const cmGlobalXCodeGenerator&) = + delete; + //! Get the name for the generator. std::string GetName() const override { @@ -249,7 +253,7 @@ protected: unsigned int XcodeVersion; std::string VersionString; std::set<std::string> XCodeObjectIDs; - std::vector<cmXCodeObject*> XCodeObjects; + std::vector<std::unique_ptr<cmXCodeObject>> XCodeObjects; cmXCodeObject* RootObject; private: @@ -273,7 +277,7 @@ private: void ComputeArchitectures(cmMakefile* mf); void ComputeObjectDirArch(cmMakefile* mf); - void addObject(cmXCodeObject* obj); + void addObject(std::unique_ptr<cmXCodeObject> obj); std::string PostBuildMakeTarget(std::string const& tName, std::string const& configName); cmXCodeObject* MainGroupChildren; diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index 1b77678..0fcda4e 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -298,13 +298,13 @@ void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& fs, const std::string& name) { auto const escapedGraphName = EscapeForDotFile(name); - fs << "digraph \"" << escapedGraphName << "\" {" << std::endl; - fs << this->GraphHeader << std::endl; + fs << "digraph \"" << escapedGraphName << "\" {\n" + << this->GraphHeader << '\n'; } void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& fs) { - fs << "}" << std::endl; + fs << "}\n"; } void cmGraphVizWriter::WriteLegend(cmGeneratedFileStream& fs) @@ -312,52 +312,46 @@ void cmGraphVizWriter::WriteLegend(cmGeneratedFileStream& fs) // Note that the subgraph name must start with "cluster", as done here, to // make Graphviz layout engines do the right thing and keep the nodes // together. - fs << "subgraph clusterLegend {" << std::endl; - fs << " label = \"Legend\";" << std::endl; - // Set the color of the box surrounding the legend. - fs << " color = black;" << std::endl; - // We use invisible edges just to enforce the layout. - fs << " edge [ style = invis ];" << std::endl; - - // Nodes. - fs << " legendNode0 [ label = \"Executable\", shape = " - << GRAPHVIZ_NODE_SHAPE_EXECUTABLE << " ];" << std::endl; - - fs << " legendNode1 [ label = \"Static Library\", shape = " - << GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC << " ];" << std::endl; - fs << " legendNode2 [ label = \"Shared Library\", shape = " - << GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED << " ];" << std::endl; - fs << " legendNode3 [ label = \"Module Library\", shape = " - << GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE << " ];" << std::endl; - - fs << " legendNode4 [ label = \"Interface Library\", shape = " - << GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE << " ];" << std::endl; - fs << " legendNode5 [ label = \"Object Library\", shape = " - << GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT << " ];" << std::endl; - fs << " legendNode6 [ label = \"Unknown Library\", shape = " - << GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN << " ];" << std::endl; - - fs << " legendNode7 [ label = \"Custom Target\", shape = " - << GRAPHVIZ_NODE_SHAPE_UTILITY << " ];" << std::endl; - - // Edges. - // Some of those are dummy (invisible) edges to enforce a layout. - fs << " legendNode0 -> legendNode1 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC - << " ];" << std::endl; - fs << " legendNode0 -> legendNode2 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC - << " ];" << std::endl; - fs << " legendNode0 -> legendNode3;" << std::endl; - - fs << " legendNode1 -> legendNode4 [ label = \"Interface\", style = " - << GRAPHVIZ_EDGE_STYLE_INTERFACE << " ];" << std::endl; - fs << " legendNode2 -> legendNode5 [ label = \"Private\", style = " - << GRAPHVIZ_EDGE_STYLE_PRIVATE << " ];" << std::endl; - fs << " legendNode3 -> legendNode6 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC - << " ];" << std::endl; - - fs << " legendNode0 -> legendNode7;" << std::endl; - - fs << "}" << std::endl; + /* clang-format off */ + fs << "subgraph clusterLegend {\n" + " label = \"Legend\";\n" + // Set the color of the box surrounding the legend. + " color = black;\n" + // We use invisible edges just to enforce the layout. + " edge [ style = invis ];\n" + // Nodes. + " legendNode0 [ label = \"Executable\", shape = " + << GRAPHVIZ_NODE_SHAPE_EXECUTABLE << " ];\n" + " legendNode1 [ label = \"Static Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC << " ];\n" + " legendNode2 [ label = \"Shared Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED << " ];\n" + " legendNode3 [ label = \"Module Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE << " ];\n" + " legendNode4 [ label = \"Interface Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE << " ];\n" + " legendNode5 [ label = \"Object Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT << " ];\n" + " legendNode6 [ label = \"Unknown Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN << " ];\n" + " legendNode7 [ label = \"Custom Target\", shape = " + << GRAPHVIZ_NODE_SHAPE_UTILITY << " ];\n" + // Edges. + // Some of those are dummy (invisible) edges to enforce a layout. + " legendNode0 -> legendNode1 [ style = " + << GRAPHVIZ_EDGE_STYLE_PUBLIC << " ];\n" + " legendNode0 -> legendNode2 [ style = " + << GRAPHVIZ_EDGE_STYLE_PUBLIC << " ];\n" + " legendNode0 -> legendNode3;\n" + " legendNode1 -> legendNode4 [ label = \"Interface\", style = " + << GRAPHVIZ_EDGE_STYLE_INTERFACE << " ];\n" + " legendNode2 -> legendNode5 [ label = \"Private\", style = " + << GRAPHVIZ_EDGE_STYLE_PRIVATE << " ];\n" + " legendNode3 -> legendNode6 [ style = " + << GRAPHVIZ_EDGE_STYLE_PUBLIC << " ];\n" + " legendNode0 -> legendNode7;\n" + "}\n"; + /* clang-format off */ } void cmGraphVizWriter::WriteNode(cmGeneratedFileStream& fs, @@ -370,7 +364,7 @@ void cmGraphVizWriter::WriteNode(cmGeneratedFileStream& fs, auto const escapedLabel = EscapeForDotFile(itemNameWithAliases); fs << " \"" << nodeName << "\" [ label = \"" << escapedLabel - << "\", shape = " << getShapeForTarget(item) << " ];" << std::endl; + << "\", shape = " << getShapeForTarget(item) << " ];\n"; } void cmGraphVizWriter::WriteConnection(cmGeneratedFileStream& fs, @@ -382,11 +376,9 @@ void cmGraphVizWriter::WriteConnection(cmGeneratedFileStream& fs, auto const& dependeeName = dependee.AsStr(); fs << " \"" << this->NodeNames[dependerName] << "\" -> \"" - << this->NodeNames[dependeeName] << "\" "; - - fs << edgeStyle; - - fs << " // " << dependerName << " -> " << dependeeName << std::endl; + << this->NodeNames[dependeeName] << "\" " + << edgeStyle + << " // " << dependerName << " -> " << dependeeName << '\n'; } bool cmGraphVizWriter::ItemExcluded(cmLinkItem const& item) @@ -402,9 +394,9 @@ bool cmGraphVizWriter::ItemExcluded(cmLinkItem const& item) } if (item.Target->GetType() == cmStateEnums::UTILITY) { - if ((itemName.find("Nightly") == 0) || - (itemName.find("Continuous") == 0) || - (itemName.find("Experimental") == 0)) { + if (cmHasLiteralPrefix(itemName, "Nightly") || + cmHasLiteralPrefix(itemName, "Continuous") || + cmHasLiteralPrefix(itemName, "Experimental")) { return true; } } diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index d669ed7..704db66 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -680,9 +680,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, } if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) { - const char* files = target.GetProperty("PRIVATE_HEADER"); - if ((files) && (*files)) { - std::vector<std::string> relFiles = cmExpandedList(files); + cmProp files = target.GetProperty("PRIVATE_HEADER"); + if (files && !files->empty()) { + std::vector<std::string> relFiles = cmExpandedList(*files); std::vector<std::string> absFiles; if (!helper.MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) { return false; @@ -703,8 +703,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, } files = target.GetProperty("PUBLIC_HEADER"); - if ((files) && (*files)) { - std::vector<std::string> relFiles = cmExpandedList(files); + if (files && !files->empty()) { + std::vector<std::string> relFiles = cmExpandedList(*files); std::vector<std::string> absFiles; if (!helper.MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) { return false; @@ -725,8 +725,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, } files = target.GetProperty("RESOURCE"); - if ((files) && (*files)) { - std::vector<std::string> relFiles = cmExpandedList(files); + if (files && !files->empty()) { + std::vector<std::string> relFiles = cmExpandedList(*files); std::vector<std::string> absFiles; if (!helper.MakeFilesFullPath("RESOURCE", relFiles, absFiles)) { return false; diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 2c53a28..6e3508c 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -7,6 +7,8 @@ #include <sstream> #include <utility> +#include <cm/memory> + #ifndef CMAKE_BOOTSTRAP # include "cmExportInstallAndroidMKGenerator.h" #endif @@ -33,18 +35,15 @@ cmInstallExportGenerator::cmInstallExportGenerator( { if (android) { #ifndef CMAKE_BOOTSTRAP - this->EFGen = new cmExportInstallAndroidMKGenerator(this); + this->EFGen = cm::make_unique<cmExportInstallAndroidMKGenerator>(this); #endif } else { - this->EFGen = new cmExportInstallFileGenerator(this); + this->EFGen = cm::make_unique<cmExportInstallFileGenerator>(this); } exportSet->AddInstallation(this); } -cmInstallExportGenerator::~cmInstallExportGenerator() -{ - delete this->EFGen; -} +cmInstallExportGenerator::~cmInstallExportGenerator() = default; bool cmInstallExportGenerator::Compute(cmLocalGenerator* lg) { diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index cf28b35..43dd00d 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -7,6 +7,7 @@ #include <cstddef> #include <iosfwd> +#include <memory> #include <string> #include <vector> @@ -30,8 +31,12 @@ public: bool exclude_from_all, std::string filename, std::string name_space, bool exportOld, bool android); + cmInstallExportGenerator(const cmInstallExportGenerator&) = delete; ~cmInstallExportGenerator() override; + cmInstallExportGenerator& operator=(const cmInstallExportGenerator&) = + delete; + cmExportSet* GetExportSet() { return this->ExportSet; } bool Compute(cmLocalGenerator* lg) override; @@ -61,7 +66,7 @@ protected: std::string TempDir; std::string MainImportFile; - cmExportInstallFileGenerator* EFGen; + std::unique_ptr<cmExportInstallFileGenerator> EFGen; }; #endif diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index a65ae03..32395d1 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -42,7 +42,8 @@ void cmInstalledFile::RemoveProperty(const std::string& prop) } void cmInstalledFile::SetProperty(cmMakefile const* mf, - const std::string& prop, const char* value) + const std::string& prop, + const std::string& value) { this->RemoveProperty(prop); this->AppendProperty(mf, prop, value); @@ -50,7 +51,8 @@ void cmInstalledFile::SetProperty(cmMakefile const* mf, void cmInstalledFile::AppendProperty(cmMakefile const* mf, const std::string& prop, - const char* value, bool /*asString*/) + const std::string& value, + bool /*asString*/) { cmListFileBacktrace backtrace = mf->GetBacktrace(); cmGeneratorExpression ge(backtrace); diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h index 698151e..07f7081 100644 --- a/Source/cmInstalledFile.h +++ b/Source/cmInstalledFile.h @@ -49,10 +49,10 @@ public: void RemoveProperty(const std::string& prop); void SetProperty(cmMakefile const* mf, const std::string& prop, - const char* value); + const std::string& value); void AppendProperty(cmMakefile const* mf, const std::string& prop, - const char* value, bool asString = false); + const std::string& value, bool asString = false); bool HasProperty(const std::string& prop) const; diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx index dd36386..9ecf378 100644 --- a/Source/cmJsonObjects.cxx +++ b/Source/cmJsonObjects.cxx @@ -90,7 +90,8 @@ void cmGetCMakeInputs(const cmGlobalGenerator* gg, const std::string startOfFile = lf.substr(0, cmakeRootDir.size()); const bool isInternal = (startOfFile == cmakeRootDir); - const bool isTemporary = !isInternal && (lf.find(buildDir + '/') == 0); + const bool isTemporary = + !isInternal && (cmHasPrefix(lf, buildDir + '/')); std::string toAdd = lf; if (!sourceDir.empty()) { diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index 0ea25c0..ae87e45 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -81,6 +81,9 @@ struct cmLinkInterface : public cmLinkInterfaceLibraries std::vector<cmLinkItem> WrongConfigLibraries; bool ImplementationIsInterface = false; + + // Whether the list depends on a link language genex. + bool HadLinkLanguageSensitiveCondition = false; }; struct cmOptionalLinkInterface : public cmLinkInterface @@ -100,6 +103,9 @@ struct cmLinkImplementation : public cmLinkImplementationLibraries { // Languages whose runtime libraries must be linked. std::vector<std::string> Languages; + + // Whether the list depends on a link language genex. + bool HadLinkLanguageSensitiveCondition = false; }; // Cache link implementation computation from each configuration. diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 47679c9..7ebb02f 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -26,13 +26,15 @@ cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=( struct cmListFileParser { cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt, - cmMessenger* messenger, const char* filename); + cmMessenger* messenger); ~cmListFileParser(); cmListFileParser(const cmListFileParser&) = delete; cmListFileParser& operator=(const cmListFileParser&) = delete; void IssueFileOpenError(std::string const& text) const; void IssueError(std::string const& text) const; - bool ParseFile(); + bool ParseFile(const char* filename); + bool ParseString(const char* str, const char* virtual_filename); + bool Parse(); bool ParseFunction(const char* name, long line); bool AddArgument(cmListFileLexer_Token* token, cmListFileArgument::Delimiter delim); @@ -51,12 +53,11 @@ struct cmListFileParser }; cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt, - cmMessenger* messenger, - const char* filename) + cmMessenger* messenger) : ListFile(lf) , Backtrace(std::move(lfbt)) , Messenger(messenger) - , FileName(filename) + , FileName(nullptr) , Lexer(cmListFileLexer_New()) { } @@ -83,8 +84,10 @@ void cmListFileParser::IssueError(const std::string& text) const cmSystemTools::SetFatalErrorOccured(); } -bool cmListFileParser::ParseFile() +bool cmListFileParser::ParseFile(const char* filename) { + this->FileName = filename; + // Open the file. cmListFileLexer_BOM bom; if (!cmListFileLexer_SetFileName(this->Lexer, this->FileName, &bom)) { @@ -107,6 +110,24 @@ bool cmListFileParser::ParseFile() return false; } + return Parse(); +} + +bool cmListFileParser::ParseString(const char* str, + const char* virtual_filename) +{ + this->FileName = virtual_filename; + + if (!cmListFileLexer_SetString(this->Lexer, str)) { + this->IssueFileOpenError("cmListFileCache: cannot allocate buffer."); + return false; + } + + return Parse(); +} + +bool cmListFileParser::Parse() +{ // Use a simple recursive-descent parser to process the token // stream. bool haveNewline = true; @@ -155,8 +176,22 @@ bool cmListFile::ParseFile(const char* filename, cmMessenger* messenger, bool parseError = false; { - cmListFileParser parser(this, lfbt, messenger, filename); - parseError = !parser.ParseFile(); + cmListFileParser parser(this, lfbt, messenger); + parseError = !parser.ParseFile(filename); + } + + return !parseError; +} + +bool cmListFile::ParseString(const char* str, const char* virtual_filename, + cmMessenger* messenger, + const cmListFileBacktrace& lfbt) +{ + bool parseError = false; + + { + cmListFileParser parser(this, lfbt, messenger); + parseError = !parser.ParseString(str, virtual_filename); } return !parseError; diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 9cae827..89902ff 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -184,6 +184,9 @@ struct cmListFile bool ParseFile(const char* path, cmMessenger* messenger, cmListFileBacktrace const& lfbt); + bool ParseString(const char* str, const char* virtual_filename, + cmMessenger* messenger, cmListFileBacktrace const& lfbt); + std::vector<cmListFileFunction> Functions; }; diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 92258e2..5790e16 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -1,5 +1,15 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ + +#if !defined(_WIN32) && !defined(__sun) +// POSIX APIs are needed +# define _POSIX_C_SOURCE 200809L +#endif +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) +// For isascii +# define _XOPEN_SOURCE 700 +#endif + #include "cmLoadCommandCommand.h" #include <csignal> diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index 025ef7e..278ec8b 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -50,6 +50,15 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags( this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG"), mod_dir); this->AppendFlags(flags, modflag); + // Some compilers do not search their own module output directory + // for using other modules. Add an include directory explicitly + // for consistency with compilers that do search it. + std::string incflag = + this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_INCLUDE_FLAG"); + if (!incflag.empty()) { + incflag = cmStrCat(incflag, mod_dir); + this->AppendFlags(flags, incflag); + } } // If there is a separate module path flag then duplicate the diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index cf6802d..a80bc7c 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -288,29 +288,29 @@ void cmLocalGenerator::GenerateTestFiles() cmGeneratedFileStream fout(file); fout.SetCopyIfDifferent(true); - fout << "# CMake generated Testfile for " << std::endl - << "# Source directory: " - << this->StateSnapshot.GetDirectory().GetCurrentSource() << std::endl - << "# Build directory: " - << this->StateSnapshot.GetDirectory().GetCurrentBinary() << std::endl - << "# " << std::endl - << "# This file includes the relevant testing commands " - << "required for " << std::endl - << "# testing this directory and lists subdirectories to " - << "be tested as well." << std::endl; - - const char* testIncludeFile = - this->Makefile->GetProperty("TEST_INCLUDE_FILE"); + fout << "# CMake generated Testfile for \n" + "# Source directory: " + << this->StateSnapshot.GetDirectory().GetCurrentSource() + << "\n" + "# Build directory: " + << this->StateSnapshot.GetDirectory().GetCurrentBinary() + << "\n" + "# \n" + "# This file includes the relevant testing commands " + "required for \n" + "# testing this directory and lists subdirectories to " + "be tested as well.\n"; + + cmProp testIncludeFile = this->Makefile->GetProperty("TEST_INCLUDE_FILE"); if (testIncludeFile) { - fout << "include(\"" << testIncludeFile << "\")" << std::endl; + fout << "include(\"" << *testIncludeFile << "\")\n"; } - const char* testIncludeFiles = - this->Makefile->GetProperty("TEST_INCLUDE_FILES"); + cmProp testIncludeFiles = this->Makefile->GetProperty("TEST_INCLUDE_FILES"); if (testIncludeFiles) { - std::vector<std::string> includesList = cmExpandedList(testIncludeFiles); + std::vector<std::string> includesList = cmExpandedList(*testIncludeFiles); for (std::string const& i : includesList) { - fout << "include(\"" << i << "\")" << std::endl; + fout << "include(\"" << i << "\")\n"; } } @@ -327,18 +327,18 @@ void cmLocalGenerator::GenerateTestFiles() std::string outP = i.GetDirectory().GetCurrentBinary(); outP = this->MaybeConvertToRelativePath(parentBinDir, outP); outP = cmOutputConverter::EscapeForCMake(outP); - fout << "subdirs(" << outP << ")" << std::endl; + fout << "subdirs(" << outP << ")\n"; } // Add directory labels property const char* directoryLabels = this->Makefile->GetDefinition("CMAKE_DIRECTORY_LABELS"); - const char* labels = this->Makefile->GetProperty("LABELS"); + cmProp labels = this->Makefile->GetProperty("LABELS"); if (labels || directoryLabels) { fout << "set_directory_properties(PROPERTIES LABELS "; if (labels) { - fout << cmOutputConverter::EscapeForCMake(labels); + fout << cmOutputConverter::EscapeForCMake(*labels); } if (labels && directoryLabels) { fout << ";"; @@ -346,7 +346,7 @@ void cmLocalGenerator::GenerateTestFiles() if (directoryLabels) { fout << cmOutputConverter::EscapeForCMake(directoryLabels); } - fout << ")" << std::endl; + fout << ")\n"; } } @@ -467,16 +467,17 @@ void cmLocalGenerator::GenerateInstallRules() fout.SetCopyIfDifferent(true); // Write the header. + /* clang-format off */ fout << "# Install script for directory: " - << this->StateSnapshot.GetDirectory().GetCurrentSource() << std::endl - << std::endl; - fout << "# Set the install prefix" << std::endl - << "if(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl - << " set(CMAKE_INSTALL_PREFIX \"" << prefix << "\")" << std::endl - << "endif()" << std::endl + << this->StateSnapshot.GetDirectory().GetCurrentSource() + << "\n\n" + "# Set the install prefix\n" + "if(NOT DEFINED CMAKE_INSTALL_PREFIX)\n" + " set(CMAKE_INSTALL_PREFIX \"" << prefix << "\")\n" + "endif()\n" << R"(string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX )" - << "\"${CMAKE_INSTALL_PREFIX}\")" << std::endl - << std::endl; + << "\"${CMAKE_INSTALL_PREFIX}\")\n\n"; + /* clang-format on */ // Write support code for generating per-configuration install rules. /* clang-format off */ @@ -591,8 +592,7 @@ void cmLocalGenerator::GenerateInstallRules() if (!c.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) { std::string odir = c.GetDirectory().GetCurrentBinary(); cmSystemTools::ConvertToUnixSlashes(odir); - fout << " include(\"" << odir << "/cmake_install.cmake\")" - << std::endl; + fout << " include(\"" << odir << "/cmake_install.cmake\")\n"; } } fout << "\n"; @@ -773,7 +773,8 @@ const char* cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target, if (target) { return target->GetProperty(prop); } - return this->Makefile->GetProperty(prop); + cmProp p = this->Makefile->GetProperty(prop); + return p ? p->c_str() : nullptr; } std::string cmLocalGenerator::ConvertToIncludeReference( @@ -877,7 +878,7 @@ std::string cmLocalGenerator::GetIncludeFlags( if ((sep[0] != ' ') && !flags.empty() && flags.back() == sep[0]) { flags.back() = ' '; } - return flags; + return cmTrimWhitespace(flags); } void cmLocalGenerator::AddCompileOptions(std::string& flags, @@ -949,8 +950,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, << "\". " "This is not permitted. The COMPILE_FEATURES may not both depend " "on " - "and be depended on by the link implementation." - << std::endl; + "and be depended on by the link implementation.\n"; this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -1292,14 +1292,15 @@ std::vector<BT<std::string>> cmLocalGenerator::GetStaticLibraryFlags( std::string const& config, std::string const& linkLanguage, cmGeneratorTarget* target) { + const std::string configUpper = cmSystemTools::UpperCase(config); std::vector<BT<std::string>> flags; if (linkLanguage != "Swift") { std::string staticLibFlags; this->AppendFlags( staticLibFlags, this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS")); - if (!config.empty()) { - std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config; + if (!configUpper.empty()) { + std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + configUpper; this->AppendFlags(staticLibFlags, this->Makefile->GetSafeDefinition(name)); } @@ -1311,8 +1312,8 @@ std::vector<BT<std::string>> cmLocalGenerator::GetStaticLibraryFlags( std::string staticLibFlags; this->AppendFlags(staticLibFlags, target->GetSafeProperty("STATIC_LIBRARY_FLAGS")); - if (!config.empty()) { - std::string name = "STATIC_LIBRARY_FLAGS_" + config; + if (!configUpper.empty()) { + std::string name = "STATIC_LIBRARY_FLAGS_" + configUpper; this->AppendFlags(staticLibFlags, target->GetSafeProperty(name)); } @@ -1349,17 +1350,17 @@ void cmLocalGenerator::GetTargetFlags( std::vector<BT<std::string>>& linkFlags, std::string& frameworkPath, std::vector<BT<std::string>>& linkPath, cmGeneratorTarget* target) { - const std::string buildType = cmSystemTools::UpperCase(config); + const std::string configUpper = cmSystemTools::UpperCase(config); cmComputeLinkInformation* pcli = target->GetLinkInformation(config); const char* libraryLinkVariable = "CMAKE_SHARED_LINKER_FLAGS"; // default to shared library const std::string linkLanguage = - linkLineComputer->GetLinkerLanguage(target, buildType); + linkLineComputer->GetLinkerLanguage(target, config); switch (target->GetType()) { case cmStateEnums::STATIC_LIBRARY: - linkFlags = this->GetStaticLibraryFlags(buildType, linkLanguage, target); + linkFlags = this->GetStaticLibraryFlags(config, linkLanguage, target); if (pcli && dynamic_cast<cmLinkLineDeviceComputer*>(linkLineComputer)) { // Compute the required cuda device link libraries when // resolving cuda device symbols @@ -1375,8 +1376,8 @@ void cmLocalGenerator::GetTargetFlags( if (linkLanguage != "Swift") { sharedLibFlags = cmStrCat( this->Makefile->GetSafeDefinition(libraryLinkVariable), ' '); - if (!buildType.empty()) { - std::string build = cmStrCat(libraryLinkVariable, '_', buildType); + if (!configUpper.empty()) { + std::string build = cmStrCat(libraryLinkVariable, '_', configUpper); sharedLibFlags += this->Makefile->GetSafeDefinition(build); sharedLibFlags += " "; } @@ -1384,14 +1385,14 @@ void cmLocalGenerator::GetTargetFlags( !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW"))) { std::vector<cmSourceFile*> sources; - target->GetSourceFiles(sources, buildType); + target->GetSourceFiles(sources, config); std::string defFlag = this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); for (cmSourceFile* sf : sources) { if (sf->GetExtension() == "def") { sharedLibFlags += defFlag; - sharedLibFlags += this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(sf->ResolveFullPath()), SHELL); + sharedLibFlags += + this->ConvertToOutputFormat(sf->ResolveFullPath(), SHELL); sharedLibFlags += " "; } } @@ -1403,9 +1404,9 @@ void cmLocalGenerator::GetTargetFlags( sharedLibFlags += targetLinkFlags; sharedLibFlags += " "; } - if (!buildType.empty()) { + if (!configUpper.empty()) { targetLinkFlags = - target->GetProperty(cmStrCat("LINK_FLAGS_", buildType)); + target->GetProperty(cmStrCat("LINK_FLAGS_", configUpper)); if (targetLinkFlags) { sharedLibFlags += targetLinkFlags; sharedLibFlags += " "; @@ -1430,9 +1431,9 @@ void cmLocalGenerator::GetTargetFlags( if (linkLanguage != "Swift") { exeFlags = this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS"); exeFlags += " "; - if (!buildType.empty()) { + if (!configUpper.empty()) { exeFlags += this->Makefile->GetSafeDefinition( - cmStrCat("CMAKE_EXE_LINKER_FLAGS_", buildType)); + cmStrCat("CMAKE_EXE_LINKER_FLAGS_", configUpper)); exeFlags += " "; } if (linkLanguage.empty()) { @@ -1459,7 +1460,7 @@ void cmLocalGenerator::GetTargetFlags( } } - this->AddLanguageFlagsForLinking(flags, target, linkLanguage, buildType); + this->AddLanguageFlagsForLinking(flags, target, linkLanguage, config); if (pcli) { this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath, linkPath); @@ -1484,9 +1485,9 @@ void cmLocalGenerator::GetTargetFlags( exeFlags += targetLinkFlags; exeFlags += " "; } - if (!buildType.empty()) { + if (!configUpper.empty()) { targetLinkFlags = - target->GetProperty(cmStrCat("LINK_FLAGS_", buildType)); + target->GetProperty(cmStrCat("LINK_FLAGS_", configUpper)); if (targetLinkFlags) { exeFlags += targetLinkFlags; exeFlags += " "; @@ -2396,7 +2397,9 @@ void cmLocalGenerator::AddConfigVariableFlags(std::string& flags, void cmLocalGenerator::AppendFlags(std::string& flags, const std::string& newFlags) const { - if (!newFlags.empty()) { + bool allSpaces = std::all_of(newFlags.begin(), newFlags.end(), cmIsSpace); + + if (!newFlags.empty() && !allSpaces) { if (!flags.empty()) { flags += " "; } @@ -2429,11 +2432,9 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) } for (std::string const& config : configsList) { - const std::string buildType = cmSystemTools::UpperCase(config); - // FIXME: Refactor collection of sources to not evaluate object libraries. std::vector<cmSourceFile*> sources; - target->GetSourceFiles(sources, buildType); + target->GetSourceFiles(sources, config); for (const std::string& lang : { "C", "CXX", "OBJC", "OBJCXX" }) { auto langSources = std::count_if( @@ -2602,15 +2603,13 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); } - const std::string buildType = cmSystemTools::UpperCase(config); - std::string filename_base = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", target->GetName(), ".dir/Unity/"); // FIXME: Refactor collection of sources to not evaluate object libraries. std::vector<cmSourceFile*> sources; - target->GetSourceFiles(sources, buildType); + target->GetSourceFiles(sources, config); auto batchSizeString = target->GetProperty("UNITY_BUILD_BATCH_SIZE"); const size_t unityBatchSize = @@ -2914,11 +2913,11 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines, // command line without any escapes. However we still have to // get the '$' and '#' characters through WMake as '$$' and // '$#'. - for (const char* c = define.c_str(); *c; ++c) { - if (*c == '$' || *c == '#') { + for (char c : define) { + if (c == '$' || c == '#') { def += '$'; } - def += *c; + def += c; } } else { // Make the definition appear properly on the command line. Use @@ -2962,8 +2961,8 @@ const char* cmLocalGenerator::GetFeature(const std::string& feature, } cmStateSnapshot snp = this->StateSnapshot; while (snp.IsValid()) { - if (const char* value = snp.GetDirectory().GetProperty(featureName)) { - return value; + if (cmProp value = snp.GetDirectory().GetProperty(featureName)) { + return value->c_str(); } snp = snp.GetBuildsystemDirectoryParent(); } diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index be1dd0d..d1944a4 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -144,8 +144,9 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference( bool forceFullPaths) { if (forceFullPaths) { - return this->ConvertToOutputFormat(cmSystemTools::CollapseFullPath(path), - format); + return this->ConvertToOutputFormat( + cmSystemTools::CollapseFullPath(path, this->GetCurrentBinaryDirectory()), + format); } return this->ConvertToOutputFormat( this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), path), @@ -206,9 +207,8 @@ void cmLocalNinjaGenerator::WriteBuildFileTop() void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); - os << "# Project: " << this->GetProjectName() << std::endl - << "# Configurations: " << cmJoin(this->GetConfigNames(), ", ") - << std::endl; + os << "# Project: " << this->GetProjectName() << '\n' + << "# Configurations: " << cmJoin(this->GetConfigNames(), ", ") << '\n'; cmGlobalNinjaGenerator::WriteDivider(os); } @@ -235,8 +235,7 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) cmGlobalNinjaGenerator::WriteComment( os, "Minimal version of Ninja required by this file"); - os << "ninja_required_version = " << requiredVersion << std::endl - << std::endl; + os << "ninja_required_version = " << requiredVersion << "\n\n"; } void cmLocalNinjaGenerator::WriteNinjaConfigurationVariable( @@ -251,23 +250,22 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); - const char* jobpools = + cmProp jobpools = this->GetCMakeInstance()->GetState()->GetGlobalProperty("JOB_POOLS"); if (!jobpools) { - jobpools = this->GetMakefile()->GetDefinition("CMAKE_JOB_POOLS"); + jobpools = this->GetMakefile()->GetDef("CMAKE_JOB_POOLS"); } if (jobpools) { cmGlobalNinjaGenerator::WriteComment( os, "Pools defined by global property JOB_POOLS"); - std::vector<std::string> pools = cmExpandedList(jobpools); + std::vector<std::string> pools = cmExpandedList(*jobpools); for (std::string const& pool : pools) { const std::string::size_type eq = pool.find('='); unsigned int jobs; if (eq != std::string::npos && sscanf(pool.c_str() + eq, "=%u", &jobs) == 1) { - os << "pool " << pool.substr(0, eq) << std::endl; - os << " depth = " << jobs << std::endl; - os << std::endl; + os << "pool " << pool.substr(0, eq) << "\n depth = " << jobs + << "\n\n"; } else { cmSystemTools::Error("Invalid pool defined by property 'JOB_POOLS': " + pool); @@ -279,8 +277,7 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os) void cmLocalNinjaGenerator::WriteNinjaFilesInclusionConfig(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); - os << "# Include auxiliary files.\n" - << "\n"; + os << "# Include auxiliary files.\n\n"; cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator(); std::string const ninjaCommonFile = ng->NinjaOutputPath(cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE); @@ -293,8 +290,7 @@ void cmLocalNinjaGenerator::WriteNinjaFilesInclusionConfig(std::ostream& os) void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); - os << "# Include auxiliary files.\n" - << "\n"; + os << "# Include auxiliary files.\n\n"; cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator(); std::string const ninjaRulesFile = ng->NinjaOutputPath(cmGlobalNinjaGenerator::NINJA_RULES_FILE); @@ -307,14 +303,14 @@ void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os) void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); - os << "# Write statements declared in CMakeLists.txt:" << std::endl + os << "# Write statements declared in CMakeLists.txt:\n" << "# " << this->Makefile->GetDefinition("CMAKE_CURRENT_LIST_FILE") - << std::endl; + << '\n'; if (this->IsRootMakefile()) { - os << "# Which is the root file." << std::endl; + os << "# Which is the root file.\n"; } cmGlobalNinjaGenerator::WriteDivider(os); - os << std::endl; + os << '\n'; } void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target, @@ -632,10 +628,9 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements( std::string cmLocalNinjaGenerator::MakeCustomLauncher( cmCustomCommandGenerator const& ccg) { - const char* property_value = - this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM"); + cmProp property_value = this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM"); - if (!property_value || !*property_value) { + if (!property_value || property_value->empty()) { return std::string(); } @@ -657,7 +652,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( this->CreateRulePlaceholderExpander()); - std::string launcher = property_value; + std::string launcher = *property_value; rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars); if (!launcher.empty()) { launcher += " "; @@ -668,11 +663,11 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( void cmLocalNinjaGenerator::AdditionalCleanFiles(const std::string& config) { - if (const char* prop_value = + if (cmProp prop_value = this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { std::vector<std::string> cleanFiles; { - cmExpandList(cmGeneratorExpression::Evaluate(prop_value, this, config), + cmExpandList(cmGeneratorExpression::Evaluate(*prop_value, this, config), cleanFiles); } std::string const& binaryDir = this->GetCurrentBinaryDirectory(); diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 63c6680..99428bc 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -623,8 +623,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeVariables( this->MaybeConvertWatcomShellCommand(cmSystemTools::GetCMakeCommand()); if (cmakeShellCommand.empty()) { cmakeShellCommand = this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()), - cmOutputConverter::SHELL); + cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); } /* clang-format off */ @@ -648,16 +647,14 @@ void cmLocalUnixMakefileGenerator3::WriteMakeVariables( << "# The top-level source directory on which CMake was run.\n" << "CMAKE_SOURCE_DIR = " << this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(this->GetSourceDirectory()), - cmOutputConverter::SHELL) + this->GetSourceDirectory(), cmOutputConverter::SHELL) << "\n" << "\n"; makefileStream << "# The top-level build directory on which CMake was run.\n" << "CMAKE_BINARY_DIR = " << this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(this->GetBinaryDirectory()), - cmOutputConverter::SHELL) + this->GetBinaryDirectory(), cmOutputConverter::SHELL) << "\n" << "\n"; /* clang-format on */ @@ -728,6 +725,10 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsTop( ; /* clang-format on */ } else { + makefileStream << "# Command-line flag to silence nested $(MAKE).\n" + "$(VERBOSE)MAKESILENT = -s\n" + "\n"; + // Write special target to silence make output. This must be after // the default target in case VERBOSE is set (which changes the // name). The setting of CMAKE_VERBOSE_MAKEFILE to ON will cause a @@ -974,7 +975,8 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( // Expand rule variables referenced in the given launcher command. cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = target->GetName().c_str(); - vars.CMTargetType = cmState::GetTargetTypeName(target->GetType()); + vars.CMTargetType = + cmState::GetTargetTypeName(target->GetType()).c_str(); std::string output; const std::vector<std::string>& outputs = ccg.GetOutputs(); if (!outputs.empty()) { @@ -1053,10 +1055,9 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand( cleanfile += filename; } cleanfile += ".cmake"; - std::string cleanfilePath = cmSystemTools::CollapseFullPath(cleanfile); - cmsys::ofstream fout(cleanfilePath.c_str()); + cmsys::ofstream fout(cleanfile.c_str()); if (!fout) { - cmSystemTools::Error("Could not create " + cleanfilePath); + cmSystemTools::Error("Could not create " + cleanfile); } if (!files.empty()) { fout << "file(REMOVE_RECURSE\n"; @@ -1098,10 +1099,10 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( { std::vector<std::string> cleanFiles; // Look for additional files registered for cleaning in this directory. - if (const char* prop_value = + if (cmProp prop_value = this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { cmExpandList(cmGeneratorExpression::Evaluate( - prop_value, this, + *prop_value, this, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), cleanFiles); } @@ -1116,10 +1117,9 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( cmStrCat(currentBinaryDir, "/CMakeFiles/cmake_directory_clean.cmake"); // Write clean script { - std::string cleanfilePath = cmSystemTools::CollapseFullPath(cleanfile); - cmsys::ofstream fout(cleanfilePath.c_str()); + cmsys::ofstream fout(cleanfile.c_str()); if (!fout) { - cmSystemTools::Error("Could not create " + cleanfilePath); + cmSystemTools::Error("Could not create " + cleanfile); return; } fout << "file(REMOVE_RECURSE\n"; @@ -1190,9 +1190,8 @@ void cmLocalUnixMakefileGenerator3::AppendEcho( color_name); if (progress) { cmd += "--progress-dir="; - cmd += this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(progress->Dir), - cmOutputConverter::SHELL); + cmd += this->ConvertToOutputFormat(progress->Dir, + cmOutputConverter::SHELL); cmd += " "; cmd += "--progress-num="; cmd += progress->Arg; @@ -1327,10 +1326,9 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( int result; if (!ftc->Compare(internalDependFile, tgtInfo, &result) || result < 0) { if (verbose) { - std::ostringstream msg; - msg << "Dependee \"" << tgtInfo << "\" is newer than depender \"" - << internalDependFile << "\"." << std::endl; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout(cmStrCat("Dependee \"", tgtInfo, + "\" is newer than depender \"", + internalDependFile, "\".\n")); } needRescanDependInfo = true; } @@ -1347,10 +1345,9 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( if (!ftc->Compare(internalDependFile, dirInfoFile, &result) || result < 0) { if (verbose) { - std::ostringstream msg; - msg << "Dependee \"" << dirInfoFile << "\" is newer than depender \"" - << internalDependFile << "\"." << std::endl; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout(cmStrCat("Dependee \"", dirInfoFile, + "\" is newer than depender \"", + internalDependFile, "\".\n")); } needRescanDirInfo = true; } @@ -1516,11 +1513,9 @@ void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose) if (cmSystemTools::FileExists(dependee) && !cmSystemTools::FileExists(depender)) { if (verbose) { - std::ostringstream msg; - msg << "Deleting primary custom command output \"" << dependee - << "\" because another output \"" << depender - << "\" does not exist." << std::endl; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout(cmStrCat( + "Deleting primary custom command output \"", dependee, + "\" because another output \"", depender, "\" does not exist.\n")); } cmSystemTools::RemoveFile(dependee); } @@ -1632,15 +1627,14 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( { std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; - progCmd << this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(progressDir), cmOutputConverter::SHELL); + progCmd << this->ConvertToOutputFormat(progressDir, + cmOutputConverter::SHELL); std::string progressFile = "/CMakeFiles/progress.marks"; std::string progressFileNameFull = this->ConvertToFullPath(progressFile); progCmd << " " - << this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(progressFileNameFull), - cmOutputConverter::SHELL); + << this->ConvertToOutputFormat(progressFileNameFull, + cmOutputConverter::SHELL); commands.push_back(progCmd.str()); } std::string mf2Dir = "CMakeFiles/Makefile2"; @@ -1650,8 +1644,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( { std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0 - progCmd << this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(progressDir), cmOutputConverter::SHELL); + progCmd << this->ConvertToOutputFormat(progressDir, + cmOutputConverter::SHELL); progCmd << " 0"; commands.push_back(progCmd.str()); } @@ -1784,7 +1778,7 @@ private: const std::string& testDir) { // First check if the test directory "starts with" the base directory: - if (testDir.find(baseDir) != 0) { + if (!cmHasPrefix(testDir, baseDir)) { return false; } // If it does, then check that it's either the same string, or that the @@ -1895,9 +1889,9 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( // Store include transform rule properties. Write the directory // rules first because they may be overridden by later target rules. std::vector<std::string> transformRules; - if (const char* xform = + if (cmProp xform = this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) { - cmExpandList(xform, transformRules); + cmExpandList(*xform, transformRules); } if (const char* xform = target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) { @@ -1925,7 +1919,7 @@ std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall( { // Call make on the given file. std::string cmd = cmStrCat( - "$(MAKE) -f ", + "$(MAKE) $(MAKESILENT) -f ", this->ConvertToOutputFormat(makefile, cmOutputConverter::SHELL), ' '); cmGlobalUnixMakefileGenerator3* gg = @@ -1968,7 +1962,7 @@ std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall( void cmLocalUnixMakefileGenerator3::WriteDivider(std::ostream& os) { os << "#======================================" - << "=======================================\n"; + "=======================================\n"; } void cmLocalUnixMakefileGenerator3::WriteCMakeArgument(std::ostream& os, @@ -1976,7 +1970,7 @@ void cmLocalUnixMakefileGenerator3::WriteCMakeArgument(std::ostream& os, { // Write the given string to the stream with escaping to get it back // into CMake through the lexical scanner. - os << "\""; + os << '"'; for (char c : s) { if (c == '\\') { os << "\\\\"; @@ -1986,7 +1980,7 @@ void cmLocalUnixMakefileGenerator3::WriteCMakeArgument(std::ostream& os, os << c; } } - os << "\""; + os << '"'; } std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath( diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 9aa3991..9148b27 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLocalVisualStudio7Generator.h" +#include <cm/memory> + #include <windows.h> #include <ctype.h> // for isspace @@ -18,6 +20,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLParser.h" #include "cmake.h" @@ -52,14 +55,11 @@ extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[]; cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator( cmGlobalGenerator* gg, cmMakefile* mf) : cmLocalVisualStudioGenerator(gg, mf) + , Internal(cm::make_unique<cmLocalVisualStudio7GeneratorInternals>(this)) { - this->Internal = new cmLocalVisualStudio7GeneratorInternals(this); } -cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator() -{ - delete this->Internal; -} +cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator() = default; void cmLocalVisualStudio7Generator::AddHelperCommands() { @@ -226,7 +226,6 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() std::string makefileIn = cmStrCat(this->GetCurrentSourceDirectory(), "/CMakeLists.txt"); - makefileIn = cmSystemTools::CollapseFullPath(makefileIn); if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) { if (file->GetCustomCommand()) { return file; @@ -257,8 +256,7 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() "--check-stamp-file", stampName }); std::string comment = cmStrCat("Building Custom Rule ", makefileIn); const char* no_working_directory = nullptr; - std::string fullpathStampName = cmSystemTools::CollapseFullPath(stampName); - this->AddCustomCommandToOutput(fullpathStampName, listFiles, makefileIn, + this->AddCustomCommandToOutput(stampName, listFiles, makefileIn, commandLines, comment.c_str(), no_working_directory, true, false); if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) { @@ -1006,9 +1004,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( } } std::string libflags; - this->GetStaticLibraryFlags(libflags, configTypeUpper, - target->GetLinkerLanguage(configName), - target); + this->GetStaticLibraryFlags( + libflags, configName, target->GetLinkerLanguage(configName), target); if (!libflags.empty()) { fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n"; } @@ -1511,10 +1508,9 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( if (const char* deps = sf.GetProperty("OBJECT_DEPENDS")) { std::vector<std::string> depends = cmExpandedList(deps); const char* sep = ""; - for (std::vector<std::string>::iterator j = depends.begin(); - j != depends.end(); ++j) { + for (const std::string& d : depends) { fc.AdditionalDeps += sep; - fc.AdditionalDeps += lg->ConvertToXMLOutputPath(*j); + fc.AdditionalDeps += lg->ConvertToXMLOutputPath(d); sep = ";"; needfc = true; } @@ -2010,7 +2006,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFooter( fout << "\t<Globals>\n"; for (std::string const& key : target->GetPropertyKeys()) { - if (key.find("VS_GLOBAL_") == 0) { + if (cmHasLiteralPrefix(key, "VS_GLOBAL_")) { std::string name = key.substr(10); if (!name.empty()) { /* clang-format off */ diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 745766c..8b9b8ad 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <string> #include <vector> @@ -48,6 +49,10 @@ public: virtual ~cmLocalVisualStudio7Generator(); + cmLocalVisualStudio7Generator(const cmLocalVisualStudio7Generator&) = delete; + const cmLocalVisualStudio7Generator& operator=( + const cmLocalVisualStudio7Generator&) = delete; + void AddHelperCommands() override; /** @@ -144,7 +149,7 @@ private: bool FortranProject; bool WindowsCEProject; - cmLocalVisualStudio7GeneratorInternals* Internal; + std::unique_ptr<cmLocalVisualStudio7GeneratorInternals> Internal; }; #endif diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 8d50898..7267976 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -154,8 +154,7 @@ std::string cmLocalVisualStudioGenerator::ConstructScript( script += newline; newline = newline_text; script += "cd "; - script += this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(workingDirectory), SHELL); + script += this->ConvertToOutputFormat(workingDirectory, SHELL); script += check_error; // Change the working drive. diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx index 6cbed36..53112e0 100644 --- a/Source/cmMachO.cxx +++ b/Source/cmMachO.cxx @@ -79,14 +79,14 @@ public: // A load_command and its associated data struct RawLoadCommand { - uint32_t type(const cmMachOHeaderAndLoadCommands* m) const + uint32_t type(const cmMachOHeaderAndLoadCommands& m) const { if (this->LoadCommand.size() < sizeof(load_command)) { return 0; } const load_command* cmd = reinterpret_cast<const load_command*>(&this->LoadCommand[0]); - return m->swap(cmd->cmd); + return m.swap(cmd->cmd); } std::vector<char> LoadCommand; }; @@ -186,8 +186,11 @@ class cmMachOInternal { public: cmMachOInternal(const char* fname); + cmMachOInternal(const cmMachOInternal&) = delete; ~cmMachOInternal(); + cmMachOInternal& operator=(const cmMachOInternal&) = delete; + // read a Mach-O file bool read_mach_o(uint32_t file_offset); @@ -202,7 +205,7 @@ public: std::string ErrorMessage; // the list of Mach-O's - std::vector<cmMachOHeaderAndLoadCommands*> MachOList; + std::vector<std::unique_ptr<cmMachOHeaderAndLoadCommands>> MachOList; }; cmMachOInternal::cmMachOInternal(const char* fname) @@ -260,12 +263,7 @@ cmMachOInternal::cmMachOInternal(const char* fname) } } -cmMachOInternal::~cmMachOInternal() -{ - for (auto& i : this->MachOList) { - delete i; - } -} +cmMachOInternal::~cmMachOInternal() = default; bool cmMachOInternal::read_mach_o(uint32_t file_offset) { @@ -280,25 +278,25 @@ bool cmMachOInternal::read_mach_o(uint32_t file_offset) return false; } - cmMachOHeaderAndLoadCommands* f = nullptr; + std::unique_ptr<cmMachOHeaderAndLoadCommands> f; if (magic == MH_CIGAM || magic == MH_MAGIC) { bool swap = false; if (magic == MH_CIGAM) { swap = true; } - f = new cmMachOHeaderAndLoadCommandsImpl<mach_header>(swap); + f = cm::make_unique<cmMachOHeaderAndLoadCommandsImpl<mach_header>>(swap); } else if (magic == MH_CIGAM_64 || magic == MH_MAGIC_64) { bool swap = false; if (magic == MH_CIGAM_64) { swap = true; } - f = new cmMachOHeaderAndLoadCommandsImpl<mach_header_64>(swap); + f = + cm::make_unique<cmMachOHeaderAndLoadCommandsImpl<mach_header_64>>(swap); } if (f && f->read_mach_o(this->Fin)) { - this->MachOList.push_back(f); + this->MachOList.push_back(std::move(f)); } else { - delete f; this->ErrorMessage = "Failed to read Mach-O header."; return false; } @@ -333,11 +331,12 @@ bool cmMachO::GetInstallName(std::string& install_name) } // grab the first Mach-O and get the install name from that one - cmMachOHeaderAndLoadCommands* macho = this->Internal->MachOList[0]; + std::unique_ptr<cmMachOHeaderAndLoadCommands>& macho = + this->Internal->MachOList[0]; for (size_t i = 0; i < macho->load_commands().size(); i++) { const cmMachOHeaderAndLoadCommands::RawLoadCommand& cmd = macho->load_commands()[i]; - uint32_t lc_cmd = cmd.type(macho); + uint32_t lc_cmd = cmd.type(*macho); if (lc_cmd == LC_ID_DYLIB || lc_cmd == LC_LOAD_WEAK_DYLIB || lc_cmd == LC_LOAD_DYLIB) { if (sizeof(dylib_command) < cmd.LoadCommand.size()) { diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 18689fa..69f316d 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -61,6 +61,7 @@ #include "cmake.h" #ifndef CMAKE_BOOTSTRAP +# include "cmMakefileProfilingData.h" # include "cmVariableWatch.h" #endif @@ -373,19 +374,30 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const class cmMakefileCall { public: - cmMakefileCall(cmMakefile* mf, cmCommandContext const& cc, + cmMakefileCall(cmMakefile* mf, cmListFileFunction const& lff, cmExecutionStatus& status) : Makefile(mf) { cmListFileContext const& lfc = cmListFileContext::FromCommandContext( - cc, this->Makefile->StateSnapshot.GetExecutionListFile()); + lff, this->Makefile->StateSnapshot.GetExecutionListFile()); this->Makefile->Backtrace = this->Makefile->Backtrace.Push(lfc); ++this->Makefile->RecursionDepth; this->Makefile->ExecutionStatusStack.push_back(&status); +#if !defined(CMAKE_BOOTSTRAP) + if (this->Makefile->GetCMakeInstance()->IsProfilingEnabled()) { + this->Makefile->GetCMakeInstance()->GetProfilingOutput().StartEntry(lff, + lfc); + } +#endif } ~cmMakefileCall() { +#if !defined(CMAKE_BOOTSTRAP) + if (this->Makefile->GetCMakeInstance()->IsProfilingEnabled()) { + this->Makefile->GetCMakeInstance()->GetProfilingOutput().StopEntry(); + } +#endif this->Makefile->ExecutionStatusStack.pop_back(); --this->Makefile->RecursionDepth; this->Makefile->Backtrace = this->Makefile->Backtrace.Pop(); @@ -685,6 +697,27 @@ bool cmMakefile::ReadListFile(const std::string& filename) return true; } +bool cmMakefile::ReadListFileAsString(const std::string& content, + const std::string& virtualFileName) +{ + std::string filenametoread = cmSystemTools::CollapseFullPath( + virtualFileName, this->GetCurrentSourceDirectory()); + + ListFileScope scope(this, filenametoread); + + cmListFile listFile; + if (!listFile.ParseString(content.c_str(), virtualFileName.c_str(), + this->GetMessenger(), this->Backtrace)) { + return false; + } + + this->ReadListFile(listFile, filenametoread); + if (cmSystemTools::GetFatalErrorOccured()) { + scope.Quiet(); + } + return true; +} + void cmMakefile::ReadListFile(cmListFile const& listFile, std::string const& filenametoread) { @@ -1358,9 +1391,9 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) const char* define = def.c_str() + 2; if (remove) { - if (const char* cdefs = this->GetProperty("COMPILE_DEFINITIONS")) { + if (cmProp cdefs = this->GetProperty("COMPILE_DEFINITIONS")) { // Expand the list. - std::vector<std::string> defs = cmExpandedList(cdefs); + std::vector<std::string> defs = cmExpandedList(*cdefs); // Recompose the list without the definition. auto defEnd = std::remove(defs.begin(), defs.end(), define); @@ -1389,29 +1422,32 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent) // Include transform property. There is no per-config version. { const char* prop = "IMPLICIT_DEPENDS_INCLUDE_TRANSFORM"; - this->SetProperty(prop, parent->GetProperty(prop)); + cmProp p = parent->GetProperty(prop); + this->SetProperty(prop, p ? p->c_str() : nullptr); } // compile definitions property and per-config versions cmPolicies::PolicyStatus polSt = this->GetPolicyStatus(cmPolicies::CMP0043); if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) { - this->SetProperty("COMPILE_DEFINITIONS", - parent->GetProperty("COMPILE_DEFINITIONS")); + cmProp p = parent->GetProperty("COMPILE_DEFINITIONS"); + this->SetProperty("COMPILE_DEFINITIONS", p ? p->c_str() : nullptr); std::vector<std::string> configs; this->GetConfigurations(configs); for (std::string const& config : configs) { std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config)); - const char* prop = parent->GetProperty(defPropName); - this->SetProperty(defPropName, prop); + cmProp prop = parent->GetProperty(defPropName); + this->SetProperty(defPropName, prop ? prop->c_str() : nullptr); } } // labels - this->SetProperty("LABELS", parent->GetProperty("LABELS")); + cmProp p = parent->GetProperty("LABELS"); + this->SetProperty("LABELS", p ? p->c_str() : nullptr); // link libraries - this->SetProperty("LINK_LIBRARIES", parent->GetProperty("LINK_LIBRARIES")); + p = parent->GetProperty("LINK_LIBRARIES"); + this->SetProperty("LINK_LIBRARIES", p ? p->c_str() : nullptr); // the initial project name this->StateSnapshot.SetProjectName(parent->StateSnapshot.GetProjectName()); @@ -1973,8 +2009,8 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target) default:; } - if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { - std::vector<std::string> linkLibs = cmExpandedList(linkLibsProp); + if (cmProp linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { + std::vector<std::string> linkLibs = cmExpandedList(*linkLibsProp); for (auto j = linkLibs.begin(); j != linkLibs.end(); ++j) { std::string libraryName = *j; @@ -2418,14 +2454,14 @@ void cmMakefile::ExpandVariablesCMP0019() } std::ostringstream w; - const char* includeDirs = this->GetProperty("INCLUDE_DIRECTORIES"); - if (mightExpandVariablesCMP0019(includeDirs)) { - std::string dirs = includeDirs; + cmProp includeDirs = this->GetProperty("INCLUDE_DIRECTORIES"); + if (includeDirs && mightExpandVariablesCMP0019(includeDirs->c_str())) { + std::string dirs = *includeDirs; this->ExpandVariablesInString(dirs, true, true); - if (pol == cmPolicies::WARN && dirs != includeDirs) { + if (pol == cmPolicies::WARN && dirs != *includeDirs) { /* clang-format off */ w << "Evaluated directory INCLUDE_DIRECTORIES\n" - << " " << includeDirs << "\n" + << " " << *includeDirs << "\n" << "as\n" << " " << dirs << "\n"; /* clang-format on */ @@ -2441,13 +2477,13 @@ void cmMakefile::ExpandVariablesCMP0019() continue; } includeDirs = t.GetProperty("INCLUDE_DIRECTORIES"); - if (mightExpandVariablesCMP0019(includeDirs)) { - std::string dirs = includeDirs; + if (includeDirs && mightExpandVariablesCMP0019(includeDirs->c_str())) { + std::string dirs = *includeDirs; this->ExpandVariablesInString(dirs, true, true); - if (pol == cmPolicies::WARN && dirs != includeDirs) { + if (pol == cmPolicies::WARN && dirs != *includeDirs) { /* clang-format off */ w << "Evaluated target " << t.GetName() << " INCLUDE_DIRECTORIES\n" - << " " << includeDirs << "\n" + << " " << *includeDirs << "\n" << "as\n" << " " << dirs << "\n"; /* clang-format on */ @@ -2456,10 +2492,10 @@ void cmMakefile::ExpandVariablesCMP0019() } } - if (const char* linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) { - if (mightExpandVariablesCMP0019(linkDirsProp)) { - std::string d = linkDirsProp; - std::string orig = linkDirsProp; + if (cmProp linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) { + if (mightExpandVariablesCMP0019(linkDirsProp->c_str())) { + std::string d = *linkDirsProp; + const std::string orig = d; this->ExpandVariablesInString(d, true, true); if (pol == cmPolicies::WARN && d != orig) { /* clang-format off */ @@ -2472,8 +2508,8 @@ void cmMakefile::ExpandVariablesCMP0019() } } - if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { - std::vector<std::string> linkLibs = cmExpandedList(linkLibsProp); + if (cmProp linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { + std::vector<std::string> linkLibs = cmExpandedList(*linkLibsProp); for (auto l = linkLibs.begin(); l != linkLibs.end(); ++l) { std::string libName = *l; @@ -2485,7 +2521,7 @@ void cmMakefile::ExpandVariablesCMP0019() libName = *l; } if (mightExpandVariablesCMP0019(libName.c_str())) { - std::string orig = libName; + const std::string orig = libName; this->ExpandVariablesInString(libName, true, true); if (pol == cmPolicies::WARN && libName != orig) { /* clang-format off */ @@ -2589,7 +2625,7 @@ cmMakefile::AppleSDK cmMakefile::GetAppleSDKType() const }; for (auto const& entry : sdkDatabase) { - if (sdkRoot.find(entry.name) == 0 || + if (cmHasPrefix(sdkRoot, entry.name) || sdkRoot.find(std::string("/") + entry.name) != std::string::npos) { return entry.sdk; } @@ -2998,7 +3034,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( openstack.pop_back(); result.append(last, in - last); std::string const& lookup = result.substr(var.loc); - const char* value = nullptr; + cmProp value = nullptr; std::string varresult; std::string svalue; switch (var.domain) { @@ -3006,12 +3042,12 @@ MessageType cmMakefile::ExpandVariablesInStringNew( if (filename && lookup == lineVar) { varresult = std::to_string(line); } else { - value = this->GetDefinition(lookup); + value = this->GetDef(lookup); } break; case ENVIRONMENT: if (cmSystemTools::GetEnv(lookup, svalue)) { - value = svalue.c_str(); + value = &svalue; } break; case CACHE: @@ -3021,9 +3057,9 @@ MessageType cmMakefile::ExpandVariablesInStringNew( // Get the string we're meant to append to. if (value) { if (escapeQuotes) { - varresult = cmEscapeQuotes(value); + varresult = cmEscapeQuotes(*value); } else { - varresult = value; + varresult = *value; } } else if (!this->SuppressSideEffects) { this->MaybeWarnUninitialized(lookup, filename); @@ -4051,7 +4087,7 @@ void cmMakefile::AppendProperty(const std::string& prop, this->Backtrace); } -const char* cmMakefile::GetProperty(const std::string& prop) const +cmProp cmMakefile::GetProperty(const std::string& prop) const { // Check for computed properties. static std::string output; @@ -4064,20 +4100,21 @@ const char* cmMakefile::GetProperty(const std::string& prop) const return pair.first; }); output = cmJoin(keys, ";"); - return output.c_str(); + return &output; } return this->StateSnapshot.GetDirectory().GetProperty(prop); } -const char* cmMakefile::GetProperty(const std::string& prop, bool chain) const +cmProp cmMakefile::GetProperty(const std::string& prop, bool chain) const { return this->StateSnapshot.GetDirectory().GetProperty(prop, chain); } bool cmMakefile::GetPropertyAsBool(const std::string& prop) const { - return cmIsOn(this->GetProperty(prop)); + cmProp p = this->GetProperty(prop); + return p && cmIsOn(*p); } std::vector<std::string> cmMakefile::GetPropertyKeys() const @@ -4129,8 +4166,8 @@ void cmMakefile::GetTests(const std::string& config, void cmMakefile::AddCMakeDependFilesFromUser() { std::vector<std::string> deps; - if (const char* deps_str = this->GetProperty("CMAKE_CONFIGURE_DEPENDS")) { - cmExpandList(deps_str, deps); + if (cmProp deps_str = this->GetProperty("CMAKE_CONFIGURE_DEPENDS")) { + cmExpandList(*deps_str, deps); } for (std::string const& dep : deps) { if (cmSystemTools::FileIsFullPath(dep)) { @@ -4498,7 +4535,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::CMP0069 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0071 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. @@ -4763,8 +4800,8 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, const std::string& feature, std::string const& lang) const { - const char* defaultCStandard = - this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); + cmProp defaultCStandard = + this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); if (!defaultCStandard) { this->IssueMessage( MessageType::INTERNAL_ERROR, @@ -4775,11 +4812,11 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, return true; } if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), - cmStrCmp(defaultCStandard)) == cm::cend(C_STANDARDS)) { + cmStrCmp(*defaultCStandard)) == cm::cend(C_STANDARDS)) { const std::string e = cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an " "invalid value: \"", - defaultCStandard, "\"."); + *defaultCStandard, "\"."); this->IssueMessage(MessageType::INTERNAL_ERROR, e); return false; } @@ -4790,24 +4827,23 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11); - const char* existingCStandard = - target->GetProperty(cmStrCat(lang, "_STANDARD")); + cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD")); if (!existingCStandard) { existingCStandard = defaultCStandard; } if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), - cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) { + cmStrCmp(*existingCStandard)) == cm::cend(C_STANDARDS)) { const std::string e = cmStrCat( "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", existingCStandard, "\"."); + "\" contained an invalid value: \"", *existingCStandard, "\"."); this->IssueMessage(MessageType::FATAL_ERROR, e); return false; } const char* const* existingCIt = existingCStandard ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), - cmStrCmp(existingCStandard)) + cmStrCmp(*existingCStandard)) : cm::cend(C_STANDARDS); if (needC11 && existingCStandard && @@ -4858,8 +4894,8 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, const std::string& feature, std::string const& lang) const { - const char* defaultCxxStandard = - this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); + cmProp defaultCxxStandard = + this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); if (!defaultCxxStandard) { this->IssueMessage( MessageType::INTERNAL_ERROR, @@ -4870,10 +4906,10 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, return true; } if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), - cmStrCmp(defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) { + cmStrCmp(*defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) { const std::string e = cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ", - "invalid value: \"", defaultCxxStandard, "\"."); + "invalid value: \"", *defaultCxxStandard, "\"."); this->IssueMessage(MessageType::INTERNAL_ERROR, e); return false; } @@ -4886,7 +4922,7 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14, needCxx17, needCxx20); - const char* existingCxxStandard = + cmProp existingCxxStandard = target->GetProperty(cmStrCat(lang, "_STANDARD")); if (!existingCxxStandard) { existingCxxStandard = defaultCxxStandard; @@ -4894,11 +4930,11 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, const char* const* existingCxxLevel = std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), - cmStrCmp(existingCxxStandard)); + cmStrCmp(*existingCxxStandard)); if (existingCxxLevel == cm::cend(CXX_STANDARDS)) { const std::string e = cmStrCat( "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", existingCxxStandard, "\"."); + "\" contained an invalid value: \"", *existingCxxStandard, "\"."); this->IssueMessage(MessageType::FATAL_ERROR, e); return false; } @@ -4963,12 +4999,12 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14, needCxx17, needCxx20); - const char* existingCxxStandard = + cmProp existingCxxStandard = target->GetProperty(cmStrCat(lang, "_STANDARD")); if (existingCxxStandard == nullptr) { - const char* defaultCxxStandard = - this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); - if (defaultCxxStandard && *defaultCxxStandard) { + cmProp defaultCxxStandard = + this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); + if (defaultCxxStandard && !defaultCxxStandard->empty()) { existingCxxStandard = defaultCxxStandard; } } @@ -4976,11 +5012,11 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, if (existingCxxStandard) { existingCxxLevel = std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), - cmStrCmp(existingCxxStandard)); + cmStrCmp(*existingCxxStandard)); if (existingCxxLevel == cm::cend(CXX_STANDARDS)) { const std::string e = cmStrCat( "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", existingCxxStandard, "\"."); + "\" contained an invalid value: \"", *existingCxxStandard, "\"."); if (error) { *error = e; } else { @@ -5016,8 +5052,8 @@ bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target, const std::string& feature, std::string const& lang) const { - const char* defaultCudaStandard = - this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); + cmProp defaultCudaStandard = + this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); if (!defaultCudaStandard) { this->IssueMessage( MessageType::INTERNAL_ERROR, @@ -5028,11 +5064,11 @@ bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target, return true; } if (std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), - cmStrCmp(defaultCudaStandard)) == + cmStrCmp(*defaultCudaStandard)) == cm::cend(CUDA_STANDARDS)) { const std::string e = cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ", - "invalid value: \"", defaultCudaStandard, "\"."); + "invalid value: \"", *defaultCudaStandard, "\"."); this->IssueMessage(MessageType::INTERNAL_ERROR, e); return false; } @@ -5045,7 +5081,7 @@ bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target, this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11, needCuda14, needCuda17, needCuda20); - const char* existingCudaStandard = + cmProp existingCudaStandard = target->GetProperty(cmStrCat(lang, "_STANDARD")); if (!existingCudaStandard) { existingCudaStandard = defaultCudaStandard; @@ -5053,11 +5089,11 @@ bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target, const char* const* existingCudaLevel = std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), - cmStrCmp(existingCudaStandard)); + cmStrCmp(*existingCudaStandard)); if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) { const std::string e = cmStrCat( "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", existingCudaStandard, "\"."); + "\" contained an invalid value: \"", *existingCudaStandard, "\"."); this->IssueMessage(MessageType::FATAL_ERROR, e); return false; } @@ -5122,12 +5158,12 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target, this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11, needCuda14, needCuda17, needCuda20); - const char* existingCudaStandard = + cmProp existingCudaStandard = target->GetProperty(cmStrCat(lang, "_STANDARD")); if (existingCudaStandard == nullptr) { - const char* defaultCudaStandard = - this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); - if (defaultCudaStandard && *defaultCudaStandard) { + cmProp defaultCudaStandard = + this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); + if (defaultCudaStandard && !defaultCudaStandard->empty()) { existingCudaStandard = defaultCudaStandard; } } @@ -5135,11 +5171,11 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target, if (existingCudaStandard) { existingCudaLevel = std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), - cmStrCmp(existingCudaStandard)); + cmStrCmp(*existingCudaStandard)); if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) { const std::string e = cmStrCat( "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", existingCudaStandard, "\"."); + "\" contained an invalid value: \"", *existingCudaStandard, "\"."); if (error) { *error = e; } else { @@ -5203,21 +5239,20 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11); - const char* existingCStandard = - target->GetProperty(cmStrCat(lang, "_STANDARD")); + cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD")); if (existingCStandard == nullptr) { - const char* defaultCStandard = - this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); - if (defaultCStandard && *defaultCStandard) { + cmProp defaultCStandard = + this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); + if (defaultCStandard && !defaultCStandard->empty()) { existingCStandard = defaultCStandard; } } if (existingCStandard) { if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), - cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) { + cmStrCmp(*existingCStandard)) == cm::cend(C_STANDARDS)) { const std::string e = cmStrCat( "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", existingCStandard, "\"."); + "\" contained an invalid value: \"", *existingCStandard, "\"."); if (error) { *error = e; } else { @@ -5229,7 +5264,7 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, } const char* const* existingCIt = existingCStandard ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), - cmStrCmp(existingCStandard)) + cmStrCmp(*existingCStandard)) : cm::cend(C_STANDARDS); bool setC90 = needC90 && !existingCStandard; diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index d918abe..9a7eff9 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -58,6 +58,8 @@ class cmTestGenerator; class cmVariableWatch; class cmake; +using cmProp = const std::string*; + /** Flag if byproducts shall also be considered. */ enum class cmSourceOutputKind { @@ -117,6 +119,9 @@ public: bool ReadListFile(const std::string& filename); + bool ReadListFileAsString(const std::string& content, + const std::string& virtualFileName); + bool ReadDependentFile(const std::string& filename, bool noPolicyScope = true); @@ -314,6 +319,12 @@ public: void AddCacheDefinition(const std::string& name, const char* value, const char* doc, cmStateEnums::CacheEntryType type, bool force = false); + void AddCacheDefinition(const std::string& name, const std::string& value, + const char* doc, cmStateEnums::CacheEntryType type, + bool force = false) + { + AddCacheDefinition(name, value.c_str(), doc, type, force); + } /** * Remove a variable definition from the build. This is not valid @@ -408,7 +419,8 @@ public: } const char* GetIncludeRegularExpression() const { - return this->GetProperty("INCLUDE_REGULAR_EXPRESSION"); + cmProp p = this->GetProperty("INCLUDE_REGULAR_EXPRESSION"); + return p ? p->c_str() : nullptr; } /** @@ -786,8 +798,8 @@ public: void SetProperty(const std::string& prop, const char* value); void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); - const char* GetProperty(const std::string& prop) const; - const char* GetProperty(const std::string& prop, bool chain) const; + cmProp GetProperty(const std::string& prop) const; + cmProp GetProperty(const std::string& prop, bool chain) const; bool GetPropertyAsBool(const std::string& prop) const; std::vector<std::string> GetPropertyKeys() const; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 0471a45..4fe10ad 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -547,7 +547,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); vars.CMTargetType = - cmState::GetTargetTypeName(this->GeneratorTarget->GetType()); + cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str(); vars.Language = linkLanguage.c_str(); vars.Objects = buildObjs.c_str(); std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index d3f3a4f..372b43b 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -141,8 +141,7 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() std::string extraFlags; this->LocalGenerator->GetStaticLibraryFlags( - extraFlags, cmSystemTools::UpperCase(this->GetConfigName()), linkLanguage, - this->GeneratorTarget); + extraFlags, this->GetConfigName(), linkLanguage, this->GeneratorTarget); this->WriteLibraryRules(linkRuleVar, extraFlags, false); } @@ -756,7 +755,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); vars.CMTargetType = - cmState::GetTargetTypeName(this->GeneratorTarget->GetType()); + cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str(); vars.Language = linkLanguage.c_str(); vars.AIXExports = aixExports.c_str(); vars.Objects = buildObjs.c_str(); diff --git a/Source/cmMakefileProfilingData.cxx b/Source/cmMakefileProfilingData.cxx new file mode 100644 index 0000000..adf4eee --- /dev/null +++ b/Source/cmMakefileProfilingData.cxx @@ -0,0 +1,114 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmMakefileProfilingData.h" + +#include <chrono> +#include <stdexcept> +#include <vector> + +#include "cmsys/FStream.hxx" +#include "cmsys/SystemInformation.hxx" + +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" + +#include "cmListFileCache.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +cmMakefileProfilingData::cmMakefileProfilingData( + const std::string& profileStream) +{ + std::ios::openmode omode = std::ios::out | std::ios::trunc; + this->ProfileStream.open(profileStream.c_str(), omode); + Json::StreamWriterBuilder wbuilder; + this->JsonWriter = + std::unique_ptr<Json::StreamWriter>(wbuilder.newStreamWriter()); + if (!this->ProfileStream.good()) { + throw std::runtime_error(std::string("Unable to open: ") + profileStream); + } + + this->ProfileStream << "["; +}; + +cmMakefileProfilingData::~cmMakefileProfilingData() noexcept +{ + if (this->ProfileStream.good()) { + try { + this->ProfileStream << "]"; + this->ProfileStream.close(); + } catch (...) { + cmSystemTools::Error("Error writing profiling output!"); + } + } +} + +void cmMakefileProfilingData::StartEntry(const cmListFileFunction& lff, + cmListFileContext const& lfc) +{ + /* Do not try again if we previously failed to write to output. */ + if (!this->ProfileStream.good()) { + return; + } + + try { + if (this->ProfileStream.tellp() > 1) { + this->ProfileStream << ","; + } + cmsys::SystemInformation info; + Json::Value v; + v["ph"] = "B"; + v["name"] = lff.Name.Original; + v["cat"] = "cmake"; + v["ts"] = Json::Value::UInt64( + std::chrono::duration_cast<std::chrono::microseconds>( + std::chrono::steady_clock::now().time_since_epoch()) + .count()); + v["pid"] = static_cast<int>(info.GetProcessId()); + v["tid"] = 0; + Json::Value argsValue; + if (!lff.Arguments.empty()) { + std::string args; + for (const auto& a : lff.Arguments) { + args += (args.empty() ? "" : " ") + a.Value; + } + argsValue["functionArgs"] = args; + } + argsValue["location"] = lfc.FilePath + ":" + std::to_string(lfc.Line); + v["args"] = argsValue; + + this->JsonWriter->write(v, &this->ProfileStream); + } catch (std::ios_base::failure& fail) { + cmSystemTools::Error( + cmStrCat("Failed to write to profiling output: ", fail.what())); + } catch (...) { + cmSystemTools::Error("Error writing profiling output!"); + } +} + +void cmMakefileProfilingData::StopEntry() +{ + /* Do not try again if we previously failed to write to output. */ + if (!this->ProfileStream.good()) { + return; + } + + try { + this->ProfileStream << ","; + cmsys::SystemInformation info; + Json::Value v; + v["ph"] = "E"; + v["ts"] = Json::Value::UInt64( + std::chrono::duration_cast<std::chrono::microseconds>( + std::chrono::steady_clock::now().time_since_epoch()) + .count()); + v["pid"] = static_cast<int>(info.GetProcessId()); + v["tid"] = 0; + this->JsonWriter->write(v, &this->ProfileStream); + } catch (std::ios_base::failure& fail) { + cmSystemTools::Error( + cmStrCat("Failed to write to profiling output:", fail.what())); + } catch (...) { + cmSystemTools::Error("Error writing profiling output!"); + } +} diff --git a/Source/cmMakefileProfilingData.h b/Source/cmMakefileProfilingData.h new file mode 100644 index 0000000..1babd97 --- /dev/null +++ b/Source/cmMakefileProfilingData.h @@ -0,0 +1,29 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmMakefileProfilingData_h +#define cmMakefileProfilingData_h +#include <memory> +#include <string> + +#include "cmsys/FStream.hxx" + +namespace Json { +class StreamWriter; +} + +class cmListFileContext; +struct cmListFileFunction; + +class cmMakefileProfilingData +{ +public: + cmMakefileProfilingData(const std::string&); + ~cmMakefileProfilingData() noexcept; + void StartEntry(const cmListFileFunction& lff, cmListFileContext const& lfc); + void StopEntry(); + +private: + cmsys::ofstream ProfileStream; + std::unique_ptr<Json::StreamWriter> JsonWriter; +}; +#endif diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index d7e2de6..f687289 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -46,9 +46,8 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) this->LocalGenerator->GetGlobalGenerator()); cmake* cm = this->GlobalGenerator->GetCMakeInstance(); this->NoRuleMessages = false; - if (const char* ruleStatus = - cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) { - this->NoRuleMessages = cmIsOff(ruleStatus); + if (cmProp ruleStatus = cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) { + this->NoRuleMessages = cmIsOff(*ruleStatus); } MacOSXContentGenerator = cm::make_unique<MacOSXContentGeneratorType>(this); } @@ -155,7 +154,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() // Evaluates generator expressions and expands prop_value auto evaluatedFiles = - [this](const char* prop_value) -> std::vector<std::string> { + [this](const std::string& prop_value) -> std::vector<std::string> { std::vector<std::string> files; cmExpandList(cmGeneratorExpression::Evaluate( prop_value, this->LocalGenerator, this->GetConfigName(), @@ -165,9 +164,9 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() }; // Look for additional files registered for cleaning in this directory. - if (const char* prop_value = + if (cmProp prop_value = this->Makefile->GetProperty("ADDITIONAL_MAKE_CLEAN_FILES")) { - std::vector<std::string> const files = evaluatedFiles(prop_value); + std::vector<std::string> const files = evaluatedFiles(*prop_value); this->CleanFiles.insert(files.begin(), files.end()); } @@ -184,8 +183,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } // add custom commands to the clean rules? - const char* clean_no_custom = this->Makefile->GetProperty("CLEAN_NO_CUSTOM"); - bool clean = cmIsOff(clean_no_custom); + cmProp clean_no_custom = this->Makefile->GetProperty("CLEAN_NO_CUSTOM"); + bool clean = clean_no_custom ? cmIsOff(*clean_no_custom) : true; // First generate the object rule files. Save a list of all object // files for this target. @@ -300,8 +299,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); depFileStream << "# Empty dependencies file for " << this->GeneratorTarget->GetName() << ".\n" - << "# This may be replaced when dependencies are built." - << std::endl; + << "# This may be replaced when dependencies are built.\n"; } // Open the flags file. This should be copy-if-different because the @@ -639,7 +637,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); vars.CMTargetType = - cmState::GetTargetTypeName(this->GeneratorTarget->GetType()); + cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str(); vars.Language = lang.c_str(); vars.Target = targetOutPathReal.c_str(); vars.TargetPDB = targetOutPathPDB.c_str(); @@ -716,8 +714,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // no launcher for CMAKE_EXPORT_COMPILE_COMMANDS rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, compileCommand, vars); - std::string workingDirectory = cmSystemTools::CollapseFullPath( - this->LocalGenerator->GetCurrentBinaryDirectory()); + std::string workingDirectory = + this->LocalGenerator->GetCurrentBinaryDirectory(); compileCommand.replace(compileCommand.find(langFlags), langFlags.size(), this->GetFlags(lang, this->GetConfigName())); std::string langDefines = std::string("$(") + lang + "_DEFINES)"; @@ -1129,8 +1127,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() // translation table for the dependency scanning process. depCmd << "cd " << (this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath( - this->LocalGenerator->GetBinaryDirectory()), + this->LocalGenerator->GetBinaryDirectory(), cmOutputConverter::SHELL)) << " && "; #endif @@ -1146,23 +1143,19 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() depCmd << "$(CMAKE_COMMAND) -E cmake_depends \"" << this->GlobalGenerator->GetName() << "\" " << this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath( - this->LocalGenerator->GetSourceDirectory()), + this->LocalGenerator->GetSourceDirectory(), cmOutputConverter::SHELL) << " " << this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath( - this->LocalGenerator->GetCurrentSourceDirectory()), + this->LocalGenerator->GetCurrentSourceDirectory(), cmOutputConverter::SHELL) << " " << this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath( - this->LocalGenerator->GetBinaryDirectory()), + this->LocalGenerator->GetBinaryDirectory(), cmOutputConverter::SHELL) << " " << this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath( - this->LocalGenerator->GetCurrentBinaryDirectory()), + this->LocalGenerator->GetCurrentBinaryDirectory(), cmOutputConverter::SHELL) << " " << this->LocalGenerator->ConvertToOutputFormat( @@ -1250,8 +1243,10 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( // Setup implicit dependency scanning. for (auto const& idi : ccg.GetCC().GetImplicitDepends()) { - std::string objFullPath = cmSystemTools::CollapseFullPath(outputs[0]); - std::string srcFullPath = cmSystemTools::CollapseFullPath(idi.second); + std::string objFullPath = cmSystemTools::CollapseFullPath( + outputs[0], this->LocalGenerator->GetCurrentBinaryDirectory()); + std::string srcFullPath = cmSystemTools::CollapseFullPath( + idi.second, this->LocalGenerator->GetCurrentBinaryDirectory()); this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, idi.first, objFullPath, srcFullPath); } diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 885703f..9c4ff83 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -156,23 +156,25 @@ const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule( const std::string& config) const { - return this->TargetLinkLanguage(config) + "_" + - cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + - "_LINKER__" + + return cmStrCat( + this->TargetLinkLanguage(config), "_", + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()), + "_LINKER__", cmGlobalNinjaGenerator::EncodeRuleName( - this->GetGeneratorTarget()->GetName()) + - "_" + config; + this->GetGeneratorTarget()->GetName()), + "_", config); } std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule( const std::string& config) const { - return this->TargetLinkLanguage(config) + "_" + - cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + - "_DEVICE_LINKER__" + + return cmStrCat( + this->TargetLinkLanguage(config), "_", + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()), + "_DEVICE_LINKER__", cmGlobalNinjaGenerator::EncodeRuleName( - this->GetGeneratorTarget()->GetName()) + - "_" + config; + this->GetGeneratorTarget()->GetName()), + "_", config); } struct cmNinjaRemoveNoOpCommands @@ -191,7 +193,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule( cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = - cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()); + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + .c_str(); vars.Language = "CUDA"; @@ -282,7 +285,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, cmNinjaRule rule(std::move(linkRuleName)); cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); - vars.CMTargetType = cmState::GetTargetTypeName(targetType); + vars.CMTargetType = cmState::GetTargetTypeName(targetType).c_str(); std::string lang = this->TargetLinkLanguage(config); vars.Language = config.c_str(); @@ -812,8 +815,20 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( targetOutputReal = this->ConvertToNinjaPath(targetOutputReal); } else if (gt->IsFrameworkOnApple()) { // Create the library framework. + + cmOSXBundleGenerator::SkipParts bundleSkipParts; + if (globalGen->GetName() == "Ninja Multi-Config") { + const auto postFix = this->GeneratorTarget->GetFilePostfix(config); + // Skip creating Info.plist when there are multiple configurations, and + // the current configuration has a postfix. The non-postfix configuration + // Info.plist can be used by all the other configurations. + if (!postFix.empty()) { + bundleSkipParts.infoPlist = true; + } + } + this->OSXBundleGenerator->CreateFramework( - tgtNames.Output, gt->GetDirectory(config), config); + tgtNames.Output, gt->GetDirectory(config), config, bundleSkipParts); } else if (gt->IsCFBundleOnApple()) { // Create the core foundation bundle. this->OSXBundleGenerator->CreateCFBundle(tgtNames.Output, diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index abf12f8..8833fa4 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -94,17 +94,19 @@ cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const std::string cmNinjaTargetGenerator::LanguageCompilerRule( const std::string& lang, const std::string& config) const { - return lang + "_COMPILER__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + - "_" + config; + return cmStrCat( + lang, "_COMPILER__", + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()), + '_', config); } std::string cmNinjaTargetGenerator::LanguagePreprocessRule( std::string const& lang, const std::string& config) const { - return lang + "_PREPROCESS__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + - "_" + config; + return cmStrCat( + lang, "_PREPROCESS__", + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()), + '_', config); } bool cmNinjaTargetGenerator::NeedExplicitPreprocessing( @@ -129,9 +131,10 @@ bool cmNinjaTargetGenerator::CompilePreprocessedSourceWithDefines( std::string cmNinjaTargetGenerator::LanguageDyndepRule( const std::string& lang, const std::string& config) const { - return lang + "_DYNDEP__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + - "_" + config; + return cmStrCat( + lang, "_DYNDEP__", + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()), + '_', config); } bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const @@ -219,8 +222,8 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags, bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const { - std::string const& deptype = - this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" + lang); + std::string const& deptype = this->GetMakefile()->GetSafeDefinition( + cmStrCat("CMAKE_NINJA_DEPTYPE_", lang)); if (deptype == "msvc") { return true; } @@ -355,13 +358,12 @@ std::string cmNinjaTargetGenerator::GetObjectFilePath( { std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if (!path.empty()) { - path += "/"; + path += '/'; } std::string const& objectName = this->GeneratorTarget->GetObjectName(source); - path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - path += this->GetGlobalGenerator()->ConfigDirectory(config); - path += "/"; - path += objectName; + path += cmStrCat( + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), + this->GetGlobalGenerator()->ConfigDirectory(config), '/', objectName); return path; } @@ -389,16 +391,15 @@ std::string cmNinjaTargetGenerator::GetPreprocessedFilePath( this->GetGlobalGenerator()->GetLanguageOutputExtension(*source); assert(objName.size() >= objExt.size()); std::string const ppName = - objName.substr(0, objName.size() - objExt.size()) + "-pp." + ppExt; + cmStrCat(objName.substr(0, objName.size() - objExt.size()), "-pp.", ppExt); std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if (!path.empty()) { - path += "/"; + path += '/'; } - path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - path += this->GetGlobalGenerator()->ConfigDirectory(config); - path += "/"; - path += ppName; + path += + cmStrCat(this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), + this->GetGlobalGenerator()->ConfigDirectory(config), '/', ppName); return path; } @@ -407,13 +408,11 @@ std::string cmNinjaTargetGenerator::GetDyndepFilePath( { std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if (!path.empty()) { - path += "/"; + path += '/'; } - path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - path += this->GetGlobalGenerator()->ConfigDirectory(config); - path += "/"; - path += lang; - path += ".dd"; + path += cmStrCat( + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), + this->GetGlobalGenerator()->ConfigDirectory(config), '/', lang, ".dd"); return path; } @@ -442,8 +441,7 @@ std::string cmNinjaTargetGenerator::GetTargetFilePath( if (path.empty() || path == ".") { return name; } - path += "/"; - path += name; + path += cmStrCat('/', name); return path; } @@ -497,7 +495,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = - cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()); + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()).c_str(); vars.Language = lang.c_str(); vars.Source = "$in"; vars.Object = "$out"; @@ -522,7 +520,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, bool const lang_supports_response = lang != "RC"; if (lang_supports_response && this->ForceResponseFile()) { std::string const responseFlagVar = - "CMAKE_" + lang + "_RESPONSE_FILE_FLAG"; + cmStrCat("CMAKE_", lang, "_RESPONSE_FILE_FLAG"); responseFlag = this->Makefile->GetSafeDefinition(responseFlagVar); if (responseFlag.empty() && lang != "CUDA") { responseFlag = "@"; @@ -587,7 +585,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, rule.RspFile = "$RSP_FILE"; rule.RspContent = cmStrCat(' ', ppVars.Defines, ' ', ppVars.Includes, ' ', ppFlags); - ppFlags = responseFlag + rule.RspFile; + ppFlags = cmStrCat(responseFlag, rule.RspFile); ppVars.Defines = ""; ppVars.Includes = ""; } @@ -658,7 +656,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, rule.RspFile = "$RSP_FILE"; rule.RspContent = cmStrCat(' ', vars.Defines, ' ', vars.Includes, ' ', flags); - flags = responseFlag + rule.RspFile; + flags = cmStrCat(responseFlag, rule.RspFile); vars.Defines = ""; vars.Includes = ""; } @@ -671,7 +669,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, rule.DepType = "msvc"; rule.DepFile.clear(); flags += " /showIncludes"; - } else if (mf->IsOn("CMAKE_NINJA_CMCLDEPS_" + lang)) { + } else if (mf->IsOn(cmStrCat("CMAKE_NINJA_CMCLDEPS_", lang))) { // For the MS resource compiler we need cmcldeps, but skip dependencies // for source-file try_compile cases because they are always fresh. if (!mf->GetIsSourceFileTryCompile()) { @@ -688,14 +686,14 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, } else { rule.DepType = "gcc"; rule.DepFile = "$DEP_FILE"; - const std::string flagsName = "CMAKE_DEPFILE_FLAGS_" + lang; + const std::string flagsName = cmStrCat("CMAKE_DEPFILE_FLAGS_", lang); std::string depfileFlags = mf->GetSafeDefinition(flagsName); if (!depfileFlags.empty()) { cmSystemTools::ReplaceString(depfileFlags, "<DEPFILE>", "$DEP_FILE"); cmSystemTools::ReplaceString(depfileFlags, "<OBJECT>", "$out"); cmSystemTools::ReplaceString(depfileFlags, "<CMAKE_C_COMPILER>", mf->GetDefinition("CMAKE_C_COMPILER")); - flags += " " + depfileFlags; + flags += cmStrCat(' ', depfileFlags); } } @@ -718,7 +716,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar); cmExpandList(compileCmd, compileCmds); } else { - const std::string cmdVar = "CMAKE_" + lang + "_COMPILE_OBJECT"; + const std::string cmdVar = cmStrCat("CMAKE_", lang, "_COMPILE_OBJECT"); const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar); cmExpandList(compileCmd, compileCmds); } @@ -728,7 +726,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, if (!compileCmds.empty() && (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" || lang == "OBJC" || lang == "OBJCXX")) { - std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; + std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER"); const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); if (clauncher && *clauncher) { compilerLauncher = clauncher; @@ -737,13 +735,13 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, // Maybe insert an include-what-you-use runner. if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) { - std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE"; + std::string const iwyu_prop = cmStrCat(lang, "_INCLUDE_WHAT_YOU_USE"); const char* iwyu = this->GeneratorTarget->GetProperty(iwyu_prop); - std::string const tidy_prop = lang + "_CLANG_TIDY"; + std::string const tidy_prop = cmStrCat(lang, "_CLANG_TIDY"); const char* tidy = this->GeneratorTarget->GetProperty(tidy_prop); - std::string const cpplint_prop = lang + "_CPPLINT"; + std::string const cpplint_prop = cmStrCat(lang, "_CPPLINT"); const char* cpplint = this->GeneratorTarget->GetProperty(cpplint_prop); - std::string const cppcheck_prop = lang + "_CPPCHECK"; + std::string const cppcheck_prop = cmStrCat(lang, "_CPPCHECK"); const char* cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop); if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint) || (cppcheck && *cppcheck)) { @@ -751,18 +749,19 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, if (!compilerLauncher.empty()) { // In __run_co_compile case the launcher command is supplied // via --launcher=<maybe-list> and consumed - run_iwyu += " --launcher="; - run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher); + run_iwyu += + cmStrCat(" --launcher=", + this->LocalGenerator->EscapeForShell(compilerLauncher)); compilerLauncher.clear(); } if (iwyu && *iwyu) { - run_iwyu += " --iwyu="; - run_iwyu += this->GetLocalGenerator()->EscapeForShell(iwyu); + run_iwyu += cmStrCat(" --iwyu=", + this->GetLocalGenerator()->EscapeForShell(iwyu)); } if (tidy && *tidy) { run_iwyu += " --tidy="; const char* driverMode = this->Makefile->GetDefinition( - "CMAKE_" + lang + "_CLANG_TIDY_DRIVER_MODE"); + cmStrCat("CMAKE_", lang, "_CLANG_TIDY_DRIVER_MODE")); if (!(driverMode && *driverMode)) { driverMode = lang == "C" ? "gcc" : "g++"; } @@ -770,12 +769,12 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, cmStrCat(tidy, ";--extra-arg-before=--driver-mode=", driverMode)); } if (cpplint && *cpplint) { - run_iwyu += " --cpplint="; - run_iwyu += this->GetLocalGenerator()->EscapeForShell(cpplint); + run_iwyu += cmStrCat( + " --cpplint=", this->GetLocalGenerator()->EscapeForShell(cpplint)); } if (cppcheck && *cppcheck) { - run_iwyu += " --cppcheck="; - run_iwyu += this->GetLocalGenerator()->EscapeForShell(cppcheck); + run_iwyu += cmStrCat( + " --cppcheck=", this->GetLocalGenerator()->EscapeForShell(cppcheck)); } if ((tidy && *tidy) || (cpplint && *cpplint) || (cppcheck && *cppcheck)) { @@ -797,7 +796,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, i = this->LocalGenerator->EscapeForShell(i); } } - compileCmds.front().insert(0, cmJoin(args, " ") + " "); + compileCmds.front().insert(0, cmStrCat(cmJoin(args, " "), ' ')); } if (!compileCmds.empty()) { @@ -872,7 +871,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( { cmNinjaBuild build("phony"); - build.Comment = "Order-only phony target for " + this->GetTargetName(); + build.Comment = + cmStrCat("Order-only phony target for ", this->GetTargetName()); build.Outputs.push_back(this->OrderDependsTargetForTarget(config)); cmNinjaDeps& orderOnlyDeps = build.OrderOnlyDeps; @@ -960,9 +960,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( if (const char* name = target->GetProperty("Swift_DEPENDENCIES_FILE")) { return name; } - return this->ConvertToNinjaPath(target->GetSupportDirectory() + "/" + - config + "/" + target->GetName() + - ".swiftdeps"); + return this->ConvertToNinjaPath( + cmStrCat(target->GetSupportDirectory(), '/', config, '/', + target->GetName(), ".swiftdeps")); }(); // build the global target dependencies @@ -994,7 +994,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string cmakeVarLang = cmStrCat("CMAKE_", language); // build response file name - std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_FLAG"; + std::string cmakeLinkVar = cmStrCat(cmakeVarLang, "_RESPONSE_FILE_FLAG"); const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar); @@ -1019,14 +1019,15 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( if (!replaceExt) { // use original code vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat( - objectFileName + ".d", cmOutputConverter::SHELL); + cmStrCat(objectFileName, ".d"), cmOutputConverter::SHELL); } else { // Replace the original source file extension with the // depend file extension. - std::string dependFileName = - cmSystemTools::GetFilenameWithoutLastExtension(objectFileName) + ".d"; + std::string dependFileName = cmStrCat( + cmSystemTools::GetFilenameWithoutLastExtension(objectFileName), ".d"); vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat( - objectFileDir + "/" + dependFileName, cmOutputConverter::SHELL); + cmStrCat(objectFileDir, '/', dependFileName), + cmOutputConverter::SHELL); } } @@ -1101,7 +1102,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source, config)); ppBuild.Outputs.push_back(ppFileName); - ppBuild.RspFile = ppFileName + ".rsp"; + ppBuild.RspFile = cmStrCat(ppFileName, ".rsp"); bool const compilePP = this->UsePreprocessedSource(language); bool const compilePPWithDefines = @@ -1130,7 +1131,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( // In case compilation requires flags that are incompatible with // preprocessing, include them here. std::string const& postFlag = this->Makefile->GetSafeDefinition( - "CMAKE_" + language + "_POSTPROCESS_FLAG"); + cmStrCat("CMAKE_", language, "_POSTPROCESS_FLAG")); this->LocalGenerator->AppendFlags(vars["FLAGS"], postFlag); } @@ -1158,13 +1159,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( sourceDirectory, this->GeneratorTarget, language, false, false, config); - vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"]; + vars["INCLUDES"] = cmStrCat(sourceDirectoryFlag, ' ', vars["INCLUDES"]); } // Explicit preprocessing always uses a depfile. ppBuild.Variables["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat( - objectFileName + ".pp.d", cmOutputConverter::SHELL); + cmStrCat(objectFileName, ".pp.d"), cmOutputConverter::SHELL); if (compilePP) { // The actual compilation does not need a depfile because it // depends on the already-preprocessed source. @@ -1177,7 +1178,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( ppBuild.Variables["OBJ_FILE"] = objectFileName; // Tell dependency scanner where to store dyndep intermediate results. - std::string const ddiFile = objectFileName + ".ddi"; + std::string const ddiFile = cmStrCat(objectFileName, ".ddi"); ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile; ppBuild.ImplicitOuts.push_back(ddiFile); if (firstForConfig) { @@ -1216,7 +1217,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->SetMsvcTargetPdbVariable(vars, config); - objBuild.RspFile = objectFileName + ".rsp"; + objBuild.RspFile = cmStrCat(objectFileName, ".rsp"); if (language == "Swift") { this->EmitSwiftDependencyInfo(source, config); @@ -1242,8 +1243,8 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, { Json::Value tdi(Json::objectValue); tdi["language"] = lang; - tdi["compiler-id"] = - this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID"); + tdi["compiler-id"] = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_COMPILER_ID")); if (lang == "Fortran") { std::string mod_dir = this->GeneratorTarget->GetFortranModuleDirectory( @@ -1295,13 +1296,13 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( if (const char* name = source->GetProperty("Swift_DEPENDENCIES_FILE")) { return name; } - return objectFilePath + ".swiftdeps"; + return cmStrCat(objectFilePath, ".swiftdeps"); }(); std::string const swiftDiaPath = [source, objectFilePath]() -> std::string { if (const char* name = source->GetProperty("Swift_DIAGNOSTICS_FILE")) { return name; } - return objectFilePath + ".dia"; + return cmStrCat(objectFilePath, ".dia"); }(); std::string const makeDepsPath = [this, source, config]() -> std::string { cmLocalNinjaGenerator const* local = this->GetLocalGenerator(); @@ -1311,12 +1312,13 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( cmSystemTools::GetFilenamePath(objectFileName); if (this->Makefile->IsOn("CMAKE_Swift_DEPFLE_EXTNSION_REPLACE")) { - std::string dependFileName = - cmSystemTools::GetFilenameWithoutLastExtension(objectFileName) + ".d"; - return local->ConvertToOutputFormat(objectFileDir + "/" + dependFileName, - cmOutputConverter::SHELL); + std::string dependFileName = cmStrCat( + cmSystemTools::GetFilenameWithoutLastExtension(objectFileName), ".d"); + return local->ConvertToOutputFormat( + cmStrCat(objectFileDir, '/', dependFileName), + cmOutputConverter::SHELL); } - return local->ConvertToOutputFormat(objectFileName + ".d", + return local->ConvertToOutputFormat(cmStrCat(objectFileName, ".d"), cmOutputConverter::SHELL); }(); @@ -1381,7 +1383,7 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( this->GetMakefile()->GetRequiredDefinition(cmdVar); cmExpandList(compileCmd, compileCmds); } else { - const std::string cmdVar = "CMAKE_" + language + "_COMPILE_OBJECT"; + const std::string cmdVar = cmStrCat("CMAKE_", language, "_COMPILE_OBJECT"); const std::string& compileCmd = this->GetMakefile()->GetRequiredDefinition(cmdVar); cmExpandList(compileCmd, compileCmds); diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index 382b563..7eea4b2 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -56,9 +56,9 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, outpath = out; } -void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, - const std::string& outpath, - const std::string& config) +void cmOSXBundleGenerator::CreateFramework( + const std::string& targetName, const std::string& outpath, + const std::string& config, const cmOSXBundleGenerator::SkipParts& skipParts) { if (this->MustSkip()) { return; @@ -77,16 +77,18 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, std::string frameworkVersion = this->GT->GetFrameworkVersion(); - // Configure the Info.plist file - std::string plist = newoutpath; - if (!this->Makefile->PlatformIsAppleEmbedded()) { - // Put the Info.plist file into the Resources directory. - this->MacContentFolders->insert("Resources"); - plist += "/Resources"; - } - plist += "/Info.plist"; std::string name = cmSystemTools::GetFilenameName(targetName); - this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name, plist); + if (!skipParts.infoPlist) { + // Configure the Info.plist file + std::string plist = newoutpath; + if (!this->Makefile->PlatformIsAppleEmbedded()) { + // Put the Info.plist file into the Resources directory. + this->MacContentFolders->insert("Resources"); + plist += "/Resources"; + } + plist += "/Info.plist"; + this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name, plist); + } // Generate Versions directory only for MacOSX frameworks if (this->Makefile->PlatformIsAppleEmbedded()) { diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index 232be48..5bf1d98 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -19,6 +19,15 @@ class cmOSXBundleGenerator public: cmOSXBundleGenerator(cmGeneratorTarget* target); + struct SkipParts + { + SkipParts() + : infoPlist(false) + { + } + bool infoPlist; // NOLINT(modernize-use-default-member-init) + }; + // create an app bundle at a given root, and return // the directory within the bundle that contains the executable void CreateAppBundle(const std::string& targetName, std::string& root, @@ -26,7 +35,8 @@ public: // create a framework at a given root void CreateFramework(const std::string& targetName, const std::string& root, - const std::string& config); + const std::string& config, + const SkipParts& skipParts = SkipParts()); // create a cf bundle at a given root void CreateCFBundle(const std::string& targetName, const std::string& root, diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx index 22e59ac..a9adf99 100644 --- a/Source/cmOptionCommand.cxx +++ b/Source/cmOptionCommand.cxx @@ -52,7 +52,7 @@ bool cmOptionCommand(std::vector<std::string> const& args, // See if a cache variable with this name already exists // If so just make sure the doc state is correct cmState* state = status.GetMakefile().GetState(); - const char* existingValue = state->GetCacheEntryValue(args[0]); + cmProp existingValue = state->GetCacheEntryValue(args[0]); if (existingValue && (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED)) { state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]); @@ -60,7 +60,7 @@ bool cmOptionCommand(std::vector<std::string> const& args, } // Nothing in the cache so add it - std::string initialValue = existingValue ? existingValue : "Off"; + std::string initialValue = existingValue ? *existingValue : "Off"; if (args.size() == 3) { initialValue = args[2]; } diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index 147f97f..b18c205 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -20,6 +20,8 @@ #include "cmSystemTools.h" #include "cmTarget.h" +using cmProp = const std::string*; + namespace { /** \class cmDependInformation * \brief Store dependency information for a single source file. @@ -117,14 +119,13 @@ public: std::set<std::string> uniqueIncludes; std::vector<std::string> orderedAndUniqueIncludes; for (auto const& target : this->Makefile->GetTargets()) { - const char* incDirProp = - target.second.GetProperty("INCLUDE_DIRECTORIES"); + cmProp incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES"); if (!incDirProp) { continue; } std::string incDirs = cmGeneratorExpression::Preprocess( - incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions); + *incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions); std::vector<std::string> includes = cmExpandedList(incDirs); diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 1366ff0..d3daad8 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -305,7 +305,10 @@ class cmMakefile; 17, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0102, \ "mark_as_advanced() does nothing if a cache entry does not exist.", \ - 3, 17, 0, cmPolicies::WARN) + 3, 17, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0103, \ + "multiple export() with same FILE without APPEND is not allowed.", \ + 3, 18, 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/cmProcessOutput.cxx b/Source/cmProcessOutput.cxx index e80ea5c..0fb4ff7 100644 --- a/Source/cmProcessOutput.cxx +++ b/Source/cmProcessOutput.cxx @@ -4,7 +4,10 @@ #include "cmProcessOutput.h" #if defined(_WIN32) +# include <cm/memory> + # include <windows.h> + unsigned int cmProcessOutput::defaultCodepage = KWSYS_ENCODING_DEFAULT_CODEPAGE; #endif @@ -143,9 +146,9 @@ bool cmProcessOutput::DoDecodeText(std::string raw, std::string& decoded, bool success = false; const int wlength = MultiByteToWideChar(codepage, 0, raw.c_str(), int(raw.size()), NULL, 0); - wchar_t* wdata = new wchar_t[wlength]; - int r = MultiByteToWideChar(codepage, 0, raw.c_str(), int(raw.size()), wdata, - wlength); + auto wdata = cm::make_unique<wchar_t[]>(wlength); + int r = MultiByteToWideChar(codepage, 0, raw.c_str(), int(raw.size()), + wdata.get(), wlength); if (r > 0) { if (lastChar) { *lastChar = 0; @@ -154,18 +157,16 @@ bool cmProcessOutput::DoDecodeText(std::string raw, std::string& decoded, *lastChar = wdata[wlength - 1]; } } - int length = WideCharToMultiByte(defaultCodepage, 0, wdata, wlength, NULL, - 0, NULL, NULL); - char* data = new char[length]; - r = WideCharToMultiByte(defaultCodepage, 0, wdata, wlength, data, length, - NULL, NULL); + int length = WideCharToMultiByte(defaultCodepage, 0, wdata.get(), wlength, + NULL, 0, NULL, NULL); + auto data = cm::make_unique<char[]>(length); + r = WideCharToMultiByte(defaultCodepage, 0, wdata.get(), wlength, + data.get(), length, NULL, NULL); if (r > 0) { - decoded = std::string(data, length); + decoded = std::string(data.get(), length); success = true; } - delete[] data; } - delete[] wdata; return success; } #endif diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index a25fd42..2ec66d9 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -47,10 +47,10 @@ bool cmProjectCommand(std::vector<std::string> const& args, mf.SetProjectName(projectName); mf.AddCacheDefinition(projectName + "_BINARY_DIR", - mf.GetCurrentBinaryDirectory().c_str(), + mf.GetCurrentBinaryDirectory(), "Value Computed by CMake", cmStateEnums::STATIC); mf.AddCacheDefinition(projectName + "_SOURCE_DIR", - mf.GetCurrentSourceDirectory().c_str(), + mf.GetCurrentSourceDirectory(), "Value Computed by CMake", cmStateEnums::STATIC); mf.AddDefinition("PROJECT_BINARY_DIR", mf.GetCurrentBinaryDirectory()); @@ -66,7 +66,7 @@ bool cmProjectCommand(std::vector<std::string> const& args, // will work. if (!mf.GetDefinition("CMAKE_PROJECT_NAME") || mf.IsRootMakefile()) { mf.AddDefinition("CMAKE_PROJECT_NAME", projectName); - mf.AddCacheDefinition("CMAKE_PROJECT_NAME", projectName.c_str(), + mf.AddCacheDefinition("CMAKE_PROJECT_NAME", projectName, "Value Computed by CMake", cmStateEnums::STATIC); } @@ -379,7 +379,7 @@ static void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name, // CMakeLists.txt file, then go with the last one. if (!mf.GetDefinition(name) || mf.IsRootMakefile()) { mf.AddDefinition(name, value); - mf.AddCacheDefinition(name, value.c_str(), "Value Computed by CMake", + mf.AddCacheDefinition(name, value, "Value Computed by CMake", cmStateEnums::STATIC); } } diff --git a/Source/cmPropertyDefinition.cxx b/Source/cmPropertyDefinition.cxx index 6a3174c..c8efaf6 100644 --- a/Source/cmPropertyDefinition.cxx +++ b/Source/cmPropertyDefinition.cxx @@ -2,19 +2,17 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmPropertyDefinition.h" -void cmPropertyDefinition::DefineProperty(const std::string& name, - cmProperty::ScopeType scope, - const char* shortDescription, - const char* fullDescription, - bool chain) +#include <utility> + +cmPropertyDefinition::cmPropertyDefinition(std::string name, + cmProperty::ScopeType scope, + std::string shortDescription, + std::string fullDescription, + bool chain) + : Name(std::move(name)) + , ShortDescription(std::move(shortDescription)) + , FullDescription(std::move(fullDescription)) + , Scope(scope) + , Chained(chain) { - this->Name = name; - this->Scope = scope; - this->Chained = chain; - if (shortDescription) { - this->ShortDescription = shortDescription; - } - if (fullDescription) { - this->FullDescription = fullDescription; - } } diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h index 0d68c32..d2e4467 100644 --- a/Source/cmPropertyDefinition.h +++ b/Source/cmPropertyDefinition.h @@ -21,13 +21,10 @@ class cmPropertyDefinition { public: - /// Define this property - void DefineProperty(const std::string& name, cmProperty::ScopeType scope, - const char* ShortDescription, - const char* FullDescription, bool chained); - - /// Default constructor - cmPropertyDefinition() { this->Chained = false; } + /// Constructor + cmPropertyDefinition(std::string name, cmProperty::ScopeType scope, + std::string ShortDescription, + std::string FullDescription, bool chained = false); /// Is the property chained? bool IsChained() const { return this->Chained; } diff --git a/Source/cmPropertyDefinitionMap.cxx b/Source/cmPropertyDefinitionMap.cxx index f752ed7..614d5a4 100644 --- a/Source/cmPropertyDefinitionMap.cxx +++ b/Source/cmPropertyDefinitionMap.cxx @@ -2,20 +2,20 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmPropertyDefinitionMap.h" +#include <tuple> #include <utility> -void cmPropertyDefinitionMap::DefineProperty(const std::string& name, - cmProperty::ScopeType scope, - const char* ShortDescription, - const char* FullDescription, - bool chain) +void cmPropertyDefinitionMap::DefineProperty( + const std::string& name, cmProperty::ScopeType scope, + const std::string& ShortDescription, const std::string& FullDescription, + bool chain) { auto it = this->find(name); - cmPropertyDefinition* prop; if (it == this->end()) { - prop = &(*this)[name]; - prop->DefineProperty(name, scope, ShortDescription, FullDescription, - chain); + // try_emplace() since C++17 + this->emplace(std::piecewise_construct, std::forward_as_tuple(name), + std::forward_as_tuple(name, scope, ShortDescription, + FullDescription, chain)); } } diff --git a/Source/cmPropertyDefinitionMap.h b/Source/cmPropertyDefinitionMap.h index 8ec7910..2ae6efb 100644 --- a/Source/cmPropertyDefinitionMap.h +++ b/Source/cmPropertyDefinitionMap.h @@ -17,8 +17,8 @@ class cmPropertyDefinitionMap public: // define the property void DefineProperty(const std::string& name, cmProperty::ScopeType scope, - const char* ShortDescription, - const char* FullDescription, bool chain); + const std::string& ShortDescription, + const std::string& FullDescription, bool chain); // has a named property been defined bool IsPropertyDefined(const std::string& name) const; diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx index d4b3552..f22f36d 100644 --- a/Source/cmPropertyMap.cxx +++ b/Source/cmPropertyMap.cxx @@ -42,13 +42,11 @@ void cmPropertyMap::RemoveProperty(const std::string& name) Map_.erase(name); } -const char* cmPropertyMap::GetPropertyValue(const std::string& name) const +cmProp cmPropertyMap::GetPropertyValue(const std::string& name) const { - { - auto it = Map_.find(name); - if (it != Map_.end()) { - return it->second.c_str(); - } + auto it = Map_.find(name); + if (it != Map_.end()) { + return &it->second; } return nullptr; } diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h index bea4372..40ac356 100644 --- a/Source/cmPropertyMap.h +++ b/Source/cmPropertyMap.h @@ -10,6 +10,8 @@ #include <utility> #include <vector> +using cmProp = const std::string*; + /** \class cmPropertyMap * \brief String property map. */ @@ -31,7 +33,7 @@ public: bool asString = false); //! Get the property value - const char* GetPropertyValue(const std::string& name) const; + cmProp GetPropertyValue(const std::string& name) const; //! Remove the property @a name from the map void RemoveProperty(const std::string& name); diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index 7a6cb42..18b135d 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -164,10 +164,10 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget( // Set FOLDER property in the target { - char const* folder = + cmProp folder = makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); if (folder != nullptr) { - target->SetProperty("FOLDER", folder); + target->SetProperty("FOLDER", *folder); } } } diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 629367d..a5af810 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -339,15 +339,18 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // Targets FOLDER { - const char* folder = + cmProp prop = this->Makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); - if (folder == nullptr) { - folder = this->Makefile->GetState()->GetGlobalProperty( + if (prop == nullptr) { + prop = this->Makefile->GetState()->GetGlobalProperty( "AUTOGEN_TARGETS_FOLDER"); } + const char* folder; // Inherit FOLDER property from target (#13688) - if (folder == nullptr) { + if (prop == nullptr) { folder = this->GenTarget->GetProperty("FOLDER"); + } else { + folder = prop->c_str(); } if (folder != nullptr) { this->TargetsFolder = folder; @@ -1604,10 +1607,9 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, cmStrCat(genNameUpper, "_SOURCE_GROUP"), "AUTOGEN_SOURCE_GROUP" }; for (std::string const& prop : props) { - const char* propName = - this->Makefile->GetState()->GetGlobalProperty(prop); - if ((propName != nullptr) && (*propName != '\0')) { - groupName = propName; + cmProp propName = this->Makefile->GetState()->GetGlobalProperty(prop); + if (propName && !propName->empty()) { + groupName = *propName; property = prop; break; } @@ -1668,6 +1670,13 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) } return 0u; }; + auto toUInt2 = [](cmProp input) -> unsigned int { + unsigned long tmp = 0; + if (input != nullptr && cmStrToULong(*input, &tmp)) { + return static_cast<unsigned int>(tmp); + } + return 0u; + }; // Initialize return value to a default std::pair<IntegerVersion, unsigned int> res( @@ -1689,9 +1698,9 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) knownQtVersions.reserve(keys.size() * 2); // Adds a version to the result (nullptr safe) - auto addVersion = [&knownQtVersions, &toUInt](const char* major, - const char* minor) { - cmQtAutoGen::IntegerVersion ver(toUInt(major), toUInt(minor)); + auto addVersion = [&knownQtVersions, &toUInt2](cmProp major, + cmProp minor) { + cmQtAutoGen::IntegerVersion ver(toUInt2(major), toUInt2(minor)); if (ver.Major != 0) { knownQtVersions.emplace_back(ver); } @@ -1699,8 +1708,8 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) // Read versions from variables for (auto const& keyPair : keys) { - addVersion(target->Makefile->GetDefinition(std::string(keyPair.first)), - target->Makefile->GetDefinition(std::string(keyPair.second))); + addVersion(target->Makefile->GetDef(std::string(keyPair.first)), + target->Makefile->GetDef(std::string(keyPair.second))); } // Read versions from directory properties diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 893bd6b..36dd627 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -700,27 +700,27 @@ bool cmQtAutoMocUicT::ParseCacheT::WriteToFile(std::string const& fileName) if (!ofs) { return false; } - ofs << "# Generated by CMake. Changes will be overwritten." << std::endl; + ofs << "# Generated by CMake. Changes will be overwritten.\n"; for (auto const& pair : Map_) { - ofs << pair.first << std::endl; + ofs << pair.first << '\n'; FileT const& file = *pair.second; if (!file.Moc.Macro.empty()) { - ofs << " mmc:" << file.Moc.Macro << std::endl; + ofs << " mmc:" << file.Moc.Macro << '\n'; } for (IncludeKeyT const& item : file.Moc.Include.Underscore) { - ofs << " miu:" << item.Key << std::endl; + ofs << " miu:" << item.Key << '\n'; } for (IncludeKeyT const& item : file.Moc.Include.Dot) { - ofs << " mid:" << item.Key << std::endl; + ofs << " mid:" << item.Key << '\n'; } for (std::string const& item : file.Moc.Depends) { - ofs << " mdp:" << item << std::endl; + ofs << " mdp:" << item << '\n'; } for (IncludeKeyT const& item : file.Uic.Include) { - ofs << " uic:" << item.Key << std::endl; + ofs << " uic:" << item.Key << '\n'; } for (std::string const& item : file.Uic.Depends) { - ofs << " udp:" << item << std::endl; + ofs << " udp:" << item << '\n'; } } return ofs.Close(); @@ -2211,9 +2211,9 @@ void cmQtAutoMocUicT::JobDepFilesMergeT::Process() " for writing.")); return; } - ofs << BaseConst().DepFileRuleName << ": \\" << std::endl; + ofs << BaseConst().DepFileRuleName << ": \\\n"; for (const std::string& file : dependencies) { - ofs << '\t' << escapeDependencyPath(file) << " \\" << std::endl; + ofs << '\t' << escapeDependencyPath(file) << " \\\n"; if (!ofs.good()) { LogError(GenT::GEN, cmStrCat("Writing depfile", MessagePath(BaseConst().DepFile), @@ -2224,8 +2224,7 @@ void cmQtAutoMocUicT::JobDepFilesMergeT::Process() // Add the CMake executable to re-new cache data if necessary. // Also, this is the last entry, so don't add a backslash. - ofs << '\t' << escapeDependencyPath(BaseConst().CMakeExecutable) - << std::endl; + ofs << '\t' << escapeDependencyPath(BaseConst().CMakeExecutable) << '\n'; } void cmQtAutoMocUicT::JobFinishT::Process() diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx index 7f4abf9..c39d162 100644 --- a/Source/cmRST.cxx +++ b/Source/cmRST.cxx @@ -89,7 +89,8 @@ void cmRST::ProcessModule(std::istream& is) this->ProcessLine(line); } else { if (line[0] != '#') { - this->ProcessLine(line.substr(0, pos)); + line.resize(pos); + this->ProcessLine(line); } rst.clear(); this->Reset(); @@ -102,8 +103,9 @@ void cmRST::ProcessModule(std::istream& is) this->ProcessLine(""); continue; } - if (line.substr(0, 2) == "# ") { - this->ProcessLine(line.substr(2)); + if (cmHasLiteralPrefix(line, "# ")) { + line.erase(0, 2); + this->ProcessLine(line); continue; } rst.clear(); diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx index 5ab1b3a..254131b 100644 --- a/Source/cmRulePlaceholderExpander.cxx +++ b/Source/cmRulePlaceholderExpander.cxx @@ -236,8 +236,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( } if (variable == "CMAKE_COMMAND") { return outputConverter->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()), - cmOutputConverter::SHELL); + cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); } auto compIt = this->Compilers.find(variable); @@ -334,7 +333,17 @@ void cmRulePlaceholderExpander::ExpandRuleVariables( std::string replace = this->ExpandRuleVariable(outputConverter, var, replaceValues); expandedInput += s.substr(pos, start - pos); + + // Prevent consecutive whitespace in the output if the rule variable + // expands to an empty string. + bool consecutive = replace.empty() && start > 0 && s[start - 1] == ' ' && + end + 1 < s.size() && s[end + 1] == ' '; + if (consecutive) { + expandedInput.pop_back(); + } + expandedInput += replace; + // move to next one start = s.find('<', start + var.size() + 2); pos = end + 1; diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx index 7a987c2..34b3105 100644 --- a/Source/cmRuntimeDependencyArchive.cxx +++ b/Source/cmRuntimeDependencyArchive.cxx @@ -39,7 +39,7 @@ static void AddVisualStudioPath(std::vector<std::string>& paths, std::string vsloc; bool found = false; # ifndef CMAKE_BOOTSTRAP - if (gg->GetName().find(prefix) == 0) { + if (cmHasPrefix(gg->GetName(), prefix)) { cmGlobalVisualStudioVersionedGenerator* vsgen = static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); if (vsgen->GetVSInstance(vsloc)) { diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index 3b2e5f3..434fb68 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -59,16 +59,12 @@ cmServer::cmServer(cmConnection* conn, bool supportExperimental) , SupportExperimental(supportExperimental) { // Register supported protocols: - this->RegisterProtocol(new cmServerProtocol1); + this->RegisterProtocol(cm::make_unique<cmServerProtocol1>()); } cmServer::~cmServer() { Close(); - - for (cmServerProtocol* p : this->SupportedProtocols) { - delete p; - } } void cmServer::ProcessRequest(cmConnection* connection, @@ -117,22 +113,22 @@ void cmServer::ProcessRequest(cmConnection* connection, } } -void cmServer::RegisterProtocol(cmServerProtocol* protocol) +void cmServer::RegisterProtocol(std::unique_ptr<cmServerProtocol> protocol) { if (protocol->IsExperimental() && !this->SupportExperimental) { - delete protocol; + protocol.reset(); return; } auto version = protocol->ProtocolVersion(); assert(version.first >= 0); assert(version.second >= 0); - auto it = std::find_if(this->SupportedProtocols.begin(), - this->SupportedProtocols.end(), - [version](cmServerProtocol* p) { - return p->ProtocolVersion() == version; - }); + auto it = std::find_if( + this->SupportedProtocols.begin(), this->SupportedProtocols.end(), + [version](const std::unique_ptr<cmServerProtocol>& p) { + return p->ProtocolVersion() == version; + }); if (it == this->SupportedProtocols.end()) { - this->SupportedProtocols.push_back(protocol); + this->SupportedProtocols.push_back(std::move(protocol)); } } @@ -297,19 +293,20 @@ void cmServer::WriteJsonObject(cmConnection* connection, } cmServerProtocol* cmServer::FindMatchingProtocol( - const std::vector<cmServerProtocol*>& protocols, int major, int minor) + const std::vector<std::unique_ptr<cmServerProtocol>>& protocols, int major, + int minor) { cmServerProtocol* bestMatch = nullptr; - for (auto protocol : protocols) { + for (const auto& protocol : protocols) { auto version = protocol->ProtocolVersion(); if (major != version.first) { continue; } if (minor == version.second) { - return protocol; + return protocol.get(); } if (!bestMatch || bestMatch->ProtocolVersion().second < version.second) { - bestMatch = protocol; + bestMatch = protocol.get(); } } return minor < 0 ? bestMatch : nullptr; diff --git a/Source/cmServer.h b/Source/cmServer.h index 3d7027b..ec40738 100644 --- a/Source/cmServer.h +++ b/Source/cmServer.h @@ -103,7 +103,7 @@ public: cmFileMonitor* FileMonitor() const; private: - void RegisterProtocol(cmServerProtocol* protocol); + void RegisterProtocol(std::unique_ptr<cmServerProtocol> protocol); // Callbacks from cmServerConnection: @@ -149,12 +149,13 @@ private: const DebugInfo* debug) const; static cmServerProtocol* FindMatchingProtocol( - const std::vector<cmServerProtocol*>& protocols, int major, int minor); + const std::vector<std::unique_ptr<cmServerProtocol>>& protocols, int major, + int minor); const bool SupportExperimental; cmServerProtocol* Protocol = nullptr; - std::vector<cmServerProtocol*> SupportedProtocols; + std::vector<std::unique_ptr<cmServerProtocol>> SupportedProtocols; friend class cmServerProtocol; friend class cmServerRequest; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 1d4ea01..c5f3463 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -182,7 +182,7 @@ static bool getOrTestHomeDirectory(cmState* state, std::string& value, std::string* errorMessage) { const std::string cachedValue = - std::string(state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY")); + *state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"); if (value.empty()) { value = cachedValue; return true; @@ -205,9 +205,7 @@ static bool getOrTestValue(cmState* state, const std::string& key, const std::string& keyDescription, std::string* errorMessage) { - const char* entry = state->GetCacheEntryValue(key); - const std::string cachedValue = - entry == nullptr ? std::string() : std::string(entry); + const std::string cachedValue = state->GetSafeCacheEntryValue(key); if (value.empty()) { value = cachedValue; } @@ -452,7 +450,7 @@ cmServerResponse cmServerProtocol1::ProcessCache( bool haveProperties = false; for (auto const& prop : state->GetCacheEntryPropertyList(key)) { haveProperties = true; - props[prop] = state->GetCacheEntryProperty(key, prop); + props[prop] = *state->GetCacheEntryProperty(key, prop); } if (haveProperties) { entry[kPROPERTIES_KEY] = props; diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index 5e2a146..5c55427 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -135,7 +135,7 @@ bool cmSetCommand(std::vector<std::string> const& args, // see if this is already in the cache cmState* state = status.GetMakefile().GetState(); - const char* existingValue = state->GetCacheEntryValue(variable); + cmProp existingValue = state->GetCacheEntryValue(variable); if (existingValue && (state->GetCacheEntryType(variable) != cmStateEnums::UNINITIALIZED)) { // if the set is trying to CACHE the value but the value @@ -149,8 +149,8 @@ bool cmSetCommand(std::vector<std::string> const& args, // if it is meant to be in the cache then define it in the cache if (cache) { - status.GetMakefile().AddCacheDefinition(variable, value.c_str(), docstring, - type, force); + status.GetMakefile().AddCacheDefinition(variable, value, docstring, type, + force); } else { // add the definition status.GetMakefile().AddDefinition(variable, value); diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 3705727..4dbbbd7 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -235,14 +235,8 @@ bool HandleDirectoryMode(cmExecutionStatus& status, if (!names.empty()) { // Construct the directory name. Interpret relative paths with // respect to the current directory. - std::string dir = *names.begin(); - if (!cmSystemTools::FileIsFullPath(dir)) { - dir = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', - *names.begin()); - } - - // The local generators are associated with collapsed paths. - dir = cmSystemTools::CollapseFullPath(dir); + std::string dir = cmSystemTools::CollapseFullPath( + *names.begin(), status.GetMakefile().GetCurrentSourceDirectory()); mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir); if (!mf) { @@ -307,7 +301,7 @@ bool HandleTarget(cmTarget* target, cmMakefile& makefile, if (remove) { target->SetProperty(propertyName, nullptr); } else { - target->SetProperty(propertyName, propertyValue.c_str()); + target->SetProperty(propertyName, propertyValue); } } @@ -438,7 +432,7 @@ bool HandleCacheMode(cmExecutionStatus& status, for (std::string const& name : names) { // Get the source file. cmake* cm = status.GetMakefile().GetCMakeInstance(); - const char* existingValue = cm->GetState()->GetCacheEntryValue(name); + cmProp existingValue = cm->GetState()->GetCacheEntryValue(name); if (existingValue) { if (!HandleCacheEntry(name, status.GetMakefile(), propertyName, propertyValue, appendAsString, appendMode, @@ -460,16 +454,15 @@ bool HandleCacheEntry(std::string const& cacheKey, const cmMakefile& makefile, bool appendMode, bool remove) { // Set or append the property. - const char* value = propertyValue.c_str(); cmState* state = makefile.GetState(); if (remove) { state->RemoveCacheEntryProperty(cacheKey, propertyName); } if (appendMode) { - state->AppendCacheEntryProperty(cacheKey, propertyName, value, + state->AppendCacheEntryProperty(cacheKey, propertyName, propertyValue, appendAsString); } else { - state->SetCacheEntryProperty(cacheKey, propertyName, value); + state->SetCacheEntryProperty(cacheKey, propertyName, propertyValue); } return true; @@ -505,13 +498,13 @@ bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile, bool appendMode, bool remove) { // Set or append the property. - const char* value = propertyValue.c_str(); if (remove) { file->RemoveProperty(propertyName); } else if (appendMode) { - file->AppendProperty(&makefile, propertyName, value, appendAsString); + file->AppendProperty(&makefile, propertyName, propertyValue, + appendAsString); } else { - file->SetProperty(&makefile, propertyName, value); + file->SetProperty(&makefile, propertyName, propertyValue); } return true; } diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index d47f121..b2d905e 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -72,8 +72,7 @@ bool cmSiteNameCommand(std::vector<std::string> const& args, } #endif status.GetMakefile().AddCacheDefinition( - args[0], siteName.c_str(), - "Name of the computer/site where compile is being run", + args[0], siteName, "Name of the computer/site where compile is being run", cmStateEnums::STRING); return true; diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index fd9cacd..ad59cd6 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -361,17 +361,20 @@ const char* cmSourceFile::GetProperty(const std::string& prop) const return output.c_str(); } - const char* retVal = this->Properties.GetPropertyValue(prop); + cmProp retVal = this->Properties.GetPropertyValue(prop); if (!retVal) { cmMakefile const* mf = this->Location.GetMakefile(); const bool chain = mf->GetState()->IsPropertyChained(prop, cmProperty::SOURCE_FILE); if (chain) { - return mf->GetProperty(prop, chain); + if (cmProp p = mf->GetProperty(prop, chain)) { + return p->c_str(); + } } + return nullptr; } - return retVal; + return retVal->c_str(); } const char* cmSourceFile::GetSafeProperty(const std::string& prop) const diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index 5f807b8..e852c05 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -4,6 +4,8 @@ #include <cassert> +#include <cm/string_view> + #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -152,7 +154,7 @@ bool cmSourceFileLocation::MatchesAmbiguousExtension( // Only a fixed set of extensions will be tried to match a file on // disk. One of these must match if loc refers to this source file. - std::string const& ext = this->Name.substr(loc.Name.size() + 1); + auto ext = cm::string_view(this->Name).substr(loc.Name.size() + 1); cmMakefile const* mf = this->Makefile; auto cm = mf->GetCMakeInstance(); return cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext); diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx index 8c3ec9f..155068cb 100644 --- a/Source/cmSourceGroup.cxx +++ b/Source/cmSourceGroup.cxx @@ -4,6 +4,8 @@ #include <utility> +#include <cm/memory> + #include "cmStringAlgorithms.h" class cmSourceGroupInternals @@ -16,7 +18,7 @@ cmSourceGroup::cmSourceGroup(std::string name, const char* regex, const char* parentName) : Name(std::move(name)) { - this->Internal = new cmSourceGroupInternals; + this->Internal = cm::make_unique<cmSourceGroupInternals>(); this->SetGroupRegex(regex); if (parentName) { this->FullName = cmStrCat(parentName, '\\'); @@ -24,10 +26,7 @@ cmSourceGroup::cmSourceGroup(std::string name, const char* regex, this->FullName += this->Name; } -cmSourceGroup::~cmSourceGroup() -{ - delete this->Internal; -} +cmSourceGroup::~cmSourceGroup() = default; cmSourceGroup::cmSourceGroup(cmSourceGroup const& r) { @@ -36,7 +35,7 @@ cmSourceGroup::cmSourceGroup(cmSourceGroup const& r) this->GroupRegex = r.GroupRegex; this->GroupFiles = r.GroupFiles; this->SourceFiles = r.SourceFiles; - this->Internal = new cmSourceGroupInternals(*r.Internal); + this->Internal = cm::make_unique<cmSourceGroupInternals>(*r.Internal); } cmSourceGroup& cmSourceGroup::operator=(cmSourceGroup const& r) diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h index 581dc5d..623cded 100644 --- a/Source/cmSourceGroup.h +++ b/Source/cmSourceGroup.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <set> #include <string> #include <vector> @@ -122,7 +123,7 @@ private: */ std::vector<const cmSourceFile*> SourceFiles; - cmSourceGroupInternals* Internal; + std::unique_ptr<cmSourceGroupInternals> Internal; }; #endif diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx index cc62952..8350410 100644 --- a/Source/cmSourceGroupCommand.cxx +++ b/Source/cmSourceGroupCommand.cxx @@ -30,18 +30,6 @@ std::vector<std::string> tokenizePath(const std::string& path) return cmTokenize(path, "\\/"); } -std::string getFullFilePath(const std::string& currentPath, - const std::string& path) -{ - std::string fullPath = path; - - if (!cmSystemTools::FileIsFullPath(path)) { - fullPath = cmStrCat(currentPath, '/', path); - } - - return cmSystemTools::CollapseFullPath(fullPath); -} - std::set<std::string> getSourceGroupFilesPaths( const std::string& root, const std::vector<std::string>& files) { @@ -124,7 +112,8 @@ bool addFilesToItsSourceGroups(const std::string& root, errorMsg = "Could not create source group for file: " + sgFilesPath; return false; } - const std::string fullPath = getFullFilePath(root, sgFilesPath); + const std::string fullPath = + cmSystemTools::CollapseFullPath(sgFilesPath, root); sg->AddGroupFile(fullPath); } } @@ -255,10 +244,8 @@ bool cmSourceGroupCommand(std::vector<std::string> const& args, parsedArguments[kFilesOptionName]; for (auto const& filesArg : filesArguments) { std::string src = filesArg; - if (!cmSystemTools::FileIsFullPath(src)) { - src = cmStrCat(mf.GetCurrentSourceDirectory(), '/', filesArg); - } - src = cmSystemTools::CollapseFullPath(src); + src = + cmSystemTools::CollapseFullPath(src, mf.GetCurrentSourceDirectory()); sg->AddGroupFile(src); } } diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h index 13f7622..55d23c1 100644 --- a/Source/cmStandardLexer.h +++ b/Source/cmStandardLexer.h @@ -3,6 +3,19 @@ #ifndef cmStandardLexer_h #define cmStandardLexer_h +#if !defined(_WIN32) && !defined(__sun) +/* POSIX APIs are needed */ +# define _POSIX_C_SOURCE 200809L +#endif +#if defined(__sun) && defined(__GNUC__) && !defined(__cplusplus) +/* C sources: for fileno and strdup */ +# define _XOPEN_SOURCE 600 +#endif +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) +/* For isascii */ +# define _XOPEN_SOURCE 700 +#endif + #include "cmsys/Configure.h" // IWYU pragma: keep /* Disable some warnings. */ diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 9fc7615..2dfdcf7 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -26,6 +26,8 @@ #include "cmSystemTools.h" #include "cmake.h" +using cmProp = const std::string*; + cmState::cmState() { this->CacheManager = cm::make_unique<cmCacheManager>(); @@ -34,30 +36,44 @@ cmState::cmState() cmState::~cmState() = default; -const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType) -{ +const std::string& cmState::GetTargetTypeName( + cmStateEnums::TargetType targetType) +{ +#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP + MAKE_STATIC_PROP(STATIC_LIBRARY); + MAKE_STATIC_PROP(MODULE_LIBRARY); + MAKE_STATIC_PROP(SHARED_LIBRARY); + MAKE_STATIC_PROP(OBJECT_LIBRARY); + MAKE_STATIC_PROP(EXECUTABLE); + MAKE_STATIC_PROP(UTILITY); + MAKE_STATIC_PROP(GLOBAL_TARGET); + MAKE_STATIC_PROP(INTERFACE_LIBRARY); + MAKE_STATIC_PROP(UNKNOWN_LIBRARY); + static const std::string propEmpty; +#undef MAKE_STATIC_PROP + switch (targetType) { case cmStateEnums::STATIC_LIBRARY: - return "STATIC_LIBRARY"; + return propSTATIC_LIBRARY; case cmStateEnums::MODULE_LIBRARY: - return "MODULE_LIBRARY"; + return propMODULE_LIBRARY; case cmStateEnums::SHARED_LIBRARY: - return "SHARED_LIBRARY"; + return propSHARED_LIBRARY; case cmStateEnums::OBJECT_LIBRARY: - return "OBJECT_LIBRARY"; + return propOBJECT_LIBRARY; case cmStateEnums::EXECUTABLE: - return "EXECUTABLE"; + return propEXECUTABLE; case cmStateEnums::UTILITY: - return "UTILITY"; + return propUTILITY; case cmStateEnums::GLOBAL_TARGET: - return "GLOBAL_TARGET"; + return propGLOBAL_TARGET; case cmStateEnums::INTERFACE_LIBRARY: - return "INTERFACE_LIBRARY"; + return propINTERFACE_LIBRARY; case cmStateEnums::UNKNOWN_LIBRARY: - return "UNKNOWN_LIBRARY"; + return propUNKNOWN_LIBRARY; } assert(false && "Unexpected target type"); - return nullptr; + return propEmpty; } static const std::array<std::string, 7> cmCacheEntryTypes = { @@ -132,23 +148,22 @@ std::vector<std::string> cmState::GetCacheEntryKeys() const return definitions; } -const char* cmState::GetCacheEntryValue(std::string const& key) const +cmProp cmState::GetCacheEntryValue(std::string const& key) const { cmCacheManager::CacheEntry* e = this->CacheManager->GetCacheEntry(key); if (!e) { return nullptr; } - return e->Value.c_str(); + return &e->Value; } std::string cmState::GetSafeCacheEntryValue(std::string const& key) const { - std::string retval; - auto val = this->GetCacheEntryValue(key); + cmProp val = this->GetCacheEntryValue(key); if (val) { - retval = val; + return *val; } - return retval; + return std::string(); } const std::string* cmState::GetInitializedCacheValue( @@ -193,8 +208,8 @@ std::vector<std::string> cmState::GetCacheEntryPropertyList( return it.GetPropertyList(); } -const char* cmState::GetCacheEntryProperty(std::string const& key, - std::string const& propertyName) +cmProp cmState::GetCacheEntryProperty(std::string const& key, + std::string const& propertyName) { cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); if (!it.PropertyExists(propertyName)) { @@ -335,8 +350,8 @@ cmStateSnapshot cmState::Reset() void cmState::DefineProperty(const std::string& name, cmProperty::ScopeType scope, - const char* ShortDescription, - const char* FullDescription, bool chained) + const std::string& ShortDescription, + const std::string& FullDescription, bool chained) { this->PropertyDefinitions[scope].DefineProperty( name, scope, ShortDescription, FullDescription, chained); @@ -573,7 +588,7 @@ void cmState::AppendGlobalProperty(const std::string& prop, this->GlobalProperties.AppendProperty(prop, value, asString); } -const char* cmState::GetGlobalProperty(const std::string& prop) +cmProp cmState::GetGlobalProperty(const std::string& prop) { if (prop == "CACHE_VARIABLES") { std::vector<std::string> cacheKeys = this->GetCacheEntryKeys(); @@ -597,31 +612,49 @@ const char* cmState::GetGlobalProperty(const std::string& prop) } #define STRING_LIST_ELEMENT(F) ";" #F if (prop == "CMAKE_C_KNOWN_FEATURES") { - return &FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT)[1]; + static const std::string s_out( + &FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT)[1]); + return &s_out; } if (prop == "CMAKE_C90_KNOWN_FEATURES") { - return &FOR_EACH_C90_FEATURE(STRING_LIST_ELEMENT)[1]; + static const std::string s_out( + &FOR_EACH_C90_FEATURE(STRING_LIST_ELEMENT)[1]); + return &s_out; } if (prop == "CMAKE_C99_KNOWN_FEATURES") { - return &FOR_EACH_C99_FEATURE(STRING_LIST_ELEMENT)[1]; + static const std::string s_out( + &FOR_EACH_C99_FEATURE(STRING_LIST_ELEMENT)[1]); + return &s_out; } if (prop == "CMAKE_C11_KNOWN_FEATURES") { - return &FOR_EACH_C11_FEATURE(STRING_LIST_ELEMENT)[1]; + static const std::string s_out( + &FOR_EACH_C11_FEATURE(STRING_LIST_ELEMENT)[1]); + return &s_out; } if (prop == "CMAKE_CXX_KNOWN_FEATURES") { - return &FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT)[1]; + static const std::string s_out( + &FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT)[1]); + return &s_out; } if (prop == "CMAKE_CXX98_KNOWN_FEATURES") { - return &FOR_EACH_CXX98_FEATURE(STRING_LIST_ELEMENT)[1]; + static const std::string s_out( + &FOR_EACH_CXX98_FEATURE(STRING_LIST_ELEMENT)[1]); + return &s_out; } if (prop == "CMAKE_CXX11_KNOWN_FEATURES") { - return &FOR_EACH_CXX11_FEATURE(STRING_LIST_ELEMENT)[1]; + static const std::string s_out( + &FOR_EACH_CXX11_FEATURE(STRING_LIST_ELEMENT)[1]); + return &s_out; } if (prop == "CMAKE_CXX14_KNOWN_FEATURES") { - return &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1]; + static const std::string s_out( + &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1]); + return &s_out; } if (prop == "CMAKE_CUDA_KNOWN_FEATURES") { - return &FOR_EACH_CUDA_FEATURE(STRING_LIST_ELEMENT)[1]; + static const std::string s_out( + &FOR_EACH_CUDA_FEATURE(STRING_LIST_ELEMENT)[1]); + return &s_out; } #undef STRING_LIST_ELEMENT @@ -630,7 +663,8 @@ const char* cmState::GetGlobalProperty(const std::string& prop) bool cmState::GetGlobalPropertyAsBool(const std::string& prop) { - return cmIsOn(this->GetGlobalProperty(prop)); + cmProp p = this->GetGlobalProperty(prop); + return p && cmIsOn(*p); } void cmState::SetSourceDirectory(std::string const& sourceDirectory) diff --git a/Source/cmState.h b/Source/cmState.h index 6ee2b0c..e3fbfdc 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -30,6 +30,8 @@ class cmStateSnapshot; class cmMessenger; class cmExecutionStatus; +using cmProp = const std::string*; + class cmState { friend class cmStateSnapshot; @@ -51,7 +53,8 @@ public: CPack, }; - static const char* GetTargetTypeName(cmStateEnums::TargetType targetType); + static const std::string& GetTargetTypeName( + cmStateEnums::TargetType targetType); cmStateSnapshot CreateBaseSnapshot(); cmStateSnapshot CreateBuildsystemDirectorySnapshot( @@ -87,7 +90,7 @@ public: bool DeleteCache(const std::string& path); std::vector<std::string> GetCacheEntryKeys() const; - const char* GetCacheEntryValue(std::string const& key) const; + cmProp GetCacheEntryValue(std::string const& key) const; std::string GetSafeCacheEntryValue(std::string const& key) const; const std::string* GetInitializedCacheValue(std::string const& key) const; cmStateEnums::CacheEntryType GetCacheEntryType(std::string const& key) const; @@ -102,8 +105,8 @@ public: void SetCacheEntryBoolProperty(std::string const& key, std::string const& propertyName, bool value); std::vector<std::string> GetCacheEntryPropertyList(std::string const& key); - const char* GetCacheEntryProperty(std::string const& key, - std::string const& propertyName); + cmProp GetCacheEntryProperty(std::string const& key, + std::string const& propertyName); bool GetCacheEntryPropertyAsBool(std::string const& key, std::string const& propertyName); void AppendCacheEntryProperty(std::string const& key, @@ -121,8 +124,8 @@ public: cmStateSnapshot Reset(); // Define a property void DefineProperty(const std::string& name, cmProperty::ScopeType scope, - const char* ShortDescription, - const char* FullDescription, bool chain = false); + const std::string& ShortDescription, + const std::string& FullDescription, bool chain = false); // get property definition cmPropertyDefinition const* GetPropertyDefinition( @@ -171,7 +174,7 @@ public: void SetGlobalProperty(const std::string& prop, const char* value); void AppendGlobalProperty(const std::string& prop, const std::string& value, bool asString = false); - const char* GetGlobalProperty(const std::string& prop); + cmProp GetGlobalProperty(const std::string& prop); bool GetGlobalPropertyAsBool(const std::string& prop); std::string const& GetSourceDirectory() const; diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 4f003ed..a4fe663 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -548,32 +548,31 @@ void cmStateDirectory::AppendProperty(const std::string& prop, this->DirectoryState->Properties.AppendProperty(prop, value, asString); } -const char* cmStateDirectory::GetProperty(const std::string& prop) const +cmProp cmStateDirectory::GetProperty(const std::string& prop) const { const bool chain = this->Snapshot_.State->IsPropertyChained(prop, cmProperty::DIRECTORY); return this->GetProperty(prop, chain); } -const char* cmStateDirectory::GetProperty(const std::string& prop, - bool chain) const +cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const { static std::string output; output.clear(); if (prop == "PARENT_DIRECTORY") { cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent(); if (parent.IsValid()) { - return parent.GetDirectory().GetCurrentSource().c_str(); + return &parent.GetDirectory().GetCurrentSource(); } - return ""; + return &output; } if (prop == kBINARY_DIR) { output = this->GetCurrentBinary(); - return output.c_str(); + return &output; } if (prop == kSOURCE_DIR) { output = this->GetCurrentSource(); - return output.c_str(); + return &output; } if (prop == kSUBDIRECTORIES) { std::vector<std::string> child_dirs; @@ -584,11 +583,11 @@ const char* cmStateDirectory::GetProperty(const std::string& prop, child_dirs.push_back(ci.GetDirectory().GetCurrentSource()); } output = cmJoin(child_dirs, ";"); - return output.c_str(); + return &output; } if (prop == kBUILDSYSTEM_TARGETS) { output = cmJoin(this->DirectoryState->NormalTargetNames, ";"); - return output.c_str(); + return &output; } if (prop == "LISTFILE_STACK") { @@ -600,41 +599,41 @@ const char* cmStateDirectory::GetProperty(const std::string& prop, } std::reverse(listFiles.begin(), listFiles.end()); output = cmJoin(listFiles, ";"); - return output.c_str(); + return &output; } if (prop == "CACHE_VARIABLES") { output = cmJoin(this->Snapshot_.State->GetCacheEntryKeys(), ";"); - return output.c_str(); + return &output; } if (prop == "VARIABLES") { std::vector<std::string> res = this->Snapshot_.ClosureKeys(); cm::append(res, this->Snapshot_.State->GetCacheEntryKeys()); std::sort(res.begin(), res.end()); output = cmJoin(res, ";"); - return output.c_str(); + return &output; } if (prop == "INCLUDE_DIRECTORIES") { output = cmJoin(this->GetIncludeDirectoriesEntries(), ";"); - return output.c_str(); + return &output; } if (prop == "COMPILE_OPTIONS") { output = cmJoin(this->GetCompileOptionsEntries(), ";"); - return output.c_str(); + return &output; } if (prop == "COMPILE_DEFINITIONS") { output = cmJoin(this->GetCompileDefinitionsEntries(), ";"); - return output.c_str(); + return &output; } if (prop == "LINK_OPTIONS") { output = cmJoin(this->GetLinkOptionsEntries(), ";"); - return output.c_str(); + return &output; } if (prop == "LINK_DIRECTORIES") { output = cmJoin(this->GetLinkDirectoriesEntries(), ";"); - return output.c_str(); + return &output; } - const char* retVal = this->DirectoryState->Properties.GetPropertyValue(prop); + cmProp retVal = this->DirectoryState->Properties.GetPropertyValue(prop); if (!retVal && chain) { cmStateSnapshot parentSnapshot = this->Snapshot_.GetBuildsystemDirectoryParent(); @@ -649,7 +648,8 @@ const char* cmStateDirectory::GetProperty(const std::string& prop, bool cmStateDirectory::GetPropertyAsBool(const std::string& prop) const { - return cmIsOn(this->GetProperty(prop)); + cmProp p = this->GetProperty(prop); + return p && cmIsOn(*p); } std::vector<std::string> cmStateDirectory::GetPropertyKeys() const diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index 53a2d54..8144160 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -16,6 +16,8 @@ #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" +using cmProp = const std::string*; + class cmStateDirectory { cmStateDirectory( @@ -86,8 +88,8 @@ public: cmListFileBacktrace const& lfbt); void AppendProperty(const std::string& prop, const std::string& value, bool asString, cmListFileBacktrace const& lfbt); - const char* GetProperty(const std::string& prop) const; - const char* GetProperty(const std::string& prop, bool chain) const; + cmProp GetProperty(const std::string& prop) const; + cmProp GetProperty(const std::string& prop, bool chain) const; bool GetPropertyAsBool(const std::string& prop) const; std::vector<std::string> GetPropertyKeys() const; diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 832e74e..d79df6f 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -411,11 +411,12 @@ void cmStateSnapshot::InitializeFromParent() this->Position->BuildSystemDirectory->LinkDirectoriesBacktraces, this->Position->LinkDirectoriesPosition); - const char* include_regex = + cmProp include_regex = parent->BuildSystemDirectory->Properties.GetPropertyValue( "INCLUDE_REGULAR_EXPRESSION"); this->Position->BuildSystemDirectory->Properties.SetProperty( - "INCLUDE_REGULAR_EXPRESSION", include_regex); + "INCLUDE_REGULAR_EXPRESSION", + include_regex ? include_regex->c_str() : nullptr); } cmState* cmStateSnapshot::GetState() const diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 9212195..7662204 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -124,6 +124,27 @@ bool HandleAsciiCommand(std::vector<std::string> const& args, return true; } +bool HandleHexCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() != 3) { + status.SetError("Incorrect number of arguments"); + return false; + } + auto const& instr = args[1]; + auto const& outvar = args[2]; + std::string output(instr.size() * 2, ' '); + + std::string::size_type hexIndex = 0; + for (auto const& c : instr) { + sprintf(&output[hexIndex], "%.2x", static_cast<unsigned char>(c) & 0xFF); + hexIndex += 2; + } + + status.GetMakefile().AddDefinition(outvar, output); + return true; +} + bool HandleConfigureCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -936,6 +957,7 @@ bool cmStringCommand(std::vector<std::string> const& args, { "TOUPPER"_s, HandleToUpperCommand }, { "COMPARE"_s, HandleCompareCommand }, { "ASCII"_s, HandleAsciiCommand }, + { "HEX"_s, HandleHexCommand }, { "CONFIGURE"_s, HandleConfigureCommand }, { "LENGTH"_s, HandleLengthCommand }, { "APPEND"_s, HandleAppendCommand }, diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 9127c50..d290c0c 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1,5 +1,15 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ + +#if !defined(_WIN32) && !defined(__sun) +// POSIX APIs are needed +# define _POSIX_C_SOURCE 200809L +#endif +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) +// For isascii +# define _XOPEN_SOURCE 700 +#endif + #include "cmSystemTools.h" #include <cmext/algorithm> @@ -25,6 +35,9 @@ #endif #if !defined(CMAKE_BOOTSTRAP) +# if defined(_WIN32) +# include <cm/memory> +# endif # include "cmCryptoHash.h" #endif @@ -908,7 +921,6 @@ std::string cmSystemTools::ComputeCertificateThumbprint( std::string thumbprint; #if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) - BYTE* certData = NULL; CRYPT_INTEGER_BLOB cryptBlob; HCERTSTORE certStore = NULL; PCCERT_CONTEXT certContext = NULL; @@ -920,12 +932,12 @@ std::string cmSystemTools::ComputeCertificateThumbprint( if (certFile != INVALID_HANDLE_VALUE && certFile != NULL) { DWORD fileSize = GetFileSize(certFile, NULL); if (fileSize != INVALID_FILE_SIZE) { - certData = new BYTE[fileSize]; + auto certData = cm::make_unique<BYTE[]>(fileSize); if (certData != NULL) { DWORD dwRead = 0; - if (ReadFile(certFile, certData, fileSize, &dwRead, NULL)) { + if (ReadFile(certFile, certData.get(), fileSize, &dwRead, NULL)) { cryptBlob.cbData = fileSize; - cryptBlob.pbData = certData; + cryptBlob.pbData = certData.get(); // Verify that this is a valid cert if (PFXIsPFXBlob(&cryptBlob)) { @@ -961,7 +973,6 @@ std::string cmSystemTools::ComputeCertificateThumbprint( } } } - delete[] certData; } } CloseHandle(certFile); @@ -1054,8 +1065,7 @@ bool cmSystemTools::SimpleGlob(const std::string& glob, if (type < 0 && !cmSystemTools::FileIsDirectory(fname)) { continue; } - if (sfname.size() >= ppath.size() && - sfname.substr(0, ppath.size()) == ppath) { + if (cmHasPrefix(sfname, ppath)) { files.push_back(fname); res = true; } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 97d7fce..063576c 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -78,7 +78,7 @@ const std::string& cmTargetPropertyComputer::ComputeLocation<cmTarget>( } template <> -const char* cmTargetPropertyComputer::GetSources<cmTarget>( +cmProp cmTargetPropertyComputer::GetSources<cmTarget>( cmTarget const* tgt, cmMessenger* messenger, cmListFileBacktrace const& context) { @@ -156,7 +156,7 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>( } static std::string srcs; srcs = ss.str(); - return srcs.c_str(); + return &srcs; } class cmTargetInternals @@ -300,6 +300,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("PDB_OUTPUT_DIRECTORY"); initProp("COMPILE_PDB_OUTPUT_DIRECTORY"); initProp("FRAMEWORK"); + initProp("FRAMEWORK_MULTI_CONFIG_POSTFIX"); initProp("Fortran_FORMAT"); initProp("Fortran_MODULE_DIRECTORY"); initProp("Fortran_COMPILER_LAUNCHER"); @@ -367,6 +368,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("DISABLE_PRECOMPILE_HEADERS"); initProp("UNITY_BUILD"); initPropValue("UNITY_BUILD_BATCH_SIZE", "8"); + initPropValue("PCH_WARN_INVALID", "ON"); #ifdef __APPLE__ if (this->GetGlobalGenerator()->IsXcode()) { initProp("XCODE_SCHEME_ADDRESS_SANITIZER"); @@ -435,6 +437,13 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, cmStrCat(cmSystemTools::UpperCase(configName), "_POSTFIX"); initProp(property); } + + if (impl->TargetType == cmStateEnums::SHARED_LIBRARY || + impl->TargetType == cmStateEnums::STATIC_LIBRARY) { + std::string property = cmStrCat("FRAMEWORK_MULTI_CONFIG_POSTFIX_", + cmSystemTools::UpperCase(configName)); + initProp(property); + } } } @@ -880,7 +889,7 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const cmListFileContext lfc = cmd.second; lfc.FilePath = cmDir.ConvertToRelPathIfNotContained( impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath); - s << " * " << lfc << std::endl; + s << " * " << lfc << '\n'; } } } @@ -999,7 +1008,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, dependencies += ";"; dependencies += lib; dependencies += ";"; - mf.AddCacheDefinition(targetEntry, dependencies.c_str(), + mf.AddCacheDefinition(targetEntry, dependencies, "Dependencies for the target", cmStateEnums::STATIC); } } @@ -1292,8 +1301,8 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", cmStrCat(reusedFrom, ".dir/")); - this->SetProperty("COMPILE_PDB_NAME", - reusedTarget->GetProperty("COMPILE_PDB_NAME")); + cmProp tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME"); + this->SetProperty("COMPILE_PDB_NAME", tmp ? tmp->c_str() : nullptr); this->AddUtility(reusedFrom, false, impl->Makefile); } else { impl->Properties.SetProperty(prop, value); @@ -1497,7 +1506,7 @@ void cmTarget::InsertPrecompileHeader(std::string const& entry, } static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop, - const char* value, + const std::string& value, cmMakefile* context, bool imported) { @@ -1535,7 +1544,7 @@ static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop, context->IssueMessage(MessageType::FATAL_ERROR, e.str()); } -static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, +static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const std::string& value, cmMakefile* context) { // Look for link-type keywords in the value. @@ -1580,18 +1589,18 @@ void cmTarget::CheckProperty(const std::string& prop, { // Certain properties need checking. if (cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES")) { - if (const char* value = this->GetProperty(prop)) { - cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, false); + if (cmProp value = this->GetProperty(prop)) { + cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, *value, context, false); } } if (cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES")) { - if (const char* value = this->GetProperty(prop)) { - cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true); + if (cmProp value = this->GetProperty(prop)) { + cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, *value, context, true); } } if (prop == "INTERFACE_LINK_LIBRARIES") { - if (const char* value = this->GetProperty(prop)) { - cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context); + if (cmProp value = this->GetProperty(prop)) { + cmTargetCheckINTERFACE_LINK_LIBRARIES(*value, context); } } if (prop == "IMPORTED_GLOBAL") { @@ -1601,14 +1610,14 @@ void cmTarget::CheckProperty(const std::string& prop, } } -const char* cmTarget::GetComputedProperty( - const std::string& prop, cmMessenger* messenger, - cmListFileBacktrace const& context) const +cmProp cmTarget::GetComputedProperty(const std::string& prop, + cmMessenger* messenger, + cmListFileBacktrace const& context) const { return cmTargetPropertyComputer::GetProperty(this, prop, messenger, context); } -const char* cmTarget::GetProperty(const std::string& prop) const +cmProp cmTarget::GetProperty(const std::string& prop) const { #define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP MAKE_STATIC_PROP(LINK_LIBRARIES); @@ -1627,6 +1636,8 @@ const char* cmTarget::GetProperty(const std::string& prop) const MAKE_STATIC_PROP(BINARY_DIR); MAKE_STATIC_PROP(SOURCE_DIR); MAKE_STATIC_PROP(SOURCES); + MAKE_STATIC_PROP(FALSE); + MAKE_STATIC_PROP(TRUE); #undef MAKE_STATIC_PROP static std::unordered_set<std::string> const specialProps{ propLINK_LIBRARIES, @@ -1654,11 +1665,11 @@ const char* cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(impl->LinkImplementationPropertyEntries, ";"); - return output.c_str(); + return &output; } // the type property returns what type the target is if (prop == propTYPE) { - return cmState::GetTargetTypeName(this->GetType()); + return &cmState::GetTargetTypeName(this->GetType()); } if (prop == propINCLUDE_DIRECTORIES) { if (impl->IncludeDirectoriesEntries.empty()) { @@ -1667,7 +1678,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(impl->IncludeDirectoriesEntries, ";"); - return output.c_str(); + return &output; } if (prop == propCOMPILE_FEATURES) { if (impl->CompileFeaturesEntries.empty()) { @@ -1676,7 +1687,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(impl->CompileFeaturesEntries, ";"); - return output.c_str(); + return &output; } if (prop == propCOMPILE_OPTIONS) { if (impl->CompileOptionsEntries.empty()) { @@ -1685,7 +1696,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(impl->CompileOptionsEntries, ";"); - return output.c_str(); + return &output; } if (prop == propCOMPILE_DEFINITIONS) { if (impl->CompileDefinitionsEntries.empty()) { @@ -1694,7 +1705,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(impl->CompileDefinitionsEntries, ";"); - return output.c_str(); + return &output; } if (prop == propLINK_OPTIONS) { if (impl->LinkOptionsEntries.empty()) { @@ -1703,7 +1714,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(impl->LinkOptionsEntries, ";"); - return output.c_str(); + return &output; } if (prop == propLINK_DIRECTORIES) { if (impl->LinkDirectoriesEntries.empty()) { @@ -1713,7 +1724,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(impl->LinkDirectoriesEntries, ";"); - return output.c_str(); + return &output; } if (prop == propMANUALLY_ADDED_DEPENDENCIES) { if (impl->Utilities.empty()) { @@ -1729,7 +1740,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const return item.Value.first; }); output = cmJoin(utilities, ";"); - return output.c_str(); + return &output; } if (prop == propPRECOMPILE_HEADERS) { if (impl->PrecompileHeadersEntries.empty()) { @@ -1738,32 +1749,30 @@ const char* cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(impl->PrecompileHeadersEntries, ";"); - return output.c_str(); + return &output; } if (prop == propIMPORTED) { - return this->IsImported() ? "TRUE" : "FALSE"; + return this->IsImported() ? &propTRUE : &propFALSE; } if (prop == propIMPORTED_GLOBAL) { - return this->IsImportedGloballyVisible() ? "TRUE" : "FALSE"; + return this->IsImportedGloballyVisible() ? &propTRUE : &propFALSE; } if (prop == propNAME) { - return this->GetName().c_str(); + return &this->GetName(); } if (prop == propBINARY_DIR) { - return impl->Makefile->GetStateSnapshot() - .GetDirectory() - .GetCurrentBinary() - .c_str(); + return &impl->Makefile->GetStateSnapshot() + .GetDirectory() + .GetCurrentBinary(); } if (prop == propSOURCE_DIR) { - return impl->Makefile->GetStateSnapshot() - .GetDirectory() - .GetCurrentSource() - .c_str(); + return &impl->Makefile->GetStateSnapshot() + .GetDirectory() + .GetCurrentSource(); } } - const char* retVal = impl->Properties.GetPropertyValue(prop); + cmProp retVal = impl->Properties.GetPropertyValue(prop); if (!retVal) { const bool chain = impl->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TARGET); @@ -1771,22 +1780,24 @@ const char* cmTarget::GetProperty(const std::string& prop) const return impl->Makefile->GetStateSnapshot().GetDirectory().GetProperty( prop, chain); } + return nullptr; } return retVal; } const char* cmTarget::GetSafeProperty(const std::string& prop) const { - const char* ret = this->GetProperty(prop); + cmProp ret = this->GetProperty(prop); if (!ret) { return ""; } - return ret; + return ret->c_str(); } bool cmTarget::GetPropertyAsBool(const std::string& prop) const { - return cmIsOn(this->GetProperty(prop)); + cmProp p = this->GetProperty(prop); + return p && cmIsOn(*p); } cmPropertyMap const& cmTarget::GetProperties() const @@ -1915,38 +1926,37 @@ std::string cmTarget::ImportedGetFullPath( std::string result; - const char* loc = nullptr; - const char* imp = nullptr; + cmProp loc = nullptr; + cmProp imp = nullptr; std::string suffix; if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && - this->GetMappedConfig(desired_config, &loc, &imp, suffix)) { + this->GetMappedConfig(desired_config, loc, imp, suffix)) { switch (artifact) { case cmStateEnums::RuntimeBinaryArtifact: if (loc) { - result = loc; + result = *loc; } else { std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix); - if (const char* config_location = this->GetProperty(impProp)) { - result = config_location; - } else if (const char* location = + if (cmProp config_location = this->GetProperty(impProp)) { + result = *config_location; + } else if (cmProp location = this->GetProperty("IMPORTED_LOCATION")) { - result = location; + result = *location; } } break; case cmStateEnums::ImportLibraryArtifact: if (imp) { - result = imp; + result = *imp; } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->IsExecutableWithExports()) { std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); - if (const char* config_implib = this->GetProperty(impProp)) { - result = config_implib; - } else if (const char* implib = - this->GetProperty("IMPORTED_IMPLIB")) { - result = implib; + if (cmProp config_implib = this->GetProperty(impProp)) { + result = *config_implib; + } else if (cmProp implib = this->GetProperty("IMPORTED_IMPLIB")) { + result = *implib; } } break; @@ -1989,9 +1999,8 @@ bool cmTargetInternals::CheckImportedLibName(std::string const& prop, return true; } -bool cmTarget::GetMappedConfig(std::string const& desired_config, - const char** loc, const char** imp, - std::string& suffix) const +bool cmTarget::GetMappedConfig(std::string const& desired_config, cmProp& loc, + cmProp& imp, std::string& suffix) const { std::string config_upper; if (!desired_config.empty()) { @@ -2013,8 +2022,8 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, std::vector<std::string> mappedConfigs; { std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", config_upper); - if (const char* mapValue = this->GetProperty(mapProp)) { - cmExpandList(mapValue, mappedConfigs, true); + if (cmProp mapValue = this->GetProperty(mapProp)) { + cmExpandList(*mapValue, mappedConfigs, true); } } @@ -2028,30 +2037,30 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, // If a mapping was found, check its configurations. for (auto mci = mappedConfigs.begin(); - !*loc && !*imp && mci != mappedConfigs.end(); ++mci) { + !loc && !imp && mci != mappedConfigs.end(); ++mci) { // Look for this configuration. if (mci->empty()) { // An empty string in the mapping has a special meaning: // look up the config-less properties. - *loc = this->GetProperty(locPropBase); + loc = this->GetProperty(locPropBase); if (allowImp) { - *imp = this->GetProperty("IMPORTED_IMPLIB"); + imp = this->GetProperty("IMPORTED_IMPLIB"); } // If it was found, set the suffix. - if (*loc || *imp) { + if (loc || imp) { suffix.clear(); } } else { std::string mcUpper = cmSystemTools::UpperCase(*mci); std::string locProp = cmStrCat(locPropBase, '_', mcUpper); - *loc = this->GetProperty(locProp); + loc = this->GetProperty(locProp); if (allowImp) { std::string impProp = cmStrCat("IMPORTED_IMPLIB_", mcUpper); - *imp = this->GetProperty(impProp); + imp = this->GetProperty(impProp); } // If it was found, use it for all properties below. - if (*loc || *imp) { + if (loc || imp) { suffix = cmStrCat('_', mcUpper); } } @@ -2060,59 +2069,59 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, // If we needed to find one of the mapped configurations but did not // then the target location is not found. The project does not want // any other configuration. - if (!mappedConfigs.empty() && !*loc && !*imp) { + if (!mappedConfigs.empty() && !loc && !imp) { // Interface libraries are always available because their - // library name is optional so it is okay to leave *loc empty. + // library name is optional so it is okay to leave loc empty. return this->GetType() == cmStateEnums::INTERFACE_LIBRARY; } // If we have not yet found it then there are no mapped // configurations. Look for an exact-match. - if (!*loc && !*imp) { + if (!loc && !imp) { std::string locProp = cmStrCat(locPropBase, suffix); - *loc = this->GetProperty(locProp); + loc = this->GetProperty(locProp); if (allowImp) { std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); - *imp = this->GetProperty(impProp); + imp = this->GetProperty(impProp); } } // If we have not yet found it then there are no mapped // configurations and no exact match. - if (!*loc && !*imp) { + if (!loc && !imp) { // The suffix computed above is not useful. suffix.clear(); // Look for a configuration-less location. This may be set by // manually-written code. - *loc = this->GetProperty(locPropBase); + loc = this->GetProperty(locPropBase); if (allowImp) { - *imp = this->GetProperty("IMPORTED_IMPLIB"); + imp = this->GetProperty("IMPORTED_IMPLIB"); } } // If we have not yet found it then the project is willing to try // any available configuration. - if (!*loc && !*imp) { + if (!loc && !imp) { std::vector<std::string> availableConfigs; - if (const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) { - cmExpandList(iconfigs, availableConfigs); + if (cmProp iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) { + cmExpandList(*iconfigs, availableConfigs); } for (auto aci = availableConfigs.begin(); - !*loc && !*imp && aci != availableConfigs.end(); ++aci) { + !loc && !imp && aci != availableConfigs.end(); ++aci) { suffix = cmStrCat('_', cmSystemTools::UpperCase(*aci)); std::string locProp = cmStrCat(locPropBase, suffix); - *loc = this->GetProperty(locProp); + loc = this->GetProperty(locProp); if (allowImp) { std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); - *imp = this->GetProperty(impProp); + imp = this->GetProperty(impProp); } } } // If we have not yet found it then the target location is not available. - if (!*loc && !*imp) { + if (!loc && !imp) { // Interface libraries are always available because their - // library name is optional so it is okay to leave *loc empty. + // library name is optional so it is okay to leave loc empty. return this->GetType() == cmStateEnums::INTERFACE_LIBRARY; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 286933b..ddc3b9b 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -28,6 +28,8 @@ class cmPropertyMap; class cmSourceFile; class cmTargetInternals; +using cmProp = const std::string*; + /** \class cmTarget * \brief Represent a library or executable target loaded from a makefile. * @@ -170,14 +172,13 @@ public: void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); //! Might return a nullptr if the property is not set or invalid - const char* GetProperty(const std::string& prop) const; + cmProp GetProperty(const std::string& prop) const; //! Always returns a valid pointer const char* GetSafeProperty(const std::string& prop) const; bool GetPropertyAsBool(const std::string& prop) const; void CheckProperty(const std::string& prop, cmMakefile* context) const; - const char* GetComputedProperty(const std::string& prop, - cmMessenger* messenger, - cmListFileBacktrace const& context) const; + cmProp GetComputedProperty(const std::string& prop, cmMessenger* messenger, + cmListFileBacktrace const& context) const; //! Get all properties cmPropertyMap const& GetProperties() const; @@ -191,8 +192,8 @@ public: bool IsImportedGloballyVisible() const; bool IsPerConfig() const; - bool GetMappedConfig(std::string const& desired_config, const char** loc, - const char** imp, std::string& suffix) const; + bool GetMappedConfig(std::string const& desired_config, cmProp& loc, + cmProp& imp, std::string& suffix) const; //! Return whether this target is an executable with symbol exports enabled. bool IsExecutableWithExports() const; diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 0de8d6d..6325837 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -9,6 +9,8 @@ #include "cmTarget.h" #include "cmake.h" +using cmProp = const std::string*; + cmTargetPropCommandBase::cmTargetPropCommandBase(cmExecutionStatus& status) : Makefile(&status.GetMakefile()) , Status(status) @@ -157,9 +159,9 @@ void cmTargetPropCommandBase::HandleInterfaceContent( { if (prepend) { const std::string propName = std::string("INTERFACE_") + this->Property; - const char* propValue = tgt->GetProperty(propName); - const std::string totalContent = this->Join(content) + - (propValue ? std::string(";") + propValue : std::string()); + cmProp propValue = tgt->GetProperty(propName); + const std::string totalContent = + this->Join(content) + (propValue ? (";" + *propValue) : std::string()); tgt->SetProperty(propName, totalContent); } else { tgt->AppendProperty("INTERFACE_" + this->Property, this->Join(content)); diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h index df34f18..5387e00 100644 --- a/Source/cmTargetPropertyComputer.h +++ b/Source/cmTargetPropertyComputer.h @@ -14,15 +14,17 @@ class cmMessenger; +using cmProp = const std::string*; + class cmTargetPropertyComputer { public: template <typename Target> - static const char* GetProperty(Target const* tgt, const std::string& prop, - cmMessenger* messenger, - cmListFileBacktrace const& context) + static cmProp GetProperty(Target const* tgt, const std::string& prop, + cmMessenger* messenger, + cmListFileBacktrace const& context) { - if (const char* loc = GetLocation(tgt, prop, messenger, context)) { + if (cmProp loc = GetLocation(tgt, prop, messenger, context)) { return loc; } if (cmSystemTools::GetFatalErrorOccured()) { @@ -52,9 +54,9 @@ private: std::string const& config); template <typename Target> - static const char* GetLocation(Target const* tgt, std::string const& prop, - cmMessenger* messenger, - cmListFileBacktrace const& context) + static cmProp GetLocation(Target const* tgt, std::string const& prop, + cmMessenger* messenger, + cmListFileBacktrace const& context) { // Watch for special "computed" properties that are dependent on @@ -71,7 +73,7 @@ private: context)) { return nullptr; } - return ComputeLocationForBuild(tgt).c_str(); + return &ComputeLocationForBuild(tgt); } // Support "LOCATION_<CONFIG>". @@ -82,7 +84,7 @@ private: return nullptr; } std::string configName = prop.substr(9); - return ComputeLocation(tgt, configName).c_str(); + return &ComputeLocation(tgt, configName); } // Support "<CONFIG>_LOCATION". @@ -95,7 +97,7 @@ private: context)) { return nullptr; } - return ComputeLocation(tgt, configName).c_str(); + return &ComputeLocation(tgt, configName); } } } @@ -103,8 +105,8 @@ private: } template <typename Target> - static const char* GetSources(Target const* tgt, cmMessenger* messenger, - cmListFileBacktrace const& context); + static cmProp GetSources(Target const* tgt, cmMessenger* messenger, + cmListFileBacktrace const& context); }; #endif diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index 3b731cc..a26bef3 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -34,15 +34,18 @@ void cmTest::SetCommand(std::vector<std::string> const& command) const char* cmTest::GetProperty(const std::string& prop) const { - const char* retVal = this->Properties.GetPropertyValue(prop); + cmProp retVal = this->Properties.GetPropertyValue(prop); if (!retVal) { const bool chain = this->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TEST); if (chain) { - return this->Makefile->GetProperty(prop, chain); + if (cmProp p = this->Makefile->GetProperty(prop, chain)) { + return p->c_str(); + } } + return nullptr; } - return retVal; + return retVal->c_str(); } bool cmTest::GetPropertyAsBool(const std::string& prop) const diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 333d4d5..1142dbd 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -134,7 +134,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, ge.Parse(i.second)->Evaluate(this->LG, config)); } this->GenerateInternalProperties(os); - os << ")" << std::endl; + os << ")\n"; } void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent) @@ -176,9 +176,9 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent) } fout << c; } - fout << "\""; + fout << '"'; } - fout << ")" << std::endl; + fout << ")\n"; // Output properties for the test. fout << indent << "set_tests_properties(" << this->Test->GetName() @@ -188,7 +188,7 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent) << cmOutputConverter::EscapeForCMake(i.second); } this->GenerateInternalProperties(fout); - fout << ")" << std::endl; + fout << ")\n"; } void cmTestGenerator::GenerateInternalProperties(std::ostream& os) @@ -213,7 +213,7 @@ void cmTestGenerator::GenerateInternalProperties(std::ostream& os) prependTripleSeparator = true; } - os << "\""; + os << '"'; } std::vector<std::string> cmTestGenerator::EvaluateCommandLineArguments( diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 390fd16..13f73dc 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -1,5 +1,15 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ + +#if !defined(_WIN32) && !defined(__sun) +// POSIX APIs are needed +# define _POSIX_C_SOURCE 200809L +#endif +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) +// For isascii +# define _XOPEN_SOURCE 700 +#endif + #include "cmTimestamp.h" #include <cstdlib> diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index 0e8e986..329b3b9 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -242,8 +242,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, comment.c_str(), cmStateEnums::STRING); cmState* state = this->Makefile->GetState(); - const char* existingValue = - state->GetCacheEntryValue(this->RunResultVariable); + cmProp existingValue = state->GetCacheEntryValue(this->RunResultVariable); if (existingValue) { state->SetCacheEntryProperty(this->RunResultVariable, "ADVANCED", "1"); } @@ -265,7 +264,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, internalRunOutputName, "PLEASE_FILL_OUT-NOTFOUND", comment.c_str(), cmStateEnums::STRING); cmState* state = this->Makefile->GetState(); - const char* existing = state->GetCacheEntryValue(internalRunOutputName); + cmProp existing = state->GetCacheEntryValue(internalRunOutputName); if (existing) { state->SetCacheEntryProperty(internalRunOutputName, "ADVANCED", "1"); } diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index a43165c..5865a19 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -102,15 +102,15 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args, cmSystemTools::ReplaceString(utilityExecutable, "/./", "/"); // Enter the value into the cache. - status.GetMakefile().AddCacheDefinition( - cacheEntry, utilityExecutable.c_str(), "Path to an internal program.", - cmStateEnums::FILEPATH); + status.GetMakefile().AddCacheDefinition(cacheEntry, utilityExecutable, + "Path to an internal program.", + cmStateEnums::FILEPATH); // add a value into the cache that maps from the // full path to the name of the project cmSystemTools::ConvertToUnixSlashes(utilityExecutable); - status.GetMakefile().AddCacheDefinition( - utilityExecutable, utilityName.c_str(), "Executable to project name.", - cmStateEnums::INTERNAL); + status.GetMakefile().AddCacheDefinition(utilityExecutable, utilityName, + "Executable to project name.", + cmStateEnums::INTERNAL); return true; } diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index 35b9a1d..ecae16d 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -42,7 +42,7 @@ void cmVariableWatchCommandVariableAccessed(const std::string& variable, /// Ultra bad!! cmMakefile* makefile = const_cast<cmMakefile*>(mf); - std::string stack = makefile->GetProperty("LISTFILE_STACK"); + std::string stack = *mf->GetProperty("LISTFILE_STACK"); if (!data->Command.empty()) { cmListFileFunction newLFF; const char* const currentListFile = diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 8da113e..ec7fe96 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -6,6 +6,7 @@ #include <set> #include <cm/memory> +#include <cm/string_view> #include <cm/vector> #include "windows.h" @@ -22,6 +23,7 @@ #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVisualStudioGeneratorOptions.h" @@ -61,10 +63,10 @@ struct cmVisualStudio10TargetGenerator::Elem this->StartElement(); } Elem(const Elem&) = delete; - Elem(Elem& par, const std::string& tag) + Elem(Elem& par, cm::string_view tag) : S(par.S) , Indent(par.Indent + 1) - , Tag(tag) + , Tag(std::string(tag)) { par.SetHasElements(); this->StartElement(); @@ -78,22 +80,22 @@ struct cmVisualStudio10TargetGenerator::Elem } std::ostream& WriteString(const char* line); void StartElement() { this->WriteString("<") << this->Tag; } - void Element(const std::string& tag, const std::string& val) + void Element(cm::string_view tag, std::string val) { - Elem(*this, tag).Content(val); + Elem(*this, tag).Content(std::move(val)); } - Elem& Attribute(const char* an, const std::string& av) + Elem& Attribute(const char* an, std::string av) { - this->S << " " << an << "=\"" << cmVS10EscapeAttr(av) << "\""; + this->S << " " << an << "=\"" << cmVS10EscapeAttr(std::move(av)) << "\""; return *this; } - void Content(const std::string& val) + void Content(std::string val) { if (!this->HasContent) { this->S << ">"; this->HasContent = true; } - this->S << cmVS10EscapeXML(val); + this->S << cmVS10EscapeXML(std::move(val)); } ~Elem() { @@ -556,10 +558,11 @@ void cmVisualStudio10TargetGenerator::Generate() std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys(); for (std::string const& keyIt : keys) { - static const char* prefix = "VS_GLOBAL_"; - if (keyIt.find(prefix) != 0) + static const cm::string_view prefix = "VS_GLOBAL_"; + if (!cmHasPrefix(keyIt, prefix)) continue; - std::string globalKey = keyIt.substr(strlen(prefix)); + cm::string_view globalKey = + cm::string_view(keyIt).substr(prefix.length()); // Skip invalid or separately-handled properties. if (globalKey.empty() || globalKey == "PROJECT_TYPES" || globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") { @@ -790,21 +793,14 @@ void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0) for (std::string const& ri : packageReferences) { size_t versionIndex = ri.find_last_of('_'); if (versionIndex != std::string::npos) { - WritePackageReference(e1, ri.substr(0, versionIndex), - ri.substr(versionIndex + 1)); + Elem e2(e1, "PackageReference"); + e2.Attribute("Include", ri.substr(0, versionIndex)); + e2.Attribute("Version", ri.substr(versionIndex + 1)); } } } } -void cmVisualStudio10TargetGenerator::WritePackageReference( - Elem& e1, std::string const& ref, std::string const& version) -{ - Elem e2(e1, "PackageReference"); - e2.Attribute("Include", ref); - e2.Attribute("Version", version); -} - void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) { std::vector<std::string> references; @@ -814,17 +810,15 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) } cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties(); for (auto const& i : props.GetList()) { - if (i.first.find("VS_DOTNET_REFERENCE_") == 0) { - std::string name = i.first.substr(20); - if (!name.empty()) { - std::string path = i.second; - if (!cmsys::SystemTools::FileIsFullPath(path)) { - path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; - } - ConvertToWindowsSlash(path); - this->DotNetHintReferences[""].push_back( - DotNetHintReference(name, path)); + static const cm::string_view vsDnRef = "VS_DOTNET_REFERENCE_"; + if (cmHasPrefix(i.first, vsDnRef)) { + std::string path = i.second; + if (!cmsys::SystemTools::FileIsFullPath(path)) { + path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; } + ConvertToWindowsSlash(path); + this->DotNetHintReferences[""].emplace_back( + DotNetHintReference(i.first.substr(vsDnRef.length()), path)); } } if (!references.empty() || !this->DotNetHintReferences.empty()) { @@ -837,7 +831,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) cmsys::SystemTools::GetFilenameWithoutLastExtension(ri); std::string path = ri; ConvertToWindowsSlash(path); - this->DotNetHintReferences[""].push_back( + this->DotNetHintReferences[""].emplace_back( DotNetHintReference(name, path)); } else { this->WriteDotNetReference(e1, ri, "", ""); @@ -883,11 +877,10 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference( void cmVisualStudio10TargetGenerator::WriteImports(Elem& e0) { - const char* imports = + cmProp imports = this->GeneratorTarget->Target->GetProperty("VS_PROJECT_IMPORT"); if (imports) { - std::vector<std::string> argsSplit = - cmExpandedList(std::string(imports), false); + std::vector<std::string> argsSplit = cmExpandedList(*imports, false); for (auto& path : argsSplit) { if (!cmsys::SystemTools::FileIsFullPath(path)) { path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; @@ -910,12 +903,8 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags( CustomTags tags; cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties(); for (const auto& i : props.GetList()) { - if (i.first.find(refPropFullPrefix) == 0) { - std::string refTag = i.first.substr(refPropFullPrefix.length()); - std::string refVal = i.second; - if (!refTag.empty() && !refVal.empty()) { - tags[refTag] = refVal; - } + if (cmHasPrefix(i.first, refPropFullPrefix) && !i.second.empty()) { + tags[i.first.substr(refPropFullPrefix.length())] = i.second; } } for (auto const& tag : tags) { @@ -952,7 +941,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) // subdirectory // of the .csproj file, we have to use relative pathnames, otherwise // visual studio does not show the file in the IDE. Sorry. - if (obj.find(srcDir) == 0) { + if (cmHasPrefix(obj, srcDir)) { obj = this->ConvertPath(obj, true); ConvertToWindowsSlash(obj); useRelativePath = true; @@ -981,17 +970,11 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) // If the resource was NOT added using a relative path (which should // be the default), we have to provide a link here if (!useRelativePath) { - std::string link; - if (obj.find(srcDir) == 0) { - link = obj.substr(srcDir.length() + 1); - } else if (obj.find(binDir) == 0) { - link = obj.substr(binDir.length() + 1); - } else { + std::string link = this->GetCSharpSourceLink(oi); + if (link.empty()) { link = cmsys::SystemTools::GetFilenameName(obj); } - if (!link.empty()) { - e2.Element("Link", link); - } + e2.Element("Link", link); } // Determine if this is a generated resource from a .Designer.cs file std::string designerResource = @@ -1005,10 +988,10 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) } if (!generator.empty()) { e2.Element("Generator", generator); - if (designerResource.find(srcDir) == 0) { - designerResource = designerResource.substr(srcDir.length() + 1); - } else if (designerResource.find(binDir) == 0) { - designerResource = designerResource.substr(binDir.length() + 1); + if (cmHasPrefix(designerResource, srcDir)) { + designerResource.erase(0, srcDir.length()); + } else if (cmHasPrefix(designerResource, binDir)) { + designerResource.erase(0, binDir.length()); } else { designerResource = cmsys::SystemTools::GetFilenameName(designerResource); @@ -1019,11 +1002,12 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) } const cmPropertyMap& props = oi->GetProperties(); for (const std::string& p : props.GetKeys()) { - static const std::string propNamePrefix = "VS_CSHARP_"; - if (p.find(propNamePrefix) == 0) { - std::string tagName = p.substr(propNamePrefix.length()); + static const cm::string_view propNamePrefix = "VS_CSHARP_"; + if (cmHasPrefix(p, propNamePrefix)) { + cm::string_view tagName = + cm::string_view(p).substr(propNamePrefix.length()); if (!tagName.empty()) { - std::string value = props.GetPropertyValue(p); + const std::string& value = *props.GetPropertyValue(p); if (!value.empty()) { e2.Element(tagName, value); } @@ -1054,25 +1038,6 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0) Elem e2(e1, xamlType); this->WriteSource(e2, oi); e2.SetHasElements(); - if (this->ProjectType == csproj && !this->InSourceBuild) { - // add <Link> tag to written XAML source if necessary - const std::string& srcDir = - this->Makefile->GetCurrentSourceDirectory(); - const std::string& binDir = - this->Makefile->GetCurrentBinaryDirectory(); - std::string link; - if (obj.find(srcDir) == 0) { - link = obj.substr(srcDir.length() + 1); - } else if (obj.find(binDir) == 0) { - link = obj.substr(binDir.length() + 1); - } else { - link = cmsys::SystemTools::GetFilenameName(obj); - } - if (!link.empty()) { - ConvertToWindowsSlash(link); - e2.Element("Link", link); - } - } e2.Element("SubType", "Designer"); } } @@ -1442,13 +1407,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( } else { Elem e1(e0, "ItemGroup"); Elem e2(e1, "None"); - std::string link; - this->GetCSharpSourceLink(source, link); this->WriteSource(e2, source); e2.SetHasElements(); - if (!link.empty()) { - e2.Element("Link", link); - } } for (std::string const& c : this->Configurations) { cmCustomCommandGenerator ccg(command, c, lg); @@ -1779,9 +1739,63 @@ void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1, if (this->IsResxHeader(fileName)) { e2.Element("FileType", "CppForm"); } else if (this->IsXamlHeader(fileName)) { - std::string xamlFileName = fileName.substr(0, fileName.find_last_of(".")); - e2.Element("DependentUpon", xamlFileName); + e2.Element("DependentUpon", + fileName.substr(0, fileName.find_last_of("."))); + } +} + +void cmVisualStudio10TargetGenerator::ParseSettingsProperty( + const char* settingsPropertyValue, ConfigToSettings& toolSettings) +{ + if (settingsPropertyValue) { + cmGeneratorExpression ge; + + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(settingsPropertyValue); + + for (const std::string& config : this->Configurations) { + std::string evaluated = cge->Evaluate(this->LocalGenerator, config); + + std::vector<std::string> settings = cmExpandedList(evaluated); + for (const std::string& setting : settings) { + const std::string::size_type assignment = setting.find('='); + if (assignment != std::string::npos) { + const std::string propName = setting.substr(0, assignment); + const std::string propValue = setting.substr(assignment + 1); + + if (!propValue.empty()) { + toolSettings[config][propName] = propValue; + } + } + } + } + } +} + +bool cmVisualStudio10TargetGenerator::PropertyIsSameInAllConfigs( + const ConfigToSettings& toolSettings, const std::string& propName) +{ + std::string firstPropValue = ""; + for (const auto& configToSettings : toolSettings) { + const std::unordered_map<std::string, std::string>& settings = + configToSettings.second; + + if (firstPropValue.empty()) { + if (settings.find(propName) != settings.end()) { + firstPropValue = settings.find(propName)->second; + } + } + + if (settings.find(propName) == settings.end()) { + return false; + } + + if (settings.find(propName)->second != firstPropValue) { + return false; + } } + + return true; } void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, @@ -1789,15 +1803,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, { bool toolHasSettings = false; const char* tool = "None"; - std::string shaderType; - std::string shaderEntryPoint; - std::string shaderModel; - std::string shaderAdditionalFlags; - std::string shaderDisableOptimizations; - std::string shaderEnableDebug; - std::string shaderObjectFileName; - std::string outputHeaderFile; - std::string variableName; std::string settingsGenerator; std::string settingsLastGenOutput; std::string sourceLink; @@ -1805,76 +1810,84 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, std::string copyToOutDir; std::string includeInVsix; std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); - if (this->ProjectType == csproj) { - // EVERY extra source file must have a <Link>, otherwise it might not - // be visible in Visual Studio at all. The path relative to current - // source- or binary-dir is used within the link, if the file is - // in none of these paths, it is added with the plain filename without - // any path. This means the file will show up at root-level of the csproj - // (where CMakeLists.txt etc. are). - if (!this->InSourceBuild) { - toolHasSettings = true; - std::string fullFileName = sf->GetFullPath(); - std::string srcDir = this->Makefile->GetCurrentSourceDirectory(); - std::string binDir = this->Makefile->GetCurrentBinaryDirectory(); - if (fullFileName.find(binDir) != std::string::npos) { - sourceLink.clear(); - } else if (fullFileName.find(srcDir) != std::string::npos) { - sourceLink = fullFileName.substr(srcDir.length() + 1); - } else { - // fallback: add plain filename without any path - sourceLink = cmsys::SystemTools::GetFilenameName(fullFileName); - } - if (!sourceLink.empty()) { - ConvertToWindowsSlash(sourceLink); - } - } + ConfigToSettings toolSettings; + for (const auto& config : this->Configurations) { + toolSettings[config]; + } + + if (this->ProjectType == csproj && !this->InSourceBuild) { + toolHasSettings = true; } if (ext == "hlsl") { tool = "FXCompile"; // Figure out the type of shader compiler to use. if (const char* st = sf->GetProperty("VS_SHADER_TYPE")) { - shaderType = st; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["ShaderType"] = st; + } } // Figure out which entry point to use if any if (const char* se = sf->GetProperty("VS_SHADER_ENTRYPOINT")) { - shaderEntryPoint = se; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["EntryPointName"] = se; + } } // Figure out which shader model to use if any if (const char* sm = sf->GetProperty("VS_SHADER_MODEL")) { - shaderModel = sm; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["ShaderModel"] = sm; + } } // Figure out which output header file to use if any if (const char* ohf = sf->GetProperty("VS_SHADER_OUTPUT_HEADER_FILE")) { - outputHeaderFile = ohf; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["HeaderFileOutput"] = ohf; + } } // Figure out which variable name to use if any if (const char* vn = sf->GetProperty("VS_SHADER_VARIABLE_NAME")) { - variableName = vn; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["VariableName"] = vn; + } } // Figure out if there's any additional flags to use if (const char* saf = sf->GetProperty("VS_SHADER_FLAGS")) { - shaderAdditionalFlags = saf; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["AdditionalOptions"] = saf; + } } // Figure out if debug information should be generated if (const char* sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) { - shaderEnableDebug = sed; - toolHasSettings = true; + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(sed); + + for (const std::string& config : this->Configurations) { + std::string evaluated = cge->Evaluate(this->LocalGenerator, config); + + if (!evaluated.empty()) { + toolSettings[config]["EnableDebuggingInformation"] = + cmIsOn(evaluated) ? "true" : "false"; + } + } } // Figure out if optimizations should be disabled if (const char* sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) { - shaderDisableOptimizations = sdo; - toolHasSettings = true; + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(sdo); + + for (const std::string& config : this->Configurations) { + std::string evaluated = cge->Evaluate(this->LocalGenerator, config); + + if (!evaluated.empty()) { + toolSettings[config]["DisableOptimizations"] = + cmIsOn(evaluated) ? "true" : "false"; + } + } } if (const char* sofn = sf->GetProperty("VS_SHADER_OBJECT_FILE_NAME")) { - shaderObjectFileName = sofn; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["ObjectFileOutput"] = sofn; + } } } else if (ext == "jpg" || ext == "png") { tool = "Image"; @@ -1944,11 +1957,56 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, } } + if (ParsedToolTargetSettings.find(tool) == ParsedToolTargetSettings.end()) { + cmProp toolTargetProperty = this->GeneratorTarget->Target->GetProperty( + "VS_SOURCE_SETTINGS_" + std::string(tool)); + ConfigToSettings toolTargetSettings; + if (toolTargetProperty) { + ParseSettingsProperty(toolTargetProperty->c_str(), toolTargetSettings); + } + + ParsedToolTargetSettings[tool] = toolTargetSettings; + } + + for (const auto& configToSetting : ParsedToolTargetSettings[tool]) { + for (const auto& setting : configToSetting.second) { + toolSettings[configToSetting.first][setting.first] = setting.second; + } + } + + ParseSettingsProperty(sf->GetProperty("VS_SETTINGS"), toolSettings); + + if (!toolSettings.empty()) { + toolHasSettings = true; + } + Elem e2(e1, tool); this->WriteSource(e2, sf); if (toolHasSettings) { e2.SetHasElements(); + std::vector<std::string> writtenSettings; + for (const auto& configSettings : toolSettings) { + for (const auto& setting : configSettings.second) { + + if (std::find(writtenSettings.begin(), writtenSettings.end(), + setting.first) != writtenSettings.end()) { + continue; + } + + if (PropertyIsSameInAllConfigs(toolSettings, setting.first)) { + e2.Element(setting.first, setting.second); + writtenSettings.push_back(setting.first); + } else { + e2.WritePlatformConfigTag(setting.first, + "'$(Configuration)|$(Platform)'=='" + + configSettings.first + "|" + + this->Platform + "'", + setting.second); + } + } + } + if (!deployContent.empty()) { cmGeneratorExpression ge; std::unique_ptr<cmCompiledGeneratorExpression> cge = @@ -1974,82 +2032,13 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, } } } - if (!shaderType.empty()) { - e2.Element("ShaderType", shaderType); - } - if (!shaderEntryPoint.empty()) { - e2.Element("EntryPointName", shaderEntryPoint); - } - if (!shaderModel.empty()) { - e2.Element("ShaderModel", shaderModel); - } - if (!outputHeaderFile.empty()) { - for (size_t i = 0; i != this->Configurations.size(); ++i) { - e2.WritePlatformConfigTag("HeaderFileOutput", - "'$(Configuration)|$(Platform)'=='" + - this->Configurations[i] + "|" + - this->Platform + "'", - outputHeaderFile); - } - } - if (!variableName.empty()) { - for (size_t i = 0; i != this->Configurations.size(); ++i) { - e2.WritePlatformConfigTag("VariableName", - "'$(Configuration)|$(Platform)'=='" + - this->Configurations[i] + "|" + - this->Platform + "'", - variableName); - } - } - if (!shaderEnableDebug.empty()) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(shaderEnableDebug); - - for (size_t i = 0; i != this->Configurations.size(); ++i) { - const std::string& enableDebug = - cge->Evaluate(this->LocalGenerator, this->Configurations[i]); - if (!enableDebug.empty()) { - e2.WritePlatformConfigTag("EnableDebuggingInformation", - "'$(Configuration)|$(Platform)'=='" + - this->Configurations[i] + "|" + - this->Platform + "'", - cmIsOn(enableDebug) ? "true" : "false"); - } - } - } - if (!shaderDisableOptimizations.empty()) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(shaderDisableOptimizations); - for (size_t i = 0; i != this->Configurations.size(); ++i) { - const std::string& disableOptimizations = - cge->Evaluate(this->LocalGenerator, this->Configurations[i]); - if (!disableOptimizations.empty()) { - e2.WritePlatformConfigTag( - "DisableOptimizations", - "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] + - "|" + this->Platform + "'", - (cmIsOn(disableOptimizations) ? "true" : "false")); - } - } - } - if (!shaderObjectFileName.empty()) { - e2.Element("ObjectFileOutput", shaderObjectFileName); - } - if (!shaderAdditionalFlags.empty()) { - e2.Element("AdditionalOptions", shaderAdditionalFlags); - } if (!settingsGenerator.empty()) { e2.Element("Generator", settingsGenerator); } if (!settingsLastGenOutput.empty()) { e2.Element("LastGenOutput", settingsLastGenOutput); } - if (!sourceLink.empty()) { - e2.Element("Link", sourceLink); - } if (!subType.empty()) { e2.Element("SubType", subType); } @@ -2102,6 +2091,20 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2, ConvertToWindowsSlash(sourceFile); e2.Attribute("Include", sourceFile); + if (this->ProjectType == csproj && !this->InSourceBuild) { + // For out of source projects we have to provide a link (if not specified + // via property) for every source file (besides .cs files) otherwise they + // will not be visible in VS at all. + // First we check if the file is in a source group, then we check if the + // file path is relative to current source- or binary-dir, otherwise it is + // added with the plain filename without any path. This means the file will + // show up at root-level of the csproj (where CMakeLists.txt etc. are). + std::string link = this->GetCSharpSourceLink(sf); + if (link.empty()) + link = cmsys::SystemTools::GetFilenameName(sf->GetFullPath()); + e2.Element("Link", link); + } + ToolSource toolSource = { sf, forceRelative }; this->Tools[e2.Tag].push_back(toolSource); } @@ -2454,19 +2457,13 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } if (this->IsXamlSource(source->GetFullPath())) { const std::string& fileName = source->GetFullPath(); - std::string xamlFileName = fileName.substr(0, fileName.find_last_of(".")); - e2.Element("DependentUpon", xamlFileName); + e2.Element("DependentUpon", + fileName.substr(0, fileName.find_last_of("."))); } if (this->ProjectType == csproj) { std::string f = source->GetFullPath(); using CsPropMap = std::map<std::string, std::string>; CsPropMap sourceFileTags; - // set <Link> tag if necessary - std::string link; - this->GetCSharpSourceLink(source, link); - if (!link.empty()) { - sourceFileTags["Link"] = link; - } this->GetCSharpSourceProperties(&sf, sourceFileTags); // write source file specific tags if (!sourceFileTags.empty()) { @@ -3412,9 +3409,8 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions( this->GeneratorTarget->GetLinkClosure(config)->LinkerLanguage; std::string libflags; - this->LocalGenerator->GetStaticLibraryFlags( - libflags, cmSystemTools::UpperCase(config), linkLanguage, - this->GeneratorTarget); + this->LocalGenerator->GetStaticLibraryFlags(libflags, config, linkLanguage, + this->GeneratorTarget); if (!libflags.empty()) { Elem e2(e1, "Lib"); cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; @@ -4845,11 +4841,11 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties( if (this->ProjectType == csproj) { const cmPropertyMap& props = sf->GetProperties(); for (const std::string& p : props.GetKeys()) { - static const std::string propNamePrefix = "VS_CSHARP_"; - if (p.find(propNamePrefix) == 0) { + static const cm::string_view propNamePrefix = "VS_CSHARP_"; + if (cmHasPrefix(p, propNamePrefix)) { std::string tagName = p.substr(propNamePrefix.length()); if (!tagName.empty()) { - const std::string val = props.GetPropertyValue(p); + const std::string& val = *props.GetPropertyValue(p); if (!val.empty()) { tags[tagName] = val; } else { @@ -4869,24 +4865,34 @@ void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties( } } -void cmVisualStudio10TargetGenerator::GetCSharpSourceLink( - cmSourceFile const* sf, std::string& link) +std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink( + cmSourceFile const* source) { - std::string const& sourceFilePath = sf->GetFullPath(); - std::string const& binaryDir = LocalGenerator->GetCurrentBinaryDirectory(); - - if (!cmSystemTools::IsSubDirectory(sourceFilePath, binaryDir)) { - const std::string& stripFromPath = - this->Makefile->GetCurrentSourceDirectory(); - if (sourceFilePath.find(stripFromPath) == 0) { - if (const char* l = sf->GetProperty("VS_CSHARP_Link")) { - link = l; - } else { - link = sourceFilePath.substr(stripFromPath.length() + 1); - } - ConvertToWindowsSlash(link); - } - } + // 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 + std::string link; + std::string const& fullFileName = source->GetFullPath(); + std::string const& srcDir = this->Makefile->GetCurrentSourceDirectory(); + std::string const& binDir = this->Makefile->GetCurrentBinaryDirectory(); + // unfortunately we have to copy the source groups, because + // FindSourceGroup uses a regex which is modifying the group + std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); + cmSourceGroup* sourceGroup = + this->Makefile->FindSourceGroup(fullFileName, sourceGroups); + if (sourceGroup && !sourceGroup->GetFullName().empty()) { + link = sourceGroup->GetFullName() + "/" + + cmsys::SystemTools::GetFilenameName(fullFileName); + } else if (cmHasPrefix(fullFileName, srcDir)) { + link = fullFileName.substr(srcDir.length() + 1); + } else if (cmHasPrefix(fullFileName, binDir)) { + link = fullFileName.substr(binDir.length() + 1); + } else if (const char* l = source->GetProperty("VS_CSHARP_Link")) { + link = l; + } + + ConvertToWindowsSlash(link); + return link; } std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath( diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 30027c9..e588de8 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -10,6 +10,7 @@ #include <memory> #include <set> #include <string> +#include <unordered_map> #include <vector> class cmComputeLinkInformation; @@ -73,8 +74,6 @@ private: std::vector<size_t> const& exclude_configs); void WriteAllSources(Elem& e0); void WritePackageReferences(Elem& e0); - void WritePackageReference(Elem& e1, std::string const& ref, - std::string const& version); void WriteDotNetReferences(Elem& e0); void WriteDotNetReference(Elem& e1, std::string const& ref, std::string const& hint, @@ -183,7 +182,7 @@ private: std::map<std::string, std::string>& tags); void WriteCSharpSourceProperties( Elem& e2, const std::map<std::string, std::string>& tags); - void GetCSharpSourceLink(cmSourceFile const* sf, std::string& link); + std::string GetCSharpSourceLink(cmSourceFile const* source); private: friend class cmVS10GeneratorOptions; @@ -236,6 +235,15 @@ private: using ToolSourceMap = std::map<std::string, ToolSources>; ToolSourceMap Tools; + + using ConfigToSettings = + std::unordered_map<std::string, + std::unordered_map<std::string, std::string>>; + std::unordered_map<std::string, ConfigToSettings> ParsedToolTargetSettings; + bool PropertyIsSameInAllConfigs(const ConfigToSettings& toolSettings, + const std::string& propName); + void ParseSettingsProperty(const char* settingsPropertyValue, + ConfigToSettings& toolSettings); std::string GetCMakeFilePath(const char* name) const; }; diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx index 4533e9b..d7822b1 100644 --- a/Source/cmVisualStudioSlnParser.cxx +++ b/Source/cmVisualStudioSlnParser.cxx @@ -517,7 +517,7 @@ bool cmVisualStudioSlnParser::ParseMultiValueTag(const std::string& line, State& state) { size_t idxEqualSign = line.find('='); - const std::string& fullTag = line.substr(0, idxEqualSign); + auto fullTag = cm::string_view(line).substr(0, idxEqualSign); if (!this->ParseTag(fullTag, parsedLine, state)) return false; if (idxEqualSign != line.npos) { @@ -560,7 +560,7 @@ bool cmVisualStudioSlnParser::ParseSingleValueTag(const std::string& line, State& state) { size_t idxEqualSign = line.find('='); - const std::string& fullTag = line.substr(0, idxEqualSign); + auto fullTag = cm::string_view(line).substr(0, idxEqualSign); if (!this->ParseTag(fullTag, parsedLine, state)) return false; if (idxEqualSign != line.npos) { @@ -586,17 +586,17 @@ bool cmVisualStudioSlnParser::ParseKeyValuePair(const std::string& line, return true; } -bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag, +bool cmVisualStudioSlnParser::ParseTag(cm::string_view fullTag, ParsedLine& parsedLine, State& state) { size_t idxLeftParen = fullTag.find('('); - if (idxLeftParen == fullTag.npos) { + if (idxLeftParen == cm::string_view::npos) { parsedLine.SetTag(cmTrimWhitespace(fullTag)); return true; } parsedLine.SetTag(cmTrimWhitespace(fullTag.substr(0, idxLeftParen))); size_t idxRightParen = fullTag.rfind(')'); - if (idxRightParen == fullTag.npos) { + if (idxRightParen == cm::string_view::npos) { this->LastResult.SetError(ResultErrorInputStructure, state.GetCurrentLine()); return false; diff --git a/Source/cmVisualStudioSlnParser.h b/Source/cmVisualStudioSlnParser.h index 6c05633..4557cdb 100644 --- a/Source/cmVisualStudioSlnParser.h +++ b/Source/cmVisualStudioSlnParser.h @@ -9,6 +9,8 @@ #include <iosfwd> #include <string> +#include <cm/string_view> + #include <stddef.h> class cmSlnData; @@ -97,8 +99,7 @@ protected: bool ParseKeyValuePair(const std::string& line, ParsedLine& parsedLine, State& state); - bool ParseTag(const std::string& fullTag, ParsedLine& parsedLine, - State& state); + bool ParseTag(cm::string_view fullTag, ParsedLine& parsedLine, State& state); bool ParseValue(const std::string& value, ParsedLine& parsedLine); }; diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx index 34e21b2..666ba87 100644 --- a/Source/cmWriteFileCommand.cxx +++ b/Source/cmWriteFileCommand.cxx @@ -72,7 +72,7 @@ bool cmWriteFileCommand(std::vector<std::string> const& args, status.SetError(error); return false; } - file << message << std::endl; + file << message << '\n'; file.close(); if (mode && !writable) { cmSystemTools::SetPermissions(fileName.c_str(), mode); diff --git a/Source/cmXCode21Object.cxx b/Source/cmXCode21Object.cxx index a9bb2ef..6b133a9 100644 --- a/Source/cmXCode21Object.cxx +++ b/Source/cmXCode21Object.cxx @@ -30,11 +30,12 @@ void cmXCode21Object::PrintComment(std::ostream& out) out << " */"; } -void cmXCode21Object::PrintList(std::vector<cmXCodeObject*> const& v, - std::ostream& out, PBXType t) +void cmXCode21Object::PrintList( + std::vector<std::unique_ptr<cmXCodeObject>> const& v, std::ostream& out, + PBXType t) { bool hasOne = false; - for (auto obj : v) { + for (const auto& obj : v) { if (obj->GetType() == OBJECT && obj->GetIsA() == t) { hasOne = true; break; @@ -44,7 +45,7 @@ void cmXCode21Object::PrintList(std::vector<cmXCodeObject*> const& v, return; } out << "\n/* Begin " << PBXTypeNames[t] << " section */\n"; - for (auto obj : v) { + for (const auto& obj : v) { if (obj->GetType() == OBJECT && obj->GetIsA() == t) { obj->Print(out); } @@ -52,8 +53,8 @@ void cmXCode21Object::PrintList(std::vector<cmXCodeObject*> const& v, out << "/* End " << PBXTypeNames[t] << " section */\n"; } -void cmXCode21Object::PrintList(std::vector<cmXCodeObject*> const& v, - std::ostream& out) +void cmXCode21Object::PrintList( + std::vector<std::unique_ptr<cmXCodeObject>> const& v, std::ostream& out) { cmXCodeObject::Indent(1, out); out << "objects = {\n"; diff --git a/Source/cmXCode21Object.h b/Source/cmXCode21Object.h index 8e4b80f..76fad23 100644 --- a/Source/cmXCode21Object.h +++ b/Source/cmXCode21Object.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <vector> #include "cmXCodeObject.h" @@ -15,8 +16,9 @@ class cmXCode21Object : public cmXCodeObject public: cmXCode21Object(PBXType ptype, Type type); void PrintComment(std::ostream&) override; - static void PrintList(std::vector<cmXCodeObject*> const&, std::ostream& out, - PBXType t); - static void PrintList(std::vector<cmXCodeObject*> const&, std::ostream& out); + static void PrintList(std::vector<std::unique_ptr<cmXCodeObject>> const&, + std::ostream& out, PBXType t); + static void PrintList(std::vector<std::unique_ptr<cmXCodeObject>> const&, + std::ostream& out); }; #endif diff --git a/Source/cm_get_date.c b/Source/cm_get_date.c index 4bef803..49f5577 100644 --- a/Source/cm_get_date.c +++ b/Source/cm_get_date.c @@ -2,6 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cm_get_date.h" +// FIXME: This suppresses use of localtime_r because archive_getdate.c +// depends the rest of libarchive's checks for that. +#define CM_GET_DATE + #define __archive_get_date cm_get_date #include "../Utilities/cmlibarchive/libarchive/archive_getdate.c" diff --git a/Source/cmake.cxx b/Source/cmake.cxx index a99d9a6..2ec893f 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -9,6 +9,7 @@ #include <initializer_list> #include <iostream> #include <sstream> +#include <stdexcept> #include <utility> #include <cm/memory> @@ -23,6 +24,7 @@ #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" +#include "cm_static_string_view.hxx" #include "cm_sys_stat.h" #include "cmAlgorithms.h" @@ -39,6 +41,9 @@ #include "cmLinkLineComputer.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#if !defined(CMAKE_BOOTSTRAP) +# include "cmMakefileProfilingData.h" +#endif #include "cmMessenger.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -288,7 +293,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) bool findPackageMode = false; for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; - if (arg.find("-D", 0) == 0) { + if (cmHasLiteralPrefix(arg, "-D")) { std::string entry = arg.substr(2); if (entry.empty()) { ++i; @@ -377,7 +382,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) // -Wno-error=<name> this->DiagLevels[name] = std::min(this->DiagLevels[name], DIAG_WARN); } - } else if (arg.find("-U", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-U")) { std::string entryPattern = arg.substr(2); if (entryPattern.empty()) { ++i; @@ -407,7 +412,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) for (std::string const& currentEntry : entriesToDelete) { this->State->RemoveCacheEntry(currentEntry); } - } else if (arg.find("-C", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-C")) { std::string path = arg.substr(2); if (path.empty()) { ++i; @@ -422,7 +427,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) // Resolve script path specified on command line relative to $PWD. path = cmSystemTools::CollapseFullPath(path); this->ReadListFile(args, path); - } else if (arg.find("-P", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-P")) { i++; if (i >= args.size()) { cmSystemTools::Error("-P must be followed by a file name."); @@ -441,7 +446,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) this->SetHomeOutputDirectory( cmSystemTools::GetCurrentWorkingDirectory()); this->ReadListFile(args, path); - } else if (arg.find("--find-package", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--find-package")) { findPackageMode = true; } } @@ -520,11 +525,11 @@ bool cmake::FindPackage(const std::vector<std::string>& args) if (!quiet) { printf("%s not found.\n", packageName.c_str()); } - } else if (mode == "EXIST") { + } else if (mode == "EXIST"_s) { if (!quiet) { printf("%s found.\n", packageName.c_str()); } - } else if (mode == "COMPILE") { + } else if (mode == "COMPILE"_s) { std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS"); std::vector<std::string> includeDirs = cmExpandedList(includes); @@ -535,7 +540,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS"); printf("%s %s\n", includeFlags.c_str(), definitions.c_str()); - } else if (mode == "LINK") { + } else if (mode == "LINK"_s) { const char* targetName = "dummy"; std::vector<std::string> srcs; cmTarget* tgt = mf->AddExecutable(targetName, srcs, true); @@ -613,9 +618,13 @@ void cmake::SetArgs(const std::vector<std::string>& args) { bool haveToolset = false; bool havePlatform = false; +#if !defined(CMAKE_BOOTSTRAP) + std::string profilingFormat; + std::string profilingOutput; +#endif for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; - if (arg.find("-H", 0) == 0 || arg.find("-S", 0) == 0) { + if (cmHasLiteralPrefix(arg, "-H") || cmHasLiteralPrefix(arg, "-S")) { std::string path = arg.substr(2); if (path.empty()) { ++i; @@ -633,9 +642,9 @@ void cmake::SetArgs(const std::vector<std::string>& args) path = cmSystemTools::CollapseFullPath(path); cmSystemTools::ConvertToUnixSlashes(path); this->SetHomeDirectory(path); - } else if (arg.find("-O", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-O")) { // There is no local generate anymore. Ignore -O option. - } else if (arg.find("-B", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-B")) { std::string path = arg.substr(2); if (path.empty()) { ++i; @@ -654,54 +663,54 @@ void cmake::SetArgs(const std::vector<std::string>& args) cmSystemTools::ConvertToUnixSlashes(path); this->SetHomeOutputDirectory(path); } else if ((i < args.size() - 2) && - (arg.find("--check-build-system", 0) == 0)) { + cmHasLiteralPrefix(arg, "--check-build-system")) { this->CheckBuildSystemArgument = args[++i]; this->ClearBuildSystem = (atoi(args[++i].c_str()) > 0); } else if ((i < args.size() - 1) && - (arg.find("--check-stamp-file", 0) == 0)) { + cmHasLiteralPrefix(arg, "--check-stamp-file")) { this->CheckStampFile = args[++i]; } else if ((i < args.size() - 1) && - (arg.find("--check-stamp-list", 0) == 0)) { + cmHasLiteralPrefix(arg, "--check-stamp-list")) { this->CheckStampList = args[++i]; - } else if (arg == "--regenerate-during-build") { + } else if (arg == "--regenerate-during-build"_s) { this->RegenerateDuringBuild = true; } #if defined(CMAKE_HAVE_VS_GENERATORS) else if ((i < args.size() - 1) && - (arg.find("--vs-solution-file", 0) == 0)) { + cmHasLiteralPrefix(arg, "--vs-solution-file")) { this->VSSolutionFile = args[++i]; } #endif - else if (arg.find("-D", 0) == 0) { + else if (cmHasLiteralPrefix(arg, "-D")) { // skip for now // in case '-D var=val' is given, also skip the next // in case '-Dvar=val' is given, don't skip the next if (arg.size() == 2) { ++i; } - } else if (arg.find("-U", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-U")) { // skip for now // in case '-U var' is given, also skip the next // in case '-Uvar' is given, don't skip the next if (arg.size() == 2) { ++i; } - } else if (arg.find("-C", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-C")) { // skip for now // in case '-C path' is given, also skip the next // in case '-Cpath' is given, don't skip the next if (arg.size() == 2) { ++i; } - } else if (arg.find("-P", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-P")) { // skip for now i++; - } else if (arg.find("--find-package", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--find-package")) { // skip for now i++; - } else if (arg.find("-W", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-W")) { // skip for now - } else if (arg.find("--graphviz=", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--graphviz=")) { std::string path = arg.substr(strlen("--graphviz=")); path = cmSystemTools::CollapseFullPath(path); cmSystemTools::ConvertToUnixSlashes(path); @@ -710,13 +719,13 @@ void cmake::SetArgs(const std::vector<std::string>& args) cmSystemTools::Error("No file specified for --graphviz"); return; } - } else if (arg.find("--debug-trycompile", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--debug-trycompile")) { std::cout << "debug trycompile on\n"; this->DebugTryCompileOn(); - } else if (arg.find("--debug-output", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--debug-output")) { std::cout << "Running with debug output on.\n"; this->SetDebugOutputOn(true); - } else if (arg.find("--log-level=", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--log-level=")) { const auto logLevel = StringToLogLevel(arg.substr(sizeof("--log-level=") - 1)); if (logLevel == LogLevel::LOG_UNDEFINED) { @@ -725,7 +734,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) } this->SetLogLevel(logLevel); this->LogLevelWasSetViaCLI = true; - } else if (arg.find("--loglevel=", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--loglevel=")) { // This is supported for backward compatibility. This option only // appeared in the 3.15.x release series and was renamed to // --log-level in 3.16.0 @@ -737,16 +746,16 @@ void cmake::SetArgs(const std::vector<std::string>& args) } this->SetLogLevel(logLevel); this->LogLevelWasSetViaCLI = true; - } else if (arg == "--log-context") { + } else if (arg == "--log-context"_s) { this->SetShowLogContext(true); - } else if (arg.find("--debug-find", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--debug-find")) { std::cout << "Running with debug output on for the `find` commands.\n"; this->SetDebugFindOutputOn(true); - } else if (arg.find("--trace-expand", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--trace-expand")) { std::cout << "Running with expanded trace output on.\n"; this->SetTrace(true); this->SetTraceExpand(true); - } else if (arg.find("--trace-format=", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--trace-format=")) { this->SetTrace(true); const auto traceFormat = StringToTraceFormat(arg.substr(strlen("--trace-format="))); @@ -756,35 +765,35 @@ void cmake::SetArgs(const std::vector<std::string>& args) return; } this->SetTraceFormat(traceFormat); - } else if (arg.find("--trace-source=", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--trace-source=")) { std::string file = arg.substr(strlen("--trace-source=")); cmSystemTools::ConvertToUnixSlashes(file); this->AddTraceSource(file); this->SetTrace(true); - } else if (arg.find("--trace-redirect=", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--trace-redirect=")) { std::string file = arg.substr(strlen("--trace-redirect=")); cmSystemTools::ConvertToUnixSlashes(file); this->SetTraceFile(file); this->SetTrace(true); - } else if (arg.find("--trace", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--trace")) { std::cout << "Running with trace output on.\n"; this->SetTrace(true); this->SetTraceExpand(false); - } else if (arg.find("--warn-uninitialized", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--warn-uninitialized")) { std::cout << "Warn about uninitialized values.\n"; this->SetWarnUninitialized(true); - } else if (arg.find("--warn-unused-vars", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--warn-unused-vars")) { std::cout << "Finding unused variables.\n"; this->SetWarnUnused(true); - } else if (arg.find("--no-warn-unused-cli", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--no-warn-unused-cli")) { std::cout << "Not searching for unused variables given on the " << "command line.\n"; this->SetWarnUnusedCli(false); - } else if (arg.find("--check-system-vars", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "--check-system-vars")) { std::cout << "Also check system files when warning about unused and " << "uninitialized variables.\n"; this->SetCheckSystemVars(true); - } else if (arg.find("-A", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-A")) { std::string value = arg.substr(2); if (value.empty()) { ++i; @@ -800,7 +809,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) } this->SetGeneratorPlatform(value); havePlatform = true; - } else if (arg.find("-T", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-T")) { std::string value = arg.substr(2); if (value.empty()) { ++i; @@ -816,7 +825,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) } this->SetGeneratorToolset(value); haveToolset = true; - } else if (arg.find("-G", 0) == 0) { + } else if (cmHasLiteralPrefix(arg, "-G")) { std::string value = arg.substr(2); if (value.empty()) { ++i; @@ -840,6 +849,20 @@ void cmake::SetArgs(const std::vector<std::string>& args) return; } this->SetGlobalGenerator(std::move(gen)); +#if !defined(CMAKE_BOOTSTRAP) + } else if (cmHasLiteralPrefix(arg, "--profiling-format")) { + profilingFormat = arg.substr(strlen("--profiling-format=")); + if (profilingFormat.empty()) { + cmSystemTools::Error("No format specified for --profiling-format"); + } + } else if (cmHasLiteralPrefix(arg, "--profiling-output")) { + profilingOutput = arg.substr(strlen("--profiling-output=")); + profilingOutput = cmSystemTools::CollapseFullPath(profilingOutput); + cmSystemTools::ConvertToUnixSlashes(profilingOutput); + if (profilingOutput.empty()) { + cmSystemTools::Error("No path specified for --profiling-output"); + } +#endif } // no option assume it is the path to the source or an existing build else { @@ -857,6 +880,29 @@ void cmake::SetArgs(const std::vector<std::string>& args) } } +#if !defined(CMAKE_BOOTSTRAP) + if (!profilingOutput.empty() || !profilingFormat.empty()) { + if (profilingOutput.empty()) { + cmSystemTools::Error( + "--profiling-format specified but no --profiling-output!"); + return; + } + if (profilingFormat == "google-trace"_s) { + try { + this->ProfilingOutput = + cm::make_unique<cmMakefileProfilingData>(profilingOutput); + } catch (std::runtime_error& e) { + cmSystemTools::Error( + cmStrCat("Could not start profiling: ", e.what())); + return; + } + } else { + cmSystemTools::Error("Invalid format specified for --profiling-format"); + return; + } + } +#endif + const bool haveSourceDir = !this->GetHomeDirectory().empty(); const bool haveBinaryDir = !this->GetHomeOutputDirectory().empty(); @@ -992,9 +1038,9 @@ void cmake::SetDirectoriesFromFile(const std::string& arg) std::string fullPath = cmSystemTools::CollapseFullPath(arg); std::string name = cmSystemTools::GetFilenameName(fullPath); name = cmSystemTools::LowerCase(name); - if (name == "cmakecache.txt") { + if (name == "cmakecache.txt"_s) { cachePath = cmSystemTools::GetFilenamePath(fullPath); - } else if (name == "cmakelists.txt") { + } else if (name == "cmakelists.txt"_s) { listPath = cmSystemTools::GetFilenamePath(fullPath); } } else { @@ -1003,7 +1049,7 @@ void cmake::SetDirectoriesFromFile(const std::string& arg) std::string fullPath = cmSystemTools::CollapseFullPath(arg); std::string name = cmSystemTools::GetFilenameName(fullPath); name = cmSystemTools::LowerCase(name); - if (name == "cmakecache.txt" || name == "cmakelists.txt") { + if (name == "cmakecache.txt"_s || name == "cmakelists.txt"_s) { argIsFile = true; listPath = cmSystemTools::GetFilenamePath(fullPath); } else { @@ -1014,11 +1060,11 @@ void cmake::SetDirectoriesFromFile(const std::string& arg) // If there is a CMakeCache.txt file, use its settings. if (!cachePath.empty()) { if (this->LoadCache(cachePath)) { - const char* existingValue = + cmProp existingValue = this->State->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"); if (existingValue) { this->SetHomeOutputDirectory(cachePath); - this->SetHomeDirectory(existingValue); + this->SetHomeDirectory(*existingValue); return; } } @@ -1361,12 +1407,12 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) i++; save.value = *i; warning << *i << "\n"; - const char* existingValue = this->State->GetCacheEntryValue(save.key); + cmProp existingValue = this->State->GetCacheEntryValue(save.key); if (existingValue) { save.type = this->State->GetCacheEntryType(save.key); - if (const char* help = + if (cmProp help = this->State->GetCacheEntryProperty(save.key, "HELPSTRING")) { - save.help = help; + save.help = *help; } } saved.push_back(std::move(save)); @@ -1411,9 +1457,9 @@ int cmake::Configure() if (this->DiagLevels.count("dev") == 1) { bool setDeprecatedVariables = false; - const char* cachedWarnDeprecated = + cmProp cachedWarnDeprecated = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); - const char* cachedErrorDeprecated = + cmProp cachedErrorDeprecated = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED"); // don't overwrite deprecated warning setting from a previous invocation @@ -1452,23 +1498,23 @@ int cmake::Configure() // Cache variables may have already been set by a previous invocation, // so we cannot rely on command line options alone. Always ensure our // messenger is in sync with the cache. - const char* value = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); - this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(value)); + cmProp value = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); + this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(*value)); value = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED"); - this->Messenger->SetDeprecatedWarningsAsErrors(cmIsOn(value)); + this->Messenger->SetDeprecatedWarningsAsErrors(value && cmIsOn(*value)); value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_WARNINGS"); - this->Messenger->SetSuppressDevWarnings(cmIsOn(value)); + this->Messenger->SetSuppressDevWarnings(value && cmIsOn(*value)); value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS"); - this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(value)); + this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(*value)); int ret = this->ActualConfigure(); - const char* delCacheVars = + cmProp delCacheVars = this->State->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_"); - if (delCacheVars && delCacheVars[0] != 0) { - return this->HandleDeleteCacheVariables(delCacheVars); + if (delCacheVars && !delCacheVars->empty()) { + return this->HandleDeleteCacheVariables(*delCacheVars); } return ret; } @@ -1891,13 +1937,13 @@ void cmake::AddCacheEntry(const std::string& key, const char* value, cmStateEnums::CacheEntryType(type)); this->UnwatchUnusedCli(key); - if (key == "CMAKE_WARN_DEPRECATED") { + if (key == "CMAKE_WARN_DEPRECATED"_s) { this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(value)); - } else if (key == "CMAKE_ERROR_DEPRECATED") { + } else if (key == "CMAKE_ERROR_DEPRECATED"_s) { this->Messenger->SetDeprecatedWarningsAsErrors(cmIsOn(value)); - } else if (key == "CMAKE_SUPPRESS_DEVELOPER_WARNINGS") { + } else if (key == "CMAKE_SUPPRESS_DEVELOPER_WARNINGS"_s) { this->Messenger->SetSuppressDevWarnings(cmIsOn(value)); - } else if (key == "CMAKE_SUPPRESS_DEVELOPER_ERRORS") { + } else if (key == "CMAKE_SUPPRESS_DEVELOPER_ERRORS"_s) { this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(value)); } } @@ -1933,9 +1979,10 @@ std::string cmake::StripExtension(const std::string& file) const { auto dotpos = file.rfind('.'); if (dotpos != std::string::npos) { - auto ext = file.substr(dotpos + 1); #if defined(_WIN32) || defined(__APPLE__) - ext = cmSystemTools::LowerCase(ext); + auto ext = cmSystemTools::LowerCase(file.substr(dotpos + 1)); +#else + auto ext = cm::string_view(file).substr(dotpos + 1); #endif if (this->IsSourceExtension(ext) || this->IsHeaderExtension(ext)) { return file.substr(0, dotpos); @@ -2383,7 +2430,7 @@ void cmake::AppendProperty(const std::string& prop, const std::string& value, this->State->AppendGlobalProperty(prop, value, asString); } -const char* cmake::GetProperty(const std::string& prop) +cmProp cmake::GetProperty(const std::string& prop) { return this->State->GetGlobalProperty(prop); } @@ -2435,7 +2482,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) bool writeToStdout = true; for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; - if (arg.find("-G", 0) == 0) { + if (cmHasLiteralPrefix(arg, "-G")) { std::string value = arg.substr(2); if (value.empty()) { ++i; @@ -2624,10 +2671,10 @@ void cmake::IssueMessage(MessageType t, std::string const& text, std::vector<std::string> cmake::GetDebugConfigs() { std::vector<std::string> configs; - if (const char* config_list = + if (cmProp config_list = this->State->GetGlobalProperty("DEBUG_CONFIGURATIONS")) { // Expand the specified list and convert to upper-case. - cmExpandList(config_list, configs); + cmExpandList(*config_list, configs); std::transform(configs.begin(), configs.end(), configs.begin(), cmSystemTools::UpperCase); } @@ -2657,59 +2704,58 @@ int cmake::Build(int jobs, const std::string& dir, std::cerr << "Error: could not load cache\n"; return 1; } - const char* cachedGenerator = - this->State->GetCacheEntryValue("CMAKE_GENERATOR"); + cmProp cachedGenerator = this->State->GetCacheEntryValue("CMAKE_GENERATOR"); if (!cachedGenerator) { std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n"; return 1; } - auto gen = this->CreateGlobalGenerator(cachedGenerator); + auto gen = this->CreateGlobalGenerator(*cachedGenerator); if (!gen) { - std::cerr << "Error: could create CMAKE_GENERATOR \"" << cachedGenerator + std::cerr << "Error: could create CMAKE_GENERATOR \"" << *cachedGenerator << "\"\n"; return 1; } this->SetGlobalGenerator(std::move(gen)); - const char* cachedGeneratorInstance = + cmProp cachedGeneratorInstance = this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE"); if (cachedGeneratorInstance) { cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); - if (!this->GlobalGenerator->SetGeneratorInstance(cachedGeneratorInstance, + if (!this->GlobalGenerator->SetGeneratorInstance(*cachedGeneratorInstance, &mf)) { return 1; } } - const char* cachedGeneratorPlatform = + cmProp cachedGeneratorPlatform = this->State->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); if (cachedGeneratorPlatform) { cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); - if (!this->GlobalGenerator->SetGeneratorPlatform(cachedGeneratorPlatform, + if (!this->GlobalGenerator->SetGeneratorPlatform(*cachedGeneratorPlatform, &mf)) { return 1; } } - const char* cachedGeneratorToolset = + cmProp cachedGeneratorToolset = this->State->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); if (cachedGeneratorToolset) { cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); - if (!this->GlobalGenerator->SetGeneratorToolset(cachedGeneratorToolset, + if (!this->GlobalGenerator->SetGeneratorToolset(*cachedGeneratorToolset, true, &mf)) { return 1; } } std::string output; std::string projName; - const char* cachedProjectName = + cmProp cachedProjectName = this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME"); if (!cachedProjectName) { std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n"; return 1; } - projName = cachedProjectName; + projName = *cachedProjectName; - const char* cachedVerbose = + cmProp cachedVerbose = this->State->GetCacheEntryValue("CMAKE_VERBOSE_MAKEFILE"); - if (cmIsOn(cachedVerbose)) { + if (cachedVerbose && cmIsOn(*cachedVerbose)) { verbose = true; } @@ -2793,7 +2839,7 @@ bool cmake::Open(const std::string& dir, bool dryRun) std::cerr << "Error: could not load cache\n"; return false; } - const char* genName = this->State->GetCacheEntryValue("CMAKE_GENERATOR"); + cmProp genName = this->State->GetCacheEntryValue("CMAKE_GENERATOR"); if (!genName) { std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n"; return false; @@ -2802,7 +2848,7 @@ bool cmake::Open(const std::string& dir, bool dryRun) this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR"); std::string fullName = cmExternalMakefileProjectGenerator::CreateFullGeneratorName( - genName, extraGenName ? *extraGenName : ""); + *genName, extraGenName ? *extraGenName : ""); std::unique_ptr<cmGlobalGenerator> gen = this->CreateGlobalGenerator(fullName); @@ -2812,14 +2858,14 @@ bool cmake::Open(const std::string& dir, bool dryRun) return false; } - const char* cachedProjectName = + cmProp cachedProjectName = this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME"); if (!cachedProjectName) { std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n"; return false; } - return gen->Open(dir, cachedProjectName, dryRun); + return gen->Open(dir, *cachedProjectName, dryRun); } void cmake::WatchUnusedCli(const std::string& var) @@ -2953,3 +2999,15 @@ void cmake::SetDeprecatedWarningsAsErrors(bool b) " and functions.", cmStateEnums::INTERNAL); } + +#if !defined(CMAKE_BOOTSTRAP) +cmMakefileProfilingData& cmake::GetProfilingOutput() +{ + return *(this->ProfilingOutput); +} + +bool cmake::IsProfilingEnabled() const +{ + return static_cast<bool>(this->ProfilingOutput); +} +#endif diff --git a/Source/cmake.h b/Source/cmake.h index 35425ec..cfcd264 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -16,6 +16,8 @@ #include <utility> #include <vector> +#include <cm/string_view> + #include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" #include "cmListFileCache.h" @@ -34,6 +36,9 @@ class cmFileTimeCache; class cmGlobalGenerator; class cmGlobalGeneratorFactory; class cmMakefile; +#if !defined(CMAKE_BOOTSTRAP) +class cmMakefileProfilingData; +#endif class cmMessenger; class cmVariableWatch; struct cmDocumentationEntry; @@ -135,13 +140,13 @@ public: struct FileExtensions { - bool Test(std::string const& ext) const + bool Test(cm::string_view ext) const { return (this->unordered.find(ext) != this->unordered.end()); } std::vector<std::string> ordered; - std::unordered_set<std::string> unordered; + std::unordered_set<cm::string_view> unordered; }; using InstalledFilesMap = std::map<std::string, cmInstalledFile>; @@ -263,7 +268,7 @@ public: return this->SourceFileExtensions.ordered; } - bool IsSourceExtension(const std::string& ext) const + bool IsSourceExtension(cm::string_view ext) const { return this->SourceFileExtensions.Test(ext); } @@ -273,7 +278,7 @@ public: return this->HeaderFileExtensions.ordered; } - bool IsHeaderExtension(const std::string& ext) const + bool IsHeaderExtension(cm::string_view ext) const { return this->HeaderFileExtensions.Test(ext); } @@ -283,7 +288,7 @@ public: return this->CudaFileExtensions.ordered; } - bool IsCudaExtension(const std::string& ext) const + bool IsCudaExtension(cm::string_view ext) const { return this->CudaFileExtensions.Test(ext); } @@ -293,7 +298,7 @@ public: return this->FortranFileExtensions.ordered; } - bool IsFortranExtension(const std::string& ext) const + bool IsFortranExtension(cm::string_view ext) const { return this->FortranFileExtensions.Test(ext); } @@ -361,7 +366,7 @@ public: void SetProperty(const std::string& prop, const char* value); void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); - const char* GetProperty(const std::string& prop); + cmProp GetProperty(const std::string& prop); bool GetPropertyAsBool(const std::string& prop); //! Get or create an cmInstalledFile instance and return a pointer to it @@ -549,6 +554,11 @@ public: bool GetRegenerateDuringBuild() const { return this->RegenerateDuringBuild; } +#if !defined(CMAKE_BOOTSTRAP) + cmMakefileProfilingData& GetProfilingOutput(); + bool IsProfilingEnabled() const; +#endif + protected: void RunCheckForUnusedVariables(); int HandleDeleteCacheVariables(const std::string& var); @@ -657,6 +667,10 @@ private: void AppendGlobalGeneratorsDocumentation(std::vector<cmDocumentationEntry>&); void AppendExtraGeneratorsDocumentation(std::vector<cmDocumentationEntry>&); + +#if !defined(CMAKE_BOOTSTRAP) + std::unique_ptr<cmMakefileProfilingData> ProfilingOutput; +#endif }; #define CMAKE_STANDARD_OPTIONS_TABLE \ diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 494d5d9..84d0538 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -93,6 +93,12 @@ const char* cmDocumentationOptions[][2] = { { "--check-system-vars", "Find problems with variable usage in system " "files." }, +# if !defined(CMAKE_BOOTSTRAP) + { "--profiling-format=<fmt>", "Output data for profiling CMake scripts." }, + { "--profiling-output=<file>", + "Select an output path for the profiling data enabled through " + "--profiling-format." }, +# endif { nullptr, nullptr } }; @@ -286,16 +292,16 @@ int do_cmake(int ac, char const* const* av) cmStateEnums::CacheEntryType t = cm.GetState()->GetCacheEntryType(k); if (t != cmStateEnums::INTERNAL && t != cmStateEnums::STATIC && t != cmStateEnums::UNINITIALIZED) { - const char* advancedProp = + cmProp advancedProp = cm.GetState()->GetCacheEntryProperty(k, "ADVANCED"); if (list_all_cached || !advancedProp) { if (list_help) { - std::cout << "// " - << cm.GetState()->GetCacheEntryProperty(k, "HELPSTRING") - << std::endl; + cmProp help = + cm.GetState()->GetCacheEntryProperty(k, "HELPSTRING"); + std::cout << "// " << (help ? *help : "") << std::endl; } std::cout << k << ":" << cmState::CacheEntryTypeToString(t) << "=" - << cm.GetState()->GetCacheEntryValue(k) << std::endl; + << cm.GetState()->GetSafeCacheEntryValue(k) << std::endl; if (list_help) { std::cout << std::endl; } diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx index caf6453..5c27ac1 100644 --- a/Source/cmcldeps.cxx +++ b/Source/cmcldeps.cxx @@ -25,6 +25,7 @@ #include "cmsys/Encoding.hxx" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" // We don't want any wildcard expansion. @@ -63,7 +64,7 @@ static void usage(const char* msg) msg); } -static std::string trimLeadingSpace(const std::string& cmdline) +static cm::string_view trimLeadingSpace(cm::string_view cmdline) { int i = 0; for (; cmdline[i] == ' '; ++i) @@ -81,34 +82,30 @@ static void replaceAll(std::string& str, const std::string& search, } } -bool startsWith(const std::string& str, const std::string& what) -{ - return str.compare(0, what.size(), what) == 0; -} - // Strips one argument from the cmdline and returns it. "surrounding quotes" // are removed from the argument if there were any. static std::string getArg(std::string& cmdline) { - std::string ret; bool in_quoted = false; unsigned int i = 0; - cmdline = trimLeadingSpace(cmdline); + cm::string_view cmdview = trimLeadingSpace(cmdline); + size_t spaceCnt = cmdline.size() - cmdview.size(); for (;; ++i) { - if (i >= cmdline.size()) + if (i >= cmdview.size()) usage("Couldn't parse arguments."); - if (!in_quoted && cmdline[i] == ' ') + if (!in_quoted && cmdview[i] == ' ') break; // "a b" "x y" - if (cmdline[i] == '"') + if (cmdview[i] == '"') in_quoted = !in_quoted; } - ret = cmdline.substr(0, i); - if (ret[0] == '"' && ret[i - 1] == '"') - ret = ret.substr(1, ret.size() - 2); - cmdline = cmdline.substr(i); + cmdview = cmdview.substr(0, i); + if (cmdview[0] == '"' && cmdview[i - 1] == '"') + cmdview = cmdview.substr(1, i - 2); + std::string ret(cmdview); + cmdline.erase(0, spaceCnt + i); return ret; } @@ -127,7 +124,7 @@ static void parseCommandLine(LPWSTR wincmdline, std::string& lang, prefix = getArg(cmdline); clpath = getArg(cmdline); binpath = getArg(cmdline); - rest = trimLeadingSpace(cmdline); + rest = std::string(trimLeadingSpace(cmdline)); } // Not all backslashes need to be escaped in a depfile, but it's easier that @@ -169,8 +166,8 @@ static void outputDepFile(const std::string& dfile, const std::string& objfile, // build.ninja file. Therefore we need to canonicalize the path to use // backward slashes and relativize the path to the build directory. replaceAll(tmp, "/", "\\"); - if (startsWith(tmp, cwd)) - tmp = tmp.substr(cwd.size()); + if (cmHasPrefix(tmp, cwd)) + tmp.erase(0, cwd.size()); escapePath(tmp); fprintf(out, "%s \\\n", tmp.c_str()); } @@ -194,7 +191,7 @@ std::string replace(const std::string& str, const std::string& what, return replaced.replace(pos, what.size(), replacement); } -static int process(const std::string& srcfilename, const std::string& dfile, +static int process(cm::string_view srcfilename, const std::string& dfile, const std::string& objfile, const std::string& prefix, const std::string& cmd, const std::string& dir = "", bool quiet = false) @@ -221,13 +218,14 @@ static int process(const std::string& srcfilename, const std::string& dfile, std::vector<std::string> includes; bool isFirstLine = true; // cl prints always first the source filename while (std::getline(ss, line)) { - if (startsWith(line, prefix)) { - std::string inc = trimLeadingSpace(line.substr(prefix.size()).c_str()); + cm::string_view inc(line); + if (cmHasPrefix(inc, prefix)) { + inc = trimLeadingSpace(inc.substr(prefix.size())); if (inc.back() == '\r') // blech, stupid \r\n inc = inc.substr(0, inc.size() - 1); - includes.push_back(inc); + includes.emplace_back(std::string(inc)); } else { - if (!isFirstLine || !startsWith(line, srcfilename)) { + if (!isFirstLine || !cmHasPrefix(inc, srcfilename)) { if (!quiet || exit_code != 0) { fprintf(stdout, "%s\n", line.c_str()); } @@ -258,14 +256,10 @@ int main() cl, binpath, rest); // needed to suppress filename output of msvc tools - std::string srcfilename; - { - std::string::size_type pos = srcfile.rfind('\\'); - if (pos == std::string::npos) { - srcfilename = srcfile; - } else { - srcfilename = srcfile.substr(pos + 1); - } + cm::string_view srcfilename(srcfile); + std::string::size_type pos = srcfile.rfind('\\'); + if (pos != std::string::npos) { + srcfilename = srcfilename.substr(pos + 1); } std::string nol = " /nologo "; @@ -286,7 +280,7 @@ int main() // call cl in object dir so the .i is generated there std::string objdir; { - std::string::size_type pos = objfile.rfind("\\"); + pos = objfile.rfind("\\"); if (pos != std::string::npos) { objdir = objfile.substr(0, pos); } diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 7eeb97f..18a2108 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -678,7 +678,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) } else if (!a.empty() && a[0] == '-') { // Environment variable and command names cannot start in '-', // so this must be an unknown option. - std::cerr << "cmake -E env: unknown option '" << a << "'" + std::cerr << "cmake -E env: unknown option '" << a << '\'' << std::endl; return 1; } else if (a.find('=') != std::string::npos) { @@ -1054,8 +1054,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) homeOutDir = args[5]; startOutDir = args[6]; depInfo = args[7]; - if (args.size() >= 9 && args[8].length() >= 8 && - args[8].substr(0, 8) == "--color=") { + if (args.size() >= 9 && cmHasLiteralPrefix(args[8], "--color=")) { // Enable or disable color based on the switch value. color = (args[8].size() == 8 || cmIsOn(args[8].substr(8))); } @@ -1304,7 +1303,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) } else if (arg == "--debug") { pipe.clear(); isDebug = true; - } else if (arg.substr(0, pipePrefix.size()) == pipePrefix) { + } else if (cmHasPrefix(arg, pipePrefix)) { isDebug = false; pipe = arg.substr(pipePrefix.size()); if (pipe.empty()) { @@ -1511,7 +1510,7 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string> const& args) bool newline = true; std::string progressDir; for (auto const& arg : cmMakeRange(args).advance(2)) { - if (arg.find("--switch=") == 0) { + if (cmHasLiteralPrefix(arg, "--switch=")) { // Enable or disable color based on the switch value. std::string value = arg.substr(9); if (!value.empty()) { @@ -1566,7 +1565,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string> const& args) // args[3] == --verbose=? bool verbose = false; if (args.size() >= 4) { - if (args[3].find("--verbose=") == 0) { + if (cmHasLiteralPrefix(args[3], "--verbose=")) { if (!cmIsOff(args[3].substr(10))) { verbose = true; } @@ -1654,11 +1653,13 @@ int cmcmd::WindowsCEEnvironment(const char* version, const std::string& name) cmVisualStudioWCEPlatformParser parser(name.c_str()); parser.ParseVersion(version); if (parser.Found()) { - std::cout << "@echo off" << std::endl; - std::cout << "echo Environment Selection: " << name << std::endl; - std::cout << "set PATH=" << parser.GetPathDirectories() << std::endl; - std::cout << "set INCLUDE=" << parser.GetIncludeDirectories() << std::endl; - std::cout << "set LIB=" << parser.GetLibraryDirectories() << std::endl; + /* clang-format off */ + std::cout << "@echo off\n" + "echo Environment Selection: " << name << "\n" + "set PATH=" << parser.GetPathDirectories() << "\n" + "set INCLUDE=" << parser.GetIncludeDirectories() << "\n" + "set LIB=" << parser.GetLibraryDirectories() << std::endl; + /* clang-format on */ return 0; } #else @@ -1697,6 +1698,11 @@ int cmcmd::RunPreprocessor(const std::vector<std::string>& command, } auto status = process.GetStatus(); if (!status[0] || status[0]->ExitStatus != 0) { + auto errorStream = process.ErrorStream(); + if (errorStream) { + std::cerr << errorStream->rdbuf(); + } + return 1; } @@ -1765,6 +1771,10 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args) } auto status = process.GetStatus(); if (!status[0] || status[0]->ExitStatus != 0) { + auto errorStream = process.ErrorStream(); + if (errorStream) { + std::cerr << errorStream->rdbuf(); + } return 1; } @@ -1826,7 +1836,7 @@ int cmcmd::VisualStudioLink(std::vector<std::string> const& args, int type) std::vector<std::string> expandedArgs; for (std::string const& i : args) { // check for nmake temporary files - if (i[0] == '@' && i.find("@CMakeFiles") != 0) { + if (i[0] == '@' && !cmHasLiteralPrefix(i, "@CMakeFiles")) { cmsys::ifstream fin(i.substr(1).c_str()); std::string line; while (cmSystemTools::GetLineFromStream(fin, line)) { diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 09bcdb9..5de2776 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -11,9 +11,9 @@ # be used. All classes are disabled by default. The CMake listfile # above this one configures the library as follows: # -# SET(KWSYS_NAMESPACE foosys) -# SET(KWSYS_USE_Directory 1) # Enable Directory class. -# SUBDIRS(kwsys) +# set(KWSYS_NAMESPACE foosys) +# set(KWSYS_USE_Directory 1) # Enable Directory class. +# add_subdirectory(kwsys) # # Optional settings are as follows: # @@ -39,8 +39,8 @@ # # Example: # -# SET(KWSYS_HEADER_ROOT ${PROJECT_BINARY_DIR}) -# INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR}) +# set(KWSYS_HEADER_ROOT ${PROJECT_BINARY_DIR}) +# include_directories(${PROJECT_BINARY_DIR}) # # KWSYS_CXX_STANDARD = A value for CMAKE_CXX_STANDARD within KWSys. # Set to empty string to use no default value. @@ -65,11 +65,11 @@ # # Example: # -# SET(KWSYS_INSTALL_BIN_DIR bin) -# SET(KWSYS_INSTALL_LIB_DIR lib) -# SET(KWSYS_INSTALL_INCLUDE_DIR include) -# SET(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME Runtime) -# SET(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT Development) +# set(KWSYS_INSTALL_BIN_DIR bin) +# set(KWSYS_INSTALL_LIB_DIR lib) +# set(KWSYS_INSTALL_INCLUDE_DIR include) +# set(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME Runtime) +# set(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT Development) # Once configured, kwsys should be used as follows from C or C++ code: # @@ -86,33 +86,33 @@ # any outside mailing list and no documentation of the change will be # written. -CMAKE_MINIMUM_REQUIRED(VERSION 3.1 FATAL_ERROR) -FOREACH(p +cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +foreach(p CMP0056 # CMake 3.2, Honor link flags in try_compile() source-file signature. CMP0063 # CMake 3.3, Honor visibility properties for all target types. CMP0067 # CMake 3.8, Honor language standard in try_compile source-file signature. CMP0069 # CMake 3.9, INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. ) - IF(POLICY ${p}) - CMAKE_POLICY(SET ${p} NEW) - ENDIF() -ENDFOREACH() + if(POLICY ${p}) + cmake_policy(SET ${p} NEW) + endif() +endforeach() #----------------------------------------------------------------------------- # If a namespace is not specified, use "kwsys" and enable testing. # This should be the case only when kwsys is not included inside # another project and is being tested. -IF(NOT KWSYS_NAMESPACE) - SET(KWSYS_NAMESPACE "kwsys") - SET(KWSYS_STANDALONE 1) -ENDIF() +if(NOT KWSYS_NAMESPACE) + set(KWSYS_NAMESPACE "kwsys") + set(KWSYS_STANDALONE 1) +endif() #----------------------------------------------------------------------------- # The project name is that of the specified namespace. -PROJECT(${KWSYS_NAMESPACE}) +project(${KWSYS_NAMESPACE}) # Tell CMake how to follow dependencies of sources in this directory. -SET_PROPERTY(DIRECTORY +set_property(DIRECTORY PROPERTY IMPLICIT_DEPENDS_INCLUDE_TRANSFORM "KWSYS_HEADER(%)=<${KWSYS_NAMESPACE}/%>" ) @@ -131,229 +131,229 @@ elseif(NOT DEFINED CMAKE_CXX_STANDARD AND NOT DEFINED KWSYS_CXX_STANDARD) endif() # Select library components. -IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) - SET(KWSYS_ENABLE_C 1) +if(KWSYS_STANDALONE OR CMake_SOURCE_DIR) + set(KWSYS_ENABLE_C 1) # Enable all components. - SET(KWSYS_USE_Base64 1) - SET(KWSYS_USE_Directory 1) - SET(KWSYS_USE_DynamicLoader 1) - SET(KWSYS_USE_Encoding 1) - SET(KWSYS_USE_Glob 1) - SET(KWSYS_USE_MD5 1) - SET(KWSYS_USE_Process 1) - SET(KWSYS_USE_RegularExpression 1) - SET(KWSYS_USE_System 1) - SET(KWSYS_USE_SystemTools 1) - SET(KWSYS_USE_CommandLineArguments 1) - SET(KWSYS_USE_Terminal 1) - SET(KWSYS_USE_IOStream 1) - SET(KWSYS_USE_FStream 1) - SET(KWSYS_USE_String 1) - SET(KWSYS_USE_SystemInformation 1) - SET(KWSYS_USE_ConsoleBuf 1) -ENDIF() + set(KWSYS_USE_Base64 1) + set(KWSYS_USE_Directory 1) + set(KWSYS_USE_DynamicLoader 1) + set(KWSYS_USE_Encoding 1) + set(KWSYS_USE_Glob 1) + set(KWSYS_USE_MD5 1) + set(KWSYS_USE_Process 1) + set(KWSYS_USE_RegularExpression 1) + set(KWSYS_USE_System 1) + set(KWSYS_USE_SystemTools 1) + set(KWSYS_USE_CommandLineArguments 1) + set(KWSYS_USE_Terminal 1) + set(KWSYS_USE_IOStream 1) + set(KWSYS_USE_FStream 1) + set(KWSYS_USE_String 1) + set(KWSYS_USE_SystemInformation 1) + set(KWSYS_USE_ConsoleBuf 1) +endif() # Enforce component dependencies. -IF(KWSYS_USE_SystemTools) - SET(KWSYS_USE_Directory 1) - SET(KWSYS_USE_FStream 1) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_Glob) - SET(KWSYS_USE_Directory 1) - SET(KWSYS_USE_SystemTools 1) - SET(KWSYS_USE_RegularExpression 1) - SET(KWSYS_USE_FStream 1) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_Process) - SET(KWSYS_USE_System 1) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_SystemInformation) - SET(KWSYS_USE_Process 1) -ENDIF() -IF(KWSYS_USE_System) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_Directory) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_DynamicLoader) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_FStream) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_ConsoleBuf) - SET(KWSYS_USE_Encoding 1) -ENDIF() +if(KWSYS_USE_SystemTools) + set(KWSYS_USE_Directory 1) + set(KWSYS_USE_FStream 1) + set(KWSYS_USE_Encoding 1) +endif() +if(KWSYS_USE_Glob) + set(KWSYS_USE_Directory 1) + set(KWSYS_USE_SystemTools 1) + set(KWSYS_USE_RegularExpression 1) + set(KWSYS_USE_FStream 1) + set(KWSYS_USE_Encoding 1) +endif() +if(KWSYS_USE_Process) + set(KWSYS_USE_System 1) + set(KWSYS_USE_Encoding 1) +endif() +if(KWSYS_USE_SystemInformation) + set(KWSYS_USE_Process 1) +endif() +if(KWSYS_USE_System) + set(KWSYS_USE_Encoding 1) +endif() +if(KWSYS_USE_Directory) + set(KWSYS_USE_Encoding 1) +endif() +if(KWSYS_USE_DynamicLoader) + set(KWSYS_USE_Encoding 1) +endif() +if(KWSYS_USE_FStream) + set(KWSYS_USE_Encoding 1) +endif() +if(KWSYS_USE_ConsoleBuf) + set(KWSYS_USE_Encoding 1) +endif() # Specify default 8 bit encoding for Windows -IF(NOT KWSYS_ENCODING_DEFAULT_CODEPAGE) - SET(KWSYS_ENCODING_DEFAULT_CODEPAGE CP_ACP) -ENDIF() +if(NOT KWSYS_ENCODING_DEFAULT_CODEPAGE) + set(KWSYS_ENCODING_DEFAULT_CODEPAGE CP_ACP) +endif() # Enable testing if building standalone. -IF(KWSYS_STANDALONE) - INCLUDE(Dart) - MARK_AS_ADVANCED(BUILD_TESTING DART_ROOT TCL_TCLSH) - IF(BUILD_TESTING) - ENABLE_TESTING() - ENDIF() -ENDIF() +if(KWSYS_STANDALONE) + include(Dart) + mark_as_advanced(BUILD_TESTING DART_ROOT TCL_TCLSH) + if(BUILD_TESTING) + enable_testing() + endif() +endif() # Choose default shared/static build if not specified. -IF(NOT DEFINED KWSYS_BUILD_SHARED) - SET(KWSYS_BUILD_SHARED ${BUILD_SHARED_LIBS}) -ENDIF() +if(NOT DEFINED KWSYS_BUILD_SHARED) + set(KWSYS_BUILD_SHARED ${BUILD_SHARED_LIBS}) +endif() # Include helper macros. -INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformTests.cmake) -INCLUDE(CheckTypeSize) +include(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformTests.cmake) +include(CheckTypeSize) # Do full dependency headers. -INCLUDE_REGULAR_EXPRESSION("^.*$") +include_regular_expression("^.*$") # Use new KWSYS_INSTALL_*_DIR variable names to control installation. # Take defaults from the old names. Note that there was no old name # for the bin dir, so we take the old lib dir name so DLLs will be # installed in a compatible way for old code. -IF(NOT KWSYS_INSTALL_INCLUDE_DIR) - STRING(REGEX REPLACE "^/" "" KWSYS_INSTALL_INCLUDE_DIR +if(NOT KWSYS_INSTALL_INCLUDE_DIR) + string(REGEX REPLACE "^/" "" KWSYS_INSTALL_INCLUDE_DIR "${KWSYS_HEADER_INSTALL_DIR}") -ENDIF() -IF(NOT KWSYS_INSTALL_LIB_DIR) - STRING(REGEX REPLACE "^/" "" KWSYS_INSTALL_LIB_DIR +endif() +if(NOT KWSYS_INSTALL_LIB_DIR) + string(REGEX REPLACE "^/" "" KWSYS_INSTALL_LIB_DIR "${KWSYS_LIBRARY_INSTALL_DIR}") -ENDIF() -IF(NOT KWSYS_INSTALL_BIN_DIR) - STRING(REGEX REPLACE "^/" "" KWSYS_INSTALL_BIN_DIR +endif() +if(NOT KWSYS_INSTALL_BIN_DIR) + string(REGEX REPLACE "^/" "" KWSYS_INSTALL_BIN_DIR "${KWSYS_LIBRARY_INSTALL_DIR}") -ENDIF() +endif() # Setup header install rules. -SET(KWSYS_INSTALL_INCLUDE_OPTIONS) -IF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT) - SET(KWSYS_INSTALL_INCLUDE_OPTIONS ${KWSYS_INSTALL_INCLUDE_OPTIONS} +set(KWSYS_INSTALL_INCLUDE_OPTIONS) +if(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT) + set(KWSYS_INSTALL_INCLUDE_OPTIONS ${KWSYS_INSTALL_INCLUDE_OPTIONS} COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT} ) -ENDIF() +endif() # Setup library install rules. -SET(KWSYS_INSTALL_LIBRARY_RULE) -SET(KWSYS_INSTALL_NAMELINK_RULE) -IF(KWSYS_INSTALL_LIB_DIR) - IF(KWSYS_INSTALL_EXPORT_NAME) - LIST(APPEND KWSYS_INSTALL_LIBRARY_RULE EXPORT ${KWSYS_INSTALL_EXPORT_NAME}) - ENDIF() +set(KWSYS_INSTALL_LIBRARY_RULE) +set(KWSYS_INSTALL_NAMELINK_RULE) +if(KWSYS_INSTALL_LIB_DIR) + if(KWSYS_INSTALL_EXPORT_NAME) + list(APPEND KWSYS_INSTALL_LIBRARY_RULE EXPORT ${KWSYS_INSTALL_EXPORT_NAME}) + endif() # Install the shared library to the lib directory. - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} + set(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR} NAMELINK_SKIP ) # Assign the shared library to the runtime component. - IF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME) - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} + if(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME) + set(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME} ) - ENDIF() - IF(KWSYS_BUILD_SHARED) - SET(KWSYS_INSTALL_NAMELINK_RULE ${KWSYS_INSTALL_NAMELINK_RULE} + endif() + if(KWSYS_BUILD_SHARED) + set(KWSYS_INSTALL_NAMELINK_RULE ${KWSYS_INSTALL_NAMELINK_RULE} LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR} NAMELINK_ONLY ) # Assign the namelink to the development component. - IF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT) - SET(KWSYS_INSTALL_NAMELINK_RULE ${KWSYS_INSTALL_NAMELINK_RULE} + if(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT) + set(KWSYS_INSTALL_NAMELINK_RULE ${KWSYS_INSTALL_NAMELINK_RULE} COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT} ) - ENDIF() - ENDIF() + endif() + endif() # Install the archive to the lib directory. - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} + set(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} ARCHIVE DESTINATION ${KWSYS_INSTALL_LIB_DIR} ) # Assign the archive to the development component. - IF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT) - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} + if(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT) + set(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT} ) - ENDIF() -ENDIF() -IF(KWSYS_INSTALL_BIN_DIR) + endif() +endif() +if(KWSYS_INSTALL_BIN_DIR) # Install the runtime library to the bin directory. - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} + set(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} RUNTIME DESTINATION ${KWSYS_INSTALL_BIN_DIR} ) # Assign the runtime library to the runtime component. - IF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME) - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} + if(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME) + set(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME} ) - ENDIF() -ENDIF() + endif() +endif() # Do not support old KWSYS_*a_INSTALL_DIR variable names. -SET(KWSYS_HEADER_INSTALL_DIR) -SET(KWSYS_LIBRARY_INSTALL_DIR) +set(KWSYS_HEADER_INSTALL_DIR) +set(KWSYS_LIBRARY_INSTALL_DIR) # Generated source files will need this header. -STRING(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" +string(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" KWSYS_IN_SOURCE_BUILD) -IF(NOT KWSYS_IN_SOURCE_BUILD) - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsysPrivate.h +if(NOT KWSYS_IN_SOURCE_BUILD) + configure_file(${PROJECT_SOURCE_DIR}/kwsysPrivate.h ${PROJECT_BINARY_DIR}/kwsysPrivate.h COPYONLY IMMEDIATE) -ENDIF() +endif() # Select plugin module file name convention. -IF(NOT KWSYS_DynamicLoader_PREFIX) - SET(KWSYS_DynamicLoader_PREFIX ${CMAKE_SHARED_MODULE_PREFIX}) -ENDIF() -IF(NOT KWSYS_DynamicLoader_SUFFIX) - SET(KWSYS_DynamicLoader_SUFFIX ${CMAKE_SHARED_MODULE_SUFFIX}) -ENDIF() +if(NOT KWSYS_DynamicLoader_PREFIX) + set(KWSYS_DynamicLoader_PREFIX ${CMAKE_SHARED_MODULE_PREFIX}) +endif() +if(NOT KWSYS_DynamicLoader_SUFFIX) + set(KWSYS_DynamicLoader_SUFFIX ${CMAKE_SHARED_MODULE_SUFFIX}) +endif() #----------------------------------------------------------------------------- # We require ANSI support from the C compiler. Add any needed flags. -IF(CMAKE_ANSI_CFLAGS) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ANSI_CFLAGS}") -ENDIF() +if(CMAKE_ANSI_CFLAGS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ANSI_CFLAGS}") +endif() #----------------------------------------------------------------------------- # Adjust compiler flags for some platforms. -IF(NOT CMAKE_COMPILER_IS_GNUCXX) - IF(CMAKE_SYSTEM MATCHES "OSF1-V.*") - STRING(REGEX MATCH "-timplicit_local" +if(NOT CMAKE_COMPILER_IS_GNUCXX) + if(CMAKE_SYSTEM MATCHES "OSF1-V.*") + string(REGEX MATCH "-timplicit_local" KWSYS_CXX_FLAGS_HAVE_IMPLICIT_LOCAL "${CMAKE_CXX_FLAGS}") - STRING(REGEX MATCH "-no_implicit_include" + string(REGEX MATCH "-no_implicit_include" KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE "${CMAKE_CXX_FLAGS}") - IF(NOT KWSYS_CXX_FLAGS_HAVE_IMPLICIT_LOCAL) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -timplicit_local") - ENDIF() - IF(NOT KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no_implicit_include") - ENDIF() - ENDIF() - IF(CMAKE_SYSTEM MATCHES "HP-UX") - SET(KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS "+p") - IF(CMAKE_CXX_COMPILER_ID MATCHES "HP") + if(NOT KWSYS_CXX_FLAGS_HAVE_IMPLICIT_LOCAL) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -timplicit_local") + endif() + if(NOT KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no_implicit_include") + endif() + endif() + if(CMAKE_SYSTEM MATCHES "HP-UX") + set(KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS "+p") + if(CMAKE_CXX_COMPILER_ID MATCHES "HP") # it is known that version 3.85 fails and 6.25 works without these flags - IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4) + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4) # use new C++ library and improved template support - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -AA +hpxstd98") - ENDIF() - ENDIF() - ENDIF() -ENDIF() -IF(KWSYS_STANDALONE) - IF(CMAKE_CXX_COMPILER_ID STREQUAL SunPro) - IF(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03") - ELSE() - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -library=stlport4") - ENDIF() - ENDIF() -ENDIF() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -AA +hpxstd98") + endif() + endif() + endif() +endif() +if(KWSYS_STANDALONE) + if(CMAKE_CXX_COMPILER_ID STREQUAL SunPro) + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -library=stlport4") + endif() + endif() +endif() #----------------------------------------------------------------------------- # Configure the standard library header wrappers based on compiler's @@ -365,75 +365,75 @@ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_LONG_LONG "Checking whether C++ compiler has 'long long'" DIRECT) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS___INT64 "Checking whether C++ compiler has '__int64'" DIRECT) -IF(KWSYS_CXX_HAS___INT64) +if(KWSYS_CXX_HAS___INT64) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_SAME_LONG_AND___INT64 "Checking whether long and __int64 are the same type" DIRECT) - IF(KWSYS_CXX_HAS_LONG_LONG) + if(KWSYS_CXX_HAS_LONG_LONG) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_SAME_LONG_LONG_AND___INT64 "Checking whether long long and __int64 are the same type" DIRECT) - ENDIF() -ENDIF() + endif() +endif() # Enable the "long long" type if it is available. It is standard in # C99 and C++03 but not in earlier standards. -IF(KWSYS_CXX_HAS_LONG_LONG) - SET(KWSYS_USE_LONG_LONG 1) -ELSE() - SET(KWSYS_USE_LONG_LONG 0) -ENDIF() +if(KWSYS_CXX_HAS_LONG_LONG) + set(KWSYS_USE_LONG_LONG 1) +else() + set(KWSYS_USE_LONG_LONG 0) +endif() # Enable the "__int64" type if it is available and unique. It is not # standard. -SET(KWSYS_USE___INT64 0) -IF(KWSYS_CXX_HAS___INT64) - IF(NOT KWSYS_CXX_SAME_LONG_AND___INT64) - IF(NOT KWSYS_CXX_SAME_LONG_LONG_AND___INT64) - SET(KWSYS_USE___INT64 1) - ENDIF() - ENDIF() -ENDIF() - -IF(KWSYS_USE_Encoding) +set(KWSYS_USE___INT64 0) +if(KWSYS_CXX_HAS___INT64) + if(NOT KWSYS_CXX_SAME_LONG_AND___INT64) + if(NOT KWSYS_CXX_SAME_LONG_LONG_AND___INT64) + set(KWSYS_USE___INT64 1) + endif() + endif() +endif() + +if(KWSYS_USE_Encoding) # Look for type size helper macros. KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_WSTRING "Checking whether wstring is available" DIRECT) -ENDIF() +endif() -IF(KWSYS_USE_IOStream) +if(KWSYS_USE_IOStream) # Determine whether iostreams support long long. - IF(KWSYS_CXX_HAS_LONG_LONG) + if(KWSYS_CXX_HAS_LONG_LONG) KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_ISTREAM_LONG_LONG "Checking if istream supports long long" DIRECT) KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_OSTREAM_LONG_LONG "Checking if ostream supports long long" DIRECT) - ELSE() - SET(KWSYS_IOS_HAS_ISTREAM_LONG_LONG 0) - SET(KWSYS_IOS_HAS_OSTREAM_LONG_LONG 0) - ENDIF() - IF(KWSYS_CXX_HAS___INT64) + else() + set(KWSYS_IOS_HAS_ISTREAM_LONG_LONG 0) + set(KWSYS_IOS_HAS_OSTREAM_LONG_LONG 0) + endif() + if(KWSYS_CXX_HAS___INT64) KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_ISTREAM___INT64 "Checking if istream supports __int64" DIRECT) KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_OSTREAM___INT64 "Checking if ostream supports __int64" DIRECT) - ELSE() - SET(KWSYS_IOS_HAS_ISTREAM___INT64 0) - SET(KWSYS_IOS_HAS_OSTREAM___INT64 0) - ENDIF() -ENDIF() - -IF(KWSYS_NAMESPACE MATCHES "^kwsys$") - SET(KWSYS_NAME_IS_KWSYS 1) -ELSE() - SET(KWSYS_NAME_IS_KWSYS 0) -ENDIF() - -IF(KWSYS_BUILD_SHARED) - SET(KWSYS_BUILD_SHARED 1) - SET(KWSYS_LIBRARY_TYPE SHARED) -ELSE() - SET(KWSYS_BUILD_SHARED 0) - SET(KWSYS_LIBRARY_TYPE STATIC) -ENDIF() + else() + set(KWSYS_IOS_HAS_ISTREAM___INT64 0) + set(KWSYS_IOS_HAS_OSTREAM___INT64 0) + endif() +endif() + +if(KWSYS_NAMESPACE MATCHES "^kwsys$") + set(KWSYS_NAME_IS_KWSYS 1) +else() + set(KWSYS_NAME_IS_KWSYS 0) +endif() + +if(KWSYS_BUILD_SHARED) + set(KWSYS_BUILD_SHARED 1) + set(KWSYS_LIBRARY_TYPE SHARED) +else() + set(KWSYS_BUILD_SHARED 0) + set(KWSYS_LIBRARY_TYPE STATIC) +endif() if(NOT DEFINED KWSYS_BUILD_PIC) set(KWSYS_BUILD_PIC 0) @@ -446,32 +446,32 @@ KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_PTRDIFF_T "Checking whether C compiler has ptrdiff_t in stddef.h" DIRECT) KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_SSIZE_T "Checking whether C compiler has ssize_t in unistd.h" DIRECT) -IF(KWSYS_USE_Process) +if(KWSYS_USE_Process) KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC "Checking whether C compiler has clock_gettime" DIRECT) -ENDIF() +endif() -SET_SOURCE_FILES_PROPERTIES(ProcessUNIX.c System.c PROPERTIES +set_source_files_properties(ProcessUNIX.c System.c PROPERTIES COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T} -DKWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC=${KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC}" ) -IF(DEFINED KWSYS_PROCESS_USE_SELECT) - GET_PROPERTY(ProcessUNIX_FLAGS SOURCE ProcessUNIX.c PROPERTY COMPILE_FLAGS) - SET_PROPERTY(SOURCE ProcessUNIX.c PROPERTY COMPILE_FLAGS "${ProcessUNIX_FLAGS} -DKWSYSPE_USE_SELECT=${KWSYSPE_USE_SELECT}") -ENDIF() - -IF(KWSYS_USE_DynamicLoader) - GET_PROPERTY(KWSYS_SUPPORTS_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) - IF(KWSYS_SUPPORTS_SHARED_LIBS) - SET(KWSYS_SUPPORTS_SHARED_LIBS 1) - ELSE() - SET(KWSYS_SUPPORTS_SHARED_LIBS 0) - ENDIF() - SET_PROPERTY(SOURCE DynamicLoader.cxx APPEND PROPERTY COMPILE_DEFINITIONS +if(DEFINED KWSYS_PROCESS_USE_SELECT) + get_property(ProcessUNIX_FLAGS SOURCE ProcessUNIX.c PROPERTY COMPILE_FLAGS) + set_property(SOURCE ProcessUNIX.c PROPERTY COMPILE_FLAGS "${ProcessUNIX_FLAGS} -DKWSYSPE_USE_SELECT=${KWSYSPE_USE_SELECT}") +endif() + +if(KWSYS_USE_DynamicLoader) + get_property(KWSYS_SUPPORTS_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) + if(KWSYS_SUPPORTS_SHARED_LIBS) + set(KWSYS_SUPPORTS_SHARED_LIBS 1) + else() + set(KWSYS_SUPPORTS_SHARED_LIBS 0) + endif() + set_property(SOURCE DynamicLoader.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_SUPPORTS_SHARED_LIBS=${KWSYS_SUPPORTS_SHARED_LIBS}) -ENDIF() +endif() -IF(KWSYS_USE_SystemTools) +if(KWSYS_USE_SystemTools) if (NOT DEFINED KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP) set(KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP 1) endif () @@ -494,7 +494,7 @@ IF(KWSYS_USE_SystemTools) "Checking whether CXX compiler struct stat has st_mtim member" DIRECT) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_STAT_HAS_ST_MTIMESPEC "Checking whether CXX compiler struct stat has st_mtimespec member" DIRECT) - SET_PROPERTY(SOURCE SystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS + set_property(SOURCE SystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV} KWSYS_CXX_HAS_UNSETENV=${KWSYS_CXX_HAS_UNSETENV} KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=${KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H} @@ -503,623 +503,623 @@ IF(KWSYS_USE_SystemTools) KWSYS_CXX_STAT_HAS_ST_MTIM=${KWSYS_CXX_STAT_HAS_ST_MTIM} KWSYS_CXX_STAT_HAS_ST_MTIMESPEC=${KWSYS_CXX_STAT_HAS_ST_MTIMESPEC} ) - IF(NOT WIN32) - IF(KWSYS_STANDALONE) - OPTION(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES "If true, Windows paths will be supported on Unix as well" ON) - ENDIF() - IF(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES) - SET_PROPERTY(SOURCE SystemTools.cxx testSystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS + if(NOT WIN32) + if(KWSYS_STANDALONE) + option(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES "If true, Windows paths will be supported on Unix as well" ON) + endif() + if(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES) + set_property(SOURCE SystemTools.cxx testSystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES ) - ENDIF() - ENDIF() + endif() + endif() # Disable getpwnam for static linux builds since it depends on shared glibc - GET_PROPERTY(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) - IF(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT SHARED_LIBS_SUPPORTED) - SET_PROPERTY(SOURCE SystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS + get_property(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) + if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT SHARED_LIBS_SUPPORTED) + set_property(SOURCE SystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS HAVE_GETPWNAM=0 ) - ENDIF() -ENDIF() + endif() +endif() -IF(KWSYS_USE_SystemInformation) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY +if(KWSYS_USE_SystemInformation) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P}) - IF(NOT CYGWIN) - INCLUDE(CheckIncludeFiles) + if(NOT CYGWIN) + include(CheckIncludeFiles) CHECK_INCLUDE_FILES("sys/types.h;ifaddrs.h" KWSYS_SYS_HAS_IFADDRS_H) - IF(KWSYS_SYS_HAS_IFADDRS_H) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + if(KWSYS_SYS_HAS_IFADDRS_H) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_SYS_HAS_IFADDRS_H=1) - ENDIF() - ENDIF() - IF(WIN32) - INCLUDE(CheckSymbolExists) - SET(CMAKE_REQUIRED_LIBRARIES Psapi) + endif() + endif() + if(WIN32) + include(CheckSymbolExists) + set(CMAKE_REQUIRED_LIBRARIES psapi) CHECK_SYMBOL_EXISTS(GetProcessMemoryInfo "windows.h;psapi.h" KWSYS_SYS_HAS_PSAPI) - UNSET(CMAKE_REQUIRED_LIBRARIES) - IF(KWSYS_SYS_HAS_PSAPI) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + unset(CMAKE_REQUIRED_LIBRARIES) + if(KWSYS_SYS_HAS_PSAPI) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_SYS_HAS_PSAPI=1) - IF(MSVC70 OR MSVC71) + if(MSVC70 OR MSVC71) # Suppress LNK4089: all references to 'PSAPI.DLL' discarded by /OPT:REF - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /IGNORE:4089") - ENDIF() - ENDIF() - ENDIF() - IF(CMAKE_SYSTEM MATCHES "HP-UX") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /IGNORE:4089") + endif() + endif() + endif() + if(CMAKE_SYSTEM MATCHES "HP-UX") CHECK_INCLUDE_FILES("sys/mpctl.h" KWSYS_SYS_HAS_MPCTL_H) - IF(KWSYS_SYS_HAS_MPCTL_H) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + if(KWSYS_SYS_HAS_MPCTL_H) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_SYS_HAS_MPCTL_H=1) - ENDIF() - ENDIF() - IF(CMAKE_SYSTEM MATCHES "BSD") + endif() + endif() + if(CMAKE_SYSTEM MATCHES "BSD") CHECK_INCLUDE_FILES("machine/cpu.h" KWSYS_SYS_HAS_MACHINE_CPU_H) - IF(KWSYS_SYS_HAS_MACHINE_CPU_H) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + if(KWSYS_SYS_HAS_MACHINE_CPU_H) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_SYS_HAS_MACHINE_CPU_H=1) - ENDIF() - ENDIF() + endif() + endif() KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_RLIMIT64 "Checking whether CXX compiler has rlimit64" DIRECT) - SET(KWSYS_PLATFORM_CXX_TEST_DEFINES) - IF(KWSYS_CXX_HAS_RLIMIT64) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + set(KWSYS_PLATFORM_CXX_TEST_DEFINES) + if(KWSYS_CXX_HAS_RLIMIT64) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS_RLIMIT64=1) - ENDIF() + endif() KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ATOL "Checking whether CXX compiler has atol" DIRECT) - IF(KWSYS_CXX_HAS_ATOL) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + if(KWSYS_CXX_HAS_ATOL) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS_ATOL=1) - ENDIF() + endif() KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ATOLL "Checking whether CXX compiler has atoll" DIRECT) - IF(KWSYS_CXX_HAS_ATOLL) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + if(KWSYS_CXX_HAS_ATOLL) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS_ATOLL=1) - ENDIF() + endif() KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS__ATOI64 "Checking whether CXX compiler has _atoi64" DIRECT) - IF(KWSYS_CXX_HAS__ATOI64) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + if(KWSYS_CXX_HAS__ATOI64) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1) - ENDIF() - IF(UNIX) - INCLUDE(CheckIncludeFileCXX) + endif() + if(UNIX) + include(CheckIncludeFileCXX) # check for simple stack trace # usually it's in libc but on FreeBSD # it's in libexecinfo - FIND_LIBRARY(EXECINFO_LIB "execinfo") - MARK_AS_ADVANCED(EXECINFO_LIB) - IF (NOT EXECINFO_LIB) - SET(EXECINFO_LIB "") - ENDIF() + find_library(EXECINFO_LIB "execinfo") + mark_as_advanced(EXECINFO_LIB) + if (NOT EXECINFO_LIB) + set(EXECINFO_LIB "") + endif() CHECK_INCLUDE_FILE_CXX("execinfo.h" KWSYS_CXX_HAS_EXECINFOH) - IF (KWSYS_CXX_HAS_EXECINFOH) + if (KWSYS_CXX_HAS_EXECINFOH) # we have the backtrace header check if it # can be used with this compiler - SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${EXECINFO_LIB}) + set(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${EXECINFO_LIB}) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BACKTRACE "Checking whether backtrace works with this C++ compiler" DIRECT) - SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES) - IF (KWSYS_CXX_HAS_BACKTRACE) + set(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES) + if (KWSYS_CXX_HAS_BACKTRACE) # backtrace is supported by this system and compiler. # now check for the more advanced capabilities. - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE=1) # check for symbol lookup using dladdr CHECK_INCLUDE_FILE_CXX("dlfcn.h" KWSYS_CXX_HAS_DLFCNH) - IF (KWSYS_CXX_HAS_DLFCNH) + if (KWSYS_CXX_HAS_DLFCNH) # we have symbol lookup libraries and headers # check if they can be used with this compiler - SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${CMAKE_DL_LIBS}) + set(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${CMAKE_DL_LIBS}) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_DLADDR "Checking whether dladdr works with this C++ compiler" DIRECT) - SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES) - IF (KWSYS_CXX_HAS_DLADDR) + set(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES) + if (KWSYS_CXX_HAS_DLADDR) # symbol lookup is supported by this system # and compiler. - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP=1) - ENDIF() - ENDIF() + endif() + endif() # c++ demangling support # check for cxxabi headers CHECK_INCLUDE_FILE_CXX("cxxabi.h" KWSYS_CXX_HAS_CXXABIH) - IF (KWSYS_CXX_HAS_CXXABIH) + if (KWSYS_CXX_HAS_CXXABIH) # check if cxxabi can be used with this # system and compiler. KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CXXABI "Checking whether cxxabi works with this C++ compiler" DIRECT) - IF (KWSYS_CXX_HAS_CXXABI) + if (KWSYS_CXX_HAS_CXXABI) # c++ demangle using cxxabi is supported with # this system and compiler - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE=1) - ENDIF() - ENDIF() + endif() + endif() # basic backtrace works better with release build # don't bother with advanced features for release - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1) - ENDIF() - ENDIF() - ENDIF() - IF(BORLAND) + endif() + endif() + endif() + if(BORLAND) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM "Checking whether Borland CXX compiler supports assembler instructions" DIRECT) - IF(KWSYS_CXX_HAS_BORLAND_ASM) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + if(KWSYS_CXX_HAS_BORLAND_ASM) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM=1) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM_CPUID "Checking whether Borland CXX compiler supports CPUID assembler instruction" DIRECT) - IF(KWSYS_CXX_HAS_BORLAND_ASM_CPUID) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + if(KWSYS_CXX_HAS_BORLAND_ASM_CPUID) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM_CPUID=1) - ENDIF() - ENDIF() - ENDIF() - IF(KWSYS_USE___INT64) - SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY + endif() + endif() + endif() + if(KWSYS_USE___INT64) + set_property(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_USE___INT64=1) - ENDIF() - IF(KWSYS_USE_LONG_LONG) - SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY + endif() + if(KWSYS_USE_LONG_LONG) + set_property(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_USE_LONG_LONG=1) - ENDIF() - IF(KWSYS_IOS_HAS_OSTREAM_LONG_LONG) - SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY + endif() + if(KWSYS_IOS_HAS_OSTREAM_LONG_LONG) + set_property(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_IOS_HAS_OSTREAM_LONG_LONG=1) - ENDIF() - IF(KWSYS_IOS_HAS_OSTREAM___INT64) - SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY + endif() + if(KWSYS_IOS_HAS_OSTREAM___INT64) + set_property(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_IOS_HAS_OSTREAM___INT64=1) - ENDIF() - IF(KWSYS_BUILD_SHARED) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + endif() + if(KWSYS_BUILD_SHARED) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_BUILD_SHARED=1) - ENDIF() + endif() - IF(UNIX AND NOT CYGWIN) + if(UNIX AND NOT CYGWIN) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_GETLOADAVG "Checking whether CXX compiler has getloadavg" DIRECT) - IF(KWSYS_CXX_HAS_GETLOADAVG) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + if(KWSYS_CXX_HAS_GETLOADAVG) + set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS_GETLOADAVG=1) - ENDIF() - ENDIF() -ENDIF() + endif() + endif() +endif() -IF(KWSYS_USE_FStream) +if(KWSYS_USE_FStream) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H "Checking whether <ext/stdio_filebuf.h> is available" DIRECT) -ENDIF() +endif() #----------------------------------------------------------------------------- # Choose a directory for the generated headers. -IF(NOT KWSYS_HEADER_ROOT) - SET(KWSYS_HEADER_ROOT "${PROJECT_BINARY_DIR}") -ENDIF() -SET(KWSYS_HEADER_DIR "${KWSYS_HEADER_ROOT}/${KWSYS_NAMESPACE}") -INCLUDE_DIRECTORIES(${KWSYS_HEADER_ROOT}) +if(NOT KWSYS_HEADER_ROOT) + set(KWSYS_HEADER_ROOT "${PROJECT_BINARY_DIR}") +endif() +set(KWSYS_HEADER_DIR "${KWSYS_HEADER_ROOT}/${KWSYS_NAMESPACE}") +include_directories(${KWSYS_HEADER_ROOT}) #----------------------------------------------------------------------------- -IF(KWSYS_INSTALL_DOC_DIR) +if(KWSYS_INSTALL_DOC_DIR) # Assign the license to the runtime component since it must be # distributed with binary forms of this software. - IF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME) - SET(KWSYS_INSTALL_LICENSE_OPTIONS ${KWSYS_INSTALL_LICENSE_OPTIONS} + if(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME) + set(KWSYS_INSTALL_LICENSE_OPTIONS ${KWSYS_INSTALL_LICENSE_OPTIONS} COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME} ) - ENDIF() + endif() # Install the license under the documentation directory. - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt DESTINATION ${KWSYS_INSTALL_DOC_DIR}/${KWSYS_NAMESPACE} ${KWSYS_INSTALL_LICENSE_OPTIONS}) -ENDIF() +endif() #----------------------------------------------------------------------------- # Build a list of classes and headers we need to implement the # selected components. Initialize with required components. -SET(KWSYS_CLASSES) -SET(KWSYS_H_FILES Configure SharedForward) -SET(KWSYS_HXX_FILES Configure String) +set(KWSYS_CLASSES) +set(KWSYS_H_FILES Configure SharedForward) +set(KWSYS_HXX_FILES Configure String) -IF(NOT CMake_SOURCE_DIR) - SET(KWSYS_HXX_FILES ${KWSYS_HXX_FILES} +if(NOT CMake_SOURCE_DIR) + set(KWSYS_HXX_FILES ${KWSYS_HXX_FILES} hashtable hash_fun hash_map hash_set ) -ENDIF() +endif() # Add selected C++ classes. -SET(cppclasses +set(cppclasses Directory DynamicLoader Encoding Glob RegularExpression SystemTools CommandLineArguments IOStream FStream SystemInformation ConsoleBuf ) -FOREACH(cpp ${cppclasses}) - IF(KWSYS_USE_${cpp}) +foreach(cpp ${cppclasses}) + if(KWSYS_USE_${cpp}) # Use the corresponding class. - SET(KWSYS_CLASSES ${KWSYS_CLASSES} ${cpp}) + set(KWSYS_CLASSES ${KWSYS_CLASSES} ${cpp}) # Load component-specific CMake code. - IF(EXISTS ${PROJECT_SOURCE_DIR}/kwsys${cpp}.cmake) - INCLUDE(${PROJECT_SOURCE_DIR}/kwsys${cpp}.cmake) - ENDIF() - ENDIF() -ENDFOREACH() + if(EXISTS ${PROJECT_SOURCE_DIR}/kwsys${cpp}.cmake) + include(${PROJECT_SOURCE_DIR}/kwsys${cpp}.cmake) + endif() + endif() +endforeach() # Add selected C components. -FOREACH(c +foreach(c Process Base64 Encoding MD5 Terminal System String ) - IF(KWSYS_USE_${c}) + if(KWSYS_USE_${c}) # Use the corresponding header file. - SET(KWSYS_H_FILES ${KWSYS_H_FILES} ${c}) + set(KWSYS_H_FILES ${KWSYS_H_FILES} ${c}) # Load component-specific CMake code. - IF(EXISTS ${PROJECT_SOURCE_DIR}/kwsys${c}.cmake) - INCLUDE(${PROJECT_SOURCE_DIR}/kwsys${c}.cmake) - ENDIF() - ENDIF() -ENDFOREACH() + if(EXISTS ${PROJECT_SOURCE_DIR}/kwsys${c}.cmake) + include(${PROJECT_SOURCE_DIR}/kwsys${c}.cmake) + endif() + endif() +endforeach() #----------------------------------------------------------------------------- # Build a list of sources for the library based on components that are # included. -SET(KWSYS_C_SRCS) -SET(KWSYS_CXX_SRCS) +set(KWSYS_C_SRCS) +set(KWSYS_CXX_SRCS) # Add the proper sources for this platform's Process implementation. -IF(KWSYS_USE_Process) - IF(NOT UNIX) +if(KWSYS_USE_Process) + if(NOT UNIX) # Use the Windows implementation. - SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c) - ELSE() + set(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c) + else() # Use the UNIX implementation. - SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c) - ENDIF() -ENDIF() + set(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c) + endif() +endif() # Add selected C sources. -FOREACH(c Base64 Encoding MD5 Terminal System String) - IF(KWSYS_USE_${c}) - IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}C.c) - LIST(APPEND KWSYS_C_SRCS ${c}C.c) - ELSE() - LIST(APPEND KWSYS_C_SRCS ${c}.c) - ENDIF() - ENDIF() -ENDFOREACH() +foreach(c Base64 Encoding MD5 Terminal System String) + if(KWSYS_USE_${c}) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}C.c) + list(APPEND KWSYS_C_SRCS ${c}C.c) + else() + list(APPEND KWSYS_C_SRCS ${c}.c) + endif() + endif() +endforeach() # Configure headers of C++ classes and construct the list of sources. -FOREACH(c ${KWSYS_CLASSES}) +foreach(c ${KWSYS_CLASSES}) # Add this source to the list of source files for the library. - IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}CXX.cxx) - LIST(APPEND KWSYS_CXX_SRCS ${c}CXX.cxx) - ELSEIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}.cxx) - LIST(APPEND KWSYS_CXX_SRCS ${c}.cxx) - ENDIF() + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}CXX.cxx) + list(APPEND KWSYS_CXX_SRCS ${c}CXX.cxx) + elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}.cxx) + list(APPEND KWSYS_CXX_SRCS ${c}.cxx) + endif() # Configure the header for this class. - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${c}.hxx.in ${KWSYS_HEADER_DIR}/${c}.hxx + configure_file(${PROJECT_SOURCE_DIR}/${c}.hxx.in ${KWSYS_HEADER_DIR}/${c}.hxx @ONLY IMMEDIATE) - SET(KWSYS_CXX_SRCS ${KWSYS_CXX_SRCS} ${KWSYS_HEADER_DIR}/${c}.hxx) + set(KWSYS_CXX_SRCS ${KWSYS_CXX_SRCS} ${KWSYS_HEADER_DIR}/${c}.hxx) # Create an install target for the header. - IF(KWSYS_INSTALL_INCLUDE_DIR) - INSTALL(FILES ${KWSYS_HEADER_DIR}/${c}.hxx + if(KWSYS_INSTALL_INCLUDE_DIR) + install(FILES ${KWSYS_HEADER_DIR}/${c}.hxx DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE} ${KWSYS_INSTALL_INCLUDE_OPTIONS}) - ENDIF() -ENDFOREACH() + endif() +endforeach() # Configure C headers. -FOREACH(h ${KWSYS_H_FILES}) +foreach(h ${KWSYS_H_FILES}) # Configure the header into the given directory. - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.h.in ${KWSYS_HEADER_DIR}/${h}.h + configure_file(${PROJECT_SOURCE_DIR}/${h}.h.in ${KWSYS_HEADER_DIR}/${h}.h @ONLY IMMEDIATE) - SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ${KWSYS_HEADER_DIR}/${h}.h) + set(KWSYS_C_SRCS ${KWSYS_C_SRCS} ${KWSYS_HEADER_DIR}/${h}.h) # Create an install target for the header. - IF(KWSYS_INSTALL_INCLUDE_DIR) - INSTALL(FILES ${KWSYS_HEADER_DIR}/${h}.h + if(KWSYS_INSTALL_INCLUDE_DIR) + install(FILES ${KWSYS_HEADER_DIR}/${h}.h DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE} ${KWSYS_INSTALL_INCLUDE_OPTIONS}) - ENDIF() -ENDFOREACH() + endif() +endforeach() # Configure other C++ headers. -FOREACH(h ${KWSYS_HXX_FILES}) +foreach(h ${KWSYS_HXX_FILES}) # Configure the header into the given directory. - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.hxx.in ${KWSYS_HEADER_DIR}/${h}.hxx + configure_file(${PROJECT_SOURCE_DIR}/${h}.hxx.in ${KWSYS_HEADER_DIR}/${h}.hxx @ONLY IMMEDIATE) - SET(KWSYS_CXX_SRCS ${KWSYS_CXX_SRCS} ${KWSYS_HEADER_DIR}/${h}.hxx) + set(KWSYS_CXX_SRCS ${KWSYS_CXX_SRCS} ${KWSYS_HEADER_DIR}/${h}.hxx) # Create an install target for the header. - IF(KWSYS_INSTALL_INCLUDE_DIR) - INSTALL(FILES ${KWSYS_HEADER_DIR}/${h}.hxx + if(KWSYS_INSTALL_INCLUDE_DIR) + install(FILES ${KWSYS_HEADER_DIR}/${h}.hxx DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE} ${KWSYS_INSTALL_INCLUDE_OPTIONS}) - ENDIF() -ENDFOREACH() + endif() +endforeach() #----------------------------------------------------------------------------- # Add the library with the configured name and list of sources. -IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) - IF(KWSYS_SPLIT_OBJECTS_FROM_INTERFACE) - SET(KWSYS_TARGET_INTERFACE ${KWSYS_NAMESPACE}) - SET(KWSYS_TARGET_OBJECT ${KWSYS_NAMESPACE}_objects) - SET(KWSYS_TARGET_LINK ${KWSYS_NAMESPACE}_private) - SET(KWSYS_TARGET_INSTALL ${KWSYS_TARGET_INTERFACE} ${KWSYS_TARGET_LINK}) - SET(KWSYS_LINK_DEPENDENCY INTERFACE) - ADD_LIBRARY(${KWSYS_TARGET_OBJECT} OBJECT +if(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) + if(KWSYS_SPLIT_OBJECTS_FROM_INTERFACE) + set(KWSYS_TARGET_INTERFACE ${KWSYS_NAMESPACE}) + set(KWSYS_TARGET_OBJECT ${KWSYS_NAMESPACE}_objects) + set(KWSYS_TARGET_LINK ${KWSYS_NAMESPACE}_private) + set(KWSYS_TARGET_INSTALL ${KWSYS_TARGET_INTERFACE} ${KWSYS_TARGET_LINK}) + set(KWSYS_LINK_DEPENDENCY INTERFACE) + add_library(${KWSYS_TARGET_OBJECT} OBJECT ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS}) - IF(KWSYS_BUILD_SHARED OR KWSYS_BUILD_PIC) - SET_PROPERTY(TARGET ${KWSYS_TARGET_OBJECT} PROPERTY + if(KWSYS_BUILD_SHARED OR KWSYS_BUILD_PIC) + set_property(TARGET ${KWSYS_TARGET_OBJECT} PROPERTY POSITION_INDEPENDENT_CODE TRUE) - ENDIF() - ADD_LIBRARY(${KWSYS_TARGET_INTERFACE} INTERFACE) - ADD_LIBRARY(${KWSYS_TARGET_LINK} INTERFACE) - TARGET_LINK_LIBRARIES(${KWSYS_TARGET_LINK} INTERFACE + endif() + add_library(${KWSYS_TARGET_INTERFACE} INTERFACE) + add_library(${KWSYS_TARGET_LINK} INTERFACE) + target_link_libraries(${KWSYS_TARGET_LINK} INTERFACE ${KWSYS_TARGET_INTERFACE}) - TARGET_SOURCES(${KWSYS_TARGET_LINK} INTERFACE + target_sources(${KWSYS_TARGET_LINK} INTERFACE $<TARGET_OBJECTS:${KWSYS_TARGET_OBJECT}>) target_compile_features(${KWSYS_TARGET_OBJECT} PRIVATE ${KWSYS_CXX_COMPILE_FEATURES}) target_compile_features(${KWSYS_TARGET_INTERFACE} INTERFACE ${KWSYS_CXX_COMPILE_FEATURES}) - ELSE() - SET(KWSYS_TARGET_INTERFACE ${KWSYS_NAMESPACE}) - SET(KWSYS_TARGET_OBJECT ${KWSYS_NAMESPACE}) - SET(KWSYS_TARGET_LINK ${KWSYS_NAMESPACE}) + else() + set(KWSYS_TARGET_INTERFACE ${KWSYS_NAMESPACE}) + set(KWSYS_TARGET_OBJECT ${KWSYS_NAMESPACE}) + set(KWSYS_TARGET_LINK ${KWSYS_NAMESPACE}) set(KWSYS_TARGET_INSTALL ${KWSYS_TARGET_LINK}) - SET(KWSYS_LINK_DEPENDENCY PUBLIC) - ADD_LIBRARY(${KWSYS_TARGET_INTERFACE} ${KWSYS_LIBRARY_TYPE} + set(KWSYS_LINK_DEPENDENCY PUBLIC) + add_library(${KWSYS_TARGET_INTERFACE} ${KWSYS_LIBRARY_TYPE} ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS}) target_compile_features(${KWSYS_TARGET_INTERFACE} PUBLIC ${KWSYS_CXX_COMPILE_FEATURES}) - ENDIF() + endif() if (KWSYS_ALIAS_TARGET) add_library(${KWSYS_ALIAS_TARGET} ALIAS ${KWSYS_TARGET_INTERFACE}) endif () - SET_TARGET_PROPERTIES(${KWSYS_TARGET_OBJECT} PROPERTIES + set_target_properties(${KWSYS_TARGET_OBJECT} PROPERTIES C_CLANG_TIDY "" CXX_CLANG_TIDY "" C_INCLUDE_WHAT_YOU_USE "" CXX_INCLUDE_WHAT_YOU_USE "" LABELS "${KWSYS_LABELS_LIB}") - IF(KWSYS_USE_DynamicLoader) - IF(UNIX) - TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} + if(KWSYS_USE_DynamicLoader) + if(UNIX) + target_link_libraries(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} ${CMAKE_DL_LIBS}) - ENDIF() - ENDIF() + endif() + endif() - IF(KWSYS_USE_SystemInformation) - IF(WIN32) - TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} ws2_32) + if(KWSYS_USE_SystemInformation) + if(WIN32) + target_link_libraries(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} ws2_32) # link in dbghelp.dll for symbol lookup if MSVC 1800 or later # Note that the dbghelp runtime is part of MS Windows OS - IF(MSVC_VERSION AND NOT MSVC_VERSION VERSION_LESS 1800) - TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} dbghelp) - ENDIF() - IF(KWSYS_SYS_HAS_PSAPI) - TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} - Psapi) - ENDIF() - ELSEIF(UNIX) - IF (EXECINFO_LIB AND KWSYS_CXX_HAS_BACKTRACE) + if(MSVC_VERSION AND NOT MSVC_VERSION VERSION_LESS 1800) + target_link_libraries(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} dbghelp) + endif() + if(KWSYS_SYS_HAS_PSAPI) + target_link_libraries(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} + psapi) + endif() + elseif(UNIX) + if (EXECINFO_LIB AND KWSYS_CXX_HAS_BACKTRACE) # backtrace on FreeBSD is not in libc - TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} + target_link_libraries(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} ${EXECINFO_LIB}) - ENDIF() - IF (KWSYS_CXX_HAS_DLADDR) + endif() + if (KWSYS_CXX_HAS_DLADDR) # for symbol lookup using dladdr - TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} + target_link_libraries(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} ${CMAKE_DL_LIBS}) - ENDIF() - IF (CMAKE_SYSTEM_NAME STREQUAL "SunOS") - TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} + endif() + if (CMAKE_SYSTEM_NAME STREQUAL "SunOS") + target_link_libraries(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} socket) - ENDIF() - ENDIF() - ENDIF() + endif() + endif() + endif() # Apply user-defined target properties to the library. - IF(KWSYS_PROPERTIES_CXX) - SET_TARGET_PROPERTIES(${KWSYS_TARGET_INTERFACE} PROPERTIES + if(KWSYS_PROPERTIES_CXX) + set_target_properties(${KWSYS_TARGET_INTERFACE} PROPERTIES ${KWSYS_PROPERTIES_CXX}) - ENDIF() + endif() # Set up include usage requirement - IF(COMMAND TARGET_INCLUDE_DIRECTORIES) - TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_INTERFACE} INTERFACE + if(COMMAND TARGET_INCLUDE_DIRECTORIES) + target_include_directories(${KWSYS_TARGET_INTERFACE} INTERFACE $<BUILD_INTERFACE:${KWSYS_HEADER_ROOT}>) - IF(KWSYS_INSTALL_INCLUDE_DIR) - TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_INTERFACE} INTERFACE + if(KWSYS_INSTALL_INCLUDE_DIR) + target_include_directories(${KWSYS_TARGET_INTERFACE} INTERFACE $<INSTALL_INTERFACE:${KWSYS_INSTALL_INCLUDE_DIR}>) - ENDIF() - ENDIF() + endif() + endif() # Create an install target for the library. - IF(KWSYS_INSTALL_LIBRARY_RULE) - INSTALL(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_LIBRARY_RULE}) - ENDIF() - IF(KWSYS_INSTALL_NAMELINK_RULE) - INSTALL(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_NAMELINK_RULE}) - ENDIF() -ENDIF() + if(KWSYS_INSTALL_LIBRARY_RULE) + install(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_LIBRARY_RULE}) + endif() + if(KWSYS_INSTALL_NAMELINK_RULE) + install(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_NAMELINK_RULE}) + endif() +endif() # Add a C-only library if requested. -IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS) - IF(KWSYS_SPLIT_OBJECTS_FROM_INTERFACE) - SET(KWSYS_TARGET_C_INTERFACE ${KWSYS_NAMESPACE}_c) - SET(KWSYS_TARGET_C_OBJECT ${KWSYS_NAMESPACE}_c_objects) - SET(KWSYS_TARGET_C_LINK ${KWSYS_NAMESPACE}_c_private) - SET(KWSYS_TARGET_C_INSTALL +if(KWSYS_ENABLE_C AND KWSYS_C_SRCS) + if(KWSYS_SPLIT_OBJECTS_FROM_INTERFACE) + set(KWSYS_TARGET_C_INTERFACE ${KWSYS_NAMESPACE}_c) + set(KWSYS_TARGET_C_OBJECT ${KWSYS_NAMESPACE}_c_objects) + set(KWSYS_TARGET_C_LINK ${KWSYS_NAMESPACE}_c_private) + set(KWSYS_TARGET_C_INSTALL ${KWSYS_TARGET_C_INTERFACE} ${KWSYS_TARGET_C_LINK}) - SET(KWSYS_LINK_DEPENDENCY INTERFACE) - ADD_LIBRARY(${KWSYS_TARGET_C_OBJECT} OBJECT ${KWSYS_C_SRCS}) - IF(KWSYS_BUILD_SHARED OR KWSYS_BUILD_PIC) - SET_PROPERTY(TARGET ${KWSYS_TARGET_C_OBJECT} PROPERTY + set(KWSYS_LINK_DEPENDENCY INTERFACE) + add_library(${KWSYS_TARGET_C_OBJECT} OBJECT ${KWSYS_C_SRCS}) + if(KWSYS_BUILD_SHARED OR KWSYS_BUILD_PIC) + set_property(TARGET ${KWSYS_TARGET_C_OBJECT} PROPERTY POSITION_INDEPENDENT_CODE TRUE) - ENDIF() - ADD_LIBRARY(${KWSYS_TARGET_C_INTERFACE} INTERFACE) - ADD_LIBRARY(${KWSYS_TARGET_C_LINK} INTERFACE) - TARGET_LINK_LIBRARIES(${KWSYS_TARGET_C_LINK} INTERFACE + endif() + add_library(${KWSYS_TARGET_C_INTERFACE} INTERFACE) + add_library(${KWSYS_TARGET_C_LINK} INTERFACE) + target_link_libraries(${KWSYS_TARGET_C_LINK} INTERFACE ${KWSYS_TARGET_C_INTERFACE}) - TARGET_SOURCES(${KWSYS_TARGET_C_LINK} INTERFACE + target_sources(${KWSYS_TARGET_C_LINK} INTERFACE $<TARGET_OBJECTS:${KWSYS_TARGET_C_OBJECT}>) - ELSE() - SET(KWSYS_TARGET_C_INTERFACE ${KWSYS_NAMESPACE}_c) - SET(KWSYS_TARGET_C_OBJECT ${KWSYS_NAMESPACE}_c) - SET(KWSYS_TARGET_C_LINK ${KWSYS_NAMESPACE}_c) - SET(KWSYS_TARGET_C_INSTALL ${KWSYS_TARGET_C_LINK}) - SET(KWSYS_LINK_DEPENDENCY PUBLIC) - ADD_LIBRARY(${KWSYS_TARGET_C_INTERFACE} ${KWSYS_LIBRARY_TYPE} + else() + set(KWSYS_TARGET_C_INTERFACE ${KWSYS_NAMESPACE}_c) + set(KWSYS_TARGET_C_OBJECT ${KWSYS_NAMESPACE}_c) + set(KWSYS_TARGET_C_LINK ${KWSYS_NAMESPACE}_c) + set(KWSYS_TARGET_C_INSTALL ${KWSYS_TARGET_C_LINK}) + set(KWSYS_LINK_DEPENDENCY PUBLIC) + add_library(${KWSYS_TARGET_C_INTERFACE} ${KWSYS_LIBRARY_TYPE} ${KWSYS_C_SRCS}) - ENDIF() - SET_TARGET_PROPERTIES(${KWSYS_TARGET_C_OBJECT} PROPERTIES + endif() + set_target_properties(${KWSYS_TARGET_C_OBJECT} PROPERTIES LABELS "${KWSYS_LABELS_LIB}") # Apply user-defined target properties to the library. - IF(KWSYS_PROPERTIES_C) - SET_TARGET_PROPERTIES(${KWSYS_TARGET_C_INTERFACE} PROPERTIES + if(KWSYS_PROPERTIES_C) + set_target_properties(${KWSYS_TARGET_C_INTERFACE} PROPERTIES ${KWSYS_PROPERTIES_C}) - ENDIF() + endif() # Set up include usage requirement - IF(COMMAND TARGET_INCLUDE_DIRECTORIES) - TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_C_INTERFACE} INTERFACE + if(COMMAND TARGET_INCLUDE_DIRECTORIES) + target_include_directories(${KWSYS_TARGET_C_INTERFACE} INTERFACE $<BUILD_INTERFACE:${KWSYS_HEADER_ROOT}>) - IF(KWSYS_INSTALL_INCLUDE_DIR) - TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_C_INTERFACE} INTERFACE + if(KWSYS_INSTALL_INCLUDE_DIR) + target_include_directories(${KWSYS_TARGET_C_INTERFACE} INTERFACE $<INSTALL_INTERFACE:${KWSYS_INSTALL_INCLUDE_DIR}>) - ENDIF() - ENDIF() + endif() + endif() # Create an install target for the library. - IF(KWSYS_INSTALL_LIBRARY_RULE) - INSTALL(TARGETS ${KWSYS_TARGET_C_INSTALL}) - ENDIF() -ENDIF() + if(KWSYS_INSTALL_LIBRARY_RULE) + install(TARGETS ${KWSYS_TARGET_C_INSTALL}) + endif() +endif() # For building kwsys itself, we use a macro defined on the command # line to configure the namespace in the C and C++ source files. -ADD_DEFINITIONS("-DKWSYS_NAMESPACE=${KWSYS_NAMESPACE}") +add_definitions("-DKWSYS_NAMESPACE=${KWSYS_NAMESPACE}") # Disable deprecation warnings for standard C functions. -IF(MSVC OR (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "Intel" OR +if(MSVC OR (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "Intel" OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")))) - ADD_DEFINITIONS( + add_definitions( -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_DEPRECATE ) -ENDIF() +endif() -IF(WIN32) +if(WIN32) # Help enforce the use of wide Windows apis. - ADD_DEFINITIONS(-DUNICODE -D_UNICODE) -ENDIF() + add_definitions(-DUNICODE -D_UNICODE) +endif() -IF(KWSYS_USE_String) +if(KWSYS_USE_String) # Activate code in "String.c". See the comment in the source. - SET_SOURCE_FILES_PROPERTIES(String.c PROPERTIES + set_source_files_properties(String.c PROPERTIES COMPILE_FLAGS "-DKWSYS_STRING_C") -ENDIF() +endif() -IF(KWSYS_USE_Encoding) +if(KWSYS_USE_Encoding) # Set default 8 bit encoding in "EndcodingC.c". - SET_PROPERTY(SOURCE EncodingC.c EncodingCXX.cxx APPEND PROPERTY COMPILE_DEFINITIONS + set_property(SOURCE EncodingC.c EncodingCXX.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE}) -ENDIF() +endif() #----------------------------------------------------------------------------- # Setup testing if not being built as part of another project. -IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) - IF(BUILD_TESTING) +if(KWSYS_STANDALONE OR CMake_SOURCE_DIR) + if(BUILD_TESTING) # Compute the location of executables. - SET(EXEC_DIR "${CMAKE_CURRENT_BINARY_DIR}") - IF(EXECUTABLE_OUTPUT_PATH) - SET(EXEC_DIR "${EXECUTABLE_OUTPUT_PATH}") - ENDIF() + set(EXEC_DIR "${CMAKE_CURRENT_BINARY_DIR}") + if(CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(EXEC_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") + endif() # C tests - SET(KWSYS_C_TESTS + set(KWSYS_C_TESTS testEncode.c testTerminal.c ) - IF(KWSYS_STANDALONE) - SET(KWSYS_C_TESTS ${KWSYS_C_TESTS} testFail.c) - ENDIF() - CREATE_TEST_SOURCELIST( + if(KWSYS_STANDALONE) + set(KWSYS_C_TESTS ${KWSYS_C_TESTS} testFail.c) + endif() + create_test_sourcelist( KWSYS_C_TEST_SRCS ${KWSYS_NAMESPACE}TestsC.c ${KWSYS_C_TESTS} ) - ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestsC ${KWSYS_C_TEST_SRCS}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsC PROPERTY LABELS ${KWSYS_LABELS_EXE}) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsC ${KWSYS_TARGET_C_LINK}) - FOREACH(testfile ${KWSYS_C_TESTS}) + add_executable(${KWSYS_NAMESPACE}TestsC ${KWSYS_C_TEST_SRCS}) + set_property(TARGET ${KWSYS_NAMESPACE}TestsC PROPERTY LABELS ${KWSYS_LABELS_EXE}) + target_link_libraries(${KWSYS_NAMESPACE}TestsC ${KWSYS_TARGET_C_LINK}) + foreach(testfile ${KWSYS_C_TESTS}) get_filename_component(test "${testfile}" NAME_WE) - ADD_TEST(kwsys.${test} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestsC ${test} ${KWSYS_TEST_ARGS_${test}}) - SET_PROPERTY(TEST kwsys.${test} PROPERTY LABELS ${KWSYS_LABELS_TEST}) - ENDFOREACH() + add_test(kwsys.${test} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestsC ${test} ${KWSYS_TEST_ARGS_${test}}) + set_property(TEST kwsys.${test} PROPERTY LABELS ${KWSYS_LABELS_TEST}) + endforeach() # C++ tests - IF(NOT WATCOM AND NOT CMake_SOURCE_DIR) - SET(KWSYS_CXX_TESTS + if(NOT WATCOM AND NOT CMake_SOURCE_DIR) + set(KWSYS_CXX_TESTS testHashSTL.cxx ) - ENDIF() - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} + endif() + set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testConfigure.cxx testSystemTools.cxx testCommandLineArguments.cxx testCommandLineArguments1.cxx testDirectory.cxx ) - IF(KWSYS_STL_HAS_WSTRING) - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} + if(KWSYS_STL_HAS_WSTRING) + set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testEncoding.cxx ) - ENDIF() - IF(KWSYS_USE_FStream) - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} + endif() + if(KWSYS_USE_FStream) + set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testFStream.cxx ) - ENDIF() - IF(KWSYS_USE_ConsoleBuf) - ADD_EXECUTABLE(testConsoleBufChild testConsoleBufChild.cxx) - SET_PROPERTY(TARGET testConsoleBufChild PROPERTY C_CLANG_TIDY "") - SET_PROPERTY(TARGET testConsoleBufChild PROPERTY CXX_CLANG_TIDY "") - SET_PROPERTY(TARGET testConsoleBufChild PROPERTY C_INCLUDE_WHAT_YOU_USE "") - SET_PROPERTY(TARGET testConsoleBufChild PROPERTY CXX_INCLUDE_WHAT_YOU_USE "") - SET_PROPERTY(TARGET testConsoleBufChild PROPERTY LABELS ${KWSYS_LABELS_EXE}) - TARGET_LINK_LIBRARIES(testConsoleBufChild ${KWSYS_TARGET_LINK}) - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} + endif() + if(KWSYS_USE_ConsoleBuf) + add_executable(testConsoleBufChild testConsoleBufChild.cxx) + set_property(TARGET testConsoleBufChild PROPERTY C_CLANG_TIDY "") + set_property(TARGET testConsoleBufChild PROPERTY CXX_CLANG_TIDY "") + set_property(TARGET testConsoleBufChild PROPERTY C_INCLUDE_WHAT_YOU_USE "") + set_property(TARGET testConsoleBufChild PROPERTY CXX_INCLUDE_WHAT_YOU_USE "") + set_property(TARGET testConsoleBufChild PROPERTY LABELS ${KWSYS_LABELS_EXE}) + target_link_libraries(testConsoleBufChild ${KWSYS_TARGET_LINK}) + set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testConsoleBuf.cxx ) - IF(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "19.0.23506") set_property(SOURCE testConsoleBuf.cxx testConsoleBufChild.cxx PROPERTY COMPILE_FLAGS /utf-8) - ENDIF() - SET_PROPERTY(SOURCE testConsoleBuf.cxx APPEND PROPERTY COMPILE_DEFINITIONS + endif() + set_property(SOURCE testConsoleBuf.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE}) - ENDIF() - IF(KWSYS_USE_SystemInformation) - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testSystemInformation.cxx) - ENDIF() - IF(KWSYS_USE_DynamicLoader) - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testDynamicLoader.cxx) + endif() + if(KWSYS_USE_SystemInformation) + set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testSystemInformation.cxx) + endif() + if(KWSYS_USE_DynamicLoader) + set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testDynamicLoader.cxx) # If kwsys contains the DynamicLoader, need extra library - ADD_LIBRARY(${KWSYS_NAMESPACE}TestDynload MODULE testDynload.c) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestDynload PROPERTY LABELS ${KWSYS_LABELS_LIB}) - ADD_DEPENDENCIES(${KWSYS_NAMESPACE}TestDynload ${KWSYS_TARGET_INTERFACE}) + add_library(${KWSYS_NAMESPACE}TestDynload MODULE testDynload.c) + set_property(TARGET ${KWSYS_NAMESPACE}TestDynload PROPERTY LABELS ${KWSYS_LABELS_LIB}) + add_dependencies(${KWSYS_NAMESPACE}TestDynload ${KWSYS_TARGET_INTERFACE}) if (WIN32) # Windows tests supported flags. @@ -1134,33 +1134,33 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) add_dependencies(${KWSYS_NAMESPACE}TestDynloadUse ${KWSYS_TARGET_INTERFACE}) target_link_libraries(${KWSYS_NAMESPACE}TestDynloadUse PRIVATE ${KWSYS_NAMESPACE}TestDynloadImpl) endif () - ENDIF() - CREATE_TEST_SOURCELIST( + endif() + create_test_sourcelist( KWSYS_CXX_TEST_SRCS ${KWSYS_NAMESPACE}TestsCxx.cxx ${KWSYS_CXX_TESTS} ) - ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_CXX_TEST_SRCS}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY C_CLANG_TIDY "") - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY CXX_CLANG_TIDY "") - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY C_INCLUDE_WHAT_YOU_USE "") - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY CXX_INCLUDE_WHAT_YOU_USE "") - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY LABELS ${KWSYS_LABELS_EXE}) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_TARGET_LINK}) - - SET(TEST_SYSTEMTOOLS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") - SET(TEST_SYSTEMTOOLS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") - CONFIGURE_FILE( + add_executable(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_CXX_TEST_SRCS}) + set_property(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY C_CLANG_TIDY "") + set_property(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY CXX_CLANG_TIDY "") + set_property(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY C_INCLUDE_WHAT_YOU_USE "") + set_property(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY CXX_INCLUDE_WHAT_YOU_USE "") + set_property(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY LABELS ${KWSYS_LABELS_EXE}) + target_link_libraries(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_TARGET_LINK}) + + set(TEST_SYSTEMTOOLS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + set(TEST_SYSTEMTOOLS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") + configure_file( ${PROJECT_SOURCE_DIR}/testSystemTools.h.in ${PROJECT_BINARY_DIR}/testSystemTools.h) - INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR}) + include_directories(${PROJECT_BINARY_DIR}) - IF(CTEST_TEST_KWSYS) - CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/ExtraTest.cmake.in" + if(CTEST_TEST_KWSYS) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ExtraTest.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/ExtraTest.cmake") - SET_DIRECTORY_PROPERTIES(PROPERTIES TEST_INCLUDE_FILE "${CMAKE_CURRENT_BINARY_DIR}/ExtraTest.cmake") - ENDIF() + set_directory_properties(PROPERTIES TEST_INCLUDE_FILE "${CMAKE_CURRENT_BINARY_DIR}/ExtraTest.cmake") + endif() - SET(KWSYS_TEST_ARGS_testCommandLineArguments + set(KWSYS_TEST_ARGS_testCommandLineArguments --another-bool-variable --long3=opt --set-bool-arg1 @@ -1179,7 +1179,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) -C=test --long2 hello ) - SET(KWSYS_TEST_ARGS_testCommandLineArguments1 + set(KWSYS_TEST_ARGS_testCommandLineArguments1 --ignored -n 24 --second-ignored @@ -1188,73 +1188,73 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) -p some junk at the end ) - FOREACH(testfile ${KWSYS_CXX_TESTS}) + foreach(testfile ${KWSYS_CXX_TESTS}) get_filename_component(test "${testfile}" NAME_WE) - ADD_TEST(kwsys.${test} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestsCxx ${test} ${KWSYS_TEST_ARGS_${test}}) - SET_PROPERTY(TEST kwsys.${test} PROPERTY LABELS ${KWSYS_LABELS_TEST}) - ENDFOREACH() + add_test(kwsys.${test} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestsCxx ${test} ${KWSYS_TEST_ARGS_${test}}) + set_property(TEST kwsys.${test} PROPERTY LABELS ${KWSYS_LABELS_TEST}) + endforeach() # Process tests. - ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestProcess testProcess.c) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestProcess PROPERTY LABELS ${KWSYS_LABELS_EXE}) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestProcess ${KWSYS_TARGET_C_LINK}) - IF(NOT CYGWIN) - SET(KWSYS_TEST_PROCESS_7 7) - ENDIF() - FOREACH(n 1 2 3 4 5 6 ${KWSYS_TEST_PROCESS_7} 9 10) - ADD_TEST(kwsys.testProcess-${n} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestProcess ${n}) - SET_PROPERTY(TEST kwsys.testProcess-${n} PROPERTY LABELS ${KWSYS_LABELS_TEST}) - SET_TESTS_PROPERTIES(kwsys.testProcess-${n} PROPERTIES TIMEOUT 120) - ENDFOREACH() - - SET(testProcess_COMPILE_FLAGS "") + add_executable(${KWSYS_NAMESPACE}TestProcess testProcess.c) + set_property(TARGET ${KWSYS_NAMESPACE}TestProcess PROPERTY LABELS ${KWSYS_LABELS_EXE}) + target_link_libraries(${KWSYS_NAMESPACE}TestProcess ${KWSYS_TARGET_C_LINK}) + if(NOT CYGWIN) + set(KWSYS_TEST_PROCESS_7 7) + endif() + foreach(n 1 2 3 4 5 6 ${KWSYS_TEST_PROCESS_7} 9 10) + add_test(kwsys.testProcess-${n} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestProcess ${n}) + set_property(TEST kwsys.testProcess-${n} PROPERTY LABELS ${KWSYS_LABELS_TEST}) + set_tests_properties(kwsys.testProcess-${n} PROPERTIES TIMEOUT 120) + endforeach() + + set(testProcess_COMPILE_FLAGS "") # Some Apple compilers produce bad optimizations in this source. - IF(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$") - SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -O0") - ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL") + if(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$") + set(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -O0") + elseif(CMAKE_C_COMPILER_ID STREQUAL "XL") # Tell IBM XL not to warn about our test infinite loop - IF(CMAKE_SYSTEM MATCHES "Linux.*ppc64le" + if(CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "16.1.0" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1") # v13.1.[1-6] on Linux ppc64le is clang based and does not accept # the -qsuppress option, so just suppress all warnings. - SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -w") - ELSE() - SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010") - ENDIF() - ENDIF() - IF(CMAKE_C_FLAGS MATCHES "-fsanitize=") - SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -DCRASH_USING_ABORT") - ENDIF() - SET_PROPERTY(SOURCE testProcess.c PROPERTY COMPILE_FLAGS "${testProcess_COMPILE_FLAGS}") + set(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -w") + else() + set(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010") + endif() + endif() + if(CMAKE_C_FLAGS MATCHES "-fsanitize=") + set(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -DCRASH_USING_ABORT") + endif() + set_property(SOURCE testProcess.c PROPERTY COMPILE_FLAGS "${testProcess_COMPILE_FLAGS}") # Test SharedForward - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/testSharedForward.c.in + configure_file(${PROJECT_SOURCE_DIR}/testSharedForward.c.in ${PROJECT_BINARY_DIR}/testSharedForward.c @ONLY IMMEDIATE) - ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestSharedForward + add_executable(${KWSYS_NAMESPACE}TestSharedForward ${PROJECT_BINARY_DIR}/testSharedForward.c) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestSharedForward PROPERTY LABELS ${KWSYS_LABELS_EXE}) - ADD_DEPENDENCIES(${KWSYS_NAMESPACE}TestSharedForward ${KWSYS_TARGET_C_LINK}) - ADD_TEST(kwsys.testSharedForward ${EXEC_DIR}/${KWSYS_NAMESPACE}TestSharedForward 1) - SET_PROPERTY(TEST kwsys.testSharedForward PROPERTY LABELS ${KWSYS_LABELS_TEST}) + set_property(TARGET ${KWSYS_NAMESPACE}TestSharedForward PROPERTY LABELS ${KWSYS_LABELS_EXE}) + add_dependencies(${KWSYS_NAMESPACE}TestSharedForward ${KWSYS_TARGET_C_LINK}) + add_test(kwsys.testSharedForward ${EXEC_DIR}/${KWSYS_NAMESPACE}TestSharedForward 1) + set_property(TEST kwsys.testSharedForward PROPERTY LABELS ${KWSYS_LABELS_TEST}) # Configure some test properties. - IF(KWSYS_STANDALONE) + if(KWSYS_STANDALONE) # We expect test to fail - SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES WILL_FAIL ON) - GET_TEST_PROPERTY(kwsys.testFail WILL_FAIL wfv) - SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES MEASUREMENT "Some Key=Some Value") - MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}") - ENDIF() + set_tests_properties(kwsys.testFail PROPERTIES WILL_FAIL ON) + get_test_property(kwsys.testFail WILL_FAIL wfv) + set_tests_properties(kwsys.testFail PROPERTIES MEASUREMENT "Some Key=Some Value") + message(STATUS "GET_TEST_PROPERTY returned: ${wfv}") + endif() # Set up ctest custom configuration file. - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/CTestCustom.cmake.in + configure_file(${PROJECT_SOURCE_DIR}/CTestCustom.cmake.in ${PROJECT_BINARY_DIR}/CTestCustom.cmake @ONLY) # Suppress known consistent failures on buggy systems. - IF(KWSYS_TEST_BOGUS_FAILURES) - SET_TESTS_PROPERTIES(${KWSYS_TEST_BOGUS_FAILURES} PROPERTIES WILL_FAIL ON) - ENDIF() + if(KWSYS_TEST_BOGUS_FAILURES) + set_tests_properties(${KWSYS_TEST_BOGUS_FAILURES} PROPERTIES WILL_FAIL ON) + endif() - ENDIF() -ENDIF() + endif() +endif() diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx index 3fd1955..a2ed874 100644 --- a/Source/kwsys/CommandLineArguments.cxx +++ b/Source/kwsys/CommandLineArguments.cxx @@ -66,26 +66,21 @@ class CommandLineArgumentsMapOfStrucs class CommandLineArgumentsInternal { public: - CommandLineArgumentsInternal() - : UnknownArgumentCallback{ nullptr } - , ClientData{ nullptr } - , LastArgument{ 0 } - { - } + CommandLineArgumentsInternal() = default; - typedef CommandLineArgumentsVectorOfStrings VectorOfStrings; - typedef CommandLineArgumentsMapOfStrucs CallbacksMap; - typedef kwsys::String String; - typedef CommandLineArgumentsSetOfStrings SetOfStrings; + using VectorOfStrings = CommandLineArgumentsVectorOfStrings; + using CallbacksMap = CommandLineArgumentsMapOfStrucs; + using String = kwsys::String; + using SetOfStrings = CommandLineArgumentsSetOfStrings; VectorOfStrings Argv; String Argv0; CallbacksMap Callbacks; - CommandLineArguments::ErrorCallbackType UnknownArgumentCallback; - void* ClientData; + CommandLineArguments::ErrorCallbackType UnknownArgumentCallback{ nullptr }; + void* ClientData{ nullptr }; - VectorOfStrings::size_type LastArgument; + VectorOfStrings::size_type LastArgument{ 0 }; VectorOfStrings UnusedArguments; }; @@ -424,8 +419,7 @@ void CommandLineArguments::SetUnknownArgumentCallback( const char* CommandLineArguments::GetHelp(const char* arg) { - CommandLineArguments::Internal::CallbacksMap::iterator it = - this->Internals->Callbacks.find(arg); + auto it = this->Internals->Callbacks.find(arg); if (it == this->Internals->Callbacks.end()) { return nullptr; } @@ -434,8 +428,7 @@ const char* CommandLineArguments::GetHelp(const char* arg) // one point to if this one is pointing to another argument. CommandLineArgumentsCallbackStructure* cs = &(it->second); for (;;) { - CommandLineArguments::Internal::CallbacksMap::iterator hit = - this->Internals->Callbacks.find(cs->Help); + auto hit = this->Internals->Callbacks.find(cs->Help); if (hit == this->Internals->Callbacks.end()) { break; } @@ -470,9 +463,8 @@ void CommandLineArguments::GenerateHelp() // Collapse all arguments into the map of vectors of all arguments that do // the same thing. CommandLineArguments::Internal::CallbacksMap::iterator it; - typedef std::map<CommandLineArguments::Internal::String, - CommandLineArguments::Internal::SetOfStrings> - MapArgs; + using MapArgs = std::map<CommandLineArguments::Internal::String, + CommandLineArguments::Internal::SetOfStrings>; MapArgs mp; MapArgs::iterator mpit, smpit; for (it = this->Internals->Callbacks.begin(); @@ -709,7 +701,7 @@ bool CommandLineArguments::PopulateVariable( if (cs->Callback) { if (!cs->Callback(cs->Argument, value, cs->CallData)) { this->Internals->LastArgument--; - return 0; + return false; } } CommandLineArguments_DEBUG("Set argument: " << cs->Argument << " to " @@ -759,10 +751,10 @@ bool CommandLineArguments::PopulateVariable( std::cerr << "Got unknown variable type: \"" << cs->VariableType << "\"" << std::endl; this->Internals->LastArgument--; - return 0; + return false; } } - return 1; + return true; } } // namespace KWSYS_NAMESPACE diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx index e379182..d640948 100644 --- a/Source/kwsys/Directory.cxx +++ b/Source/kwsys/Directory.cxx @@ -35,6 +35,18 @@ Directory::Directory() this->Internal = new DirectoryInternals; } +Directory::Directory(Directory&& other) +{ + this->Internal = other.Internal; + other.Internal = nullptr; +} + +Directory& Directory::operator=(Directory&& other) +{ + std::swap(this->Internal, other.Internal); + return *this; +} + Directory::~Directory() { delete this->Internal; @@ -204,15 +216,15 @@ bool Directory::Load(const std::string& name) DIR* dir = opendir(name.c_str()); if (!dir) { - return 0; + return false; } for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) { - this->Internal->Files.push_back(d->d_name); + this->Internal->Files.emplace_back(d->d_name); } this->Internal->Path = name; closedir(dir); - return 1; + return true; } unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name) diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in index ad8c51b..9b0f4c3 100644 --- a/Source/kwsys/Directory.hxx.in +++ b/Source/kwsys/Directory.hxx.in @@ -23,6 +23,11 @@ class @KWSYS_NAMESPACE@_EXPORT Directory { public: Directory(); + Directory(Directory&& other); + Directory(const Directory&) = delete; + Directory& operator=(const Directory&) = delete; + Directory& operator=(Directory&& other); + bool operator==(const Directory&) = delete; ~Directory(); /** @@ -62,10 +67,7 @@ public: private: // Private implementation details. DirectoryInternals* Internal; - - Directory(const Directory&); // Not implemented. - void operator=(const Directory&); // Not implemented. -}; // End Class: Directory +}; // End Class: Directory } // namespace @KWSYS_NAMESPACE@ diff --git a/Source/kwsys/ExtraTest.cmake.in b/Source/kwsys/ExtraTest.cmake.in index e8c0a1c..4cec9e2 100644 --- a/Source/kwsys/ExtraTest.cmake.in +++ b/Source/kwsys/ExtraTest.cmake.in @@ -1 +1 @@ -MESSAGE("*** This message is generated by message inside a file that is included in DartTestfile.txt ***") +message("*** This message is generated by message inside a file that is included in DartTestfile.txt ***") diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx index 34bb0d0..8e30f92 100644 --- a/Source/kwsys/Glob.cxx +++ b/Source/kwsys/Glob.cxx @@ -385,10 +385,9 @@ bool Glob::FindFiles(const std::string& inexpr, GlobMessages* messages) } if (skip > 0) { - expr = expr.substr(skip); + expr.erase(0, skip); } - cexpr = ""; for (cc = 0; cc < expr.size(); cc++) { int ch = expr[cc]; if (ch == '/') { @@ -415,8 +414,7 @@ bool Glob::FindFiles(const std::string& inexpr, GlobMessages* messages) void Glob::AddExpression(const std::string& expr) { - this->Internals->Expressions.push_back( - kwsys::RegularExpression(this->PatternToRegex(expr))); + this->Internals->Expressions.emplace_back(this->PatternToRegex(expr)); } void Glob::SetRelative(const char* dir) diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in index 73ea9db..9f2162b 100644 --- a/Source/kwsys/Process.h.in +++ b/Source/kwsys/Process.h.in @@ -180,8 +180,8 @@ kwsysEXPORT void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, * write end of the pipe will be closed in the parent process and the * read end will be closed in the child process. */ -kwsysEXPORT void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, - kwsysProcess_Pipe_Handle p[2]); +kwsysEXPORT void kwsysProcess_SetPipeNative( + kwsysProcess* cp, int pipe, const kwsysProcess_Pipe_Handle p[2]); /** * Get/Set a possibly platform-specific option. Possible options are: diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index f65690b..5fde0b0 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -152,10 +152,11 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, static void kwsysProcessDestroy(kwsysProcess* cp); static int kwsysProcessSetupOutputPipeFile(int* p, const char* name); static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]); -static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, +static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, + const double* userTimeout, kwsysProcessTime* timeoutTime); static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, - double* userTimeout, + const double* userTimeout, kwsysProcessTimeNative* timeoutLength, int zeroIsExpired); static kwsysProcessTime kwsysProcessTimeGetCurrent(void); @@ -571,7 +572,7 @@ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared) } } -void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, int p[2]) +void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, const int p[2]) { int* pPipeNative = 0; @@ -1959,7 +1960,8 @@ static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]) /* Get the time at which either the process or user timeout will expire. Returns 1 if the user timeout is first, and 0 otherwise. */ -static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, +static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, + const double* userTimeout, kwsysProcessTime* timeoutTime) { /* The first time this is called, we need to calculate the time at @@ -1991,7 +1993,7 @@ static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, /* Get the length of time before the given timeout time arrives. Returns 1 if the time has already arrived, and 0 otherwise. */ static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, - double* userTimeout, + const double* userTimeout, kwsysProcessTimeNative* timeoutLength, int zeroIsExpired) { diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index 68c5218..56bbd20 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -761,7 +761,7 @@ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared) } } -void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, HANDLE p[2]) +void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, const HANDLE p[2]) { HANDLE* pPipeNative = 0; diff --git a/Source/kwsys/System.c b/Source/kwsys/System.c index d43cc6f..dbfd2fd 100644 --- a/Source/kwsys/System.c +++ b/Source/kwsys/System.c @@ -22,7 +22,7 @@ typedef ptrdiff_t kwsysSystem_ptrdiff_t; typedef int kwsysSystem_ptrdiff_t; #endif -static int kwsysSystem__AppendByte(char* local, char** begin, char** end, +static int kwsysSystem__AppendByte(const char* local, char** begin, char** end, int* size, char c) { /* Allocate space for the character. */ diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 6ec6e48..95b06e1 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -132,7 +132,7 @@ typedef int siginfo_t; # endif # endif # if defined(KWSYS_CXX_HAS_RLIMIT64) -typedef struct rlimit64 ResourceLimitType; +using ResourceLimitType = struct rlimit64; # define GetResourceLimit getrlimit64 # else typedef struct rlimit ResourceLimitType; @@ -303,34 +303,34 @@ T min(T a, T b) } extern "C" { -typedef void (*SigAction)(int, siginfo_t*, void*); +using SigAction = void (*)(int, siginfo_t*, void*); } // Define SystemInformationImplementation class -typedef void (*DELAY_FUNC)(unsigned int uiMS); +using DELAY_FUNC = void (*)(unsigned int); class SystemInformationImplementation { public: - typedef SystemInformation::LongLong LongLong; + using LongLong = SystemInformation::LongLong; SystemInformationImplementation(); - ~SystemInformationImplementation(); + ~SystemInformationImplementation() = default; - const char* GetVendorString(); + const char* GetVendorString() const; const char* GetVendorID(); - std::string GetTypeID(); - std::string GetFamilyID(); - std::string GetModelID(); - std::string GetModelName(); - std::string GetSteppingCode(); - const char* GetExtendedProcessorName(); - const char* GetProcessorSerialNumber(); - int GetProcessorCacheSize(); - unsigned int GetLogicalProcessorsPerPhysical(); - float GetProcessorClockFrequency(); - int GetProcessorAPICID(); - int GetProcessorCacheXSize(long int); - bool DoesCPUSupportFeature(long int); + std::string GetTypeID() const; + std::string GetFamilyID() const; + std::string GetModelID() const; + std::string GetModelName() const; + std::string GetSteppingCode() const; + const char* GetExtendedProcessorName() const; + const char* GetProcessorSerialNumber() const; + int GetProcessorCacheSize() const; + unsigned int GetLogicalProcessorsPerPhysical() const; + float GetProcessorClockFrequency() const; + int GetProcessorAPICID() const; + int GetProcessorCacheXSize(long int) const; + bool DoesCPUSupportFeature(long int) const; const char* GetOSName(); const char* GetHostname(); @@ -339,24 +339,24 @@ public: const char* GetOSVersion(); const char* GetOSPlatform(); - bool Is64Bits(); + bool Is64Bits() const; - unsigned int GetNumberOfLogicalCPU(); // per physical cpu - unsigned int GetNumberOfPhysicalCPU(); + unsigned int GetNumberOfLogicalCPU() const; // per physical cpu + unsigned int GetNumberOfPhysicalCPU() const; bool DoesCPUSupportCPUID(); // Retrieve memory information in MiB. - size_t GetTotalVirtualMemory(); - size_t GetAvailableVirtualMemory(); - size_t GetTotalPhysicalMemory(); - size_t GetAvailablePhysicalMemory(); + size_t GetTotalVirtualMemory() const; + size_t GetAvailableVirtualMemory() const; + size_t GetTotalPhysicalMemory() const; + size_t GetAvailablePhysicalMemory() const; LongLong GetProcessId(); // Retrieve memory information in KiB. LongLong GetHostMemoryTotal(); - LongLong GetHostMemoryAvailable(const char* envVarName); + LongLong GetHostMemoryAvailable(const char* hostLimitEnvVarName); LongLong GetHostMemoryUsed(); LongLong GetProcMemoryAvailable(const char* hostLimitEnvVarName, @@ -377,60 +377,103 @@ public: void RunMemoryCheck(); public: - typedef struct tagID + using ID = struct tagID + { + int Type; + int Family; + int Model; + int Revision; + int ExtendedFamily; + int ExtendedModel; + std::string ProcessorName; + std::string Vendor; + std::string SerialNumber; + std::string ModelName; - } ID; + }; + + using CPUPowerManagement = struct tagCPUPowerManagement - typedef struct tagCPUPowerManagement { + bool HasVoltageID; + bool HasFrequencyID; + bool HasTempSenseDiode; - } CPUPowerManagement; + }; + + using CPUExtendedFeatures = struct tagCPUExtendedFeatures - typedef struct tagCPUExtendedFeatures { + bool Has3DNow; + bool Has3DNowPlus; + bool SupportsMP; + bool HasMMXPlus; + bool HasSSEMMX; + unsigned int LogicalProcessorsPerPhysical; + int APIC_ID; + CPUPowerManagement PowerManagement; - } CPUExtendedFeatures; + }; + + using CPUFeatures = struct CPUtagFeatures - typedef struct CPUtagFeatures { + bool HasFPU; + bool HasTSC; + bool HasMMX; + bool HasSSE; + bool HasSSEFP; + bool HasSSE2; + bool HasIA64; + bool HasAPIC; + bool HasCMOV; + bool HasMTRR; + bool HasACPI; + bool HasSerial; + bool HasThermal; + int CPUSpeed; + int L1CacheSize; + int L2CacheSize; + int L3CacheSize; + CPUExtendedFeatures ExtendedFeatures; - } CPUFeatures; + }; enum Manufacturer { @@ -476,7 +519,7 @@ protected: void CPUCountWindows(); // For windows unsigned char GetAPICId(); // For windows - bool IsSMTSupported(); + bool IsSMTSupported() const; static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows // For Linux and Cygwin, /proc/cpuinfo formats are slightly different @@ -885,7 +928,7 @@ int LoadLines(FILE* file, std::vector<std::string>& lines) *pBuf = '\0'; pBuf += 1; } - lines.push_back(buf); + lines.emplace_back(buf); ++nRead; } if (ferror(file)) { @@ -899,7 +942,7 @@ int LoadLines(FILE* file, std::vector<std::string>& lines) int LoadLines(const char* fileName, std::vector<std::string>& lines) { FILE* file = fopen(fileName, "r"); - if (file == 0) { + if (file == nullptr) { return 0; } int nRead = LoadLines(file, lines); @@ -1324,7 +1367,7 @@ std::string SymbolProperties::GetFileName(const std::string& path) const if (!this->ReportPath) { size_t at = file.rfind("/"); if (at != std::string::npos) { - file = file.substr(at + 1); + file.erase(0, at + 1); } } return file; @@ -1464,10 +1507,6 @@ SystemInformationImplementation::SystemInformationImplementation() this->OSIs64Bit = (sizeof(void*) == 8); } -SystemInformationImplementation::~SystemInformationImplementation() -{ -} - void SystemInformationImplementation::RunCPUCheck() { #ifdef _WIN32 @@ -1564,7 +1603,7 @@ void SystemInformationImplementation::RunMemoryCheck() } /** Get the vendor string */ -const char* SystemInformationImplementation::GetVendorString() +const char* SystemInformationImplementation::GetVendorString() const { return this->ChipID.Vendor.c_str(); } @@ -1760,7 +1799,7 @@ const char* SystemInformationImplementation::GetVendorID() } /** Return the type ID of the CPU */ -std::string SystemInformationImplementation::GetTypeID() +std::string SystemInformationImplementation::GetTypeID() const { std::ostringstream str; str << this->ChipID.Type; @@ -1768,7 +1807,7 @@ std::string SystemInformationImplementation::GetTypeID() } /** Return the family of the CPU present */ -std::string SystemInformationImplementation::GetFamilyID() +std::string SystemInformationImplementation::GetFamilyID() const { std::ostringstream str; str << this->ChipID.Family; @@ -1776,7 +1815,7 @@ std::string SystemInformationImplementation::GetFamilyID() } // Return the model of CPU present */ -std::string SystemInformationImplementation::GetModelID() +std::string SystemInformationImplementation::GetModelID() const { std::ostringstream str; str << this->ChipID.Model; @@ -1784,13 +1823,13 @@ std::string SystemInformationImplementation::GetModelID() } // Return the model name of CPU present */ -std::string SystemInformationImplementation::GetModelName() +std::string SystemInformationImplementation::GetModelName() const { return this->ChipID.ModelName; } /** Return the stepping code of the CPU present. */ -std::string SystemInformationImplementation::GetSteppingCode() +std::string SystemInformationImplementation::GetSteppingCode() const { std::ostringstream str; str << this->ChipID.Revision; @@ -1798,44 +1837,46 @@ std::string SystemInformationImplementation::GetSteppingCode() } /** Return the stepping code of the CPU present. */ -const char* SystemInformationImplementation::GetExtendedProcessorName() +const char* SystemInformationImplementation::GetExtendedProcessorName() const { return this->ChipID.ProcessorName.c_str(); } /** Return the serial number of the processor * in hexadecimal: xxxx-xxxx-xxxx-xxxx-xxxx-xxxx. */ -const char* SystemInformationImplementation::GetProcessorSerialNumber() +const char* SystemInformationImplementation::GetProcessorSerialNumber() const { return this->ChipID.SerialNumber.c_str(); } /** Return the logical processors per physical */ unsigned int SystemInformationImplementation::GetLogicalProcessorsPerPhysical() + const { return this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical; } /** Return the processor clock frequency. */ -float SystemInformationImplementation::GetProcessorClockFrequency() +float SystemInformationImplementation::GetProcessorClockFrequency() const { return this->CPUSpeedInMHz; } /** Return the APIC ID. */ -int SystemInformationImplementation::GetProcessorAPICID() +int SystemInformationImplementation::GetProcessorAPICID() const { return this->Features.ExtendedFeatures.APIC_ID; } /** Return the L1 cache size. */ -int SystemInformationImplementation::GetProcessorCacheSize() +int SystemInformationImplementation::GetProcessorCacheSize() const { return this->Features.L1CacheSize; } /** Return the chosen cache size. */ -int SystemInformationImplementation::GetProcessorCacheXSize(long int dwCacheID) +int SystemInformationImplementation::GetProcessorCacheXSize( + long int dwCacheID) const { switch (dwCacheID) { case SystemInformation::CPU_FEATURE_L1CACHE: @@ -1848,7 +1889,8 @@ int SystemInformationImplementation::GetProcessorCacheXSize(long int dwCacheID) return -1; } -bool SystemInformationImplementation::DoesCPUSupportFeature(long int dwFeature) +bool SystemInformationImplementation::DoesCPUSupportFeature( + long int dwFeature) const { bool bHasFeature = false; @@ -2128,7 +2170,7 @@ void SystemInformationImplementation::FindManufacturer( this->ChipManufacturer = HP; // Hewlett-Packard else if (this->ChipID.Vendor == "Motorola") this->ChipManufacturer = Motorola; // Motorola Microelectronics - else if (family.substr(0, 7) == "PA-RISC") + else if (family.compare(0, 7, "PA-RISC") == 0) this->ChipManufacturer = HP; // Hewlett-Packard else this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer @@ -2843,7 +2885,7 @@ static void SystemInformationStripLeadingSpace(std::string& str) // post-process the name. std::string::size_type pos = str.find_first_not_of(" "); if (pos != std::string::npos) { - str = str.substr(pos); + str.erase(0, pos); } } #endif @@ -3358,7 +3400,9 @@ std::string SystemInformationImplementation::ExtractValueFromCpuInfoFile( return this->ExtractValueFromCpuInfoFile(buffer, word, pos2); } } - return buffer.substr(pos + 2, pos2 - pos - 2); + buffer.erase(0, pos + 2); + buffer.resize(pos2 - pos - 2); + return buffer; } } this->CurrentPositionInFile = std::string::npos; @@ -3409,7 +3453,7 @@ 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"); - unsigned int NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str()); + auto NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str()); NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u); this->NumberOfPhysicalCPU = NumberOfCoresPerSocket * (unsigned int)NumberOfSockets; @@ -3441,7 +3485,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() // 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(), 0, 16)) / 1000000.0f; + static_cast<float>(strtoull(CPUSpeed.c_str(), nullptr, 16)) / 1000000.0f; } #endif @@ -3502,13 +3546,12 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() cachename.push_back("D-cache"); // e.g. PA-RISC this->Features.L1CacheSize = 0; - for (size_t index = 0; index < cachename.size(); index++) { - std::string cacheSize = - this->ExtractValueFromCpuInfoFile(buffer, cachename[index]); + for (auto& index : cachename) { + std::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer, index); if (!cacheSize.empty()) { pos = cacheSize.find(" KB"); if (pos != std::string::npos) { - cacheSize = cacheSize.substr(0, pos); + cacheSize.resize(pos); } this->Features.L1CacheSize += atoi(cacheSize.c_str()); } @@ -4249,24 +4292,24 @@ bool SystemInformationImplementation::QueryMemory() } /** */ -size_t SystemInformationImplementation::GetTotalVirtualMemory() +size_t SystemInformationImplementation::GetTotalVirtualMemory() const { return this->TotalVirtualMemory; } /** */ -size_t SystemInformationImplementation::GetAvailableVirtualMemory() +size_t SystemInformationImplementation::GetAvailableVirtualMemory() const { return this->AvailableVirtualMemory; } -size_t SystemInformationImplementation::GetTotalPhysicalMemory() +size_t SystemInformationImplementation::GetTotalPhysicalMemory() const { return this->TotalPhysicalMemory; } /** */ -size_t SystemInformationImplementation::GetAvailablePhysicalMemory() +size_t SystemInformationImplementation::GetAvailablePhysicalMemory() const { return this->AvailablePhysicalMemory; } @@ -4350,7 +4393,7 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS) } /** Works only for windows */ -bool SystemInformationImplementation::IsSMTSupported() +bool SystemInformationImplementation::IsSMTSupported() const { return this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical > 1; } @@ -4432,13 +4475,13 @@ void SystemInformationImplementation::CPUCountWindows() } /** Return the number of logical CPUs on the system */ -unsigned int SystemInformationImplementation::GetNumberOfLogicalCPU() +unsigned int SystemInformationImplementation::GetNumberOfLogicalCPU() const { return this->NumberOfLogicalCPU; } /** Return the number of physical CPUs on the system */ -unsigned int SystemInformationImplementation::GetNumberOfPhysicalCPU() +unsigned int SystemInformationImplementation::GetNumberOfPhysicalCPU() const { return this->NumberOfPhysicalCPU; } @@ -4733,14 +4776,15 @@ std::string SystemInformationImplementation::ParseValueFromKStat( } pos = command.find(' ', pos + 1); } - args_string.push_back(command.substr(start + 1, command.size() - start - 1)); + command.erase(0, start + 1); + args_string.push_back(command); std::vector<const char*> args; args.reserve(3 + args_string.size()); args.push_back("kstat"); args.push_back("-p"); - for (size_t i = 0; i < args_string.size(); ++i) { - args.push_back(args_string[i].c_str()); + for (auto& i : args_string) { + args.push_back(i.c_str()); } args.push_back(nullptr); @@ -4922,7 +4966,9 @@ bool SystemInformationImplementation::QueryQNXMemory() while (buffer[pos] == ' ') pos++; - this->TotalPhysicalMemory = atoi(buffer.substr(pos, pos2 - pos).c_str()); + buffer.erase(0, pos); + buffer.resize(pos2); + this->TotalPhysicalMemory = atoi(buffer.c_str()); return true; #endif return false; @@ -5459,7 +5505,7 @@ void SystemInformationImplementation::TrimNewline(std::string& output) } /** Return true if the machine is 64 bits */ -bool SystemInformationImplementation::Is64Bits() +bool SystemInformationImplementation::Is64Bits() const { return this->OSIs64Bit; } diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index d27081b..e073cbf 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -123,9 +123,9 @@ extern char** environ; #define VTK_URL_PROTOCOL_REGEX "([a-zA-Z0-9]*)://(.*)" #define VTK_URL_REGEX \ - "([a-zA-Z0-9]*)://(([A-Za-z0-9]+)(:([^:@]+))?@)?([^:@/]+)(:([0-9]+))?/" \ + "([a-zA-Z0-9]*)://(([A-Za-z0-9]+)(:([^:@]+))?@)?([^:@/]*)(:([0-9]+))?/" \ "(.+)?" - +#define VTK_URL_BYTE_REGEX "%[0-9a-fA-F][0-9a-fA-F]" #ifdef _MSC_VER # include <sys/utime.h> #else @@ -221,11 +221,17 @@ static time_t windows_filetime_to_posix_time(const FILETIME& ft) #ifdef KWSYS_WINDOWS_DIRS # include <wctype.h> +# ifdef _MSC_VER +typedef KWSYS_NAMESPACE::SystemTools::mode_t mode_t; +# endif -inline int Mkdir(const std::string& dir) +inline int Mkdir(const std::string& dir, const mode_t* mode) { - return _wmkdir( - KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str()); + int ret = + _wmkdir(KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str()); + if (ret == 0 && mode) + KWSYS_NAMESPACE::SystemTools::SetPermissions(dir, *mode); + return ret; } inline int Rmdir(const std::string& dir) { @@ -295,9 +301,9 @@ inline void Realpath(const std::string& path, std::string& resolved_path, # include <fcntl.h> # include <unistd.h> -inline int Mkdir(const std::string& dir) +inline int Mkdir(const std::string& dir, const mode_t* mode) { - return mkdir(dir.c_str(), 00777); + return mkdir(dir.c_str(), mode ? *mode : 00777); } inline int Rmdir(const std::string& dir) { @@ -350,7 +356,7 @@ extern int putenv(char* __string) __THROW; namespace KWSYS_NAMESPACE { -double SystemTools::GetTime(void) +double SystemTools::GetTime() { #if defined(_WIN32) && !defined(__CYGWIN__) FILETIME ft; @@ -368,7 +374,7 @@ double SystemTools::GetTime(void) #if defined(_WIN32) typedef wchar_t envchar; #else -typedef char envchar; +using envchar = char; #endif /* Order by environment key only (VAR from VAR=VALUE). */ @@ -421,7 +427,7 @@ public: const envchar* Release(const envchar* env) { const envchar* old = nullptr; - iterator i = this->find(env); + auto i = this->find(env); if (i != this->end()) { old = *i; this->erase(i); @@ -452,7 +458,7 @@ struct SystemToolsPathCaseCmp class SystemToolsStatic { public: - typedef std::map<std::string, std::string> StringMap; + using StringMap = std::map<std::string, std::string>; #if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP /** * Path translation table from dir to refdir @@ -488,7 +494,7 @@ public: */ static std::string FindName( const std::string& name, - const std::vector<std::string>& path = std::vector<std::string>(), + const std::vector<std::string>& userPaths = std::vector<std::string>(), bool no_system_path = false); }; @@ -613,8 +619,7 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env) done = true; } } - for (std::vector<std::string>::iterator i = path.begin() + old_size; - i != path.end(); ++i) { + for (auto i = path.begin() + old_size; i != path.end(); ++i) { SystemTools::ConvertToUnixSlashes(*i); } } @@ -913,16 +918,17 @@ bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode) std::string::size_type pos = 0; std::string topdir; while ((pos = dir.find('/', pos)) != std::string::npos) { - topdir = dir.substr(0, pos); + // all underlying functions use C strings, so temporarily + // end the string here + dir[pos] = '\0'; - if (Mkdir(topdir) == 0 && mode != nullptr) { - SystemTools::SetPermissions(topdir, *mode); - } + Mkdir(dir, mode); + dir[pos] = '/'; ++pos; } topdir = dir; - if (Mkdir(topdir) != 0) { + if (Mkdir(topdir, mode) != 0) { // There is a bug in the Borland Run time library which makes MKDIR // return EACCES when it should return EEXISTS // if it is some other error besides directory exists @@ -934,8 +940,6 @@ bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode) ) { return false; } - } else if (mode != nullptr) { - SystemTools::SetPermissions(topdir, *mode); } return true; @@ -1011,38 +1015,40 @@ void SystemToolsStatic::ReplaceString(std::string& source, const char* replace, # define KWSYS_ST_KEY_WOW64_64KEY 0x0100 # endif -static bool SystemToolsParseRegistryKey(const std::string& key, - HKEY& primaryKey, std::string& second, - std::string& valuename) +static bool hasPrefix(const std::string& s, const char* pattern, + std::string::size_type spos) { - std::string primary = key; + size_t plen = strlen(pattern); + if (spos != plen) + return false; + return s.compare(0, plen, pattern) == 0; +} - size_t start = primary.find('\\'); +static bool SystemToolsParseRegistryKey(const std::string& key, + HKEY& primaryKey, std::wstring& second, + std::string* valuename) +{ + size_t start = key.find('\\'); if (start == std::string::npos) { return false; } - size_t valuenamepos = primary.find(';'); - if (valuenamepos != std::string::npos) { - valuename = primary.substr(valuenamepos + 1); + size_t valuenamepos = key.find(';'); + if (valuenamepos != std::string::npos && valuename) { + *valuename = key.substr(valuenamepos + 1); } - second = primary.substr(start + 1, valuenamepos - start - 1); - primary = primary.substr(0, start); + second = Encoding::ToWide(key.substr(start + 1, valuenamepos - start - 1)); - if (primary == "HKEY_CURRENT_USER") { + if (hasPrefix(key, "HKEY_CURRENT_USER", start)) { primaryKey = HKEY_CURRENT_USER; - } - if (primary == "HKEY_CURRENT_CONFIG") { + } else if (hasPrefix(key, "HKEY_CURRENT_CONFIG", start)) { primaryKey = HKEY_CURRENT_CONFIG; - } - if (primary == "HKEY_CLASSES_ROOT") { + } else if (hasPrefix(key, "HKEY_CLASSES_ROOT", start)) { primaryKey = HKEY_CLASSES_ROOT; - } - if (primary == "HKEY_LOCAL_MACHINE") { + } else if (hasPrefix(key, "HKEY_LOCAL_MACHINE", start)) { primaryKey = HKEY_LOCAL_MACHINE; - } - if (primary == "HKEY_USERS") { + } else if (hasPrefix(key, "HKEY_USERS", start)) { primaryKey = HKEY_USERS; } @@ -1074,14 +1080,13 @@ bool SystemTools::GetRegistrySubKeys(const std::string& key, KeyWOW64 view) { HKEY primaryKey = HKEY_CURRENT_USER; - std::string second; - std::string valuename; - if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { + std::wstring second; + if (!SystemToolsParseRegistryKey(key, primaryKey, second, nullptr)) { return false; } HKEY hKey; - if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, + if (RegOpenKeyExW(primaryKey, second.c_str(), 0, SystemToolsMakeRegistryMode(KEY_READ, view), &hKey) != ERROR_SUCCESS) { return false; @@ -1121,14 +1126,14 @@ bool SystemTools::ReadRegistryValue(const std::string& key, std::string& value, { bool valueset = false; HKEY primaryKey = HKEY_CURRENT_USER; - std::string second; + std::wstring second; std::string valuename; - if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { + if (!SystemToolsParseRegistryKey(key, primaryKey, second, &valuename)) { return false; } HKEY hKey; - if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, + if (RegOpenKeyExW(primaryKey, second.c_str(), 0, SystemToolsMakeRegistryMode(KEY_READ, view), &hKey) != ERROR_SUCCESS) { return false; @@ -1175,16 +1180,16 @@ bool SystemTools::WriteRegistryValue(const std::string& key, const std::string& value, KeyWOW64 view) { HKEY primaryKey = HKEY_CURRENT_USER; - std::string second; + std::wstring second; std::string valuename; - if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { + if (!SystemToolsParseRegistryKey(key, primaryKey, second, &valuename)) { return false; } HKEY hKey; DWORD dwDummy; wchar_t lpClass[] = L""; - if (RegCreateKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, lpClass, + if (RegCreateKeyExW(primaryKey, second.c_str(), 0, lpClass, REG_OPTION_NON_VOLATILE, SystemToolsMakeRegistryMode(KEY_WRITE, view), nullptr, &hKey, &dwDummy) != ERROR_SUCCESS) { @@ -1219,14 +1224,14 @@ bool SystemTools::WriteRegistryValue(const std::string&, const std::string&, bool SystemTools::DeleteRegistryValue(const std::string& key, KeyWOW64 view) { HKEY primaryKey = HKEY_CURRENT_USER; - std::string second; + std::wstring second; std::string valuename; - if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { + if (!SystemToolsParseRegistryKey(key, primaryKey, second, &valuename)) { return false; } HKEY hKey; - if (RegOpenKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, + if (RegOpenKeyExW(primaryKey, second.c_str(), 0, SystemToolsMakeRegistryMode(KEY_WRITE, view), &hKey) != ERROR_SUCCESS) { return false; @@ -1858,7 +1863,7 @@ char* SystemTools::DuplicateString(const char* str) // Return a cropped string std::string SystemTools::CropString(const std::string& s, size_t max_len) { - if (!s.size() || max_len == 0 || max_len >= s.size()) { + if (s.empty() || max_len == 0 || max_len >= s.size()) { return s; } @@ -1867,7 +1872,7 @@ std::string SystemTools::CropString(const std::string& s, size_t max_len) size_t middle = max_len / 2; - n += s.substr(0, middle); + n.assign(s, 0, middle); n += s.substr(s.size() - (max_len - middle)); if (max_len > 2) { @@ -1893,7 +1898,7 @@ std::vector<std::string> SystemTools::SplitString(const std::string& p, } if (isPath && path[0] == '/') { path.erase(path.begin()); - paths.push_back("/"); + paths.emplace_back("/"); } std::string::size_type pos1 = 0; std::string::size_type pos2 = path.find(sep, pos1 + 1); @@ -2065,8 +2070,10 @@ void SystemTools::ConvertToUnixSlashes(std::string& path) #ifdef HAVE_GETPWNAM else if (pathCString[0] == '~') { std::string::size_type idx = path.find_first_of("/\0"); - std::string user = path.substr(1, idx - 1); - passwd* pw = getpwnam(user.c_str()); + char oldch = path[idx]; + path[idx] = '\0'; + passwd* pw = getpwnam(path.c_str() + 1); + path[idx] = oldch; if (pw) { path.replace(0, idx, pw->pw_dir); } @@ -3132,17 +3139,17 @@ bool SystemTools::SplitProgramPath(const std::string& in_name, std::string& dir, std::string& file, bool) { dir = in_name; - file = ""; + file.clear(); SystemTools::ConvertToUnixSlashes(dir); if (!SystemTools::FileIsDirectory(dir)) { std::string::size_type slashPos = dir.rfind("/"); if (slashPos != std::string::npos) { file = dir.substr(slashPos + 1); - dir = dir.substr(0, slashPos); + dir.resize(slashPos); } else { file = dir; - dir = ""; + dir.clear(); } } if (!(dir.empty()) && !SystemTools::FileIsDirectory(dir)) { @@ -3269,7 +3276,7 @@ void SystemTools::CheckTranslationPath(std::string& path) // Now convert any path found in the table back to the one desired: for (auto const& pair : SystemTools::Statics->TranslationMap) { // We need to check of the path is a substring of the other path - if (path.find(pair.first) == 0) { + if (path.compare(0, pair.first.size(), pair.first) == 0) { path = path.replace(0, pair.first.size(), pair.second); } } @@ -3541,7 +3548,7 @@ void SystemTools::SplitPath(const std::string& p, // Expand home directory references if requested. if (expand_home_dir && !root.empty() && root[0] == '~') { std::string homedir; - root = root.substr(0, root.size() - 1); + root.resize(root.size() - 1); if (root.size() == 1) { #if defined(_WIN32) && !defined(__CYGWIN__) if (!SystemTools::GetEnv("USERPROFILE", homedir)) @@ -3571,14 +3578,14 @@ void SystemTools::SplitPath(const std::string& p, for (; *last; ++last) { if (*last == '/' || *last == '\\') { // End of a component. Save it. - components.push_back(std::string(first, last)); + components.emplace_back(first, last); first = last + 1; } } // Save the last component unless there were no components. if (last != c) { - components.push_back(std::string(first, last)); + components.emplace_back(first, last); } } @@ -3594,7 +3601,7 @@ std::string SystemTools::JoinPath( // Construct result in a single string. std::string result; size_t len = 0; - for (std::vector<std::string>::const_iterator i = first; i != last; ++i) { + for (auto i = first; i != last; ++i) { len += 1 + i->size(); } result.reserve(len); @@ -3686,18 +3693,19 @@ std::string SystemTools::GetFilenamePath(const std::string& filename) SystemTools::ConvertToUnixSlashes(fn); std::string::size_type slash_pos = fn.rfind("/"); - if (slash_pos != std::string::npos) { - std::string ret = fn.substr(0, slash_pos); - if (ret.size() == 2 && ret[1] == ':') { - return ret + '/'; - } - if (ret.empty()) { - return "/"; - } - return ret; - } else { + if (slash_pos == 0) { + return "/"; + } + if (slash_pos == 2 && fn[1] == ':') { + // keep the / after a drive letter + fn.resize(3); + return fn; + } + if (slash_pos == std::string::npos) { return ""; } + fn.resize(slash_pos); + return fn; } /** @@ -3727,7 +3735,8 @@ std::string SystemTools::GetFilenameExtension(const std::string& filename) std::string name = SystemTools::GetFilenameName(filename); std::string::size_type dot_pos = name.find('.'); if (dot_pos != std::string::npos) { - return name.substr(dot_pos); + name.erase(0, dot_pos); + return name; } else { return ""; } @@ -3742,7 +3751,8 @@ std::string SystemTools::GetFilenameLastExtension(const std::string& filename) std::string name = SystemTools::GetFilenameName(filename); std::string::size_type dot_pos = name.rfind('.'); if (dot_pos != std::string::npos) { - return name.substr(dot_pos); + name.erase(0, dot_pos); + return name; } else { return ""; } @@ -3758,10 +3768,9 @@ std::string SystemTools::GetFilenameWithoutExtension( std::string name = SystemTools::GetFilenameName(filename); std::string::size_type dot_pos = name.find('.'); if (dot_pos != std::string::npos) { - return name.substr(0, dot_pos); - } else { - return name; + name.resize(dot_pos); } + return name; } /** @@ -3775,10 +3784,9 @@ std::string SystemTools::GetFilenameWithoutLastExtension( std::string name = SystemTools::GetFilenameName(filename); std::string::size_type dot_pos = name.rfind('.'); if (dot_pos != std::string::npos) { - return name.substr(0, dot_pos); - } else { - return name; + name.resize(dot_pos); } + return name; } bool SystemTools::FileHasSignature(const char* filename, const char* signature, @@ -3828,7 +3836,7 @@ SystemTools::FileTypeEnum SystemTools::DetectFileType(const char* filename, // Allocate buffer and read bytes - unsigned char* buffer = new unsigned char[length]; + auto* buffer = new unsigned char[length]; size_t read_length = fread(buffer, 1, length, fp); fclose(fp); if (read_length == 0) { @@ -4000,7 +4008,8 @@ bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath) // if the path passed in has quotes around it, first remove the quotes if (!path.empty() && path[0] == '"' && path.back() == '"') { - tempPath = path.substr(1, path.length() - 2); + tempPath.resize(path.length() - 1); + tempPath.erase(0, 1); } std::wstring wtempPath = Encoding::ToWide(tempPath); @@ -4219,8 +4228,8 @@ bool SystemTools::IsSubDirectory(const std::string& cSubdir, if (subdir[expectedSlashPosition] != '/') { return false; } - std::string s = subdir.substr(0, dir.size()); - return SystemTools::ComparePath(s, dir); + subdir.resize(dir.size()); + return SystemTools::ComparePath(subdir, dir); } void SystemTools::Delay(unsigned int msec) @@ -4516,7 +4525,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() bool SystemTools::ParseURLProtocol(const std::string& URL, std::string& protocol, - std::string& dataglom) + std::string& dataglom, bool decode) { // match 0 entire url // match 1 protocol @@ -4529,13 +4538,17 @@ bool SystemTools::ParseURLProtocol(const std::string& URL, protocol = urlRe.match(1); dataglom = urlRe.match(2); + if (decode) { + dataglom = DecodeURL(dataglom); + } + return true; } bool SystemTools::ParseURL(const std::string& URL, std::string& protocol, std::string& username, std::string& password, std::string& hostname, std::string& dataport, - std::string& database) + std::string& database, bool decode) { kwsys::RegularExpression urlRe(VTK_URL_REGEX); if (!urlRe.find(URL)) @@ -4559,9 +4572,35 @@ bool SystemTools::ParseURL(const std::string& URL, std::string& protocol, dataport = urlRe.match(8); database = urlRe.match(9); + if (decode) { + username = DecodeURL(username); + password = DecodeURL(password); + hostname = DecodeURL(hostname); + dataport = DecodeURL(dataport); + database = DecodeURL(database); + } + return true; } +// ---------------------------------------------------------------------- +std::string SystemTools::DecodeURL(const std::string& url) +{ + kwsys::RegularExpression urlByteRe(VTK_URL_BYTE_REGEX); + std::string ret; + for (size_t i = 0; i < url.length(); i++) { + if (urlByteRe.find(url.substr(i, 3))) { + char bytes[] = { url[i + 1], url[i + 2], '\0' }; + ret += static_cast<char>(strtoul(bytes, nullptr, 16)); + i += 2; + } else { + ret += url[i]; + } + } + return ret; +} + +// ---------------------------------------------------------------------- // These must NOT be initialized. Default initialization to zero is // necessary. static unsigned int SystemToolsManagerCount; diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index c4ab9d4..d4a93fa 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -935,22 +935,32 @@ public: * Parse a character string : * protocol://dataglom * and fill protocol as appropriate. + * decode the dataglom using DecodeURL if set to true. * Return false if the URL does not have the required form, true otherwise. */ static bool ParseURLProtocol(const std::string& URL, std::string& protocol, - std::string& dataglom); + std::string& dataglom, bool decode = false); /** * Parse a string (a URL without protocol prefix) with the form: * protocol://[[username[':'password]'@']hostname[':'dataport]]'/'[datapath] * and fill protocol, username, password, hostname, dataport, and datapath * when values are found. + * decode all string except the protocol using DecodeUrl if set to true. * Return true if the string matches the format; false otherwise. */ static bool ParseURL(const std::string& URL, std::string& protocol, std::string& username, std::string& password, std::string& hostname, std::string& dataport, - std::string& datapath); + std::string& datapath, bool decode = false); + + /** + * Decode the percent-encoded string from an URL or an URI + * into their correct char values. + * Does not perform any other sort of validation. + * Return the decoded string + */ + static std::string DecodeURL(const std::string& url); private: /** diff --git a/Source/kwsys/kwsysPlatformTests.cmake b/Source/kwsys/kwsysPlatformTests.cmake index 28d3f68..89be4b8 100644 --- a/Source/kwsys/kwsysPlatformTests.cmake +++ b/Source/kwsys/kwsysPlatformTests.cmake @@ -1,185 +1,185 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing#kwsys for details. -SET(KWSYS_PLATFORM_TEST_FILE_C kwsysPlatformTestsC.c) -SET(KWSYS_PLATFORM_TEST_FILE_CXX kwsysPlatformTestsCXX.cxx) +set(KWSYS_PLATFORM_TEST_FILE_C kwsysPlatformTestsC.c) +set(KWSYS_PLATFORM_TEST_FILE_CXX kwsysPlatformTestsCXX.cxx) -MACRO(KWSYS_PLATFORM_TEST lang var description invert) - IF(NOT DEFINED ${var}_COMPILED) - MESSAGE(STATUS "${description}") +macro(KWSYS_PLATFORM_TEST lang var description invert) + if(NOT DEFINED ${var}_COMPILED) + message(STATUS "${description}") set(maybe_cxx_standard "") if(CMAKE_VERSION VERSION_LESS 3.8 AND CMAKE_CXX_STANDARD) set(maybe_cxx_standard "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}") endif() - TRY_COMPILE(${var}_COMPILED + try_compile(${var}_COMPILED ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}} COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_TEST_DEFINES} ${KWSYS_PLATFORM_TEST_EXTRA_FLAGS} CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${KWSYS_PLATFORM_TEST_LINK_LIBRARIES}" ${maybe_cxx_standard} OUTPUT_VARIABLE OUTPUT) - IF(${var}_COMPILED) - FILE(APPEND + if(${var}_COMPILED) + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "${description} compiled with the following output:\n${OUTPUT}\n\n") - ELSE() - FILE(APPEND + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${description} failed to compile with the following output:\n${OUTPUT}\n\n") - ENDIF() - IF(${invert} MATCHES INVERT) - IF(${var}_COMPILED) - MESSAGE(STATUS "${description} - no") - ELSE() - MESSAGE(STATUS "${description} - yes") - ENDIF() - ELSE() - IF(${var}_COMPILED) - MESSAGE(STATUS "${description} - yes") - ELSE() - MESSAGE(STATUS "${description} - no") - ENDIF() - ENDIF() - ENDIF() - IF(${invert} MATCHES INVERT) - IF(${var}_COMPILED) - SET(${var} 0) - ELSE() - SET(${var} 1) - ENDIF() - ELSE() - IF(${var}_COMPILED) - SET(${var} 1) - ELSE() - SET(${var} 0) - ENDIF() - ENDIF() -ENDMACRO() + endif() + if(${invert} MATCHES INVERT) + if(${var}_COMPILED) + message(STATUS "${description} - no") + else() + message(STATUS "${description} - yes") + endif() + else() + if(${var}_COMPILED) + message(STATUS "${description} - yes") + else() + message(STATUS "${description} - no") + endif() + endif() + endif() + if(${invert} MATCHES INVERT) + if(${var}_COMPILED) + set(${var} 0) + else() + set(${var} 1) + endif() + else() + if(${var}_COMPILED) + set(${var} 1) + else() + set(${var} 0) + endif() + endif() +endmacro() -MACRO(KWSYS_PLATFORM_TEST_RUN lang var description invert) - IF(NOT DEFINED ${var}) - MESSAGE(STATUS "${description}") - TRY_RUN(${var} ${var}_COMPILED +macro(KWSYS_PLATFORM_TEST_RUN lang var description invert) + if(NOT DEFINED ${var}) + message(STATUS "${description}") + try_run(${var} ${var}_COMPILED ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}} COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_TEST_DEFINES} ${KWSYS_PLATFORM_TEST_EXTRA_FLAGS} OUTPUT_VARIABLE OUTPUT) # Note that ${var} will be a 0 return value on success. - IF(${var}_COMPILED) - IF(${var}) - FILE(APPEND + if(${var}_COMPILED) + if(${var}) + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${description} compiled but failed to run with the following output:\n${OUTPUT}\n\n") - ELSE() - FILE(APPEND + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "${description} compiled and ran with the following output:\n${OUTPUT}\n\n") - ENDIF() - ELSE() - FILE(APPEND + endif() + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${description} failed to compile with the following output:\n${OUTPUT}\n\n") - SET(${var} -1 CACHE INTERNAL "${description} failed to compile.") - ENDIF() + set(${var} -1 CACHE INTERNAL "${description} failed to compile.") + endif() - IF(${invert} MATCHES INVERT) - IF(${var}_COMPILED) - IF(${var}) - MESSAGE(STATUS "${description} - yes") - ELSE() - MESSAGE(STATUS "${description} - no") - ENDIF() - ELSE() - MESSAGE(STATUS "${description} - failed to compile") - ENDIF() - ELSE() - IF(${var}_COMPILED) - IF(${var}) - MESSAGE(STATUS "${description} - no") - ELSE() - MESSAGE(STATUS "${description} - yes") - ENDIF() - ELSE() - MESSAGE(STATUS "${description} - failed to compile") - ENDIF() - ENDIF() - ENDIF() + if(${invert} MATCHES INVERT) + if(${var}_COMPILED) + if(${var}) + message(STATUS "${description} - yes") + else() + message(STATUS "${description} - no") + endif() + else() + message(STATUS "${description} - failed to compile") + endif() + else() + if(${var}_COMPILED) + if(${var}) + message(STATUS "${description} - no") + else() + message(STATUS "${description} - yes") + endif() + else() + message(STATUS "${description} - failed to compile") + endif() + endif() + endif() - IF(${invert} MATCHES INVERT) - IF(${var}_COMPILED) - IF(${var}) - SET(${var} 1) - ELSE() - SET(${var} 0) - ENDIF() - ELSE() - SET(${var} 1) - ENDIF() - ELSE() - IF(${var}_COMPILED) - IF(${var}) - SET(${var} 0) - ELSE() - SET(${var} 1) - ENDIF() - ELSE() - SET(${var} 0) - ENDIF() - ENDIF() -ENDMACRO() + if(${invert} MATCHES INVERT) + if(${var}_COMPILED) + if(${var}) + set(${var} 1) + else() + set(${var} 0) + endif() + else() + set(${var} 1) + endif() + else() + if(${var}_COMPILED) + if(${var}) + set(${var} 0) + else() + set(${var} 1) + endif() + else() + set(${var} 0) + endif() + endif() +endmacro() -MACRO(KWSYS_PLATFORM_C_TEST var description invert) - SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_C_TEST_DEFINES}) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_C_TEST_EXTRA_FLAGS}) +macro(KWSYS_PLATFORM_C_TEST var description invert) + set(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_C_TEST_DEFINES}) + set(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_C_TEST_EXTRA_FLAGS}) KWSYS_PLATFORM_TEST(C "${var}" "${description}" "${invert}") - SET(KWSYS_PLATFORM_TEST_DEFINES) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) -ENDMACRO() + set(KWSYS_PLATFORM_TEST_DEFINES) + set(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) +endmacro() -MACRO(KWSYS_PLATFORM_C_TEST_RUN var description invert) - SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_C_TEST_DEFINES}) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_C_TEST_EXTRA_FLAGS}) +macro(KWSYS_PLATFORM_C_TEST_RUN var description invert) + set(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_C_TEST_DEFINES}) + set(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_C_TEST_EXTRA_FLAGS}) KWSYS_PLATFORM_TEST_RUN(C "${var}" "${description}" "${invert}") - SET(KWSYS_PLATFORM_TEST_DEFINES) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) -ENDMACRO() + set(KWSYS_PLATFORM_TEST_DEFINES) + set(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) +endmacro() -MACRO(KWSYS_PLATFORM_CXX_TEST var description invert) - SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES}) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS}) - SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES ${KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES}) +macro(KWSYS_PLATFORM_CXX_TEST var description invert) + set(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES}) + set(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS}) + set(KWSYS_PLATFORM_TEST_LINK_LIBRARIES ${KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES}) KWSYS_PLATFORM_TEST(CXX "${var}" "${description}" "${invert}") - SET(KWSYS_PLATFORM_TEST_DEFINES) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) - SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES) -ENDMACRO() + set(KWSYS_PLATFORM_TEST_DEFINES) + set(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) + set(KWSYS_PLATFORM_TEST_LINK_LIBRARIES) +endmacro() -MACRO(KWSYS_PLATFORM_CXX_TEST_RUN var description invert) - SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES}) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS}) +macro(KWSYS_PLATFORM_CXX_TEST_RUN var description invert) + set(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES}) + set(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS}) KWSYS_PLATFORM_TEST_RUN(CXX "${var}" "${description}" "${invert}") - SET(KWSYS_PLATFORM_TEST_DEFINES) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) -ENDMACRO() + set(KWSYS_PLATFORM_TEST_DEFINES) + set(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) +endmacro() #----------------------------------------------------------------------------- # KWSYS_PLATFORM_INFO_TEST(lang var description) # # Compile test named by ${var} and store INFO strings extracted from binary. -MACRO(KWSYS_PLATFORM_INFO_TEST lang var description) +macro(KWSYS_PLATFORM_INFO_TEST lang var description) # We can implement this macro on CMake 2.6 and above. - IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6) - SET(${var} "") - ELSE() + if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6) + set(${var} "") + else() # Choose a location for the result binary. - SET(KWSYS_PLATFORM_INFO_FILE + set(KWSYS_PLATFORM_INFO_FILE ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/${var}.bin) # Compile the test binary. - IF(NOT EXISTS ${KWSYS_PLATFORM_INFO_FILE}) - MESSAGE(STATUS "${description}") - TRY_COMPILE(${var}_COMPILED + if(NOT EXISTS ${KWSYS_PLATFORM_INFO_FILE}) + message(STATUS "${description}") + try_compile(${var}_COMPILED ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}} COMPILE_DEFINITIONS -DTEST_${var} @@ -188,29 +188,29 @@ MACRO(KWSYS_PLATFORM_INFO_TEST lang var description) OUTPUT_VARIABLE OUTPUT COPY_FILE ${KWSYS_PLATFORM_INFO_FILE} ) - IF(${var}_COMPILED) - FILE(APPEND + if(${var}_COMPILED) + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "${description} compiled with the following output:\n${OUTPUT}\n\n") - ELSE() - FILE(APPEND + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${description} failed to compile with the following output:\n${OUTPUT}\n\n") - ENDIF() - IF(${var}_COMPILED) - MESSAGE(STATUS "${description} - compiled") - ELSE() - MESSAGE(STATUS "${description} - failed") - ENDIF() - ENDIF() + endif() + if(${var}_COMPILED) + message(STATUS "${description} - compiled") + else() + message(STATUS "${description} - failed") + endif() + endif() # Parse info strings out of the compiled binary. - IF(${var}_COMPILED) - FILE(STRINGS ${KWSYS_PLATFORM_INFO_FILE} ${var} REGEX "INFO:[A-Za-z0-9]+\\[[^]]*\\]") - ELSE() - SET(${var} "") - ENDIF() + if(${var}_COMPILED) + file(STRINGS ${KWSYS_PLATFORM_INFO_FILE} ${var} REGEX "INFO:[A-Za-z0-9]+\\[[^]]*\\]") + else() + set(${var} "") + endif() - SET(KWSYS_PLATFORM_INFO_FILE) - ENDIF() -ENDMACRO() + set(KWSYS_PLATFORM_INFO_FILE) + endif() +endmacro() diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx index 1778a9b..79ebe1a 100644 --- a/Source/kwsys/testCommandLineArguments.cxx +++ b/Source/kwsys/testCommandLineArguments.cxx @@ -98,7 +98,7 @@ int testCommandLineArguments(int argc, char* argv[]) std::vector<std::string> stl_strings_argument; std::string valid_stl_strings[] = { "ken", "brad", "bill", "andy" }; - typedef kwsys::CommandLineArguments argT; + using argT = kwsys::CommandLineArguments; arg.AddArgument("--some-int-variable", argT::SPACE_ARGUMENT, &some_int_variable, "Set some random int variable"); diff --git a/Source/kwsys/testCommandLineArguments1.cxx b/Source/kwsys/testCommandLineArguments1.cxx index 64561b1..cbc3002 100644 --- a/Source/kwsys/testCommandLineArguments1.cxx +++ b/Source/kwsys/testCommandLineArguments1.cxx @@ -25,7 +25,7 @@ int testCommandLineArguments1(int argc, char* argv[]) std::string p; int res = 0; - typedef kwsys::CommandLineArguments argT; + using argT = kwsys::CommandLineArguments; arg.AddArgument("-n", argT::SPACE_ARGUMENT, &n, "Argument N"); arg.AddArgument("-m", argT::EQUAL_ARGUMENT, &m, "Argument M"); arg.AddBooleanArgument("-p", &p, "Argument P"); diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx index 2421ac0..703ad4d 100644 --- a/Source/kwsys/testDynamicLoader.cxx +++ b/Source/kwsys/testDynamicLoader.cxx @@ -25,7 +25,7 @@ static std::string GetLibName(const char* lname, const char* subdir = nullptr) { // Construct proper name of lib std::string slname; - slname = EXECUTABLE_OUTPUT_PATH; + slname = RUNTIME_OUTPUT_DIRECTORY; if (subdir) { slname += "/"; slname += subdir; diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx index 988697b..d672aed 100644 --- a/Source/kwsys/testEncoding.cxx +++ b/Source/kwsys/testEncoding.cxx @@ -85,7 +85,7 @@ static int testRobustEncoding() std::wstring wstr = kwsys::Encoding::ToWide(cstr); wstr = kwsys::Encoding::ToWide(nullptr); - if (wstr != L"") { + if (!wstr.empty()) { const wchar_t* wcstr = wstr.c_str(); std::cout << "ToWide(NULL) returned"; for (size_t i = 0; i < wstr.size(); i++) { @@ -95,7 +95,7 @@ static int testRobustEncoding() ret++; } wstr = kwsys::Encoding::ToWide(""); - if (wstr != L"") { + if (!wstr.empty()) { const wchar_t* wcstr = wstr.c_str(); std::cout << "ToWide(\"\") returned"; for (size_t i = 0; i < wstr.size(); i++) { @@ -113,13 +113,13 @@ static int testRobustEncoding() #endif std::string str = kwsys::Encoding::ToNarrow(nullptr); - if (str != "") { + if (!str.empty()) { std::cout << "ToNarrow(NULL) returned " << str << std::endl; ret++; } str = kwsys::Encoding::ToNarrow(L""); - if (wstr != L"") { + if (!wstr.empty()) { std::cout << "ToNarrow(\"\") returned " << str << std::endl; ret++; } @@ -140,14 +140,13 @@ static int testWithNulls() strings.push_back(std::string("k") + '\0' + '\0'); strings.push_back(std::string("\0\0\0\0", 4) + "lmn" + std::string("\0\0\0\0", 4)); - for (std::vector<std::string>::iterator it = strings.begin(); - it != strings.end(); ++it) { - std::wstring wstr = kwsys::Encoding::ToWide(*it); + for (auto& string : strings) { + std::wstring wstr = kwsys::Encoding::ToWide(string); std::string str = kwsys::Encoding::ToNarrow(wstr); - std::string s(*it); + std::string s(string); std::replace(s.begin(), s.end(), '\0', ' '); - std::cout << "'" << s << "' (" << it->size() << ")" << std::endl; - if (str != *it) { + std::cout << "'" << s << "' (" << string.size() << ")" << std::endl; + if (str != string) { std::replace(str.begin(), str.end(), '\0', ' '); std::cout << "string with null was different: '" << str << "' (" << str.size() << ")" << std::endl; diff --git a/Source/kwsys/testHashSTL.cxx b/Source/kwsys/testHashSTL.cxx index 4ed2f89..18cae7f 100644 --- a/Source/kwsys/testHashSTL.cxx +++ b/Source/kwsys/testHashSTL.cxx @@ -27,30 +27,30 @@ template class kwsys::hash_set<int>; static bool test_hash_map() { - typedef kwsys::hash_map<const char*, int> mtype; + using mtype = kwsys::hash_map<const char*, int>; mtype m; const char* keys[] = { "hello", "world" }; m[keys[0]] = 1; m.insert(mtype::value_type(keys[1], 2)); int sum = 0; - for (mtype::iterator mi = m.begin(); mi != m.end(); ++mi) { - std::cout << "Found entry [" << mi->first << "," << mi->second << "]" + for (auto& mi : m) { + std::cout << "Found entry [" << mi.first << "," << mi.second << "]" << std::endl; - sum += mi->second; + sum += mi.second; } return sum == 3; } static bool test_hash_set() { - typedef kwsys::hash_set<int> stype; + using stype = kwsys::hash_set<int>; stype s; s.insert(1); s.insert(2); int sum = 0; - for (stype::iterator si = s.begin(); si != s.end(); ++si) { - std::cout << "Found entry [" << *si << "]" << std::endl; - sum += *si; + for (int si : s) { + std::cout << "Found entry [" << si << "]" << std::endl; + sum += si; } return sum == 3; } diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 3f6eeb8..aa38aec 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -328,7 +328,14 @@ static bool CheckFileOperations() } // While we're at it, check proper TestFileAccess functionality. - if (kwsys::SystemTools::TestFileAccess(testNewFile, + bool do_write_test = true; +#if defined(__linux__) + // If we are running as root on linux ignore this check, as + // root can always write to files + do_write_test = (getuid() != 0); +#endif + if (do_write_test && + kwsys::SystemTools::TestFileAccess(testNewFile, kwsys::TEST_FILE_WRITE)) { std::cerr << "TestFileAccess incorrectly indicated that this is a writable file:" @@ -721,8 +728,7 @@ static std::string StringVectorToString(const std::vector<std::string>& vec) { std::stringstream ss; ss << "vector("; - for (std::vector<std::string>::const_iterator i = vec.begin(); - i != vec.end(); ++i) { + for (auto i = vec.begin(); i != vec.end(); ++i) { if (i != vec.begin()) { ss << ", "; } @@ -743,16 +749,16 @@ static bool CheckGetPath() const char* registryPath = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MyApp; MyKey]"; std::vector<std::string> originalPaths; - originalPaths.push_back(registryPath); + originalPaths.emplace_back(registryPath); std::vector<std::string> expectedPaths; - expectedPaths.push_back(registryPath); + expectedPaths.emplace_back(registryPath); #ifdef _WIN32 expectedPaths.push_back("C:/Somewhere/something"); expectedPaths.push_back("D:/Temp"); #else - expectedPaths.push_back("/Somewhere/something"); - expectedPaths.push_back("/tmp"); + expectedPaths.emplace_back("/Somewhere/something"); + expectedPaths.emplace_back("/tmp"); #endif bool res = true; @@ -817,7 +823,7 @@ static bool CheckFind() } std::vector<std::string> searchPaths; - searchPaths.push_back(TEST_SYSTEMTOOLS_BINARY_DIR); + searchPaths.emplace_back(TEST_SYSTEMTOOLS_BINARY_DIR); if (kwsys::SystemTools::FindFile(testFindFileName, searchPaths, true) .empty()) { std::cerr << "Problem with FindFile without system paths for: " @@ -1086,6 +1092,34 @@ static bool CheckCopyFileIfDifferent() return ret; } +static bool CheckURLParsing() +{ + bool ret = true; + std::string url = "http://user:pw@hostname:42/full/url.com"; + + std::string protocol, username, password, hostname, dataport, database; + kwsys::SystemTools::ParseURL(url, protocol, username, password, hostname, + dataport, database); + if (protocol != "http" || username != "user" || password != "pw" || + hostname != "hostname" || dataport != "42" || + database != "full/url.com") { + std::cerr << "Incorrect URL parsing" << std::endl; + ret = false; + } + + std::string uri = + "file://hostname/path/to/" + "a%20file%20with%20str%C3%A0ng%C3%A8%20ch%40r%20and%20s%C2%B5aces"; + kwsys::SystemTools::ParseURL(uri, protocol, username, password, hostname, + dataport, database, true); + if (protocol != "file" || hostname != "hostname" || + database != "path/to/a file with stràngè ch@r and sµaces") { + std::cerr << "Incorrect URL parsing or decoding" << std::endl; + ret = false; + } + return ret; +} + int testSystemTools(int, char* []) { bool res = true; @@ -1133,5 +1167,7 @@ int testSystemTools(int, char* []) res &= CheckCopyFileIfDifferent(); + res &= CheckURLParsing(); + return res ? 0 : 1; } diff --git a/Source/kwsys/testSystemTools.h.in b/Source/kwsys/testSystemTools.h.in index 022e36e..e4b89a7 100644 --- a/Source/kwsys/testSystemTools.h.in +++ b/Source/kwsys/testSystemTools.h.in @@ -3,7 +3,7 @@ #ifndef @KWSYS_NAMESPACE@_testSystemtools_h #define @KWSYS_NAMESPACE@_testSystemtools_h -#define EXECUTABLE_OUTPUT_PATH "@CMAKE_CURRENT_BINARY_DIR@" +#define RUNTIME_OUTPUT_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@" #define TEST_SYSTEMTOOLS_SOURCE_DIR "@TEST_SYSTEMTOOLS_SOURCE_DIR@" #define TEST_SYSTEMTOOLS_BINARY_DIR "@TEST_SYSTEMTOOLS_BINARY_DIR@" |