diff options
Diffstat (limited to 'Source')
175 files changed, 3121 insertions, 1409 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index c8498a9..677fd2f 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -261,6 +261,8 @@ set(SRCS cmFileLockResult.h cmFilePathChecksum.cxx cmFilePathChecksum.h + cmFileSet.cxx + cmFileSet.h cmFileTime.cxx cmFileTime.h cmFileTimeCache.cxx @@ -316,6 +318,8 @@ set(SRCS cmInstallExportGenerator.cxx cmInstalledFile.h cmInstalledFile.cxx + cmInstallFileSetGenerator.h + cmInstallFileSetGenerator.cxx cmInstallFilesGenerator.h cmInstallFilesGenerator.cxx cmInstallImportedRuntimeArtifactsGenerator.h @@ -1105,7 +1109,6 @@ if(APPLE) set(CPACK_SRCS ${CPACK_SRCS} CPack/cmCPackBundleGenerator.cxx CPack/cmCPackDragNDropGenerator.cxx - CPack/cmCPackOSXX11Generator.cxx CPack/cmCPackPKGGenerator.cxx CPack/cmCPackPackageMakerGenerator.cxx CPack/cmCPackProductBuildGenerator.cxx @@ -1142,13 +1145,6 @@ if(CPACK_ENABLE_FREEBSD_PKG AND FREEBSD_PKG_INCLUDE_DIRS AND FREEBSD_PKG_LIBRARI add_definitions(-DHAVE_FREEBSD_PKG) endif() -if(APPLE) - add_executable(OSXScriptLauncher - CPack/OSXScriptLauncher.cxx) - target_link_libraries(OSXScriptLauncher cmsys) - target_link_libraries(OSXScriptLauncher "-framework CoreFoundation") -endif() - # Build CMake executable add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h ${MANIFEST_FILE}) list(APPEND _tools cmake) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 85791c2..7b3d170 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,8 +1,8 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 22) -set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 2) +set(CMake_VERSION_PATCH 20211109) +#set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx index f6b8a8a..5d995c3 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.cxx +++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx @@ -29,19 +29,18 @@ cmValue cmCPackIFWCommon::GetOption(const std::string& op) const bool cmCPackIFWCommon::IsOn(const std::string& op) const { - return this->Generator ? this->Generator->cmCPackGenerator::IsOn(op) : false; + return this->Generator && this->Generator->cmCPackGenerator::IsOn(op); } bool cmCPackIFWCommon::IsSetToOff(const std::string& op) const { - return this->Generator ? this->Generator->cmCPackGenerator::IsSetToOff(op) - : false; + return this->Generator && this->Generator->cmCPackGenerator::IsSetToOff(op); } bool cmCPackIFWCommon::IsSetToEmpty(const std::string& op) const { - return this->Generator ? this->Generator->cmCPackGenerator::IsSetToEmpty(op) - : false; + return this->Generator && + this->Generator->cmCPackGenerator::IsSetToEmpty(op); } bool cmCPackIFWCommon::IsVersionLess(const char* version) const diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index b375ba6..f35d7e9 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -38,202 +38,255 @@ int cmCPackIFWGenerator::PackageFiles() std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); std::string ifwTmpFile = cmStrCat(ifwTLD, "/IFWOutput.log"); - // Run repogen - if (!this->Installer.RemoteRepositories.empty()) { - std::vector<std::string> ifwCmd; - std::string ifwArg; + // Create repositories + if (!this->RunRepogen(ifwTmpFile)) { + return 0; + } + + // Create installer + if (!this->RunBinaryCreator(ifwTmpFile)) { + return 0; + } - ifwCmd.emplace_back(this->RepoGen); + return 1; +} + +std::vector<std::string> cmCPackIFWGenerator::BuildRepogenCommand() +{ + std::vector<std::string> ifwCmd; + std::string ifwArg; - if (this->IsVersionLess("2.0.0")) { - ifwCmd.emplace_back("-c"); - ifwCmd.emplace_back(this->toplevel + "/config/config.xml"); + ifwCmd.emplace_back(this->RepoGen); + + if (!this->IsVersionLess("4.2")) { + if (!this->ArchiveFormat.empty()) { + ifwCmd.emplace_back("--archive-format"); + ifwCmd.emplace_back(this->ArchiveFormat); + } + if (!this->ArchiveCompression.empty()) { + ifwCmd.emplace_back("--compression"); + ifwCmd.emplace_back(this->ArchiveCompression); } + } + + if (this->IsVersionLess("2.0.0")) { + ifwCmd.emplace_back("-c"); + ifwCmd.emplace_back(this->toplevel + "/config/config.xml"); + } - ifwCmd.emplace_back("-p"); - ifwCmd.emplace_back(this->toplevel + "/packages"); + ifwCmd.emplace_back("-p"); + ifwCmd.emplace_back(this->toplevel + "/packages"); - if (!this->PkgsDirsVector.empty()) { - for (std::string const& it : this->PkgsDirsVector) { - ifwCmd.emplace_back("-p"); - ifwCmd.emplace_back(it); - } + if (!this->PkgsDirsVector.empty()) { + for (std::string const& it : this->PkgsDirsVector) { + ifwCmd.emplace_back("-p"); + ifwCmd.emplace_back(it); } + } - if (!this->RepoDirsVector.empty()) { - if (!this->IsVersionLess("3.1")) { - for (std::string const& rd : this->RepoDirsVector) { - ifwCmd.emplace_back("--repository"); - ifwCmd.emplace_back(rd); - } - } else { - cmCPackIFWLogger(WARNING, - "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" " - << "variable is set, but content will be skipped, " - << "because this feature available only since " - << "QtIFW 3.1. Please update your QtIFW instance." - << std::endl); + if (!this->RepoDirsVector.empty()) { + if (!this->IsVersionLess("3.1")) { + for (std::string const& rd : this->RepoDirsVector) { + ifwCmd.emplace_back("--repository"); + ifwCmd.emplace_back(rd); } + } else { + cmCPackIFWLogger(WARNING, + "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" " + << "variable is set, but content will be skipped, " + << "because this feature available only since " + << "QtIFW 3.1. Please update your QtIFW instance." + << std::endl); } + } - if (!this->OnlineOnly && !this->DownloadedPackages.empty()) { - ifwCmd.emplace_back("-i"); - auto it = this->DownloadedPackages.begin(); - ifwArg = (*it)->Name; + if (!this->OnlineOnly && !this->DownloadedPackages.empty()) { + ifwCmd.emplace_back("-i"); + auto it = this->DownloadedPackages.begin(); + ifwArg = (*it)->Name; + ++it; + while (it != this->DownloadedPackages.end()) { + ifwArg += "," + (*it)->Name; ++it; - while (it != this->DownloadedPackages.end()) { - ifwArg += "," + (*it)->Name; - ++it; - } - ifwCmd.emplace_back(ifwArg); - } - ifwCmd.emplace_back(this->toplevel + "/repository"); - cmCPackIFWLogger(VERBOSE, - "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd) - << std::endl); - std::string output; - int retVal = 1; - cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl); - bool res = cmSystemTools::RunSingleCommand( - ifwCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose, - cmDuration::zero()); - if (!res || retVal) { - cmGeneratedFileStream ofs(ifwTmpFile); - ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd) - << std::endl - << "# Output:" << std::endl - << output << std::endl; - cmCPackIFWLogger( - ERROR, - "Problem running IFW command: " - << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl - << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl); - return 0; } + ifwCmd.emplace_back(ifwArg); + } + ifwCmd.emplace_back(this->toplevel + "/repository"); - if (!this->Repository.RepositoryUpdate.empty() && - !this->Repository.PatchUpdatesXml()) { - cmCPackIFWLogger(WARNING, - "Problem patch IFW \"Updates\" " - << "file: \"" << this->toplevel - << "/repository/Updates.xml\"" << std::endl); - } + return ifwCmd; +} + +int cmCPackIFWGenerator::RunRepogen(const std::string& ifwTmpFile) +{ + if (this->Installer.RemoteRepositories.empty()) { + return 1; + } + + std::vector<std::string> ifwCmd = this->BuildRepogenCommand(); + cmCPackIFWLogger(VERBOSE, + "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd) + << std::endl); + std::string output; + int retVal = 1; + cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl); + bool res = cmSystemTools::RunSingleCommand(ifwCmd, &output, &output, &retVal, + nullptr, this->GeneratorVerbose, + cmDuration::zero()); + if (!res || retVal) { + cmGeneratedFileStream ofs(ifwTmpFile); + ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd) + << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackIFWLogger( + ERROR, + "Problem running IFW command: " + << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl + << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl); + return 0; + } - cmCPackIFWLogger(OUTPUT, - "- repository: \"" << this->toplevel - << "/repository\" generated" - << std::endl); + if (!this->Repository.RepositoryUpdate.empty() && + !this->Repository.PatchUpdatesXml()) { + cmCPackIFWLogger(WARNING, + "Problem patch IFW \"Updates\" " + << "file: \"" << this->toplevel + << "/repository/Updates.xml\"" << std::endl); } - // Run binary creator - { - std::vector<std::string> ifwCmd; - std::string ifwArg; + cmCPackIFWLogger(OUTPUT, + "- repository: \"" << this->toplevel + << "/repository\" generated" + << std::endl); + return 1; +} + +std::vector<std::string> cmCPackIFWGenerator::BuildBinaryCreatorCommmand() +{ + std::vector<std::string> ifwCmd; + std::string ifwArg; - ifwCmd.emplace_back(this->BinCreator); + ifwCmd.emplace_back(this->BinCreator); - ifwCmd.emplace_back("-c"); - ifwCmd.emplace_back(this->toplevel + "/config/config.xml"); + if (!this->IsVersionLess("4.2")) { + if (!this->ArchiveFormat.empty()) { + ifwCmd.emplace_back("--archive-format"); + ifwCmd.emplace_back(this->ArchiveFormat); + } + if (!this->ArchiveCompression.empty()) { + ifwCmd.emplace_back("--compression"); + ifwCmd.emplace_back(this->ArchiveCompression); + } + } + + ifwCmd.emplace_back("-c"); + ifwCmd.emplace_back(this->toplevel + "/config/config.xml"); - if (!this->Installer.Resources.empty()) { - ifwCmd.emplace_back("-r"); - auto it = this->Installer.Resources.begin(); - std::string path = this->toplevel + "/resources/"; - ifwArg = path + *it; + if (!this->Installer.Resources.empty()) { + ifwCmd.emplace_back("-r"); + auto it = this->Installer.Resources.begin(); + std::string path = this->toplevel + "/resources/"; + ifwArg = path + *it; + ++it; + while (it != this->Installer.Resources.end()) { + ifwArg += "," + path + *it; ++it; - while (it != this->Installer.Resources.end()) { - ifwArg += "," + path + *it; - ++it; - } - ifwCmd.emplace_back(ifwArg); } + ifwCmd.emplace_back(ifwArg); + } - ifwCmd.emplace_back("-p"); - ifwCmd.emplace_back(this->toplevel + "/packages"); + ifwCmd.emplace_back("-p"); + ifwCmd.emplace_back(this->toplevel + "/packages"); - if (!this->PkgsDirsVector.empty()) { - for (std::string const& it : this->PkgsDirsVector) { - ifwCmd.emplace_back("-p"); - ifwCmd.emplace_back(it); - } + if (!this->PkgsDirsVector.empty()) { + for (std::string const& it : this->PkgsDirsVector) { + ifwCmd.emplace_back("-p"); + ifwCmd.emplace_back(it); } + } - if (!this->RepoDirsVector.empty()) { - if (!this->IsVersionLess("3.1")) { - for (std::string const& rd : this->RepoDirsVector) { - ifwCmd.emplace_back("--repository"); - ifwCmd.emplace_back(rd); - } - } else { - cmCPackIFWLogger(WARNING, - "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" " - << "variable is set, but content will be skipped, " - << "because this feature available only since " - << "QtIFW 3.1. Please update your QtIFW instance." - << std::endl); + if (!this->RepoDirsVector.empty()) { + if (!this->IsVersionLess("3.1")) { + for (std::string const& rd : this->RepoDirsVector) { + ifwCmd.emplace_back("--repository"); + ifwCmd.emplace_back(rd); } + } else { + cmCPackIFWLogger(WARNING, + "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" " + << "variable is set, but content will be skipped, " + << "because this feature available only since " + << "QtIFW 3.1. Please update your QtIFW instance." + << std::endl); } + } - if (this->OnlineOnly) { - ifwCmd.emplace_back("--online-only"); - } else if (!this->DownloadedPackages.empty() && - !this->Installer.RemoteRepositories.empty()) { - ifwCmd.emplace_back("-e"); - auto it = this->DownloadedPackages.begin(); - ifwArg = (*it)->Name; + if (this->OnlineOnly) { + ifwCmd.emplace_back("--online-only"); + } else if (!this->DownloadedPackages.empty() && + !this->Installer.RemoteRepositories.empty()) { + ifwCmd.emplace_back("-e"); + auto it = this->DownloadedPackages.begin(); + ifwArg = (*it)->Name; + ++it; + while (it != this->DownloadedPackages.end()) { + ifwArg += "," + (*it)->Name; ++it; - while (it != this->DownloadedPackages.end()) { - ifwArg += "," + (*it)->Name; - ++it; - } - ifwCmd.emplace_back(ifwArg); - } else if (!this->DependentPackages.empty()) { - ifwCmd.emplace_back("-i"); - ifwArg.clear(); - // Binary - auto bit = this->BinaryPackages.begin(); - while (bit != this->BinaryPackages.end()) { - ifwArg += (*bit)->Name + ","; - ++bit; - } - // Depend - auto it = this->DependentPackages.begin(); - ifwArg += it->second.Name; - ++it; - while (it != this->DependentPackages.end()) { - ifwArg += "," + it->second.Name; - ++it; - } - ifwCmd.emplace_back(ifwArg); } - // TODO: set correct name for multipackages - if (!this->packageFileNames.empty()) { - ifwCmd.emplace_back(this->packageFileNames[0]); - } else { - ifwCmd.emplace_back("installer" + this->OutputExtension); + ifwCmd.emplace_back(ifwArg); + } else if (!this->DependentPackages.empty()) { + ifwCmd.emplace_back("-i"); + ifwArg.clear(); + // Binary + auto bit = this->BinaryPackages.begin(); + while (bit != this->BinaryPackages.end()) { + ifwArg += (*bit)->Name + ","; + ++bit; } - cmCPackIFWLogger(VERBOSE, - "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd) - << std::endl); - std::string output; - int retVal = 1; - cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl); - bool res = cmSystemTools::RunSingleCommand( - ifwCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose, - cmDuration::zero()); - if (!res || retVal) { - cmGeneratedFileStream ofs(ifwTmpFile); - ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd) - << std::endl - << "# Output:" << std::endl - << output << std::endl; - cmCPackIFWLogger( - ERROR, - "Problem running IFW command: " - << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl - << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl); - return 0; + // Depend + auto it = this->DependentPackages.begin(); + ifwArg += it->second.Name; + ++it; + while (it != this->DependentPackages.end()) { + ifwArg += "," + it->second.Name; + ++it; } + ifwCmd.emplace_back(ifwArg); + } + // TODO: set correct name for multipackages + if (!this->packageFileNames.empty()) { + ifwCmd.emplace_back(this->packageFileNames[0]); + } else { + ifwCmd.emplace_back("installer" + this->OutputExtension); + } + + return ifwCmd; +} + +int cmCPackIFWGenerator::RunBinaryCreator(const std::string& ifwTmpFile) +{ + std::vector<std::string> ifwCmd = this->BuildBinaryCreatorCommmand(); + cmCPackIFWLogger(VERBOSE, + "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd) + << std::endl); + std::string output; + int retVal = 1; + cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl); + bool res = cmSystemTools::RunSingleCommand(ifwCmd, &output, &output, &retVal, + nullptr, this->GeneratorVerbose, + cmDuration::zero()); + if (!res || retVal) { + cmGeneratedFileStream ofs(ifwTmpFile); + ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd) + << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackIFWLogger( + ERROR, + "Problem running IFW command: " + << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl + << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl); + return 0; } return 1; @@ -323,6 +376,14 @@ int cmCPackIFWGenerator::InitializeInternal() cmExpandList(dirs, this->RepoDirsVector); } + // Archive format and compression level + if (cmValue af = this->GetOption("CPACK_IFW_ARCHIVE_FORMAT")) { + this->ArchiveFormat = *af; + } + if (cmValue ac = this->GetOption("CPACK_IFW_ARCHIVE_COMPRESSION")) { + this->ArchiveCompression = *ac; + } + // Installer this->Installer.Generator = this; this->Installer.ConfigureFromOptions(); diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h index 024d25d..86b4993 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.h +++ b/Source/CPack/IFW/cmCPackIFWGenerator.h @@ -9,13 +9,15 @@ #include <string> #include <vector> -#include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackIFWCommon.h" #include "cmCPackIFWInstaller.h" #include "cmCPackIFWPackage.h" #include "cmCPackIFWRepository.h" +class cmCPackComponent; +class cmCPackComponentGroup; + /** \class cmCPackIFWGenerator * \brief A generator for Qt Installer Framework tools * @@ -30,8 +32,6 @@ public: using PackagesMap = std::map<std::string, cmCPackIFWPackage>; using RepositoriesMap = std::map<std::string, cmCPackIFWRepository>; - using ComponentsMap = std::map<std::string, cmCPackComponent>; - using ComponentGoupsMap = std::map<std::string, cmCPackComponentGroup>; using DependenceMap = std::map<std::string, cmCPackIFWPackage::DependenceStruct>; @@ -140,14 +140,22 @@ protected: std::map<cmCPackComponentGroup*, cmCPackIFWPackage*> GroupPackages; private: + std::vector<std::string> BuildRepogenCommand(); + int RunRepogen(const std::string& ifwTmpFile); + + std::vector<std::string> BuildBinaryCreatorCommmand(); + int RunBinaryCreator(const std::string& ifwTmpFile); + std::string RepoGen; std::string BinCreator; std::string FrameworkVersion; std::string ExecutableSuffix; std::string OutputExtension; + std::string ArchiveFormat; + std::string ArchiveCompression; - bool OnlineOnly; - bool ResolveDuplicateNames; + bool OnlineOnly{}; + bool ResolveDuplicateNames{}; std::vector<std::string> PkgsDirsVector; std::vector<std::string> RepoDirsVector; }; diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index 7ee6300..a94ca48 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -254,6 +254,16 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } } + // DisableCommandLineInterface + if (this->GetOption("CPACK_IFW_PACKAGE_DISABLE_COMMAND_LINE_INTERFACE")) { + if (this->IsOn("CPACK_IFW_PACKAGE_DISABLE_COMMAND_LINE_INTERFACE")) { + this->DisableCommandLineInterface = "true"; + } else if (this->IsSetToOff( + "CPACK_IFW_PACKAGE_DISABLE_COMMAND_LINE_INTERFACE")) { + this->DisableCommandLineInterface = "false"; + } + } + // Space in path if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) { if (this->IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) { @@ -275,6 +285,27 @@ void cmCPackIFWInstaller::ConfigureFromOptions() this->Resources.clear(); cmExpandList(optIFW_PACKAGE_RESOURCES, this->Resources); } + + // ProductImages + if (cmValue productImages = + this->GetOption("CPACK_IFW_PACKAGE_PRODUCT_IMAGES")) { + this->ProductImages.clear(); + cmExpandList(productImages, this->ProductImages); + } + + // Run program, run program arguments, and run program description + if (cmValue program = this->GetOption("CPACK_IFW_PACKAGE_RUN_PROGRAM")) { + this->RunProgram = *program; + } + if (cmValue arguments = + this->GetOption("CPACK_IFW_PACKAGE_RUN_PROGRAM_ARGUMENTS")) { + this->RunProgramArguments.clear(); + cmExpandList(arguments, this->RunProgramArguments); + } + if (cmValue description = + this->GetOption("CPACK_IFW_PACKAGE_RUN_PROGRAM_DESCRIPTION")) { + this->RunProgramDescription = *description; + } } /** \class cmCPackIFWResourcesParser @@ -362,29 +393,11 @@ void cmCPackIFWInstaller::GenerateInstallerFile() xout.Element("ProductUrl", this->ProductUrl); } - // ApplicationIcon - if (!this->InstallerApplicationIcon.empty()) { - std::string name = - cmSystemTools::GetFilenameName(this->InstallerApplicationIcon); - std::string path = this->Directory + "/config/" + name; - name = cmSystemTools::GetFilenameWithoutExtension(name); - cmsys::SystemTools::CopyFileIfDifferent(this->InstallerApplicationIcon, - path); - xout.Element("InstallerApplicationIcon", name); - } - - // WindowIcon - if (!this->InstallerWindowIcon.empty()) { - std::string name = - cmSystemTools::GetFilenameName(this->InstallerWindowIcon); - std::string path = this->Directory + "/config/" + name; - cmsys::SystemTools::CopyFileIfDifferent(this->InstallerWindowIcon, path); - xout.Element("InstallerWindowIcon", name); - } - // Logo if (!this->Logo.empty()) { - std::string name = cmSystemTools::GetFilenameName(this->Logo); + std::string srcName = cmSystemTools::GetFilenameName(this->Logo); + std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName); + std::string name = "cm_logo." + suffix; std::string path = this->Directory + "/config/" + name; cmsys::SystemTools::CopyFileIfDifferent(this->Logo, path); xout.Element("Logo", name); @@ -414,42 +427,81 @@ void cmCPackIFWInstaller::GenerateInstallerFile() xout.Element("Background", name); } - // WizardStyle - if (!this->WizardStyle.empty()) { - xout.Element("WizardStyle", this->WizardStyle); - } + // Attributes introduced in QtIFW 1.4.0 + if (!this->IsVersionLess("1.4")) { + // ApplicationIcon + if (!this->InstallerApplicationIcon.empty()) { + std::string srcName = + cmSystemTools::GetFilenameName(this->InstallerApplicationIcon); + std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName); + std::string name = "cm_appicon." + suffix; + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->InstallerApplicationIcon, + path); + // The actual file is looked up by attaching a '.icns' (macOS), + // '.ico' (Windows). No functionality on Unix. + name = cmSystemTools::GetFilenameWithoutExtension(name); + xout.Element("InstallerApplicationIcon", name); + } - // Stylesheet - if (!this->StyleSheet.empty()) { - std::string name = cmSystemTools::GetFilenameName(this->StyleSheet); - std::string path = this->Directory + "/config/" + name; - cmsys::SystemTools::CopyFileIfDifferent(this->StyleSheet, path); - xout.Element("StyleSheet", name); + // WindowIcon + if (!this->InstallerWindowIcon.empty()) { + std::string srcName = + cmSystemTools::GetFilenameName(this->InstallerWindowIcon); + std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName); + std::string name = "cm_winicon." + suffix; + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->InstallerWindowIcon, path); + xout.Element("InstallerWindowIcon", name); + } } - // WizardDefaultWidth - if (!this->WizardDefaultWidth.empty()) { - xout.Element("WizardDefaultWidth", this->WizardDefaultWidth); - } + // Attributes introduced in QtIFW 2.0.0 + if (!this->IsVersionLess("2.0")) { + // WizardDefaultWidth + if (!this->WizardDefaultWidth.empty()) { + xout.Element("WizardDefaultWidth", this->WizardDefaultWidth); + } - // WizardDefaultHeight - if (!this->WizardDefaultHeight.empty()) { - xout.Element("WizardDefaultHeight", this->WizardDefaultHeight); - } + // WizardDefaultHeight + if (!this->WizardDefaultHeight.empty()) { + xout.Element("WizardDefaultHeight", this->WizardDefaultHeight); + } - // WizardShowPageList - if (!this->IsVersionLess("4.0") && !this->WizardShowPageList.empty()) { - xout.Element("WizardShowPageList", this->WizardShowPageList); - } + // Start menu directory + if (!this->StartMenuDir.empty()) { + xout.Element("StartMenuDir", this->StartMenuDir); + } - // TitleColor - if (!this->TitleColor.empty()) { - xout.Element("TitleColor", this->TitleColor); - } + // Maintenance tool + if (!this->MaintenanceToolName.empty()) { + xout.Element("MaintenanceToolName", this->MaintenanceToolName); + } - // Start menu - if (!this->IsVersionLess("2.0")) { - xout.Element("StartMenuDir", this->StartMenuDir); + // Maintenance tool ini file + if (!this->MaintenanceToolIniFile.empty()) { + xout.Element("MaintenanceToolIniFile", this->MaintenanceToolIniFile); + } + + if (!this->AllowNonAsciiCharacters.empty()) { + xout.Element("AllowNonAsciiCharacters", this->AllowNonAsciiCharacters); + } + if (!this->AllowSpaceInPath.empty()) { + xout.Element("AllowSpaceInPath", this->AllowSpaceInPath); + } + + // Control script (copy to config dir) + if (!this->ControlScript.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->ControlScript); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->ControlScript, path); + xout.Element("ControlScript", name); + } + } else { + // CPack IFW default policy + xout.Comment("CPack IFW default policy for QtIFW less 2.0"); + xout.Element("AllowNonAsciiCharacters", "true"); + xout.Element("AllowSpaceInPath", "true"); } // Target dir @@ -471,41 +523,74 @@ void cmCPackIFWInstaller::GenerateInstallerFile() xout.EndElement(); } - // Maintenance tool - if (!this->IsVersionLess("2.0") && !this->MaintenanceToolName.empty()) { - xout.Element("MaintenanceToolName", this->MaintenanceToolName); + // Attributes introduced in QtIFW 3.0.0 + if (!this->IsVersionLess("3.0")) { + // WizardStyle + if (!this->WizardStyle.empty()) { + xout.Element("WizardStyle", this->WizardStyle); + } + + // Stylesheet (copy to config dir) + if (!this->StyleSheet.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->StyleSheet); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->StyleSheet, path); + xout.Element("StyleSheet", name); + } + + // TitleColor + if (!this->TitleColor.empty()) { + xout.Element("TitleColor", this->TitleColor); + } } - // Maintenance tool ini file - if (!this->IsVersionLess("2.0") && !this->MaintenanceToolIniFile.empty()) { - xout.Element("MaintenanceToolIniFile", this->MaintenanceToolIniFile); + // Attributes introduced in QtIFW 4.0.0 + if (!this->IsVersionLess("4.0")) { + // WizardShowPageList + if (!this->WizardShowPageList.empty()) { + xout.Element("WizardShowPageList", this->WizardShowPageList); + } + + // DisableCommandLineInterface + if (!this->DisableCommandLineInterface.empty()) { + xout.Element("DisableCommandLineInterface", + this->DisableCommandLineInterface); + } + + // RunProgram + if (!this->RunProgram.empty()) { + xout.Element("RunProgram", this->RunProgram); + } + + // RunProgramArguments + if (!this->RunProgramArguments.empty()) { + xout.StartElement("RunProgramArguments"); + for (const auto& arg : this->RunProgramArguments) { + xout.Element("Argument", arg); + } + xout.EndElement(); + } + + // RunProgramDescription + if (!this->RunProgramDescription.empty()) { + xout.Element("RunProgramDescription", this->RunProgramDescription); + } } if (!this->RemoveTargetDir.empty()) { xout.Element("RemoveTargetDir", this->RemoveTargetDir); } - // Different allows - if (this->IsVersionLess("2.0")) { - // CPack IFW default policy - xout.Comment("CPack IFW default policy for QtIFW less 2.0"); - xout.Element("AllowNonAsciiCharacters", "true"); - xout.Element("AllowSpaceInPath", "true"); - } else { - if (!this->AllowNonAsciiCharacters.empty()) { - xout.Element("AllowNonAsciiCharacters", this->AllowNonAsciiCharacters); - } - if (!this->AllowSpaceInPath.empty()) { - xout.Element("AllowSpaceInPath", this->AllowSpaceInPath); + // Product images (copy to config dir) + if (!this->IsVersionLess("4.0") && !this->ProductImages.empty()) { + xout.StartElement("ProductImages"); + for (auto const& srcImg : this->ProductImages) { + std::string name = cmSystemTools::GetFilenameName(srcImg); + std::string dstImg = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(srcImg, dstImg); + xout.Element("Image", name); } - } - - // Control script (copy to config dir) - if (!this->IsVersionLess("2.0") && !this->ControlScript.empty()) { - std::string name = cmSystemTools::GetFilenameName(this->ControlScript); - std::string path = this->Directory + "/config/" + name; - cmsys::SystemTools::CopyFileIfDifferent(this->ControlScript, path); - xout.Element("ControlScript", name); + xout.EndElement(); } // Resources (copy to resources dir) diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h index a031fc2..0ace099 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.h +++ b/Source/CPack/IFW/cmCPackIFWInstaller.h @@ -109,6 +109,9 @@ public: /// uninstalling std::string RemoveTargetDir; + /// Set to true if command line interface features should be disabled + std::string DisableCommandLineInterface; + /// Set to false if the installation path cannot contain space characters std::string AllowSpaceInPath; @@ -118,6 +121,20 @@ public: /// List of resources to include in the installer binary std::vector<std::string> Resources; + /// A list of images to be shown on PerformInstallationPage. + std::vector<std::string> ProductImages; + + /// Command executed after the installer is done if the user accepts the + /// action + std::string RunProgram; + + /// Arguments passed to the program specified in <RunProgram> + std::vector<std::string> RunProgramArguments; + + /// Text shown next to the check box for running the program after the + /// installation + std::string RunProgramDescription; + public: // Internal implementation diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h index 0cc6f2f..350f6b2 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.h +++ b/Source/CPack/IFW/cmCPackIFWPackage.h @@ -44,7 +44,7 @@ public: struct DependenceStruct { DependenceStruct(); - DependenceStruct(const std::string& dependence); + explicit DependenceStruct(const std::string& dependence); std::string Name; CompareStruct Compare; diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx deleted file mode 100644 index b7140ab..0000000 --- a/Source/CPack/OSXScriptLauncher.cxx +++ /dev/null @@ -1,122 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include <cstddef> -#include <iostream> -#include <string> -#include <vector> - -#include <cm/memory> - -#include <CoreFoundation/CoreFoundation.h> - -#include "cmsys/FStream.hxx" -#include "cmsys/Process.h" -#include "cmsys/SystemTools.hxx" - -// For the PATH_MAX constant -#include <sys/syslimits.h> - -#define DebugError(x) \ - ofs << x << std::endl; \ - std::cout << x << std::endl - -int main(int argc, char* argv[]) -{ - // if ( cmsys::SystemTools::FileExists( - cmsys::ofstream ofs("/tmp/output.txt"); - - CFStringRef fileName; - CFBundleRef appBundle; - CFURLRef scriptFileURL; - - // get CF URL for script - if (!(appBundle = CFBundleGetMainBundle())) { - DebugError("Cannot get main bundle"); - return 1; - } - fileName = CFSTR("RuntimeScript"); - if (!(scriptFileURL = - CFBundleCopyResourceURL(appBundle, fileName, nullptr, nullptr))) { - DebugError("CFBundleCopyResourceURL failed"); - return 1; - } - - // create path string - 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.get(), - PATH_MAX)) { - DebugError("CFURLGetFileSystemRepresentation failed"); - return 1; - } - - // dispose of the CF variable - CFRelease(scriptFileURL); - - std::string fullScriptPath = reinterpret_cast<char*>(path.get()); - path.reset(); - - if (!cmsys::SystemTools::FileExists(fullScriptPath)) { - return 1; - } - - std::string scriptDirectory = - cmsys::SystemTools::GetFilenamePath(fullScriptPath); - ofs << fullScriptPath << std::endl; - std::vector<const char*> args; - args.push_back(fullScriptPath.c_str()); - int cc; - for (cc = 1; cc < argc; ++cc) { - args.push_back(argv[cc]); - } - args.push_back(nullptr); - - cmsysProcess* cp = cmsysProcess_New(); - cmsysProcess_SetCommand(cp, args.data()); - cmsysProcess_SetWorkingDirectory(cp, scriptDirectory.c_str()); - cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); - cmsysProcess_SetTimeout(cp, 0); - cmsysProcess_Execute(cp); - - char* data; - int length; - while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) { - // Translate NULL characters in the output into valid text. - for (int i = 0; i < length; ++i) { - if (data[i] == '\0') { - data[i] = ' '; - } - } - std::cout.write(data, length); - } - - cmsysProcess_WaitForExit(cp, nullptr); - - bool result = true; - if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) { - if (cmsysProcess_GetExitValue(cp) != 0) { - result = false; - } - } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) { - const char* exception_str = cmsysProcess_GetExceptionString(cp); - std::cerr << exception_str << std::endl; - result = false; - } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) { - const char* error_str = cmsysProcess_GetErrorString(cp); - std::cerr << error_str << std::endl; - result = false; - } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) { - const char* error_str = "Process terminated due to timeout\n"; - std::cerr << error_str << std::endl; - result = false; - } - - cmsysProcess_Delete(cp); - - return !result; -} diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index d03239b..6a0095b 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -219,7 +219,9 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() CollectExtensions("CPACK_WIX_EXTENSIONS", this->CandleExtensions); CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", this->CandleExtensions); - this->LightExtensions.insert("WixUIExtension"); + if (!cmIsOn(GetOption("CPACK_WIX_SKIP_WIX_UI_EXTENSION"))) { + this->LightExtensions.insert("WixUIExtension"); + } CollectExtensions("CPACK_WIX_EXTENSIONS", this->LightExtensions); CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions); CollectXmlNamespaces("CPACK_WIX_CUSTOM_XMLNS", this->CustomXmlNamespaces); diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h index 58377d4..6a47b6d 100644 --- a/Source/CPack/cmCPackComponentGroup.h +++ b/Source/CPack/cmCPackComponentGroup.h @@ -35,12 +35,10 @@ class cmCPackComponent { public: cmCPackComponent() - : Group(nullptr) - , IsRequired(true) + : IsRequired(true) , IsHidden(false) , IsDisabledByDefault(false) , IsDownloaded(false) - , TotalSize(0) { } @@ -51,7 +49,7 @@ public: std::string DisplayName; /// The component group that contains this component (if any). - cmCPackComponentGroup* Group; + cmCPackComponentGroup* Group = nullptr; /// Whether this component group must always be installed. bool IsRequired : 1; @@ -103,7 +101,7 @@ public: unsigned long GetInstalledSizeInKbytes(const std::string& installDir) const; private: - mutable unsigned long TotalSize; + mutable unsigned long TotalSize = 0; }; /** \class cmCPackComponentGroup @@ -113,7 +111,8 @@ class cmCPackComponentGroup { public: cmCPackComponentGroup() - : ParentGroup(nullptr) + : IsBold(false) + , IsExpandedByDefault(false) { } @@ -136,7 +135,7 @@ public: std::vector<cmCPackComponent*> Components; /// The parent group of this component group (if any). - cmCPackComponentGroup* ParentGroup; + cmCPackComponentGroup* ParentGroup = nullptr; /// The subgroups of this group. std::vector<cmCPackComponentGroup*> Subgroups; diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx index 484db00..fabf4c5 100644 --- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx +++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx @@ -17,9 +17,7 @@ cmCPackCygwinBinaryGenerator::cmCPackCygwinBinaryGenerator() { } -cmCPackCygwinBinaryGenerator::~cmCPackCygwinBinaryGenerator() -{ -} +cmCPackCygwinBinaryGenerator::~cmCPackCygwinBinaryGenerator() = default; int cmCPackCygwinBinaryGenerator::InitializeInternal() { @@ -43,7 +41,7 @@ int cmCPackCygwinBinaryGenerator::PackageFiles() // create an extra scope to force the stream // to create the file before the super class is called { - cmGeneratedFileStream ofs(manifestFile.c_str()); + cmGeneratedFileStream ofs(manifestFile); for (std::string const& file : files) { // remove the temp dir and replace with /usr ofs << file.substr(tempdir.size()) << "\n"; diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.h b/Source/CPack/cmCPackCygwinBinaryGenerator.h index f5f7700..ca8e0b5 100644 --- a/Source/CPack/cmCPackCygwinBinaryGenerator.h +++ b/Source/CPack/cmCPackCygwinBinaryGenerator.h @@ -19,8 +19,8 @@ public: ~cmCPackCygwinBinaryGenerator() override; protected: - virtual int InitializeInternal(); - int PackageFiles(); - virtual const char* GetOutputExtension(); + int InitializeInternal() override; + int PackageFiles() override; + const char* GetOutputExtension() override; std::string OutputExtension; }; diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx index 59df380..a5863ff 100644 --- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx +++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx @@ -26,9 +26,7 @@ cmCPackCygwinSourceGenerator::cmCPackCygwinSourceGenerator() { } -cmCPackCygwinSourceGenerator::~cmCPackCygwinSourceGenerator() -{ -} +cmCPackCygwinSourceGenerator::~cmCPackCygwinSourceGenerator() = default; int cmCPackCygwinSourceGenerator::InitializeInternal() { @@ -50,7 +48,7 @@ int cmCPackCygwinSourceGenerator::PackageFiles() // Now create a tar file that contains the above .tar.bz2 file // and the CPACK_CYGWIN_PATCH_FILE and CPACK_TOPLEVEL_DIRECTORY // files - std::string compressOutFile = packageDirFileName; + const std::string& compressOutFile = packageDirFileName; // at this point compressOutFile is the full path to // _CPack_Package/.../package-2.5.0.tar.bz2 // we want to create a tar _CPack_Package/.../package-2.5.0-1-src.tar.bz2 diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.h b/Source/CPack/cmCPackCygwinSourceGenerator.h index 964a4d4..2207bde 100644 --- a/Source/CPack/cmCPackCygwinSourceGenerator.h +++ b/Source/CPack/cmCPackCygwinSourceGenerator.h @@ -19,10 +19,10 @@ public: ~cmCPackCygwinSourceGenerator() override; protected: - const char* GetPackagingInstallPrefix(); - virtual int InitializeInternal(); - int PackageFiles(); - virtual const char* GetOutputExtension(); + const char* GetPackagingInstallPrefix() override; + int InitializeInternal() override; + int PackageFiles() override; + const char* GetOutputExtension() override; std::string InstallPrefix; std::string OutputExtension; }; diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index d7aa287..8e5e637 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -203,7 +203,7 @@ bool DebGenerator::generateDataTar() const // uid/gid should be the one of the root user, and this root user has // always uid/gid equal to 0. - data_tar.SetUIDAndGID(0u, 0u); + data_tar.SetUIDAndGID(0U, 0U); data_tar.SetUNAMEAndGNAME("root", "root"); // now add all directories which have to be compressed @@ -902,7 +902,7 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix( } if (this->componentPackageMethod == ONE_PACKAGE) { - return std::string("ALL_COMPONENTS_IN_ONE"); + return { "ALL_COMPONENTS_IN_ONE" }; } // We have to find the name of the COMPONENT GROUP // the current COMPONENT belongs to. diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h index 61a6616..11561a4 100644 --- a/Source/CPack/cmCPackDebGenerator.h +++ b/Source/CPack/cmCPackDebGenerator.h @@ -29,9 +29,9 @@ public: #ifdef __APPLE__ // on MacOS enable CPackDeb iff dpkg is found std::vector<std::string> locations; - locations.push_back("/sw/bin"); // Fink - locations.push_back("/opt/local/bin"); // MacPorts - return cmSystemTools::FindProgram("dpkg", locations) != "" ? true : false; + locations.emplace_back("/sw/bin"); // Fink + locations.emplace_back("/opt/local/bin"); // MacPorts + return !cmSystemTools::FindProgram("dpkg", locations).empty(); #else // legacy behavior on other systems return true; diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h index 310b0ab..6d1267b 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.h +++ b/Source/CPack/cmCPackDragNDropGenerator.h @@ -4,12 +4,11 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <sstream> #include <string> #include <vector> -#include <stddef.h> - #include "cmCPackGenerator.h" class cmGeneratedFileStream; @@ -34,7 +33,7 @@ protected: bool CopyFile(std::ostringstream& source, std::ostringstream& target); bool CreateEmptyFile(std::ostringstream& target, size_t size); - bool RunCommand(std::ostringstream& command, std::string* output = 0); + bool RunCommand(std::ostringstream& command, std::string* output = nullptr); std::string GetComponentInstallDirNameSuffix( const std::string& componentName) override; diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index 30b6b0d..fcd5753 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -205,7 +205,7 @@ std::string cmCPackFreeBSDGenerator::var_lookup(const char* var_name) { cmValue pv = this->GetOption(var_name); if (!pv) { - return std::string(); + return {}; } return *pv; } diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 2f700b4..7ddb103 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -186,7 +186,7 @@ int cmCPackGenerator::InstallProject() std::string bareTempInstallDirectory = this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY"); std::string tempInstallDirectoryStr = bareTempInstallDirectory; - bool setDestDir = cmIsOn(this->GetOption("CPACK_SET_DESTDIR")) | + bool setDestDir = cmIsOn(this->GetOption("CPACK_SET_DESTDIR")) || cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR")); if (!setDestDir) { tempInstallDirectoryStr += this->GetPackagingInstallPrefix(); diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index 79e344b..0b2acca 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -21,7 +21,6 @@ #ifdef __APPLE__ # include "cmCPackBundleGenerator.h" # include "cmCPackDragNDropGenerator.h" -# include "cmCPackOSXX11Generator.h" # include "cmCPackPackageMakerGenerator.h" # include "cmCPackProductBuildGenerator.h" #endif @@ -113,10 +112,6 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("PackageMaker", "Mac OSX Package Maker installer", cmCPackPackageMakerGenerator::CreateGenerator); } - if (cmCPackOSXX11Generator::CanGenerate()) { - this->RegisterGenerator("OSXX11", "Mac OSX X11 bundle", - cmCPackOSXX11Generator::CreateGenerator); - } if (cmCPackProductBuildGenerator::CanGenerate()) { this->RegisterGenerator("productbuild", "Mac OSX pkg", cmCPackProductBuildGenerator::CreateGenerator); diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h index 0846573..f3e25a6 100644 --- a/Source/CPack/cmCPackGeneratorFactory.h +++ b/Source/CPack/cmCPackGeneratorFactory.h @@ -41,5 +41,5 @@ private: using t_GeneratorCreatorsMap = std::map<std::string, CreateGeneratorCall*>; t_GeneratorCreatorsMap GeneratorCreators; DescriptionsMap GeneratorDescriptions; - cmCPackLog* Logger; + cmCPackLog* Logger{}; }; diff --git a/Source/CPack/cmCPackLog.h b/Source/CPack/cmCPackLog.h index 6cec39c..2ab2f8e 100644 --- a/Source/CPack/cmCPackLog.h +++ b/Source/CPack/cmCPackLog.h @@ -4,12 +4,11 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstring> #include <memory> #include <ostream> #include <string> -#include <string.h> - #define cmCPack_Log(ctSelf, logType, msg) \ do { \ std::ostringstream cmCPackLog_msg; \ @@ -129,7 +128,7 @@ public: } const char* Data; - size_t Length; + std::streamsize Length; }; inline std::ostream& operator<<(std::ostream& os, const cmCPackLogWrite& c) diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index ecc5e08..217f716 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -883,7 +883,7 @@ std::string cmCPackNSISGenerator::CreateSelectionDependenciesDescription( { // Don't visit a component twice if (visited.count(component)) { - return std::string(); + return {}; } visited.insert(component); @@ -907,7 +907,7 @@ std::string cmCPackNSISGenerator::CreateDeselectionDependenciesDescription( { // Don't visit a component twice if (visited.count(component)) { - return std::string(); + return {}; } visited.insert(component); @@ -933,7 +933,7 @@ std::string cmCPackNSISGenerator::CreateComponentGroupDescription( { if (group->Components.empty() && group->Subgroups.empty()) { // Silently skip empty groups. NSIS doesn't support them. - return std::string(); + return {}; } std::string code = "SectionGroup "; diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx deleted file mode 100644 index 7bf1dc7..0000000 --- a/Source/CPack/cmCPackOSXX11Generator.cxx +++ /dev/null @@ -1,272 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmCPackOSXX11Generator.h" - -#include <sstream> - -#include "cm_sys_stat.h" - -#include "cmCPackGenerator.h" -#include "cmCPackLog.h" -#include "cmDuration.h" -#include "cmGeneratedFileStream.h" -#include "cmStringAlgorithms.h" -#include "cmSystemTools.h" -#include "cmValue.h" - -cmCPackOSXX11Generator::cmCPackOSXX11Generator() = default; - -cmCPackOSXX11Generator::~cmCPackOSXX11Generator() = default; - -int cmCPackOSXX11Generator::PackageFiles() -{ - // TODO: Use toplevel ? - // It is used! Is this an obsolete comment? - - cmValue cpackPackageExecutables = - this->GetOption("CPACK_PACKAGE_EXECUTABLES"); - if (cpackPackageExecutables) { - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "The cpackPackageExecutables: " << cpackPackageExecutables - << "." << std::endl); - std::ostringstream str; - std::ostringstream deleteStr; - std::vector<std::string> cpackPackageExecutablesVector = - cmExpandedList(cpackPackageExecutables); - if (cpackPackageExecutablesVector.size() % 2 != 0) { - cmCPackLogger( - cmCPackLog::LOG_ERROR, - "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and " - "<icon name>." - << std::endl); - return 0; - } - std::vector<std::string>::iterator it; - for (it = cpackPackageExecutablesVector.begin(); - it != cpackPackageExecutablesVector.end(); ++it) { - std::string cpackExecutableName = *it; - ++it; - this->SetOptionIfNotSet("CPACK_EXECUTABLE_NAME", cpackExecutableName); - } - } - - // Disk image directories - std::string diskImageDirectory = toplevel; - std::string diskImageBackgroundImageDir = - diskImageDirectory + "/.background"; - - // App bundle directories - std::string packageDirFileName = cmStrCat( - toplevel, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".app"); - std::string contentsDirectory = packageDirFileName + "/Contents"; - std::string resourcesDirectory = contentsDirectory + "/Resources"; - std::string appDirectory = contentsDirectory + "/MacOS"; - std::string scriptDirectory = resourcesDirectory + "/Scripts"; - std::string resourceFileName = - cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".rsrc"); - - const char* dir = resourcesDirectory.c_str(); - const char* appdir = appDirectory.c_str(); - const char* scrDir = scriptDirectory.c_str(); - const char* contDir = contentsDirectory.c_str(); - const char* rsrcFile = resourceFileName.c_str(); - cmValue iconFile = this->GetOption("CPACK_PACKAGE_ICON"); - if (iconFile) { - std::string iconFileName = cmsys::SystemTools::GetFilenameName(iconFile); - if (!cmSystemTools::FileExists(iconFile)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find icon file: " - << iconFile - << ". Please check CPACK_PACKAGE_ICON setting." - << std::endl); - return 0; - } - std::string destFileName = resourcesDirectory + "/" + iconFileName; - this->ConfigureFile(iconFile, destFileName, true); - this->SetOptionIfNotSet("CPACK_APPLE_GUI_ICON", iconFileName); - } - - std::string applicationsLinkName = diskImageDirectory + "/Applications"; - cmSystemTools::CreateSymlink("/Applications", applicationsLinkName); - - if (!this->CopyResourcePlistFile("VolumeIcon.icns", diskImageDirectory, - ".VolumeIcon.icns", true) || - !this->CopyResourcePlistFile("DS_Store", diskImageDirectory, ".DS_Store", - true) || - !this->CopyResourcePlistFile("background.png", - diskImageBackgroundImageDir, - "background.png", true) || - !this->CopyResourcePlistFile("RuntimeScript", dir) || - !this->CopyResourcePlistFile("OSXX11.Info.plist", contDir, - "Info.plist") || - !this->CopyResourcePlistFile("OSXX11.main.scpt", scrDir, "main.scpt", - true) || - !this->CopyResourcePlistFile("OSXScriptLauncher.rsrc", dir, rsrcFile, - true) || - !this->CopyResourcePlistFile( - "OSXScriptLauncher", appdir, - this->GetOption("CPACK_PACKAGE_FILE_NAME").GetCStr(), true)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem copying the resource files" << std::endl); - return 0; - } - - // Two of the files need to have execute permission, so ensure they do: - std::string runTimeScript = cmStrCat(dir, "/RuntimeScript"); - - std::string appScriptName = - cmStrCat(appdir, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME")); - - mode_t mode; - if (cmsys::SystemTools::GetPermissions(runTimeScript.c_str(), mode)) { - mode |= (S_IXUSR | S_IXGRP | S_IXOTH); - cmsys::SystemTools::SetPermissions(runTimeScript.c_str(), mode); - cmCPackLogger(cmCPackLog::LOG_OUTPUT, - "Setting: " << runTimeScript << " to permission: " << mode - << std::endl); - } - - if (cmsys::SystemTools::GetPermissions(appScriptName.c_str(), mode)) { - mode |= (S_IXUSR | S_IXGRP | S_IXOTH); - cmsys::SystemTools::SetPermissions(appScriptName.c_str(), mode); - cmCPackLogger(cmCPackLog::LOG_OUTPUT, - "Setting: " << appScriptName << " to permission: " << mode - << std::endl); - } - - std::string output; - std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), - "/hdiutilOutput.log"); - std::ostringstream dmgCmd; - dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE") - << "\" create -ov -fs HFS+ -format UDZO -srcfolder \"" - << diskImageDirectory << "\" \"" << packageFileNames[0] << "\""; - cmCPackLogger(cmCPackLog::LOG_VERBOSE, - "Compress disk image using command: " << dmgCmd.str() - << std::endl); - // since we get random dashboard failures with this one - // try running it more than once - int retVal = 1; - int numTries = 10; - bool res = false; - while (numTries > 0) { - res = cmSystemTools::RunSingleCommand( - dmgCmd.str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose, - cmDuration::zero()); - if (res && !retVal) { - numTries = -1; - break; - } - cmSystemTools::Delay(500); - numTries--; - } - if (!res || retVal) { - cmGeneratedFileStream ofs(tmpFile); - ofs << "# Run command: " << dmgCmd.str() << std::endl - << "# Output:" << std::endl - << output << std::endl; - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem running hdiutil command: " - << dmgCmd.str() << std::endl - << "Please check " << tmpFile << " for errors" - << std::endl); - return 0; - } - - return 1; -} - -int cmCPackOSXX11Generator::InitializeInternal() -{ - cmCPackLogger(cmCPackLog::LOG_WARNING, - "The OSXX11 generator is deprecated " - "and will be removed in a future version.\n"); - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "cmCPackOSXX11Generator::Initialize()" << std::endl); - std::vector<std::string> path; - std::string pkgPath = cmSystemTools::FindProgram("hdiutil", path, false); - if (pkgPath.empty()) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find hdiutil compiler" << std::endl); - return 0; - } - this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE", pkgPath); - - return this->Superclass::InitializeInternal(); -} - -/* -bool cmCPackOSXX11Generator::CopyCreateResourceFile(const std::string& name) -{ - std::string uname = cmSystemTools::UpperCase(name); - std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname; - const char* inFileName = this->GetOption(cpackVar.c_str()); - if ( !inFileName ) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack option: " << cpackVar.c_str() - << " not specified. It should point to " - << (name ? name : "(NULL)") - << ".rtf, " << name - << ".html, or " << name << ".txt file" << std::endl); - return false; - } - if ( !cmSystemTools::FileExists(inFileName) ) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find " - << (name ? name : "(NULL)") - << " resource file: " << inFileName << std::endl); - return false; - } - std::string ext = cmSystemTools::GetFilenameLastExtension(inFileName); - if ( ext != ".rtfd" && ext != ".rtf" && ext != ".html" && ext != ".txt" ) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, "Bad file extension specified: " - << ext << ". Currently only .rtfd, .rtf, .html, and .txt files allowed." - << std::endl); - return false; - } - - std::string destFileName = cmStrCat( -this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources/", name, ext ); - - - cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: " - << (inFileName ? inFileName : "(NULL)") - << " to " << destFileName << std::endl); - this->ConfigureFile(inFileName, destFileName); - return true; -} -*/ - -bool cmCPackOSXX11Generator::CopyResourcePlistFile( - const std::string& name, const std::string& dir, - const char* outputFileName /* = 0 */, bool copyOnly /* = false */) -{ - std::string inFName = cmStrCat("CPack.", name, ".in"); - std::string inFileName = this->FindTemplate(inFName.c_str()); - if (inFileName.empty()) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find input file: " << inFName << std::endl); - return false; - } - - if (!outputFileName) { - outputFileName = name.c_str(); - } - - std::string destFileName = cmStrCat(dir, '/', outputFileName); - - cmCPackLogger(cmCPackLog::LOG_VERBOSE, - "Configure file: " << inFileName << " to " << destFileName - << std::endl); - this->ConfigureFile(inFileName, destFileName, copyOnly); - return true; -} - -const char* cmCPackOSXX11Generator::GetPackagingInstallPrefix() -{ - this->InstallPrefix = - cmStrCat('/', this->GetOption("CPACK_PACKAGE_FILE_NAME"), - ".app/Contents/Resources"); - return this->InstallPrefix.c_str(); -} diff --git a/Source/CPack/cmCPackOSXX11Generator.h b/Source/CPack/cmCPackOSXX11Generator.h deleted file mode 100644 index 8fae136..0000000 --- a/Source/CPack/cmCPackOSXX11Generator.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#pragma once - -#include "cmConfigure.h" // IWYU pragma: keep - -#include <string> - -#include "cmCPackGenerator.h" - -/** \class cmCPackOSXX11Generator - * \brief A generator for OSX X11 modules - * - * Based on Gimp.app - */ -class cmCPackOSXX11Generator : public cmCPackGenerator -{ -public: - cmCPackTypeMacro(cmCPackOSXX11Generator, cmCPackGenerator); - - /** - * Construct generator - */ - cmCPackOSXX11Generator(); - ~cmCPackOSXX11Generator() override; - -protected: - virtual int InitializeInternal() override; - int PackageFiles() override; - const char* GetPackagingInstallPrefix() override; - const char* GetOutputExtension() override { return ".dmg"; } - - // bool CopyCreateResourceFile(const std::string& name, - // const std::string& dir); - bool CopyResourcePlistFile(const std::string& name, const std::string& dir, - const char* outputFileName = 0, - bool copyOnly = false); - std::string InstallPrefix; -}; diff --git a/Source/CPack/cmCPackPKGGenerator.h b/Source/CPack/cmCPackPKGGenerator.h index 17cdcdf..5d97d16 100644 --- a/Source/CPack/cmCPackPKGGenerator.h +++ b/Source/CPack/cmCPackPKGGenerator.h @@ -43,7 +43,8 @@ protected: // which will be configured via ConfigureFile. bool CopyCreateResourceFile(const std::string& name, const std::string& dirName); - bool CopyResourcePlistFile(const std::string& name, const char* outName = 0); + bool CopyResourcePlistFile(const std::string& name, + const char* outName = nullptr); int CopyInstallScript(const std::string& resdir, const std::string& script, const std::string& name); diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index 9e50700..3d4d05e 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -329,9 +329,10 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup) if (retval) { this->AddGeneratedPackageNames(); + return retval; } - return retval; + return 0; } int cmCPackRPMGenerator::PackageComponentsAllInOne( @@ -424,7 +425,7 @@ std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix( } if (this->componentPackageMethod == ONE_PACKAGE) { - return std::string("ALL_COMPONENTS_IN_ONE"); + return { "ALL_COMPONENTS_IN_ONE" }; } // We have to find the name of the COMPONENT GROUP // the current COMPONENT belongs to. diff --git a/Source/CPack/cmCPackRPMGenerator.h b/Source/CPack/cmCPackRPMGenerator.h index 0288f2f..886afb1 100644 --- a/Source/CPack/cmCPackRPMGenerator.h +++ b/Source/CPack/cmCPackRPMGenerator.h @@ -32,9 +32,9 @@ public: #ifdef __APPLE__ // on MacOS enable CPackRPM iff rpmbuild is found std::vector<std::string> locations; - locations.push_back("/sw/bin"); // Fink - locations.push_back("/opt/local/bin"); // MacPorts - return cmSystemTools::FindProgram("rpmbuild") != "" ? true : false; + locations.emplace_back("/sw/bin"); // Fink + locations.emplace_back("/opt/local/bin"); // MacPorts + return !cmSystemTools::FindProgram("rpmbuild").empty(); #else // legacy behavior on other systems return true; diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index 1340fb5..6ad3755 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -107,7 +107,7 @@ int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os) cmCPackLogger(cmCPackLog::LOG_DEBUG, "Number of lines: " << counter << std::endl); char buffer[1024]; - sprintf(buffer, "%d", counter); + snprintf(buffer, sizeof(buffer), "%d", counter); cmSystemTools::ReplaceString(res, headerLengthTag, buffer); // Write in file diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 54fd358..f43642f 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -67,7 +67,7 @@ struct cpackDefinitions { using MapType = std::map<std::string, std::string>; MapType Map; - cmCPackLog* Log; + cmCPackLog* Log{}; }; int cpackDefinitionArgument(const char* argument, const char* cValue, diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index a353435..0fe4ff4 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -20,9 +20,9 @@ #include "cmSystemTools.h" #include "cmXMLParser.h" -extern "C" int cmBZRXMLParserUnknownEncodingHandler(void* /*unused*/, - const XML_Char* name, - XML_Encoding* info) +static int cmBZRXMLParserUnknownEncodingHandler(void* /*unused*/, + const XML_Char* name, + XML_Encoding* info) { static const int latin1[] = { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h index b9cc35c..e022e68 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.h +++ b/Source/CTest/cmCTestBuildAndTestHandler.h @@ -4,12 +4,11 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <sstream> #include <string> #include <vector> -#include <stddef.h> - #include "cmCTestGenericHandler.h" #include "cmDuration.h" diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index f9c4a8e..2aba79d 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -81,6 +81,7 @@ static const char* cmCTestErrorMatches[] = { "^The project cannot be built\\.", "^\\[ERROR\\]", "^Command .* failed with exit code", + "lcc: \"([^\"]+)\", (line|строка) ([0-9]+): (error|ошибка)", nullptr }; @@ -122,6 +123,7 @@ static const char* cmCTestWarningMatches[] = { "cc-[0-9]* CC: REMARK File = .*, Line = [0-9]*", "^CMake Warning.*:", "^\\[WARNING\\]", + "lcc: \"([^\"]+)\", (line|строка) ([0-9]+): (warning|предупреждение)", nullptr }; @@ -160,6 +162,9 @@ static cmCTestBuildCompileErrorWarningRex cmCTestWarningErrorFileLine[] = { { "^([a-zA-Z./0-9_+ ~-]+)\\(([0-9]+)\\)", 1, 2 }, { "\"([a-zA-Z./0-9_+ ~-]+)\", line ([0-9]+)", 1, 2 }, { "File = ([a-zA-Z./0-9_+ ~-]+), Line = ([0-9]+)", 1, 2 }, + { "lcc: \"([^\"]+)\", (line|строка) ([0-9]+): " + "(error|ошибка|warning|предупреждение)", + 1, 3 }, { nullptr, 0, 0 } }; diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h index 58e8d9c..e33294d 100644 --- a/Source/CTest/cmCTestBuildHandler.h +++ b/Source/CTest/cmCTestBuildHandler.h @@ -5,13 +5,12 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <chrono> +#include <cstddef> #include <deque> #include <iosfwd> #include <string> #include <vector> -#include <stddef.h> - #include "cmsys/RegularExpression.hxx" #include "cmCTestGenericHandler.h" diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 57b1dda..1b2f769 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -49,9 +49,8 @@ public: } ~cmCTestRunProcess() { - if (!(this->PipeState == -1) && - !(this->PipeState == cmsysProcess_Pipe_None) && - !(this->PipeState == cmsysProcess_Pipe_Timeout)) { + if (this->PipeState != -1 && this->PipeState != cmsysProcess_Pipe_None && + this->PipeState != cmsysProcess_Pipe_Timeout) { this->WaitForExit(); } cmsysProcess_Delete(this->Process); @@ -148,7 +147,8 @@ bool cmCTestCoverageHandler::StartCoverageLogFile( cmGeneratedFileStream& covLogFile, int logFileCount) { char covLogFilename[1024]; - sprintf(covLogFilename, "CoverageLog-%d", logFileCount); + snprintf(covLogFilename, sizeof(covLogFilename), "CoverageLog-%d", + logFileCount); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Open file: " << covLogFilename << std::endl, this->Quiet); @@ -165,7 +165,8 @@ void cmCTestCoverageHandler::EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount) { char covLogFilename[1024]; - sprintf(covLogFilename, "CoverageLog-%d.xml", logFileCount); + snprintf(covLogFilename, sizeof(covLogFilename), "CoverageLog-%d.xml", + logFileCount); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Close file: " << covLogFilename << std::endl, this->Quiet); @@ -692,7 +693,7 @@ void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile* mf) # define fnc_prefix(s, t) cmHasPrefix(s, t) #endif -bool IsFileInDir(const std::string& infile, const std::string& indir) +static bool IsFileInDir(const std::string& infile, const std::string& indir) { std::string file = cmSystemTools::CollapseFullPath(infile); std::string dir = cmSystemTools::CollapseFullPath(indir); diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index d85edcc..56f805c 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -24,7 +24,7 @@ static unsigned int cmCTestGITVersion(unsigned int epic, unsigned int major, unsigned int minor, unsigned int fix) { // 1.6.5.0 maps to 10605000 - return fix + minor * 1000 + major * 100000 + epic * 10000000; + return epic * 10000000 + major * 100000 + minor * 1000 + fix; } cmCTestGIT::cmCTestGIT(cmCTest* ct, std::ostream& log) @@ -582,16 +582,17 @@ private: time_t seconds = static_cast<time_t>(person.Time); struct tm* t = gmtime(&seconds); char dt[1024]; - sprintf(dt, "%04d-%02d-%02d %02d:%02d:%02d", t->tm_year + 1900, - t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + snprintf(dt, sizeof(dt), "%04d-%02d-%02d %02d:%02d:%02d", + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, + t->tm_min, t->tm_sec); std::string out = dt; // Add the time-zone field "+zone" or "-zone". char tz[32]; if (person.TimeZone >= 0) { - sprintf(tz, " +%04ld", person.TimeZone); + snprintf(tz, sizeof(tz), " +%04ld", person.TimeZone); } else { - sprintf(tz, " -%04ld", -person.TimeZone); + snprintf(tz, sizeof(tz), " -%04ld", -person.TimeZone); } out += tz; return out; diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index b4b0ad8..4bdb9c2 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -4,12 +4,11 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <map> #include <string> #include <vector> -#include <stddef.h> - #include "cmCTest.h" #include "cmSystemTools.h" #include "cmValue.h" diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 15c443a..4a33869 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -20,9 +20,10 @@ #include "cmake.h" #ifdef _WIN32 +# include <cstdio> // for std{out,err} and fileno + # include <fcntl.h> // for _O_BINARY # include <io.h> // for _setmode -# include <stdio.h> // for std{out,err} and fileno #endif cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv) diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h index eabb608..c5a6476 100644 --- a/Source/CTest/cmCTestLaunch.h +++ b/Source/CTest/cmCTestLaunch.h @@ -24,14 +24,14 @@ public: /** Entry point from ctest executable main(). */ static int Main(int argc, const char* const argv[]); + cmCTestLaunch(const cmCTestLaunch&) = delete; + cmCTestLaunch& operator=(const cmCTestLaunch&) = delete; + private: // Initialize the launcher from its command line. cmCTestLaunch(int argc, const char* const* argv); ~cmCTestLaunch(); - cmCTestLaunch(const cmCTestLaunch&) = delete; - cmCTestLaunch& operator=(const cmCTestLaunch&) = delete; - // Run the real command. int Run(); void RunChild(); diff --git a/Source/CTest/cmCTestLaunchReporter.cxx b/Source/CTest/cmCTestLaunchReporter.cxx index 5334a93..149ba5d 100644 --- a/Source/CTest/cmCTestLaunchReporter.cxx +++ b/Source/CTest/cmCTestLaunchReporter.cxx @@ -13,9 +13,10 @@ #include "cmXMLWriter.h" #ifdef _WIN32 +# include <cstdio> // for std{out,err} and fileno + # include <fcntl.h> // for _O_BINARY # include <io.h> // for _setmode -# include <stdio.h> // for std{out,err} and fileno #endif cmCTestLaunchReporter::cmCTestLaunchReporter() diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 5de42f9..2f5ad40 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <map> #include <memory> #include <set> @@ -11,7 +12,6 @@ #include <vector> #include <cm3p/uv.h> -#include <stddef.h> #include "cmCTest.h" #include "cmCTestResourceAllocator.h" diff --git a/Source/CTest/cmCTestP4.h b/Source/CTest/cmCTestP4.h index d03f9cb..1889520 100644 --- a/Source/CTest/cmCTestP4.h +++ b/Source/CTest/cmCTestP4.h @@ -34,14 +34,6 @@ private: std::string Name; std::string EMail; std::string AccessTime; - - User() - : UserName() - , Name() - , EMail() - , AccessTime() - { - } }; std::map<std::string, User> Users; std::vector<std::string> P4Options; diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 9d2cef6..6cd3b09 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -229,7 +229,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED; char buf[1024]; - sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime().count()); + snprintf(buf, sizeof(buf), "%6.2f sec", + this->TestProcess->GetTotalTime().count()); outputStream << buf << "\n"; bool passedOrSkipped = passed || skipped; @@ -294,9 +295,10 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) ttime -= minutes; auto seconds = std::chrono::duration_cast<std::chrono::seconds>(ttime); char buffer[100]; - sprintf(buffer, "%02d:%02d:%02d", static_cast<unsigned>(hours.count()), - static_cast<unsigned>(minutes.count()), - static_cast<unsigned>(seconds.count())); + snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d", + static_cast<unsigned>(hours.count()), + static_cast<unsigned>(minutes.count()), + static_cast<unsigned>(seconds.count())); *this->TestHandler->LogFile << "----------------------------------------------------------" << std::endl; diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 2082156..7a97fa9 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -4,14 +4,13 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <map> #include <memory> #include <set> #include <string> #include <vector> -#include <stddef.h> - #include "cmCTest.h" #include "cmCTestMultiProcessHandler.h" #include "cmCTestTestHandler.h" diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index f685f66..16c0a0e 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -48,8 +48,6 @@ # include <unistd.h> #endif -#define CTEST_INITIAL_CMAKE_OUTPUT_FILE_NAME "CTestInitialCMakeOutput.log" - cmCTestScriptHandler::cmCTestScriptHandler() = default; void cmCTestScriptHandler::Initialize() @@ -411,7 +409,7 @@ int cmCTestScriptHandler::ExtractVariables() char updateVar[40]; int i; for (i = 1; i < 10; ++i) { - sprintf(updateVar, "CTEST_EXTRA_UPDATES_%i", i); + snprintf(updateVar, sizeof(updateVar), "CTEST_EXTRA_UPDATES_%i", i); cmValue updateVal = this->Makefile->GetDefinition(updateVar); if (updateVal) { if (this->UpdateCmd.empty()) { diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index c4f87e9..a2dc615 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -58,6 +58,9 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() this->CTest->SetCTestConfigurationFromCMakeVariable( this->Makefile, "CurlOptions", "CTEST_CURL_OPTIONS", this->Quiet); + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "SubmitInactivityTimeout", + "CTEST_SUBMIT_INACTIVITY_TIMEOUT", this->Quiet); cmValue notesFilesVariable = this->Makefile->GetDefinition("CTEST_NOTES_FILES"); diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index b99bb79..fae5e30 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -7,6 +7,7 @@ #include <cstdlib> #include <sstream> +#include <cm/iomanip> #include <cmext/algorithm> #include <cm3p/curl/curl.h> @@ -216,8 +217,11 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( // if there is little to no activity for too long stop submitting ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1); - ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, - SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT); + auto submitInactivityTimeout = this->GetSubmitInactivityTimeout(); + if (submitInactivityTimeout != 0) { + ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, + submitInactivityTimeout); + } /* HTTP PUT please */ ::curl_easy_setopt(curl, CURLOPT_PUT, 1); @@ -499,7 +503,10 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions")); std::vector<std::string> args = cmExpandedList(curlopt); curl.SetCurlOptions(args); - curl.SetTimeOutSeconds(SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT); + auto submitInactivityTimeout = this->GetSubmitInactivityTimeout(); + if (submitInactivityTimeout != 0) { + curl.SetTimeOutSeconds(submitInactivityTimeout); + } curl.SetHttpHeaders(this->HttpHeaders); std::string url = this->CTest->GetSubmitURL(); if (!cmHasLiteralPrefix(url, "http://") && @@ -893,6 +900,26 @@ void cmCTestSubmitHandler::SelectParts(std::set<cmCTest::Part> const& parts) } } +int cmCTestSubmitHandler::GetSubmitInactivityTimeout() +{ + int submitInactivityTimeout = SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT; + std::string const& timeoutStr = + this->CTest->GetCTestConfiguration("SubmitInactivityTimeout"); + if (!timeoutStr.empty()) { + unsigned long timeout; + if (cmStrToULong(timeoutStr, &timeout)) { + submitInactivityTimeout = static_cast<int>(timeout); + } else { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "SubmitInactivityTimeout is invalid: " + << cm::quoted(timeoutStr) << "." + << " Using a default value of " + << SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT << "." << std::endl); + } + } + return submitInactivityTimeout; +} + void cmCTestSubmitHandler::SelectFiles(std::set<std::string> const& files) { this->Files.insert(files.begin(), files.end()); diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h index 809c615..0c7253c 100644 --- a/Source/CTest/cmCTestSubmitHandler.h +++ b/Source/CTest/cmCTestSubmitHandler.h @@ -63,6 +63,7 @@ private: void ParseResponse(cmCTestSubmitHandlerVectorOfChar chunk); std::string GetSubmitResultsPrefix(); + int GetSubmitInactivityTimeout(); class ResponseParser; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 6e97a83..02db0c6 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -59,6 +59,8 @@ public: } virtual ~cmCTestCommand() = default; + cmCTestCommand(const cmCTestCommand&) = default; + cmCTestCommand& operator=(const cmCTestCommand&) = default; bool operator()(std::vector<cmListFileArgument> const& args, cmExecutionStatus& status) @@ -621,7 +623,7 @@ void cmCTestTestHandler::LogTestSummary(const std::vector<std::string>& passed, this->PrintLabelOrSubprojectSummary(false); } char realBuf[1024]; - sprintf(realBuf, "%6.2f sec", durationInSecs.count()); + snprintf(realBuf, sizeof(realBuf), "%6.2f sec", durationInSecs.count()); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\nTotal Test time (real) = " << realBuf << "\n", this->Quiet); @@ -782,7 +784,7 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject) label.resize(maxlen + 3, ' '); char buf[1024]; - sprintf(buf, "%6.2f sec*proc", labelTimes[i]); + snprintf(buf, sizeof(buf), "%6.2f sec*proc", labelTimes[i]); std::ostringstream labelCountStr; labelCountStr << "(" << labelCounts[i] << " test"; diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 3ac05e7..135e764 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <chrono> +#include <cstddef> #include <cstdint> #include <iosfwd> #include <map> @@ -13,8 +14,6 @@ #include <utility> #include <vector> -#include <stddef.h> - #include "cmsys/RegularExpression.hxx" #include "cmCTest.h" diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 423b506..d5711c5 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -123,9 +123,10 @@ std::string cmCTestVC::GetNightlyTime() this->CTest->GetCTestConfiguration("NightlyStartTime"), this->CTest->GetTomorrowTag()); char current_time[1024]; - sprintf(current_time, "%04d-%02d-%02d %02d:%02d:%02d", t->tm_year + 1900, - t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); - return std::string(current_time); + snprintf(current_time, sizeof(current_time), "%04d-%02d-%02d %02d:%02d:%02d", + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, + t->tm_sec); + return { current_time }; } void cmCTestVC::Cleanup() diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h index 9bd7229..7b03d10 100644 --- a/Source/CTest/cmCTestVC.h +++ b/Source/CTest/cmCTestVC.h @@ -95,15 +95,10 @@ protected: /** Represent change to one file. */ struct File { - PathStatus Status; - Revision const* Rev; - Revision const* PriorRev; - File() - : Status(PathUpdated) - , Rev(nullptr) - , PriorRev(nullptr) - { - } + PathStatus Status = PathUpdated; + Revision const* Rev = nullptr; + Revision const* PriorRev = nullptr; + File() = default; File(PathStatus status, Revision const* rev, Revision const* priorRev) : Status(status) , Rev(rev) diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 16bca01..e14a4e1 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -511,7 +511,7 @@ std::string cmProcess::GetExitExceptionString() const default: char buf[1024]; const char* fmt = "Exit code 0x%" KWIML_INT_PRIx64 "\n"; - _snprintf(buf, 1024, fmt, this->ExitValue); + snprintf(buf, sizeof(buf), fmt, this->ExitValue); exception_str.assign(buf); } #else diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index a44aeb0..be030e4 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -5,14 +5,14 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <chrono> +#include <cstddef> +#include <cstdint> #include <memory> #include <string> #include <utility> #include <vector> #include <cm3p/uv.h> -#include <stddef.h> -#include <stdint.h> #include "cmDuration.h" #include "cmProcessOutput.h" @@ -52,9 +52,9 @@ public: }; State GetProcessStatus(); - int GetId() { return this->Id; } + int GetId() const { return this->Id; } void SetId(int id) { this->Id = id; } - int64_t GetExitValue() { return this->ExitValue; } + int64_t GetExitValue() const { return this->ExitValue; } cmDuration GetTotalTime() { return this->TotalTime; } enum class Exception @@ -111,15 +111,11 @@ private: class Buffer : public std::vector<char> { // Half-open index range of partial line already scanned. - size_type First; - size_type Last; + size_type First = 0; + size_type Last = 0; public: - Buffer() - : First(0) - , Last(0) - { - } + Buffer() = default; bool GetLine(std::string& line); bool GetLast(std::string& line); }; diff --git a/Source/Checks/cm_c11_thread_local.cmake b/Source/Checks/cm_c11_thread_local.cmake index 2263be3..f59688d 100644 --- a/Source/Checks/cm_c11_thread_local.cmake +++ b/Source/Checks/cm_c11_thread_local.cmake @@ -1,5 +1,5 @@ set(CMake_C11_THREAD_LOCAL_BROKEN 0) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION) +if((CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "LCC") AND CMAKE_C11_STANDARD_COMPILE_OPTION) if(NOT DEFINED CMake_C11_THREAD_LOCAL_WORKS) include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) cm_message_checks_compat( diff --git a/Source/Checks/cm_cxx14_check.cmake b/Source/Checks/cm_cxx14_check.cmake index e5656bf..abf232a 100644 --- a/Source/Checks/cm_cxx14_check.cmake +++ b/Source/Checks/cm_cxx14_check.cmake @@ -1,5 +1,5 @@ set(CMake_CXX14_BROKEN 0) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang|PGI|Intel") if(NOT CMAKE_CXX14_STANDARD_COMPILE_OPTION) set(CMake_CXX14_WORKS 0) endif() diff --git a/Source/Checks/cm_cxx17_check.cmake b/Source/Checks/cm_cxx17_check.cmake index dba3eaf..78a2382 100644 --- a/Source/Checks/cm_cxx17_check.cmake +++ b/Source/Checks/cm_cxx17_check.cmake @@ -1,5 +1,5 @@ set(CMake_CXX17_BROKEN 0) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang|PGI|Intel") if(NOT CMAKE_CXX17_STANDARD_COMPILE_OPTION) set(CMake_CXX17_WORKS 0) endif() diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 1ba45e5..ae4c0f6 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -55,7 +55,7 @@ cmCursesForm* cmCursesForm::CurrentForm = nullptr; extern "C" { -void onsig(int /*unused*/) +static void onsig(int /*unused*/) { if (cmCursesForm::CurrentForm) { endwin(); diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index 591c546..7f1815f 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -78,7 +78,8 @@ void cmCursesLongMessageForm::UpdateStatusBar() char version[cmCursesMainForm::MAX_WIDTH]; char vertmp[128]; - sprintf(vertmp, "CMake Version %s", cmVersion::GetCMakeVersion()); + snprintf(vertmp, sizeof(vertmp), "CMake Version %s", + cmVersion::GetCMakeVersion()); size_t sideSpace = (width - strlen(vertmp)); for (size_t i = 0; i < sideSpace; i++) { version[i] = ' '; @@ -105,7 +106,7 @@ void cmCursesLongMessageForm::PrintKeys() return; } char firstLine[512]; - sprintf(firstLine, "Press [e] to exit screen"); + snprintf(firstLine, sizeof(firstLine), "Press [e] to exit screen"); char fmt_s[] = "%s"; curses_move(y - 2, 0); @@ -176,7 +177,8 @@ void cmCursesLongMessageForm::HandleInput() this->PrintKeys(); int key = getch(); - sprintf(debugMessage, "Message widget handling input, key: %d", key); + snprintf(debugMessage, sizeof(debugMessage), + "Message widget handling input, key: %d", key); cmCursesForm::LogMessage(debugMessage); // quit diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index b28c5b7..0012a25 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -322,22 +322,22 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */) memset(thirdLine, ' ', 68); } else { if (this->OkToGenerate) { - sprintf(firstLine, - " [l] Show log output [c] Configure" - " [g] Generate "); + snprintf(firstLine, sizeof(firstLine), + " [l] Show log output [c] Configure" + " [g] Generate "); } else { - sprintf(firstLine, - " [l] Show log output [c] Configure" - " "); + snprintf(firstLine, sizeof(firstLine), + " [l] Show log output [c] Configure" + " "); } { const char* toggleKeyInstruction = " [t] Toggle advanced mode (currently %s)"; - sprintf(thirdLine, toggleKeyInstruction, - this->AdvancedMode ? "on" : "off"); + snprintf(thirdLine, sizeof(thirdLine), toggleKeyInstruction, + this->AdvancedMode ? "on" : "off"); } - sprintf(secondLine, - " [h] Help [q] Quit without generating"); + snprintf(secondLine, sizeof(secondLine), + " [h] Help [q] Quit without generating"); } curses_move(y - 4, 0); @@ -356,7 +356,8 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */) if (cw) { char pageLine[512] = ""; - sprintf(pageLine, "Page %d of %d", cw->GetPage(), this->NumberOfPages); + snprintf(pageLine, sizeof(pageLine), "Page %d of %d", cw->GetPage(), + this->NumberOfPages); curses_move(0, 65 - static_cast<unsigned int>(strlen(pageLine)) - 1); printw(fmt_s, pageLine); } @@ -739,7 +740,8 @@ void cmCursesMainForm::HandleInput() if ((!currentWidget || !widgetHandled) && !this->SearchMode) { // If the current widget does not want to handle input, // we handle it. - sprintf(debugMessage, "Main form handling input, key: %d", key); + snprintf(debugMessage, sizeof(debugMessage), + "Main form handling input, key: %d", key); cmCursesForm::LogMessage(debugMessage); // quit if (key == 'q') { diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx index 4830d63..c0d06ce 100644 --- a/Source/CursesDialog/cmCursesStringWidget.cxx +++ b/Source/CursesDialog/cmCursesStringWidget.cxx @@ -85,7 +85,8 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm, // <Enter> is used to change edit mode (like <Esc> in vi). while (!this->Done) { - sprintf(debugMessage, "String widget handling input, key: %d", key); + snprintf(debugMessage, sizeof(debugMessage), + "String widget handling input, key: %d", key); cmCursesForm::LogMessage(debugMessage); fm->PrintKeys(); diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt index 9202bc1..22a2e84 100644 --- a/Source/CursesDialog/form/CMakeLists.txt +++ b/Source/CursesDialog/form/CMakeLists.txt @@ -5,7 +5,7 @@ project(CMAKE_FORM) # Disable warnings to avoid changing 3rd party code. if(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") + "^(GNU|LCC|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Source/CursesDialog/form/fty_enum.c b/Source/CursesDialog/form/fty_enum.c index 59058a9..f1059b1 100644 --- a/Source/CursesDialog/form/fty_enum.c +++ b/Source/CursesDialog/form/fty_enum.c @@ -116,7 +116,7 @@ static int Compare(const unsigned char *s, const unsigned char *buf, if (*buf=='\0') { - return (((*s)!='\0') ? NOMATCH : EXACT); + return (((*s)=='\0') ? EXACT : NOMATCH); } else { @@ -144,7 +144,7 @@ static int Compare(const unsigned char *s, const unsigned char *buf, /* If it happens that the reference buffer is at its end, the partial match is actually an exact match. */ - return ((s[-1]!='\0') ? PARTIAL : EXACT); + return ((s[-1]=='\0') ? EXACT : PARTIAL); } /*--------------------------------------------------------------------------- diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 0dc954a..017fdc0 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -320,9 +320,9 @@ private: }; #endif -bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename, - std::set<std::string>& symbols, - std::set<std::string>& dataSymbols) +static bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename, + std::set<std::string>& symbols, + std::set<std::string>& dataSymbols) { std::string output; // break up command line into a vector @@ -375,9 +375,9 @@ bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename, return true; } -bool DumpFile(std::string const& nmPath, const char* filename, - std::set<std::string>& symbols, - std::set<std::string>& dataSymbols) +static bool DumpFile(std::string const& nmPath, const char* filename, + std::set<std::string>& symbols, + std::set<std::string>& dataSymbols) { #ifndef _WIN32 return DumpFileWithLlvmNm(nmPath, filename, symbols, dataSymbols); diff --git a/Source/bindexplib.h b/Source/bindexplib.h index bd1398f..c5d81c7 100644 --- a/Source/bindexplib.h +++ b/Source/bindexplib.h @@ -4,11 +4,10 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstdio> #include <set> #include <string> -#include <stdio.h> - class bindexplib { public: diff --git a/Source/cmAffinity.cxx b/Source/cmAffinity.cxx index 35443e7..591199b 100644 --- a/Source/cmAffinity.cxx +++ b/Source/cmAffinity.cxx @@ -12,7 +12,7 @@ # define CM_HAVE_CPU_AFFINITY # include <pthread.h> # include <sched.h> -// On some platforms CPU_ZERO needs memset but sched.h forgets string.h +// On some platforms CPU_ZERO needs memset but sched.h forgets cstring # include <cstring> // IWYU pragma: keep # if defined(__FreeBSD__) # include <pthread_np.h> diff --git a/Source/cmBase32.cxx b/Source/cmBase32.cxx index a9c15c2..e8e46aa 100644 --- a/Source/cmBase32.cxx +++ b/Source/cmBase32.cxx @@ -12,7 +12,7 @@ inline unsigned char Base32EncodeChar(int schar) return Base32EncodeTable[schar]; } -void Base32Encode5(const unsigned char src[5], char dst[8]) +static void Base32Encode5(const unsigned char src[5], char dst[8]) { // [0]:5 bits dst[0] = Base32EncodeChar((src[0] >> 3) & 0x1F); diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h index 7aa9b6a..769fb4e 100644 --- a/Source/cmCMakePresetsFile.h +++ b/Source/cmCMakePresetsFile.h @@ -60,18 +60,20 @@ public: class Preset { public: -#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L) + Preset() = default; + Preset(Preset&& /*other*/) = default; + Preset(const Preset& /*other*/) = default; + Preset& operator=(const Preset& /*other*/) = default; + virtual ~Preset() = default; +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) + Preset& operator=(Preset&& /*other*/) = default; +#else // The move assignment operators for several STL classes did not become // noexcept until C++17, which causes some tools to warn about this move - // assignment operator throwing an exception when it shouldn't. Disable the - // move assignment operator until C++17 is enabled. - // Explicitly defining a copy assignment operator prevents the compiler - // from automatically generating a move assignment operator. - Preset& operator=(const Preset& /*other*/) = default; + // assignment operator throwing an exception when it shouldn't. + Preset& operator=(Preset&& /*other*/) = delete; #endif - virtual ~Preset() = default; - std::string Name; std::vector<std::string> Inherits; bool Hidden; @@ -99,14 +101,18 @@ public: class ConfigurePreset : public Preset { public: -#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L) + ConfigurePreset() = default; + ConfigurePreset(ConfigurePreset&& /*other*/) = default; + ConfigurePreset(const ConfigurePreset& /*other*/) = default; + ConfigurePreset& operator=(const ConfigurePreset& /*other*/) = default; + ~ConfigurePreset() override = default; +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) + ConfigurePreset& operator=(ConfigurePreset&& /*other*/) = default; +#else // The move assignment operators for several STL classes did not become // noexcept until C++17, which causes some tools to warn about this move - // assignment operator throwing an exception when it shouldn't. Disable the - // move assignment operator until C++17 is enabled. - // Explicitly defining a copy assignment operator prevents the compiler - // from automatically generating a move assignment operator. - ConfigurePreset& operator=(const ConfigurePreset& /*other*/) = default; + // assignment operator throwing an exception when it shouldn't. + ConfigurePreset& operator=(ConfigurePreset&& /*other*/) = delete; #endif std::string Generator; @@ -140,14 +146,18 @@ public: class BuildPreset : public Preset { public: -#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L) + BuildPreset() = default; + BuildPreset(BuildPreset&& /*other*/) = default; + BuildPreset(const BuildPreset& /*other*/) = default; + BuildPreset& operator=(const BuildPreset& /*other*/) = default; + ~BuildPreset() override = default; +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) + BuildPreset& operator=(BuildPreset&& /*other*/) = default; +#else // The move assignment operators for several STL classes did not become // noexcept until C++17, which causes some tools to warn about this move - // assignment operator throwing an exception when it shouldn't. Disable the - // move assignment operator until C++17 is enabled. - // Explicitly defining a copy assignment operator prevents the compiler - // from automatically generating a move assignment operator. - BuildPreset& operator=(const BuildPreset& /*other*/) = default; + // assignment operator throwing an exception when it shouldn't. + BuildPreset& operator=(BuildPreset&& /*other*/) = delete; #endif std::string ConfigurePreset; @@ -166,14 +176,18 @@ public: class TestPreset : public Preset { public: -#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L) + TestPreset() = default; + TestPreset(TestPreset&& /*other*/) = default; + TestPreset(const TestPreset& /*other*/) = default; + TestPreset& operator=(const TestPreset& /*other*/) = default; + ~TestPreset() override = default; +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) + TestPreset& operator=(TestPreset&& /*other*/) = default; +#else // The move assignment operators for several STL classes did not become // noexcept until C++17, which causes some tools to warn about this move - // assignment operator throwing an exception when it shouldn't. Disable the - // move assignment operator until C++17 is enabled. - // Explicitly defining a copy assignment operator prevents the compiler - // from automatically generating a move assignment operator. - TestPreset& operator=(const TestPreset& /*other*/) = default; + // assignment operator throwing an exception when it shouldn't. + TestPreset& operator=(TestPreset&& /*other*/) = delete; #endif struct OutputOptions diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index e460031..c49347d 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -22,17 +22,17 @@ extern "C" { -void CCONV* cmGetClientData(void* info) +static void CCONV* cmGetClientData(void* info) { return ((cmLoadedCommandInfo*)info)->ClientData; } -void CCONV cmSetClientData(void* info, void* cd) +static void CCONV cmSetClientData(void* info, void* cd) { ((cmLoadedCommandInfo*)info)->ClientData = cd; } -void CCONV cmSetError(void* info, const char* err) +static void CCONV cmSetError(void* info, const char* err) { if (((cmLoadedCommandInfo*)info)->Error) { free(((cmLoadedCommandInfo*)info)->Error); @@ -40,30 +40,31 @@ void CCONV cmSetError(void* info, const char* err) ((cmLoadedCommandInfo*)info)->Error = strdup(err); } -unsigned int CCONV cmGetCacheMajorVersion(void* arg) +static unsigned int CCONV cmGetCacheMajorVersion(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); cmState* state = mf->GetState(); return state->GetCacheMajorVersion(); } -unsigned int CCONV cmGetCacheMinorVersion(void* arg) +static unsigned int CCONV cmGetCacheMinorVersion(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); cmState* state = mf->GetState(); return state->GetCacheMinorVersion(); } -unsigned int CCONV cmGetMajorVersion(void*) +static unsigned int CCONV cmGetMajorVersion(void*) { return cmVersion::GetMajorVersion(); } -unsigned int CCONV cmGetMinorVersion(void*) +static unsigned int CCONV cmGetMinorVersion(void*) { return cmVersion::GetMinorVersion(); } -void CCONV cmAddDefinition(void* arg, const char* name, const char* value) +static void CCONV cmAddDefinition(void* arg, const char* name, + const char* value) { if (value) { cmMakefile* mf = static_cast<cmMakefile*>(arg); @@ -72,8 +73,9 @@ void CCONV cmAddDefinition(void* arg, const char* name, const char* value) } /* Add a definition to this makefile and the global cmake cache. */ -void CCONV cmAddCacheDefinition(void* arg, const char* name, const char* value, - const char* doc, int type) +static void CCONV cmAddCacheDefinition(void* arg, const char* name, + const char* value, const char* doc, + int type) { cmMakefile* mf = static_cast<cmMakefile*>(arg); @@ -99,7 +101,7 @@ void CCONV cmAddCacheDefinition(void* arg, const char* name, const char* value, } } -const char* CCONV cmGetProjectName(void* arg) +static const char* CCONV cmGetProjectName(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); static std::string name; @@ -107,63 +109,63 @@ const char* CCONV cmGetProjectName(void* arg) return name.c_str(); } -const char* CCONV cmGetHomeDirectory(void* arg) +static const char* CCONV cmGetHomeDirectory(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); return mf->GetHomeDirectory().c_str(); } -const char* CCONV cmGetHomeOutputDirectory(void* arg) +static const char* CCONV cmGetHomeOutputDirectory(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); return mf->GetHomeOutputDirectory().c_str(); } -const char* CCONV cmGetStartDirectory(void* arg) +static const char* CCONV cmGetStartDirectory(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); return mf->GetCurrentSourceDirectory().c_str(); } -const char* CCONV cmGetStartOutputDirectory(void* arg) +static const char* CCONV cmGetStartOutputDirectory(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); return mf->GetCurrentBinaryDirectory().c_str(); } -const char* CCONV cmGetCurrentDirectory(void* arg) +static const char* CCONV cmGetCurrentDirectory(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); return mf->GetCurrentSourceDirectory().c_str(); } -const char* CCONV cmGetCurrentOutputDirectory(void* arg) +static const char* CCONV cmGetCurrentOutputDirectory(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); return mf->GetCurrentBinaryDirectory().c_str(); } -const char* CCONV cmGetDefinition(void* arg, const char* def) +static const char* CCONV cmGetDefinition(void* arg, const char* def) { cmMakefile* mf = static_cast<cmMakefile*>(arg); return mf->GetDefinition(def).GetCStr(); } -int CCONV cmIsOn(void* arg, const char* name) +static int CCONV cmIsOn(void* arg, const char* name) { cmMakefile* mf = static_cast<cmMakefile*>(arg); return static_cast<int>(mf->IsOn(name)); } /** Check if a command exists. */ -int CCONV cmCommandExists(void* arg, const char* name) +static int CCONV cmCommandExists(void* arg, const char* name) { cmMakefile* mf = static_cast<cmMakefile*>(arg); return static_cast<int>(mf->GetState()->GetCommand(name) ? 1 : 0); } -void CCONV cmAddDefineFlag(void* arg, const char* definition) +static void CCONV cmAddDefineFlag(void* arg, const char* definition) { cmMakefile* mf = static_cast<cmMakefile*>(arg); mf->AddDefineFlag(definition); } -void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt, - const char* d) +static void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt, + const char* d) { cmMakefile* mf = static_cast<cmMakefile*>(arg); cmTarget* t = mf->FindLocalNonAliasTarget(tgt); @@ -176,8 +178,8 @@ void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt, t->InsertLinkDirectory(BT<std::string>(d, mf->GetBacktrace())); } -void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs, - const char** srcs, int win32) +static void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs, + const char** srcs, int win32) { cmMakefile* mf = static_cast<cmMakefile*>(arg); std::vector<std::string> srcs2; @@ -191,10 +193,11 @@ void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs, } } -void CCONV cmAddUtilityCommand(void* arg, const char* utilityName, - const char* command, const char* arguments, - int all, int numDepends, const char** depends, - int, const char**) +static void CCONV cmAddUtilityCommand(void* arg, const char* utilityName, + const char* command, + const char* arguments, int all, + int numDepends, const char** depends, + int, const char**) { // Get the makefile instance. Perform an extra variable expansion // now because the API caller expects it. @@ -226,11 +229,11 @@ void CCONV cmAddUtilityCommand(void* arg, const char* utilityName, mf->GetPolicyStatus(cmPolicies::CMP0116)); } -void CCONV cmAddCustomCommand(void* arg, const char* source, - const char* command, int numArgs, - const char** args, int numDepends, - const char** depends, int numOutputs, - const char** outputs, const char* target) +static void CCONV cmAddCustomCommand(void* arg, const char* source, + const char* command, int numArgs, + const char** args, int numDepends, + const char** depends, int numOutputs, + const char** outputs, const char* target) { // Get the makefile instance. Perform an extra variable expansion // now because the API caller expects it. @@ -268,11 +271,12 @@ void CCONV cmAddCustomCommand(void* arg, const char* source, mf->GetPolicyStatus(cmPolicies::CMP0116)); } -void CCONV cmAddCustomCommandToOutput(void* arg, const char* output, - const char* command, int numArgs, - const char** args, - const char* main_dependency, - int numDepends, const char** depends) +static void CCONV cmAddCustomCommandToOutput(void* arg, const char* output, + const char* command, int numArgs, + const char** args, + const char* main_dependency, + int numDepends, + const char** depends) { // Get the makefile instance. Perform an extra variable expansion // now because the API caller expects it. @@ -304,9 +308,10 @@ void CCONV cmAddCustomCommandToOutput(void* arg, const char* output, mf->GetPolicyStatus(cmPolicies::CMP0116)); } -void CCONV cmAddCustomCommandToTarget(void* arg, const char* target, - const char* command, int numArgs, - const char** args, int commandType) +static void CCONV cmAddCustomCommandToTarget(void* arg, const char* target, + const char* command, int numArgs, + const char** args, + int commandType) { // Get the makefile instance. cmMakefile* mf = static_cast<cmMakefile*>(arg); @@ -376,8 +381,8 @@ static void addLinkLibrary(cmMakefile* mf, std::string const& target, t->AddLinkLibrary(*mf, lib, llt); } -void CCONV cmAddLinkLibraryForTarget(void* arg, const char* tgt, - const char* value, int libtype) +static void CCONV cmAddLinkLibraryForTarget(void* arg, const char* tgt, + const char* value, int libtype) { cmMakefile* mf = static_cast<cmMakefile*>(arg); @@ -394,8 +399,8 @@ void CCONV cmAddLinkLibraryForTarget(void* arg, const char* tgt, } } -void CCONV cmAddLibrary(void* arg, const char* libname, int shared, - int numSrcs, const char** srcs) +static void CCONV cmAddLibrary(void* arg, const char* libname, int shared, + int numSrcs, const char** srcs) { cmMakefile* mf = static_cast<cmMakefile*>(arg); std::vector<std::string> srcs2; @@ -409,8 +414,8 @@ void CCONV cmAddLibrary(void* arg, const char* libname, int shared, srcs2); } -char CCONV* cmExpandVariablesInString(void* arg, const char* source, - int escapeQuotes, int atOnly) +static char CCONV* cmExpandVariablesInString(void* arg, const char* source, + int escapeQuotes, int atOnly) { cmMakefile* mf = static_cast<cmMakefile*>(arg); std::string barf = source; @@ -419,8 +424,8 @@ char CCONV* cmExpandVariablesInString(void* arg, const char* source, return strdup(result.c_str()); } -int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs, - const char** args) +static int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs, + const char** args) { cmMakefile* mf = static_cast<cmMakefile*>(arg); @@ -436,10 +441,10 @@ int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs, return mf->ExecuteCommand(lff, status); } -void CCONV cmExpandSourceListArguments(void* arg, int numArgs, - const char** args, int* resArgc, - char*** resArgv, - unsigned int startArgumentIndex) +static void CCONV cmExpandSourceListArguments(void* arg, int numArgs, + const char** args, int* resArgc, + char*** resArgv, + unsigned int startArgumentIndex) { (void)arg; (void)startArgumentIndex; @@ -460,7 +465,7 @@ void CCONV cmExpandSourceListArguments(void* arg, int numArgs, *resArgv = resargv; } -void CCONV cmFreeArguments(int argc, char** argv) +static void CCONV cmFreeArguments(int argc, char** argv) { int i; for (i = 0; i < argc; ++i) { @@ -469,7 +474,7 @@ void CCONV cmFreeArguments(int argc, char** argv) free(argv); } -int CCONV cmGetTotalArgumentSize(int argc, char** argv) +static int CCONV cmGetTotalArgumentSize(int argc, char** argv) { int i; int result = 0; @@ -497,19 +502,19 @@ struct cmCPluginAPISourceFile // the CPluginAPI proxy source file. using cmCPluginAPISourceFileMap = std::map<cmSourceFile*, std::unique_ptr<cmCPluginAPISourceFile>>; -cmCPluginAPISourceFileMap cmCPluginAPISourceFiles; +static cmCPluginAPISourceFileMap cmCPluginAPISourceFiles; -void* CCONV cmCreateSourceFile(void) +static void* CCONV cmCreateSourceFile() { return new cmCPluginAPISourceFile; } -void* CCONV cmCreateNewSourceFile(void*) +static void* CCONV cmCreateNewSourceFile(void*) { return new cmCPluginAPISourceFile; } -void CCONV cmDestroySourceFile(void* arg) +static void CCONV cmDestroySourceFile(void* arg) { cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); // Only delete if it was created by cmCreateSourceFile or @@ -519,7 +524,7 @@ void CCONV cmDestroySourceFile(void* arg) } } -void CCONV* cmGetSource(void* arg, const char* name) +static void CCONV* cmGetSource(void* arg, const char* name) { cmMakefile* mf = static_cast<cmMakefile*>(arg); if (cmSourceFile* rsf = mf->GetSource(name)) { @@ -543,7 +548,7 @@ void CCONV* cmGetSource(void* arg, const char* name) return nullptr; } -void* CCONV cmAddSource(void* arg, void* arg2) +static void* CCONV cmAddSource(void* arg, void* arg2) { cmMakefile* mf = static_cast<cmMakefile*>(arg); cmCPluginAPISourceFile* osf = static_cast<cmCPluginAPISourceFile*>(arg2); @@ -576,19 +581,19 @@ void* CCONV cmAddSource(void* arg, void* arg2) return value; } -const char* CCONV cmSourceFileGetSourceName(void* arg) +static const char* CCONV cmSourceFileGetSourceName(void* arg) { cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); return sf->SourceName.c_str(); } -const char* CCONV cmSourceFileGetFullPath(void* arg) +static const char* CCONV cmSourceFileGetFullPath(void* arg) { cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); return sf->FullPath.c_str(); } -const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop) +static const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop) { cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); if (cmSourceFile* rsf = sf->RealSourceFile) { @@ -600,7 +605,7 @@ const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop) return sf->Properties.GetPropertyValue(prop).GetCStr(); } -int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop) +static int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop) { cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); if (cmSourceFile* rsf = sf->RealSourceFile) { @@ -609,8 +614,8 @@ int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop) return cmIsOn(cmSourceFileGetProperty(arg, prop)) ? 1 : 0; } -void CCONV cmSourceFileSetProperty(void* arg, const char* prop, - const char* value) +static void CCONV cmSourceFileSetProperty(void* arg, const char* prop, + const char* value) { cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); if (cmSourceFile* rsf = sf->RealSourceFile) { @@ -623,7 +628,7 @@ void CCONV cmSourceFileSetProperty(void* arg, const char* prop, } } -void CCONV cmSourceFileAddDepend(void* arg, const char* depend) +static void CCONV cmSourceFileAddDepend(void* arg, const char* depend) { cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); if (cmSourceFile* rsf = sf->RealSourceFile) { @@ -633,11 +638,11 @@ void CCONV cmSourceFileAddDepend(void* arg, const char* depend) } } -void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir, - int numSourceExtensions, - const char** sourceExtensions, - int numHeaderExtensions, - const char** headerExtensions) +static void CCONV cmSourceFileSetName(void* arg, const char* name, + const char* dir, int numSourceExtensions, + const char** sourceExtensions, + int numHeaderExtensions, + const char** headerExtensions) { cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); if (sf->RealSourceFile) { @@ -718,8 +723,9 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir, cmSystemTools::Error(e.str()); } -void CCONV cmSourceFileSetName2(void* arg, const char* name, const char* dir, - const char* ext, int headerFileOnly) +static void CCONV cmSourceFileSetName2(void* arg, const char* name, + const char* dir, const char* ext, + int headerFileOnly) { cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); if (sf->RealSourceFile) { @@ -743,48 +749,48 @@ void CCONV cmSourceFileSetName2(void* arg, const char* name, const char* dir, sf->SourceExtension = ext; } -char* CCONV cmGetFilenameWithoutExtension(const char* name) +static char* CCONV cmGetFilenameWithoutExtension(const char* name) { std::string sres = cmSystemTools::GetFilenameWithoutExtension(name); return strdup(sres.c_str()); } -char* CCONV cmGetFilenamePath(const char* name) +static char* CCONV cmGetFilenamePath(const char* name) { std::string sres = cmSystemTools::GetFilenamePath(name); return strdup(sres.c_str()); } -char* CCONV cmCapitalized(const char* name) +static char* CCONV cmCapitalized(const char* name) { std::string sres = cmSystemTools::Capitalized(name); return strdup(sres.c_str()); } -void CCONV cmCopyFileIfDifferent(const char* name1, const char* name2) +static void CCONV cmCopyFileIfDifferent(const char* name1, const char* name2) { cmSystemTools::CopyFileIfDifferent(name1, name2); } -void CCONV cmRemoveFile(const char* name) +static void CCONV cmRemoveFile(const char* name) { cmSystemTools::RemoveFile(name); } -void CCONV cmDisplayStatus(void* arg, const char* message) +static void CCONV cmDisplayStatus(void* arg, const char* message) { cmMakefile* mf = static_cast<cmMakefile*>(arg); mf->DisplayStatus(message, -1); } -void CCONV cmFree(void* data) +static void CCONV cmFree(void* data) { free(data); } -void CCONV DefineSourceFileProperty(void* arg, const char* name, - const char* briefDocs, - const char* longDocs, int chained) +static void CCONV DefineSourceFileProperty(void* arg, const char* name, + const char* briefDocs, + const char* longDocs, int chained) { cmMakefile* mf = static_cast<cmMakefile*>(arg); mf->GetState()->DefineProperty(name, cmProperty::SOURCE_FILE, @@ -794,7 +800,7 @@ void CCONV DefineSourceFileProperty(void* arg, const char* name, } // close the extern "C" scope -cmCAPI cmStaticCAPI = { +static cmCAPI cmStaticCAPI = { cmGetClientData, cmGetTotalArgumentSize, cmFreeArguments, diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index dfd2b6c..647dd87 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -227,8 +227,8 @@ struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag) char buf[1024]; // add todays year day and month to the time in str because // curl_getdate no longer assumes the day is today - sprintf(buf, "%d%02d%02d %s", lctime->tm_year + 1900, lctime->tm_mon + 1, - lctime->tm_mday, str.c_str()); + snprintf(buf, sizeof(buf), "%d%02d%02d %s", lctime->tm_year + 1900, + lctime->tm_mon + 1, lctime->tm_mday, str.c_str()); cmCTestLog(this, OUTPUT, "Determine Nightly Start Time" << std::endl << " Specified time: " << str @@ -543,9 +543,9 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) this->Impl->TomorrowTag); } char datestring[100]; - sprintf(datestring, "%04d%02d%02d-%02d%02d", lctime->tm_year + 1900, - lctime->tm_mon + 1, lctime->tm_mday, lctime->tm_hour, - lctime->tm_min); + snprintf(datestring, sizeof(datestring), "%04d%02d%02d-%02d%02d", + lctime->tm_year + 1900, lctime->tm_mon + 1, lctime->tm_mday, + lctime->tm_hour, lctime->tm_min); tag = datestring; cmsys::ofstream ofs(tagfile.c_str()); if (ofs) { @@ -2967,8 +2967,9 @@ void cmCTest::SetStopTime(std::string const& time_str) tzone_offset *= 100; char buf[1024]; - sprintf(buf, "%d%02d%02d %s %+05i", lctime->tm_year + 1900, - lctime->tm_mon + 1, lctime->tm_mday, time_str.c_str(), tzone_offset); + snprintf(buf, sizeof(buf), "%d%02d%02d %s %+05i", lctime->tm_year + 1900, + lctime->tm_mon + 1, lctime->tm_mday, time_str.c_str(), + tzone_offset); time_t stop_time = curl_getdate(buf, ¤t_time); if (stop_time == -1) { diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 831a81f..2ff91fe 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -722,7 +722,7 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item, this->AddFrameworkItem(item.Value); } else if (cmSystemTools::FileIsDirectory(item.Value)) { // This is a directory. - this->DropDirectoryItem(item.Value); + this->DropDirectoryItem(item); } else { // Use the full path given to the library file. this->Depends.push_back(item.Value); @@ -1349,16 +1349,17 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item) } } -void cmComputeLinkInformation::DropDirectoryItem(std::string const& item) +void cmComputeLinkInformation::DropDirectoryItem(BT<std::string> const& item) { // A full path to a directory was found as a link item. Warn the // user. - std::ostringstream e; - e << "WARNING: Target \"" << this->Target->GetName() - << "\" requests linking to directory \"" << item << "\". " - << "Targets may link only to libraries. " - << "CMake is dropping the item."; - cmSystemTools::Message(e.str()); + this->CMakeInstance->IssueMessage( + MessageType::WARNING, + cmStrCat( + "Target \"", this->Target->GetName(), + "\" requests linking to directory \"", item.Value, + "\". Targets may link only to libraries. CMake is dropping the item."), + item.Backtrace); } void cmComputeLinkInformation::ComputeFrameworkInfo() diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 90a699e..0315540 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -187,7 +187,7 @@ private: bool CheckImplicitDirItem(std::string const& item); void AddUserItem(BT<std::string> const& item, bool pathNotKnown); void AddFrameworkItem(std::string const& item); - void DropDirectoryItem(std::string const& item); + void DropDirectoryItem(BT<std::string> const& item); bool CheckSharedLibNoSOName(std::string const& item); void AddSharedLibNoSOName(std::string const& item); void HandleBadFullItem(std::string const& item, std::string const& file); diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 971c86e..84fa897 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -699,7 +699,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, /* Use a random file name to avoid rapid creation and deletion of the same executable name (some filesystems fail on that). */ - sprintf(targetNameBuf, "cmTC_%05x", cmSystemTools::RandomSeed() & 0xFFFFF); + snprintf(targetNameBuf, sizeof(targetNameBuf), "cmTC_%05x", + cmSystemTools::RandomSeed() & 0xFFFFF); targetName = targetNameBuf; if (!targets.empty()) { diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index fd0a63c..41d4442 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -346,7 +346,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const return this->CommandLines[c][0]; } -std::string escapeForShellOldStyle(const std::string& str) +static std::string escapeForShellOldStyle(const std::string& str) { std::string result; #if defined(_WIN32) && !defined(__CYGWIN__) diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 1678ce8..66f1733 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -26,17 +26,14 @@ template <size_t s> struct cmELFByteSwapSize { }; -void cmELFByteSwap(char* /*unused*/, cmELFByteSwapSize<1> /*unused*/) -{ -} -void cmELFByteSwap(char* data, cmELFByteSwapSize<2> /*unused*/) +static void cmELFByteSwap(char* data, cmELFByteSwapSize<2> /*unused*/) { char one_byte; one_byte = data[0]; data[0] = data[1]; data[1] = one_byte; } -void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/) +static void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/) { char one_byte; one_byte = data[0]; @@ -46,7 +43,7 @@ void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/) data[1] = data[2]; data[2] = one_byte; } -void cmELFByteSwap(char* data, cmELFByteSwapSize<8> /*unused*/) +static void cmELFByteSwap(char* data, cmELFByteSwapSize<8> /*unused*/) { char one_byte; one_byte = data[0]; diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index 51fb219..e069b77 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -114,7 +114,7 @@ bool cmExecProgramCommand(std::vector<std::string> const& args, if (!return_variable.empty()) { char buffer[100]; - sprintf(buffer, "%d", retVal); + snprintf(buffer, sizeof(buffer), "%d", retVal); status.GetMakefile().AddDefinition(return_variable, buffer); } diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index ffcc415..3b990cc 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -318,7 +318,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, case cmsysProcess_State_Exited: { int v = cmsysProcess_GetExitValue(cp); char buf[16]; - sprintf(buf, "%d", v); + snprintf(buf, sizeof(buf), "%d", v); status.GetMakefile().AddDefinition(arguments.ResultVariable, buf); } break; case cmsysProcess_State_Exception: @@ -346,7 +346,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, int exitCode = cmsysProcess_GetExitValueByIndex(cp, static_cast<int>(i)); char buf[16]; - sprintf(buf, "%d", exitCode); + snprintf(buf, sizeof(buf), "%d", exitCode); res.emplace_back(buf); } break; case kwsysProcess_StateByIndex_Exception: diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index aa968dc..a47f1e5 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -11,12 +11,15 @@ #include <cmext/algorithm> #include "cmExportSet.h" +#include "cmFileSet.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -135,6 +138,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateCompatibleInterfaceProperties(gte, properties); this->GenerateInterfaceProperties(gte, os, properties); + + this->GenerateTargetFileSets(gte, os); } // Generate import file content for each configuration. @@ -356,3 +361,17 @@ std::string cmExportBuildFileGenerator::InstallNameDir( return install_name_dir; } + +std::string cmExportBuildFileGenerator::GetFileSetDirectories( + cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/) +{ + return cmOutputConverter::EscapeForCMake( + cmJoin(fileSet->GetDirectoryEntries(), ";")); +} + +std::string cmExportBuildFileGenerator::GetFileSetFiles( + cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/) +{ + return cmOutputConverter::EscapeForCMake( + cmJoin(fileSet->GetFileEntries(), ";")); +} diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 244f526..a7985c7 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -15,9 +15,11 @@ #include "cmStateTypes.h" class cmExportSet; +class cmFileSet; class cmGeneratorTarget; class cmGlobalGenerator; class cmLocalGenerator; +class cmTargetExport; /** \class cmExportBuildFileGenerator * \brief Generate a file exporting targets from a build tree. @@ -76,6 +78,11 @@ protected: std::string InstallNameDir(cmGeneratorTarget const* target, const std::string& config) override; + std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet, + cmTargetExport* te) override; + std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet, + cmTargetExport* te) override; + std::pair<std::vector<std::string>, std::string> FindBuildExportInfo( cmGlobalGenerator* gg, const std::string& name); diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 8ca9a66..896240c 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -12,6 +12,7 @@ #include "cmsys/FStream.hxx" #include "cmComputeLinkInformation.h" +#include "cmFileSet.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -494,8 +495,9 @@ void cmExportFileGenerator::PopulateInterfaceProperty( properties, missingTargets); } -void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop, - std::set<std::string>& ifaceProperties) +static void getPropertyContents(cmGeneratorTarget const* tgt, + const std::string& prop, + std::set<std::string>& ifaceProperties) { cmValue p = tgt->GetProperty(prop); if (!p) { @@ -505,9 +507,9 @@ void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop, ifaceProperties.insert(content.begin(), content.end()); } -void getCompatibleInterfaceProperties(cmGeneratorTarget const* target, - std::set<std::string>& ifaceProperties, - const std::string& config) +static void getCompatibleInterfaceProperties( + cmGeneratorTarget const* target, std::set<std::string>& ifaceProperties, + const std::string& config) { if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { // object libraries have no link information, so nothing to compute @@ -924,13 +926,13 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) // Isolate the file policy level. // Support CMake versions as far back as 2.6 but also support using NEW - // policy settings for up to CMake 3.20 (this upper limit may be reviewed + // policy settings for up to CMake 3.21 (this upper limit may be reviewed // and increased from time to time). This reduces the opportunity for CMake // warnings when an older export file is later used with newer CMake // versions. /* clang-format off */ os << "cmake_policy(PUSH)\n" - << "cmake_policy(VERSION 2.6...3.20)\n"; + << "cmake_policy(VERSION 2.6...3.21)\n"; /* clang-format on */ } @@ -1072,6 +1074,12 @@ void cmExportFileGenerator::GenerateImportTargetCode( os << "set_property(TARGET " << targetName << " PROPERTY DEPRECATION " << cmExportFileGeneratorEscape(target->GetDeprecation()) << ")\n"; } + + if (target->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) { + os << "set_property(TARGET " << targetName + << " PROPERTY IMPORTED_NO_SYSTEM 1)\n"; + } + os << "\n"; } @@ -1249,3 +1257,39 @@ bool cmExportFileGenerator::PopulateExportProperties( } return true; } + +void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte, + std::ostream& os, + cmTargetExport* te) +{ + auto interfaceFileSets = gte->Target->GetAllInterfaceFileSets(); + if (!interfaceFileSets.empty()) { + std::string targetName = cmStrCat(this->Namespace, gte->GetExportName()); + os << "if(NOT CMAKE_VERSION VERSION_LESS \"" << DEVEL_CMAKE_VERSION(3, 23) + << "\")\n" + " target_sources(" + << targetName << "\n"; + + for (auto const& name : interfaceFileSets) { + auto* fileSet = gte->Target->GetFileSet(name); + if (!fileSet) { + gte->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("File set \"", name, + "\" is listed in interface file sets of ", gte->GetName(), + " but has not been created")); + return; + } + + os << " INTERFACE" + << "\n FILE_SET " << cmOutputConverter::EscapeForCMake(name) + << "\n TYPE " + << cmOutputConverter::EscapeForCMake(fileSet->GetType()) + << "\n BASE_DIRS " + << this->GetFileSetDirectories(gte, fileSet, te) << "\n FILES " + << this->GetFileSetFiles(gte, fileSet, te) << "\n"; + } + + os << " )\nendif()\n\n"; + } +} diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 24e048b..5875247 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -15,7 +15,9 @@ #include "cmVersion.h" #include "cmVersionConfig.h" +class cmFileSet; class cmGeneratorTarget; +class cmTargetExport; #define STRINGIFY_HELPER(X) #X #define STRINGIFY(X) STRINGIFY_HELPER(X) @@ -184,6 +186,16 @@ protected: ImportPropertyMap& properties, std::string& errorMessage); + void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os, + cmTargetExport* te = nullptr); + + virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte, + cmFileSet* fileSet, + cmTargetExport* te) = 0; + virtual std::string GetFileSetFiles(cmGeneratorTarget* gte, + cmFileSet* fileSet, + cmTargetExport* te) = 0; + // The namespace in which the exports are placed in the generated file. std::string Namespace; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index e9ac875..2dd8b8f 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -2,19 +2,23 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExportInstallFileGenerator.h" +#include <algorithm> #include <memory> #include <sstream> #include <utility> #include "cmExportSet.h" +#include "cmFileSet.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmInstallExportGenerator.h" +#include "cmInstallFileSetGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -147,6 +151,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateCompatibleInterfaceProperties(gt, properties); this->GenerateInterfaceProperties(gt, os, properties); + + this->GenerateTargetFileSets(gt, os, te); } if (require3_1_0) { @@ -534,3 +540,102 @@ std::string cmExportInstallFileGenerator::InstallNameDir( return install_name_dir; } + +namespace { +bool EntryIsContextSensitive( + const std::unique_ptr<cmCompiledGeneratorExpression>& cge) +{ + return cge->GetHadContextSensitiveCondition(); +} +} + +std::string cmExportInstallFileGenerator::GetFileSetDirectories( + cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te) +{ + std::vector<std::string> resultVector; + + auto configs = + gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + + cmGeneratorExpression ge; + auto cge = ge.Parse(te->FileSetGenerators.at(fileSet)->GetDestination()); + + for (auto const& config : configs) { + auto dest = cmStrCat("${_IMPORT_PREFIX}/", + cmOutputConverter::EscapeForCMake( + cge->Evaluate(gte->LocalGenerator, config, gte), + cmOutputConverter::WrapQuotes::NoWrap)); + + if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) { + resultVector.push_back( + cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\"")); + } else { + resultVector.push_back(cmStrCat('"', dest, '"')); + break; + } + } + + return cmJoin(resultVector, " "); +} + +std::string cmExportInstallFileGenerator::GetFileSetFiles( + cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te) +{ + std::vector<std::string> resultVector; + + auto configs = + gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + + auto fileEntries = fileSet->CompileFileEntries(); + auto directoryEntries = fileSet->CompileDirectoryEntries(); + + cmGeneratorExpression destGe; + auto destCge = + destGe.Parse(te->FileSetGenerators.at(fileSet)->GetDestination()); + + for (auto const& config : configs) { + auto directories = fileSet->EvaluateDirectoryEntries( + directoryEntries, gte->LocalGenerator, config, gte); + + std::map<std::string, std::vector<std::string>> files; + for (auto const& entry : fileEntries) { + fileSet->EvaluateFileEntry(directories, files, entry, + gte->LocalGenerator, config, gte); + } + auto dest = cmStrCat("${_IMPORT_PREFIX}/", + cmOutputConverter::EscapeForCMake( + destCge->Evaluate(gte->LocalGenerator, config, gte), + cmOutputConverter::WrapQuotes::NoWrap), + '/'); + + bool const contextSensitive = destCge->GetHadContextSensitiveCondition() || + std::any_of(directoryEntries.begin(), directoryEntries.end(), + EntryIsContextSensitive) || + std::any_of(fileEntries.begin(), fileEntries.end(), + EntryIsContextSensitive); + + for (auto const& it : files) { + auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/'); + for (auto const& filename : it.second) { + auto relFile = + cmStrCat(prefix, cmSystemTools::GetFilenameName(filename)); + auto escapedFile = + cmStrCat(dest, + cmOutputConverter::EscapeForCMake( + relFile, cmOutputConverter::WrapQuotes::NoWrap)); + if (contextSensitive && configs.size() != 1) { + resultVector.push_back( + cmStrCat("\"$<$<CONFIG:", config, ">:", escapedFile, ">\"")); + } else { + resultVector.push_back(cmStrCat('"', escapedFile, '"')); + } + } + } + + if (!(contextSensitive && configs.size() != 1)) { + break; + } + } + + return cmJoin(resultVector, " "); +} diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 5cec2e0..9374c6b 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -14,6 +14,7 @@ #include "cmExportFileGenerator.h" #include "cmStateTypes.h" +class cmFileSet; class cmGeneratorTarget; class cmGlobalGenerator; class cmInstallExportGenerator; @@ -97,6 +98,11 @@ protected: std::string InstallNameDir(cmGeneratorTarget const* target, const std::string& config) override; + std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet, + cmTargetExport* te) override; + std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet, + cmTargetExport* te) override; + cmInstallExportGenerator* IEGen; // The import file generated for each configuration. diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index cbe3c4d..4fe92c6 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -7,17 +7,22 @@ #include <cm/memory> +#include "cmFileSet.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmOutputConverter.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" #include "cmValue.h" +class cmTargetExport; + cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator( cmGlobalGenerator* gg, const std::vector<std::string>& targets, cmMakefile* mf, std::set<std::string> const& langs) @@ -137,3 +142,17 @@ std::string cmExportTryCompileFileGenerator::InstallNameDir( return install_name_dir; } + +std::string cmExportTryCompileFileGenerator::GetFileSetDirectories( + cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/) +{ + return cmOutputConverter::EscapeForCMake( + cmJoin(fileSet->GetDirectoryEntries(), ";")); +} + +std::string cmExportTryCompileFileGenerator::GetFileSetFiles( + cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/) +{ + return cmOutputConverter::EscapeForCMake( + cmJoin(fileSet->GetFileEntries(), ";")); +} diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index 127b8df..8a1fd7e 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -11,9 +11,11 @@ #include "cmExportFileGenerator.h" +class cmFileSet; class cmGeneratorTarget; class cmGlobalGenerator; class cmMakefile; +class cmTargetExport; class cmExportTryCompileFileGenerator : public cmExportFileGenerator { @@ -48,6 +50,13 @@ protected: std::string InstallNameDir(cmGeneratorTarget const* target, const std::string& config) override; + std::string GetFileSetDirectories(cmGeneratorTarget* target, + cmFileSet* fileSet, + cmTargetExport* te) override; + + std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet, + cmTargetExport* te) override; + private: std::string FindTargets(const std::string& prop, const cmGeneratorTarget* tgt, diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index e2c54d7..988c5c3 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -677,6 +677,12 @@ std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf) } else { compiler = "pgi"; // does not exist as default in CodeBlocks 16.01 } + } else if (compilerId == "LCC") { + if (pureFortran) { + compiler = "lfortran"; + } else { + compiler = "lcc"; + } } else if (compilerId == "GNU") { if (pureFortran) { compiler = "gfortran"; diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx index d529f52..c1df992 100644 --- a/Source/cmFileAPI.cxx +++ b/Source/cmFileAPI.cxx @@ -686,7 +686,8 @@ std::string cmFileAPI::NoSupportedVersion( // The "codemodel" object kind. -static unsigned int const CodeModelV2Minor = 3; +// Update Help/manual/cmake-file-api.7.rst when updating this constant. +static unsigned int const CodeModelV2Minor = 4; void cmFileAPI::BuildClientRequestCodeModel( ClientRequest& r, std::vector<RequestVersion> const& versions) diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 147181e..40e1d2e 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -23,11 +23,13 @@ #include "cmCryptoHash.h" #include "cmExportSet.h" #include "cmFileAPI.h" +#include "cmFileSet.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmInstallDirectoryGenerator.h" #include "cmInstallExportGenerator.h" +#include "cmInstallFileSetGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" #include "cmInstallGetRuntimeDependenciesGenerator.h" @@ -1043,6 +1045,53 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) installer["runtimeDependencySetType"] = "library"; break; } + } else if (auto* installFileSet = + dynamic_cast<cmInstallFileSetGenerator*>(gen)) { + installer["type"] = "fileSet"; + installer["destination"] = installFileSet->GetDestination(this->Config); + + auto* fileSet = installFileSet->GetFileSet(); + auto* target = installFileSet->GetTarget(); + + auto dirCges = fileSet->CompileDirectoryEntries(); + auto dirs = fileSet->EvaluateDirectoryEntries( + dirCges, target->GetLocalGenerator(), this->Config, target); + + auto entryCges = fileSet->CompileFileEntries(); + std::map<std::string, std::vector<std::string>> entries; + for (auto const& entryCge : entryCges) { + fileSet->EvaluateFileEntry(dirs, entries, entryCge, + target->GetLocalGenerator(), this->Config, + target); + } + + Json::Value files = Json::arrayValue; + for (auto const& it : entries) { + auto dir = it.first; + if (!dir.empty()) { + dir += '/'; + } + for (auto const& file : it.second) { + files.append(this->DumpInstallerPath( + this->TopSource, file, + cmStrCat(dir, cmSystemTools::GetFilenameName(file)))); + } + } + installer["paths"] = std::move(files); + installer["fileSetName"] = fileSet->GetName(); + installer["fileSetType"] = fileSet->GetType(); + installer["fileSetDirectories"] = Json::arrayValue; + for (auto const& dir : dirs) { + installer["fileSetDirectories"].append( + RelativeIfUnder(this->TopSource, dir)); + } + installer["fileSetTarget"] = Json::objectValue; + installer["fileSetTarget"]["id"] = TargetId(target, this->TopBuild); + installer["fileSetTarget"]["index"] = this->TargetIndexMap[target]; + + if (installFileSet->GetOptional()) { + installer["isOptional"] = true; + } } // Add fields common to all install generators. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index fd0595d..338f3c9 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -217,7 +217,7 @@ bool HandleReadCommand(std::vector<std::string> const& args, char c; while ((sizeLimit != 0) && (file.get(c))) { char hex[4]; - sprintf(hex, "%.2x", c & 0xff); + snprintf(hex, sizeof(hex), "%.2x", c & 0xff); output += hex; if (sizeLimit > 0) { sizeLimit--; @@ -1627,8 +1627,9 @@ size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr, case CURLINFO_SSL_DATA_IN: case CURLINFO_SSL_DATA_OUT: { char buf[128]; - int n = sprintf(buf, "[%" KWIML_INT_PRIu64 " bytes data]\n", - static_cast<KWIML_INT_uint64_t>(size)); + int n = + snprintf(buf, sizeof(buf), "[%" KWIML_INT_PRIu64 " bytes data]\n", + static_cast<KWIML_INT_uint64_t>(size)); if (n > 0) { cm::append(vec, buf, buf + n); } diff --git a/Source/cmFileLockResult.cxx b/Source/cmFileLockResult.cxx index 9d5a6c6..70b8cdb 100644 --- a/Source/cmFileLockResult.cxx +++ b/Source/cmFileLockResult.cxx @@ -5,7 +5,6 @@ #include <cerrno> #include <cstring> -#define WINMSG_BUF_LEN (1024) cmFileLockResult cmFileLockResult::MakeOk() { return { OK, 0 }; @@ -54,6 +53,7 @@ std::string cmFileLockResult::GetOutputMessage() const case SYSTEM: #if defined(_WIN32) { +# define WINMSG_BUF_LEN (1024) char winmsg[WINMSG_BUF_LEN]; DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; if (FormatMessageA(flags, NULL, this->ErrorValue, diff --git a/Source/cmFileSet.cxx b/Source/cmFileSet.cxx new file mode 100644 index 0000000..08d56ba --- /dev/null +++ b/Source/cmFileSet.cxx @@ -0,0 +1,151 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFileSet.h" + +#include <sstream> +#include <string> +#include <utility> +#include <vector> + +#include "cmGeneratorExpression.h" +#include "cmListFileCache.h" +#include "cmLocalGenerator.h" +#include "cmMessageType.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" +#include "cmake.h" + +cmFileSet::cmFileSet(std::string name, std::string type) + : Name(std::move(name)) + , Type(std::move(type)) +{ +} + +void cmFileSet::ClearDirectoryEntries() +{ + this->DirectoryEntries.clear(); +} + +void cmFileSet::AddDirectoryEntry(BT<std::string> directories) +{ + this->DirectoryEntries.push_back(std::move(directories)); +} + +void cmFileSet::ClearFileEntries() +{ + this->FileEntries.clear(); +} + +void cmFileSet::AddFileEntry(BT<std::string> files) +{ + this->FileEntries.push_back(std::move(files)); +} + +std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> +cmFileSet::CompileFileEntries() const +{ + std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result; + + for (auto const& entry : this->FileEntries) { + for (auto const& ex : cmExpandedList(entry.Value)) { + cmGeneratorExpression ge(entry.Backtrace); + auto cge = ge.Parse(ex); + result.push_back(std::move(cge)); + } + } + + return result; +} + +std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> +cmFileSet::CompileDirectoryEntries() const +{ + std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result; + + for (auto const& entry : this->DirectoryEntries) { + for (auto const& ex : cmExpandedList(entry.Value)) { + cmGeneratorExpression ge(entry.Backtrace); + auto cge = ge.Parse(ex); + result.push_back(std::move(cge)); + } + } + + return result; +} + +std::vector<std::string> cmFileSet::EvaluateDirectoryEntries( + const std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>& cges, + cmLocalGenerator* lg, const std::string& config, + const cmGeneratorTarget* target, + cmGeneratorExpressionDAGChecker* dagChecker) const +{ + std::vector<std::string> result; + for (auto const& cge : cges) { + auto entry = cge->Evaluate(lg, config, target, dagChecker); + auto dirs = cmExpandedList(entry); + for (std::string dir : dirs) { + if (!cmSystemTools::FileIsFullPath(dir)) { + dir = cmStrCat(lg->GetCurrentSourceDirectory(), '/', dir); + } + auto collapsedDir = cmSystemTools::CollapseFullPath(dir); + for (auto const& priorDir : result) { + auto collapsedPriorDir = cmSystemTools::CollapseFullPath(priorDir); + if (!cmSystemTools::SameFile(collapsedDir, collapsedPriorDir) && + (cmSystemTools::IsSubDirectory(collapsedDir, collapsedPriorDir) || + cmSystemTools::IsSubDirectory(collapsedPriorDir, collapsedDir))) { + lg->GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Base directories in file set cannot be subdirectories of each " + "other:\n ", + priorDir, "\n ", dir), + cge->GetBacktrace()); + return {}; + } + } + result.push_back(dir); + } + } + return result; +} + +void cmFileSet::EvaluateFileEntry( + const std::vector<std::string>& dirs, + std::map<std::string, std::vector<std::string>>& filesPerDir, + const std::unique_ptr<cmCompiledGeneratorExpression>& cge, + cmLocalGenerator* lg, const std::string& config, + const cmGeneratorTarget* target, + cmGeneratorExpressionDAGChecker* dagChecker) const +{ + auto files = cge->Evaluate(lg, config, target, dagChecker); + for (std::string file : cmExpandedList(files)) { + if (!cmSystemTools::FileIsFullPath(file)) { + file = cmStrCat(lg->GetCurrentSourceDirectory(), '/', file); + } + auto collapsedFile = cmSystemTools::CollapseFullPath(file); + bool found = false; + std::string relDir; + for (auto const& dir : dirs) { + auto collapsedDir = cmSystemTools::CollapseFullPath(dir); + if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) { + found = true; + relDir = cmSystemTools::GetParentDirectory( + cmSystemTools::RelativePath(collapsedDir, collapsedFile)); + break; + } + } + if (!found) { + std::ostringstream e; + e << "File:\n " << file + << "\nmust be in one of the file set's base directories:"; + for (auto const& dir : dirs) { + e << "\n " << dir; + } + lg->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), + cge->GetBacktrace()); + return; + } + + filesPerDir[relDir].push_back(file); + } +} diff --git a/Source/cmFileSet.h b/Source/cmFileSet.h new file mode 100644 index 0000000..5ee4a98 --- /dev/null +++ b/Source/cmFileSet.h @@ -0,0 +1,64 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "cmListFileCache.h" + +class cmCompiledGeneratorExpression; +struct cmGeneratorExpressionDAGChecker; +class cmGeneratorTarget; +class cmLocalGenerator; + +class cmFileSet +{ +public: + cmFileSet(std::string name, std::string type); + + const std::string& GetName() const { return this->Name; } + const std::string& GetType() const { return this->Type; } + + void ClearDirectoryEntries(); + void AddDirectoryEntry(BT<std::string> directories); + const std::vector<BT<std::string>>& GetDirectoryEntries() const + { + return this->DirectoryEntries; + } + + void ClearFileEntries(); + void AddFileEntry(BT<std::string> files); + const std::vector<BT<std::string>>& GetFileEntries() const + { + return this->FileEntries; + } + + std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> + CompileFileEntries() const; + + std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> + CompileDirectoryEntries() const; + + std::vector<std::string> EvaluateDirectoryEntries( + const std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>& cges, + cmLocalGenerator* lg, const std::string& config, + const cmGeneratorTarget* target, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; + + void EvaluateFileEntry( + const std::vector<std::string>& dirs, + std::map<std::string, std::vector<std::string>>& filesPerDir, + const std::unique_ptr<cmCompiledGeneratorExpression>& cge, + cmLocalGenerator* lg, const std::string& config, + const cmGeneratorTarget* target, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; + +private: + std::string Name; + std::string Type; + std::vector<BT<std::string>> DirectoryEntries; + std::vector<BT<std::string>> FileEntries; +}; diff --git a/Source/cmFileTime.h b/Source/cmFileTime.h index 4419880..ccc9633 100644 --- a/Source/cmFileTime.h +++ b/Source/cmFileTime.h @@ -24,6 +24,8 @@ public: #endif cmFileTime() = default; ~cmFileTime() = default; + cmFileTime(const cmFileTime&) = default; + cmFileTime& operator=(const cmFileTime&) = default; /** * @brief Loads the file time of fileName from the file system diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index bdc9207..70d59c2 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -240,14 +240,20 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) std::vector<std::string> unrootedPaths = paths; paths.clear(); + auto isSameDirectoryOrSubDirectory = [](std::string const& l, + std::string const& r) { + return (cmSystemTools::GetRealPath(l) == cmSystemTools::GetRealPath(r)) || + cmSystemTools::IsSubDirectory(l, r); + }; + for (std::string const& r : roots) { for (std::string const& up : unrootedPaths) { // Place the unrooted path under the current root if it is not // already inside. Skip the unrooted path if it is relative to // a user home directory or is empty. std::string rootedDir; - if (cmSystemTools::IsSubDirectory(up, r) || - (stagePrefix && cmSystemTools::IsSubDirectory(up, *stagePrefix))) { + if (isSameDirectoryOrSubDirectory(up, r) || + (stagePrefix && isSameDirectoryOrSubDirectory(up, *stagePrefix))) { rootedDir = up; } else if (!up.empty() && up[0] != '~') { // Start with the new root. @@ -347,7 +353,7 @@ void cmFindCommon::AddPathSuffix(std::string const& arg) this->SearchPathSuffixes.push_back(std::move(suffix)); } -void AddTrailingSlash(std::string& s) +static void AddTrailingSlash(std::string& s) { if (!s.empty() && s.back() != '/') { s += '/'; diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 335ebbe..694eb0f 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -671,7 +671,7 @@ void cmFindPackageCommand::SetVersionVariables( addDefinition(prefix, version); char buf[64]; - sprintf(buf, "%u", major); + snprintf(buf, sizeof(buf), "%u", major); addDefinition(prefix + "_MAJOR", buf); sprintf(buf, "%u", minor); addDefinition(prefix + "_MINOR", buf); diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 1c87625..9a4b063 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -104,6 +104,26 @@ struct cmFindProgramHelper } bool FileIsExecutable(std::string const& file) const { +#ifdef _WIN32 + if (!this->FileIsExecutableCMP0109(file)) { + return false; + } + // Pretend the Windows "python" app installer alias does not exist. + if (cmSystemTools::LowerCase(file).find("/windowsapps/python") != + std::string::npos) { + std::string dest; + if (cmSystemTools::ReadSymlink(file, dest) && + cmHasLiteralSuffix(dest, "\\AppInstallerPythonRedirector.exe")) { + return false; + } + } + return true; +#else + return this->FileIsExecutableCMP0109(file); +#endif + } + bool FileIsExecutableCMP0109(std::string const& file) const + { switch (this->PolicyCMP0109) { case cmPolicies::OLD: return cmSystemTools::FileExists(file, true); diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 06778b1..c86001a 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -136,7 +136,8 @@ void cmGeneratedFileStreamBase::Open(std::string const& name) this->TempName += this->TempExt; } else { char buf[64]; - sprintf(buf, "tmp%05x", cmSystemTools::RandomSeed() & 0xFFFFF); + snprintf(buf, sizeof(buf), "tmp%05x", + cmSystemTools::RandomSeed() & 0xFFFFF); this->TempName += buf; } diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index c357ee1..396e9c9 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -814,7 +814,8 @@ struct PlatformIdNode : public cmGeneratorExpressionNode } return "0"; } -} platformIdNode; +}; +static struct PlatformIdNode platformIdNode; template <cmSystemTools::CompareOp Op> struct VersionNode : public cmGeneratorExpressionNode @@ -1261,7 +1262,7 @@ static const struct DeviceLinkNode : public cmGeneratorExpressionNode } } deviceLinkNode; -std::string getLinkedTargetsContent( +static std::string getLinkedTargetsContent( cmGeneratorTarget const* target, std::string const& prop, cmGeneratorExpressionContext* context, cmGeneratorExpressionDAGChecker* dagChecker) @@ -1830,8 +1831,8 @@ static const char* targetPolicyWhitelist[] = { #undef TARGET_POLICY_STRING }; -cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt, - const char* policy) +static cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt, + const char* policy) { #define RETURN_POLICY(POLICY) \ if (strcmp(policy, #POLICY) == 0) { \ @@ -1846,7 +1847,7 @@ cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt, return cmPolicies::WARN; } -cmPolicies::PolicyID policyForString(const char* policy_id) +static cmPolicies::PolicyID policyForString(const char* policy_id) { #define RETURN_POLICY_ID(POLICY_ID) \ if (strcmp(policy_id, #POLICY_ID) == 0) { \ diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 8033ef5..2fedbd1 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -25,6 +25,7 @@ #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" +#include "cmFileSet.h" #include "cmFileTimes.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" @@ -41,6 +42,7 @@ #include "cmSourceFile.h" #include "cmSourceFileLocation.h" #include "cmSourceFileLocationKind.h" +#include "cmSourceGroup.h" #include "cmStandardLevelResolver.h" #include "cmState.h" #include "cmStringAlgorithms.h" @@ -173,9 +175,73 @@ private: BT<std::string> PropertyValue; }; -std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry> -CreateTargetPropertyEntry(const BT<std::string>& propertyValue, - bool evaluateForBuildsystem = false) +class TargetPropertyEntryFileSet + : public cmGeneratorTarget::TargetPropertyEntry +{ +public: + TargetPropertyEntryFileSet( + std::vector<std::string> dirs, bool contextSensitiveDirs, + std::unique_ptr<cmCompiledGeneratorExpression> entryCge, + const cmFileSet* fileSet, cmLinkImplItem const& item = NoLinkImplItem) + : cmGeneratorTarget::TargetPropertyEntry(item) + , BaseDirs(std::move(dirs)) + , ContextSensitiveDirs(contextSensitiveDirs) + , EntryCge(std::move(entryCge)) + , FileSet(fileSet) + { + } + + const std::string& Evaluate(cmLocalGenerator* lg, const std::string& config, + cmGeneratorTarget const* headTarget, + cmGeneratorExpressionDAGChecker* dagChecker, + std::string const& /*lang*/) const override + { + std::map<std::string, std::vector<std::string>> filesPerDir; + this->FileSet->EvaluateFileEntry(this->BaseDirs, filesPerDir, + this->EntryCge, lg, config, headTarget, + dagChecker); + + std::vector<std::string> files; + for (auto const& it : filesPerDir) { + files.insert(files.end(), it.second.begin(), it.second.end()); + } + + static std::string filesStr; + filesStr = cmJoin(files, ";"); + return filesStr; + } + + cmListFileBacktrace GetBacktrace() const override + { + return this->EntryCge->GetBacktrace(); + } + + std::string const& GetInput() const override + { + return this->EntryCge->GetInput(); + } + + bool GetHadContextSensitiveCondition() const override + { + return this->ContextSensitiveDirs || + this->EntryCge->GetHadContextSensitiveCondition(); + } + +private: + const std::vector<std::string> BaseDirs; + const bool ContextSensitiveDirs; + const std::unique_ptr<cmCompiledGeneratorExpression> EntryCge; + const cmFileSet* FileSet; +}; + +std::unique_ptr< + cmGeneratorTarget:: + TargetPropertyEntry> static CreateTargetPropertyEntry(const BT<std:: + string>& + propertyValue, + bool + evaluateForBuildsystem = + false) { if (cmGeneratorExpression::Find(propertyValue.Value) != std::string::npos) { cmGeneratorExpression ge(propertyValue.Backtrace); @@ -190,7 +256,7 @@ CreateTargetPropertyEntry(const BT<std::string>& propertyValue, cm::make_unique<TargetPropertyEntryString>(propertyValue)); } -void CreatePropertyGeneratorExpressions( +static void CreatePropertyGeneratorExpressions( cmBTStringRange entries, std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items, bool evaluateForBuildsystem = false) @@ -747,6 +813,9 @@ void handleSystemIncludesDep(cmLocalGenerator* lg, if (!depTgt->IsImported() || excludeImported) { return; } + if (depTgt->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) { + return; + } if (cmValue dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) { cmExpandList(cmGeneratorExpression::Evaluate(*dirs, lg, config, headTarget, @@ -1586,6 +1655,80 @@ void AddObjectEntries(cmGeneratorTarget const* headTarget, } } +void addFileSetEntry(cmGeneratorTarget const* headTarget, + std::string const& config, + cmGeneratorExpressionDAGChecker* dagChecker, + cmFileSet const* fileSet, + EvaluatedTargetPropertyEntries& entries) +{ + auto dirCges = fileSet->CompileDirectoryEntries(); + auto dirs = fileSet->EvaluateDirectoryEntries( + dirCges, headTarget->GetLocalGenerator(), config, headTarget, dagChecker); + bool contextSensitiveDirs = false; + for (auto const& dirCge : dirCges) { + if (dirCge->GetHadContextSensitiveCondition()) { + contextSensitiveDirs = true; + break; + } + } + cmake* cm = headTarget->GetLocalGenerator()->GetCMakeInstance(); + for (auto& entryCge : fileSet->CompileFileEntries()) { + TargetPropertyEntryFileSet tpe(dirs, contextSensitiveDirs, + std::move(entryCge), fileSet); + entries.Entries.emplace_back( + EvaluateTargetPropertyEntry(headTarget, config, "", dagChecker, tpe)); + for (auto const& file : entries.Entries.back().Values) { + auto* sf = headTarget->Makefile->GetOrCreateSource(file); + if (fileSet->GetType() == "HEADERS"_s) { + sf->SetProperty("HEADER_FILE_ONLY", "TRUE"); + } + +#ifndef CMAKE_BOOTSTRAP + std::string e; + std::string w; + auto path = sf->ResolveFullPath(&e, &w); + if (!w.empty()) { + cm->IssueMessage(MessageType::AUTHOR_WARNING, w, + headTarget->GetBacktrace()); + } + if (path.empty()) { + if (!e.empty()) { + cm->IssueMessage(MessageType::FATAL_ERROR, e, + headTarget->GetBacktrace()); + } + return; + } + bool found = false; + for (auto const& sg : headTarget->Makefile->GetSourceGroups()) { + if (sg.MatchesFiles(path)) { + found = true; + break; + } + } + if (!found) { + if (fileSet->GetType() == "HEADERS"_s) { + headTarget->Makefile->GetOrCreateSourceGroup("Header Files") + ->AddGroupFile(path); + } + } +#endif + } + } +} + +void AddFileSetEntries(cmGeneratorTarget const* headTarget, + std::string const& config, + cmGeneratorExpressionDAGChecker* dagChecker, + EvaluatedTargetPropertyEntries& entries) +{ + for (auto const& entry : headTarget->Target->GetHeaderSetsEntries()) { + for (auto const& name : cmExpandedList(entry.Value)) { + auto const* headerSet = headTarget->Target->GetFileSet(name); + addFileSetEntry(headTarget, config, dagChecker, headerSet, entries); + } + } +} + bool processSources(cmGeneratorTarget const* tgt, EvaluatedTargetPropertyEntries& entries, std::vector<BT<std::string>>& srcs, @@ -1723,10 +1866,18 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( uniqueSrcs, debugSources); } + // Collect this target's file sets. + std::vector<std::string>::size_type numFilesBefore3 = files.size(); + EvaluatedTargetPropertyEntries fileSetEntries; + AddFileSetEntries(this, config, &dagChecker, fileSetEntries); + bool contextDependentFileSets = + processSources(this, fileSetEntries, files, uniqueSrcs, debugSources); + // Determine if sources are context-dependent or not. if (!contextDependentDirectSources && !(contextDependentInterfaceSources && numFilesBefore < files.size()) && - !(contextDependentObjects && numFilesBefore2 < files.size())) { + !(contextDependentObjects && numFilesBefore2 < files.size()) && + !(contextDependentFileSets && numFilesBefore3 < files.size())) { this->SourcesAreContextDependent = Tribool::False; } else { this->SourcesAreContextDependent = Tribool::True; @@ -2923,11 +3074,11 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result, result); } -void processILibs(const std::string& config, - cmGeneratorTarget const* headTarget, cmLinkItem const& item, - cmGlobalGenerator* gg, - std::vector<cmGeneratorTarget const*>& tgts, - std::set<cmGeneratorTarget const*>& emitted) +static void processILibs(const std::string& config, + cmGeneratorTarget const* headTarget, + cmLinkItem const& item, cmGlobalGenerator* gg, + std::vector<cmGeneratorTarget const*>& tgts, + std::set<cmGeneratorTarget const*>& emitted) { if (item.Target && emitted.insert(item.Target).second) { tgts.push_back(item.Target); @@ -3314,6 +3465,22 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const return; } + std::string const& compiler = + this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID"); + + // Check for special modes: `all`, `all-major`. + if (property == "all") { + if (compiler == "NVIDIA") { + flags += " -arch=all"; + return; + } + } else if (property == "all-major") { + if (compiler == "NVIDIA") { + flags += " -arch=all-major"; + return; + } + } + struct CudaArchitecture { std::string name; @@ -3355,9 +3522,6 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const } } - std::string const& compiler = - this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID"); - if (compiler == "NVIDIA") { for (CudaArchitecture& architecture : architectures) { flags += @@ -5692,7 +5856,7 @@ std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/) return "(unset)"; } -std::string compatibilityType(CompatibleType t) +static std::string compatibilityType(CompatibleType t) { switch (t) { case BoolType: @@ -5708,7 +5872,7 @@ std::string compatibilityType(CompatibleType t) return ""; } -std::string compatibilityAgree(CompatibleType t, bool dominant) +static std::string compatibilityAgree(CompatibleType t, bool dominant) { switch (t) { case BoolType: @@ -5798,23 +5962,23 @@ std::pair<bool, bool> consistentProperty(bool lhs, bool rhs, return { lhs == rhs, lhs }; } -std::pair<bool, const char*> consistentStringProperty(const char* lhs, - const char* rhs) +static std::pair<bool, const char*> consistentStringProperty(const char* lhs, + const char* rhs) { const bool b = strcmp(lhs, rhs) == 0; return { b, b ? lhs : nullptr }; } -std::pair<bool, std::string> consistentStringProperty(const std::string& lhs, - const std::string& rhs) +static std::pair<bool, std::string> consistentStringProperty( + const std::string& lhs, const std::string& rhs) { const bool b = lhs == rhs; return { b, b ? lhs : valueAsString(nullptr) }; } -std::pair<bool, const char*> consistentNumberProperty(const char* lhs, - const char* rhs, - CompatibleType t) +static std::pair<bool, const char*> consistentNumberProperty(const char* lhs, + const char* rhs, + CompatibleType t) { char* pEnd; @@ -5865,9 +6029,9 @@ std::pair<bool, const char*> consistentProperty(const char* lhs, return { false, nullptr }; } -std::pair<bool, std::string> consistentProperty(const std::string& lhs, - const std::string& rhs, - CompatibleType t) +static std::pair<bool, std::string> consistentProperty(const std::string& lhs, + const std::string& rhs, + CompatibleType t) { const std::string null_ptr = valueAsString(nullptr); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 9914902..94eec2e 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -337,6 +337,12 @@ bool cmGlobalGenerator::CheckTargetsForType() const bool failed = false; for (const auto& generator : this->LocalGenerators) { for (const auto& target : generator->GetGeneratorTargets()) { + std::string systemName = + target->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME"); + if (systemName.find("Windows") == std::string::npos) { + continue; + } + if (target->GetType() == cmStateEnums::EXECUTABLE) { std::vector<std::string> const& configs = target->Makefile->GetGeneratorConfigs( @@ -1027,6 +1033,54 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( break; } } + + if (compilerId == "LCC") { + switch (mf->GetPolicyStatus(cmPolicies::CMP0129)) { + case cmPolicies::WARN: + if (!this->CMakeInstance->GetIsInTryCompile() && + mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0129")) { + std::ostringstream w; + /* clang-format off */ + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0129) << "\n" + "Converting " << lang << + R"( compiler id "LCC" to "GNU" for compatibility.)" + ; + /* clang-format on */ + mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); + } + CM_FALLTHROUGH; + case cmPolicies::OLD: + // OLD behavior is to convert LCC to GNU. + mf->AddDefinition(compilerIdVar, "GNU"); + if (lang == "C") { + mf->AddDefinition("CMAKE_COMPILER_IS_GNUCC", "1"); + } else if (lang == "CXX") { + mf->AddDefinition("CMAKE_COMPILER_IS_GNUCXX", "1"); + } else if (lang == "Fortran") { + mf->AddDefinition("CMAKE_COMPILER_IS_GNUG77", "1"); + } + { + // Fix compiler versions. + std::string version = "CMAKE_" + lang + "_COMPILER_VERSION"; + std::string emulated = "CMAKE_" + lang + "_SIMULATE_VERSION"; + std::string emulatedId = "CMAKE_" + lang + "_SIMULATE_ID"; + std::string const& actual = mf->GetRequiredDefinition(emulated); + mf->AddDefinition(version, actual); + mf->RemoveDefinition(emulatedId); + mf->RemoveDefinition(emulated); + } + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + mf->IssueMessage( + MessageType::FATAL_ERROR, + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0129)); + CM_FALLTHROUGH; + case cmPolicies::NEW: + // NEW behavior is to keep LCC. + break; + } + } } std::string cmGlobalGenerator::GetLanguageOutputExtension( @@ -1263,7 +1317,7 @@ void cmGlobalGenerator::Configure() // update the cache entry for the number of local generators, this is used // for progress char num[100]; - sprintf(num, "%d", static_cast<int>(this->Makefiles.size())); + snprintf(num, sizeof(num), "%d", static_cast<int>(this->Makefiles.size())); this->GetCMakeInstance()->AddCacheEntry("CMAKE_NUMBER_OF_MAKEFILES", num, "number of local generators", cmStateEnums::INTERNAL); diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 7122b9f..19c4ee3 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -156,7 +156,7 @@ std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name) encoded += i; } else { char buf[16]; - sprintf(buf, ".%02x", static_cast<unsigned int>(i)); + snprintf(buf, sizeof(buf), ".%02x", static_cast<unsigned int>(i)); encoded += buf; } } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 6876e61..58b24fc 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio7Generator.h" +#include <cassert> #include <utility> #include <vector> @@ -10,8 +11,6 @@ #include <windows.h> -#include <assert.h> - #include "cmsys/Encoding.hxx" #include "cmGeneratedFileStream.h" diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index b5a6b9f..be7f149 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -6,6 +6,7 @@ #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" +#include "cmsys/RegularExpression.hxx" #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" @@ -109,6 +110,30 @@ static const char* VSVersionToToolset( return ""; } +static std::string VSVersionToMajorString( + cmGlobalVisualStudioGenerator::VSVersion v) +{ + switch (v) { + case cmGlobalVisualStudioGenerator::VS9: + return "9"; + case cmGlobalVisualStudioGenerator::VS10: + return "10"; + case cmGlobalVisualStudioGenerator::VS11: + return "11"; + case cmGlobalVisualStudioGenerator::VS12: + return "12"; + case cmGlobalVisualStudioGenerator::VS14: + return "14"; + case cmGlobalVisualStudioGenerator::VS15: + return "15"; + case cmGlobalVisualStudioGenerator::VS16: + return "16"; + case cmGlobalVisualStudioGenerator::VS17: + return "17"; + } + return ""; +} + static const char* VSVersionToAndroidToolset( cmGlobalVisualStudioGenerator::VSVersion v) { @@ -447,15 +472,25 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( return true; } - if (!i.empty()) { - if (!this->vsSetupAPIHelper.SetVSInstance(i)) { + if (!this->ParseGeneratorInstance(i, mf)) { + return false; + } + + if (!this->GeneratorInstanceVersion.empty()) { + std::string const majorStr = VSVersionToMajorString(this->Version); + cmsys::RegularExpression versionRegex( + cmStrCat("^", majorStr, "\\.[0-9]+\\.[0-9]+\\.[0-9]+$")); + if (!versionRegex.find(this->GeneratorInstanceVersion)) { std::ostringstream e; /* clang-format off */ e << "Generator\n" " " << this->GetName() << "\n" - "could not find specified instance of Visual Studio:\n" - " " << i; + "given instance specification\n" + " " << i << "\n" + "but the version field is not 4 integer components" + " starting in " << majorStr << "." + ; /* clang-format on */ mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; @@ -463,7 +498,29 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( } std::string vsInstance; - if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { + if (!i.empty()) { + vsInstance = i; + if (!this->vsSetupAPIHelper.SetVSInstance( + this->GeneratorInstance, this->GeneratorInstanceVersion)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "could not find specified instance of Visual Studio:\n" + " " << i; + /* clang-format on */ + if (!this->GeneratorInstance.empty() && + this->GeneratorInstanceVersion.empty() && + cmSystemTools::FileIsDirectory(this->GeneratorInstance)) { + e << "\n" + "The directory exists, but the instance is not known to the " + "Visual Studio Installer, and no 'version=' field was given."; + } + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + } else if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { std::ostringstream e; /* clang-format off */ e << @@ -491,6 +548,88 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( return true; } +bool cmGlobalVisualStudioVersionedGenerator::ParseGeneratorInstance( + std::string const& is, cmMakefile* mf) +{ + this->GeneratorInstance.clear(); + this->GeneratorInstanceVersion.clear(); + + std::vector<std::string> const fields = cmTokenize(is, ","); + std::vector<std::string>::const_iterator fi = fields.begin(); + if (fi == fields.end()) { + return true; + } + + // The first field may be the VS instance. + if (fi->find('=') == fi->npos) { + this->GeneratorInstance = *fi; + ++fi; + } + + std::set<std::string> handled; + + // The rest of the fields must be key=value pairs. + for (; fi != fields.end(); ++fi) { + std::string::size_type pos = fi->find('='); + if (pos == fi->npos) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given instance specification\n" + " " << is << "\n" + "that contains a field after the first ',' with no '='." + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + std::string const key = fi->substr(0, pos); + std::string const value = fi->substr(pos + 1); + if (!handled.insert(key).second) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given instance specification\n" + " " << is << "\n" + "that contains duplicate field key '" << key << "'." + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + if (!this->ProcessGeneratorInstanceField(key, value)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given instance specification\n" + " " << is << "\n" + "that contains invalid field '" << *fi << "'." + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + } + + return true; +} + +bool cmGlobalVisualStudioVersionedGenerator::ProcessGeneratorInstanceField( + std::string const& key, std::string const& value) +{ + if (key == "version") { + this->GeneratorInstanceVersion = value; + return true; + } + return false; +} + bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance( std::string& dir) const { diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index 2aed65b..54c38d9 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -65,6 +65,9 @@ protected: std::string GetWindows10SDKMaxVersionDefault(cmMakefile*) const override; + virtual bool ProcessGeneratorInstanceField(std::string const& key, + std::string const& value); + std::string FindMSBuildCommand() override; std::string FindDevEnvCommand() override; @@ -76,5 +79,10 @@ private: class Factory17; friend class Factory17; mutable cmVSSetupAPIHelper vsSetupAPIHelper; + + bool ParseGeneratorInstance(std::string const& is, cmMakefile* mf); + + std::string GeneratorInstance; + std::string GeneratorInstanceVersion; cm::optional<std::string> LastGeneratorInstanceString; }; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index f34ef62..c8df0a7 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -833,8 +833,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateFlatClone(cmXCodeObject* orig) return obj; } -std::string GetGroupMapKeyFromPath(cmGeneratorTarget* target, - const std::string& fullpath) +static std::string GetGroupMapKeyFromPath(cmGeneratorTarget* target, + const std::string& fullpath) { std::string key(target->GetName()); key += "-"; diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index b53319f..c476d47 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -2,12 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmIDEOptions.h" +#include <cstring> #include <iterator> #include <cmext/algorithm> -#include <string.h> - #include "cmsys/String.h" #include "cmAlgorithms.h" diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index eaf88f6..52a411b 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -6,11 +6,13 @@ #include <cassert> #include <cstddef> #include <iterator> +#include <map> #include <set> #include <sstream> #include <utility> #include <cm/memory> +#include <cm/string_view> #include <cmext/string_view> #include "cmsys/Glob.hxx" @@ -18,11 +20,13 @@ #include "cmArgumentParser.h" #include "cmExecutionStatus.h" #include "cmExportSet.h" +#include "cmFileSet.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmInstallCommandArguments.h" #include "cmInstallDirectoryGenerator.h" #include "cmInstallExportGenerator.h" +#include "cmInstallFileSetGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" #include "cmInstallGetRuntimeDependenciesGenerator.h" @@ -89,6 +93,9 @@ public: bool MakeFilesFullPath(const char* modeName, const std::vector<std::string>& relFiles, std::vector<std::string>& absFiles); + bool MakeFilesFullPath(const char* modeName, const std::string& basePath, + const std::vector<std::string>& relFiles, + std::vector<std::string>& absFiles); bool CheckCMP0006(bool& failure) const; std::string GetDestination(const cmInstallCommandArguments* args, @@ -177,6 +184,19 @@ std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator( args.GetDestination()); } +std::unique_ptr<cmInstallFileSetGenerator> CreateInstallFileSetGenerator( + Helper& helper, cmTarget& target, cmFileSet* fileSet, + const std::string& destination, const cmInstallCommandArguments& args) +{ + cmInstallGenerator::MessageLevel message = + cmInstallGenerator::SelectMessageLevel(helper.Makefile); + return cm::make_unique<cmInstallFileSetGenerator>( + target.GetName(), fileSet, destination, args.GetPermissions(), + args.GetConfigurations(), args.GetComponent(), message, + args.GetExcludeFromAll(), args.GetOptional(), + helper.Makefile->GetBacktrace()); +} + void AddInstallRuntimeDependenciesGenerator( Helper& helper, cmInstallRuntimeDependencySet* runtimeDependencySet, const cmInstallCommandArguments& runtimeArgs, @@ -390,6 +410,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, std::vector<std::string> PrivateHeader; std::vector<std::string> PublicHeader; std::vector<std::string> Resource; + std::vector<std::vector<std::string>> FileSets; }; static auto const argHelper = @@ -403,7 +424,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, .Bind("INCLUDES"_s, &ArgVectors::Includes) .Bind("PRIVATE_HEADER"_s, &ArgVectors::PrivateHeader) .Bind("PUBLIC_HEADER"_s, &ArgVectors::PublicHeader) - .Bind("RESOURCE"_s, &ArgVectors::Resource); + .Bind("RESOURCE"_s, &ArgVectors::Resource) + .Bind("FILE_SET"_s, &ArgVectors::FileSets); std::vector<std::string> genericArgVector; ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector); @@ -442,6 +464,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, cmInstallCommandArguments publicHeaderArgs(helper.DefaultComponentName); cmInstallCommandArguments resourceArgs(helper.DefaultComponentName); cmInstallCommandIncludesArgument includesArgs; + std::vector<cmInstallCommandFileSetArguments> fileSetArgs( + argVectors.FileSets.size(), { helper.DefaultComponentName }); // now parse the args for specific parts of the target (e.g. LIBRARY, // RUNTIME, ARCHIVE etc. @@ -455,6 +479,15 @@ bool HandleTargetsMode(std::vector<std::string> const& args, publicHeaderArgs.Parse(argVectors.PublicHeader, &unknownArgs); resourceArgs.Parse(argVectors.Resource, &unknownArgs); includesArgs.Parse(&argVectors.Includes, &unknownArgs); + for (std::size_t i = 0; i < argVectors.FileSets.size(); i++) { + // We have to create a separate object for the parsing because + // cmArgumentParser<void>::Bind() binds to a specific address, but the + // objects in the vector can move around. So we parse in an object with a + // fixed address and then copy the data into the vector. + cmInstallCommandFileSetArguments fileSetArg(helper.DefaultComponentName); + fileSetArg.Parse(argVectors.FileSets[i], &unknownArgs); + fileSetArgs[i] = std::move(fileSetArg); + } if (!unknownArgs.empty()) { // Unknown argument. @@ -473,6 +506,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, privateHeaderArgs.SetGenericArguments(&genericArgs); publicHeaderArgs.SetGenericArguments(&genericArgs); resourceArgs.SetGenericArguments(&genericArgs); + for (auto& fileSetArg : fileSetArgs) { + fileSetArg.SetGenericArguments(&genericArgs); + } success = success && archiveArgs.Finalize(); success = success && libraryArgs.Finalize(); @@ -483,6 +519,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, success = success && privateHeaderArgs.Finalize(); success = success && publicHeaderArgs.Finalize(); success = success && resourceArgs.Finalize(); + for (auto& fileSetArg : fileSetArgs) { + success = success && fileSetArg.Finalize(); + } if (!success) { return false; @@ -493,7 +532,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args, if (archiveArgs.GetNamelinkOnly() || runtimeArgs.GetNamelinkOnly() || objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() || bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() || - publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly()) { + publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly() || + std::any_of(fileSetArgs.begin(), fileSetArgs.end(), + [](const cmInstallCommandFileSetArguments& fileSetArg) + -> bool { return fileSetArg.GetNamelinkOnly(); })) { status.SetError( "TARGETS given NAMELINK_ONLY option not in LIBRARY group. " "The NAMELINK_ONLY option may be specified only following LIBRARY."); @@ -502,7 +544,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args, if (archiveArgs.GetNamelinkSkip() || runtimeArgs.GetNamelinkSkip() || objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() || bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() || - publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip()) { + publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip() || + std::any_of(fileSetArgs.begin(), fileSetArgs.end(), + [](const cmInstallCommandFileSetArguments& fileSetArg) + -> bool { return fileSetArg.GetNamelinkSkip(); })) { status.SetError( "TARGETS given NAMELINK_SKIP option not in LIBRARY group. " "The NAMELINK_SKIP option may be specified only following LIBRARY."); @@ -515,7 +560,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args, bundleArgs.HasNamelinkComponent() || privateHeaderArgs.HasNamelinkComponent() || publicHeaderArgs.HasNamelinkComponent() || - resourceArgs.HasNamelinkComponent()) { + resourceArgs.HasNamelinkComponent() || + std::any_of(fileSetArgs.begin(), fileSetArgs.end(), + [](const cmInstallCommandFileSetArguments& fileSetArg) + -> bool { return fileSetArg.HasNamelinkComponent(); })) { status.SetError( "TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. " "The NAMELINK_COMPONENT option may be specified only following " @@ -531,12 +579,21 @@ bool HandleTargetsMode(std::vector<std::string> const& args, !libraryArgs.GetType().empty() || !runtimeArgs.GetType().empty() || !objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() || !bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() || - !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) { + !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty() || + std::any_of(fileSetArgs.begin(), fileSetArgs.end(), + [](const cmInstallCommandFileSetArguments& fileSetArg) + -> bool { return !fileSetArg.GetType().empty(); })) { status.SetError( "TARGETS given TYPE option. The TYPE option may only be specified in " " install(FILES) and install(DIRECTORIES)."); return false; } + if (std::any_of(fileSetArgs.begin(), fileSetArgs.end(), + [](const cmInstallCommandFileSetArguments& fileSetArg) + -> bool { return fileSetArg.GetFileSet().empty(); })) { + status.SetError("TARGETS given FILE_SET option without file set name."); + return false; + } cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr; if (withRuntimeDependencies) { @@ -647,6 +704,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, bool installsPrivateHeader = false; bool installsPublicHeader = false; bool installsResource = false; + std::vector<bool> installsFileSet(fileSetArgs.size(), false); // Generate install script code to install the given targets. for (cmTarget* ti : targets) { @@ -662,6 +720,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, std::unique_ptr<cmInstallFilesGenerator> privateHeaderGenerator; std::unique_ptr<cmInstallFilesGenerator> publicHeaderGenerator; std::unique_ptr<cmInstallFilesGenerator> resourceGenerator; + std::vector<std::unique_ptr<cmInstallFileSetGenerator>> fileSetGenerators; // Avoid selecting default destinations for PUBLIC_HEADER and // PRIVATE_HEADER if any artifacts are specified. @@ -670,9 +729,24 @@ bool HandleTargetsMode(std::vector<std::string> const& args, // Track whether this is a namelink-only rule. bool namelinkOnly = false; - auto addTargetExport = [&]() { + auto addTargetExport = [&]() -> bool { // Add this install rule to an export if one was specified. if (!exports.empty()) { + auto interfaceFileSets = target.GetAllInterfaceFileSets(); + if (std::any_of( + interfaceFileSets.begin(), interfaceFileSets.end(), + [=](const std::string& name) -> bool { + return !std::any_of( + fileSetArgs.begin(), fileSetArgs.end(), + [=](const cmInstallCommandFileSetArguments& fileSetArg) + -> bool { return fileSetArg.GetFileSet() == name; }); + })) { + status.SetError(cmStrCat( + "TARGETS target ", target.GetName(), + " is exported but not all of its file sets are installed")); + return false; + } + auto te = cm::make_unique<cmTargetExport>(); te->TargetName = target.GetName(); te->ArchiveGenerator = archiveGenerator.get(); @@ -682,6 +756,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, te->LibraryGenerator = libraryGenerator.get(); te->RuntimeGenerator = runtimeGenerator.get(); te->ObjectsGenerator = objectGenerator.get(); + for (auto const& gen : fileSetGenerators) { + te->FileSetGenerators[gen->GetFileSet()] = gen.get(); + } target.AddInstallIncludeDirectories( cmMakeRange(includesArgs.GetIncludeDirs())); te->NamelinkOnly = namelinkOnly; @@ -689,6 +766,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, ->GetExportSets()[exports] .AddTargetExport(std::move(te)); } + return true; }; switch (target.GetType()) { @@ -700,7 +778,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, // When in namelink only mode skip all libraries on Windows. if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) { namelinkOnly = true; - addTargetExport(); + if (!addTargetExport()) { + return false; + } continue; } @@ -736,7 +816,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, // When in namelink only mode skip frameworks. if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) { namelinkOnly = true; - addTargetExport(); + if (!addTargetExport()) { + return false; + } continue; } @@ -785,7 +867,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, // When in namelink only mode skip frameworks. if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) { namelinkOnly = true; - addTargetExport(); + if (!addTargetExport()) { + return false; + } continue; } @@ -942,9 +1026,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, helper.GetIncludeDestination(&privateHeaderArgs)); } else { std::ostringstream e; - e << "INSTALL TARGETS - target " << target.GetName() << " has " + e << "Target " << target.GetName() << " has " << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION."; - cmSystemTools::Message(e.str(), "Warning"); + helper.Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } } @@ -964,9 +1048,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, helper.GetIncludeDestination(&publicHeaderArgs)); } else { std::ostringstream e; - e << "INSTALL TARGETS - target " << target.GetName() << " has " + e << "Target " << target.GetName() << " has " << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION."; - cmSystemTools::Message(e.str(), "Warning"); + helper.Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } } @@ -983,16 +1067,47 @@ bool HandleTargetsMode(std::vector<std::string> const& args, resourceGenerator = CreateInstallFilesGenerator( helper.Makefile, absFiles, resourceArgs, false); } else if (!target.IsAppBundleOnApple()) { - cmSystemTools::Message( - cmStrCat("INSTALL TARGETS - target ", target.GetName(), - " has RESOURCE files but no RESOURCE DESTINATION."), - "Warning"); + helper.Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat("Target ", target.GetName(), + " has RESOURCE files but no RESOURCE DESTINATION.")); + } + } + } + + if (!namelinkOnly) { + for (std::size_t i = 0; i < fileSetArgs.size(); i++) { + auto* fileSet = target.GetFileSet(fileSetArgs[i].GetFileSet()); + auto interfaceFileSetEntries = cmExpandedList(target.GetSafeProperty( + cmTarget::GetInterfaceFileSetsPropertyName(fileSet->GetType()))); + if (fileSet && + std::find( + interfaceFileSetEntries.begin(), interfaceFileSetEntries.end(), + fileSetArgs[i].GetFileSet()) != interfaceFileSetEntries.end()) { + std::string destination; + if (fileSet->GetType() == "HEADERS"_s) { + destination = helper.GetIncludeDestination(&fileSetArgs[i]); + } else { + destination = fileSetArgs[i].GetDestination(); + if (destination.empty()) { + status.SetError( + cmStrCat("TARGETS given no FILE_SET DESTINATION for target \"", + target.GetName(), "\" file set \"", + fileSet->GetName(), "\".")); + return false; + } + } + fileSetGenerators.push_back(CreateInstallFileSetGenerator( + helper, target, fileSet, destination, fileSetArgs[i])); + installsFileSet[i] = true; } } } // Add this install rule to an export if one was specified. - addTargetExport(); + if (!addTargetExport()) { + return false; + } // Keep track of whether we're installing anything in each category installsArchive = installsArchive || archiveGenerator; @@ -1016,6 +1131,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, helper.Makefile->AddInstallGenerator(std::move(privateHeaderGenerator)); helper.Makefile->AddInstallGenerator(std::move(publicHeaderGenerator)); helper.Makefile->AddInstallGenerator(std::move(resourceGenerator)); + for (auto& gen : fileSetGenerators) { + helper.Makefile->AddInstallGenerator(std::move(gen)); + } } if (withRuntimeDependencies && !runtimeDependencySet->Empty()) { @@ -1067,6 +1185,12 @@ bool HandleTargetsMode(std::vector<std::string> const& args, helper.Makefile->GetGlobalGenerator()->AddInstallComponent( resourceArgs.GetComponent()); } + for (std::size_t i = 0; i < fileSetArgs.size(); i++) { + if (installsFileSet[i]) { + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( + fileSetArgs[i].GetComponent()); + } + } return true; } @@ -2063,12 +2187,20 @@ bool Helper::MakeFilesFullPath(const char* modeName, const std::vector<std::string>& relFiles, std::vector<std::string>& absFiles) { + return this->MakeFilesFullPath( + modeName, this->Makefile->GetCurrentSourceDirectory(), relFiles, absFiles); +} + +bool Helper::MakeFilesFullPath(const char* modeName, + const std::string& basePath, + const std::vector<std::string>& relFiles, + std::vector<std::string>& absFiles) +{ for (std::string const& relFile : relFiles) { std::string file = relFile; std::string::size_type gpos = cmGeneratorExpression::Find(file); if (gpos != 0 && !cmSystemTools::FileIsFullPath(file)) { - file = - cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', relFile); + file = cmStrCat(basePath, '/', relFile); } // Make sure the file is not a directory. diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx index cc3df2a..7309316 100644 --- a/Source/cmInstallCommandArguments.cxx +++ b/Source/cmInstallCommandArguments.cxx @@ -152,6 +152,11 @@ const std::string& cmInstallCommandArguments::GetType() const return this->Type; } +const std::string& cmInstallCommandArguments::GetDefaultComponent() const +{ + return this->DefaultComponentName; +} + const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations() const { @@ -220,3 +225,17 @@ void cmInstallCommandIncludesArgument::Parse( this->IncludeDirs.push_back(std::move(dir)); } } + +cmInstallCommandFileSetArguments::cmInstallCommandFileSetArguments( + std::string defaultComponent) + : cmInstallCommandArguments(std::move(defaultComponent)) +{ + this->Bind("FILE_SET"_s, this->FileSet); +} + +void cmInstallCommandFileSetArguments::Parse( + std::vector<std::string> args, std::vector<std::string>* unconsumedArgs) +{ + args.insert(args.begin(), "FILE_SET"); + this->cmInstallCommandArguments::Parse(args, unconsumedArgs); +} diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h index f318a1a..79bd945 100644 --- a/Source/cmInstallCommandArguments.h +++ b/Source/cmInstallCommandArguments.h @@ -34,6 +34,8 @@ public: bool HasNamelinkComponent() const; const std::string& GetType() const; + const std::string& GetDefaultComponent() const; + static bool CheckPermissions(const std::string& onePerm, std::string& perm); private: @@ -71,3 +73,17 @@ public: private: std::vector<std::string> IncludeDirs; }; + +class cmInstallCommandFileSetArguments : public cmInstallCommandArguments +{ +public: + cmInstallCommandFileSetArguments(std::string defaultComponent); + + void Parse(std::vector<std::string> args, + std::vector<std::string>* unconsumedArgs); + + const std::string& GetFileSet() const { return this->FileSet; } + +private: + std::string FileSet; +}; diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index d932fd9..820f24a 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -85,7 +85,9 @@ void cmInstallExportGenerator::ComputeTempDir() } if (useMD5) { // Replace the destination path with a hash to keep it short. +#ifndef CMAKE_BOOTSTRAP this->TempDir += cmSystemTools::ComputeStringMD5(this->Destination); +#endif } else { std::string dest = this->Destination; // Avoid unix full paths. diff --git a/Source/cmInstallFileSetGenerator.cxx b/Source/cmInstallFileSetGenerator.cxx new file mode 100644 index 0000000..7121ea3 --- /dev/null +++ b/Source/cmInstallFileSetGenerator.cxx @@ -0,0 +1,88 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmInstallFileSetGenerator.h" + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "cmFileSet.h" +#include "cmGeneratorExpression.h" +#include "cmGlobalGenerator.h" +#include "cmInstallType.h" +#include "cmLocalGenerator.h" +#include "cmStringAlgorithms.h" + +cmInstallFileSetGenerator::cmInstallFileSetGenerator( + std::string targetName, cmFileSet* fileSet, std::string const& dest, + std::string file_permissions, std::vector<std::string> const& configurations, + std::string const& component, MessageLevel message, bool exclude_from_all, + bool optional, cmListFileBacktrace backtrace) + : cmInstallGenerator(dest, configurations, component, message, + exclude_from_all, false, std::move(backtrace)) + , TargetName(std::move(targetName)) + , FileSet(fileSet) + , FilePermissions(std::move(file_permissions)) + , Optional(optional) +{ + this->ActionsPerConfig = true; +} + +cmInstallFileSetGenerator::~cmInstallFileSetGenerator() = default; + +bool cmInstallFileSetGenerator::Compute(cmLocalGenerator* lg) +{ + this->LocalGenerator = lg; + + // Lookup this target in the current directory. + this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName); + if (!this->Target) { + // If no local target has been found, find it in the global scope. + this->Target = + lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName); + } + + return true; +} + +std::string cmInstallFileSetGenerator::GetDestination( + std::string const& config) const +{ + return cmGeneratorExpression::Evaluate(this->Destination, + this->LocalGenerator, config); +} + +void cmInstallFileSetGenerator::GenerateScriptForConfig( + std::ostream& os, const std::string& config, Indent indent) +{ + for (auto const& dirEntry : this->CalculateFilesPerDir(config)) { + std::string destSub; + if (!dirEntry.first.empty()) { + destSub = cmStrCat('/', dirEntry.first); + } + this->AddInstallRule(os, cmStrCat(this->GetDestination(config), destSub), + cmInstallType_FILES, dirEntry.second, + this->GetOptional(), this->FilePermissions.c_str(), + nullptr, nullptr, nullptr, indent); + } +} + +std::map<std::string, std::vector<std::string>> +cmInstallFileSetGenerator::CalculateFilesPerDir( + const std::string& config) const +{ + std::map<std::string, std::vector<std::string>> result; + + auto dirCges = this->FileSet->CompileDirectoryEntries(); + auto dirs = this->FileSet->EvaluateDirectoryEntries( + dirCges, this->LocalGenerator, config, this->Target); + + auto fileCges = this->FileSet->CompileFileEntries(); + for (auto const& fileCge : fileCges) { + this->FileSet->EvaluateFileEntry( + dirs, result, fileCge, this->LocalGenerator, config, this->Target); + } + + return result; +} diff --git a/Source/cmInstallFileSetGenerator.h b/Source/cmInstallFileSetGenerator.h new file mode 100644 index 0000000..8d067d9 --- /dev/null +++ b/Source/cmInstallFileSetGenerator.h @@ -0,0 +1,52 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include <iosfwd> +#include <map> +#include <string> +#include <vector> + +#include "cmInstallGenerator.h" +#include "cmListFileCache.h" +#include "cmScriptGenerator.h" + +class cmGeneratorTarget; +class cmFileSet; +class cmLocalGenerator; + +class cmInstallFileSetGenerator : public cmInstallGenerator +{ +public: + cmInstallFileSetGenerator(std::string targetName, cmFileSet* fileSet, + std::string const& dest, + std::string file_permissions, + std::vector<std::string> const& configurations, + std::string const& component, MessageLevel message, + bool exclude_from_all, bool optional, + cmListFileBacktrace backtrace); + ~cmInstallFileSetGenerator() override; + + bool Compute(cmLocalGenerator* lg) override; + + std::string GetDestination(std::string const& config) const; + std::string GetDestination() const { return this->Destination; } + bool GetOptional() const { return this->Optional; } + cmFileSet* GetFileSet() const { return this->FileSet; } + cmGeneratorTarget* GetTarget() const { return this->Target; } + +protected: + void GenerateScriptForConfig(std::ostream& os, const std::string& config, + Indent indent) override; + +private: + std::string TargetName; + cmLocalGenerator* LocalGenerator; + cmFileSet* const FileSet; + std::string const FilePermissions; + bool const Optional; + cmGeneratorTarget* Target; + + std::map<std::string, std::vector<std::string>> CalculateFilesPerDir( + const std::string& config) const; +}; diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index 7d42fc8..b358327 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -155,7 +155,7 @@ bool HandleLengthCommand(std::vector<std::string> const& args, GetList(varArgsExpanded, listName, status.GetMakefile()); size_t length = varArgsExpanded.size(); char buffer[1024]; - sprintf(buffer, "%d", static_cast<int>(length)); + snprintf(buffer, sizeof(buffer), "%d", static_cast<int>(length)); status.GetMakefile().AddDefinition(variableName, buffer); return true; diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 2456db9..2080b40 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -44,6 +44,7 @@ namespace { const char* LastName = nullptr; +extern "C" void TrapsForSignals(int sig); extern "C" void TrapsForSignals(int sig) { fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n", diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 9b6b9abe..3a4c386 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2831,7 +2831,10 @@ void cmLocalGenerator::IncludeFileInUnitySources( unity_file << "/* " << pathToHash << " */\n" << "#undef " << *uniqueIdName << "\n" << "#define " << *uniqueIdName << " unity_" - << cmSystemTools::ComputeStringMD5(pathToHash) << "\n"; +#ifndef CMAKE_BOOTSTRAP + << cmSystemTools::ComputeStringMD5(pathToHash) << "\n" +#endif + ; } if (beforeInclude) { @@ -3505,7 +3508,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName( bool done; int cc = 0; char rpstr[100]; - sprintf(rpstr, "_p_"); + snprintf(rpstr, sizeof(rpstr), "_p_"); cmSystemTools::ReplaceString(ssin, "+", rpstr); std::string sssin = sin; do { @@ -3521,7 +3524,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName( } sssin = ssin; cmSystemTools::ReplaceString(ssin, "_p_", rpstr); - sprintf(rpstr, "_p%d_", cc++); + snprintf(rpstr, sizeof(rpstr), "_p%d_", cc++); } while (!done); } diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 7e39b91..2700ded 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1279,7 +1279,7 @@ std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable( // it is used then add number to the end of the variable while (this->ShortMakeVariableMap.count(ret) && ni < 1000) { ++ni; - sprintf(buffer, "%04d", ni); + snprintf(buffer, sizeof(buffer), "%04d", ni); ret = unmodified + buffer; } this->ShortMakeVariableMap[ret] = "1"; @@ -1304,11 +1304,11 @@ std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable( } char buffer[5]; int ni = 0; - sprintf(buffer, "%04d", ni); + snprintf(buffer, sizeof(buffer), "%04d", ni); ret = str1 + str2 + buffer; while (this->ShortMakeVariableMap.count(ret) && ni < 1000) { ++ni; - sprintf(buffer, "%04d", ni); + snprintf(buffer, sizeof(buffer), "%04d", ni); ret = str1 + str2 + buffer; } if (ni == 1000) { diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 5d3e11a..7223049 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -2,13 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLocalVisualStudio7Generator.h" +#include <cctype> // for isspace + #include <cm/memory> #include <cmext/algorithm> #include <windows.h> #include <cm3p/expat.h> -#include <ctype.h> // for isspace #include "cmComputeLinkInformation.h" #include "cmCustomCommand.h" diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx index 53112e0..4fcaedf 100644 --- a/Source/cmMachO.cxx +++ b/Source/cmMachO.cxx @@ -56,7 +56,7 @@ bool peek(cmsys::ifstream& fin, T& v) template <typename T> bool read(cmsys::ifstream& fin, T& v) { - return !!fin.read(reinterpret_cast<char*>(&v), sizeof(T)); + return static_cast<bool>(fin.read(reinterpret_cast<char*>(&v), sizeof(T))); } // read from the file and fill multiple data structures where @@ -68,7 +68,8 @@ bool read(cmsys::ifstream& fin, std::vector<T>& v) if (v.empty()) { return true; } - return !!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size()); + return static_cast<bool>( + fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size())); } } @@ -340,7 +341,8 @@ bool cmMachO::GetInstallName(std::string& install_name) if (lc_cmd == LC_ID_DYLIB || lc_cmd == LC_LOAD_WEAK_DYLIB || lc_cmd == LC_LOAD_DYLIB) { if (sizeof(dylib_command) < cmd.LoadCommand.size()) { - uint32_t namelen = cmd.LoadCommand.size() - sizeof(dylib_command); + uint32_t namelen = static_cast<uint32_t>(cmd.LoadCommand.size() - + sizeof(dylib_command)); install_name.assign(&cmd.LoadCommand[sizeof(dylib_command)], namelen); return true; } diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 8c4b2a7..154df63 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -77,7 +77,7 @@ bool cmMacroHelperCommand::operator()( argVs.reserve(expandedArgs.size()); char argvName[60]; for (unsigned int j = 0; j < expandedArgs.size(); ++j) { - sprintf(argvName, "${ARGV%u}", j); + snprintf(argvName, sizeof(argvName), "${ARGV%u}", j); argVs.emplace_back(argvName); } // Invoke all the functions that were collected in the block. diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 83984f7..bf3e217 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -134,8 +134,8 @@ cmDirectoryId cmMakefile::GetDirectoryId() const // If we ever need to expose this to CMake language code we should // add a read-only property in cmMakefile::GetProperty. char buf[32]; - sprintf(buf, "(%p)", - static_cast<void const*>(this)); // cast avoids format warning + snprintf(buf, sizeof(buf), "(%p)", + static_cast<void const*>(this)); // cast avoids format warning return std::string(buf); } @@ -4427,11 +4427,12 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, } // Deprecate old policies. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0088 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0094 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. - id == cmPolicies::CMP0065 || id == cmPolicies::CMP0083))) { + id == cmPolicies::CMP0065 || id == cmPolicies::CMP0083 || + id == cmPolicies::CMP0091))) { this->IssueMessage(MessageType::DEPRECATION_WARNING, cmPolicies::GetPolicyDeprecatedWarning(id)); } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 8edadd3..4e5913e 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -897,28 +897,31 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Construct the compile rules. { - std::vector<std::string> compileCommands; + std::string cudaCompileMode; if (lang == "CUDA") { - std::string cmdVar; if (this->GeneratorTarget->GetPropertyAsBool( "CUDA_SEPARABLE_COMPILATION")) { - cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION"; - } else if (this->GeneratorTarget->GetPropertyAsBool( - "CUDA_PTX_COMPILATION")) { - cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION"; + const std::string& rdcFlag = + this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_RDC_FLAG"); + cudaCompileMode = cmStrCat(cudaCompileMode, rdcFlag, " "); + } + if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) { + const std::string& ptxFlag = + this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_PTX_FLAG"); + cudaCompileMode = cmStrCat(cudaCompileMode, ptxFlag); } else { - cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION"; + const std::string& wholeFlag = + this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_WHOLE_FLAG"); + cudaCompileMode = cmStrCat(cudaCompileMode, wholeFlag); } - const std::string& compileRule = - this->Makefile->GetRequiredDefinition(cmdVar); - cmExpandList(compileRule, compileCommands); - } else { - const std::string cmdVar = "CMAKE_" + lang + "_COMPILE_OBJECT"; - const std::string& compileRule = - this->Makefile->GetRequiredDefinition(cmdVar); - cmExpandList(compileRule, compileCommands); + vars.CudaCompileMode = cudaCompileMode.c_str(); } + std::vector<std::string> compileCommands; + const std::string& compileRule = this->Makefile->GetRequiredDefinition( + "CMAKE_" + lang + "_COMPILE_OBJECT"); + cmExpandList(compileRule, compileCommands); + if (this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS") && lang_can_export_cmds && compileCommands.size() == 1) { std::string compileCommand = compileCommands[0]; @@ -2173,7 +2176,7 @@ void cmMakefileTargetGenerator::CreateObjectLists( for (unsigned int i = 0; i < object_strings.size(); ++i) { // Number the response files. char rsp[32]; - sprintf(rsp, "objects%u.rsp", i + 1); + snprintf(rsp, sizeof(rsp), "objects%u.rsp", i + 1); // Create this response file. std::string objects_rsp = diff --git a/Source/cmMathCommand.cxx b/Source/cmMathCommand.cxx index 56221bf..df9ebcf 100644 --- a/Source/cmMathCommand.cxx +++ b/Source/cmMathCommand.cxx @@ -107,7 +107,7 @@ bool HandleExprCommand(std::vector<std::string> const& args, fmt = "%" KWIML_INT_PRId64; break; } - sprintf(buffer, fmt, helper.GetResult()); + snprintf(buffer, sizeof(buffer), fmt, helper.GetResult()); std::string const& w = helper.GetWarning(); if (!w.empty()) { diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index 1cb638a..2eead6b 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -102,7 +102,7 @@ static int getMessageColor(MessageType t) } } -void printMessageText(std::ostream& msg, std::string const& text) +static void printMessageText(std::ostream& msg, std::string const& text) { msg << ":\n"; cmDocumentationFormatter formatter; @@ -110,7 +110,7 @@ void printMessageText(std::ostream& msg, std::string const& text) formatter.PrintFormatted(msg, text.c_str()); } -void displayMessage(MessageType t, std::ostringstream& msg) +static void displayMessage(MessageType t, std::ostringstream& msg) { // Add a note about warning suppression. if (t == MessageType::AUTHOR_WARNING) { @@ -155,19 +155,16 @@ void cmMessenger::IssueMessage(MessageType t, const std::string& text, const cmListFileBacktrace& backtrace) const { bool force = false; - if (!force) { - // override the message type, if needed, for warnings and errors - MessageType override = this->ConvertMessageType(t); - if (override != t) { - t = override; - force = true; - } + // override the message type, if needed, for warnings and errors + MessageType override = this->ConvertMessageType(t); + if (override != t) { + t = override; + force = true; } - if (!force && !this->IsMessageTypeVisible(t)) { - return; + if (force || this->IsMessageTypeVisible(t)) { + this->DisplayMessage(t, text, backtrace); } - this->DisplayMessage(t, text, backtrace); } void cmMessenger::DisplayMessage(MessageType t, const std::string& text, diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 57657b1..231433f 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -605,6 +605,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, vars.TargetCompilePDB = "$TARGET_COMPILE_PDB"; vars.ObjectDir = "$OBJECT_DIR"; vars.ObjectFileDir = "$OBJECT_FILE_DIR"; + vars.CudaCompileMode = "$CUDA_COMPILE_MODE"; vars.ISPCHeader = "$ISPC_HEADER_FILE"; cmMakefile* mf = this->GetMakefile(); @@ -815,27 +816,32 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, vars.Flags = flags.c_str(); vars.DependencyFile = rule.DepFile.c_str(); - // Rule for compiling object file. - std::vector<std::string> compileCmds; + std::string cudaCompileMode; if (lang == "CUDA") { - std::string cmdVar; if (this->GeneratorTarget->GetPropertyAsBool( "CUDA_SEPARABLE_COMPILATION")) { - cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION"; - } else if (this->GeneratorTarget->GetPropertyAsBool( - "CUDA_PTX_COMPILATION")) { - cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION"; + const std::string& rdcFlag = + this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_RDC_FLAG"); + cudaCompileMode = cmStrCat(cudaCompileMode, rdcFlag, " "); + } + if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) { + const std::string& ptxFlag = + this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_PTX_FLAG"); + cudaCompileMode = cmStrCat(cudaCompileMode, ptxFlag); } else { - cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION"; + const std::string& wholeFlag = + this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_WHOLE_FLAG"); + cudaCompileMode = cmStrCat(cudaCompileMode, wholeFlag); } - const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar); - cmExpandList(compileCmd, compileCmds); - } else { - const std::string cmdVar = cmStrCat("CMAKE_", lang, "_COMPILE_OBJECT"); - const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar); - cmExpandList(compileCmd, compileCmds); + vars.CudaCompileMode = cudaCompileMode.c_str(); } + // Rule for compiling object file. + std::vector<std::string> compileCmds; + const std::string cmdVar = cmStrCat("CMAKE_", lang, "_COMPILE_OBJECT"); + const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar); + cmExpandList(compileCmd, compileCmds); + // See if we need to use a compiler launcher like ccache or distcc std::string compilerLauncher; if (!compileCmds.empty() && diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index 2b785e1..02b4821 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -219,10 +219,11 @@ std::string cmOutputConverter::EscapeForShell( return Shell_GetArgument(str, flags); } -std::string cmOutputConverter::EscapeForCMake(cm::string_view str) +std::string cmOutputConverter::EscapeForCMake(cm::string_view str, + WrapQuotes wrapQuotes) { // Always double-quote the argument to take care of most escapes. - std::string result = "\""; + std::string result = (wrapQuotes == WrapQuotes::Wrap) ? "\"" : ""; for (const char c : str) { if (c == '"') { // Escape the double quote to avoid ending the argument. @@ -238,7 +239,9 @@ std::string cmOutputConverter::EscapeForCMake(cm::string_view str) result += c; } } - result += "\""; + if (wrapQuotes == WrapQuotes::Wrap) { + result += "\""; + } return result; } diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index 865df71..53ec247 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -94,7 +94,13 @@ public: bool forEcho = false, bool useWatcomQuote = false, bool unescapeNinjaConfiguration = false) const; - static std::string EscapeForCMake(cm::string_view str); + enum class WrapQuotes + { + Wrap, + NoWrap, + }; + static std::string EscapeForCMake(cm::string_view str, + WrapQuotes wrapQuotes = WrapQuotes::Wrap); /** Compute an escaped version of the given argument for use in a windows shell. */ diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 23000fa..e31de1c 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -103,7 +103,7 @@ static bool isPolicyNewerThan(cmPolicies::PolicyID id, unsigned int majorV, return false; } -const char* idToShortDescription(cmPolicies::PolicyID id) +static const char* idToShortDescription(cmPolicies::PolicyID id) { switch (id) { #define POLICY_CASE(ID, SHORT_DESCRIPTION) \ diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index ce04117..99e2eb6 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -385,7 +385,10 @@ class cmMakefile; 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0128, \ "Selection of language standard and extension flags improved.", 3, \ - 22, 0, cmPolicies::WARN) + 22, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0129, \ + "Compiler id for MCST LCC compilers is now LCC, not GNU.", 3, 23, 0, \ + cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 20fcdbe..04d99c9 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -235,14 +235,15 @@ bool cmProjectCommand(std::vector<std::string> const& args, std::array<std::string, MAX_VERSION_COMPONENTS> version_components; if (cmp0096 == cmPolicies::OLD || cmp0096 == cmPolicies::WARN) { - char vb[MAX_VERSION_COMPONENTS] - [std::numeric_limits<unsigned>::digits10 + 2]; + constexpr size_t maxIntLength = + std::numeric_limits<unsigned>::digits10 + 2; + char vb[MAX_VERSION_COMPONENTS][maxIntLength]; unsigned v[MAX_VERSION_COMPONENTS] = { 0, 0, 0, 0 }; const int vc = std::sscanf(version.c_str(), "%u.%u.%u.%u", &v[0], &v[1], &v[2], &v[3]); for (auto i = 0u; i < MAX_VERSION_COMPONENTS; ++i) { if (int(i) < vc) { - std::sprintf(vb[i], "%u", v[i]); + std::snprintf(vb[i], maxIntLength, "%u", v[i]); version_string += &"."[std::size_t(i == 0)]; version_string += vb[i]; version_components[i] = vb[i]; diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 9584e5c..0a394b5 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -22,10 +22,10 @@ /// @brief Merges newOpts into baseOpts /// @arg valueOpts list of options that accept a value -void MergeOptions(std::vector<std::string>& baseOpts, - std::vector<std::string> const& newOpts, - std::initializer_list<cm::string_view> valueOpts, - bool isQt5OrLater) +static void MergeOptions(std::vector<std::string>& baseOpts, + std::vector<std::string> const& newOpts, + std::initializer_list<cm::string_view> valueOpts, + bool isQt5OrLater) { if (newOpts.empty()) { return; diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx index 7480aeb..4cee09d 100644 --- a/Source/cmRulePlaceholderExpander.cxx +++ b/Source/cmRulePlaceholderExpander.cxx @@ -85,6 +85,11 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( return replaceValues.ObjectsQuoted; } } + if (replaceValues.CudaCompileMode) { + if (variable == "CUDA_COMPILE_MODE") { + return replaceValues.CudaCompileMode; + } + } if (replaceValues.AIXExports) { if (variable == "AIX_EXPORTS") { return replaceValues.AIXExports; diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h index c22e0fa..852954f 100644 --- a/Source/cmRulePlaceholderExpander.h +++ b/Source/cmRulePlaceholderExpander.h @@ -65,6 +65,7 @@ public: const char* SwiftOutputFileMap = nullptr; const char* SwiftSources = nullptr; const char* ISPCHeader = nullptr; + const char* CudaCompileMode = nullptr; const char* Fatbinary = nullptr; const char* RegisterFile = nullptr; const char* Launcher = nullptr; diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h index c15cb97..09f9722 100644 --- a/Source/cmSearchPath.h +++ b/Source/cmSearchPath.h @@ -26,6 +26,9 @@ public: cmSearchPath(cmFindCommon* findCmd = nullptr); ~cmSearchPath(); + cmSearchPath(const cmSearchPath&) = default; + cmSearchPath& operator=(const cmSearchPath&) = default; + const std::vector<std::string>& GetPaths() const { return this->Paths; } std::size_t size() const { return this->Paths.size(); } diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index f44fcf7..e5935b8 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -526,7 +526,7 @@ bool HandleLengthCommand(std::vector<std::string> const& args, size_t length = stringValue.size(); char buffer[1024]; - sprintf(buffer, "%d", static_cast<int>(length)); + snprintf(buffer, sizeof(buffer), "%d", static_cast<int>(length)); status.GetMakefile().AddDefinition(variableName, buffer); return true; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 75a5a8d..3699be3 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -540,7 +540,7 @@ size_t cmSystemTools::CalculateCommandLineLengthLimit() #if defined(_SC_ARG_MAX) // ARG_MAX is the maximum size of the command and environment // that can be passed to the exec functions on UNIX. - // The value in limits.h does not need to be present and may + // The value in climits does not need to be present and may // depend upon runtime memory constraints, hence sysconf() // should be used to query it. long szArgMax = sysconf(_SC_ARG_MAX); @@ -1158,39 +1158,26 @@ void cmSystemTools::MoveFileIfDifferent(const std::string& source, RemoveFile(source); } +#ifndef CMAKE_BOOTSTRAP std::string cmSystemTools::ComputeFileHash(const std::string& source, cmCryptoHash::Algo algo) { -#if !defined(CMAKE_BOOTSTRAP) cmCryptoHash hash(algo); return hash.HashFile(source); -#else - (void)source; - cmSystemTools::Message("hashsum not supported in bootstrapping mode", - "Error"); - return std::string(); -#endif } std::string cmSystemTools::ComputeStringMD5(const std::string& input) { -#if !defined(CMAKE_BOOTSTRAP) cmCryptoHash md5(cmCryptoHash::AlgoMD5); return md5.HashString(input); -#else - (void)input; - cmSystemTools::Message("md5sum not supported in bootstrapping mode", - "Error"); - return ""; -#endif } +# ifdef _WIN32 std::string cmSystemTools::ComputeCertificateThumbprint( const std::string& source) { std::string thumbprint; -#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) CRYPT_INTEGER_BLOB cryptBlob; HCERTSTORE certStore = NULL; PCCERT_CONTEXT certContext = NULL; @@ -1247,14 +1234,11 @@ std::string cmSystemTools::ComputeCertificateThumbprint( } CloseHandle(certFile); } -#else - (void)source; - cmSystemTools::Message("ComputeCertificateThumbprint is not implemented", - "Error"); -#endif return thumbprint; } +# endif +#endif void cmSystemTools::Glob(const std::string& directory, const std::string& regexp, @@ -1693,7 +1677,8 @@ void list_item_verbose(FILE* out, struct archive_entry* entry) /* Use uname if it's present, else uid. */ p = archive_entry_uname(entry); if ((p == nullptr) || (*p == '\0')) { - sprintf(tmp, "%lu ", static_cast<unsigned long>(archive_entry_uid(entry))); + snprintf(tmp, sizeof(tmp), "%lu ", + static_cast<unsigned long>(archive_entry_uid(entry))); p = tmp; } w = strlen(p); @@ -1707,7 +1692,8 @@ void list_item_verbose(FILE* out, struct archive_entry* entry) fprintf(out, "%s", p); w = strlen(p); } else { - sprintf(tmp, "%lu", static_cast<unsigned long>(archive_entry_gid(entry))); + snprintf(tmp, sizeof(tmp), "%lu", + static_cast<unsigned long>(archive_entry_gid(entry))); w = strlen(tmp); fprintf(out, "%s", tmp); } @@ -1721,15 +1707,15 @@ void list_item_verbose(FILE* out, struct archive_entry* entry) archive_entry_filetype(entry) == AE_IFBLK) { unsigned long rdevmajor = archive_entry_rdevmajor(entry); unsigned long rdevminor = archive_entry_rdevminor(entry); - sprintf(tmp, "%lu,%lu", rdevmajor, rdevminor); + snprintf(tmp, sizeof(tmp), "%lu,%lu", rdevmajor, rdevminor); } else { /* * Note the use of platform-dependent macros to format * the filesize here. We need the format string and the * corresponding type for the cast. */ - sprintf(tmp, BSDTAR_FILESIZE_PRINTF, - static_cast<BSDTAR_FILESIZE_TYPE>(archive_entry_size(entry))); + snprintf(tmp, sizeof(tmp), BSDTAR_FILESIZE_PRINTF, + static_cast<BSDTAR_FILESIZE_TYPE>(archive_entry_size(entry))); } if (w + strlen(tmp) >= gs_width) { gs_width = w + strlen(tmp) + 1; @@ -2496,8 +2482,8 @@ bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath, return false; } -std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have, - cm::string_view const& want) +static std::string::size_type cmSystemToolsFindRPath( + cm::string_view const& have, cm::string_view const& want) { std::string::size_type pos = 0; while (pos < have.size()) { @@ -2694,11 +2680,11 @@ std::function<bool(std::string*, const cmELF&)> MakeEmptyCallback( } } -cm::optional<bool> ChangeRPathELF(std::string const& file, - std::string const& oldRPath, - std::string const& newRPath, - bool removeEnvironmentRPath, - std::string* emsg, bool* changed) +static cm::optional<bool> ChangeRPathELF(std::string const& file, + std::string const& oldRPath, + std::string const& newRPath, + bool removeEnvironmentRPath, + std::string* emsg, bool* changed) { auto adjustCallback = [oldRPath, newRPath, removeEnvironmentRPath]( cm::optional<std::string>& outRPath, @@ -3289,7 +3275,7 @@ std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes) case ' ': case '=': case '%': - sprintf(hexCh, "%%%02X", static_cast<int>(c)); + snprintf(hexCh, sizeof(hexCh), "%%%02X", static_cast<int>(c)); break; case '/': if (escapeSlashes) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 715724c..19dabe8 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -179,6 +179,7 @@ public: static void MoveFileIfDifferent(const std::string& source, const std::string& destination); +#ifndef CMAKE_BOOTSTRAP //! Compute the hash of a file static std::string ComputeFileHash(const std::string& source, cmCryptoHash::Algo algo); @@ -186,8 +187,11 @@ public: /** Compute the md5sum of a string. */ static std::string ComputeStringMD5(const std::string& input); +# ifdef _WIN32 //! Get the SHA thumbprint for a certificate file static std::string ComputeCertificateThumbprint(const std::string& source); +# endif +#endif /** * Run a single executable command diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 97d60cf..4f0dc60 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -14,11 +14,13 @@ #include <cm/memory> #include <cmext/algorithm> +#include <cmext/string_view> #include "cmsys/RegularExpression.hxx" #include "cmAlgorithms.h" #include "cmCustomCommand.h" +#include "cmFileSet.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -200,8 +202,11 @@ public: std::vector<BT<std::string>> LinkOptionsEntries; std::vector<BT<std::string>> LinkDirectoriesEntries; std::vector<BT<std::string>> LinkImplementationPropertyEntries; + std::vector<BT<std::string>> HeaderSetsEntries; + std::vector<BT<std::string>> InterfaceHeaderSetsEntries; std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>> TLLCommands; + std::map<std::string, cmFileSet> FileSets; cmListFileBacktrace Backtrace; bool CheckImportedLibName(std::string const& prop, @@ -1110,6 +1115,16 @@ cmBTStringRange cmTarget::GetLinkImplementationEntries() const return cmMakeRange(this->impl->LinkImplementationPropertyEntries); } +cmBTStringRange cmTarget::GetHeaderSetsEntries() const +{ + return cmMakeRange(this->impl->HeaderSetsEntries); +} + +cmBTStringRange cmTarget::GetInterfaceHeaderSetsEntries() const +{ + return cmMakeRange(this->impl->InterfaceHeaderSetsEntries); +} + namespace { #define MAKE_PROP(PROP) const std::string prop##PROP = #PROP MAKE_PROP(C_STANDARD); @@ -1139,6 +1154,10 @@ MAKE_PROP(BINARY_DIR); MAKE_PROP(SOURCE_DIR); MAKE_PROP(FALSE); MAKE_PROP(TRUE); +MAKE_PROP(HEADER_DIRS); +MAKE_PROP(HEADER_SET); +MAKE_PROP(HEADER_SETS); +MAKE_PROP(INTERFACE_HEADER_SETS); #undef MAKE_PROP } @@ -1158,6 +1177,21 @@ std::string ConvertToString<cmValue>(cmValue value) { return std::string(*value); } + +template <typename ValueType> +bool StringIsEmpty(ValueType value); + +template <> +bool StringIsEmpty<const char*>(const char* value) +{ + return cmValue::IsEmpty(value); +} + +template <> +bool StringIsEmpty<cmValue>(cmValue value) +{ + return value.IsEmpty(); +} } template <typename ValueType> @@ -1321,6 +1355,104 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value) } else { this->impl->LanguageStandardProperties.erase(prop); } + } else if (prop == propHEADER_DIRS) { + auto* fileSet = this->GetFileSet("HEADERS"); + if (!fileSet) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "The default header set has not yet been created."); + return; + } + fileSet->ClearDirectoryEntries(); + if (!StringIsEmpty(value)) { + fileSet->AddDirectoryEntry( + BT<std::string>(value, this->impl->Makefile->GetBacktrace())); + } + } else if (prop == propHEADER_SET) { + auto* fileSet = this->GetFileSet("HEADERS"); + if (!fileSet) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "The default header set has not yet been created."); + return; + } + fileSet->ClearFileEntries(); + if (!StringIsEmpty(value)) { + fileSet->AddFileEntry( + BT<std::string>(value, this->impl->Makefile->GetBacktrace())); + } + } else if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) { + auto fileSetName = prop.substr(cmStrLen("HEADER_DIRS_")); + if (fileSetName.empty()) { + this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "Header set name cannot be empty."); + return; + } + auto* fileSet = this->GetFileSet(fileSetName); + if (!fileSet) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Header set \"", fileSetName, + "\" has not yet been created.")); + return; + } + fileSet->ClearDirectoryEntries(); + if (!StringIsEmpty(value)) { + fileSet->AddDirectoryEntry( + BT<std::string>(value, this->impl->Makefile->GetBacktrace())); + } + } else if (cmHasLiteralPrefix(prop, "HEADER_SET_")) { + auto fileSetName = prop.substr(cmStrLen("HEADER_SET_")); + if (fileSetName.empty()) { + this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "Header set name cannot be empty."); + return; + } + auto* fileSet = this->GetFileSet(fileSetName); + if (!fileSet) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Header set \"", fileSetName, + "\" has not yet been created.")); + return; + } + fileSet->ClearFileEntries(); + if (!StringIsEmpty(value)) { + fileSet->AddFileEntry( + BT<std::string>(value, this->impl->Makefile->GetBacktrace())); + } + } else if (prop == propHEADER_SETS) { + if (value) { + for (auto const& name : cmExpandedList(value)) { + if (!this->GetFileSet(name)) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Header set \"", name, "\" has not yet been created.")); + return; + } + } + } + this->impl->HeaderSetsEntries.clear(); + if (!StringIsEmpty(value)) { + this->impl->HeaderSetsEntries.emplace_back( + value, this->impl->Makefile->GetBacktrace()); + } + } else if (prop == propINTERFACE_HEADER_SETS) { + if (value) { + for (auto const& name : cmExpandedList(value)) { + if (!this->GetFileSet(name)) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Header set \"", name, "\" has not yet been created.")); + return; + } + } + } + this->impl->InterfaceHeaderSetsEntries.clear(); + if (!StringIsEmpty(value)) { + this->impl->InterfaceHeaderSetsEntries.emplace_back( + value, this->impl->Makefile->GetBacktrace()); + } } else { this->impl->Properties.SetProperty(prop, value); } @@ -1415,6 +1547,82 @@ void cmTarget::AppendProperty(const std::string& prop, prop == "OBJC_STANDARD" || prop == "OBJCXX_STANDARD") { this->impl->Makefile->IssueMessage( MessageType::FATAL_ERROR, prop + " property may not be appended."); + } else if (prop == "HEADER_DIRS") { + auto* fileSet = this->GetFileSet("HEADERS"); + if (!fileSet) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "The default header set has not yet been created."); + return; + } + fileSet->AddDirectoryEntry( + BT<std::string>(value, this->impl->Makefile->GetBacktrace())); + } else if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) { + auto fileSetName = prop.substr(cmStrLen("HEADER_DIRS_")); + if (fileSetName.empty()) { + this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "Header set name cannot be empty."); + return; + } + auto* fileSet = this->GetFileSet(fileSetName); + if (!fileSet) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Header set \"", fileSetName, + "\" has not yet been created.")); + return; + } + fileSet->AddDirectoryEntry( + BT<std::string>(value, this->impl->Makefile->GetBacktrace())); + } else if (prop == "HEADER_SET") { + auto* fileSet = this->GetFileSet("HEADERS"); + if (!fileSet) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "The default header set has not yet been created."); + return; + } + fileSet->AddFileEntry( + BT<std::string>(value, this->impl->Makefile->GetBacktrace())); + } else if (cmHasLiteralPrefix(prop, "HEADER_SET_")) { + auto fileSetName = prop.substr(cmStrLen("HEADER_SET_")); + if (fileSetName.empty()) { + this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "Header set name cannot be empty."); + return; + } + auto* fileSet = this->GetFileSet(fileSetName); + if (!fileSet) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Header set \"", fileSetName, + "\" has not yet been created.")); + return; + } + fileSet->AddFileEntry( + BT<std::string>(value, this->impl->Makefile->GetBacktrace())); + } else if (prop == "HEADER_SETS") { + for (auto const& name : cmExpandedList(value)) { + if (!this->GetFileSet(name)) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Header set \"", name, "\" has not yet been created.")); + return; + } + } + this->impl->HeaderSetsEntries.emplace_back( + value, this->impl->Makefile->GetBacktrace()); + } else if (prop == "INTERFACE_HEADER_SETS") { + for (auto const& name : cmExpandedList(value)) { + if (!this->GetFileSet(name)) { + this->impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Header set \"", name, "\" has not yet been created.")); + return; + } + } + this->impl->InterfaceHeaderSetsEntries.emplace_back( + value, this->impl->Makefile->GetBacktrace()); } else { this->impl->Properties.AppendProperty(prop, value, asString); } @@ -1633,7 +1841,11 @@ cmValue cmTarget::GetProperty(const std::string& prop) const propNAME, propBINARY_DIR, propSOURCE_DIR, - propSOURCES + propSOURCES, + propHEADER_DIRS, + propHEADER_SET, + propHEADER_SETS, + propINTERFACE_HEADER_SETS, }; if (specialProps.count(prop)) { if (prop == propC_STANDARD || prop == propCXX_STANDARD || @@ -1759,6 +1971,60 @@ cmValue cmTarget::GetProperty(const std::string& prop) const .GetDirectory() .GetCurrentSource()); } + if (prop == propHEADER_DIRS) { + auto const* fileSet = this->GetFileSet("HEADERS"); + if (!fileSet) { + return nullptr; + } + static std::string output; + output = cmJoin(fileSet->GetDirectoryEntries(), ";"_s); + return cmValue(output); + } + if (prop == propHEADER_SET) { + auto const* fileSet = this->GetFileSet("HEADERS"); + if (!fileSet) { + return nullptr; + } + static std::string output; + output = cmJoin(fileSet->GetFileEntries(), ";"_s); + return cmValue(output); + } + if (prop == propHEADER_SETS) { + static std::string output; + output = cmJoin(this->impl->HeaderSetsEntries, ";"_s); + return cmValue(output); + } + if (prop == propINTERFACE_HEADER_SETS) { + static std::string output; + output = cmJoin(this->impl->InterfaceHeaderSetsEntries, ";"_s); + return cmValue(output); + } + } + if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) { + std::string fileSetName = prop.substr(cmStrLen("HEADER_DIRS_")); + if (fileSetName.empty()) { + return nullptr; + } + auto const* fileSet = this->GetFileSet(fileSetName); + if (!fileSet) { + return nullptr; + } + static std::string output; + output = cmJoin(fileSet->GetDirectoryEntries(), ";"_s); + return cmValue(output); + } + if (cmHasLiteralPrefix(prop, "HEADER_SET_")) { + std::string fileSetName = prop.substr(cmStrLen("HEADER_SET_")); + if (fileSetName.empty()) { + return nullptr; + } + auto const* fileSet = this->GetFileSet(fileSetName); + if (!fileSet) { + return nullptr; + } + static std::string output; + output = cmJoin(fileSet->GetFileEntries(), ";"_s); + return cmValue(output); } cmValue retVal = this->impl->Properties.GetPropertyValue(prop); @@ -2015,6 +2281,59 @@ std::string cmTarget::ImportedGetFullPath( return result; } +const cmFileSet* cmTarget::GetFileSet(const std::string& name) const +{ + auto it = this->impl->FileSets.find(name); + return it == this->impl->FileSets.end() ? nullptr : &it->second; +} + +cmFileSet* cmTarget::GetFileSet(const std::string& name) +{ + auto it = this->impl->FileSets.find(name); + return it == this->impl->FileSets.end() ? nullptr : &it->second; +} + +std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet( + const std::string& name, const std::string& type) +{ + auto result = + this->impl->FileSets.emplace(std::make_pair(name, cmFileSet(name, type))); + return std::make_pair(&result.first->second, result.second); +} + +std::string cmTarget::GetFileSetsPropertyName(const std::string& type) +{ + if (type == "HEADERS") { + return "HEADER_SETS"; + } + return ""; +} + +std::string cmTarget::GetInterfaceFileSetsPropertyName(const std::string& type) +{ + if (type == "HEADERS") { + return "INTERFACE_HEADER_SETS"; + } + return ""; +} + +std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const +{ + std::vector<std::string> result; + auto inserter = std::back_inserter(result); + + auto appendEntries = [=](const std::vector<BT<std::string>>& entries) { + for (auto const& entry : entries) { + auto expanded = cmExpandedList(entry.Value); + std::copy(expanded.begin(), expanded.end(), inserter); + } + }; + + appendEntries(this->impl->InterfaceHeaderSetsEntries); + + return result; +} + bool cmTargetInternals::CheckImportedLibName(std::string const& prop, std::string const& value) const { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 3cf6942..27b325a 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -20,6 +20,7 @@ #include "cmValue.h" class cmCustomCommand; +class cmFileSet; class cmGlobalGenerator; class cmInstallTargetGenerator; class cmMakefile; @@ -260,6 +261,10 @@ public: cmBTStringRange GetLinkImplementationEntries() const; + cmBTStringRange GetHeaderSetsEntries() const; + + cmBTStringRange GetInterfaceHeaderSetsEntries() const; + std::string ImportedGetFullPath(const std::string& config, cmStateEnums::ArtifactType artifact) const; @@ -268,6 +273,16 @@ public: bool operator()(cmTarget const* t1, cmTarget const* t2) const; }; + const cmFileSet* GetFileSet(const std::string& name) const; + cmFileSet* GetFileSet(const std::string& name); + std::pair<cmFileSet*, bool> GetOrCreateFileSet(const std::string& name, + const std::string& type); + + std::vector<std::string> GetAllInterfaceFileSets() const; + + static std::string GetFileSetsPropertyName(const std::string& type); + static std::string GetInterfaceFileSetsPropertyName(const std::string& type); + private: template <typename ValueType> void StoreProperty(const std::string& prop, ValueType value); diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h index 19fc931..885ac74 100644 --- a/Source/cmTargetExport.h +++ b/Source/cmTargetExport.h @@ -6,7 +6,9 @@ #include <string> +class cmFileSet; class cmGeneratorTarget; +class cmInstallFileSetGenerator; class cmInstallFilesGenerator; class cmInstallTargetGenerator; @@ -29,6 +31,7 @@ public: cmInstallTargetGenerator* FrameworkGenerator; cmInstallTargetGenerator* BundleGenerator; cmInstallFilesGenerator* HeaderGenerator; + std::map<cmFileSet*, cmInstallFileSetGenerator*> FileSetGenerators; ///@} bool NamelinkOnly = false; diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 3bd1ea3..391b954 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -155,10 +155,10 @@ bool cmTargetPropCommandBase::ProcessContentArgs( return false; } } - return this->PopulateTargetProperies(scope, content, prepend, system); + return this->PopulateTargetProperties(scope, content, prepend, system); } -bool cmTargetPropCommandBase::PopulateTargetProperies( +bool cmTargetPropCommandBase::PopulateTargetProperties( const std::string& scope, const std::vector<std::string>& content, bool prepend, bool system) { diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index fc24fe8..6bf7c3c 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -40,6 +40,9 @@ protected: virtual void HandleInterfaceContent(cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool system); + virtual bool PopulateTargetProperties( + const std::string& scope, const std::vector<std::string>& content, + bool prepend, bool system); private: virtual void HandleMissingTarget(const std::string& name) = 0; @@ -52,9 +55,6 @@ private: bool ProcessContentArgs(std::vector<std::string> const& args, unsigned int& argIndex, bool prepend, bool system); - bool PopulateTargetProperies(const std::string& scope, - const std::vector<std::string>& content, - bool prepend, bool system); cmExecutionStatus& Status; }; diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index 26282ef..818e271 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -2,9 +2,17 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetSourcesCommand.h" +#include <algorithm> #include <sstream> +#include <utility> +#include <cm/string_view> +#include <cmext/string_view> + +#include "cmArgumentParser.h" +#include "cmFileSet.h" #include "cmGeneratorExpression.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -15,6 +23,20 @@ namespace { +struct FileSetArgs +{ + std::string Type; + std::string FileSet; + std::vector<std::string> BaseDirs; + std::vector<std::string> Files; +}; + +auto const FileSetArgsParser = cmArgumentParser<FileSetArgs>() + .Bind("TYPE"_s, &FileSetArgs::Type) + .Bind("FILE_SET"_s, &FileSetArgs::FileSet) + .Bind("BASE_DIRS"_s, &FileSetArgs::BaseDirs) + .Bind("FILES"_s, &FileSetArgs::Files); + class TargetSourcesImpl : public cmTargetPropCommandBase { public: @@ -26,8 +48,10 @@ protected: bool prepend, bool system) override { this->cmTargetPropCommandBase::HandleInterfaceContent( - tgt, this->ConvertToAbsoluteContent(tgt, content, true), prepend, - system); + tgt, + this->ConvertToAbsoluteContent(tgt, content, IsInterface::Yes, + CheckCMP0076::Yes), + prepend, system); } private: @@ -43,29 +67,55 @@ private: const std::vector<std::string>& content, bool /*prepend*/, bool /*system*/) override { - tgt->AppendProperty( - "SOURCES", - this->Join(this->ConvertToAbsoluteContent(tgt, content, false))); + tgt->AppendProperty("SOURCES", + this->Join(this->ConvertToAbsoluteContent( + tgt, content, IsInterface::No, CheckCMP0076::Yes))); return true; // Successfully handled. } + bool PopulateTargetProperties(const std::string& scope, + const std::vector<std::string>& content, + bool prepend, bool system) override + { + if (!content.empty() && content.front() == "FILE_SET"_s) { + return this->HandleFileSetMode(scope, content, prepend, system); + } + return this->cmTargetPropCommandBase::PopulateTargetProperties( + scope, content, prepend, system); + } + std::string Join(const std::vector<std::string>& content) override { return cmJoin(content, ";"); } + enum class IsInterface + { + Yes, + No, + }; + enum class CheckCMP0076 + { + Yes, + No, + }; std::vector<std::string> ConvertToAbsoluteContent( cmTarget* tgt, const std::vector<std::string>& content, - bool isInterfaceContent); + IsInterface isInterfaceContent, CheckCMP0076 checkCmp0076); + + bool HandleFileSetMode(const std::string& scope, + const std::vector<std::string>& content, bool prepend, + bool system); }; std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent( cmTarget* tgt, const std::vector<std::string>& content, - bool isInterfaceContent) + IsInterface isInterfaceContent, CheckCMP0076 checkCmp0076) { // Skip conversion in case old behavior has been explicitly requested - if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076) == - cmPolicies::OLD) { + if (checkCmp0076 == CheckCMP0076::Yes && + this->Makefile->GetPolicyStatus(cmPolicies::CMP0076) == + cmPolicies::OLD) { return content; } @@ -76,7 +126,7 @@ std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent( std::string absoluteSrc; if (cmSystemTools::FileIsFullPath(src) || cmGeneratorExpression::Find(src) == 0 || - (!isInterfaceContent && + (isInterfaceContent == IsInterface::No && (this->Makefile->GetCurrentSourceDirectory() == tgt->GetMakefile()->GetCurrentSourceDirectory()))) { absoluteSrc = src; @@ -95,28 +145,33 @@ std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent( bool issueMessage = true; bool useAbsoluteContent = false; std::ostringstream e; - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076)) { - case cmPolicies::WARN: - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0076) << "\n"; - break; - case cmPolicies::OLD: - issueMessage = false; - break; - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::REQUIRED_IF_USED: - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076)); - break; - case cmPolicies::NEW: { - issueMessage = false; - useAbsoluteContent = true; - break; + if (checkCmp0076 == CheckCMP0076::Yes) { + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076)) { + case cmPolicies::WARN: + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0076) << "\n"; + break; + case cmPolicies::OLD: + issueMessage = false; + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076)); + break; + case cmPolicies::NEW: { + issueMessage = false; + useAbsoluteContent = true; + break; + } } + } else { + issueMessage = false; + useAbsoluteContent = true; } if (issueMessage) { - if (isInterfaceContent) { + if (isInterfaceContent == IsInterface::Yes) { e << "An interface source of target \"" << tgt->GetName() << "\" has a relative path."; } else { @@ -129,6 +184,133 @@ std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent( return useAbsoluteContent ? absoluteContent : content; } +bool TargetSourcesImpl::HandleFileSetMode( + const std::string& scope, const std::vector<std::string>& content, + bool /*prepend*/, bool /*system*/) +{ + std::vector<std::string> unparsed; + auto args = FileSetArgsParser.Parse(content, &unparsed); + + if (!unparsed.empty()) { + this->SetError( + cmStrCat("Unrecognized keyword: \"", unparsed.front(), "\"")); + return false; + } + + if (args.FileSet.empty()) { + this->SetError("FILE_SET must not be empty"); + return false; + } + + bool const isDefault = args.Type == args.FileSet || + (args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z'); + std::string type = isDefault ? args.FileSet : args.Type; + + auto fileSet = this->Target->GetOrCreateFileSet(args.FileSet, type); + if (fileSet.second) { + if (!isDefault) { + if (args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z') { + this->SetError( + "Non-default file set name must not start with a capital letter"); + return false; + } + } + if (type.empty()) { + this->SetError("Must specify a TYPE when creating file set"); + return false; + } + if (type != "HEADERS"_s) { + this->SetError("File set TYPE may only be \"HEADERS\""); + return false; + } + + if (args.BaseDirs.empty()) { + args.BaseDirs.emplace_back(this->Makefile->GetCurrentSourceDirectory()); + } + + if (scope == "PRIVATE"_s || scope == "PUBLIC"_s) { + this->Target->AppendProperty(cmTarget::GetFileSetsPropertyName(type), + args.FileSet); + } + if (scope == "INTERFACE"_s || scope == "PUBLIC"_s) { + this->Target->AppendProperty( + cmTarget::GetInterfaceFileSetsPropertyName(type), args.FileSet); + } + } else { + type = fileSet.first->GetType(); + if (!args.Type.empty() && args.Type != type) { + this->SetError(cmStrCat( + "Type \"", args.Type, "\" for file set \"", fileSet.first->GetName(), + "\" does not match original type \"", type, "\"")); + return false; + } + + std::string existingScope = "PRIVATE"; + + auto const fileSetsProperty = cmTarget::GetFileSetsPropertyName(type); + auto const interfaceFileSetsProperty = + cmTarget::GetInterfaceFileSetsPropertyName(type); + std::vector<std::string> fileSets; + std::vector<std::string> interfaceFileSets; + cmExpandList(this->Target->GetSafeProperty(fileSetsProperty), fileSets); + cmExpandList(this->Target->GetSafeProperty(interfaceFileSetsProperty), + interfaceFileSets); + + if (std::find(interfaceFileSets.begin(), interfaceFileSets.end(), + args.FileSet) != interfaceFileSets.end()) { + existingScope = "INTERFACE"; + } + if (std::find(fileSets.begin(), fileSets.end(), args.FileSet) != + fileSets.end()) { + if (existingScope == "INTERFACE"_s) { + existingScope = "PUBLIC"; + } + } else if (existingScope != "INTERFACE"_s) { + this->SetError(cmStrCat("File set \"", args.FileSet, "\" is not in ", + fileSetsProperty, " or ", + interfaceFileSetsProperty)); + return false; + } + + if (scope != existingScope) { + this->SetError( + cmStrCat("Scope ", scope, " for file set \"", args.FileSet, + "\" does not match original scope ", existingScope)); + return false; + } + } + + auto files = this->Join(this->ConvertToAbsoluteContent( + this->Target, args.Files, IsInterface::Yes, CheckCMP0076::No)); + if (!files.empty()) { + fileSet.first->AddFileEntry( + BT<std::string>(files, this->Makefile->GetBacktrace())); + } + + auto baseDirectories = this->Join(this->ConvertToAbsoluteContent( + this->Target, args.BaseDirs, IsInterface::Yes, CheckCMP0076::No)); + if (!baseDirectories.empty()) { + fileSet.first->AddDirectoryEntry( + BT<std::string>(baseDirectories, this->Makefile->GetBacktrace())); + if (type == "HEADERS"_s) { + for (auto const& dir : cmExpandedList(baseDirectories)) { + auto interfaceDirectoriesGenex = + cmStrCat("$<BUILD_INTERFACE:", dir, ">"); + if (scope == "PRIVATE"_s || scope == "PUBLIC"_s) { + this->Target->AppendProperty("INCLUDE_DIRECTORIES", + interfaceDirectoriesGenex); + } + if (scope == "INTERFACE"_s || scope == "PUBLIC"_s) { + this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", + interfaceDirectoriesGenex); + } + } + } + } + + return true; +} + } // namespace bool cmTargetSourcesCommand(std::vector<std::string> const& args, diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index cc9e158..cd468b9 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -211,7 +211,7 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs, char retChar[16]; const char* retStr; if (worked) { - sprintf(retChar, "%i", retVal); + snprintf(retChar, sizeof(retChar), "%i", retVal); retStr = retChar; } else { retStr = "FAILED_TO_RUN"; diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index 969a2c2..cbd241b 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVSSetupHelper.h" +#include <utility> + #include "cmsys/Encoding.hxx" #include "cmsys/FStream.hxx" @@ -46,17 +48,36 @@ const CLSID CLSID_SetupConfiguration = { /* clang-format on */ #endif +namespace { const WCHAR* Win10SDKComponent = L"Microsoft.VisualStudio.Component.Windows10SDK"; const WCHAR* Win81SDKComponent = L"Microsoft.VisualStudio.Component.Windows81SDK"; const WCHAR* ComponentType = L"Component"; +bool LoadVSInstanceVCToolsetVersion(VSInstanceInfo& vsInstanceInfo) +{ + std::string const vcRoot = vsInstanceInfo.GetInstallLocation(); + std::string vcToolsVersionFile = + vcRoot + "/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt"; + std::string vcToolsVersion; + cmsys::ifstream fin(vcToolsVersionFile.c_str()); + if (!fin || !cmSystemTools::GetLineFromStream(fin, vcToolsVersion)) { + return false; + } + vcToolsVersion = cmTrimWhitespace(vcToolsVersion); + std::string const vcToolsDir = vcRoot + "/VC/Tools/MSVC/" + vcToolsVersion; + if (!cmSystemTools::FileIsDirectory(vcToolsDir)) { + return false; + } + vsInstanceInfo.VCToolsetVersion = vcToolsVersion; + return true; +} +} + std::string VSInstanceInfo::GetInstallLocation() const { - std::string loc = cmsys::Encoding::ToNarrow(this->VSInstallLocation); - cmSystemTools::ConvertToUnixSlashes(loc); - return loc; + return this->VSInstallLocation; } cmVSSetupAPIHelper::cmVSSetupAPIHelper(unsigned int version) @@ -83,10 +104,12 @@ cmVSSetupAPIHelper::~cmVSSetupAPIHelper() CoUninitialize(); } -bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation) +bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation, + std::string const& vsInstallVersion) { this->SpecifiedVSInstallLocation = vsInstallLocation; cmSystemTools::ConvertToUnixSlashes(this->SpecifiedVSInstallLocation); + this->SpecifiedVSInstallVersion = vsInstallVersion; chosenInstanceInfo = VSInstanceInfo(); return this->EnumerateAndChooseVSInstance(); } @@ -152,29 +175,17 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo( if (pInstance == NULL) return false; - SmartBSTR bstrId; - if (SUCCEEDED(pInstance->GetInstanceId(&bstrId))) { - vsInstanceInfo.InstanceId = std::wstring(bstrId); - } else { - return false; - } - InstanceState state; if (FAILED(pInstance->GetState(&state))) { return false; } - ULONGLONG ullVersion = 0; SmartBSTR bstrVersion; if (FAILED(pInstance->GetInstallationVersion(&bstrVersion))) { return false; } else { - vsInstanceInfo.Version = std::wstring(bstrVersion); - if (FAILED(setupHelper->ParseVersion(bstrVersion, &ullVersion))) { - vsInstanceInfo.ullVersion = 0; - } else { - vsInstanceInfo.ullVersion = ullVersion; - } + vsInstanceInfo.Version = + cmsys::Encoding::ToNarrow(std::wstring(bstrVersion)); } // Reboot may have been required before the installation path was created. @@ -183,26 +194,15 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo( if (FAILED(pInstance->GetInstallationPath(&bstrInstallationPath))) { return false; } else { - vsInstanceInfo.VSInstallLocation = std::wstring(bstrInstallationPath); + vsInstanceInfo.VSInstallLocation = + cmsys::Encoding::ToNarrow(std::wstring(bstrInstallationPath)); + cmSystemTools::ConvertToUnixSlashes(vsInstanceInfo.VSInstallLocation); } } // Check if a compiler is installed with this instance. - { - std::string const vcRoot = vsInstanceInfo.GetInstallLocation(); - std::string vcToolsVersionFile = - vcRoot + "/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt"; - std::string vcToolsVersion; - cmsys::ifstream fin(vcToolsVersionFile.c_str()); - if (!fin || !cmSystemTools::GetLineFromStream(fin, vcToolsVersion)) { - return false; - } - vcToolsVersion = cmTrimWhitespace(vcToolsVersion); - std::string const vcToolsDir = vcRoot + "/VC/Tools/MSVC/" + vcToolsVersion; - if (!cmSystemTools::FileIsDirectory(vcToolsDir)) { - return false; - } - vsInstanceInfo.VCToolsetVersion = vcToolsVersion; + if (!LoadVSInstanceVCToolsetVersion(vsInstanceInfo)) { + return false; } // Reboot may have been required before the product package was registered @@ -264,7 +264,7 @@ bool cmVSSetupAPIHelper::GetVSInstanceVersion(std::string& vsInstanceVersion) bool isInstalled = this->EnumerateAndChooseVSInstance(); if (isInstalled) { - vsInstanceVersion = cmsys::Encoding::ToNarrow(chosenInstanceInfo.Version); + vsInstanceVersion = chosenInstanceInfo.Version; } return isInstalled; @@ -298,7 +298,7 @@ bool cmVSSetupAPIHelper::IsEWDKEnabled() bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() { bool isVSInstanceExists = false; - if (chosenInstanceInfo.VSInstallLocation.compare(L"") != 0) { + if (chosenInstanceInfo.VSInstallLocation.compare("") != 0) { return true; } @@ -311,12 +311,11 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() if (envVSVersion.empty() || envVsInstallDir.empty()) return false; - chosenInstanceInfo.VSInstallLocation = - std::wstring(envVsInstallDir.begin(), envVsInstallDir.end()); - chosenInstanceInfo.Version = - std::wstring(envVSVersion.begin(), envVSVersion.end()); - chosenInstanceInfo.VCToolsetVersion = envVSVersion; - chosenInstanceInfo.ullVersion = std::stoi(envVSVersion); + chosenInstanceInfo.VSInstallLocation = envVsInstallDir; + chosenInstanceInfo.Version = envVSVersion; + if (!LoadVSInstanceVCToolsetVersion(chosenInstanceInfo)) { + return false; + } chosenInstanceInfo.IsWin10SDKInstalled = true; chosenInstanceInfo.IsWin81SDKInstalled = !envWindowsSdkDir81.empty(); return true; @@ -343,7 +342,9 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() return false; } - std::wstring const wantVersion = std::to_wstring(this->Version) + L'.'; + std::string const wantVersion = std::to_string(this->Version) + '.'; + + bool specifiedLocationNotSpecifiedVersion = false; SmartCOMPtr<ISetupInstance> instance; while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { @@ -371,6 +372,16 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() std::string currentVSLocation = instanceInfo.GetInstallLocation(); if (cmSystemTools::ComparePath(currentVSLocation, this->SpecifiedVSInstallLocation)) { + if (this->SpecifiedVSInstallVersion.empty() || + instanceInfo.Version == this->SpecifiedVSInstallVersion) { + chosenInstanceInfo = instanceInfo; + return true; + } + specifiedLocationNotSpecifiedVersion = true; + } + } else if (!this->SpecifiedVSInstallVersion.empty()) { + // We are looking for a specific version. + if (instanceInfo.Version == this->SpecifiedVSInstallVersion) { chosenInstanceInfo = instanceInfo; return true; } @@ -392,6 +403,13 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() } } + if (!this->SpecifiedVSInstallLocation.empty() && + !specifiedLocationNotSpecifiedVersion) { + // The VS Installer does not know about the specified location. + // Check for one directly on disk. + return this->LoadSpecifiedVSInstanceFromDisk(); + } + if (vecVSInstances.size() > 0) { isVSInstanceExists = true; int index = ChooseVSInstance(vecVSInstances); @@ -454,6 +472,32 @@ int cmVSSetupAPIHelper::ChooseVSInstance( return chosenIndex; } +bool cmVSSetupAPIHelper::LoadSpecifiedVSInstanceFromDisk() +{ + if (!cmSystemTools::FileIsDirectory(this->SpecifiedVSInstallLocation)) { + return false; + } + VSInstanceInfo vsInstanceInfo; + vsInstanceInfo.VSInstallLocation = this->SpecifiedVSInstallLocation; + // FIXME: Is there a better way to get SDK information? + vsInstanceInfo.IsWin10SDKInstalled = true; + vsInstanceInfo.IsWin81SDKInstalled = false; + + if (!this->SpecifiedVSInstallVersion.empty()) { + // Assume the version specified by the user is correct. + vsInstanceInfo.Version = this->SpecifiedVSInstallVersion; + } else { + return false; + } + + if (!LoadVSInstanceVCToolsetVersion(vsInstanceInfo)) { + return false; + } + + chosenInstanceInfo = std::move(vsInstanceInfo); + return true; +} + bool cmVSSetupAPIHelper::Initialize() { if (initializationFailure) diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index 61a3ac7..44c883b 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -84,11 +84,9 @@ private: struct VSInstanceInfo { - std::wstring InstanceId; - std::wstring VSInstallLocation; - std::wstring Version; + std::string VSInstallLocation; + std::string Version; std::string VCToolsetVersion; - ULONGLONG ullVersion = 0; // A.B.C.D = (A<<48)|(B<<32)|(C<<16)|D bool IsWin10SDKInstalled = false; bool IsWin81SDKInstalled = false; @@ -101,7 +99,8 @@ public: cmVSSetupAPIHelper(unsigned int version); ~cmVSSetupAPIHelper(); - bool SetVSInstance(std::string const& vsInstallLocation); + bool SetVSInstance(std::string const& vsInstallLocation, + std::string const& vsInstallVersion); bool IsVSInstalled(); bool GetVSInstanceInfo(std::string& vsInstallLocation); @@ -118,6 +117,7 @@ private: bool& bWin10SDK, bool& bWin81SDK); int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances); bool EnumerateAndChooseVSInstance(); + bool LoadSpecifiedVSInstanceFromDisk(); unsigned int Version; @@ -134,4 +134,5 @@ private: bool IsEWDKEnabled(); std::string SpecifiedVSInstallLocation; + std::string SpecifiedVSInstallVersion; }; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index d2c49ae..a7822b2 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2356,7 +2356,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) } } - if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) { + if (si.Kind == cmGeneratorTarget::SourceKindObjectSource || + si.Kind == cmGeneratorTarget::SourceKindUnityBatched) { this->OutputSourceSpecificFlags(e2, si.Source); } if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { @@ -3229,18 +3230,17 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( // the default to not have any extension cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).obj"); - bool notPtx = true; if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) { cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true"); - } else if (this->GeneratorTarget->GetPropertyAsBool( - "CUDA_PTX_COMPILATION")) { + } + bool notPtx = true; + if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) { cudaOptions.AddFlag("NvccCompilation", "ptx"); // We drop the %(Extension) component as CMake expects all PTX files // to not have the source file extension at all cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).ptx"); notPtx = false; } - if (notPtx && cmSystemTools::VersionCompareGreaterEq( "8.0", this->GlobalGenerator->GetPlatformToolsetCudaString())) { diff --git a/Source/cmVisualStudioSlnParser.h b/Source/cmVisualStudioSlnParser.h index 1c33759..60be598 100644 --- a/Source/cmVisualStudioSlnParser.h +++ b/Source/cmVisualStudioSlnParser.h @@ -5,13 +5,12 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <bitset> +#include <cstddef> #include <iosfwd> #include <string> #include <cm/string_view> -#include <stddef.h> - class cmSlnData; class cmVisualStudioSlnParser diff --git a/Source/cmVisualStudioWCEPlatformParser.h b/Source/cmVisualStudioWCEPlatformParser.h index eb4e978..2fff91c 100644 --- a/Source/cmVisualStudioWCEPlatformParser.h +++ b/Source/cmVisualStudioWCEPlatformParser.h @@ -4,12 +4,11 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <map> #include <string> #include <vector> -#include <stddef.h> - #include "cmXMLParser.h" // This class is used to parse XML with configuration diff --git a/Source/cmXCOFF.cxx b/Source/cmXCOFF.cxx index 890636e..a6d278d 100644 --- a/Source/cmXCOFF.cxx +++ b/Source/cmXCOFF.cxx @@ -61,20 +61,20 @@ namespace { struct XCOFF32 { - typedef struct filehdr filehdr; - typedef struct aouthdr aouthdr; - typedef struct scnhdr scnhdr; - typedef struct ldhdr ldhdr; + using filehdr = struct filehdr; + using aouthdr = struct aouthdr; + using scnhdr = struct scnhdr; + using ldhdr = struct ldhdr; static const std::size_t aouthdr_size = _AOUTHSZ_EXEC; }; const unsigned char xcoff32_magic[] = { 0x01, 0xDF }; struct XCOFF64 { - typedef struct filehdr_64 filehdr; - typedef struct aouthdr_64 aouthdr; - typedef struct scnhdr_64 scnhdr; - typedef struct ldhdr_64 ldhdr; + using filehdr = struct filehdr_64; + using aouthdr = struct aouthdr_64; + using scnhdr = struct scnhdr_64; + using ldhdr = struct ldhdr_64; static const std::size_t aouthdr_size = _AOUTHSZ_EXEC_64; }; const unsigned char xcoff64_magic[] = { 0x01, 0xF7 }; @@ -326,8 +326,8 @@ cmXCOFF::cmXCOFF(const char* fname, Mode mode) cmXCOFF::~cmXCOFF() = default; -cmXCOFF::cmXCOFF(cmXCOFF&&) = default; -cmXCOFF& cmXCOFF::operator=(cmXCOFF&&) = default; +cmXCOFF::cmXCOFF(cmXCOFF&&) noexcept = default; +cmXCOFF& cmXCOFF::operator=(cmXCOFF&&) noexcept = default; bool cmXCOFF::Valid() const { diff --git a/Source/cmXCOFF.h b/Source/cmXCOFF.h index 16cda9d..f6d9d94 100644 --- a/Source/cmXCOFF.h +++ b/Source/cmXCOFF.h @@ -35,9 +35,9 @@ public: /** Destruct. */ ~cmXCOFF(); - cmXCOFF(cmXCOFF&&); + cmXCOFF(cmXCOFF&&) noexcept; cmXCOFF(cmXCOFF const&) = delete; - cmXCOFF& operator=(cmXCOFF&&); + cmXCOFF& operator=(cmXCOFF&&) noexcept; cmXCOFF& operator=(cmXCOFF const&) = delete; /** Get the error message if any. */ diff --git a/Source/cmXMLParser.h b/Source/cmXMLParser.h index 7e805d7..176252d 100644 --- a/Source/cmXMLParser.h +++ b/Source/cmXMLParser.h @@ -21,6 +21,7 @@ class cmXMLParser { public: cmXMLParser(); + cmXMLParser(const cmXMLParser& /*other*/) = default; virtual ~cmXMLParser(); //! Parse given XML string diff --git a/Source/cmXMLSafe.cxx b/Source/cmXMLSafe.cxx index d31a239..4014635 100644 --- a/Source/cmXMLSafe.cxx +++ b/Source/cmXMLSafe.cxx @@ -73,7 +73,7 @@ std::ostream& operator<<(std::ostream& os, cmXMLSafe const& self) } else { // Use a human-readable hex value for this invalid character. char buf[16]; - sprintf(buf, "%X", ch); + snprintf(buf, sizeof(buf), "%X", ch); os << "[NON-XML-CHAR-0x" << buf << "]"; } @@ -82,7 +82,7 @@ std::ostream& operator<<(std::ostream& os, cmXMLSafe const& self) ch = static_cast<unsigned char>(*first++); // Use a human-readable hex value for this invalid byte. char buf[16]; - sprintf(buf, "%X", ch); + snprintf(buf, sizeof(buf), "%X", ch); os << "[NON-UTF-8-BYTE-0x" << buf << "]"; } } diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx index 216d3f0..ddee968 100644 --- a/Source/cm_codecvt.cxx +++ b/Source/cm_codecvt.cxx @@ -3,10 +3,10 @@ #include "cm_codecvt.hxx" #if defined(_WIN32) -# include <windows.h> +# include <cassert> +# include <cstring> -# include <assert.h> -# include <string.h> +# include <windows.h> # undef max # include "cmsys/Encoding.hxx" #endif @@ -42,7 +42,7 @@ codecvt::codecvt(Encoding e) codecvt::~codecvt() = default; -bool codecvt::do_always_noconv() const throw() +bool codecvt::do_always_noconv() const noexcept { return this->m_noconv; } @@ -234,12 +234,12 @@ void codecvt::BufferPartial(mbstate_t& state, int size, } #endif -int codecvt::do_max_length() const throw() +int codecvt::do_max_length() const noexcept { return 4; } -int codecvt::do_encoding() const throw() +int codecvt::do_encoding() const noexcept { return 0; } diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx index b73204f..9af083f 100644 --- a/Source/cm_codecvt.hxx +++ b/Source/cm_codecvt.hxx @@ -24,14 +24,14 @@ public: protected: ~codecvt() override; - bool do_always_noconv() const throw() override; + bool do_always_noconv() const noexcept override; result do_out(mbstate_t& state, const char* from, const char* from_end, const char*& from_next, char* to, char* to_end, char*& to_next) const override; result do_unshift(mbstate_t& state, char* to, char*, char*& to_next) const override; - int do_max_length() const throw() override; - int do_encoding() const throw() override; + int do_max_length() const noexcept override; + int do_encoding() const noexcept override; private: // The mbstate_t argument to do_out and do_unshift is responsible diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index bdddc4e..32c01e5 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -58,7 +58,6 @@ #ifdef _WIN32 # include <fcntl.h> // for _O_BINARY # include <io.h> // for _setmode -# include <stdio.h> // for std{out,err} and fileno #endif #include <cm/string_view> @@ -1112,7 +1111,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, int count; if (countFile) { if (1 != fscanf(countFile, "%i", &count)) { - cmSystemTools::Message("Could not read from count file."); + std::cerr << "Could not read from count file.\n"; } fclose(countFile); } else { @@ -1426,8 +1425,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, action = cmSystemTools::TarActionExtract; } break; default: { - cmSystemTools::Message( - std::string("tar: Unknown argument: ") + flag, "Warning"); + std::cerr << "tar: Unknown argument: " << flag << "\n"; } } } @@ -1448,8 +1446,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, } } else if (action == cmSystemTools::TarActionCreate) { if (files.empty()) { - cmSystemTools::Message("tar: No files or directories specified", - "Warning"); + std::cerr << "tar: No files or directories specified\n"; } if (!cmSystemTools::CreateTar(outFile, files, compress, verbose, mtime, format)) { @@ -1588,7 +1585,11 @@ int cmcmd::HashSumFile(std::vector<std::string> const& args, std::cerr << "Error: " << filename << " is a directory" << std::endl; retval++; } else { - std::string value = cmSystemTools::ComputeFileHash(filename, algo); + std::string value +#ifndef CMAKE_BOOTSTRAP + = cmSystemTools::ComputeFileHash(filename, algo) +#endif + ; if (value.empty()) { // To mimic "md5sum/shasum" behavior in a shell: std::cerr << filename << ": No such file or directory" << std::endl; @@ -1684,7 +1685,7 @@ static void cmcmdProgressReport(std::string const& dir, std::string const& num) return; } if (1 != fscanf(progFile, "%i", &count)) { - cmSystemTools::Message("Could not read from progress file."); + std::cerr << "Could not read from progress file.\n"; } fclose(progFile); @@ -2135,8 +2136,8 @@ struct NumberFormatter { } }; -std::ostream& operator<<(std::ostream& stream, - NumberFormatter const& formatter) +static std::ostream& operator<<(std::ostream& stream, + NumberFormatter const& formatter) { auto const& flags = stream.flags(); if (formatter.Format == FORMAT_DECIMAL) { diff --git a/Source/kwsys/CTestConfig.cmake b/Source/kwsys/CTestConfig.cmake index 12347b6..6484cc2 100644 --- a/Source/kwsys/CTestConfig.cmake +++ b/Source/kwsys/CTestConfig.cmake @@ -3,9 +3,7 @@ set(CTEST_PROJECT_NAME "KWSys") set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -if (NOT CTEST_DROP_METHOD STREQUAL "https") - set(CTEST_DROP_METHOD "http") -endif () +set(CTEST_DROP_METHOD "https") set(CTEST_DROP_SITE "open.cdash.org") set(CTEST_DROP_LOCATION "/submit.php?project=PublicDashboard") set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Source/kwsys/Configure.hxx.in b/Source/kwsys/Configure.hxx.in index 29a2dd1..8d47340 100644 --- a/Source/kwsys/Configure.hxx.in +++ b/Source/kwsys/Configure.hxx.in @@ -16,11 +16,11 @@ @KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP@ #if defined(__SUNPRO_CC) && __SUNPRO_CC > 0x5130 && defined(__has_attribute) -# define @KWSYS_NAMESPACE@__has_cpp_attribute(x) __has_attribute(x) +# define @KWSYS_NAMESPACE@_has_cpp_attribute(x) __has_attribute(x) #elif defined(__has_cpp_attribute) -# define @KWSYS_NAMESPACE@__has_cpp_attribute(x) __has_cpp_attribute(x) +# define @KWSYS_NAMESPACE@_has_cpp_attribute(x) __has_cpp_attribute(x) #else -# define @KWSYS_NAMESPACE@__has_cpp_attribute(x) 0 +# define @KWSYS_NAMESPACE@_has_cpp_attribute(x) 0 #endif #if __cplusplus >= 201103L @@ -31,13 +31,13 @@ #ifndef @KWSYS_NAMESPACE@_FALLTHROUGH # if __cplusplus >= 201703L && \ - @KWSYS_NAMESPACE@__has_cpp_attribute(fallthrough) + @KWSYS_NAMESPACE@_has_cpp_attribute(fallthrough) # define @KWSYS_NAMESPACE@_FALLTHROUGH [[fallthrough]] # elif __cplusplus >= 201103L && \ - @KWSYS_NAMESPACE@__has_cpp_attribute(gnu::fallthrough) + @KWSYS_NAMESPACE@_has_cpp_attribute(gnu::fallthrough) # define @KWSYS_NAMESPACE@_FALLTHROUGH [[gnu::fallthrough]] # elif __cplusplus >= 201103L && \ - @KWSYS_NAMESPACE@__has_cpp_attribute(clang::fallthrough) + @KWSYS_NAMESPACE@_has_cpp_attribute(clang::fallthrough) # define @KWSYS_NAMESPACE@_FALLTHROUGH [[clang::fallthrough]] # endif #endif @@ -45,7 +45,7 @@ # define @KWSYS_NAMESPACE@_FALLTHROUGH static_cast<void>(0) #endif -#undef @KWSYS_NAMESPACE@__has_cpp_attribute +#undef @KWSYS_NAMESPACE@_has_cpp_attribute /* If building a C++ file in kwsys itself, give the source file access to the macros without a configured namespace. */ diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx index 2e8aa83..6e31cbf 100644 --- a/Source/kwsys/Directory.cxx +++ b/Source/kwsys/Directory.cxx @@ -99,18 +99,21 @@ Status Directory::Load(std::string const& name, std::string* errorMessage) this->Clear(); intptr_t srchHandle; char* buf; + size_t bufLength; size_t n = name.size(); if (name.back() == '/' || name.back() == '\\') { - buf = new char[n + 1 + 1]; - sprintf(buf, "%s*", name.c_str()); + bufLength = n + 1 + 1; + buf = new char[bufLength]; + snprintf(buf, bufLength, "%s*", name.c_str()); } else { // Make sure the slashes in the wildcard suffix are consistent with the // rest of the path - buf = new char[n + 2 + 1]; + bufLength = n + 2 + 1; + buf = new char[bufLength]; if (name.find('\\') != std::string::npos) { - sprintf(buf, "%s\\*", name.c_str()); + snprintf(buf, bufLength, "%s\\*", name.c_str()); } else { - sprintf(buf, "%s/*", name.c_str()); + snprintf(buf, bufLength, "%s/*", name.c_str()); } } struct _wfinddata_t data; // data of current file @@ -148,13 +151,16 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, { intptr_t srchHandle; char* buf; + size_t bufLength; size_t n = name.size(); if (name.back() == '/') { + bufLength = n + 1 + 1; buf = new char[n + 1 + 1]; - sprintf(buf, "%s*", name.c_str()); + snprintf(buf, bufLength, "%s*", name.c_str()); } else { + bufLength = n + 2 + 1; buf = new char[n + 2 + 1]; - sprintf(buf, "%s/*", name.c_str()); + snprintf(buf, bufLength, "%s/*", name.c_str()); } struct _wfinddata_t data; // data of current file diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx index 66ee9ea..8afc2e8 100644 --- a/Source/kwsys/DynamicLoader.cxx +++ b/Source/kwsys/DynamicLoader.cxx @@ -275,20 +275,20 @@ const char* DynamicLoader::LastError() if (length < 1) { /* FormatMessage failed. Use a default message. */ - _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE, - "DynamicLoader encountered error 0x%X. " - "FormatMessage failed with error 0x%X", - error, GetLastError()); + snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE, + "DynamicLoader encountered error 0x%lX. " + "FormatMessage failed with error 0x%lX", + error, GetLastError()); return str; } if (!WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, str, DYNLOAD_ERROR_BUFFER_SIZE, nullptr, nullptr)) { /* WideCharToMultiByte failed. Use a default message. */ - _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE, - "DynamicLoader encountered error 0x%X. " - "WideCharToMultiByte failed with error 0x%X", - error, GetLastError()); + snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE, + "DynamicLoader encountered error 0x%lX. " + "WideCharToMultiByte failed with error 0x%lX", + error, GetLastError()); } return str; @@ -436,9 +436,14 @@ namespace KWSYS_NAMESPACE { DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( const std::string& libname, int flags) { - CHECK_OPEN_FLAGS(flags, 0, nullptr); + CHECK_OPEN_FLAGS(flags, RTLDGlobal, nullptr); + + int llFlags = RTLD_LAZY; + if (flags & RTLDGlobal) { + llFlags |= RTLD_GLOBAL; + } - return dlopen(libname.c_str(), RTLD_LAZY); + return dlopen(libname.c_str(), llFlags); } int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) diff --git a/Source/kwsys/DynamicLoader.hxx.in b/Source/kwsys/DynamicLoader.hxx.in index 539c742..4edd31c 100644 --- a/Source/kwsys/DynamicLoader.hxx.in +++ b/Source/kwsys/DynamicLoader.hxx.in @@ -73,7 +73,12 @@ public: // This is currently only supported on Windows. SearchBesideLibrary = 0x00000001, - AllOpenFlags = SearchBesideLibrary + // Make loaded symbols visible globally + // + // This is currently only supported on *nix systems. + RTLDGlobal = 0x00000002, + + AllOpenFlags = SearchBesideLibrary | RTLDGlobal }; /** Load a dynamic library into the current process. diff --git a/Source/kwsys/MD5.c b/Source/kwsys/MD5.c index fb18a5b..76995e2 100644 --- a/Source/kwsys/MD5.c +++ b/Source/kwsys/MD5.c @@ -10,6 +10,7 @@ #endif #include <stddef.h> /* size_t */ +#include <stdint.h> /* uintptr_t */ #include <stdlib.h> /* malloc, free */ #include <string.h> /* memcpy, strlen */ @@ -202,7 +203,7 @@ static void md5_process(md5_state_t* pms, const md5_byte_t* data /*[64]*/) * On little-endian machines, we can process properly aligned * data without copying it. */ - if (!((data - (const md5_byte_t*)0) & 3)) { + if (!((uintptr_t)data & 3)) { /* data are properly aligned */ X = (const md5_word_t*)data; } else { diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index a8a15dd..1963b27 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -2287,7 +2287,8 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig, #endif default: cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other; - sprintf(cp->ProcessResults[idx].ExitExceptionString, "Signal %d", sig); + snprintf(cp->ProcessResults[idx].ExitExceptionString, + KWSYSPE_PIPE_BUFFER_SIZE + 1, "Signal %d", sig); break; } } @@ -2540,7 +2541,7 @@ static void kwsysProcessKill(pid_t process_id) int pid; if (sscanf(d->d_name, "%d", &pid) == 1 && pid != 0) { struct stat finfo; - sprintf(fname, "/proc/%d/stat", pid); + snprintf(fname, sizeof(fname), "/proc/%d/stat", pid); if (stat(fname, &finfo) == 0) { FILE* f = fopen(fname, "r"); if (f) { diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index 8f01684..e97973e 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -29,7 +29,7 @@ a UNIX-style select system call. # define KWSYS_WINDOWS_DEPRECATED_GetVersionEx #endif #include <io.h> /* _unlink */ -#include <stdio.h> /* sprintf */ +#include <stdio.h> /* snprintf */ #include <string.h> /* strlen, strdup */ #ifndef _MAX_FNAME @@ -1867,18 +1867,18 @@ void kwsysProcessCleanup(kwsysProcess* cp, DWORD error) KWSYSPE_PIPE_BUFFER_SIZE, 0); if (length < 1) { /* FormatMessage failed. Use a default message. */ - _snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, - "Process execution failed with error 0x%X. " - "FormatMessage failed with error 0x%X", - error, GetLastError()); + snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, + "Process execution failed with error 0x%lX. " + "FormatMessage failed with error 0x%lX", + error, GetLastError()); } if (!WideCharToMultiByte(CP_UTF8, 0, err_msg, -1, cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, NULL, NULL)) { /* WideCharToMultiByte failed. Use a default message. */ - _snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, - "Process execution failed with error 0x%X. " - "WideCharToMultiByte failed with error 0x%X", - error, GetLastError()); + snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, + "Process execution failed with error 0x%lX. " + "WideCharToMultiByte failed with error 0x%lX", + error, GetLastError()); } } @@ -2144,8 +2144,8 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code, case STATUS_NO_MEMORY: default: cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other; - _snprintf(cp->ProcessResults[idx].ExitExceptionString, - KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code); + snprintf(cp->ProcessResults[idx].ExitExceptionString, + KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code); break; } } diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in index 091334b..d6ae75c 100644 --- a/Source/kwsys/SharedForward.h.in +++ b/Source/kwsys/SharedForward.h.in @@ -457,9 +457,9 @@ static void kwsys_shared_forward_strerror(char* message) message, KWSYS_SHARED_FORWARD_MAXPATH, 0); if (length < 1 || length > KWSYS_SHARED_FORWARD_MAXPATH) { /* FormatMessage failed. Use a default message. */ - _snprintf(message, KWSYS_SHARED_FORWARD_MAXPATH, - "Error 0x%X (FormatMessage failed with error 0x%X)", original, - GetLastError()); + snprintf(message, KWSYS_SHARED_FORWARD_MAXPATH, + "Error 0x%lX (FormatMessage failed with error 0x%lX)", original, + GetLastError()); } # else /* Implementation for UNIX. */ diff --git a/Source/kwsys/Status.cxx b/Source/kwsys/Status.cxx index 503d1e1..edda7a0 100644 --- a/Source/kwsys/Status.cxx +++ b/Source/kwsys/Status.cxx @@ -53,7 +53,7 @@ std::string Status::GetString() const LocalFree(message); } break; #endif - }; + } return err; } diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index f2bf85f..ecb9bf3 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -1267,7 +1267,9 @@ public: private: void* GetRealAddress() const { - return (void*)((char*)this->Address - (char*)this->BinaryBaseAddress); + return reinterpret_cast<void*>( + static_cast<char*>(this->Address) - + static_cast<char*>(this->BinaryBaseAddress)); } std::string GetFileName(const std::string& path) const; @@ -2789,19 +2791,20 @@ bool SystemInformationImplementation::RetrieveProcessorSerialNumber() // ; ecx: middle 32 bits are the processor signature bits // ; edx: bottom 32 bits are the processor signature bits char sn[128]; - sprintf(sn, "%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x", - ((SerialNumber[1] & 0xff000000) >> 24), - ((SerialNumber[1] & 0x00ff0000) >> 16), - ((SerialNumber[1] & 0x0000ff00) >> 8), - ((SerialNumber[1] & 0x000000ff) >> 0), - ((SerialNumber[2] & 0xff000000) >> 24), - ((SerialNumber[2] & 0x00ff0000) >> 16), - ((SerialNumber[2] & 0x0000ff00) >> 8), - ((SerialNumber[2] & 0x000000ff) >> 0), - ((SerialNumber[3] & 0xff000000) >> 24), - ((SerialNumber[3] & 0x00ff0000) >> 16), - ((SerialNumber[3] & 0x0000ff00) >> 8), - ((SerialNumber[3] & 0x000000ff) >> 0)); + snprintf(sn, sizeof(sn), + "%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x", + ((SerialNumber[1] & 0xff000000) >> 24), + ((SerialNumber[1] & 0x00ff0000) >> 16), + ((SerialNumber[1] & 0x0000ff00) >> 8), + ((SerialNumber[1] & 0x000000ff) >> 0), + ((SerialNumber[2] & 0xff000000) >> 24), + ((SerialNumber[2] & 0x00ff0000) >> 16), + ((SerialNumber[2] & 0x0000ff00) >> 8), + ((SerialNumber[2] & 0x000000ff) >> 0), + ((SerialNumber[3] & 0xff000000) >> 24), + ((SerialNumber[3] & 0x00ff0000) >> 16), + ((SerialNumber[3] & 0x0000ff00) >> 8), + ((SerialNumber[3] & 0x000000ff) >> 0)); this->ChipID.SerialNumber = sn; return true; @@ -3749,24 +3752,24 @@ long long SystemInformationImplementation::GetProcMemoryAvailable( ResourceLimitType rlim; ierr = GetResourceLimit(RLIMIT_DATA, &rlim); if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) { - memAvail = min((long long)rlim.rlim_cur / 1024, memAvail); + memAvail = min(static_cast<long long>(rlim.rlim_cur) / 1024, memAvail); } ierr = GetResourceLimit(RLIMIT_AS, &rlim); if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) { - memAvail = min((long long)rlim.rlim_cur / 1024, memAvail); + memAvail = min(static_cast<long long>(rlim.rlim_cur) / 1024, memAvail); } #elif defined(__APPLE__) struct rlimit rlim; int ierr; ierr = getrlimit(RLIMIT_DATA, &rlim); if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) { - memAvail = min((long long)rlim.rlim_cur / 1024, memAvail); + memAvail = min(static_cast<long long>(rlim.rlim_cur) / 1024, memAvail); } ierr = getrlimit(RLIMIT_RSS, &rlim); if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) { - memAvail = min((long long)rlim.rlim_cur / 1024, memAvail); + memAvail = min(static_cast<long long>(rlim.rlim_cur) / 1024, memAvail); } #endif @@ -4068,7 +4071,7 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable) // install ours struct sigaction sa; - sa.sa_sigaction = (SigAction)StacktraceSignalHandler; + sa.sa_sigaction = static_cast<SigAction>(StacktraceSignalHandler); sa.sa_flags = SA_SIGINFO | SA_RESETHAND; # ifdef SA_RESTART sa.sa_flags |= SA_RESTART; @@ -4564,7 +4567,8 @@ bool SystemInformationImplementation::ParseSysCtl() this->AvailablePhysicalMemory = 0; vm_statistics_data_t vmstat; mach_msg_type_number_t count = HOST_VM_INFO_COUNT; - if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat, + if (host_statistics(mach_host_self(), HOST_VM_INFO, + reinterpret_cast<host_info_t>(&vmstat), &count) == KERN_SUCCESS) { err = kw_sysctlbyname_int64("hw.pagesize", &tempInt64); if (err == 0) { @@ -5395,8 +5399,8 @@ bool SystemInformationImplementation::QueryOSInformation() } } - sprintf(operatingSystem, "%ls (Build %ld)", osvi.szCSDVersion, - osvi.dwBuildNumber & 0xFFFF); + snprintf(operatingSystem, sizeof(operatingSystem), "%ls (Build %ld)", + osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF); this->OSVersion = operatingSystem; } else # endif // VER_NT_WORKSTATION @@ -5439,9 +5443,10 @@ bool SystemInformationImplementation::QueryOSInformation() // Display version, service pack (if any), and build number. if (osvi.dwMajorVersion <= 4) { // NB: NT 4.0 and earlier. - sprintf(operatingSystem, "version %ld.%ld %ls (Build %ld)", - osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.szCSDVersion, - osvi.dwBuildNumber & 0xFFFF); + snprintf(operatingSystem, sizeof(operatingSystem), + "version %ld.%ld %ls (Build %ld)", osvi.dwMajorVersion, + osvi.dwMinorVersion, osvi.szCSDVersion, + osvi.dwBuildNumber & 0xFFFF); this->OSVersion = operatingSystem; } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { // Windows XP and .NET server. @@ -5467,8 +5472,8 @@ bool SystemInformationImplementation::QueryOSInformation() } } else { // Windows 2000 and everything else. - sprintf(operatingSystem, "%ls (Build %ld)", osvi.szCSDVersion, - osvi.dwBuildNumber & 0xFFFF); + snprintf(operatingSystem, sizeof(operatingSystem), "%ls (Build %ld)", + osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF); this->OSVersion = operatingSystem; } break; diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 930d84c..6a8520fe 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -34,6 +34,10 @@ #include <utility> #include <vector> +#ifdef _WIN32 +# include <cwchar> +#endif + // Work-around CMake dependency scanning limitation. This must // duplicate the above list of headers. #if 0 @@ -103,6 +107,9 @@ # if defined(_MSC_VER) && _MSC_VER >= 1800 # define KWSYS_WINDOWS_DEPRECATED_GetVersionEx # endif +# ifndef IO_REPARSE_TAG_APPEXECLINK +# define IO_REPARSE_TAG_APPEXECLINK (0x8000001BL) +# endif // from ntifs.h, which can only be used by drivers typedef struct _REPARSE_DATA_BUFFER { @@ -132,8 +139,46 @@ typedef struct _REPARSE_DATA_BUFFER { UCHAR DataBuffer[1]; } GenericReparseBuffer; + struct + { + ULONG Version; + WCHAR StringList[1]; + // In version 3, there are 4 NUL-terminated strings: + // * Package ID + // * Entry Point + // * Executable Path + // * Application Type + } AppExecLinkReparseBuffer; } DUMMYUNIONNAME; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; + +namespace { +WCHAR* GetAppExecLink(PREPARSE_DATA_BUFFER data, size_t& len) +{ + // We only know the layout of version 3. + if (data->AppExecLinkReparseBuffer.Version != 3) { + return nullptr; + } + + WCHAR* pstr = data->AppExecLinkReparseBuffer.StringList; + + // Skip the package id and entry point strings. + for (int i = 0; i < 2; ++i) { + len = std::wcslen(pstr); + if (len == 0) { + return nullptr; + } + pstr += len + 1; + } + + // The third string is the executable path. + len = std::wcslen(pstr); + if (len == 0) { + return nullptr; + } + return pstr; +} +} #endif #if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H @@ -1343,8 +1388,8 @@ bool SystemTools::FileExists(const std::string& filename) return false; } #if defined(_WIN32) - DWORD attr = - GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str()); + const std::wstring path = Encoding::ToWindowsExtendedPath(filename); + DWORD attr = GetFileAttributesW(path.c_str()); if (attr == INVALID_FILE_ATTRIBUTES) { return false; } @@ -1352,12 +1397,38 @@ bool SystemTools::FileExists(const std::string& filename) if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { // Using 0 instead of GENERIC_READ as it allows reading of file attributes // even if we do not have permission to read the file itself - HANDLE handle = - CreateFileW(Encoding::ToWindowsExtendedPath(filename).c_str(), 0, 0, - nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + HANDLE handle = CreateFileW(path.c_str(), 0, 0, nullptr, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, nullptr); if (handle == INVALID_HANDLE_VALUE) { - return false; + // A reparse point may be an execution alias (Windows Store app), which + // is similar to a symlink but it cannot be opened as a regular file. + // We must look at the reparse point data explicitly. + handle = CreateFileW( + path.c_str(), 0, 0, nullptr, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, nullptr); + + if (handle == INVALID_HANDLE_VALUE) { + return false; + } + + byte buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + DWORD bytesReturned = 0; + + if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, nullptr, 0, buffer, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned, + nullptr)) { + CloseHandle(handle); + return false; + } + + CloseHandle(handle); + + PREPARSE_DATA_BUFFER data = + reinterpret_cast<PREPARSE_DATA_BUFFER>(&buffer[0]); + + // Assume that file exists if it is an execution alias. + return data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK; } CloseHandle(handle); @@ -3011,11 +3082,7 @@ bool SystemTools::FileIsDirectory(const std::string& inName) bool SystemTools::FileIsExecutable(const std::string& name) { -#if defined(_WIN32) - return SystemTools::FileExists(name, true); -#else return !FileIsDirectory(name) && TestFileAccess(name, TEST_FILE_EXECUTE); -#endif } bool SystemTools::FileIsSymlink(const std::string& name) @@ -3164,6 +3231,15 @@ Status SystemTools::ReadSymlink(std::string const& newName, data->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR); substituteNameData = data->MountPointReparseBuffer.PathBuffer + data->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR); + } else if (data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) { + // The reparse buffer is a list of 0-terminated non-empty strings, + // terminated by an empty string (0-0). We need the third string. + size_t destLen; + substituteNameData = GetAppExecLink(data, destLen); + if (substituteNameData == nullptr || destLen == 0) { + return Status::Windows(ERROR_SYMLINK_NOT_SUPPORTED); + } + substituteNameLength = static_cast<USHORT>(destLen); } else { return Status::Windows(ERROR_REPARSE_TAG_MISMATCH); } @@ -3767,6 +3843,32 @@ bool SystemTools::Split(const std::string& str, return true; } +std::string SystemTools::Join(const std::vector<std::string>& list, + const std::string& separator) +{ + std::string result; + if (list.empty()) { + return result; + } + + size_t total_size = separator.size() * (list.size() - 1); + for (const std::string& string : list) { + total_size += string.size(); + } + + result.reserve(total_size); + bool needs_separator = false; + for (const std::string& string : list) { + if (needs_separator) { + result += separator; + } + result += string; + needs_separator = true; + } + + return result; +} + /** * Return path of a full filename (no trailing slashes). * Warning: returned path is converted to Unix slashes format. @@ -4526,10 +4628,10 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() } res += " "; - sprintf(buffer, "%ld", osvi.dwMajorVersion); + snprintf(buffer, sizeof(buffer), "%ld", osvi.dwMajorVersion); res += buffer; res += "."; - sprintf(buffer, "%ld", osvi.dwMinorVersion); + snprintf(buffer, sizeof(buffer), "%ld", osvi.dwMinorVersion); res += buffer; } @@ -4549,7 +4651,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() if (lRet == ERROR_SUCCESS) { res += " Service Pack 6a (Build "; - sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF); + snprintf(buffer, sizeof(buffer), "%ld", osvi.dwBuildNumber & 0xFFFF); res += buffer; res += ")"; } else // Windows NT 4.0 prior to SP6a @@ -4557,7 +4659,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() res += " "; res += osvi.szCSDVersion; res += " (Build "; - sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF); + snprintf(buffer, sizeof(buffer), "%ld", osvi.dwBuildNumber & 0xFFFF); res += buffer; res += ")"; } @@ -4568,7 +4670,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() res += " "; res += osvi.szCSDVersion; res += " (Build "; - sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF); + snprintf(buffer, sizeof(buffer), "%ld", osvi.dwBuildNumber & 0xFFFF); res += buffer; res += ")"; } diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index e5d115e..dd0cb3b 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -214,6 +214,13 @@ public: char separator); /** + * Joins a vector of strings into a single string, with separator in between + * each string. + */ + static std::string Join(const std::vector<std::string>& list, + const std::string& separator); + + /** * Return string with space added between capitalized words * (i.e. EatMyShorts becomes Eat My Shorts ) * (note that IEatShorts becomes IEat Shorts) diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx index a847462..79bdc98 100644 --- a/Source/kwsys/testDirectory.cxx +++ b/Source/kwsys/testDirectory.cxx @@ -19,7 +19,7 @@ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ #include <testSystemTools.h> -int _doLongPathTest() +static int _doLongPathTest() { using namespace kwsys; static const int LONG_PATH_THRESHOLD = 512; @@ -77,7 +77,7 @@ int _doLongPathTest() return res; } -int _nonExistentDirectoryTest() +static int _nonExistentDirectoryTest() { using namespace kwsys; int res = 0; @@ -105,7 +105,7 @@ int _nonExistentDirectoryTest() return res; } -int _copyDirectoryTest() +static int _copyDirectoryTest() { using namespace kwsys; const std::string source(TEST_SYSTEMTOOLS_BINARY_DIR diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx index 9ba204e..806c01a 100644 --- a/Source/kwsys/testDynamicLoader.cxx +++ b/Source/kwsys/testDynamicLoader.cxx @@ -11,20 +11,20 @@ // Needed for __GLIBC__ test macro. #ifdef __linux__ # include <features.h> -#endif // Will define LIBDL_SO macro on systems with glibc. -#ifdef __GLIBC__ -# include <gnu/lib-names.h> +# ifdef __GLIBC__ +# include <gnu/lib-names.h> // Define to LIBC_SO, if not defined by above header. -# ifndef LIBDL_SO -# define LIBDL_SO LIBC_SO +# ifndef LIBDL_SO +# define LIBDL_SO LIBC_SO +# endif # endif -#endif // Define the LIBDL_SO macro, if not defined above. -#ifndef LIBDL_SO -# define LIBDL_SO "libdl.so" +# ifndef LIBDL_SO +# define LIBDL_SO "libdl.so" +# endif #endif // Work-around CMake dependency scanning limitation. This must @@ -40,6 +40,10 @@ // left on disk. #include <testSystemTools.h> +// For TestDynamicLoaderData, which, though not referenced literally, +// is referenced semantically. +#include "testDynload.h" + static std::string GetLibName(const char* lname, const char* subdir = nullptr) { // Construct proper name of lib diff --git a/Source/kwsys/testDynload.c b/Source/kwsys/testDynload.c index 33a431e..83056c0 100644 --- a/Source/kwsys/testDynload.c +++ b/Source/kwsys/testDynload.c @@ -6,6 +6,8 @@ # define DL_EXPORT #endif +#include "testDynload.h" + DL_EXPORT int TestDynamicLoaderData = 0; DL_EXPORT void TestDynamicLoaderSymbolPointer(void) diff --git a/Source/kwsys/testDynload.h b/Source/kwsys/testDynload.h new file mode 100644 index 0000000..dc0d7a1 --- /dev/null +++ b/Source/kwsys/testDynload.h @@ -0,0 +1,9 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ +#ifdef _WIN32 +# define DL_EXPORT __declspec(dllexport) +#else +# define DL_EXPORT +#endif + +extern DL_EXPORT int TestDynamicLoaderData; diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx index ee93e8d..1d605cb 100644 --- a/Source/kwsys/testEncoding.cxx +++ b/Source/kwsys/testEncoding.cxx @@ -80,7 +80,7 @@ static int testRobustEncoding() std::ios::fmtflags const& flags = std::cout.flags(); int ret = 0; - char cstr[] = { (char)-1, 0 }; + char cstr[] = { static_cast<char>(-1), 0 }; // this conversion could fail std::wstring wstr = kwsys::Encoding::ToWide(cstr); @@ -89,7 +89,7 @@ static int testRobustEncoding() const wchar_t* wcstr = wstr.c_str(); std::cout << "ToWide(NULL) returned"; for (size_t i = 0; i < wstr.size(); i++) { - std::cout << " " << std::hex << (int)wcstr[i]; + std::cout << " " << std::hex << static_cast<int>(wcstr[i]); } std::cout << std::endl; ret++; @@ -99,7 +99,7 @@ static int testRobustEncoding() const wchar_t* wcstr = wstr.c_str(); std::cout << "ToWide(\"\") returned"; for (size_t i = 0; i < wstr.size(); i++) { - std::cout << " " << std::hex << (int)wcstr[i]; + std::cout << " " << std::hex << static_cast<int>(wcstr[i]); } std::cout << std::endl; ret++; @@ -160,7 +160,9 @@ static int testCommandLineArguments() { int status = 0; - char const* argv[2] = { "./app.exe", (char const*)helloWorldStrings[1] }; + char const* argv[2] = { + "./app.exe", reinterpret_cast<char const*>(helloWorldStrings[1]) + }; kwsys::Encoding::CommandLineArguments args(2, argv); kwsys::Encoding::CommandLineArguments arg2 = diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 6ccc7a7..f96bd71 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -626,6 +626,16 @@ static bool CheckStringOperations() res = false; } + std::vector<std::string> linesToJoin = { "Mary", "Had", "A", "Little", + "Lamb." }; + std::string joinResult = kwsys::SystemTools::Join(linesToJoin, " "); + if (joinResult != "Mary Had A Little Lamb.") { + std::cerr << "Problem with Join " + "\"Mary Had A Little Lamb.\"" + << std::endl; + res = false; + } + if (kwsys::SystemTools::ConvertToWindowsOutputPath( "L://Local Mojo/Hex Power Pack/Iffy Voodoo") != "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"") { |