diff options
Diffstat (limited to 'Source')
648 files changed, 9511 insertions, 6305 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 1b6bb00..1be424a 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -182,6 +182,8 @@ set(SRCS cmCheckCustomOutputs.cxx cmCLocaleEnvironmentScope.h cmCLocaleEnvironmentScope.cxx + cmCMakePath.h + cmCMakePath.cxx cmCommandArgumentParserHelper.cxx cmCommonTargetGenerator.cxx cmCommonTargetGenerator.h @@ -334,6 +336,7 @@ set(SRCS cmInstallTargetGenerator.cxx cmInstallDirectoryGenerator.h cmInstallDirectoryGenerator.cxx + cmJSONHelpers.h cmLDConfigLDConfigTool.cxx cmLDConfigLDConfigTool.h cmLDConfigTool.cxx @@ -412,6 +415,8 @@ set(SRCS cmSourceFileLocationKind.h cmSourceGroup.cxx cmSourceGroup.h + cmStandardLevelResolver.cxx + cmStandardLevelResolver.h cmState.cxx cmState.h cmStateDirectory.cxx @@ -496,6 +501,8 @@ set(SRCS cmCMakeLanguageCommand.h cmCMakeMinimumRequired.cxx cmCMakeMinimumRequired.h + cmCMakePathCommand.h + cmCMakePathCommand.cxx cmCMakePolicyCommand.cxx cmCMakePolicyCommand.h cmConditionEvaluator.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 5da59d4..835b785 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 18) -set(CMake_VERSION_PATCH 2) +set(CMake_VERSION_PATCH 20200910) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/IFW/cmCPackIFWCommon.h b/Source/CPack/IFW/cmCPackIFWCommon.h index 354d849..95ed213 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.h +++ b/Source/CPack/IFW/cmCPackIFWCommon.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackIFWCommon_h -#define cmCPackIFWCommon_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -77,5 +76,3 @@ protected: cmCPackLog_msg.str().c_str()); \ } \ } while (false) - -#endif // cmCPackIFWCommon_h diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h index 86a73c8..024d25d 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.h +++ b/Source/CPack/IFW/cmCPackIFWGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackIFWGenerator_h -#define cmCPackIFWGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -152,5 +151,3 @@ private: std::vector<std::string> PkgsDirsVector; std::vector<std::string> RepoDirsVector; }; - -#endif diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h index 8b3f96a..6f398e3 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.h +++ b/Source/CPack/IFW/cmCPackIFWInstaller.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackIFWInstaller_h -#define cmCPackIFWInstaller_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -132,5 +131,3 @@ protected: void printSkippedOptionWarning(const std::string& optionName, const std::string& optionValue); }; - -#endif // cmCPackIFWInstaller_h diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h index 6a4a170..dbd5540 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.h +++ b/Source/CPack/IFW/cmCPackIFWPackage.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackIFWPackage_h -#define cmCPackIFWPackage_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -149,5 +148,3 @@ public: // Patch to package directory std::string Directory; }; - -#endif // cmCPackIFWPackage_h diff --git a/Source/CPack/IFW/cmCPackIFWRepository.h b/Source/CPack/IFW/cmCPackIFWRepository.h index c293981..21afd8b 100644 --- a/Source/CPack/IFW/cmCPackIFWRepository.h +++ b/Source/CPack/IFW/cmCPackIFWRepository.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackIFWRepository_h -#define cmCPackIFWRepository_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -84,5 +83,3 @@ public: RepositoriesVector RepositoryUpdate; std::string Directory; }; - -#endif // cmCPackIFWRepository_h diff --git a/Source/CPack/WiX/cmCMakeToWixPath.h b/Source/CPack/WiX/cmCMakeToWixPath.h index 8bb9e04..074cc8e 100644 --- a/Source/CPack/WiX/cmCMakeToWixPath.h +++ b/Source/CPack/WiX/cmCMakeToWixPath.h @@ -1,12 +1,9 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCMakeToWixPath_h -#define cmCMakeToWixPath_h +#pragma once #include "cmConfigure.h" //IWYU pragma: keep #include <string> std::string CMakeToWixPath(const std::string& cygpath); - -#endif // cmCMakeToWixPath_h diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 72af10b..8b3644f 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -221,6 +221,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() this->LightExtensions.insert("WixUIExtension"); CollectExtensions("CPACK_WIX_EXTENSIONS", this->LightExtensions); CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions); + CollectXmlNamespaces("CPACK_WIX_CUSTOM_XMLNS", this->CustomXmlNamespaces); const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); if (patchFilePath) { @@ -322,6 +323,7 @@ void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() cmWIXSourceWriter includeFile(this->Logger, includeFilename, this->ComponentGuidType, cmWIXSourceWriter::INCLUDE_ELEMENT_ROOT); + InjectXmlNamespaces(includeFile); CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_GUID"); CopyDefinition(includeFile, "CPACK_WIX_UPGRADE_GUID"); @@ -345,6 +347,7 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile() cmWIXSourceWriter includeFile(this->Logger, includeFilename, this->ComponentGuidType, cmWIXSourceWriter::INCLUDE_ELEMENT_ROOT); + InjectXmlNamespaces(includeFile); std::string prefix = "CPACK_WIX_PROPERTY_"; std::vector<std::string> options = GetOptions(); @@ -393,6 +396,7 @@ void cmCPackWIXGenerator::CreateWiXProductFragmentIncludeFile() cmWIXSourceWriter includeFile(this->Logger, includeFilename, this->ComponentGuidType, cmWIXSourceWriter::INCLUDE_ELEMENT_ROOT); + InjectXmlNamespaces(includeFile); this->Patch->ApplyFragment("#PRODUCT", includeFile); } @@ -432,6 +436,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() cmWIXDirectoriesSourceWriter directoryDefinitions( this->Logger, directoryDefinitionsFilename, this->ComponentGuidType); + InjectXmlNamespaces(directoryDefinitions); directoryDefinitions.BeginElement("Fragment"); std::string installRoot; @@ -453,6 +458,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() cmWIXFilesSourceWriter fileDefinitions(this->Logger, fileDefinitionsFilename, this->ComponentGuidType); + InjectXmlNamespaces(fileDefinitions); fileDefinitions.BeginElement("Fragment"); @@ -463,6 +469,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() cmWIXFeaturesSourceWriter featureDefinitions( this->Logger, featureDefinitionsFilename, this->ComponentGuidType); + InjectXmlNamespaces(featureDefinitions); featureDefinitions.BeginElement("Fragment"); @@ -1147,6 +1154,35 @@ void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName, extensions.insert(list.begin(), list.end()); } +void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName, + xmlns_map_t& namespaces) +{ + const char* variableContent = GetOption(variableName.c_str()); + if (!variableContent) { + return; + } + + std::vector<std::string> list = cmExpandedList(variableContent); + for (std::string const& str : list) { + auto pos = str.find('='); + if (pos != std::string::npos) { + auto name = str.substr(0, pos); + auto value = str.substr(pos + 1); + namespaces.emplace(std::make_pair(name, value)); + } else { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Invalid element in CPACK_WIX_CUSTOM_XMLNS ignored: " + << "\"" << str << "\"" << std::endl); + } + } + std::ostringstream oss; + for (auto& ns : namespaces) { + oss << " xmlns:" << ns.first << "=\"" + << cmWIXSourceWriter::EscapeAttributeValue(ns.second) << '"'; + } + SetOption("CPACK_WIX_CUSTOM_XMLNS_EXPANDED", oss.str().c_str()); +} + void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName, std::ostream& stream) { @@ -1172,3 +1208,10 @@ std::string cmCPackWIXGenerator::RelativePathWithoutComponentPrefix( return path.substr(pos + 1); } + +void cmCPackWIXGenerator::InjectXmlNamespaces(cmWIXSourceWriter& sourceWriter) +{ + for (auto& ns : this->CustomXmlNamespaces) { + sourceWriter.AddAttributeUnlessEmpty("xmlns:" + ns.first, ns.second); + } +} diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index d5a16ec..8609cf3 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackWIXGenerator_h -#define cmCPackWIXGenerator_h +#pragma once #include <map> #include <memory> @@ -49,6 +48,7 @@ private: using id_map_t = std::map<std::string, std::string>; using ambiguity_map_t = std::map<std::string, size_t>; using extension_set_t = std::set<std::string>; + using xmlns_map_t = std::map<std::string, std::string>; enum class DefinitionType { @@ -147,16 +147,22 @@ private: void CollectExtensions(std::string const& variableName, extension_set_t& extensions); + void CollectXmlNamespaces(std::string const& variableName, + xmlns_map_t& namespaces); + void AddCustomFlags(std::string const& variableName, std::ostream& stream); std::string RelativePathWithoutComponentPrefix(std::string const& path); + void InjectXmlNamespaces(cmWIXSourceWriter& sourceWriter); + std::vector<std::string> WixSources; id_map_t PathToIdMap; ambiguity_map_t IdAmbiguityCounter; extension_set_t CandleExtensions; extension_set_t LightExtensions; + xmlns_map_t CustomXmlNamespaces; std::string CPackTopLevel; @@ -164,5 +170,3 @@ private: cmWIXSourceWriter::GuidType ComponentGuidType; }; - -#endif diff --git a/Source/CPack/WiX/cmWIXAccessControlList.h b/Source/CPack/WiX/cmWIXAccessControlList.h index 64f9a13..ee5efa5 100644 --- a/Source/CPack/WiX/cmWIXAccessControlList.h +++ b/Source/CPack/WiX/cmWIXAccessControlList.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWIXAccessControlList_h -#define cmWIXAccessControlList_h +#pragma once #include "cmCPackLog.h" #include "cmInstalledFile.h" @@ -29,5 +28,3 @@ private: cmInstalledFile const& InstalledFile; cmWIXSourceWriter& SourceWriter; }; - -#endif diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h index a907d6d..0af3094 100644 --- a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h +++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWIXDirectoriesSourceWriter_h -#define cmWIXDirectoriesSourceWriter_h +#pragma once #include <string> @@ -29,5 +28,3 @@ public: void EndInstallationPrefixDirectory(size_t size); }; - -#endif diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h index e03e87b..0facf97 100644 --- a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h +++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWIXFeaturesSourceWriter_h -#define cmWIXFeaturesSourceWriter_h +#pragma once #include "cmCPackGenerator.h" #include "cmWIXPatch.h" @@ -27,5 +26,3 @@ public: void EmitComponentRef(std::string const& id); }; - -#endif diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.h b/Source/CPack/WiX/cmWIXFilesSourceWriter.h index 8cc98f5..60dddd4 100644 --- a/Source/CPack/WiX/cmWIXFilesSourceWriter.h +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWIXFilesSourceWriter_h -#define cmWIXFilesSourceWriter_h +#pragma once #include "cmCPackGenerator.h" #include "cmWIXPatch.h" @@ -37,5 +36,3 @@ public: std::string const& filePath, cmWIXPatch& patch, cmInstalledFile const* installedFile); }; - -#endif diff --git a/Source/CPack/WiX/cmWIXPatch.h b/Source/CPack/WiX/cmWIXPatch.h index 31a60f4..c78722d 100644 --- a/Source/CPack/WiX/cmWIXPatch.h +++ b/Source/CPack/WiX/cmWIXPatch.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWIXPatch_h -#define cmWIXPatch_h +#pragma once #include <string> @@ -33,5 +32,3 @@ private: cmWIXPatchParser::fragment_map_t Fragments; }; - -#endif diff --git a/Source/CPack/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h index 8d5d2ad..70a21bc 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.h +++ b/Source/CPack/WiX/cmWIXPatchParser.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackWIXPatchParser_h -#define cmCPackWIXPatchParser_h +#pragma once #include <map> #include <memory> @@ -91,5 +90,3 @@ private: std::vector<cmWIXPatchElement*> ElementStack; }; - -#endif diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h index a879f3d..99471f1 100644 --- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWIXRichTextFormatWriter_h -#define cmWIXRichTextFormatWriter_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -42,5 +41,3 @@ private: cmsys::ofstream File; }; - -#endif diff --git a/Source/CPack/WiX/cmWIXShortcut.h b/Source/CPack/WiX/cmWIXShortcut.h index c67baf3..315b5ea 100644 --- a/Source/CPack/WiX/cmWIXShortcut.h +++ b/Source/CPack/WiX/cmWIXShortcut.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWIXShortcut_h -#define cmWIXShortcut_h +#pragma once #include <map> #include <set> @@ -56,5 +55,3 @@ private: shortcut_type_map_t Shortcuts; shortcut_id_map_t EmptyIdMap; }; - -#endif diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h index 8cc2070..f643acd 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.h +++ b/Source/CPack/WiX/cmWIXSourceWriter.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWIXSourceWriter_h -#define cmWIXSourceWriter_h +#pragma once #include <string> #include <vector> @@ -50,6 +49,8 @@ public: std::string CreateGuidFromComponentId(std::string const& componentId); + static std::string EscapeAttributeValue(std::string const& value); + protected: cmCPackLog* Logger; @@ -64,8 +65,6 @@ private: void Indent(size_t count); - static std::string EscapeAttributeValue(std::string const& value); - cmsys::ofstream File; State State; @@ -76,5 +75,3 @@ private: GuidType ComponentGuidType; }; - -#endif diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h index 7eb5665..5b40013 100644 --- a/Source/CPack/cmCPackArchiveGenerator.h +++ b/Source/CPack/cmCPackArchiveGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackArchiveGenerator_h -#define cmCPackArchiveGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -93,5 +92,3 @@ private: std::string ArchiveFormat; std::string OutputExtension; }; - -#endif diff --git a/Source/CPack/cmCPackBundleGenerator.h b/Source/CPack/cmCPackBundleGenerator.h index 27bac3a..072d14f 100644 --- a/Source/CPack/cmCPackBundleGenerator.h +++ b/Source/CPack/cmCPackBundleGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackBundleGenerator_h -#define cmCPackBundleGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -33,5 +32,3 @@ protected: std::string InstallPrefix; }; - -#endif diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h index bb980d7..58377d4 100644 --- a/Source/CPack/cmCPackComponentGroup.h +++ b/Source/CPack/cmCPackComponentGroup.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackComponentGroup_h -#define cmCPackComponentGroup_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -167,5 +166,3 @@ public: /// The list of components. std::vector<cmCPackComponent*> Components; }; - -#endif diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.h b/Source/CPack/cmCPackCygwinBinaryGenerator.h index 47bd41e..f5f7700 100644 --- a/Source/CPack/cmCPackCygwinBinaryGenerator.h +++ b/Source/CPack/cmCPackCygwinBinaryGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackCygwinBinaryGenerator_h -#define cmCPackCygwinBinaryGenerator_h +#pragma once #include "cmCPackArchiveGenerator.h" @@ -25,5 +24,3 @@ protected: virtual const char* GetOutputExtension(); std::string OutputExtension; }; - -#endif diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.h b/Source/CPack/cmCPackCygwinSourceGenerator.h index 98d8f0a..964a4d4 100644 --- a/Source/CPack/cmCPackCygwinSourceGenerator.h +++ b/Source/CPack/cmCPackCygwinSourceGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackCygwinSourceGenerator_h -#define cmCPackCygwinSourceGenerator_h +#pragma once #include "cmCPackArchiveGenerator.h" @@ -27,5 +26,3 @@ protected: std::string InstallPrefix; std::string OutputExtension; }; - -#endif diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 3d5fe6b..560e5c1 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -696,57 +696,57 @@ int cmCPackDebGenerator::createDeb() const char* debian_pkg_source = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); - if (debian_pkg_source && *debian_pkg_source) { + if (cmNonempty(debian_pkg_source)) { controlValues["Source"] = debian_pkg_source; } const char* debian_pkg_dep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS"); - if (debian_pkg_dep && *debian_pkg_dep) { + if (cmNonempty(debian_pkg_dep)) { controlValues["Depends"] = debian_pkg_dep; } const char* debian_pkg_rec = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS"); - if (debian_pkg_rec && *debian_pkg_rec) { + if (cmNonempty(debian_pkg_rec)) { controlValues["Recommends"] = debian_pkg_rec; } const char* debian_pkg_sug = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS"); - if (debian_pkg_sug && *debian_pkg_sug) { + if (cmNonempty(debian_pkg_sug)) { controlValues["Suggests"] = debian_pkg_sug; } const char* debian_pkg_url = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE"); - if (debian_pkg_url && *debian_pkg_url) { + if (cmNonempty(debian_pkg_url)) { controlValues["Homepage"] = debian_pkg_url; } const char* debian_pkg_predep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PREDEPENDS"); - if (debian_pkg_predep && *debian_pkg_predep) { + if (cmNonempty(debian_pkg_predep)) { controlValues["Pre-Depends"] = debian_pkg_predep; } const char* debian_pkg_enhances = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ENHANCES"); - if (debian_pkg_enhances && *debian_pkg_enhances) { + if (cmNonempty(debian_pkg_enhances)) { controlValues["Enhances"] = debian_pkg_enhances; } const char* debian_pkg_breaks = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_BREAKS"); - if (debian_pkg_breaks && *debian_pkg_breaks) { + if (cmNonempty(debian_pkg_breaks)) { controlValues["Breaks"] = debian_pkg_breaks; } const char* debian_pkg_conflicts = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONFLICTS"); - if (debian_pkg_conflicts && *debian_pkg_conflicts) { + if (cmNonempty(debian_pkg_conflicts)) { controlValues["Conflicts"] = debian_pkg_conflicts; } const char* debian_pkg_provides = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES"); - if (debian_pkg_provides && *debian_pkg_provides) { + if (cmNonempty(debian_pkg_provides)) { controlValues["Provides"] = debian_pkg_provides; } const char* debian_pkg_replaces = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_REPLACES"); - if (debian_pkg_replaces && *debian_pkg_replaces) { + if (cmNonempty(debian_pkg_replaces)) { controlValues["Replaces"] = debian_pkg_replaces; } @@ -756,7 +756,7 @@ int cmCPackDebGenerator::createDeb() const char* debian_pkg_shlibs = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SHLIBS"); const bool gen_shibs = this->IsOn("CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS") && - debian_pkg_shlibs && *debian_pkg_shlibs; + cmNonempty(debian_pkg_shlibs); if (gen_shibs) { cmGeneratedFileStream out; out.Open(shlibsfilename, false, true); @@ -832,11 +832,11 @@ int cmCPackDebGenerator::createDbgsymDDeb() const char* debian_pkg_source = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); - if (debian_pkg_source && *debian_pkg_source) { + if (cmNonempty(debian_pkg_source)) { controlValues["Source"] = debian_pkg_source; } const char* debian_build_ids = this->GetOption("GEN_BUILD_IDS"); - if (debian_build_ids && *debian_build_ids) { + if (cmNonempty(debian_build_ids)) { controlValues["Build-Ids"] = debian_build_ids; } diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h index ce77e08..ee8f39a 100644 --- a/Source/CPack/cmCPackDebGenerator.h +++ b/Source/CPack/cmCPackDebGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackDebGenerator_h -#define cmCPackDebGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -69,5 +68,3 @@ private: std::vector<std::string> packageFiles; }; - -#endif diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index fe7abf4..cefb906 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -8,7 +8,9 @@ #include <map> #include <CoreFoundation/CoreFoundation.h> +#include <cm3p/kwiml/abi.h> +#include "cmsys/Base64.h" #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" @@ -18,6 +20,7 @@ #include "cmGeneratedFileStream.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmXMLWriter.h" #ifdef HAVE_CoreServices // For the old LocaleStringToLangAndRegionCodes() function, to convert @@ -26,36 +29,28 @@ # include <CoreServices/CoreServices.h> #endif -static const char* SLAHeader = - "data 'LPic' (5000) {\n" - " $\"0002 0011 0003 0001 0000 0000 0002 0000\"\n" - " $\"0008 0003 0000 0001 0004 0000 0004 0005\"\n" - " $\"0000 000E 0006 0001 0005 0007 0000 0007\"\n" - " $\"0008 0000 0047 0009 0000 0034 000A 0001\"\n" - " $\"0035 000B 0001 0020 000C 0000 0011 000D\"\n" - " $\"0000 005B 0004 0000 0033 000F 0001 000C\"\n" - " $\"0010 0000 000B 000E 0000\"\n" - "};\n" - "\n"; - -static const char* SLASTREnglish = - "resource 'STR#' (5002, \"English\") {\n" - " {\n" - " \"English\",\n" - " \"Agree\",\n" - " \"Disagree\",\n" - " \"Print\",\n" - " \"Save...\",\n" - " \"You agree to the License Agreement terms when you click \"\n" - " \"the \\\"Agree\\\" button.\",\n" - " \"Software License Agreement\",\n" - " \"This text cannot be saved. This disk may be full or locked, " - "or the \"\n" - " \"file may be locked.\",\n" - " \"Unable to print. Make sure you have selected a printer.\"\n" - " }\n" - "};\n" - "\n"; +static const uint16_t DefaultLpic[] = { + /* clang-format off */ + 0x0002, 0x0011, 0x0003, 0x0001, 0x0000, 0x0000, 0x0002, 0x0000, + 0x0008, 0x0003, 0x0000, 0x0001, 0x0004, 0x0000, 0x0004, 0x0005, + 0x0000, 0x000E, 0x0006, 0x0001, 0x0005, 0x0007, 0x0000, 0x0007, + 0x0008, 0x0000, 0x0047, 0x0009, 0x0000, 0x0034, 0x000A, 0x0001, + 0x0035, 0x000B, 0x0001, 0x0020, 0x000C, 0x0000, 0x0011, 0x000D, + 0x0000, 0x005B, 0x0004, 0x0000, 0x0033, 0x000F, 0x0001, 0x000C, + 0x0010, 0x0000, 0x000B, 0x000E, 0x0000 + /* clang-format on */ +}; + +static const std::vector<std::string> DefaultMenu = { + { "English", "Agree", "Disagree", "Print", "Save...", + // NOLINTNEXTLINE(bugprone-suspicious-missing-comma) + "You agree to the License Agreement terms when " + "you click the \"Agree\" button.", + "Software License Agreement", + "This text cannot be saved. " + "This disk may be full or locked, or the file may be locked.", + "Unable to print. Make sure you have selected a printer." } +}; cmCPackDragNDropGenerator::cmCPackDragNDropGenerator() : singleLicense(false) @@ -523,22 +518,43 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } } + // Create the final compressed read-only disk image ... + std::ostringstream final_image_command; + final_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); + final_image_command << " convert \"" << temp_image << "\""; + final_image_command << " -format "; + final_image_command << cpack_dmg_format; + final_image_command << " -imagekey"; + final_image_command << " zlib-level=9"; + final_image_command << " -o \"" << output_file << "\""; + + std::string convert_error; + + if (!this->RunCommand(final_image_command, &convert_error)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error compressing disk image." << std::endl + << convert_error + << std::endl); + + return 0; + } + if (!cpack_license_file.empty() || !slaDirectory.empty()) { // Use old hardcoded style if sla_dir is not set bool oldStyle = slaDirectory.empty(); - std::string sla_r = - cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/sla.r"); + std::string sla_xml = + cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/sla.xml"); std::vector<std::string> languages; if (!oldStyle) { cmExpandList(cpack_dmg_languages, languages); } - cmGeneratedFileStream ofs(sla_r); - ofs << "#include <CoreServices/CoreServices.r>\n\n"; + std::vector<uint16_t> header_data; if (oldStyle) { - ofs << SLAHeader; - ofs << "\n"; + header_data = std::vector<uint16_t>( + DefaultLpic, + DefaultLpic + (sizeof(DefaultLpic) / sizeof(*DefaultLpic))); } else { /* * LPic Layout @@ -558,8 +574,6 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, * } */ - // Create vector first for readability, then iterate to write to ofs - std::vector<uint16_t> header_data; header_data.push_back(0); header_data.push_back(languages.size()); for (size_t i = 0; i < languages.size(); ++i) { @@ -596,52 +610,50 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, header_data.push_back(0); #endif } - ofs << "data 'LPic' (5000) {\n"; - ofs << std::hex << std::uppercase << std::setfill('0'); - - for (size_t i = 0; i < header_data.size(); ++i) { - if (i % 8 == 0) { - ofs << " $\""; - } - - ofs << std::setw(4) << header_data[i]; + } - if (i % 8 == 7 || i == header_data.size() - 1) { - ofs << "\"\n"; - } else { - ofs << " "; - } + RezDoc rez; + + { + RezDict lpic = { {}, 5000, {} }; + lpic.Data.reserve(header_data.size() * sizeof(header_data[0])); + for (uint16_t x : header_data) { + // LPic header is big-endian. + char* d = reinterpret_cast<char*>(&x); +#if KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE + lpic.Data.push_back(d[1]); + lpic.Data.push_back(d[0]); +#else + lpic.Data.push_back(d[0]); + lpic.Data.push_back(d[1]); +#endif } - ofs << "};\n\n"; - // Reset ofs options - ofs << std::dec << std::nouppercase << std::setfill(' '); + rez.LPic.Entries.emplace_back(std::move(lpic)); } bool have_write_license_error = false; std::string error; if (oldStyle) { - if (!this->WriteLicense(ofs, 0, "", cpack_license_file, &error)) { + if (!this->WriteLicense(rez, 0, "", cpack_license_file, &error)) { have_write_license_error = true; } } else { for (size_t i = 0; i < languages.size() && !have_write_license_error; ++i) { if (singleLicense) { - if (!this->WriteLicense(ofs, i + 5000, languages[i], + if (!this->WriteLicense(rez, i + 5000, languages[i], cpack_license_file, &error)) { have_write_license_error = true; } } else { - if (!this->WriteLicense(ofs, i + 5000, languages[i], "", &error)) { + if (!this->WriteLicense(rez, i + 5000, languages[i], "", &error)) { have_write_license_error = true; } } } } - ofs.Close(); - if (have_write_license_error) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error writing license file to SLA." << std::endl @@ -650,96 +662,27 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, return 0; } - if (temp_image_format != "UDZO") { - temp_image_format = "UDZO"; - // convert to UDZO to enable unflatten/flatten - std::string temp_udzo = cmStrCat( - this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp-udzo.dmg"); + this->WriteRezXML(sla_xml, rez); - std::ostringstream udco_image_command; - udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); - udco_image_command << " convert \"" << temp_image << "\""; - udco_image_command << " -format UDZO"; - udco_image_command << " -ov -o \"" << temp_udzo << "\""; - - if (!this->RunCommand(udco_image_command, &error)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error converting to UDCO dmg for adding SLA." - << std::endl - << error << std::endl); - return 0; - } - temp_image = temp_udzo; - } - - // unflatten dmg - std::ostringstream unflatten_command; - unflatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); - unflatten_command << " unflatten "; - unflatten_command << "\"" << temp_image << "\""; - - if (!this->RunCommand(unflatten_command, &error)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error unflattening dmg for adding SLA." << std::endl - << error - << std::endl); - return 0; - } - - // Rez the SLA + // Create the final compressed read-only disk image ... std::ostringstream embed_sla_command; - embed_sla_command << this->GetOption("CPACK_COMMAND_REZ"); - const char* sysroot = this->GetOption("CPACK_OSX_SYSROOT"); - if (sysroot && sysroot[0] != '\0') { - embed_sla_command << " -isysroot \"" << sysroot << "\""; - } - embed_sla_command << " \"" << sla_r << "\""; - embed_sla_command << " -a -o "; - embed_sla_command << "\"" << temp_image << "\""; - - if (!this->RunCommand(embed_sla_command, &error)) { + embed_sla_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); + embed_sla_command << " udifrez"; + embed_sla_command << " -xml"; + embed_sla_command << " \"" << sla_xml << "\""; + embed_sla_command << " FIXME_WHY_IS_THIS_ARGUMENT_NEEDED"; + embed_sla_command << " \"" << output_file << "\""; + std::string embed_error; + if (!this->RunCommand(embed_sla_command, &embed_error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error adding SLA." << std::endl - << error << std::endl); - return 0; - } - - // flatten dmg - std::ostringstream flatten_command; - flatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); - flatten_command << " flatten "; - flatten_command << "\"" << temp_image << "\""; + "Error compressing disk image." << std::endl + << embed_error + << std::endl); - if (!this->RunCommand(flatten_command, &error)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error flattening dmg for adding SLA." << std::endl - << error - << std::endl); return 0; } } - // Create the final compressed read-only disk image ... - std::ostringstream final_image_command; - final_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); - final_image_command << " convert \"" << temp_image << "\""; - final_image_command << " -format "; - final_image_command << cpack_dmg_format; - final_image_command << " -imagekey"; - final_image_command << " zlib-level=9"; - final_image_command << " -o \"" << output_file << "\""; - - std::string convert_error; - - if (!this->RunCommand(final_image_command, &convert_error)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error compressing disk image." << std::endl - << convert_error - << std::endl); - - return 0; - } - return 1; } @@ -788,10 +731,67 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( return GetComponentPackageFileName(package_file_name, componentName, false); } -bool cmCPackDragNDropGenerator::WriteLicense( - cmGeneratedFileStream& outputStream, int licenseNumber, - std::string licenseLanguage, const std::string& licenseFile, - std::string* error) +void cmCPackDragNDropGenerator::WriteRezXML(std::string const& file, + RezDoc const& rez) +{ + cmGeneratedFileStream fxml(file); + cmXMLWriter xml(fxml); + xml.StartDocument(); + xml.StartElement("plist"); + xml.Attribute("version", "1.0"); + xml.StartElement("dict"); + this->WriteRezArray(xml, rez.LPic); + this->WriteRezArray(xml, rez.Menu); + this->WriteRezArray(xml, rez.Text); + this->WriteRezArray(xml, rez.RTF); + xml.EndElement(); // dict + xml.EndElement(); // plist + xml.EndDocument(); + fxml.Close(); +} + +void cmCPackDragNDropGenerator::WriteRezArray(cmXMLWriter& xml, + RezArray const& array) +{ + if (array.Entries.empty()) { + return; + } + xml.StartElement("key"); + xml.Content(array.Key); + xml.EndElement(); // key + xml.StartElement("array"); + for (RezDict const& dict : array.Entries) { + this->WriteRezDict(xml, dict); + } + xml.EndElement(); // array +} + +void cmCPackDragNDropGenerator::WriteRezDict(cmXMLWriter& xml, + RezDict const& dict) +{ + std::vector<char> base64buf(dict.Data.size() * 3 / 2 + 5); + size_t base64len = + cmsysBase64_Encode(dict.Data.data(), dict.Data.size(), + reinterpret_cast<unsigned char*>(base64buf.data()), 0); + std::string base64data(base64buf.data(), base64len); + /* clang-format off */ + xml.StartElement("dict"); + xml.StartElement("key"); xml.Content("Attributes"); xml.EndElement(); + xml.StartElement("string"); xml.Content("0x0000"); xml.EndElement(); + xml.StartElement("key"); xml.Content("Data"); xml.EndElement(); + xml.StartElement("data"); xml.Content(base64data); xml.EndElement(); + xml.StartElement("key"); xml.Content("ID"); xml.EndElement(); + xml.StartElement("string"); xml.Content(dict.ID); xml.EndElement(); + xml.StartElement("key"); xml.Content("Name"); xml.EndElement(); + xml.StartElement("string"); xml.Content(dict.Name); xml.EndElement(); + xml.EndElement(); // dict + /* clang-format on */ +} + +bool cmCPackDragNDropGenerator::WriteLicense(RezDoc& rez, size_t licenseNumber, + std::string licenseLanguage, + const std::string& licenseFile, + std::string* error) { if (!licenseFile.empty() && !singleLicense) { licenseNumber = 5002; @@ -799,11 +799,11 @@ bool cmCPackDragNDropGenerator::WriteLicense( } // License file - std::string license_format = "TEXT"; + RezArray* licenseArray = &rez.Text; std::string actual_license; if (!licenseFile.empty()) { if (cmHasLiteralSuffix(licenseFile, ".rtf")) { - license_format = "RTF "; + licenseArray = &rez.RTF; } actual_license = licenseFile; } else { @@ -812,85 +812,86 @@ bool cmCPackDragNDropGenerator::WriteLicense( if (cmSystemTools::FileExists(license_wo_ext + ".txt")) { actual_license = license_wo_ext + ".txt"; } else { - license_format = "RTF "; + licenseArray = &rez.RTF; actual_license = license_wo_ext + ".rtf"; } } - // License header - outputStream << "data '" << license_format << "' (" << licenseNumber - << ", \"" << licenseLanguage << "\") {\n"; // License body - cmsys::ifstream license_ifs; - license_ifs.open(actual_license.c_str()); - if (license_ifs.is_open()) { - while (license_ifs.good()) { - std::string line; - std::getline(license_ifs, line); - if (!line.empty()) { - EscapeQuotesAndBackslashes(line); - std::vector<std::string> lines; - if (!this->BreakLongLine(line, lines, error)) { - return false; - } - for (auto const& l : lines) { - outputStream << " \"" << l << "\"\n"; - } - } - outputStream << " \"\\n\"\n"; + { + RezDict license = { licenseLanguage, licenseNumber, {} }; + std::vector<std::string> lines; + if (!this->ReadFile(actual_license, lines, error)) { + return false; } - license_ifs.close(); + this->EncodeLicense(license, lines); + licenseArray->Entries.emplace_back(std::move(license)); } - // End of License - outputStream << "};\n\n"; - if (!licenseFile.empty() && !singleLicense) { - outputStream << SLASTREnglish; - } else { - // Menu header - outputStream << "resource 'STR#' (" << licenseNumber << ", \"" - << licenseLanguage << "\") {\n"; - outputStream << " {\n"; - - // Menu body - cmsys::ifstream menu_ifs; - menu_ifs.open( - (slaDirectory + "/" + licenseLanguage + ".menu.txt").c_str()); - if (menu_ifs.is_open()) { - size_t lines_written = 0; - while (menu_ifs.good()) { - // Lines written from original file, not from broken up lines - std::string line; - std::getline(menu_ifs, line); - if (!line.empty()) { - EscapeQuotesAndBackslashes(line); - std::vector<std::string> lines; - if (!this->BreakLongLine(line, lines, error)) { - return false; - } - for (size_t i = 0; i < lines.size(); ++i) { - std::string comma; - // We need a comma after every complete string, - // but not on the very last line - if (lines_written != 8 && i == lines.size() - 1) { - comma = ","; - } else { - comma = ""; - } - outputStream << " \"" << lines[i] << "\"" << comma << "\n"; - } - ++lines_written; - } + // Menu body + { + RezDict menu = { licenseLanguage, licenseNumber, {} }; + if (!licenseFile.empty() && !singleLicense) { + this->EncodeMenu(menu, DefaultMenu); + } else { + std::vector<std::string> lines; + std::string actual_menu = + slaDirectory + "/" + licenseLanguage + ".menu.txt"; + if (!this->ReadFile(actual_menu, lines, error)) { + return false; } - menu_ifs.close(); + this->EncodeMenu(menu, lines); } + rez.Menu.Entries.emplace_back(std::move(menu)); + } + + return true; +} + +void cmCPackDragNDropGenerator::EncodeLicense( + RezDict& dict, std::vector<std::string> const& lines) +{ + // License text uses CR newlines. + for (std::string const& l : lines) { + dict.Data.insert(dict.Data.end(), l.begin(), l.end()); + dict.Data.push_back('\r'); + } + dict.Data.push_back('\r'); +} - // End of menu - outputStream << " }\n"; - outputStream << "};\n"; - outputStream << "\n"; +void cmCPackDragNDropGenerator::EncodeMenu( + RezDict& dict, std::vector<std::string> const& lines) +{ + // Menu resources start with a big-endian uint16_t for number of lines: + { + uint16_t numLines = static_cast<uint16_t>(lines.size()); + char* d = reinterpret_cast<char*>(&numLines); +#if KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE + dict.Data.push_back(d[1]); + dict.Data.push_back(d[0]); +#else + dict.Data.push_back(d[0]); + dict.Data.push_back(d[1]); +#endif } + // Each line starts with a uint8_t length, plus the bytes themselves: + for (std::string const& l : lines) { + dict.Data.push_back(static_cast<unsigned char>(l.length())); + dict.Data.insert(dict.Data.end(), l.begin(), l.end()); + } +} +bool cmCPackDragNDropGenerator::ReadFile(std::string const& file, + std::vector<std::string>& lines, + std::string* error) +{ + cmsys::ifstream ifs(file); + std::string line; + while (std::getline(ifs, line)) { + if (!this->BreakLongLine(line, lines, error)) { + return false; + } + } return true; } @@ -898,7 +899,7 @@ bool cmCPackDragNDropGenerator::BreakLongLine(const std::string& line, std::vector<std::string>& lines, std::string* error) { - const size_t max_line_length = 512; + const size_t max_line_length = 255; size_t line_length = max_line_length; for (size_t i = 0; i < line.size(); i += line_length) { line_length = max_line_length; @@ -913,25 +914,10 @@ bool cmCPackDragNDropGenerator::BreakLongLine(const std::string& line, if (line_length == 0) { *error = "Please make sure there are no words " "(or character sequences not broken up by spaces or newlines) " - "in your license file which are more than 512 characters long."; + "in your license file which are more than 255 characters long."; return false; } lines.push_back(line.substr(i, line_length)); } return true; } - -void cmCPackDragNDropGenerator::EscapeQuotesAndBackslashes(std::string& line) -{ - std::string::size_type backslash_pos = line.find('\\'); - while (backslash_pos != std::string::npos) { - line.replace(backslash_pos, 1, "\\\\"); - backslash_pos = line.find('\\', backslash_pos + 2); - } - - std::string::size_type quote_pos = line.find('\"'); - while (quote_pos != std::string::npos) { - line.replace(quote_pos, 1, "\\\""); - quote_pos = line.find('\"', quote_pos + 2); - } -} diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h index f8c86c0..310b0ab 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.h +++ b/Source/CPack/cmCPackDragNDropGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackDragNDropGenerator_h -#define cmCPackDragNDropGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -14,6 +13,7 @@ #include "cmCPackGenerator.h" class cmGeneratedFileStream; +class cmXMLWriter; /** \class cmCPackDragNDropGenerator * \brief A generator for OSX drag-n-drop installs @@ -45,12 +45,38 @@ private: std::string slaDirectory; bool singleLicense; - bool WriteLicense(cmGeneratedFileStream& outputStream, int licenseNumber, + struct RezDict + { + std::string Name; + size_t ID; + std::vector<unsigned char> Data; + }; + + struct RezArray + { + std::string Key; + std::vector<RezDict> Entries; + }; + + struct RezDoc + { + RezArray LPic = { "LPic", {} }; + RezArray Menu = { "STR#", {} }; + RezArray Text = { "TEXT", {} }; + RezArray RTF = { "RTF ", {} }; + }; + + void WriteRezXML(std::string const& file, RezDoc const& rez); + void WriteRezArray(cmXMLWriter& xml, RezArray const& array); + void WriteRezDict(cmXMLWriter& xml, RezDict const& dict); + + bool WriteLicense(RezDoc& rez, size_t licenseNumber, std::string licenseLanguage, const std::string& licenseFile, std::string* error); + void EncodeLicense(RezDict& dict, std::vector<std::string> const& lines); + void EncodeMenu(RezDict& dict, std::vector<std::string> const& lines); + bool ReadFile(std::string const& file, std::vector<std::string>& lines, + std::string* error); bool BreakLongLine(const std::string& line, std::vector<std::string>& lines, std::string* error); - void EscapeQuotesAndBackslashes(std::string& line); }; - -#endif diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx index 11e1aec..0bc8456 100644 --- a/Source/CPack/cmCPackExternalGenerator.cxx +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -61,7 +61,7 @@ int cmCPackExternalGenerator::PackageFiles() } const char* packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT"); - if (packageScript && *packageScript) { + if (cmNonempty(packageScript)) { if (!cmSystemTools::FileIsFullPath(packageScript)) { cmCPackLogger( cmCPackLog::LOG_ERROR, @@ -75,6 +75,12 @@ int cmCPackExternalGenerator::PackageFiles() if (cmSystemTools::GetErrorOccuredFlag() || !res) { return 0; } + + const char* builtPackagesStr = + this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES"); + if (builtPackagesStr) { + cmExpandList(builtPackagesStr, this->packageFileNames, false); + } } return 1; @@ -205,7 +211,7 @@ int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON( const char* defaultDirectoryPermissions = this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); - if (defaultDirectoryPermissions && *defaultDirectoryPermissions) { + if (cmNonempty(defaultDirectoryPermissions)) { root["defaultDirectoryPermissions"] = defaultDirectoryPermissions; } if (cmIsInternallyOn(this->Parent->GetOption("CPACK_SET_DESTDIR"))) { diff --git a/Source/CPack/cmCPackExternalGenerator.h b/Source/CPack/cmCPackExternalGenerator.h index 80011fd..dfd13e8 100644 --- a/Source/CPack/cmCPackExternalGenerator.h +++ b/Source/CPack/cmCPackExternalGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackExternalGenerator_h -#define cmCPackExternalGenerator_h +#pragma once #include <memory> #include <string> @@ -86,5 +85,3 @@ private: std::unique_ptr<cmCPackExternalVersionGenerator> Generator; }; - -#endif diff --git a/Source/CPack/cmCPackFreeBSDGenerator.h b/Source/CPack/cmCPackFreeBSDGenerator.h index a18b72f..eed8053 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.h +++ b/Source/CPack/cmCPackFreeBSDGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackFreeBSDGenerator_h -#define cmCPackFreeBSDGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -33,5 +32,3 @@ protected: std::string var_lookup(const char* var_name); void write_manifest_fields(cmGeneratedFileStream&); }; - -#endif diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 288dc58..a9fe91c 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -20,6 +20,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" @@ -216,7 +217,7 @@ int cmCPackGenerator::InstallProject() mode_t* default_dir_mode = nullptr; const char* default_dir_install_permissions = this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); - if (default_dir_install_permissions && *default_dir_install_permissions) { + if (cmNonempty(default_dir_install_permissions)) { std::vector<std::string> items = cmExpandedList(default_dir_install_permissions); for (const auto& arg : items) { @@ -264,6 +265,23 @@ int cmCPackGenerator::InstallProject() return 0; } + // Run pre-build actions + const char* preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS"); + if (preBuildScripts) { + const auto scripts = cmExpandedList(preBuildScripts, false); + for (const auto& script : scripts) { + cmCPackLogger(cmCPackLog::LOG_OUTPUT, + "Executing pre-build script: " << script << std::endl); + + if (!this->MakefileMap->ReadListFile(script)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "The pre-build script not found: " << script + << std::endl); + return 0; + } + } + } + if (setDestDir) { cmSystemTools::PutEnv("DESTDIR="); } @@ -276,7 +294,7 @@ int cmCPackGenerator::InstallProjectViaInstallCommands( { (void)setDestDir; const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS"); - if (installCommands && *installCommands) { + if (cmNonempty(installCommands)) { std::string tempInstallDirectoryEnv = cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory); cmSystemTools::PutEnv(tempInstallDirectoryEnv); @@ -327,13 +345,14 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( } const char* installDirectories = this->GetOption("CPACK_INSTALLED_DIRECTORIES"); - if (installDirectories && *installDirectories) { + if (cmNonempty(installDirectories)) { std::vector<std::string> installDirectoriesVector = cmExpandedList(installDirectories); if (installDirectoriesVector.size() % 2 != 0) { cmCPackLogger( cmCPackLog::LOG_ERROR, - "CPACK_INSTALLED_DIRECTORIES should contain pairs of <directory> and " + "CPACK_INSTALLED_DIRECTORIES should contain pairs of <directory> " + "and " "<subdirectory>. The <subdirectory> can be '.' to be installed in " "the toplevel directory of installation." << std::endl); @@ -475,10 +494,10 @@ int cmCPackGenerator::InstallProjectViaInstallScript( "- Install script: " << installScript << std::endl); if (setDestDir) { - // For DESTDIR based packaging, use the *project* CMAKE_INSTALL_PREFIX - // underneath the tempInstallDirectory. The value of the project's - // CMAKE_INSTALL_PREFIX is sent in here as the value of the - // CPACK_INSTALL_PREFIX variable. + // For DESTDIR based packaging, use the *project* + // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The + // value of the project's CMAKE_INSTALL_PREFIX is sent in here as the + // value of the CPACK_INSTALL_PREFIX variable. std::string dir; if (this->GetOption("CPACK_INSTALL_PREFIX")) { @@ -523,7 +542,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS"); const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR"); std::string absoluteDestFiles; - if (cmakeProjects && *cmakeProjects) { + if (cmNonempty(cmakeProjects)) { if (!cmakeGenerator) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_INSTALL_CMAKE_PROJECTS is specified, but " @@ -576,7 +595,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( std::string installTypesVar = "CPACK_" + cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES"; const char* installTypes = this->GetOption(installTypesVar); - if (installTypes && *installTypes) { + if (cmNonempty(installTypes)) { std::vector<std::string> installTypesVector = cmExpandedList(installTypes); for (std::string const& installType : installTypesVector) { @@ -589,7 +608,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( std::string componentsVar = "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component); const char* components = this->GetOption(componentsVar); - if (components && *components) { + if (cmNonempty(components)) { cmExpandList(components, componentsVector); for (std::string const& comp : componentsVector) { project.Components.push_back( @@ -753,7 +772,7 @@ int cmCPackGenerator::InstallCMakeProject( const char* default_dir_inst_permissions = this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); - if (default_dir_inst_permissions && *default_dir_inst_permissions) { + if (cmNonempty(default_dir_inst_permissions)) { mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS", default_dir_inst_permissions); } @@ -811,7 +830,7 @@ int cmCPackGenerator::InstallCMakeProject( * - Because it was already used for component install * in order to put things in subdirs... */ - cmSystemTools::PutEnv(std::string("DESTDIR=") + tempInstallDirectory); + cmSystemTools::PutEnv("DESTDIR=" + tempInstallDirectory); cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Creating directory: '" << dir << "'" << std::endl); @@ -887,8 +906,8 @@ int cmCPackGenerator::InstallCMakeProject( // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES // to CPack (may be used by generators like CPack RPM or DEB) // in order to transparently handle ABSOLUTE PATH - if (const char* def = mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) { - mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES", def); + if (cmProp def = mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) { + mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES", *def); } // Now rebuild the list of files after installation @@ -921,11 +940,11 @@ int cmCPackGenerator::InstallCMakeProject( } } - if (auto d = mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) { + if (cmProp d = mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) { if (!absoluteDestFiles.empty()) { absoluteDestFiles += ";"; } - absoluteDestFiles += d; + absoluteDestFiles += *d; cmCPackLogger(cmCPackLog::LOG_DEBUG, "Got some ABSOLUTE DESTINATION FILES: " << absoluteDestFiles << std::endl); @@ -936,12 +955,13 @@ int cmCPackGenerator::InstallCMakeProject( GetComponentInstallDirNameSuffix(component); if (nullptr != this->GetOption(absoluteDestFileComponent)) { std::string absoluteDestFilesListComponent = - cmStrCat(this->GetOption(absoluteDestFileComponent), ';', d); + cmStrCat(this->GetOption(absoluteDestFileComponent), ';', *d); this->SetOption(absoluteDestFileComponent, absoluteDestFilesListComponent.c_str()); } else { - this->SetOption(absoluteDestFileComponent, - mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")); + this->SetOption( + absoluteDestFileComponent, + cmToCStr(mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"))); } } } @@ -964,8 +984,8 @@ bool cmCPackGenerator::ReadListFile(const char* moduleName) void cmCPackGenerator::SetOptionIfNotSet(const std::string& op, const char* value) { - const char* def = this->MakefileMap->GetDefinition(op); - if (def && *def) { + cmProp def = this->MakefileMap->GetDefinition(op); + if (cmNonempty(def)) { return; } this->SetOption(op, value); @@ -1076,6 +1096,25 @@ int cmCPackGenerator::DoPackage() return 0; } } + // Run post-build actions + const char* postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS"); + if (postBuildScripts) { + this->MakefileMap->AddDefinition("CPACK_PACKAGE_FILES", + cmJoin(this->packageFileNames, ";")); + + const auto scripts = cmExpandedList(postBuildScripts, false); + for (const auto& script : scripts) { + cmCPackLogger(cmCPackLog::LOG_OUTPUT, + "Executing post-build script: " << script << std::endl); + + if (!this->MakefileMap->ReadListFile(script)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "The post-build script not found: " << script + << std::endl); + return 0; + } + } + } /* Prepare checksum algorithm*/ const char* algo = this->GetOption("CPACK_PACKAGE_CHECKSUM"); @@ -1177,30 +1216,31 @@ bool cmCPackGenerator::IsOn(const std::string& name) const bool cmCPackGenerator::IsSetToOff(const std::string& op) const { - const char* ret = this->MakefileMap->GetDefinition(op); - if (ret && *ret) { - return cmIsOff(ret); + cmProp ret = this->MakefileMap->GetDefinition(op); + if (cmNonempty(ret)) { + return cmIsOff(*ret); } return false; } bool cmCPackGenerator::IsSetToEmpty(const std::string& op) const { - const char* ret = this->MakefileMap->GetDefinition(op); + cmProp ret = this->MakefileMap->GetDefinition(op); if (ret) { - return !*ret; + return ret->empty(); } return false; } const char* cmCPackGenerator::GetOption(const std::string& op) const { - const char* ret = this->MakefileMap->GetDefinition(op); + cmProp ret = this->MakefileMap->GetDefinition(op); if (!ret) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Warning, GetOption return NULL for: " << op << std::endl); + return nullptr; } - return ret; + return ret->c_str(); } std::vector<std::string> cmCPackGenerator::GetOptions() const @@ -1289,7 +1329,7 @@ bool cmCPackGenerator::ConfigureFile(const std::string& inName, bool copyOnly /* = false */) { return this->MakefileMap->ConfigureFile(inName, outName, copyOnly, true, - false) == 1; + false, true) == 1; } int cmCPackGenerator::CleanTemporaryDirectory() @@ -1378,7 +1418,8 @@ int cmCPackGenerator::PrepareGroupingKind() << std::endl); } - // if user specified packaging method, override the default packaging method + // if user specified packaging method, override the default packaging + // method if (method != UNKNOWN_COMPONENT_PACKAGE_METHOD) { componentPackageMethod = method; } @@ -1471,7 +1512,7 @@ cmCPackInstallationType* cmCPackGenerator::GetInstallationType( installType->Name = name; const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); - if (displayName && *displayName) { + if (cmNonempty(displayName)) { installType->DisplayName = displayName; } else { installType->DisplayName = installType->Name; @@ -1493,7 +1534,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent( "CPACK_COMPONENT_" + cmsys::SystemTools::UpperCase(name); component->Name = name; const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); - if (displayName && *displayName) { + if (cmNonempty(displayName)) { component->DisplayName = displayName; } else { component->DisplayName = component->Name; @@ -1505,17 +1546,17 @@ cmCPackComponent* cmCPackGenerator::GetComponent( cmIsOn(this->GetOption("CPACK_DOWNLOAD_ALL")); const char* archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE"); - if (archiveFile && *archiveFile) { + if (cmNonempty(archiveFile)) { component->ArchiveFile = archiveFile; } const char* plist = this->GetOption(macroPrefix + "_PLIST"); - if (plist && *plist) { + if (cmNonempty(plist)) { component->Plist = plist; } const char* groupName = this->GetOption(macroPrefix + "_GROUP"); - if (groupName && *groupName) { + if (cmNonempty(groupName)) { component->Group = GetComponentGroup(projectName, groupName); component->Group->Components.push_back(component); } else { @@ -1523,13 +1564,13 @@ cmCPackComponent* cmCPackGenerator::GetComponent( } const char* description = this->GetOption(macroPrefix + "_DESCRIPTION"); - if (description && *description) { + if (cmNonempty(description)) { component->Description = description; } // Determine the installation types. const char* installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES"); - if (installTypes && *installTypes) { + if (cmNonempty(installTypes)) { std::vector<std::string> installTypesVector = cmExpandedList(installTypes); for (std::string const& installType : installTypesVector) { @@ -1540,7 +1581,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent( // Determine the component dependencies. const char* depends = this->GetOption(macroPrefix + "_DEPENDS"); - if (depends && *depends) { + if (cmNonempty(depends)) { std::vector<std::string> dependsVector = cmExpandedList(depends); for (std::string const& depend : dependsVector) { cmCPackComponent* child = GetComponent(projectName, depend); @@ -1564,21 +1605,21 @@ cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup( // Define the group group->Name = name; const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); - if (displayName && *displayName) { + if (cmNonempty(displayName)) { group->DisplayName = displayName; } else { group->DisplayName = group->Name; } const char* description = this->GetOption(macroPrefix + "_DESCRIPTION"); - if (description && *description) { + if (cmNonempty(description)) { group->Description = description; } group->IsBold = this->IsOn(macroPrefix + "_BOLD_TITLE"); group->IsExpandedByDefault = this->IsOn(macroPrefix + "_EXPANDED"); const char* parentGroupName = this->GetOption(macroPrefix + "_PARENT_GROUP"); - if (parentGroupName && *parentGroupName) { + if (cmNonempty(parentGroupName)) { group->ParentGroup = GetComponentGroup(projectName, parentGroupName); group->ParentGroup->Subgroups.push_back(group); } else { diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 33026c1..2512d42 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackGenerator_h -#define cmCPackGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -339,5 +338,3 @@ protected: this->Logger->Log(logType, __FILE__, __LINE__, \ cmCPackLog_msg.str().c_str()); \ } while (false) - -#endif diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h index 62b7484..0846573 100644 --- a/Source/CPack/cmCPackGeneratorFactory.h +++ b/Source/CPack/cmCPackGeneratorFactory.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackGeneratorFactory_h -#define cmCPackGeneratorFactory_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -44,5 +43,3 @@ private: DescriptionsMap GeneratorDescriptions; cmCPackLog* Logger; }; - -#endif diff --git a/Source/CPack/cmCPackLog.h b/Source/CPack/cmCPackLog.h index 68ffcce..6cec39c 100644 --- a/Source/CPack/cmCPackLog.h +++ b/Source/CPack/cmCPackLog.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackLog_h -#define cmCPackLog_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -139,5 +138,3 @@ inline std::ostream& operator<<(std::ostream& os, const cmCPackLogWrite& c) os.flush(); return os; } - -#endif diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 058b090..2109b4e 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -696,7 +696,7 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( const char* userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY"); std::string uploadDirectory; - if (userUploadDirectory && *userUploadDirectory) { + if (cmNonempty(userUploadDirectory)) { uploadDirectory = userUploadDirectory; } else { uploadDirectory = diff --git a/Source/CPack/cmCPackNSISGenerator.h b/Source/CPack/cmCPackNSISGenerator.h index 88cba45..ded02de 100644 --- a/Source/CPack/cmCPackNSISGenerator.h +++ b/Source/CPack/cmCPackNSISGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackNSISGenerator_h -#define cmCPackNSISGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -85,5 +84,3 @@ protected: bool Nsis64; }; - -#endif diff --git a/Source/CPack/cmCPackNuGetGenerator.h b/Source/CPack/cmCPackNuGetGenerator.h index a59db2d..609ec79 100644 --- a/Source/CPack/cmCPackNuGetGenerator.h +++ b/Source/CPack/cmCPackNuGetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackNuGetGenerator_h -#define cmCPackNuGetGenerator_h +#pragma once #include "cmCPackGenerator.h" @@ -33,5 +32,3 @@ protected: */ void AddGeneratedPackageNames(); }; - -#endif diff --git a/Source/CPack/cmCPackOSXX11Generator.h b/Source/CPack/cmCPackOSXX11Generator.h index a6461c8..8fae136 100644 --- a/Source/CPack/cmCPackOSXX11Generator.h +++ b/Source/CPack/cmCPackOSXX11Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackOSXX11Generator_h -#define cmCPackOSXX11Generator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -38,5 +37,3 @@ protected: bool copyOnly = false); std::string InstallPrefix; }; - -#endif diff --git a/Source/CPack/cmCPackPKGGenerator.h b/Source/CPack/cmCPackPKGGenerator.h index be730ab..17cdcdf 100644 --- a/Source/CPack/cmCPackPKGGenerator.h +++ b/Source/CPack/cmCPackPKGGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackPKGGenerator_h -#define cmCPackPKGGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -94,5 +93,3 @@ protected: // The PostFlight component when creating a metapackage cmCPackComponent PostFlightComponent; }; - -#endif diff --git a/Source/CPack/cmCPackPackageMakerGenerator.h b/Source/CPack/cmCPackPackageMakerGenerator.h index 0575587..cda9277 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.h +++ b/Source/CPack/cmCPackPackageMakerGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackPackageMakerGenerator_h -#define cmCPackPackageMakerGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -49,5 +48,3 @@ protected: double PackageMakerVersion; unsigned int PackageCompatibilityVersion; }; - -#endif diff --git a/Source/CPack/cmCPackProductBuildGenerator.h b/Source/CPack/cmCPackProductBuildGenerator.h index 015fe4a..462e2fc 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.h +++ b/Source/CPack/cmCPackProductBuildGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackProductBuildGenerator_h -#define cmCPackProductBuildGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -49,5 +48,3 @@ protected: const char* GetComponentScript(const char* script, const char* script_component); }; - -#endif diff --git a/Source/CPack/cmCPackRPMGenerator.h b/Source/CPack/cmCPackRPMGenerator.h index 075ce84..0288f2f 100644 --- a/Source/CPack/cmCPackRPMGenerator.h +++ b/Source/CPack/cmCPackRPMGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackRPMGenerator_h -#define cmCPackRPMGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -68,5 +67,3 @@ protected: void AddGeneratedPackageNames(); }; - -#endif diff --git a/Source/CPack/cmCPackSTGZGenerator.h b/Source/CPack/cmCPackSTGZGenerator.h index 79d7035..d2df1f2 100644 --- a/Source/CPack/cmCPackSTGZGenerator.h +++ b/Source/CPack/cmCPackSTGZGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackSTGZGenerator_h -#define cmCPackSTGZGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -30,5 +29,3 @@ protected: int InitializeInternal() override; int GenerateHeader(std::ostream* os) override; }; - -#endif diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 3a400b7..6c80753 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -12,6 +12,7 @@ #include "cmDocumentationFormatter.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" @@ -324,21 +325,22 @@ int main(int argc, char const* const* argv) } // Force CPACK_PACKAGE_DIRECTORY as absolute path - cpackProjectDirectory = globalMF.GetDefinition("CPACK_PACKAGE_DIRECTORY"); + cpackProjectDirectory = + globalMF.GetSafeDefinition("CPACK_PACKAGE_DIRECTORY"); cpackProjectDirectory = cmSystemTools::CollapseFullPath(cpackProjectDirectory); globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory); - const char* cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH"); + cmProp cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH"); if (cpackModulesPath) { - globalMF.AddDefinition("CMAKE_MODULE_PATH", cpackModulesPath); + globalMF.AddDefinition("CMAKE_MODULE_PATH", *cpackModulesPath); } - const char* genList = globalMF.GetDefinition("CPACK_GENERATOR"); + cmProp genList = globalMF.GetDefinition("CPACK_GENERATOR"); if (!genList) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "CPack generator not specified" << std::endl); } else { - std::vector<std::string> generatorsVector = cmExpandedList(genList); + std::vector<std::string> generatorsVector = cmExpandedList(*genList); for (std::string const& gen : generatorsVector) { cmMakefile::ScopePushPop raii(&globalMF); cmMakefile* mf = &globalMF; @@ -411,32 +413,31 @@ int main(int argc, char const* const* argv) parsed = 0; } if (parsed) { - const char* projName = mf->GetDefinition("CPACK_PACKAGE_NAME"); + cmProp projName = mf->GetDefinition("CPACK_PACKAGE_NAME"); cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Use generator: " << cpackGenerator->GetNameOfClass() << std::endl); cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, - "For project: " << projName << std::endl); + "For project: " << *projName << std::endl); - const char* projVersion = - mf->GetDefinition("CPACK_PACKAGE_VERSION"); + cmProp projVersion = mf->GetDefinition("CPACK_PACKAGE_VERSION"); if (!projVersion) { - const char* projVersionMajor = + cmProp projVersionMajor = mf->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR"); - const char* projVersionMinor = + cmProp projVersionMinor = mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR"); - const char* projVersionPatch = + cmProp projVersionPatch = mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH"); std::ostringstream ostr; - ostr << projVersionMajor << "." << projVersionMinor << "." - << projVersionPatch; + ostr << *projVersionMajor << "." << *projVersionMinor << "." + << *projVersionPatch; mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str()); } int res = cpackGenerator->DoPackage(); if (!res) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "Error when generating package: " << projName + "Error when generating package: " << *projName << std::endl); return 1; } diff --git a/Source/CTest/cmCTestBZR.h b/Source/CTest/cmCTestBZR.h index d7c6321..eb0dbbe 100644 --- a/Source/CTest/cmCTestBZR.h +++ b/Source/CTest/cmCTestBZR.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestBZR_h -#define cmCTestBZR_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -50,5 +49,3 @@ private: friend class UpdateParser; friend class StatusParser; }; - -#endif diff --git a/Source/CTest/cmCTestBinPacker.h b/Source/CTest/cmCTestBinPacker.h index ff02b85..e56a437 100644 --- a/Source/CTest/cmCTestBinPacker.h +++ b/Source/CTest/cmCTestBinPacker.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestBinPacker_h -#define cmCTestBinPacker_h +#pragma once #include <cstddef> #include <map> @@ -27,5 +26,3 @@ bool cmAllocateCTestResourcesRoundRobin( bool cmAllocateCTestResourcesBlock( const std::map<std::string, cmCTestResourceAllocator::Resource>& resources, std::vector<cmCTestBinPackerAllocation>& allocations); - -#endif diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index db426b2..a18cbb4 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -182,10 +182,9 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) std::vector<std::string> extraPaths; std::vector<std::string> failed; fullPath = cmCTestTestHandler::FindExecutable( - this->CTest, this->ConfigSample.c_str(), resultingConfig, extraPaths, - failed); + this->CTest, this->ConfigSample, resultingConfig, extraPaths, failed); if (!fullPath.empty() && !resultingConfig.empty()) { - this->CTest->SetConfigType(resultingConfig.c_str()); + this->CTest->SetConfigType(resultingConfig); } out << "Using config sample with results: " << fullPath << " and " << resultingConfig << std::endl; @@ -296,9 +295,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) extraPaths.push_back(tempPath); } std::vector<std::string> failed; - fullPath = - cmCTestTestHandler::FindExecutable(this->CTest, this->TestCommand.c_str(), - resultingConfig, extraPaths, failed); + fullPath = cmCTestTestHandler::FindExecutable( + this->CTest, this->TestCommand, resultingConfig, extraPaths, failed); if (!cmSystemTools::FileExists(fullPath)) { out << "Could not find path to executable, perhaps it was not built: " diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h index 0c8a040..b9cc35c 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.h +++ b/Source/CTest/cmCTestBuildAndTestHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestBuildAndTestHandler_h -#define cmCTestBuildAndTestHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -71,5 +70,3 @@ protected: bool BuildNoCMake; cmDuration Timeout; }; - -#endif diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 44fdc29..1cc267e 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestBuildCommand.h" -#include <cstring> #include <sstream> #include <cmext/string_view> @@ -12,6 +11,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -38,13 +38,13 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() this->Handler = handler; - const char* ctestBuildCommand = + cmProp ctestBuildCommand = this->Makefile->GetDefinition("CTEST_BUILD_COMMAND"); - if (ctestBuildCommand && *ctestBuildCommand) { - this->CTest->SetCTestConfiguration("MakeCommand", ctestBuildCommand, + if (cmNonempty(ctestBuildCommand)) { + this->CTest->SetCTestConfiguration("MakeCommand", *ctestBuildCommand, this->Quiet); } else { - const char* cmakeGeneratorName = + cmProp cmakeGeneratorName = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR"); // Build configuration is determined by: CONFIGURATION argument, @@ -52,49 +52,51 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() // CTEST_CONFIGURATION_TYPE script variable, or ctest -C command // line argument... in that order. // - const char* ctestBuildConfiguration = + cmProp ctestBuildConfiguration = this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION"); - const char* cmakeBuildConfiguration = !this->Configuration.empty() - ? this->Configuration.c_str() - : ((ctestBuildConfiguration && *ctestBuildConfiguration) - ? ctestBuildConfiguration - : this->CTest->GetConfigType().c_str()); - - const char* cmakeBuildAdditionalFlags = !this->Flags.empty() - ? this->Flags.c_str() + const std::string* cmakeBuildConfiguration = !this->Configuration.empty() + ? &this->Configuration + : (cmNonempty(ctestBuildConfiguration) ? ctestBuildConfiguration + : &this->CTest->GetConfigType()); + + const std::string* cmakeBuildAdditionalFlags = !this->Flags.empty() + ? &this->Flags : this->Makefile->GetDefinition("CTEST_BUILD_FLAGS"); - const char* cmakeBuildTarget = !this->Target.empty() - ? this->Target.c_str() + const std::string* cmakeBuildTarget = !this->Target.empty() + ? &this->Target : this->Makefile->GetDefinition("CTEST_BUILD_TARGET"); - if (cmakeGeneratorName && *cmakeGeneratorName) { + if (cmNonempty(cmakeGeneratorName)) { if (!cmakeBuildConfiguration) { - cmakeBuildConfiguration = "Release"; + static const std::string sRelease = "Release"; + cmakeBuildConfiguration = &sRelease; } if (this->GlobalGenerator) { - if (this->GlobalGenerator->GetName() != cmakeGeneratorName) { + if (this->GlobalGenerator->GetName() != *cmakeGeneratorName) { this->GlobalGenerator.reset(); } } if (!this->GlobalGenerator) { this->GlobalGenerator = this->Makefile->GetCMakeInstance()->CreateGlobalGenerator( - cmakeGeneratorName); + *cmakeGeneratorName); if (!this->GlobalGenerator) { std::string e = cmStrCat("could not create generator named \"", - cmakeGeneratorName, '"'); + *cmakeGeneratorName, '"'); this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); cmSystemTools::SetFatalErrorOccured(); return nullptr; } } - if (strlen(cmakeBuildConfiguration) == 0) { - const char* config = nullptr; + if (cmakeBuildConfiguration->empty()) { + const std::string* config = nullptr; #ifdef CMAKE_INTDIR - config = CMAKE_INTDIR; + static const std::string sIntDir = CMAKE_INTDIR; + config = &sIntDir; #endif if (!config) { - config = "Debug"; + static const std::string sDebug = "Debug"; + config = &sDebug; } cmakeBuildConfiguration = config; } @@ -102,13 +104,13 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() std::string dir = this->CTest->GetCTestConfiguration("BuildDirectory"); std::string buildCommand = this->GlobalGenerator->GenerateCMakeBuildCommand( - cmakeBuildTarget ? cmakeBuildTarget : "", cmakeBuildConfiguration, - cmakeBuildAdditionalFlags ? cmakeBuildAdditionalFlags : "", + cmakeBuildTarget ? *cmakeBuildTarget : "", *cmakeBuildConfiguration, + cmakeBuildAdditionalFlags ? *cmakeBuildAdditionalFlags : "", this->Makefile->IgnoreErrorsCMP0061()); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "SetMakeCommand:" << buildCommand << "\n", this->Quiet); - this->CTest->SetCTestConfiguration("MakeCommand", buildCommand.c_str(), + this->CTest->SetCTestConfiguration("MakeCommand", buildCommand, this->Quiet); } else { std::ostringstream ostr; @@ -123,16 +125,16 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() } } - if (const char* useLaunchers = + if (cmProp useLaunchers = this->Makefile->GetDefinition("CTEST_USE_LAUNCHERS")) { - this->CTest->SetCTestConfiguration("UseLaunchers", useLaunchers, + this->CTest->SetCTestConfiguration("UseLaunchers", *useLaunchers, this->Quiet); } - if (const char* labelsForSubprojects = + if (cmProp labelsForSubprojects = this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) { this->CTest->SetCTestConfiguration("LabelsForSubprojects", - labelsForSubprojects, this->Quiet); + *labelsForSubprojects, this->Quiet); } handler->SetQuiet(this->Quiet); diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h index 0f82817..00dbcc4 100644 --- a/Source/CTest/cmCTestBuildCommand.h +++ b/Source/CTest/cmCTestBuildCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestBuildCommand_h -#define cmCTestBuildCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -62,5 +61,3 @@ protected: std::string Flags; std::string ProjectName; }; - -#endif diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 35c2b11..9997548 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -19,6 +19,7 @@ #include "cmGeneratedFileStream.h" #include "cmMakefile.h" #include "cmProcessOutput.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmStringReplaceHelper.h" #include "cmSystemTools.h" @@ -248,13 +249,14 @@ void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile* mf) } // Record the user-specified custom warning rules. - if (const char* customWarningMatchers = + if (cmProp customWarningMatchers = mf->GetDefinition("CTEST_CUSTOM_WARNING_MATCH")) { - cmExpandList(customWarningMatchers, this->ReallyCustomWarningMatches); + cmExpandList(*customWarningMatchers, this->ReallyCustomWarningMatches); } - if (const char* customWarningExceptions = + if (cmProp customWarningExceptions = mf->GetDefinition("CTEST_CUSTOM_WARNING_EXCEPTION")) { - cmExpandList(customWarningExceptions, this->ReallyCustomWarningExceptions); + cmExpandList(*customWarningExceptions, + this->ReallyCustomWarningExceptions); } } diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h index a5193f6..58e8d9c 100644 --- a/Source/CTest/cmCTestBuildHandler.h +++ b/Source/CTest/cmCTestBuildHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestBuildHandler_h -#define cmCTestBuildHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -156,5 +155,3 @@ private: friend class LaunchHelper; class FragmentCompare; }; - -#endif diff --git a/Source/CTest/cmCTestCVS.h b/Source/CTest/cmCTestCVS.h index 7d33d8f..d20239b 100644 --- a/Source/CTest/cmCTestCVS.h +++ b/Source/CTest/cmCTestCVS.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestCVS_h -#define cmCTestCVS_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -51,5 +50,3 @@ private: friend class LogParser; friend class UpdateParser; }; - -#endif diff --git a/Source/CTest/cmCTestCommand.h b/Source/CTest/cmCTestCommand.h index 8efb419..007378d 100644 --- a/Source/CTest/cmCTestCommand.h +++ b/Source/CTest/cmCTestCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestCommand_h -#define cmCTestCommand_h +#pragma once #include "cmCommand.h" @@ -27,5 +26,3 @@ public: cmCTest* CTest; cmCTestScriptHandler* CTestScriptHandler; }; - -#endif diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index f42c3f1..db9923e 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -12,6 +12,7 @@ #include "cmCTestConfigureHandler.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -38,16 +39,16 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() return nullptr; } - const char* ctestConfigureCommand = + cmProp ctestConfigureCommand = this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND"); - if (ctestConfigureCommand && *ctestConfigureCommand) { + if (cmNonempty(ctestConfigureCommand)) { this->CTest->SetCTestConfiguration("ConfigureCommand", - ctestConfigureCommand, this->Quiet); + *ctestConfigureCommand, this->Quiet); } else { - const char* cmakeGeneratorName = + cmProp cmakeGeneratorName = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR"); - if (cmakeGeneratorName && *cmakeGeneratorName) { + if (cmNonempty(cmakeGeneratorName)) { const std::string& source_dir = this->CTest->GetCTestConfiguration("SourceDirectory"); if (source_dir.empty()) { @@ -70,7 +71,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() bool cmakeBuildTypeInOptions = false; auto gg = this->Makefile->GetCMakeInstance()->CreateGlobalGenerator( - cmakeGeneratorName); + *cmakeGeneratorName); if (gg) { multiConfig = gg->IsMultiConfig(); gg.reset(); @@ -102,22 +103,22 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() } cmakeConfigureCommand += " \"-G"; - cmakeConfigureCommand += cmakeGeneratorName; + cmakeConfigureCommand += *cmakeGeneratorName; cmakeConfigureCommand += "\""; - const char* cmakeGeneratorPlatform = + cmProp cmakeGeneratorPlatform = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_PLATFORM"); - if (cmakeGeneratorPlatform && *cmakeGeneratorPlatform) { + if (cmNonempty(cmakeGeneratorPlatform)) { cmakeConfigureCommand += " \"-A"; - cmakeConfigureCommand += cmakeGeneratorPlatform; + cmakeConfigureCommand += *cmakeGeneratorPlatform; cmakeConfigureCommand += "\""; } - const char* cmakeGeneratorToolset = + cmProp cmakeGeneratorToolset = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_TOOLSET"); - if (cmakeGeneratorToolset && *cmakeGeneratorToolset) { + if (cmNonempty(cmakeGeneratorToolset)) { cmakeConfigureCommand += " \"-T"; - cmakeConfigureCommand += cmakeGeneratorToolset; + cmakeConfigureCommand += *cmakeGeneratorToolset; cmakeConfigureCommand += "\""; } @@ -125,8 +126,8 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() cmakeConfigureCommand += source_dir; cmakeConfigureCommand += "\""; - this->CTest->SetCTestConfiguration( - "ConfigureCommand", cmakeConfigureCommand.c_str(), this->Quiet); + this->CTest->SetCTestConfiguration("ConfigureCommand", + cmakeConfigureCommand, this->Quiet); } else { this->SetError( "Configure command is not specified. If this is a " @@ -136,10 +137,10 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() } } - if (const char* labelsForSubprojects = + if (cmProp labelsForSubprojects = this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) { this->CTest->SetCTestConfiguration("LabelsForSubprojects", - labelsForSubprojects, this->Quiet); + *labelsForSubprojects, this->Quiet); } cmCTestConfigureHandler* handler = this->CTest->GetConfigureHandler(); diff --git a/Source/CTest/cmCTestConfigureCommand.h b/Source/CTest/cmCTestConfigureCommand.h index 3f5944a..f338637 100644 --- a/Source/CTest/cmCTestConfigureCommand.h +++ b/Source/CTest/cmCTestConfigureCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestConfigureCommand_h -#define cmCTestConfigureCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -45,5 +44,3 @@ protected: std::string Options; }; - -#endif diff --git a/Source/CTest/cmCTestConfigureHandler.h b/Source/CTest/cmCTestConfigureHandler.h index 01fe801..2aad98c 100644 --- a/Source/CTest/cmCTestConfigureHandler.h +++ b/Source/CTest/cmCTestConfigureHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestConfigureHandler_h -#define cmCTestConfigureHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -25,5 +24,3 @@ public: void Initialize() override; }; - -#endif diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h index 76aaf46..9344852 100644 --- a/Source/CTest/cmCTestCoverageCommand.h +++ b/Source/CTest/cmCTestCoverageCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestCoverageCommand_h -#define cmCTestCoverageCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -48,5 +47,3 @@ protected: bool LabelsMentioned; std::vector<std::string> Labels; }; - -#endif diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index b839c10..093b2d1 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -469,8 +469,8 @@ int cmCTestCoverageHandler::ProcessHandler() } const std::string fileName = cmSystemTools::GetFilenameName(fullFileName); - std::string shortFileName = - this->CTest->GetShortPathToFile(fullFileName.c_str()); + const std::string shortFileName = + this->CTest->GetShortPathToFile(fullFileName); const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov = file.second; covLogXML.StartElement("File"); @@ -538,7 +538,7 @@ int cmCTestCoverageHandler::ProcessHandler() covSumXML.StartElement("File"); covSumXML.Attribute("Name", fileName); covSumXML.Attribute("FullPath", - this->CTest->GetShortPathToFile(fullFileName.c_str())); + this->CTest->GetShortPathToFile(fullFileName)); covSumXML.Attribute("Covered", tested + untested > 0 ? "true" : "false"); covSumXML.Element("LOCTested", tested); covSumXML.Element("LOCUnTested", untested); @@ -1887,8 +1887,8 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch( // start the file output covLogXML.StartElement("File"); covLogXML.Attribute("Name", i->first); - covLogXML.Attribute( - "FullPath", this->CTest->GetShortPathToFile(i->second.c_str())); + covLogXML.Attribute("FullPath", + this->CTest->GetShortPathToFile(i->second)); covLogXML.StartElement("Report"); // write the bullseye header line = 0; @@ -2064,8 +2064,7 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary( total_untested += (totalFunctions - functionsCalled); std::string fileName = cmSystemTools::GetFilenameName(file); - std::string shortFileName = - this->CTest->GetShortPathToFile(file.c_str()); + std::string shortFileName = this->CTest->GetShortPathToFile(file); float cper = static_cast<float>(percentBranch + percentFunction); if (totalBranches > 0) { @@ -2266,7 +2265,7 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir) // is the end of the target-wide labels. inTarget = false; - source = this->CTest->GetShortPathToFile(line.c_str()); + source = this->CTest->GetShortPathToFile(line); // Label the source with the target labels. LabelSet& labelSet = this->SourceLabels[source]; @@ -2320,7 +2319,7 @@ bool cmCTestCoverageHandler::IsFilteredOut(std::string const& source) // The source is filtered out if it does not have any labels in // common with the filter set. - std::string shortSrc = this->CTest->GetShortPathToFile(source.c_str()); + std::string shortSrc = this->CTest->GetShortPathToFile(source); auto li = this->SourceLabels.find(shortSrc); if (li != this->SourceLabels.end()) { return !this->IntersectsFilter(li->second); @@ -2342,14 +2341,14 @@ std::set<std::string> cmCTestCoverageHandler::FindUncoveredFiles( std::vector<std::string> files = gl.GetFiles(); for (std::string const& f : files) { if (this->ShouldIDoCoverage(f, cont->SourceDir, cont->BinaryDir)) { - extraMatches.insert(this->CTest->GetShortPathToFile(f.c_str())); + extraMatches.insert(this->CTest->GetShortPathToFile(f)); } } } if (!extraMatches.empty()) { for (auto const& i : cont->TotalCoverage) { - std::string shortPath = this->CTest->GetShortPathToFile(i.first.c_str()); + std::string shortPath = this->CTest->GetShortPathToFile(i.first); extraMatches.erase(shortPath); } } diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h index 991b89d..8732723 100644 --- a/Source/CTest/cmCTestCoverageHandler.h +++ b/Source/CTest/cmCTestCoverageHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestCoverageHandler_h -#define cmCTestCoverageHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -149,5 +148,3 @@ private: bool IntersectsFilter(LabelSet const& labels); bool IsFilteredOut(std::string const& source); }; - -#endif diff --git a/Source/CTest/cmCTestCurl.h b/Source/CTest/cmCTestCurl.h index b0d7f07..d9aa916 100644 --- a/Source/CTest/cmCTestCurl.h +++ b/Source/CTest/cmCTestCurl.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestCurl_h -#define cmCTestCurl_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -52,5 +51,3 @@ private: bool Quiet; int TimeOutSeconds; }; - -#endif diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h index ac96a4e..ba2b0eb 100644 --- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h +++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestEmptyBinaryDirectoryCommand_h -#define cmCTestEmptyBinaryDirectoryCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -45,5 +44,3 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; }; - -#endif diff --git a/Source/CTest/cmCTestGIT.h b/Source/CTest/cmCTestGIT.h index 3103d84..a15aef5 100644 --- a/Source/CTest/cmCTestGIT.h +++ b/Source/CTest/cmCTestGIT.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestGIT_h -#define cmCTestGIT_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -53,5 +52,3 @@ public: friend class DiffParser; friend class OneLineParser; }; - -#endif diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index cc0b4ed..a71f550 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -100,7 +100,7 @@ bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part, << std::endl); return false; } - this->CTest->AddSubmitFile(part, ostr.str().c_str()); + this->CTest->AddSubmitFile(part, ostr.str()); return true; } diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 94e5418..591d9cd 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestGenericHandler_h -#define cmCTestGenericHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -105,5 +104,3 @@ protected: cmCTestCommand* Command; int SubmitIndex; }; - -#endif diff --git a/Source/CTest/cmCTestGlobalVC.h b/Source/CTest/cmCTestGlobalVC.h index ff86591..679b0e1 100644 --- a/Source/CTest/cmCTestGlobalVC.h +++ b/Source/CTest/cmCTestGlobalVC.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestGlobalVC_h -#define cmCTestGlobalVC_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -73,5 +72,3 @@ protected: void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path, Directory const& dir); }; - -#endif diff --git a/Source/CTest/cmCTestHG.h b/Source/CTest/cmCTestHG.h index 2900139..b81f042 100644 --- a/Source/CTest/cmCTestHG.h +++ b/Source/CTest/cmCTestHG.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestHG_h -#define cmCTestHG_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -42,5 +41,3 @@ private: friend class LogParser; friend class StatusParser; }; - -#endif diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index a755632..731932e 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -14,6 +14,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" @@ -125,23 +126,22 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, // CTEST_CONFIGURATION_TYPE script variable if it is defined. // The current script value trumps the -C argument on the command // line. - const char* ctestConfigType = + cmProp ctestConfigType = this->Makefile->GetDefinition("CTEST_CONFIGURATION_TYPE"); if (ctestConfigType) { - this->CTest->SetConfigType(ctestConfigType); + this->CTest->SetConfigType(*ctestConfigType); } if (!this->Build.empty()) { this->CTest->SetCTestConfiguration( - "BuildDirectory", cmSystemTools::CollapseFullPath(this->Build).c_str(), + "BuildDirectory", cmSystemTools::CollapseFullPath(this->Build), this->Quiet); } else { std::string const& bdir = this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY"); if (!bdir.empty()) { this->CTest->SetCTestConfiguration( - "BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(), - this->Quiet); + "BuildDirectory", cmSystemTools::CollapseFullPath(bdir), this->Quiet); } else { cmCTestLog(this->CTest, ERROR_MESSAGE, "CTEST_BINARY_DIRECTORY not set" << std::endl;); @@ -151,20 +151,18 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, cmCTestLog(this->CTest, DEBUG, "Set source directory to: " << this->Source << std::endl); this->CTest->SetCTestConfiguration( - "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(), + "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source), this->Quiet); } else { this->CTest->SetCTestConfiguration( "SourceDirectory", cmSystemTools::CollapseFullPath( - this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY")) - .c_str(), + this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY")), this->Quiet); } - if (const char* changeId = - this->Makefile->GetDefinition("CTEST_CHANGE_ID")) { - this->CTest->SetCTestConfiguration("ChangeId", changeId, this->Quiet); + if (cmProp changeId = this->Makefile->GetDefinition("CTEST_CHANGE_ID")) { + this->CTest->SetCTestConfiguration("ChangeId", *changeId, this->Quiet); } cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;); diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h index a20d607..756952d 100644 --- a/Source/CTest/cmCTestHandlerCommand.h +++ b/Source/CTest/cmCTestHandlerCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestHandlerCommand_h -#define cmCTestHandlerCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -58,5 +57,3 @@ protected: "The APPEND option marks results for append to those previously " \ "submitted to a dashboard server since the last ctest_start. " \ "Append semantics are defined by the dashboard server in use." - -#endif diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h index 79a7712..33ff82c 100644 --- a/Source/CTest/cmCTestLaunch.h +++ b/Source/CTest/cmCTestLaunch.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestLaunch_h -#define cmCTestLaunch_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -103,5 +102,3 @@ private: void LoadConfig(); std::string SourceDir; }; - -#endif diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h index 8f4ffb8..6544f16 100644 --- a/Source/CTest/cmCTestMemCheckCommand.h +++ b/Source/CTest/cmCTestMemCheckCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestMemCheckCommand_h -#define cmCTestMemCheckCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -43,5 +42,3 @@ protected: std::string DefectCount; }; - -#endif diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 85b8ab1..8b31e4b 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -326,6 +326,9 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) case cmCTestMemCheckHandler::BOUNDS_CHECKER: xml.Attribute("Checker", "BoundsChecker"); break; + case cmCTestMemCheckHandler::CUDA_MEMCHECK: + xml.Attribute("Checker", "CudaMemcheck"); + break; case cmCTestMemCheckHandler::ADDRESS_SANITIZER: xml.Attribute("Checker", "AddressSanitizer"); break; @@ -351,7 +354,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) cmCTestMemCheckHandler::TestResultsVector::size_type cc; for (cmCTestTestResult const& result : this->TestResults) { std::string testPath = result.Path + "/" + result.Name; - xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str())); + xml.Element("Test", this->CTest->GetShortPathToFile(testPath)); } xml.EndElement(); // TestList cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, @@ -465,6 +468,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY; } else if (testerName.find("BC") != std::string::npos) { this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; + } else if (testerName.find("cuda-memcheck") != std::string::npos) { + this->MemoryTesterStyle = cmCTestMemCheckHandler::CUDA_MEMCHECK; } else { this->MemoryTesterStyle = cmCTestMemCheckHandler::UNKNOWN; } @@ -485,6 +490,11 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTester = this->CTest->GetCTestConfiguration("BoundsCheckerCommand"); this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; + } else if (cmSystemTools::FileExists( + this->CTest->GetCTestConfiguration("CudaMemcheckCommand"))) { + this->MemoryTester = + this->CTest->GetCTestConfiguration("CudaMemcheckCommand"); + this->MemoryTesterStyle = cmCTestMemCheckHandler::CUDA_MEMCHECK; } if (this->CTest->GetCTestConfiguration("MemoryCheckType") == "AddressSanitizer") { @@ -528,6 +538,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; } else if (checkType == "DrMemory") { this->MemoryTesterStyle = cmCTestMemCheckHandler::DRMEMORY; + } else if (checkType == "CudaMemcheck") { + this->MemoryTesterStyle = cmCTestMemCheckHandler::CUDA_MEMCHECK; } } if (this->MemoryTester.empty()) { @@ -553,6 +565,10 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() .empty()) { memoryTesterOptions = this->CTest->GetCTestConfiguration("DrMemoryCommandOptions"); + } else if (!this->CTest->GetCTestConfiguration("CudaMemcheckCommandOptions") + .empty()) { + memoryTesterOptions = + this->CTest->GetCTestConfiguration("CudaMemcheckCommandOptions"); } this->MemoryTesterOptions = cmSystemTools::ParseArguments(memoryTesterOptions); @@ -686,6 +702,18 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterOptions.emplace_back("/M"); break; } + case cmCTestMemCheckHandler::CUDA_MEMCHECK: { + // cuda-memcheck separates flags from arguments by spaces + if (this->MemoryTesterOptions.empty()) { + this->MemoryTesterOptions.emplace_back("--tool"); + this->MemoryTesterOptions.emplace_back("memcheck"); + this->MemoryTesterOptions.emplace_back("--leak-check"); + this->MemoryTesterOptions.emplace_back("full"); + } + this->MemoryTesterDynamicOptions.emplace_back("--log-file"); + this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile); + break; + } // these are almost the same but the env var used is different case cmCTestMemCheckHandler::ADDRESS_SANITIZER: case cmCTestMemCheckHandler::LEAK_SANITIZER: @@ -771,6 +799,8 @@ bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str, return this->ProcessMemCheckSanitizerOutput(str, log, results); case cmCTestMemCheckHandler::BOUNDS_CHECKER: return this->ProcessMemCheckBoundsCheckerOutput(str, log, results); + case cmCTestMemCheckHandler::CUDA_MEMCHECK: + return this->ProcessMemCheckCudaOutput(str, log, results); default: log.append("\nMemory checking style used was: "); log.append("None that I know"); @@ -1103,6 +1133,119 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( return defects == 0; } +bool cmCTestMemCheckHandler::ProcessMemCheckCudaOutput( + const std::string& str, std::string& log, std::vector<int>& results) +{ + std::vector<std::string> lines; + cmsys::SystemTools::Split(str, lines); + bool unlimitedOutput = false; + if (str.find("CTEST_FULL_OUTPUT") != std::string::npos || + this->CustomMaximumFailedTestOutputSize == 0) { + unlimitedOutput = true; + } + + std::string::size_type cc; + + std::ostringstream ostr; + log.clear(); + + int defects = 0; + + cmsys::RegularExpression memcheckLine("^========"); + + cmsys::RegularExpression leakExpr("== Leaked [0-9,]+ bytes at"); + + // list of matchers for output messages that contain variable content + // (addresses, sizes, ...) or can be shortened in general. the first match is + // used as a error name. + std::vector<cmsys::RegularExpression> matchers{ + // API errors + "== Malloc/Free error encountered: (.*)", + "== Program hit error ([^ ]*).* on CUDA API call to", + "== Program hit ([^ ]*).* on CUDA API call to", + // memcheck + "== (Invalid .*) of size [0-9,]+", "== (Fatal UVM [CG]PU fault)", + // racecheck + "== .* (Potential .* hazard detected)", "== .* (Race reported)", + // synccheck + "== (Barrier error)", + // initcheck + "== (Uninitialized .* memory read)", "== (Unused memory)", + "== (Host API memory access error)", + // generic error: ignore ERROR SUMMARY, CUDA-MEMCHECK and others + "== ([A-Z][a-z].*)" + }; + + std::vector<std::string::size_type> nonMemcheckOutput; + auto sttime = std::chrono::steady_clock::now(); + cmCTestOptionalLog(this->CTest, DEBUG, + "Start test: " << lines.size() << std::endl, this->Quiet); + std::string::size_type totalOutputSize = 0; + for (cc = 0; cc < lines.size(); cc++) { + cmCTestOptionalLog(this->CTest, DEBUG, + "test line " << lines[cc] << std::endl, this->Quiet); + + if (memcheckLine.find(lines[cc])) { + cmCTestOptionalLog(this->CTest, DEBUG, + "cuda-memcheck line " << lines[cc] << std::endl, + this->Quiet); + int failure = -1; + auto& line = lines[cc]; + if (leakExpr.find(line)) { + failure = static_cast<int>(this->FindOrAddWarning("Memory leak")); + } else { + for (auto& matcher : matchers) { + if (matcher.find(line)) { + failure = + static_cast<int>(this->FindOrAddWarning(matcher.match(1))); + break; + } + } + } + + if (failure >= 0) { + ostr << "<b>" << this->ResultStrings[failure] << "</b> "; + if (results.empty() || unsigned(failure) > results.size() - 1) { + results.push_back(1); + } else { + results[failure]++; + } + defects++; + } + totalOutputSize += lines[cc].size(); + ostr << lines[cc] << std::endl; + } else { + nonMemcheckOutput.push_back(cc); + } + } + // Now put all all the non cuda-memcheck output into the test output + // This should be last in case it gets truncated by the output + // limiting code + for (std::string::size_type i : nonMemcheckOutput) { + totalOutputSize += lines[i].size(); + ostr << lines[i] << std::endl; + if (!unlimitedOutput && + totalOutputSize > + static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)) { + ostr << "....\n"; + ostr << "Test Output for this test has been truncated see testing" + " machine logs for full output,\n"; + ostr << "or put CTEST_FULL_OUTPUT in the output of " + "this test program.\n"; + break; // stop the copy of output if we are full + } + } + cmCTestOptionalLog(this->CTest, DEBUG, + "End test (elapsed: " + << cmDurationTo<unsigned int>( + std::chrono::steady_clock::now() - sttime) + << "s)" << std::endl, + this->Quiet); + log = ostr.str(); + this->DefectCount += defects; + return defects == 0; +} + // PostProcessTest memcheck results void cmCTestMemCheckHandler::PostProcessTest(cmCTestTestResult& res, int test) { diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index 52667f8..6ef5d20 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestMemCheckHandler_h -#define cmCTestMemCheckHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -46,6 +45,7 @@ private: DRMEMORY, BOUNDS_CHECKER, // checkers after here do not use the standard error list + CUDA_MEMCHECK, ADDRESS_SANITIZER, LEAK_SANITIZER, THREAD_SANITIZER, @@ -137,6 +137,8 @@ private: std::vector<int>& results); bool ProcessMemCheckPurifyOutput(const std::string& str, std::string& log, std::vector<int>& results); + bool ProcessMemCheckCudaOutput(const std::string& str, std::string& log, + std::vector<int>& results); bool ProcessMemCheckSanitizerOutput(const std::string& str, std::string& log, std::vector<int>& results); bool ProcessMemCheckBoundsCheckerOutput(const std::string& str, @@ -154,5 +156,3 @@ private: //! generate the output filename for the given test index void TestOutputFileNames(int test, std::vector<std::string>& files); }; - -#endif diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index e21b912..5de42f9 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestMultiProcessHandler_h -#define cmCTestMultiProcessHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -200,5 +199,3 @@ protected: bool Quiet; bool SerialTestRunning; }; - -#endif diff --git a/Source/CTest/cmCTestP4.h b/Source/CTest/cmCTestP4.h index e19472e..d03f9cb 100644 --- a/Source/CTest/cmCTestP4.h +++ b/Source/CTest/cmCTestP4.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestP4_h -#define cmCTestP4_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -72,5 +71,3 @@ private: friend class DescribeParser; friend class DiffParser; }; - -#endif diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.cxx b/Source/CTest/cmCTestReadCustomFilesCommand.cxx index ed14d06..a25cca4 100644 --- a/Source/CTest/cmCTestReadCustomFilesCommand.cxx +++ b/Source/CTest/cmCTestReadCustomFilesCommand.cxx @@ -15,7 +15,7 @@ bool cmCTestReadCustomFilesCommand::InitialPass( } for (std::string const& arg : args) { - this->CTest->ReadCustomConfigurationFileTree(arg.c_str(), this->Makefile); + this->CTest->ReadCustomConfigurationFileTree(arg, this->Makefile); } return true; diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.h b/Source/CTest/cmCTestReadCustomFilesCommand.h index cbb9390..03714f6 100644 --- a/Source/CTest/cmCTestReadCustomFilesCommand.h +++ b/Source/CTest/cmCTestReadCustomFilesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestReadCustomFilesCommand_h -#define cmCTestReadCustomFilesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -44,5 +43,3 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; }; - -#endif diff --git a/Source/CTest/cmCTestResourceAllocator.h b/Source/CTest/cmCTestResourceAllocator.h index 9f0b9c9..129e64e 100644 --- a/Source/CTest/cmCTestResourceAllocator.h +++ b/Source/CTest/cmCTestResourceAllocator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestResourceAllocator_h -#define cmCTestResourceAllocator_h +#pragma once #include <map> #include <string> @@ -35,5 +34,3 @@ public: private: std::map<std::string, std::map<std::string, Resource>> Resources; }; - -#endif diff --git a/Source/CTest/cmCTestResourceGroupsLexerHelper.h b/Source/CTest/cmCTestResourceGroupsLexerHelper.h index 2cb6cb1..ae4fa99 100644 --- a/Source/CTest/cmCTestResourceGroupsLexerHelper.h +++ b/Source/CTest/cmCTestResourceGroupsLexerHelper.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestResourceGroupsLexerHelper_h -#define cmCTestResourceGroupsLexerHelper_h +#pragma once #include <string> #include <vector> @@ -40,5 +39,3 @@ private: }; #define YY_EXTRA_TYPE cmCTestResourceGroupsLexerHelper* - -#endif diff --git a/Source/CTest/cmCTestResourceSpec.cxx b/Source/CTest/cmCTestResourceSpec.cxx index 21c97de..101dc2c 100644 --- a/Source/CTest/cmCTestResourceSpec.cxx +++ b/Source/CTest/cmCTestResourceSpec.cxx @@ -2,19 +2,140 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestResourceSpec.h" +#include <functional> #include <map> #include <string> #include <utility> #include <vector> +#include <cmext/string_view> + #include <cm3p/json/reader.h> #include <cm3p/json/value.h> #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" -static const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" }; -static const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" }; +#include "cmJSONHelpers.h" + +namespace { +const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" }; +const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" }; + +struct Version +{ + int Major = 1; + int Minor = 0; +}; + +struct TopVersion +{ + struct Version Version; +}; + +auto const VersionFieldHelper = + cmJSONIntHelper<cmCTestResourceSpec::ReadFileResult>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_VERSION); + +auto const VersionHelper = + cmJSONRequiredHelper<Version, cmCTestResourceSpec::ReadFileResult>( + cmCTestResourceSpec::ReadFileResult::NO_VERSION, + cmJSONObjectHelper<Version, cmCTestResourceSpec::ReadFileResult>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_VERSION) + .Bind("major"_s, &Version::Major, VersionFieldHelper) + .Bind("minor"_s, &Version::Minor, VersionFieldHelper)); + +auto const RootVersionHelper = + cmJSONObjectHelper<TopVersion, cmCTestResourceSpec::ReadFileResult>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_ROOT) + .Bind("version"_s, &TopVersion::Version, VersionHelper, false); + +cmCTestResourceSpec::ReadFileResult ResourceIdHelper(std::string& out, + const Json::Value* value) +{ + auto result = cmJSONStringHelper( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE)(out, value); + if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) { + return result; + } + cmsys::RegularExpressionMatch match; + if (!IdRegex.find(out.c_str(), match)) { + return cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE; + } + return cmCTestResourceSpec::ReadFileResult::READ_OK; +} + +auto const ResourceHelper = + cmJSONObjectHelper<cmCTestResourceSpec::Resource, + cmCTestResourceSpec::ReadFileResult>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE) + .Bind("id"_s, &cmCTestResourceSpec::Resource::Id, ResourceIdHelper) + .Bind("slots"_s, &cmCTestResourceSpec::Resource::Capacity, + cmJSONUIntHelper( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, 1), + false); + +auto const ResourceListHelper = + cmJSONVectorHelper<cmCTestResourceSpec::Resource, + cmCTestResourceSpec::ReadFileResult>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE_TYPE, + ResourceHelper); + +auto const ResourceMapHelper = + cmJSONMapFilterHelper<std::vector<cmCTestResourceSpec::Resource>, + cmCTestResourceSpec::ReadFileResult>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, + ResourceListHelper, [](const std::string& key) -> bool { + cmsys::RegularExpressionMatch match; + return IdentifierRegex.find(key.c_str(), match); + }); + +auto const SocketSetHelper = cmJSONVectorHelper< + std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, ResourceMapHelper); + +cmCTestResourceSpec::ReadFileResult SocketHelper( + cmCTestResourceSpec::Socket& out, const Json::Value* value) +{ + std::vector< + std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>> + sockets; + cmCTestResourceSpec::ReadFileResult result = SocketSetHelper(sockets, value); + if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) { + return result; + } + if (sockets.size() > 1) { + return cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC; + } + if (sockets.empty()) { + out.Resources.clear(); + } else { + out.Resources = std::move(sockets[0]); + } + return cmCTestResourceSpec::ReadFileResult::READ_OK; +} + +auto const LocalRequiredHelper = + cmJSONRequiredHelper<cmCTestResourceSpec::Socket, + cmCTestResourceSpec::ReadFileResult>( + cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, SocketHelper); + +auto const RootHelper = + cmJSONObjectHelper<cmCTestResourceSpec, cmCTestResourceSpec::ReadFileResult>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_ROOT) + .Bind("local", &cmCTestResourceSpec::LocalSocket, LocalRequiredHelper, + false); +} cmCTestResourceSpec::ReadFileResult cmCTestResourceSpec::ReadFromJSONFile( const std::string& filename) @@ -30,99 +151,17 @@ cmCTestResourceSpec::ReadFileResult cmCTestResourceSpec::ReadFromJSONFile( return ReadFileResult::JSON_PARSE_ERROR; } - if (!root.isObject()) { - return ReadFileResult::INVALID_ROOT; - } - - int majorVersion = 1; - int minorVersion = 0; - if (root.isMember("version")) { - auto const& version = root["version"]; - if (version.isObject()) { - if (!version.isMember("major") || !version.isMember("minor")) { - return ReadFileResult::INVALID_VERSION; - } - auto const& major = version["major"]; - auto const& minor = version["minor"]; - if (!major.isInt() || !minor.isInt()) { - return ReadFileResult::INVALID_VERSION; - } - majorVersion = major.asInt(); - minorVersion = minor.asInt(); - } else { - return ReadFileResult::INVALID_VERSION; - } - } else { - return ReadFileResult::NO_VERSION; + TopVersion version; + ReadFileResult result; + if ((result = RootVersionHelper(version, &root)) != + ReadFileResult::READ_OK) { + return result; } - - if (majorVersion != 1 || minorVersion != 0) { + if (version.Version.Major != 1 || version.Version.Minor != 0) { return ReadFileResult::UNSUPPORTED_VERSION; } - auto const& local = root["local"]; - if (!local.isArray()) { - return ReadFileResult::INVALID_SOCKET_SPEC; - } - if (local.size() > 1) { - return ReadFileResult::INVALID_SOCKET_SPEC; - } - - if (local.empty()) { - this->LocalSocket.Resources.clear(); - return ReadFileResult::READ_OK; - } - - auto const& localSocket = local[0]; - if (!localSocket.isObject()) { - return ReadFileResult::INVALID_SOCKET_SPEC; - } - std::map<std::string, std::vector<cmCTestResourceSpec::Resource>> resources; - cmsys::RegularExpressionMatch match; - for (auto const& key : localSocket.getMemberNames()) { - if (IdentifierRegex.find(key.c_str(), match)) { - auto const& value = localSocket[key]; - auto& r = resources[key]; - if (value.isArray()) { - for (auto const& item : value) { - if (item.isObject()) { - cmCTestResourceSpec::Resource resource; - - if (!item.isMember("id")) { - return ReadFileResult::INVALID_RESOURCE; - } - auto const& id = item["id"]; - if (!id.isString()) { - return ReadFileResult::INVALID_RESOURCE; - } - resource.Id = id.asString(); - if (!IdRegex.find(resource.Id.c_str(), match)) { - return ReadFileResult::INVALID_RESOURCE; - } - - if (item.isMember("slots")) { - auto const& capacity = item["slots"]; - if (!capacity.isConvertibleTo(Json::uintValue)) { - return ReadFileResult::INVALID_RESOURCE; - } - resource.Capacity = capacity.asUInt(); - } else { - resource.Capacity = 1; - } - - r.push_back(resource); - } else { - return ReadFileResult::INVALID_RESOURCE; - } - } - } else { - return ReadFileResult::INVALID_RESOURCE_TYPE; - } - } - } - - this->LocalSocket.Resources = std::move(resources); - return ReadFileResult::READ_OK; + return RootHelper(*this, &root); } const char* cmCTestResourceSpec::ResultToString(ReadFileResult result) diff --git a/Source/CTest/cmCTestResourceSpec.h b/Source/CTest/cmCTestResourceSpec.h index cb242c0..72628a3 100644 --- a/Source/CTest/cmCTestResourceSpec.h +++ b/Source/CTest/cmCTestResourceSpec.h @@ -1,7 +1,8 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestResourceSpec_h -#define cmCTestResourceSpec_h +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep #include <map> #include <string> @@ -51,5 +52,3 @@ public: bool operator==(const cmCTestResourceSpec& other) const; bool operator!=(const cmCTestResourceSpec& other) const; }; - -#endif diff --git a/Source/CTest/cmCTestRunScriptCommand.h b/Source/CTest/cmCTestRunScriptCommand.h index 2d8bde1..510b748 100644 --- a/Source/CTest/cmCTestRunScriptCommand.h +++ b/Source/CTest/cmCTestRunScriptCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestRunScriptCommand_h -#define cmCTestRunScriptCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -45,5 +44,3 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; }; - -#endif diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 2c8e385..4d65c9b 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -619,11 +619,11 @@ void cmCTestRunTest::ComputeArguments() cmCTestMemCheckHandler* handler = static_cast<cmCTestMemCheckHandler*>(this->TestHandler); this->ActualCommand = handler->MemoryTester; - this->TestProperties->Args[1] = this->TestHandler->FindTheExecutable( - this->TestProperties->Args[1].c_str()); + this->TestProperties->Args[1] = + this->TestHandler->FindTheExecutable(this->TestProperties->Args[1]); } else { - this->ActualCommand = this->TestHandler->FindTheExecutable( - this->TestProperties->Args[1].c_str()); + this->ActualCommand = + this->TestHandler->FindTheExecutable(this->TestProperties->Args[1]); ++j; // skip the executable (it will be actualCommand) } std::string testCommand = diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index d831247..863ac1b 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestRunTest_h -#define cmCTestRunTest_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -159,5 +158,3 @@ inline int getNumWidth(size_t n) } return w; } - -#endif diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h index b74dc12..370d176 100644 --- a/Source/CTest/cmCTestSVN.h +++ b/Source/CTest/cmCTestSVN.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestSVN_h -#define cmCTestSVN_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -103,5 +102,3 @@ private: friend class UpdateParser; friend class ExternalParser; }; - -#endif diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 4fa4dc0..4808c36 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -35,6 +35,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" @@ -372,8 +373,8 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) int cmCTestScriptHandler::ExtractVariables() { // Temporary variables - const char* minInterval; - const char* contDuration; + cmProp minInterval; + cmProp contDuration; this->SourceDir = this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY"); @@ -412,7 +413,7 @@ int cmCTestScriptHandler::ExtractVariables() int i; for (i = 1; i < 10; ++i) { sprintf(updateVar, "CTEST_EXTRA_UPDATES_%i", i); - const char* updateVal = this->Makefile->GetDefinition(updateVar); + cmProp updateVal = this->Makefile->GetDefinition(updateVar); if (updateVal) { if (this->UpdateCmd.empty()) { cmSystemTools::Error( @@ -420,7 +421,7 @@ int cmCTestScriptHandler::ExtractVariables() " specified without specifying CTEST_CVS_COMMAND."); return 12; } - this->ExtraUpdates.emplace_back(updateVal); + this->ExtraUpdates.emplace_back(*updateVal); } } @@ -455,10 +456,10 @@ int cmCTestScriptHandler::ExtractVariables() // the script may override the minimum continuous interval if (minInterval) { - this->MinimumInterval = 60 * atof(minInterval); + this->MinimumInterval = 60 * atof(minInterval->c_str()); } if (contDuration) { - this->ContinuousDuration = 60.0 * atof(contDuration); + this->ContinuousDuration = 60.0 * atof(contDuration->c_str()); } this->UpdateElapsedTime(); @@ -932,13 +933,13 @@ cmDuration cmCTestScriptHandler::GetRemainingTimeAllowed() return cmCTest::MaxDuration(); } - const char* timelimitS = this->Makefile->GetDefinition("CTEST_TIME_LIMIT"); + cmProp timelimitS = this->Makefile->GetDefinition("CTEST_TIME_LIMIT"); if (!timelimitS) { return cmCTest::MaxDuration(); } - auto timelimit = cmDuration(atof(timelimitS)); + auto timelimit = cmDuration(atof(timelimitS->c_str())); auto duration = std::chrono::duration_cast<cmDuration>( std::chrono::steady_clock::now() - this->ScriptStartTime); diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h index ebb7905..8eb9658 100644 --- a/Source/CTest/cmCTestScriptHandler.h +++ b/Source/CTest/cmCTestScriptHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestScriptHandler_h -#define cmCTestScriptHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -176,5 +175,3 @@ private: std::unique_ptr<cmGlobalGenerator> GlobalGenerator; std::unique_ptr<cmake> CMake; }; - -#endif diff --git a/Source/CTest/cmCTestSleepCommand.h b/Source/CTest/cmCTestSleepCommand.h index 1c3b8a1..9425576 100644 --- a/Source/CTest/cmCTestSleepCommand.h +++ b/Source/CTest/cmCTestSleepCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestSleepCommand_h -#define cmCTestSleepCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -45,5 +44,3 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; }; - -#endif diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx index fe68406..53e1b2f 100644 --- a/Source/CTest/cmCTestStartCommand.cxx +++ b/Source/CTest/cmCTestStartCommand.cxx @@ -9,6 +9,7 @@ #include "cmCTestVC.h" #include "cmGeneratedFileStream.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -29,8 +30,8 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, size_t cnt = 0; const char* smodel = nullptr; - const char* src_dir = nullptr; - const char* bld_dir = nullptr; + const std::string* src_dir = nullptr; + const std::string* bld_dir = nullptr; while (cnt < args.size()) { if (args[cnt] == "GROUP" || args[cnt] == "TRACK") { @@ -54,10 +55,10 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, smodel = args[cnt].c_str(); cnt++; } else if (!src_dir) { - src_dir = args[cnt].c_str(); + src_dir = &args[cnt]; cnt++; } else if (!bld_dir) { - bld_dir = args[cnt].c_str(); + bld_dir = &args[cnt]; cnt++; } else { this->SetError("Too many arguments"); @@ -87,32 +88,31 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, return false; } - cmSystemTools::AddKeepPath(src_dir); - cmSystemTools::AddKeepPath(bld_dir); + cmSystemTools::AddKeepPath(*src_dir); + cmSystemTools::AddKeepPath(*bld_dir); this->CTest->EmptyCTestConfiguration(); - std::string sourceDir = cmSystemTools::CollapseFullPath(src_dir); - std::string binaryDir = cmSystemTools::CollapseFullPath(bld_dir); - this->CTest->SetCTestConfiguration("SourceDirectory", sourceDir.c_str(), - this->Quiet); - this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir.c_str(), + std::string sourceDir = cmSystemTools::CollapseFullPath(*src_dir); + std::string binaryDir = cmSystemTools::CollapseFullPath(*bld_dir); + this->CTest->SetCTestConfiguration("SourceDirectory", sourceDir, this->Quiet); + this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir, this->Quiet); if (smodel) { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Run dashboard with model " << smodel << std::endl - << " Source directory: " << src_dir << std::endl - << " Build directory: " << bld_dir << std::endl, + << " Source directory: " << *src_dir << std::endl + << " Build directory: " << *bld_dir << std::endl, this->Quiet); } else { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Run dashboard with " "to-be-determined model" << std::endl - << " Source directory: " << src_dir << std::endl - << " Build directory: " << bld_dir << std::endl, + << " Source directory: " << *src_dir << std::endl + << " Build directory: " << *bld_dir << std::endl, this->Quiet); } const char* group = this->CTest->GetSpecificGroup(); @@ -162,7 +162,7 @@ bool cmCTestStartCommand::InitialCheckout(std::ostream& ofs, std::string const& sourceDir) { // Use the user-provided command to create the source tree. - const char* initialCheckoutCommand = + cmProp initialCheckoutCommand = this->Makefile->GetDefinition("CTEST_CHECKOUT_COMMAND"); if (!initialCheckoutCommand) { initialCheckoutCommand = @@ -172,7 +172,7 @@ bool cmCTestStartCommand::InitialCheckout(std::ostream& ofs, // Use a generic VC object to run and log the command. cmCTestVC vc(this->CTest, ofs); vc.SetSourceDirectory(sourceDir); - if (!vc.InitialCheckout(initialCheckoutCommand)) { + if (!vc.InitialCheckout(*initialCheckoutCommand)) { return false; } } diff --git a/Source/CTest/cmCTestStartCommand.h b/Source/CTest/cmCTestStartCommand.h index b30b1bb..b3d06a7 100644 --- a/Source/CTest/cmCTestStartCommand.h +++ b/Source/CTest/cmCTestStartCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestStartCommand_h -#define cmCTestStartCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -62,5 +61,3 @@ private: bool CreateNewTag; bool Quiet; }; - -#endif diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index 279216e..bdba0e5 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -16,6 +16,7 @@ #include "cmCommand.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -35,12 +36,12 @@ std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone() cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() { - const char* submitURL = !this->SubmitURL.empty() - ? this->SubmitURL.c_str() + const std::string* submitURL = !this->SubmitURL.empty() + ? &this->SubmitURL : this->Makefile->GetDefinition("CTEST_SUBMIT_URL"); if (submitURL) { - this->CTest->SetCTestConfiguration("SubmitURL", submitURL, this->Quiet); + this->CTest->SetCTestConfiguration("SubmitURL", *submitURL, this->Quiet); } else { this->CTest->SetCTestConfigurationFromCMakeVariable( this->Makefile, "DropMethod", "CTEST_DROP_METHOD", this->Quiet); @@ -58,17 +59,17 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() this->CTest->SetCTestConfigurationFromCMakeVariable( this->Makefile, "CurlOptions", "CTEST_CURL_OPTIONS", this->Quiet); - const char* notesFilesVariable = + cmProp notesFilesVariable = this->Makefile->GetDefinition("CTEST_NOTES_FILES"); if (notesFilesVariable) { - std::vector<std::string> notesFiles = cmExpandedList(notesFilesVariable); + std::vector<std::string> notesFiles = cmExpandedList(*notesFilesVariable); this->CTest->GenerateNotesFile(notesFiles); } - const char* extraFilesVariable = + cmProp extraFilesVariable = this->Makefile->GetDefinition("CTEST_EXTRA_SUBMIT_FILES"); if (extraFilesVariable) { - std::vector<std::string> extraFiles = cmExpandedList(extraFilesVariable); + std::vector<std::string> extraFiles = cmExpandedList(*extraFilesVariable); if (!this->CTest->SubmitExtraFiles(extraFiles)) { this->SetError("problem submitting extra files."); return nullptr; @@ -108,7 +109,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() if (this->PartsMentioned) { auto parts = cmMakeRange(this->Parts).transform([this](std::string const& arg) { - return this->CTest->GetPartFromName(arg.c_str()); + return this->CTest->GetPartFromName(arg); }); handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end())); } @@ -177,7 +178,7 @@ void cmCTestSubmitCommand::CheckArguments( !this->Files.empty() || cm::contains(keywords, "FILES"); cm::erase_if(this->Parts, [this](std::string const& arg) -> bool { - cmCTest::Part p = this->CTest->GetPartFromName(arg.c_str()); + cmCTest::Part p = this->CTest->GetPartFromName(arg); if (p == cmCTest::PartCount) { std::ostringstream e; e << "Part name \"" << arg << "\" is invalid."; diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h index 9060771..c5d11df 100644 --- a/Source/CTest/cmCTestSubmitCommand.h +++ b/Source/CTest/cmCTestSubmitCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestSubmitCommand_h -#define cmCTestSubmitCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -55,5 +54,3 @@ protected: std::vector<std::string> HttpHeaders; std::vector<std::string> Parts; }; - -#endif diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index ea36df5..5b54573 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -797,7 +797,7 @@ int cmCTestSubmitHandler::ProcessHandler() gfile = gfile.substr(glen); cmCTestOptionalLog(this->CTest, DEBUG, "Glob file: " << gfile << std::endl, this->Quiet); - this->CTest->AddSubmitFile(cmCTest::PartCoverage, gfile.c_str()); + this->CTest->AddSubmitFile(cmCTest::PartCoverage, gfile); } } else { cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem globbing" << std::endl); diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h index 304daaa..809c615 100644 --- a/Source/CTest/cmCTestSubmitHandler.h +++ b/Source/CTest/cmCTestSubmitHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestSubmitHandler_h -#define cmCTestSubmitHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -77,5 +76,3 @@ private: std::set<std::string> Files; std::vector<std::string> HttpHeaders; }; - -#endif diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index c71b409..4403733 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -13,6 +13,7 @@ #include "cmCTestTestHandler.h" #include "cmDuration.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" void cmCTestTestCommand::BindArguments() @@ -39,12 +40,11 @@ void cmCTestTestCommand::BindArguments() cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() { - const char* ctestTimeout = - this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT"); + cmProp ctestTimeout = this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT"); cmDuration timeout; if (ctestTimeout) { - timeout = cmDuration(atof(ctestTimeout)); + timeout = cmDuration(atof(ctestTimeout->c_str())); } else { timeout = this->CTest->GetTimeOut(); if (timeout <= cmDuration::zero()) { @@ -54,10 +54,10 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() } this->CTest->SetTimeOut(timeout); - const char* resourceSpecFile = + cmProp resourceSpecFile = this->Makefile->GetDefinition("CTEST_RESOURCE_SPEC_FILE"); if (this->ResourceSpecFile.empty() && resourceSpecFile) { - this->ResourceSpecFile = resourceSpecFile; + this->ResourceSpecFile = *resourceSpecFile; } cmCTestGenericHandler* handler = this->InitializeActualHandler(); @@ -114,19 +114,19 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() // or CTEST_TEST_LOAD script variable, or ctest --test-load // command line argument... in that order. unsigned long testLoad; - const char* ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD"); + cmProp ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD"); if (!this->TestLoad.empty()) { - if (!cmStrToULong(this->TestLoad.c_str(), &testLoad)) { + if (!cmStrToULong(this->TestLoad, &testLoad)) { testLoad = 0; cmCTestLog(this->CTest, WARNING, "Invalid value for 'TEST_LOAD' : " << this->TestLoad << std::endl); } - } else if (ctestTestLoad && *ctestTestLoad) { - if (!cmStrToULong(ctestTestLoad, &testLoad)) { + } else if (cmNonempty(ctestTestLoad)) { + if (!cmStrToULong(*ctestTestLoad, &testLoad)) { testLoad = 0; cmCTestLog(this->CTest, WARNING, - "Invalid value for 'CTEST_TEST_LOAD' : " << ctestTestLoad + "Invalid value for 'CTEST_TEST_LOAD' : " << *ctestTestLoad << std::endl); } } else { @@ -134,10 +134,10 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() } handler->SetTestLoad(testLoad); - if (const char* labelsForSubprojects = + if (cmProp labelsForSubprojects = this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) { this->CTest->SetCTestConfiguration("LabelsForSubprojects", - labelsForSubprojects, this->Quiet); + *labelsForSubprojects, this->Quiet); } handler->SetQuiet(this->Quiet); diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h index 7925586..624cd91 100644 --- a/Source/CTest/cmCTestTestCommand.h +++ b/Source/CTest/cmCTestTestCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestTestCommand_h -#define cmCTestTestCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -62,5 +61,3 @@ protected: std::string ResourceSpecFile; bool StopOnFailure = false; }; - -#endif diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index d0dbaae..4d1a589 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -37,6 +37,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" @@ -819,14 +820,16 @@ void cmCTestTestHandler::CheckLabelFilter(cmCTestTestProperties& it) this->CheckLabelFilterExclude(it); } -void cmCTestTestHandler::ComputeTestList() +bool cmCTestTestHandler::ComputeTestList() { this->TestList.clear(); // clear list of test - this->GetListOfTests(); + if (!this->GetListOfTests()) { + return false; + } if (this->RerunFailed) { this->ComputeTestListForRerunFailed(); - return; + return true; } cmCTestTestHandler::ListOfTests::size_type tmsize = this->TestList.size(); @@ -882,6 +885,7 @@ void cmCTestTestHandler::ComputeTestList() this->TestList = finalList; this->UpdateMaxTestNameWidth(); + return true; } void cmCTestTestHandler::ComputeTestListForRerunFailed() @@ -1260,7 +1264,10 @@ bool cmCTestTestHandler::GetValue(const char* tag, std::string& value, bool cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed, std::vector<std::string>& failed) { - this->ComputeTestList(); + if (!this->ComputeTestList()) { + return false; + } + this->StartTest = this->CTest->CurrentTime(); this->StartTestTime = std::chrono::system_clock::now(); auto elapsed_time_start = std::chrono::steady_clock::now(); @@ -1374,7 +1381,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.StartElement("TestList"); for (cmCTestTestResult const& result : this->TestResults) { std::string testPath = result.Path + "/" + result.Name; - xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str())); + xml.Element("Test", this->CTest->GetShortPathToFile(testPath)); } xml.EndElement(); // TestList for (cmCTestTestResult& result : this->TestResults) { @@ -1483,8 +1490,8 @@ void cmCTestTestHandler::WriteTestResultHeader(cmXMLWriter& xml, } std::string testPath = result.Path + "/" + result.Name; xml.Element("Name", result.Name); - xml.Element("Path", this->CTest->GetShortPathToFile(result.Path.c_str())); - xml.Element("FullName", this->CTest->GetShortPathToFile(testPath.c_str())); + xml.Element("Path", this->CTest->GetShortPathToFile(result.Path)); + xml.Element("FullName", this->CTest->GetShortPathToFile(testPath)); xml.Element("FullCommandLine", result.FullCommandLine); } @@ -1546,12 +1553,12 @@ int cmCTestTestHandler::ExecuteCommands(std::vector<std::string>& vec) } // Find the appropriate executable to run for a test -std::string cmCTestTestHandler::FindTheExecutable(const char* exe) +std::string cmCTestTestHandler::FindTheExecutable(const std::string& exe) { std::string resConfig; std::vector<std::string> extraPaths; std::vector<std::string> failedPaths; - if (strcmp(exe, "NOT_AVAILABLE") == 0) { + if (exe == "NOT_AVAILABLE") { return exe; } return cmCTestTestHandler::FindExecutable(this->CTest, exe, resConfig, @@ -1607,7 +1614,7 @@ void cmCTestTestHandler::AddConfigurations( // Find the appropriate executable to run for a test std::string cmCTestTestHandler::FindExecutable( - cmCTest* ctest, const char* testCommand, std::string& resultingConfig, + cmCTest* ctest, const std::string& testCommand, std::string& resultingConfig, std::vector<std::string>& extraPaths, std::vector<std::string>& failed) { // now run the compiled test if we can find it @@ -1695,7 +1702,7 @@ bool cmCTestTestHandler::ParseResourceGroupsProperty( return lexer.ParseString(val); } -void cmCTestTestHandler::GetListOfTests() +bool cmCTestTestHandler::GetListOfTests() { if (!this->IncludeLabelRegExp.empty()) { this->IncludeLabelRegularExpression.compile( @@ -1748,22 +1755,24 @@ void cmCTestTestHandler::GetListOfTests() // does the DartTestfile.txt exist ? testFilename = "DartTestfile.txt"; } else { - return; + return true; } if (!mf.ReadListFile(testFilename)) { - return; + return false; } if (cmSystemTools::GetErrorOccuredFlag()) { - return; + // SEND_ERROR or FATAL_ERROR in CTestTestfile or TEST_INCLUDE_FILES + return false; } - const char* specFile = mf.GetDefinition("CTEST_RESOURCE_SPEC_FILE"); + cmProp specFile = mf.GetDefinition("CTEST_RESOURCE_SPEC_FILE"); if (this->ResourceSpecFile.empty() && specFile) { - this->ResourceSpecFile = specFile; + this->ResourceSpecFile = *specFile; } cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Done constructing a list of tests" << std::endl, this->Quiet); + return true; } void cmCTestTestHandler::UseIncludeRegExp() diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 0d88c30..aa29eeb 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestTestHandler_h -#define cmCTestTestHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -198,7 +197,8 @@ public: std::string filepath, std::string& filename); // full signature static method to find an executable - static std::string FindExecutable(cmCTest* ctest, const char* testCommand, + static std::string FindExecutable(cmCTest* ctest, + const std::string& testCommand, std::string& resultingConfig, std::vector<std::string>& extraPaths, std::vector<std::string>& failed); @@ -285,10 +285,10 @@ private: /** * Get the list of tests in directory and subdirectories. */ - void GetListOfTests(); + bool GetListOfTests(); // compute the lists of tests that will actually run // based on union regex and -I stuff - void ComputeTestList(); + bool ComputeTestList(); // compute the lists of tests that will actually run // based on LastTestFailed.log @@ -309,7 +309,7 @@ private: /** * Find the executable for a test */ - std::string FindTheExecutable(const char* exe); + std::string FindTheExecutable(const std::string& exe); std::string GetTestStatus(cmCTestTestResult const&); void ExpandTestsToRunInformation(size_t numPossibleTests); @@ -359,5 +359,3 @@ private: int RepeatCount = 1; bool RerunFailed; }; - -#endif diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx index 673eb9a..6fef90a 100644 --- a/Source/CTest/cmCTestUpdateCommand.cxx +++ b/Source/CTest/cmCTestUpdateCommand.cxx @@ -5,20 +5,20 @@ #include "cmCTest.h" #include "cmCTestUpdateHandler.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmSystemTools.h" cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler() { if (!this->Source.empty()) { this->CTest->SetCTestConfiguration( - "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(), + "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source), this->Quiet); } else { this->CTest->SetCTestConfiguration( "SourceDirectory", cmSystemTools::CollapseFullPath( - this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY")) - .c_str(), + cmToCStrSafe(this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY"))), this->Quiet); } std::string source_dir = diff --git a/Source/CTest/cmCTestUpdateCommand.h b/Source/CTest/cmCTestUpdateCommand.h index 5555c16..e4c3453 100644 --- a/Source/CTest/cmCTestUpdateCommand.h +++ b/Source/CTest/cmCTestUpdateCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestUpdateCommand_h -#define cmCTestUpdateCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -42,5 +41,3 @@ public: protected: cmCTestGenericHandler* InitializeHandler() override; }; - -#endif diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h index afc0e3d..25bbb2f 100644 --- a/Source/CTest/cmCTestUpdateHandler.h +++ b/Source/CTest/cmCTestUpdateHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestUpdateHandler_h -#define cmCTestUpdateHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -63,5 +62,3 @@ private: int DetectVCS(const char* dir); bool SelectVCS(); }; - -#endif diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h index 8334a9e..fe155f6 100644 --- a/Source/CTest/cmCTestUploadCommand.h +++ b/Source/CTest/cmCTestUploadCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestUploadCommand_h -#define cmCTestUploadCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -48,5 +47,3 @@ protected: std::vector<std::string> Files; }; - -#endif diff --git a/Source/CTest/cmCTestUploadHandler.h b/Source/CTest/cmCTestUploadHandler.h index dde14df..55d21c1 100644 --- a/Source/CTest/cmCTestUploadHandler.h +++ b/Source/CTest/cmCTestUploadHandler.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestUploadHandler_h -#define cmCTestUploadHandler_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -36,5 +35,3 @@ public: private: std::set<std::string> Files; }; - -#endif diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h index 3037e01..9bd7229 100644 --- a/Source/CTest/cmCTestVC.h +++ b/Source/CTest/cmCTestVC.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTestVC_h -#define cmCTestVC_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -150,5 +149,3 @@ protected: // Count paths reported with each PathStatus value. int PathCount[3]; }; - -#endif diff --git a/Source/CTest/cmParseBlanketJSCoverage.h b/Source/CTest/cmParseBlanketJSCoverage.h index cd1b225..e107454 100644 --- a/Source/CTest/cmParseBlanketJSCoverage.h +++ b/Source/CTest/cmParseBlanketJSCoverage.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmParseBlanketJSCoverage_h -#define cmParseBlanketJSCoverage_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -39,4 +38,3 @@ protected: cmCTestCoverageHandlerContainer& Coverage; cmCTest* CTest; }; -#endif diff --git a/Source/CTest/cmParseCacheCoverage.h b/Source/CTest/cmParseCacheCoverage.h index a8200b7..523f83b 100644 --- a/Source/CTest/cmParseCacheCoverage.h +++ b/Source/CTest/cmParseCacheCoverage.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmParseCacheCoverage_h -#define cmParseCacheCoverage_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -31,5 +30,3 @@ protected: // Read a single mcov file bool ReadCMCovFile(const char* f); }; - -#endif diff --git a/Source/CTest/cmParseCoberturaCoverage.h b/Source/CTest/cmParseCoberturaCoverage.h index cb6d097..0340433 100644 --- a/Source/CTest/cmParseCoberturaCoverage.h +++ b/Source/CTest/cmParseCoberturaCoverage.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmParseCoberturaCoverage_h -#define cmParseCoberturaCoverage_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -41,5 +40,3 @@ private: cmCTest* CTest; std::string CurFileName; }; - -#endif diff --git a/Source/CTest/cmParseDelphiCoverage.h b/Source/CTest/cmParseDelphiCoverage.h index 1b37405..2a014a1 100644 --- a/Source/CTest/cmParseDelphiCoverage.h +++ b/Source/CTest/cmParseDelphiCoverage.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmParseDelphiCoverage_h -#define cmParseDelphiCoverage_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -35,4 +34,3 @@ protected: cmCTestCoverageHandlerContainer& Coverage; cmCTest* CTest; }; -#endif diff --git a/Source/CTest/cmParseGTMCoverage.h b/Source/CTest/cmParseGTMCoverage.h index 41cc7f5..c35bf6e 100644 --- a/Source/CTest/cmParseGTMCoverage.h +++ b/Source/CTest/cmParseGTMCoverage.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmParseGTMCoverage_h -#define cmParseGTMCoverage_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -37,5 +36,3 @@ protected: bool ParseMCOVLine(std::string const& line, std::string& routine, std::string& function, int& linenumber, int& count); }; - -#endif diff --git a/Source/CTest/cmParseJacocoCoverage.h b/Source/CTest/cmParseJacocoCoverage.h index f2aec6d..3442dd0 100644 --- a/Source/CTest/cmParseJacocoCoverage.h +++ b/Source/CTest/cmParseJacocoCoverage.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmParseJacocoCoverage_h -#define cmParseJacocoCoverage_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -49,5 +48,3 @@ private: cmCTestCoverageHandlerContainer& Coverage; cmCTest* CTest; }; - -#endif diff --git a/Source/CTest/cmParseMumpsCoverage.h b/Source/CTest/cmParseMumpsCoverage.h index 8c08702..00a8431 100644 --- a/Source/CTest/cmParseMumpsCoverage.h +++ b/Source/CTest/cmParseMumpsCoverage.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmParseMumpsCoverage_h -#define cmParseMumpsCoverage_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -43,5 +42,3 @@ protected: cmCTestCoverageHandlerContainer& Coverage; cmCTest* CTest; }; - -#endif diff --git a/Source/CTest/cmParsePHPCoverage.h b/Source/CTest/cmParsePHPCoverage.h index ff0e636..763a6bb 100644 --- a/Source/CTest/cmParsePHPCoverage.h +++ b/Source/CTest/cmParsePHPCoverage.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmParsePHPCoverage_h -#define cmParsePHPCoverage_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -35,5 +34,3 @@ private: cmCTestCoverageHandlerContainer& Coverage; cmCTest* CTest; }; - -#endif diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index a549117..9ee1c17 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -545,17 +545,17 @@ std::string cmProcess::GetExitExceptionString() # endif # ifdef SIGABRT case SIGABRT: - exception_str = "Child aborted"; + exception_str = "Subprocess aborted"; break; # endif # ifdef SIGKILL case SIGKILL: - exception_str = "Child killed"; + exception_str = "Subprocess killed"; break; # endif # ifdef SIGTERM case SIGTERM: - exception_str = "Child terminated"; + exception_str = "Subprocess terminated"; break; # endif # ifdef SIGHUP diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index 1e6578c..9eec952 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmProcess_h -#define cmProcess_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -132,5 +131,3 @@ private: int Id; int64_t ExitValue; }; - -#endif diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake index 50ccc7c..5c1593d 100644 --- a/Source/Checks/cm_cxx_features.cmake +++ b/Source/Checks/cm_cxx_features.cmake @@ -1,6 +1,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) function(cm_check_cxx_feature name) + set(TRY_RUN_FEATURE "${ARGN}") string(TOUPPER ${name} FEATURE) if(NOT DEFINED CMake_HAVE_CXX_${FEATURE}) cm_message_checks_compat( @@ -12,12 +13,26 @@ function(cm_check_cxx_feature name) else() set(maybe_cxx_standard "") endif() - try_compile(CMake_HAVE_CXX_${FEATURE} - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_LIST_DIR}/cm_cxx_${name}.cxx - CMAKE_FLAGS ${maybe_cxx_standard} - OUTPUT_VARIABLE OUTPUT - ) + if (TRY_RUN_FEATURE) + try_run(CMake_RUN_CXX_${FEATURE} CMake_COMPILE_CXX_${FEATURE} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_LIST_DIR}/cm_cxx_${name}.cxx + CMAKE_FLAGS ${maybe_cxx_standard} + OUTPUT_VARIABLE OUTPUT + ) + if (CMake_RUN_CXX_${FEATURE} EQUAL "0" AND CMake_COMPILE_CXX_${FEATURE}) + set(CMake_HAVE_CXX_${FEATURE} ON CACHE INTERNAL "TRY_RUN" FORCE) + else() + set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_RUN" FORCE) + endif() + else() + try_compile(CMake_HAVE_CXX_${FEATURE} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_LIST_DIR}/cm_cxx_${name}.cxx + CMAKE_FLAGS ${maybe_cxx_standard} + OUTPUT_VARIABLE OUTPUT + ) + endif() set(check_output "${OUTPUT}") # Filter out MSBuild output that looks like a warning. string(REGEX REPLACE " +0 Warning\\(s\\)" "" check_output "${check_output}") @@ -63,3 +78,8 @@ if(CMake_HAVE_CXX_MAKE_UNIQUE) set(CMake_HAVE_CXX_UNIQUE_PTR 1) endif() cm_check_cxx_feature(unique_ptr) +if (NOT CMAKE_CXX_STANDARD LESS "17") + cm_check_cxx_feature(filesystem TRY_RUN) +else() + set(CMake_HAVE_CXX_FILESYSTEM FALSE) +endif() diff --git a/Source/Checks/cm_cxx_filesystem.cxx b/Source/Checks/cm_cxx_filesystem.cxx new file mode 100644 index 0000000..ae8acc5 --- /dev/null +++ b/Source/Checks/cm_cxx_filesystem.cxx @@ -0,0 +1,27 @@ + +#include <filesystem> + +int main() +{ + std::filesystem::path p0(L"/a/b/c"); + + std::filesystem::path p1("/a/b/c"); + std::filesystem::path p2("/a/b/c"); + if (p1 != p2) { + return 1; + } + +#if defined(_WIN32) + std::filesystem::path p3("//host/a/b/../c"); + if (p3.lexically_normal().generic_string() != "//host/a/c") { + return 1; + } + + std::filesystem::path p4("c://a/.///b/../"); + if (p4.lexically_normal().generic_string() != "c:/a/") { + return 1; + } +#endif + + return 0; +} diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 9a26db5..85e256b 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -2,11 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include <csignal> +#include <cstdio> +#include <cstdlib> #include <cstring> #include <iostream> #include <string> #include <vector> +#include <unistd.h> + #include "cmsys/Encoding.hxx" #include "cmCursesColor.h" @@ -54,7 +58,12 @@ void onsig(int /*unused*/) { if (cmCursesForm::CurrentForm) { endwin(); - initscr(); /* Initialization */ + if (initscr() == nullptr) { + static const char errmsg[] = "Error: ncurses initialization failed\n"; + auto r = write(STDERR_FILENO, errmsg, sizeof(errmsg) - 1); + static_cast<void>(r); + exit(1); + } noecho(); /* Echo off */ cbreak(); /* nl- or cr not needed */ keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ @@ -124,7 +133,10 @@ int main(int argc, char const* const* argv) cmCursesForm::DebugStart(); } - initscr(); /* Initialization */ + if (initscr() == nullptr) { + fprintf(stderr, "Error: ncurses initialization failed\n"); + exit(1); + } noecho(); /* Echo off */ cbreak(); /* nl- or cr not needed */ keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ diff --git a/Source/CursesDialog/cmCursesBoolWidget.h b/Source/CursesDialog/cmCursesBoolWidget.h index 8c96256..746825b 100644 --- a/Source/CursesDialog/cmCursesBoolWidget.h +++ b/Source/CursesDialog/cmCursesBoolWidget.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesBoolWidget_h -#define cmCursesBoolWidget_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -29,5 +28,3 @@ public: void SetValueAsBool(bool value); bool GetValueAsBool(); }; - -#endif // cmCursesBoolWidget_h diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h index a711363..d414918 100644 --- a/Source/CursesDialog/cmCursesCacheEntryComposite.h +++ b/Source/CursesDialog/cmCursesCacheEntryComposite.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesCacheEntryComposite_h -#define cmCursesCacheEntryComposite_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -41,5 +40,3 @@ protected: int LabelWidth; int EntryWidth; }; - -#endif // cmCursesCacheEntryComposite_h diff --git a/Source/CursesDialog/cmCursesColor.h b/Source/CursesDialog/cmCursesColor.h index f83265f..4e8a1e4 100644 --- a/Source/CursesDialog/cmCursesColor.h +++ b/Source/CursesDialog/cmCursesColor.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesColor_h -#define cmCursesColor_h +#pragma once class cmCursesColor { @@ -23,5 +22,3 @@ public: protected: static short GetColor(char id, short fallback); }; - -#endif // cmCursesColor_h diff --git a/Source/CursesDialog/cmCursesDummyWidget.h b/Source/CursesDialog/cmCursesDummyWidget.h index 07b7288..4347746 100644 --- a/Source/CursesDialog/cmCursesDummyWidget.h +++ b/Source/CursesDialog/cmCursesDummyWidget.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesDummyWidget_h -#define cmCursesDummyWidget_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -24,5 +23,3 @@ public: // handled. bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) override; }; - -#endif // cmCursesDummyWidget_h diff --git a/Source/CursesDialog/cmCursesFilePathWidget.h b/Source/CursesDialog/cmCursesFilePathWidget.h index 3f71259..2ae5d14 100644 --- a/Source/CursesDialog/cmCursesFilePathWidget.h +++ b/Source/CursesDialog/cmCursesFilePathWidget.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesFilePathWidget_h -#define cmCursesFilePathWidget_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -15,5 +14,3 @@ public: cmCursesFilePathWidget(cmCursesFilePathWidget const&) = delete; cmCursesFilePathWidget& operator=(cmCursesFilePathWidget const&) = delete; }; - -#endif // cmCursesFilePathWidget_h diff --git a/Source/CursesDialog/cmCursesForm.h b/Source/CursesDialog/cmCursesForm.h index e3626e6..93459b9 100644 --- a/Source/CursesDialog/cmCursesForm.h +++ b/Source/CursesDialog/cmCursesForm.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesForm_h -#define cmCursesForm_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -62,5 +61,3 @@ protected: FORM* Form; }; - -#endif // cmCursesForm_h diff --git a/Source/CursesDialog/cmCursesLabelWidget.h b/Source/CursesDialog/cmCursesLabelWidget.h index 9e75681..c10aa37 100644 --- a/Source/CursesDialog/cmCursesLabelWidget.h +++ b/Source/CursesDialog/cmCursesLabelWidget.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesLabelWidget_h -#define cmCursesLabelWidget_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -28,5 +27,3 @@ public: // handled bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) override; }; - -#endif // cmCursesLabelWidget_h diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h index da9fea2..4f69cb1 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.h +++ b/Source/CursesDialog/cmCursesLongMessageForm.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesLongMessageForm_h -#define cmCursesLongMessageForm_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -59,5 +58,3 @@ protected: FIELD* Fields[2]; }; - -#endif // cmCursesLongMessageForm_h diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h index 2e06b90..c6db66f 100644 --- a/Source/CursesDialog/cmCursesMainForm.h +++ b/Source/CursesDialog/cmCursesMainForm.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesMainForm_h -#define cmCursesMainForm_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -170,5 +169,3 @@ protected: std::string OldSearchString; bool SearchMode; }; - -#endif // cmCursesMainForm_h diff --git a/Source/CursesDialog/cmCursesOptionsWidget.h b/Source/CursesDialog/cmCursesOptionsWidget.h index 0de8e64..cb06e4d 100644 --- a/Source/CursesDialog/cmCursesOptionsWidget.h +++ b/Source/CursesDialog/cmCursesOptionsWidget.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesOptionsWidget_h -#define cmCursesOptionsWidget_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -35,5 +34,3 @@ protected: std::vector<std::string> Options; std::vector<std::string>::size_type CurrentOption; }; - -#endif // cmCursesOptionsWidget_h diff --git a/Source/CursesDialog/cmCursesPathWidget.h b/Source/CursesDialog/cmCursesPathWidget.h index fb365e9..79e342e 100644 --- a/Source/CursesDialog/cmCursesPathWidget.h +++ b/Source/CursesDialog/cmCursesPathWidget.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesPathWidget_h -#define cmCursesPathWidget_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -34,5 +33,3 @@ protected: bool Cycle; std::string::size_type CurrentIndex; }; - -#endif // cmCursesPathWidget_h diff --git a/Source/CursesDialog/cmCursesStandardIncludes.h b/Source/CursesDialog/cmCursesStandardIncludes.h index 5b0ad58..9745b97 100644 --- a/Source/CursesDialog/cmCursesStandardIncludes.h +++ b/Source/CursesDialog/cmCursesStandardIncludes.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesStandardIncludes_h -#define cmCursesStandardIncludes_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -41,5 +40,3 @@ inline void curses_clear() # undef __attribute__ #endif #undef cm_no__attribute__ - -#endif // cmCursesStandardIncludes_h diff --git a/Source/CursesDialog/cmCursesStringWidget.h b/Source/CursesDialog/cmCursesStringWidget.h index ce06c6d..faa2ade 100644 --- a/Source/CursesDialog/cmCursesStringWidget.h +++ b/Source/CursesDialog/cmCursesStringWidget.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesStringWidget_h -#define cmCursesStringWidget_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -65,5 +64,3 @@ protected: std::string OriginalString; bool Done; }; - -#endif // cmCursesStringWidget_h diff --git a/Source/CursesDialog/cmCursesWidget.h b/Source/CursesDialog/cmCursesWidget.h index 9d03c6e..29ec28b 100644 --- a/Source/CursesDialog/cmCursesWidget.h +++ b/Source/CursesDialog/cmCursesWidget.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCursesWidget_h -#define cmCursesWidget_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -68,5 +67,3 @@ protected: // The page in the main form this widget is in int Page; }; - -#endif // cmCursesWidget_h diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt index b468f5b..21c499e 100644 --- a/Source/CursesDialog/form/CMakeLists.txt +++ b/Source/CursesDialog/form/CMakeLists.txt @@ -3,6 +3,14 @@ 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)$") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") +elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") +endif() + configure_file(cmFormConfigure.h.in "${CMAKE_CURRENT_BINARY_DIR}/cmFormConfigure.h") add_library(cmForm diff --git a/Source/CursesDialog/form/frm_driver.c b/Source/CursesDialog/form/frm_driver.c index e4e72aa..112ab08 100644 --- a/Source/CursesDialog/form/frm_driver.c +++ b/Source/CursesDialog/form/frm_driver.c @@ -2983,7 +2983,7 @@ INLINE static FIELD *Right_Neighbour_Field(FIELD * field) | Function : static FIELD *Upper_Neighbour_Field(FIELD * field) | | Description : Because of the row-major nature of sorting the fields, -| its more difficult to define whats the upper neighbour +| its more difficult to define what's the upper neighbour | field really means. We define that it must be on a | 'previous' line (cyclic order!) and is the rightmost | field laying on the left side of the given field. If @@ -3030,7 +3030,7 @@ static FIELD *Upper_Neighbour_Field(FIELD * field) | Function : static FIELD *Down_Neighbour_Field(FIELD * field) | | Description : Because of the row-major nature of sorting the fields, -| its more difficult to define whats the down neighbour +| its more difficult to define what's the down neighbour | field really means. We define that it must be on a | 'next' line (cyclic order!) and is the leftmost | field laying on the right side of the given field. If diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx index 5879912..46220ff 100644 --- a/Source/LexerParser/cmCommandArgumentLexer.cxx +++ b/Source/LexerParser/cmCommandArgumentLexer.cxx @@ -653,7 +653,7 @@ This file must be translated to C++ and modified to build everywhere. Run flex >= 2.6 like this: - flex --nounistd -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l + flex --nounistd --never-interactive --batch -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l Modify cmCommandArgumentLexer.cxx: - remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx @@ -668,10 +668,7 @@ Modify cmCommandArgumentLexer.cxx: #include "cmCommandArgumentParserHelper.h" -/* Replace the lexer input function. */ -#undef YY_INPUT -#define YY_INPUT(buf, result, max_size) \ - do { result = yyextra->LexInput(buf, max_size); } while (0) +#define YY_USER_ACTION yyextra->UpdateInputPosition(yyleng); /* Include the set of tokens from the parser. */ #include "cmCommandArgumentParserTokens.h" @@ -967,16 +964,12 @@ yy_match: yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 41 ); + while ( yy_current_state != 29 ); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; yy_find_action: yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - yy_act = yy_accept[yy_current_state]; - } YY_DO_BEFORE_ACTION; @@ -1173,7 +1166,8 @@ case YY_STATE_EOF(NOESCAPES): else { - yy_cp = yyg->yy_c_buf_p; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; goto yy_find_action; } } @@ -1661,7 +1655,7 @@ static void yy_load_buffer_state (yyscan_t yyscanner) b->yy_bs_column = 0; } - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + b->yy_is_interactive = 0; errno = oerrno; } diff --git a/Source/LexerParser/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l index 010d54b..8ad2335 100644 --- a/Source/LexerParser/cmCommandArgumentLexer.in.l +++ b/Source/LexerParser/cmCommandArgumentLexer.in.l @@ -7,7 +7,7 @@ This file must be translated to C++ and modified to build everywhere. Run flex >= 2.6 like this: - flex --nounistd -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l + flex --nounistd --never-interactive --batch -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l Modify cmCommandArgumentLexer.cxx: - remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx @@ -22,10 +22,7 @@ Modify cmCommandArgumentLexer.cxx: #include "cmCommandArgumentParserHelper.h" -/* Replace the lexer input function. */ -#undef YY_INPUT -#define YY_INPUT(buf, result, max_size) \ - do { result = yyextra->LexInput(buf, max_size); } while (0) +#define YY_USER_ACTION yyextra->UpdateInputPosition(yyleng); /* Include the set of tokens from the parser. */ #include "cmCommandArgumentParserTokens.h" diff --git a/Source/QtDialog/AddCacheEntry.h b/Source/QtDialog/AddCacheEntry.h index e7a60dd..35522c5 100644 --- a/Source/QtDialog/AddCacheEntry.h +++ b/Source/QtDialog/AddCacheEntry.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef AddCacheEntry_h -#define AddCacheEntry_h +#pragma once #include "QCMake.h" #include <QCheckBox> @@ -32,5 +31,3 @@ private: const QStringList& VarNames; const QStringList& VarTypes; }; - -#endif diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 98dd0e2..e6d6b17 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -3,111 +3,79 @@ project(QtDialog) CMake_OPTIONAL_COMPONENT(cmake-gui) -find_package(Qt5Widgets QUIET) -if (Qt5Widgets_FOUND) - include_directories(${Qt5Widgets_INCLUDE_DIRS}) - add_definitions(${Qt5Widgets_DEFINITONS}) - macro(qt4_wrap_ui) - qt5_wrap_ui(${ARGN}) - endmacro() - macro(qt4_wrap_cpp) - qt5_wrap_cpp(${ARGN}) - endmacro() - macro(qt4_add_resources) - qt5_add_resources(${ARGN}) - endmacro() +find_package(Qt5Widgets REQUIRED) - set(CMake_QT_LIBRARIES ${Qt5Widgets_LIBRARIES}) - set(QT_QTMAIN_LIBRARY ${Qt5Core_QTMAIN_LIBRARIES}) +set(CMake_QT_EXTRA_LIBRARIES) - # Try to find the package WinExtras for the task bar progress - if(WIN32) - find_package(Qt5WinExtras QUIET) - if (Qt5WinExtras_FOUND) - include_directories(${Qt5WinExtras_INCLUDE_DIRS}) - add_definitions(-DQT_WINEXTRAS) - list(APPEND CMake_QT_LIBRARIES ${Qt5WinExtras_LIBRARIES}) - endif() +# Try to find the package WinExtras for the task bar progress +if(WIN32) + find_package(Qt5WinExtras QUIET) + if (Qt5WinExtras_FOUND) + add_definitions(-DQT_WINEXTRAS) + list(APPEND CMake_QT_EXTRA_LIBRARIES Qt5::WinExtras) endif() +endif() - # Remove this when the minimum version of Qt is 4.6. - add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0) - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") - if(CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES) - list(APPEND CMake_QT_LIBRARIES ${CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES}) - set_property(SOURCE CMakeSetup.cxx - PROPERTY COMPILE_DEFINITIONS USE_QXcbIntegrationPlugin) - endif() +if(CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES) + list(APPEND CMake_QT_EXTRA_LIBRARIES ${CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES}) + set_property(SOURCE CMakeSetup.cxx + PROPERTY COMPILE_DEFINITIONS USE_QXcbIntegrationPlugin) +endif() - if(CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES) - list(APPEND CMake_QT_LIBRARIES ${CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES}) - set_property(SOURCE CMakeSetup.cxx - PROPERTY COMPILE_DEFINITIONS USE_QWindowsIntegrationPlugin) - endif() +if(CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES) + list(APPEND CMake_QT_EXTRA_LIBRARIES ${CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES}) + set_property(SOURCE CMakeSetup.cxx + PROPERTY COMPILE_DEFINITIONS USE_QWindowsIntegrationPlugin) +endif() - # We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows. - # FIXME: This should be part of Qt5 CMake scripts, but unfortunately - # Qt5 support is missing there. - if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) - macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var) - get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) - if(EXISTS "${_qt_plugin_path}") - get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) - get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) - get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) - if(APPLE) - set(_qt_plugin_dir "PlugIns") - elseif(WIN32) - set(_qt_plugin_dir "plugins") - endif() - set(_qt_plugin_dest "${_qt_plugin_dir}/${_qt_plugin_type}") - install(FILES "${_qt_plugin_path}" - DESTINATION "${_qt_plugin_dest}" - ${COMPONENT}) - set(${_qt_plugins_var} - "${${_qt_plugins_var}};\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}") - else() - message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") +# We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows. +# FIXME: This should be part of Qt5 CMake scripts, but unfortunately +# Qt5 support is missing there. +if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) + macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var) + get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) + if(EXISTS "${_qt_plugin_path}") + get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) + get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) + get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) + if(APPLE) + set(_qt_plugin_dir "PlugIns") + elseif(WIN32) + set(_qt_plugin_dir "plugins") endif() - endmacro() - if(APPLE) - install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" - "[Paths]\nPlugins = ${_qt_plugin_dir}\n") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" - DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources" + set(_qt_plugin_dest "${_qt_plugin_dir}/${_qt_plugin_type}") + install(FILES "${_qt_plugin_path}" + DESTINATION "${_qt_plugin_dest}" ${COMPONENT}) - elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES) - install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" - "[Paths]\nPlugins = ../${_qt_plugin_dir}\n") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" - DESTINATION bin - ${COMPONENT}) - endif() - endif() - - if(TARGET Qt5::Core) - get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION) - get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH) - if(APPLE) - get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH) + set(${_qt_plugins_var} + "${${_qt_plugins_var}};\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}") + else() + message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") endif() + endmacro() + if(APPLE) + install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + "[Paths]\nPlugins = ${_qt_plugin_dir}\n") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources" + ${COMPONENT}) + elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES) + install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + "[Paths]\nPlugins = ../${_qt_plugin_dir}\n") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + DESTINATION bin + ${COMPONENT}) endif() -else() - set(QT_MIN_VERSION "4.4.0") - find_package(Qt4 REQUIRED) - if(NOT QT4_FOUND) - message(SEND_ERROR "Failed to find Qt 4.4 or greater.") - return() - endif() - - include(${QT_USE_FILE}) - - set(CMake_QT_LIBRARIES ${QT_LIBRARIES}) +endif() +get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION) +get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH) +if(APPLE) + get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH) endif() set(SRCS @@ -116,6 +84,7 @@ set(SRCS CMakeSetup.cxx CMakeSetupDialog.cxx CMakeSetupDialog.h + Compilers.h FirstConfigure.cxx FirstConfigure.h QCMake.cxx @@ -129,7 +98,7 @@ set(SRCS WarningMessagesDialog.cxx WarningMessagesDialog.h ) -QT4_WRAP_UI(UI_SRCS +qt5_wrap_ui(UI_SRCS CMakeSetupDialog.ui Compilers.ui CrossCompiler.ui @@ -137,7 +106,7 @@ QT4_WRAP_UI(UI_SRCS RegexExplorer.ui WarningMessagesDialog.ui ) -QT4_WRAP_CPP(MOC_SRCS +qt5_wrap_cpp(MOC_SRCS AddCacheEntry.h Compilers.h CMakeSetupDialog.h @@ -148,14 +117,24 @@ QT4_WRAP_CPP(MOC_SRCS RegexExplorer.h WarningMessagesDialog.h ) -QT4_ADD_RESOURCES(RC_SRCS CMakeSetup.qrc) +qt5_add_resources(RC_SRCS CMakeSetup.qrc) + +if (FALSE) # CMake's bootstrap binary does not support automoc + set(CMAKE_AUTOMOC 1) + set(CMAKE_AUTORCC 1) + set(CMAKE_AUTOUIC 1) +else () + list(APPEND SRCS + ${UI_SRCS} + ${MOC_SRCS} + ${RC_SRCS}) +endif () -set(SRCS ${SRCS} ${UI_SRCS} ${MOC_SRCS} ${RC_SRCS}) if(WIN32) - set(SRCS ${SRCS} CMakeSetup.rc) + list(APPEND SRCS CMakeSetup.rc) endif() if(APPLE) - set(SRCS ${SRCS} CMakeSetup.icns) + list(APPEND SRCS CMakeSetup.icns) set(MACOSX_BUNDLE_ICON_FILE CMakeSetup.icns) set_source_files_properties(CMakeSetup.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) @@ -172,7 +151,7 @@ endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE}) -target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES}) +target_link_libraries(cmake-gui CMakeLib Qt5::Core Qt5::Widgets ${CMake_QT_EXTRA_LIBRARIES}) if(WIN32) target_sources(cmake-gui PRIVATE $<TARGET_OBJECTS:CMakeVersion>) diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 9d928b2..7ef5a72 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -115,14 +115,6 @@ int main(int argc, char** argv) QTextCodec* utf8_codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForLocale(utf8_codec); -#if QT_VERSION < 0x050000 - // clean out standard Qt paths for plugins, which we don't use anyway - // when creating Mac bundles, it potentially causes problems - foreach (QString p, QApplication::libraryPaths()) { - QApplication::removeLibraryPath(p); - } -#endif - // tell the cmake library where cmake is QDir cmExecDir(QApplication::applicationDirPath()); #if defined(Q_OS_MAC) diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 6dbfe11..fcc8408 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -152,9 +152,6 @@ CMakeSetupDialog::CMakeSetupDialog() this->WarnUninitializedAction = OptionsMenu->addAction(tr("&Warn Uninitialized (--warn-uninitialized)")); this->WarnUninitializedAction->setCheckable(true); - this->WarnUnusedAction = - OptionsMenu->addAction(tr("&Warn Unused (--warn-unused-vars)")); - this->WarnUnusedAction->setCheckable(true); QAction* debugAction = OptionsMenu->addAction(tr("&Debug Output")); debugAction->setCheckable(true); @@ -290,9 +287,6 @@ void CMakeSetupDialog::initialize() QObject::connect(this->WarnUninitializedAction, SIGNAL(triggered(bool)), this->CMakeThread->cmakeInstance(), SLOT(setWarnUninitializedMode(bool))); - QObject::connect(this->WarnUnusedAction, SIGNAL(triggered(bool)), - this->CMakeThread->cmakeInstance(), - SLOT(setWarnUnusedMode(bool))); if (!this->SourceDirectory->text().isEmpty() || !this->BinaryDirectory->lineEdit()->text().isEmpty()) { diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h index d1e2035..eba0b1e 100644 --- a/Source/QtDialog/CMakeSetupDialog.h +++ b/Source/QtDialog/CMakeSetupDialog.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef CMakeSetupDialog_h -#define CMakeSetupDialog_h +#pragma once #include <memory> @@ -111,7 +110,6 @@ protected: QAction* ConfigureAction; QAction* GenerateAction; QAction* WarnUninitializedAction; - QAction* WarnUnusedAction; QAction* InstallForCommandLineAction; State CurrentState; @@ -147,5 +145,3 @@ protected: virtual void run(); std::unique_ptr<QCMake> CMakeInstance; }; - -#endif // CMakeSetupDialog_h diff --git a/Source/QtDialog/Compilers.h b/Source/QtDialog/Compilers.h index 931c935..5da0781 100644 --- a/Source/QtDialog/Compilers.h +++ b/Source/QtDialog/Compilers.h @@ -1,7 +1,6 @@ -#ifndef COMPILERS_HPP -#define COMPILERS_HPP +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -21,5 +20,3 @@ public: this->setupUi(this); } }; - -#endif diff --git a/Source/QtDialog/FirstConfigure.h b/Source/QtDialog/FirstConfigure.h index c26f489..4c757da 100644 --- a/Source/QtDialog/FirstConfigure.h +++ b/Source/QtDialog/FirstConfigure.h @@ -1,6 +1,5 @@ -#ifndef FirstConfigure_h -#define FirstConfigure_h +#pragma once #include <QWizard> #include <QWizardPage> @@ -201,5 +200,3 @@ protected: ToolchainCompilerSetup* mToolchainCompilerSetupPage; QString mDefaultGenerator; }; - -#endif // FirstConfigure_h diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 776af81..6090256 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -21,7 +21,6 @@ QCMake::QCMake(QObject* p) : QObject(p) { this->WarnUninitializedMode = false; - this->WarnUnusedMode = false; qRegisterMetaType<QCMakeProperty>(); qRegisterMetaType<QCMakePropertyList>(); @@ -170,7 +169,6 @@ void QCMake::configure() this->CMakeInstance->SetGeneratorToolset(this->Toolset.toLocal8Bit().data()); this->CMakeInstance->LoadCache(); this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode); - this->CMakeInstance->SetWarnUnused(this->WarnUnusedMode); this->CMakeInstance->PreLoadCMakeFiles(); InterruptFlag = 0; @@ -340,10 +338,10 @@ void QCMake::interrupt() bool QCMake::interruptCallback() { -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) - return this->InterruptFlag; -#else +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) return this->InterruptFlag.load(); +#else + return this->InterruptFlag.loadRelaxed(); #endif } @@ -478,11 +476,6 @@ void QCMake::setWarnUninitializedMode(bool value) this->WarnUninitializedMode = value; } -void QCMake::setWarnUnusedMode(bool value) -{ - this->WarnUnusedMode = value; -} - void QCMake::checkOpenPossible() { std::string data = this->BinaryDirectory.toLocal8Bit().data(); diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h index 110a971..e87660b 100644 --- a/Source/QtDialog/QCMake.h +++ b/Source/QtDialog/QCMake.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef QCMake_h -#define QCMake_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -114,8 +113,6 @@ public slots: void setDeprecatedWarningsAsErrors(bool value); /// set whether to run cmake with warnings about uninitialized variables void setWarnUninitializedMode(bool value); - /// set whether to run cmake with warnings about unused variables - void setWarnUnusedMode(bool value); /// check if project IDE open is possible and emit openPossible signal void checkOpenPossible(); @@ -175,8 +172,6 @@ protected: void stderrCallback(std::string const& msg); bool WarnUninitializedMode; - bool WarnUnusedMode; - bool WarnUnusedAllMode; QString SourceDirectory; QString BinaryDirectory; QString Generator; @@ -186,5 +181,3 @@ protected: QString CMakeExecutable; QAtomicInt InterruptFlag; }; - -#endif // QCMake_h diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx index 9b24fbd..3bf4409 100644 --- a/Source/QtDialog/QCMakeCacheView.cxx +++ b/Source/QtDialog/QCMakeCacheView.cxx @@ -155,11 +155,7 @@ QModelIndex QCMakeCacheView::moveCursor(CursorAction act, void QCMakeCacheView::setShowAdvanced(bool s) { -#if QT_VERSION >= 040300 - // new 4.3 API that needs to be called. what about an older Qt? this->SearchFilter->invalidate(); -#endif - this->AdvancedFilter->setShowAdvanced(s); } @@ -209,9 +205,7 @@ void QCMakeCacheModel::clear() void QCMakeCacheModel::setProperties(const QCMakePropertyList& props) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) this->beginResetModel(); -#endif QSet<QCMakeProperty> newProps; QSet<QCMakeProperty> newProps2; @@ -335,11 +329,7 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props) } this->blockSignals(b); -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) this->endResetModel(); -#else - this->reset(); -#endif } QCMakeCacheModel::ViewType QCMakeCacheModel::viewType() const @@ -349,9 +339,7 @@ QCMakeCacheModel::ViewType QCMakeCacheModel::viewType() const void QCMakeCacheModel::setViewType(QCMakeCacheModel::ViewType t) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) this->beginResetModel(); -#endif this->View = t; @@ -368,11 +356,7 @@ void QCMakeCacheModel::setViewType(QCMakeCacheModel::ViewType t) this->setProperties(oldProps); this->setProperties(props); this->blockSignals(b); -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) this->endResetModel(); -#else - this->reset(); -#endif } void QCMakeCacheModel::setPropertyData(const QModelIndex& idx1, @@ -498,8 +482,7 @@ QCMakePropertyList QCMakeCacheModel::properties() const // go to the next in the tree while (!idxs.isEmpty() && ( -#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && \ - QT_VERSION < QT_VERSION_CHECK(5, 1, 0) +#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0) (idxs.last().row() + 1) >= rowCount(idxs.last().parent()) || #endif !idxs.last().sibling(idxs.last().row() + 1, 0).isValid())) { @@ -659,20 +642,6 @@ bool QCMakeCacheModelDelegate::editorEvent(QEvent* e, return success; } -// Issue 205903 fixed in Qt 4.5.0. -// Can remove this function and FileDialogFlag when minimum Qt version is 4.5 -bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* evt) -{ - // workaround for what looks like a bug in Qt on macOS - // where it doesn't create a QWidget wrapper for the native file dialog - // so the Qt library ends up assuming the focus was lost to something else - - if (evt->type() == QEvent::FocusOut && this->FileDialogFlag) { - return false; - } - return QItemDelegate::eventFilter(object, evt); -} - void QCMakeCacheModelDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const diff --git a/Source/QtDialog/QCMakeCacheView.h b/Source/QtDialog/QCMakeCacheView.h index bea1965..836a939 100644 --- a/Source/QtDialog/QCMakeCacheView.h +++ b/Source/QtDialog/QCMakeCacheView.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef QCMakeCacheView_h -#define QCMakeCacheView_h +#pragma once #include "QCMake.h" #include <QItemDelegate> @@ -144,7 +143,6 @@ public: bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index); - bool eventFilter(QObject* object, QEvent* event); void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; QSize sizeHint(const QStyleOptionViewItem& option, @@ -165,5 +163,3 @@ protected: // properties changed by user via this delegate QSet<QCMakeProperty> mChanges; }; - -#endif diff --git a/Source/QtDialog/QCMakeWidgets.cxx b/Source/QtDialog/QCMakeWidgets.cxx index 332a770..d16ea58 100644 --- a/Source/QtDialog/QCMakeWidgets.cxx +++ b/Source/QtDialog/QCMakeWidgets.cxx @@ -4,9 +4,9 @@ #include <utility> -#include <QDirModel> #include <QFileDialog> #include <QFileInfo> +#include <QFileSystemModel> #include <QResizeEvent> #include <QToolButton> @@ -88,20 +88,20 @@ void QCMakePathEditor::chooseFile() } } -// use same QDirModel for all completers -static QDirModel* fileDirModel() +// use same QFileSystemModel for all completers +static QFileSystemModel* fileDirModel() { - static QDirModel* m = nullptr; + static QFileSystemModel* m = nullptr; if (!m) { - m = new QDirModel(); + m = new QFileSystemModel(); } return m; } -static QDirModel* pathDirModel() +static QFileSystemModel* pathDirModel() { - static QDirModel* m = nullptr; + static QFileSystemModel* m = nullptr; if (!m) { - m = new QDirModel(); + m = new QFileSystemModel(); m->setFilter(QDir::AllDirs | QDir::Drives | QDir::NoDotAndDotDot); } return m; @@ -110,7 +110,7 @@ static QDirModel* pathDirModel() QCMakeFileCompleter::QCMakeFileCompleter(QObject* o, bool dirs) : QCompleter(o) { - QDirModel* m = dirs ? pathDirModel() : fileDirModel(); + QFileSystemModel* m = dirs ? pathDirModel() : fileDirModel(); this->setModel(m); } diff --git a/Source/QtDialog/QCMakeWidgets.h b/Source/QtDialog/QCMakeWidgets.h index 5d2368e..9a2a27e 100644 --- a/Source/QtDialog/QCMakeWidgets.h +++ b/Source/QtDialog/QCMakeWidgets.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef QCMakeWidgets_h -#define QCMakeWidgets_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -77,5 +76,3 @@ public: } } }; - -#endif diff --git a/Source/QtDialog/RegexExplorer.h b/Source/QtDialog/RegexExplorer.h index 1a1d770..9a42320 100644 --- a/Source/QtDialog/RegexExplorer.h +++ b/Source/QtDialog/RegexExplorer.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef RegexExplorer_h -#define RegexExplorer_h +#pragma once #include <string> @@ -39,5 +38,3 @@ private: std::string m_regex; bool m_matched; }; - -#endif diff --git a/Source/QtDialog/WarningMessagesDialog.h b/Source/QtDialog/WarningMessagesDialog.h index f209dbd..bb01704 100644 --- a/Source/QtDialog/WarningMessagesDialog.h +++ b/Source/QtDialog/WarningMessagesDialog.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef WarningMessagesDialog_h -#define WarningMessagesDialog_h +#pragma once #include "QCMake.h" #include <QDialog> @@ -63,5 +62,3 @@ private: */ void setupSignals(); }; - -#endif /* MessageDialog_h */ diff --git a/Source/bindexplib.h b/Source/bindexplib.h index 538177d..bd1398f 100644 --- a/Source/bindexplib.h +++ b/Source/bindexplib.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef bindexplib_h -#define bindexplib_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -25,4 +24,3 @@ private: std::set<std::string> DataSymbols; std::string NmPath; }; -#endif diff --git a/Source/cmAddCompileDefinitionsCommand.h b/Source/cmAddCompileDefinitionsCommand.h index 4bd621c..29282d6 100644 --- a/Source/cmAddCompileDefinitionsCommand.h +++ b/Source/cmAddCompileDefinitionsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmAddCompileDefinitionsCommand_h -#define cmAddCompileDefinitionsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddCompileDefinitionsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAddCompileOptionsCommand.h b/Source/cmAddCompileOptionsCommand.h index b172412..076a427 100644 --- a/Source/cmAddCompileOptionsCommand.h +++ b/Source/cmAddCompileOptionsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmAddCompileOptionsCommand_h -#define cmAddCompileOptionsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddCompileOptionsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h index 4f8c58f..383d116 100644 --- a/Source/cmAddCustomCommandCommand.h +++ b/Source/cmAddCustomCommandCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmAddCustomCommandCommand_h -#define cmAddCustomCommandCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddCustomCommandCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAddCustomTargetCommand.h b/Source/cmAddCustomTargetCommand.h index e23ef9f..3b784cb 100644 --- a/Source/cmAddCustomTargetCommand.h +++ b/Source/cmAddCustomTargetCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmAddCustomTargetCommand_h -#define cmAddCustomTargetCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddCustomTargetCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAddDefinitionsCommand.h b/Source/cmAddDefinitionsCommand.h index a67f095..45b4554 100644 --- a/Source/cmAddDefinitionsCommand.h +++ b/Source/cmAddDefinitionsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmAddDefinitionsCommand_h -#define cmAddDefinitionsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddDefinitionsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAddDependenciesCommand.h b/Source/cmAddDependenciesCommand.h index 0c60e3a..a767550 100644 --- a/Source/cmAddDependenciesCommand.h +++ b/Source/cmAddDependenciesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmDependenciessCommand_h -#define cmDependenciessCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddDependenciesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h index f7bc273..032c14d 100644 --- a/Source/cmAddExecutableCommand.h +++ b/Source/cmAddExecutableCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExecutablesCommand_h -#define cmExecutablesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddExecutableCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index 3e5d764..f262fac 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddLibraryCommand.h" -#include <cmext/algorithm> - #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -111,20 +109,10 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, "INTERFACE library specified with conflicting ALIAS type."); return false; } - if (excludeFromAll) { - status.SetError( - "INTERFACE library may not be used with EXCLUDE_FROM_ALL."); - return false; - } ++s; type = cmStateEnums::INTERFACE_LIBRARY; haveSpecifiedType = true; } else if (*s == "EXCLUDE_FROM_ALL") { - if (type == cmStateEnums::INTERFACE_LIBRARY) { - status.SetError( - "INTERFACE library may not be used with EXCLUDE_FROM_ALL."); - return false; - } ++s; excludeFromAll = true; } else if (*s == "IMPORTED") { @@ -143,10 +131,6 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, } if (type == cmStateEnums::INTERFACE_LIBRARY) { - if (s != args.end()) { - status.SetError("INTERFACE library requires no source arguments."); - return false; - } if (importGlobal && !importTarget) { status.SetError( "INTERFACE library specified as GLOBAL, but not as IMPORTED."); @@ -302,8 +286,6 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, } } - std::vector<std::string> srclists; - if (type == cmStateEnums::INTERFACE_LIBRARY) { if (!cmGeneratorExpression::IsValidTargetName(libName) || libName.find("::") != std::string::npos) { @@ -311,14 +293,10 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, cmStrCat("Invalid name for INTERFACE library target: ", libName)); return false; } - - mf.AddLibrary(libName, type, srclists, excludeFromAll); - return true; } - cm::append(srclists, s, args.end()); - - mf.AddLibrary(libName, type, srclists, excludeFromAll); + std::vector<std::string> srcs(s, args.end()); + mf.AddLibrary(libName, type, srcs, excludeFromAll); return true; } diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h index 609449c..a4a0ea0 100644 --- a/Source/cmAddLibraryCommand.h +++ b/Source/cmAddLibraryCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLibrarysCommand_h -#define cmLibrarysCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddLibraryCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAddLinkOptionsCommand.h b/Source/cmAddLinkOptionsCommand.h index 466fc32..5c9d5e4 100644 --- a/Source/cmAddLinkOptionsCommand.h +++ b/Source/cmAddLinkOptionsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmAddLinkOptionsCommand_h -#define cmAddLinkOptionsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddLinkOptionsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAddSubDirectoryCommand.h b/Source/cmAddSubDirectoryCommand.h index 87da840..ece3b27 100644 --- a/Source/cmAddSubDirectoryCommand.h +++ b/Source/cmAddSubDirectoryCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmAddSubDirectoryCommand_h -#define cmAddSubDirectoryCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h index 5877547..8cba2b1 100644 --- a/Source/cmAddTestCommand.h +++ b/Source/cmAddTestCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmAddTestCommand_h -#define cmAddTestCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAddTestCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index c8e8dcb..87000da 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmAlgorithms_h -#define cmAlgorithms_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -143,5 +142,3 @@ typename Range::const_iterator cmFindNot(Range const& r, T const& t) { return std::find_if(r.begin(), r.end(), [&t](T const& i) { return i != t; }); } - -#endif diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h index b643bce..fff4556 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmArchiveWrite_h -#define cmArchiveWrite_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -180,5 +179,3 @@ private: cmArchiveWriteOptional<int> Permissions; cmArchiveWriteOptional<int> PermissionsMask; }; - -#endif diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h index 5d2dfa2..71ed844 100644 --- a/Source/cmArgumentParser.h +++ b/Source/cmArgumentParser.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmArgumentParser_h -#define cmArgumentParser_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -146,5 +145,3 @@ protected: private: ArgumentParser::ActionMap Bindings; }; - -#endif diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index d6f7500e..15edcc5 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -36,10 +36,7 @@ bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args, } // was the list already populated - const char* def = mf.GetDefinition(args[1]); - if (def) { - sourceListValue = def; - } + sourceListValue = mf.GetSafeDefinition(args[1]); std::vector<std::string> files; @@ -55,7 +52,7 @@ bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args, auto ext = cm::string_view(file).substr(dotpos + 1); // Process only source files auto cm = mf.GetCMakeInstance(); - if (dotpos > 0 && cm->IsSourceExtension(ext)) { + if (dotpos > 0 && cm->IsACLikeSourceExtension(ext)) { std::string fullname = cmStrCat(templateDirectory, '/', file); // add the file as a class file so // depends can be done diff --git a/Source/cmAuxSourceDirectoryCommand.h b/Source/cmAuxSourceDirectoryCommand.h index ae26092..29ee429 100644 --- a/Source/cmAuxSourceDirectoryCommand.h +++ b/Source/cmAuxSourceDirectoryCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmAuxSourceDirectoryCommand_h -#define cmAuxSourceDirectoryCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmBase32.h b/Source/cmBase32.h index d85198d..726f45d 100644 --- a/Source/cmBase32.h +++ b/Source/cmBase32.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBase32_h -#define cmBase32_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -29,5 +28,3 @@ public: std::string encodeString(const unsigned char* input, size_t len, bool padding = true); }; - -#endif diff --git a/Source/cmBinUtilsLinker.h b/Source/cmBinUtilsLinker.h index 78d517b..5330070 100644 --- a/Source/cmBinUtilsLinker.h +++ b/Source/cmBinUtilsLinker.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsLinker_h -#define cmBinUtilsLinker_h +#pragma once #include <string> @@ -26,5 +25,3 @@ protected: void SetError(const std::string& e); }; - -#endif // cmBinUtilsLinker_h diff --git a/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h index d514e7f..15216a4 100644 --- a/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h +++ b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h -#define cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h +#pragma once #include <string> #include <vector> @@ -26,5 +25,3 @@ protected: void SetError(const std::string& e); }; - -#endif // cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsLinuxELFLinker.h b/Source/cmBinUtilsLinuxELFLinker.h index b17df11..4e7e36d 100644 --- a/Source/cmBinUtilsLinuxELFLinker.h +++ b/Source/cmBinUtilsLinuxELFLinker.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsLinuxELFLinker_h -#define cmBinUtilsLinuxELFLinker_h +#pragma once #include <memory> #include <string> @@ -40,5 +39,3 @@ private: bool GetLDConfigPaths(); }; - -#endif // cmBinUtilsLinuxELFLinker_h diff --git a/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h index 969e4d4..def1dd0 100644 --- a/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h +++ b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsLinuxELFGetRuntimeCollectDependenciesTool_h -#define cmBinUtilsLinuxELFGetRuntimeCollectDependenciesTool_h +#pragma once #include <string> #include <vector> @@ -22,5 +21,3 @@ public: std::vector<std::string>& rpaths, std::vector<std::string>& runpaths) override; }; - -#endif // cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h index dbb2882..60d34aa 100644 --- a/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h +++ b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h -#define cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h +#pragma once #include <string> #include <vector> @@ -25,5 +24,3 @@ protected: void SetError(const std::string& error); }; - -#endif // cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsMacOSMachOLinker.h b/Source/cmBinUtilsMacOSMachOLinker.h index 4a24ea3..1c4a5fc 100644 --- a/Source/cmBinUtilsMacOSMachOLinker.h +++ b/Source/cmBinUtilsMacOSMachOLinker.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsMacOSMachOLinker_h -#define cmBinUtilsMacOSMachOLinker_h +#pragma once #include <memory> #include <string> @@ -55,5 +54,3 @@ private: std::vector<std::string> const& rpaths, std::string& path, bool& resolved); }; - -#endif // cmBinUtilsMacOSMachOLinker_h diff --git a/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h index 8ac7e18..9d17450 100644 --- a/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h +++ b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h -#define cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h +#pragma once #include <string> #include <vector> @@ -21,5 +20,3 @@ public: bool GetFileInfo(std::string const& file, std::vector<std::string>& libs, std::vector<std::string>& rpaths) override; }; - -#endif // cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h index eae22ea..8609479 100644 --- a/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h +++ b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h -#define cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h +#pragma once #include <string> #include <vector> @@ -21,5 +20,3 @@ public: bool GetFileInfo(const std::string& file, std::vector<std::string>& needed) override; }; - -#endif // cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h index e9e402b..da71aaa 100644 --- a/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h +++ b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h -#define cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h +#pragma once #include <string> #include <vector> @@ -24,5 +23,3 @@ protected: void SetError(const std::string& error); }; - -#endif // cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsWindowsPELinker.h b/Source/cmBinUtilsWindowsPELinker.h index a8bb596..6bb7875 100644 --- a/Source/cmBinUtilsWindowsPELinker.h +++ b/Source/cmBinUtilsWindowsPELinker.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsWindowsPELinker_h -#define cmBinUtilsWindowsPELinker_h +#pragma once #include <memory> #include <string> @@ -29,5 +28,3 @@ private: bool ResolveDependency(std::string const& name, std::string const& origin, std::string& path, bool& resolved); }; - -#endif // cmBinUtilsWindowsPELinker_h diff --git a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h index a67cb0c..fe89a2d 100644 --- a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h +++ b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h -#define cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h +#pragma once #include <string> #include <vector> @@ -21,5 +20,3 @@ public: bool GetFileInfo(const std::string& file, std::vector<std::string>& needed) override; }; - -#endif // cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h diff --git a/Source/cmBreakCommand.h b/Source/cmBreakCommand.h index e6ce6fe..6241867 100644 --- a/Source/cmBreakCommand.h +++ b/Source/cmBreakCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBreakCommand_h -#define cmBreakCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,5 +16,3 @@ class cmExecutionStatus; */ bool cmBreakCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index b82fb9a..2eaf315 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -6,6 +6,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -94,7 +95,7 @@ bool TwoArgsSignature(std::vector<std::string> const& args, cmMakefile& mf = status.GetMakefile(); std::string const& define = args[0]; - const char* cacheValue = mf.GetDefinition(define); + cmProp cacheValue = mf.GetDefinition(define); std::string configType; if (!cmSystemTools::GetEnv("CMAKE_CONFIG_TYPE", configType) || diff --git a/Source/cmBuildCommand.h b/Source/cmBuildCommand.h index 45aa71d..eafe185 100644 --- a/Source/cmBuildCommand.h +++ b/Source/cmBuildCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBuildCommand_h -#define cmBuildCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmBuildCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index ad4d665..f9b8f8f 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -8,6 +8,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -19,12 +20,12 @@ bool cmBuildNameCommand(std::vector<std::string> const& args, return false; } cmMakefile& mf = status.GetMakefile(); - const char* cacheValue = mf.GetDefinition(args[0]); + cmProp cacheValue = mf.GetDefinition(args[0]); if (cacheValue) { // do we need to correct the value? cmsys::RegularExpression reg("[()/]"); - if (reg.find(cacheValue)) { - std::string cv = cacheValue; + std::string cv = *cacheValue; + if (reg.find(cv)) { std::replace(cv.begin(), cv.end(), '/', '_'); std::replace(cv.begin(), cv.end(), '(', '_'); std::replace(cv.begin(), cv.end(), ')', '_'); diff --git a/Source/cmBuildNameCommand.h b/Source/cmBuildNameCommand.h index 37a7268..650dc74 100644 --- a/Source/cmBuildNameCommand.h +++ b/Source/cmBuildNameCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmBuildNameCommand_h -#define cmBuildNameCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmBuildNameCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmCLocaleEnvironmentScope.h b/Source/cmCLocaleEnvironmentScope.h index aa2827e..0919acc 100644 --- a/Source/cmCLocaleEnvironmentScope.h +++ b/Source/cmCLocaleEnvironmentScope.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCLocaleEnvironmentScope_h -#define cmCLocaleEnvironmentScope_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -25,5 +24,3 @@ private: using backup_map_t = std::map<std::string, std::string>; backup_map_t EnvironmentBackup; }; - -#endif diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h index 79e3f27..8a64f6a 100644 --- a/Source/cmCMakeHostSystemInformationCommand.h +++ b/Source/cmCMakeHostSystemInformationCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCMakeHostSystemInformationCommand_h -#define cmCMakeHostSystemInformationCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -18,5 +17,3 @@ class cmExecutionStatus; */ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmCMakeLanguageCommand.h b/Source/cmCMakeLanguageCommand.h index 7306515..d45003a 100644 --- a/Source/cmCMakeLanguageCommand.h +++ b/Source/cmCMakeLanguageCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCMakeLanguageCommand_h -#define cmCMakeLanguageCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -11,10 +10,8 @@ class cmExecutionStatus; struct cmListFileArgument; /** - * \brief Calls a scripted or build-in command + * \brief Calls a scripted or built-in command * */ bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmCMakeMinimumRequired.h b/Source/cmCMakeMinimumRequired.h index 53f78f6..712d6d6 100644 --- a/Source/cmCMakeMinimumRequired.h +++ b/Source/cmCMakeMinimumRequired.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCMakeMinimumRequired_h -#define cmCMakeMinimumRequired_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,5 +16,3 @@ class cmExecutionStatus; */ bool cmCMakeMinimumRequired(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmCMakePath.cxx b/Source/cmCMakePath.cxx new file mode 100644 index 0000000..b8215df --- /dev/null +++ b/Source/cmCMakePath.cxx @@ -0,0 +1,146 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmCMakePath.h" + +#include <string> + +#if defined(_WIN32) +# include <cstdlib> +#endif + +#include <cm/filesystem> +#include <cm/string_view> + +#if defined(_WIN32) +# include "cmStringAlgorithms.h" +#endif + +cmCMakePath& cmCMakePath::ReplaceWideExtension(cm::string_view extension) +{ + auto file = this->Path.filename().string(); + if (!file.empty() && file != "." && file != "..") { + auto pos = file.find('.', file[0] == '.' ? 1 : 0); + if (pos != std::string::npos) { + file.erase(pos); + } + } + if (!extension.empty()) { + if (extension[0] != '.') { + file += '.'; + } + file.append(std::string(extension)); + } + this->Path.replace_filename(file); + return *this; +} + +cmCMakePath cmCMakePath::GetWideExtension() const +{ + auto file = this->Path.filename().string(); + if (file.empty() || file == "." || file == "..") { + return cmCMakePath{}; + } + + auto pos = file.find('.', file[0] == '.' ? 1 : 0); + if (pos != std::string::npos) { + return cm::string_view(file.data() + pos, file.length() - pos); + } + + return cmCMakePath{}; +} + +cmCMakePath cmCMakePath::GetNarrowStem() const +{ + auto stem = this->Path.stem().string(); + if (!stem.empty()) { + auto pos = stem.find('.', stem[0] == '.' ? 1 : 0); + if (pos != std::string::npos) { + return stem.substr(0, pos); + } + } + return stem; +} + +cmCMakePath cmCMakePath::Absolute(const cm::filesystem::path& base) const +{ + if (this->Path.is_relative()) { + auto path = base; + path /= this->Path; + // filesystem::path::operator/= use preferred_separator ('\' on Windows) + // so converts back to '/' + return path.generic_string(); + } + return *this; +} + +bool cmCMakePath::IsPrefix(const cmCMakePath& path) const +{ + auto prefix_it = this->Path.begin(); + auto prefix_end = this->Path.end(); + auto path_it = path.Path.begin(); + auto path_end = path.Path.end(); + + while (prefix_it != prefix_end && path_it != path_end && + *prefix_it == *path_it) { + ++prefix_it; + ++path_it; + } + return prefix_it == prefix_end; +} + +std::string cmCMakePath::FormatPath(std::string path, format fmt) +{ +#if defined(_WIN32) + if (fmt == auto_format || fmt == native_format) { + auto prefix = path.substr(0, 4); + for (auto& c : prefix) { + if (c == '\\') { + c = '/'; + } + } + // remove Windows long filename marker + if (prefix == "//?/"_s) { + path.erase(0, 4); + } + if (cmHasPrefix(path, "UNC/"_s) || cmHasPrefix(path, "UNC\\"_s)) { + path.erase(0, 2); + path[0] = '/'; + } + } +#else + static_cast<void>(fmt); +#endif + return path; +} + +void cmCMakePath::GetNativePath(std::string& path) const +{ + cm::filesystem::path tmp(this->Path); + tmp.make_preferred(); + + path = tmp.string(); +} +void cmCMakePath::GetNativePath(std::wstring& path) const +{ + cm::filesystem::path tmp(this->Path); + tmp.make_preferred(); + + path = tmp.wstring(); + +#if defined(_WIN32) + // Windows long filename + static std::wstring UNC(L"\\\\?\\UNC"); + static std::wstring PREFIX(L"\\\\?\\"); + + if (this->IsAbsolute() && path.length() > _MAX_PATH - 12) { + if (this->HasRootName() && path[0] == L'\\') { + path = UNC + path.substr(1); + } else { + path = PREFIX + path; + } + } +#endif +} diff --git a/Source/cmCMakePath.h b/Source/cmCMakePath.h new file mode 100644 index 0000000..15aa30c --- /dev/null +++ b/Source/cmCMakePath.h @@ -0,0 +1,571 @@ +/* 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 <cstddef> +#include <string> +#include <utility> + +#include <cm/filesystem> +#include <cm/string_view> +#include <cm/type_traits> +#include <cmext/string_view> + +namespace detail { +#if defined(__SUNPRO_CC) && defined(__sparc) +// Oracle DeveloperStudio C++ compiler on Solaris/Sparc fails to compile +// the full 'is_pathable' and 'is_move_pathable' checks. We use it only to +// improve error messages via 'enable_if' when calling methods with incorrect +// types. Just pretend all types are allowed so we can at least compile valid +// code. +template <typename T> +struct is_pathable : std::true_type +{ +}; + +template <typename T> +struct is_move_pathable : std::true_type +{ +}; + +#else +template <typename T, typename = void> +struct is_pathable : std::false_type +{ +}; + +template <> +struct is_pathable<cm::filesystem::path> : std::true_type +{ +}; +template <> +struct is_pathable<std::string> : std::true_type +{ +}; +template <> +struct is_pathable<cm::string_view> : std::true_type +{ +}; +template <> +struct is_pathable<cm::static_string_view> : std::true_type +{ +}; +template <typename T> +struct is_pathable< + T, + cm::enable_if_t<std::is_same<char*, typename std::decay<T>::type>::value, + void>> + : cm::bool_constant<std::is_same<char*, typename std::decay<T>::type>::value> +{ +}; + +template <typename T> +struct is_move_pathable : std::false_type +{ +}; + +template <> +struct is_move_pathable<cm::filesystem::path> : std::true_type +{ +}; +template <> +struct is_move_pathable<std::string> : std::true_type +{ +}; +#endif +} + +class cmCMakePath +{ +private: + template <typename Source> + using enable_if_move_pathable = + cm::enable_if_t<detail::is_move_pathable<Source>::value, cmCMakePath&>; + + template <typename Source> + using enable_if_pathable = + cm::enable_if_t<detail::is_pathable<Source>::value, cmCMakePath&>; + +public: + using value_type = cm::filesystem::path::value_type; + using string_type = cm::filesystem::path::string_type; + + enum format : unsigned char + { + auto_format = + static_cast<unsigned char>(cm::filesystem::path::format::auto_format), + native_format = + static_cast<unsigned char>(cm::filesystem::path::format::native_format), + generic_format = + static_cast<unsigned char>(cm::filesystem::path::format::generic_format) + }; + + class iterator; + using const_iterator = iterator; + + cmCMakePath() noexcept = default; + + cmCMakePath(const cmCMakePath&) = default; + + cmCMakePath(cmCMakePath&& path) noexcept + : Path(std::forward<cm::filesystem::path>(path.Path)) + { + } + + cmCMakePath(cm::filesystem::path path) noexcept + : Path(std::move(path)) + { + } + cmCMakePath(cm::string_view source, format fmt = generic_format) noexcept + : Path(FormatPath(source, fmt)) + { + } + template <typename Source, typename = enable_if_move_pathable<Source>> + cmCMakePath(Source source, format fmt = generic_format) + : Path(FormatPath(std::move(source), fmt)) + { + } + + template <typename Source, typename = enable_if_move_pathable<Source>> + cmCMakePath& Assign(Source&& source) + { + this->Path = std::forward<Source>(source); + return *this; + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath& Assign(const Source& source) + { + this->Path = source; + return *this; + } + + cmCMakePath& operator=(const cmCMakePath& path) + { + if (this != &path) { + this->Path = path.Path; + } + return *this; + } + cmCMakePath& operator=(cmCMakePath&& path) noexcept + { + if (this != &path) { + this->Path = std::move(path.Path); + } + return *this; + } + template <typename Source, typename = enable_if_move_pathable<Source>> + cmCMakePath& operator=(Source&& source) + { + this->Assign(std::forward<Source>(source)); + return *this; + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath& operator=(const Source& source) + { + this->Assign(source); + return *this; + } + + // Concatenation + cmCMakePath& Append(const cmCMakePath& path) + { + return this->Append(path.Path); + } + cmCMakePath& Append(const cm::filesystem::path& path) + { + this->Path /= path; + // filesystem::path::append use preferred_separator ('\' on Windows) + // so convert back to '/' + this->Path = this->Path.generic_string(); + return *this; + } + + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath& Append(const Source& source) + { + return this->Append(cm::filesystem::path(source)); + } + + cmCMakePath& operator/=(const cmCMakePath& path) + { + return this->Append(path); + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath& operator/=(const Source& source) + { + return this->Append(source); + } + + cmCMakePath& Concat(const cmCMakePath& path) + { + this->Path += path.Path; + return *this; + } + cmCMakePath& Concat(cm::static_string_view source) + { + this->Path.concat(std::string(source)); + return *this; + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath& Concat(const Source& source) + { + this->Path.concat(source); + return *this; + } + + cmCMakePath& operator+=(const cmCMakePath& path) + { + return this->Concat(path); + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath& operator+=(const Source& source) + { + return this->Concat(source); + } + + // Manipulation + void Clear() noexcept { this->Path.clear(); } + + cmCMakePath& RemoveFileName() + { + this->Path.remove_filename(); + return *this; + } + + cmCMakePath& ReplaceFileName(const cmCMakePath& filename) + { + if (this->Path.has_filename()) { + this->Path.replace_filename(filename.Path); + } + return *this; + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath& ReplaceFileName(const Source& filename) + { + if (this->Path.has_filename()) { + this->Path.replace_filename(filename); + } + return *this; + } + + cmCMakePath& ReplaceExtension(const cmCMakePath& extension = cmCMakePath()) + { + this->Path.replace_extension(extension.Path); + return *this; + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath& ReplaceExtension(const Source& extension) + { + this->Path.replace_extension(extension); + return *this; + } + + cmCMakePath& ReplaceWideExtension( + const cmCMakePath& extension = cmCMakePath()) + { + return this->ReplaceWideExtension( + static_cast<cm::string_view>(extension.Path.string())); + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath& ReplaceWideExtension(const Source& extension) + { + return this->ReplaceWideExtension(cm::string_view(extension)); + } + cmCMakePath& ReplaceWideExtension(cm::string_view extension); + + cmCMakePath& RemoveExtension() + { + if (this->Path.has_extension()) { + this->ReplaceExtension(cm::string_view("")); + } + return *this; + } + + cmCMakePath& RemoveWideExtension() + { + if (this->Path.has_extension()) { + this->ReplaceWideExtension(cm::string_view("")); + } + return *this; + } + + void swap(cmCMakePath& other) noexcept { this->Path.swap(other.Path); } + + // Observers + std::string String() const { return this->Path.string(); } + std::wstring WString() const { return this->Path.wstring(); } + + string_type Native() const + { + string_type path; + this->GetNativePath(path); + + return path; + } + std::string NativeString() const + { + std::string path; + this->GetNativePath(path); + + return path; + } + std::wstring NativeWString() const + { + std::wstring path; + this->GetNativePath(path); + + return path; + } + std::string GenericString() const { return this->Path.generic_string(); } + std::wstring GenericWString() const { return this->Path.generic_wstring(); } + + // Decomposition + cmCMakePath GetRootName() const { return this->Path.root_name(); } + cmCMakePath GetRootDirectory() const { return this->Path.root_directory(); } + cmCMakePath GetRootPath() const { return this->Path.root_path(); } + cmCMakePath GetFileName() const { return this->Path.filename(); } + cmCMakePath GetExtension() const { return this->Path.extension(); } + cmCMakePath GetWideExtension() const; + cmCMakePath GetStem() const { return this->Path.stem(); } + cmCMakePath GetNarrowStem() const; + + cmCMakePath GetRelativePath() const { return this->Path.relative_path(); } + cmCMakePath GetParentPath() const { return this->Path.parent_path(); } + + // Generation + cmCMakePath Normal() const + { + auto path = this->Path.lexically_normal(); + // filesystem::path:lexically_normal use preferred_separator ('\') on + // Windows) so convert back to '/' + return path.generic_string(); + } + + cmCMakePath Relative(const cmCMakePath& base) const + { + return this->Relative(base.Path); + } + cmCMakePath Relative(const cm::filesystem::path& base) const + { + auto path = this->Path.lexically_relative(base); + // filesystem::path:lexically_relative use preferred_separator ('\') on + // Windows) so convert back to '/' + return path.generic_string(); + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath Relative(const Source& base) const + { + return this->Relative(cm::filesystem::path(base)); + } + + cmCMakePath Proximate(const cmCMakePath& base) const + { + return this->Proximate(base.Path); + } + cmCMakePath Proximate(const cm::filesystem::path& base) const + { + auto path = this->Path.lexically_proximate(base); + // filesystem::path::lexically_proximate use preferred_separator ('\') on + // Windows) so convert back to '/' + return path.generic_string(); + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath Proximate(const Source& base) const + { + return this->Proximate(cm::filesystem::path(base)); + } + + cmCMakePath Absolute(const cmCMakePath& base) const + { + return this->Absolute(base.Path); + } + template <typename Source, typename = enable_if_pathable<Source>> + cmCMakePath Absolute(const Source& base) const + { + return this->Absolute(cm::filesystem::path(base)); + } + cmCMakePath Absolute(const cm::filesystem::path& base) const; + + // Comparison + int Compare(const cmCMakePath& path) const noexcept + { + return this->Path.compare(path.Path); + } + + // Query + bool IsEmpty() const noexcept { return this->Path.empty(); } + + bool HasRootPath() const { return this->Path.has_root_path(); } + bool HasRootName() const { return this->Path.has_root_name(); } + bool HasRootDirectory() const { return this->Path.has_root_directory(); } + bool HasRelativePath() const { return this->Path.has_relative_path(); } + bool HasParentPath() const { return this->Path.has_parent_path(); } + bool HasFileName() const { return this->Path.has_filename(); } + bool HasStem() const { return this->Path.has_stem(); } + bool HasExtension() const { return this->Path.has_extension(); } + + bool IsAbsolute() const { return this->Path.is_absolute(); } + bool IsRelative() const { return this->Path.is_relative(); } + bool IsPrefix(const cmCMakePath& path) const; + + // Iterators + // ========= + inline iterator begin() const; + inline iterator end() const; + + // Non-members + // =========== + friend inline bool operator==(const cmCMakePath& lhs, + const cmCMakePath& rhs) noexcept + { + return lhs.Compare(rhs) == 0; + } + friend inline bool operator!=(const cmCMakePath& lhs, + const cmCMakePath& rhs) noexcept + { + return lhs.Compare(rhs) != 0; + } + + friend inline cmCMakePath operator/(const cmCMakePath& lhs, + const cmCMakePath& rhs) + { + cmCMakePath result(lhs); + result /= rhs; + + return result; + } + +private: + friend std::size_t hash_value(const cmCMakePath& path) noexcept; + + static std::string FormatPath(std::string path, format fmt = generic_format); + static std::string FormatPath(cm::string_view path, + format fmt = generic_format) + { + return FormatPath(std::string(path), fmt); + } + + void GetNativePath(std::string& path) const; + void GetNativePath(std::wstring& path) const; + + cm::filesystem::path Path; +}; + +class cmCMakePath::iterator +{ +public: + using iterator_category = cm::filesystem::path::iterator::iterator_category; + + using value_type = cmCMakePath; + using difference_type = cm::filesystem::path::iterator::difference_type; + using pointer = const cmCMakePath*; + using reference = const cmCMakePath&; + + iterator() = default; + + iterator(const iterator& other) + : Iterator(other.Iterator) + , Path(other.Path) + , PathElement(*this->Iterator) + { + } + + ~iterator() = default; + + iterator& operator=(const iterator& other) + { + if (this != &other) { + this->Iterator = other.Iterator; + this->Path = other.Path; + this->PathElement = *this->Iterator; + } + + return *this; + } + + reference operator*() const { return this->PathElement; } + + pointer operator->() const { return &this->PathElement; } + + iterator& operator++() + { + ++this->Iterator; + this->PathElement = *this->Iterator; + + return *this; + } + + iterator operator++(int) + { + iterator it(*this); + this->operator++(); + return it; + } + + iterator& operator--() + { + --this->Iterator; + this->PathElement = *this->Iterator; + + return *this; + } + + iterator operator--(int) + { + iterator it(*this); + this->operator--(); + return it; + } + +private: + friend class cmCMakePath; + friend bool operator==(const iterator&, const iterator&); + + iterator(const cmCMakePath* path, const cm::filesystem::path::iterator& it) + : Iterator(it) + , Path(path) + , PathElement(*this->Iterator) + { + } + + cm::filesystem::path::iterator Iterator; + const cmCMakePath* Path = nullptr; + cmCMakePath PathElement; +}; + +inline cmCMakePath::iterator cmCMakePath::begin() const +{ + return iterator(this, this->Path.begin()); +} +inline cmCMakePath::iterator cmCMakePath::end() const +{ + return iterator(this, this->Path.end()); +} + +// Non-member functions +// ==================== +inline bool operator==(const cmCMakePath::iterator& lhs, + const cmCMakePath::iterator& rhs) +{ + return lhs.Path == rhs.Path && lhs.Path != nullptr && + lhs.Iterator == rhs.Iterator; +} + +inline bool operator!=(const cmCMakePath::iterator& lhs, + const cmCMakePath::iterator& rhs) +{ + return !(lhs == rhs); +} + +inline void swap(cmCMakePath& lhs, cmCMakePath& rhs) noexcept +{ + lhs.swap(rhs); +} + +inline std::size_t hash_value(const cmCMakePath& path) noexcept +{ + return cm::filesystem::hash_value(path.Path); +} diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx new file mode 100644 index 0000000..720f582 --- /dev/null +++ b/Source/cmCMakePathCommand.cxx @@ -0,0 +1,1019 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCMakePathCommand.h" + +#include <algorithm> +#include <functional> +#include <iomanip> +#include <map> +#include <sstream> +#include <string> +#include <utility> +#include <vector> + +#include <cm/string_view> +#include <cmext/string_view> + +#include "cmArgumentParser.h" +#include "cmCMakePath.h" +#include "cmExecutionStatus.h" +#include "cmMakefile.h" +#include "cmRange.h" +#include "cmStringAlgorithms.h" +#include "cmSubcommandTable.h" +#include "cmSystemTools.h" + +namespace { +// Helper classes for argument parsing +template <typename Result> +class CMakePathArgumentParser : public cmArgumentParser<Result> +{ +public: + CMakePathArgumentParser() + : cmArgumentParser<Result>() + { + } + + template <typename T> + CMakePathArgumentParser& Bind(cm::static_string_view name, T Result::*member) + { + cmArgumentParser<Result>::Bind(name, member); + return *this; + } + + template <int Advance = 2> + Result Parse(std::vector<std::string> const& args, + std::vector<std::string>* keywordsMissingValue = nullptr, + std::vector<std::string>* parsedKeywords = nullptr) const + { + this->Inputs.clear(); + + return cmArgumentParser<Result>::Parse(cmMakeRange(args).advance(Advance), + &this->Inputs, keywordsMissingValue, + parsedKeywords); + } + + const std::vector<std::string>& GetInputs() const { return Inputs; } + +protected: + mutable std::vector<std::string> Inputs; +}; + +// OUTPUT_VARIABLE is expected +template <typename Result> +class ArgumentParserWithOutputVariable : public CMakePathArgumentParser<Result> +{ +public: + ArgumentParserWithOutputVariable() + : CMakePathArgumentParser<Result>() + { + this->Bind("OUTPUT_VARIABLE"_s, &Result::Output); + } + + template <typename T> + ArgumentParserWithOutputVariable& Bind(cm::static_string_view name, + T Result::*member) + { + cmArgumentParser<Result>::Bind(name, member); + return *this; + } + + template <int Advance = 2> + Result Parse(std::vector<std::string> const& args) const + { + this->KeywordsMissingValue.clear(); + this->ParsedKeywords.clear(); + + return CMakePathArgumentParser<Result>::template Parse<Advance>( + args, &this->KeywordsMissingValue, &this->ParsedKeywords); + } + + const std::vector<std::string>& GetKeywordsMissingValue() const + { + return this->KeywordsMissingValue; + } + const std::vector<std::string>& GetParsedKeywords() const + { + return this->ParsedKeywords; + } + + bool checkOutputVariable(const Result& arguments, + cmExecutionStatus& status) const + { + if (std::find(this->GetKeywordsMissingValue().begin(), + this->GetKeywordsMissingValue().end(), + "OUTPUT_VARIABLE"_s) != + this->GetKeywordsMissingValue().end()) { + status.SetError("OUTPUT_VARIABLE requires an argument."); + return false; + } + + if (std::find(this->GetParsedKeywords().begin(), + this->GetParsedKeywords().end(), + "OUTPUT_VARIABLE"_s) != this->GetParsedKeywords().end() && + arguments.Output.empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + return true; + } + +private: + mutable std::vector<std::string> KeywordsMissingValue; + mutable std::vector<std::string> ParsedKeywords; +}; + +struct OutputVariable +{ + std::string Output; +}; +// Usable when OUTPUT_VARIABLE is the only option +class OutputVariableParser + : public ArgumentParserWithOutputVariable<OutputVariable> +{ +}; + +struct NormalizeOption +{ + bool Normalize = false; +}; +// Usable when NORMALIZE is the only option +class NormalizeParser : public CMakePathArgumentParser<NormalizeOption> +{ +public: + NormalizeParser() { this->Bind("NORMALIZE"_s, &NormalizeOption::Normalize); } +}; + +// retrieve value of input path from specified variable +bool getInputPath(const std::string& arg, cmExecutionStatus& status, + std::string& path) +{ + auto def = status.GetMakefile().GetDefinition(arg); + if (def == nullptr) { + status.SetError("undefined variable for input path."); + return false; + } + + path = *def; + return true; +} + +bool HandleGetCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + static std::map<cm::string_view, + std::function<cmCMakePath(const cmCMakePath&, bool)>> const + actions{ { "ROOT_NAME"_s, + [](const cmCMakePath& path, bool) -> cmCMakePath { + return path.GetRootName(); + } }, + { "ROOT_DIRECTORY"_s, + [](const cmCMakePath& path, bool) -> cmCMakePath { + return path.GetRootDirectory(); + } }, + { "ROOT_PATH"_s, + [](const cmCMakePath& path, bool) -> cmCMakePath { + return path.GetRootPath(); + } }, + { "FILENAME"_s, + [](const cmCMakePath& path, bool) -> cmCMakePath { + return path.GetFileName(); + } }, + { "EXTENSION"_s, + [](const cmCMakePath& path, bool last_only) -> cmCMakePath { + if (last_only) { + return path.GetExtension(); + } + return path.GetWideExtension(); + } }, + { "STEM"_s, + [](const cmCMakePath& path, bool last_only) -> cmCMakePath { + if (last_only) { + return path.GetStem(); + } + return path.GetNarrowStem(); + } }, + { "RELATIVE_PATH"_s, + [](const cmCMakePath& path, bool) -> cmCMakePath { + return path.GetRelativePath(); + } }, + { "PARENT_PATH"_s, + [](const cmCMakePath& path, bool) -> cmCMakePath { + return path.GetParentPath(); + } } }; + + if (args.size() < 4) { + status.SetError("GET must be called with at least three arguments."); + return false; + } + + const auto& action = args[2]; + + if (actions.find(action) == actions.end()) { + status.SetError( + cmStrCat("GET called with an unknown action: ", action, ".")); + return false; + } + + struct Arguments + { + bool LastOnly = false; + }; + + CMakePathArgumentParser<Arguments> parser; + if ((action == "EXTENSION"_s || action == "STEM"_s)) { + parser.Bind("LAST_ONLY"_s, &Arguments::LastOnly); + } + + Arguments const arguments = parser.Parse<3>(args); + + if (parser.GetInputs().size() != 1) { + status.SetError("GET called with unexpected arguments."); + return false; + } + if (parser.GetInputs().front().empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + std::string path; + if (!getInputPath(args[1], status, path)) { + return false; + } + + auto result = actions.at(action)(path, arguments.LastOnly); + + status.GetMakefile().AddDefinition(parser.GetInputs().front(), + result.String()); + + return true; +} + +bool HandleAppendCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + static OutputVariableParser const parser{}; + + const auto arguments = parser.Parse(args); + + if (!parser.checkOutputVariable(arguments, status)) { + return false; + } + + cmCMakePath path(status.GetMakefile().GetSafeDefinition(args[1])); + for (const auto& input : parser.GetInputs()) { + path /= input; + } + + status.GetMakefile().AddDefinition( + arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + + return true; +} + +bool HandleConcatCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + static OutputVariableParser const parser{}; + + const auto arguments = parser.Parse(args); + + if (!parser.checkOutputVariable(arguments, status)) { + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + cmCMakePath path(inputPath); + for (const auto& input : parser.GetInputs()) { + path += input; + } + + status.GetMakefile().AddDefinition( + arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + + return true; +} + +bool HandleRemoveFilenameCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + static OutputVariableParser const parser{}; + + const auto arguments = parser.Parse(args); + + if (!parser.checkOutputVariable(arguments, status)) { + return false; + } + + if (!parser.GetInputs().empty()) { + status.SetError("REMOVE_FILENAME called with unexpected arguments."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + cmCMakePath path(inputPath); + path.RemoveFileName(); + + status.GetMakefile().AddDefinition( + arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + + return true; +} + +bool HandleReplaceFilenameCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + static OutputVariableParser const parser{}; + + const auto arguments = parser.Parse(args); + + if (!parser.checkOutputVariable(arguments, status)) { + return false; + } + + if (parser.GetInputs().size() > 1) { + status.SetError("REPLACE_FILENAME called with unexpected arguments."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + cmCMakePath path(inputPath); + path.ReplaceFileName( + parser.GetInputs().empty() ? "" : parser.GetInputs().front()); + + status.GetMakefile().AddDefinition( + arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + + return true; +} + +bool HandleRemoveExtensionCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + struct Arguments + { + std::string Output; + bool LastOnly = false; + }; + + static auto const parser = + ArgumentParserWithOutputVariable<Arguments>{}.Bind("LAST_ONLY"_s, + &Arguments::LastOnly); + + Arguments const arguments = parser.Parse(args); + + if (!parser.checkOutputVariable(arguments, status)) { + return false; + } + + if (!parser.GetInputs().empty()) { + status.SetError("REMOVE_EXTENSION called with unexpected arguments."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + cmCMakePath path(inputPath); + + if (arguments.LastOnly) { + path.RemoveExtension(); + } else { + path.RemoveWideExtension(); + } + + status.GetMakefile().AddDefinition( + arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + + return true; +} + +bool HandleReplaceExtensionCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + struct Arguments + { + std::string Output; + bool LastOnly = false; + }; + + static auto const parser = + ArgumentParserWithOutputVariable<Arguments>{}.Bind("LAST_ONLY"_s, + &Arguments::LastOnly); + + Arguments const arguments = parser.Parse(args); + + if (!parser.checkOutputVariable(arguments, status)) { + return false; + } + + if (parser.GetInputs().size() > 1) { + status.SetError("REPLACE_EXTENSION called with unexpected arguments."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + cmCMakePath path(inputPath); + cmCMakePath extension( + parser.GetInputs().empty() ? "" : parser.GetInputs().front()); + + if (arguments.LastOnly) { + path.ReplaceExtension(extension); + } else { + path.ReplaceWideExtension(extension); + } + + status.GetMakefile().AddDefinition( + arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + + return true; +} + +bool HandleNormalPathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + static OutputVariableParser const parser{}; + + const auto arguments = parser.Parse(args); + + if (!parser.checkOutputVariable(arguments, status)) { + return false; + } + + if (!parser.GetInputs().empty()) { + status.SetError("NORMAL_PATH called with unexpected arguments."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + auto path = cmCMakePath(inputPath).Normal(); + + status.GetMakefile().AddDefinition( + arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + + return true; +} + +bool HandleTransformPathCommand( + std::vector<std::string> const& args, cmExecutionStatus& status, + const std::function<cmCMakePath(const cmCMakePath&, + const std::string& base)>& transform, + bool normalizeOption = false) +{ + struct Arguments + { + std::string Output; + std::string BaseDirectory; + bool Normalize = false; + }; + + auto parser = ArgumentParserWithOutputVariable<Arguments>{}.Bind( + "BASE_DIRECTORY"_s, &Arguments::BaseDirectory); + if (normalizeOption) { + parser.Bind("NORMALIZE"_s, &Arguments::Normalize); + } + + Arguments arguments = parser.Parse(args); + + if (!parser.checkOutputVariable(arguments, status)) { + return false; + } + + if (!parser.GetInputs().empty()) { + status.SetError(cmStrCat(args[0], " called with unexpected arguments.")); + return false; + } + + if (std::find(parser.GetKeywordsMissingValue().begin(), + parser.GetKeywordsMissingValue().end(), "BASE_DIRECTORY"_s) != + parser.GetKeywordsMissingValue().end()) { + status.SetError("BASE_DIRECTORY requires an argument."); + return false; + } + + if (std::find(parser.GetParsedKeywords().begin(), + parser.GetParsedKeywords().end(), + "BASE_DIRECTORY"_s) == parser.GetParsedKeywords().end()) { + arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory(); + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + auto path = transform(cmCMakePath(inputPath), arguments.BaseDirectory); + if (arguments.Normalize) { + path = path.Normal(); + } + + status.GetMakefile().AddDefinition( + arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + + return true; +} + +bool HandleRelativePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleTransformPathCommand( + args, status, + [](const cmCMakePath& path, const std::string& base) -> cmCMakePath { + return path.Relative(base); + }); +} + +bool HandleProximatePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleTransformPathCommand( + args, status, + [](const cmCMakePath& path, const std::string& base) -> cmCMakePath { + return path.Proximate(base); + }); +} + +bool HandleAbsolutePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleTransformPathCommand( + args, status, + [](const cmCMakePath& path, const std::string& base) -> cmCMakePath { + return path.Absolute(base); + }, + true); +} + +bool HandleCMakePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() < 3 || args.size() > 4) { + status.SetError("CMAKE_PATH must be called with two or three arguments."); + return false; + } + + static NormalizeParser const parser; + + const auto arguments = parser.Parse(args); + + if (parser.GetInputs().size() != 1) { + status.SetError("CMAKE_PATH called with unexpected arguments."); + return false; + } + + if (args[1].empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + auto path = + cmCMakePath(parser.GetInputs().front(), cmCMakePath::native_format); + + if (arguments.Normalize) { + path = path.Normal(); + } + + status.GetMakefile().AddDefinition(args[1], path.GenericString()); + + return true; +} + +bool HandleNativePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() < 3 || args.size() > 4) { + status.SetError("NATIVE_PATH must be called with two or three arguments."); + return false; + } + + static NormalizeParser const parser; + + const auto arguments = parser.Parse(args); + + if (parser.GetInputs().size() != 1) { + status.SetError("NATIVE_PATH called with unexpected arguments."); + return false; + } + if (parser.GetInputs().front().empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + cmCMakePath path(inputPath); + if (arguments.Normalize) { + path = path.Normal(); + } + + status.GetMakefile().AddDefinition(parser.GetInputs().front(), + path.NativeString()); + + return true; +} + +bool HandleConvertCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + const auto pathSep = ";"_s; +#else + const auto pathSep = ":"_s; +#endif + const auto cmakePath = "TO_CMAKE_PATH_LIST"_s; + const auto nativePath = "TO_NATIVE_PATH_LIST"_s; + + if (args.size() < 4 || args.size() > 5) { + status.SetError("CONVERT must be called with three or four arguments."); + return false; + } + + const auto& action = args[2]; + + if (action != cmakePath && action != nativePath) { + status.SetError( + cmStrCat("CONVERT called with an unknown action: ", action, ".")); + return false; + } + + if (args[3].empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + static NormalizeParser const parser; + + const auto arguments = parser.Parse<4>(args); + + if (!parser.GetInputs().empty()) { + status.SetError("CONVERT called with unexpected arguments."); + return false; + } + + std::vector<std::string> paths; + + if (action == cmakePath) { + paths = cmSystemTools::SplitString(args[1], pathSep.front()); + } else { + cmExpandList(args[1], paths); + } + + for (auto& path : paths) { + auto p = cmCMakePath(path, + action == cmakePath ? cmCMakePath::native_format + : cmCMakePath::generic_format); + if (arguments.Normalize) { + p = p.Normal(); + } + if (action == cmakePath) { + path = p.GenericString(); + } else { + path = p.NativeString(); + } + } + + auto value = cmJoin(paths, action == cmakePath ? ";"_s : pathSep); + status.GetMakefile().AddDefinition(args[3], value); + + return true; +} + +bool HandleCompareCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() != 5) { + status.SetError("COMPARE must be called with four arguments."); + return false; + } + + static std::map<cm::string_view, + std::function<bool(const cmCMakePath&, + const cmCMakePath&)>> const operators{ + { "EQUAL"_s, + [](const cmCMakePath& path1, const cmCMakePath& path2) -> bool { + return path1 == path2; + } }, + { "NOT_EQUAL"_s, + [](const cmCMakePath& path1, const cmCMakePath& path2) -> bool { + return path1 != path2; + } } + }; + + const auto op = operators.find(args[2]); + if (op == operators.end()) { + status.SetError(cmStrCat( + "COMPARE called with an unknown comparison operator: ", args[2], ".")); + return false; + } + + if (args[4].empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + cmCMakePath path1(inputPath); + cmCMakePath path2(args[3]); + auto result = op->second(path1, path2); + + status.GetMakefile().AddDefinitionBool(args[4], result); + + return true; +} + +bool HandleHasItemCommand( + std::vector<std::string> const& args, cmExecutionStatus& status, + const std::function<bool(const cmCMakePath&)>& has_item) +{ + if (args.size() != 3) { + status.SetError( + cmStrCat(args.front(), " must be called with two arguments.")); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + if (args[2].empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + cmCMakePath path(inputPath); + auto result = has_item(path); + + status.GetMakefile().AddDefinitionBool(args[2], result); + + return true; +} + +bool HandleHasRootNameCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleHasItemCommand( + args, status, + [](const cmCMakePath& path) -> bool { return path.HasRootName(); }); +} + +bool HandleHasRootDirectoryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleHasItemCommand( + args, status, + [](const cmCMakePath& path) -> bool { return path.HasRootDirectory(); }); +} + +bool HandleHasRootPathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleHasItemCommand( + args, status, + [](const cmCMakePath& path) -> bool { return path.HasRootPath(); }); +} + +bool HandleHasFilenameCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleHasItemCommand( + args, status, + [](const cmCMakePath& path) -> bool { return path.HasFileName(); }); +} + +bool HandleHasExtensionCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleHasItemCommand( + args, status, + [](const cmCMakePath& path) -> bool { return path.HasExtension(); }); +} + +bool HandleHasStemCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleHasItemCommand( + args, status, + [](const cmCMakePath& path) -> bool { return path.HasStem(); }); +} + +bool HandleHasRelativePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleHasItemCommand( + args, status, + [](const cmCMakePath& path) -> bool { return path.HasRelativePath(); }); +} + +bool HandleHasParentPathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleHasItemCommand( + args, status, + [](const cmCMakePath& path) -> bool { return path.HasParentPath(); }); +} + +bool HandleIsAbsoluteCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() != 3) { + status.SetError("IS_ABSOLUTE must be called with two arguments."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + if (args[2].empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + bool isAbsolute = cmCMakePath(inputPath).IsAbsolute(); + + status.GetMakefile().AddDefinitionBool(args[2], isAbsolute); + + return true; +} + +bool HandleIsRelativeCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() != 3) { + status.SetError("IS_RELATIVE must be called with two arguments."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + if (args[2].empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + bool isRelative = cmCMakePath(inputPath).IsRelative(); + + status.GetMakefile().AddDefinitionBool(args[2], isRelative); + + return true; +} + +bool HandleIsPrefixCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() < 4 || args.size() > 5) { + status.SetError("IS_PREFIX must be called with three or four arguments."); + return false; + } + + static NormalizeParser const parser; + + const auto arguments = parser.Parse(args); + + if (parser.GetInputs().size() != 2) { + status.SetError("IS_PREFIX called with unexpected arguments."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + const auto& input = parser.GetInputs().front(); + const auto& output = parser.GetInputs().back(); + + if (output.empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + bool isPrefix; + if (arguments.Normalize) { + isPrefix = + cmCMakePath(inputPath).Normal().IsPrefix(cmCMakePath(input).Normal()); + } else { + isPrefix = cmCMakePath(inputPath).IsPrefix(input); + } + + status.GetMakefile().AddDefinitionBool(output, isPrefix); + + return true; +} + +bool HandleHashCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() < 3 || args.size() > 4) { + status.SetError("HASH must be called with two or three arguments."); + return false; + } + + static NormalizeParser const parser; + + const auto arguments = parser.Parse(args); + + if (parser.GetInputs().size() != 1) { + status.SetError("HASH called with unexpected arguments."); + return false; + } + + std::string inputPath; + if (!getInputPath(args[1], status, inputPath)) { + return false; + } + + const auto& output = parser.GetInputs().front(); + + if (output.empty()) { + status.SetError("Invalid name for output variable."); + return false; + } + + auto hash = hash_value(arguments.Normalize ? cmCMakePath(inputPath).Normal() + : cmCMakePath(inputPath)); + + std::ostringstream out; + out << std::setbase(16) << hash; + + status.GetMakefile().AddDefinition(output, out.str()); + + return true; +} +} // anonymous namespace + +bool cmCMakePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() < 2) { + status.SetError("must be called with at least two arguments."); + return false; + } + + static cmSubcommandTable const subcommand{ + { "GET"_s, HandleGetCommand }, + { "APPEND"_s, HandleAppendCommand }, + { "CONCAT"_s, HandleConcatCommand }, + { "REMOVE_FILENAME"_s, HandleRemoveFilenameCommand }, + { "REPLACE_FILENAME"_s, HandleReplaceFilenameCommand }, + { "REMOVE_EXTENSION"_s, HandleRemoveExtensionCommand }, + { "REPLACE_EXTENSION"_s, HandleReplaceExtensionCommand }, + { "NORMAL_PATH"_s, HandleNormalPathCommand }, + { "RELATIVE_PATH"_s, HandleRelativePathCommand }, + { "PROXIMATE_PATH"_s, HandleProximatePathCommand }, + { "ABSOLUTE_PATH"_s, HandleAbsolutePathCommand }, + { "CMAKE_PATH"_s, HandleCMakePathCommand }, + { "NATIVE_PATH"_s, HandleNativePathCommand }, + { "CONVERT"_s, HandleConvertCommand }, + { "COMPARE"_s, HandleCompareCommand }, + { "HAS_ROOT_NAME"_s, HandleHasRootNameCommand }, + { "HAS_ROOT_DIRECTORY"_s, HandleHasRootDirectoryCommand }, + { "HAS_ROOT_PATH"_s, HandleHasRootPathCommand }, + { "HAS_FILENAME"_s, HandleHasFilenameCommand }, + { "HAS_EXTENSION"_s, HandleHasExtensionCommand }, + { "HAS_STEM"_s, HandleHasStemCommand }, + { "HAS_RELATIVE_PATH"_s, HandleHasRelativePathCommand }, + { "HAS_PARENT_PATH"_s, HandleHasParentPathCommand }, + { "IS_ABSOLUTE"_s, HandleIsAbsoluteCommand }, + { "IS_RELATIVE"_s, HandleIsRelativeCommand }, + { "IS_PREFIX"_s, HandleIsPrefixCommand }, + { "HASH"_s, HandleHashCommand } + }; + + return subcommand(args[0], args, status); +} diff --git a/Source/cmCMakePathCommand.h b/Source/cmCMakePathCommand.h new file mode 100644 index 0000000..49e9380 --- /dev/null +++ b/Source/cmCMakePathCommand.h @@ -0,0 +1,14 @@ +/* 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 <vector> + +class cmExecutionStatus; + +bool cmCMakePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); diff --git a/Source/cmCMakePolicyCommand.h b/Source/cmCMakePolicyCommand.h index ba9397d..7346b66 100644 --- a/Source/cmCMakePolicyCommand.h +++ b/Source/cmCMakePolicyCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCMakePolicyCommand_h -#define cmCMakePolicyCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -18,5 +17,3 @@ class cmExecutionStatus; */ bool cmCMakePolicyCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmCPackPropertiesGenerator.h b/Source/cmCPackPropertiesGenerator.h index 8339238..63c469a 100644 --- a/Source/cmCPackPropertiesGenerator.h +++ b/Source/cmCPackPropertiesGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCPackPropertiesGenerator_h -#define cmCPackPropertiesGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -36,5 +35,3 @@ protected: cmLocalGenerator* LG; cmInstalledFile const& InstalledFile; }; - -#endif diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 697d435..ee2960b 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -140,7 +140,7 @@ const char* CCONV cmGetCurrentOutputDirectory(void* arg) const char* CCONV cmGetDefinition(void* arg, const char* def) { cmMakefile* mf = static_cast<cmMakefile*>(arg); - return mf->GetDefinition(def); + return cmToCStr(mf->GetDefinition(def)); } int CCONV cmIsOn(void* arg, const char* name) @@ -581,13 +581,13 @@ const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop) cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); if (cmSourceFile* rsf = sf->RealSourceFile) { cmProp p = rsf->GetProperty(prop); - return p ? p->c_str() : nullptr; + return cmToCStr(p); } if (!strcmp(prop, "LOCATION")) { return sf->FullPath.c_str(); } cmProp retVal = sf->Properties.GetPropertyValue(prop); - return retVal ? retVal->c_str() : nullptr; + return cmToCStr(retVal); } int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop) diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index bca7540..8cf5ae9 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -394,7 +394,7 @@ bool cmCTest::ShouldCompressTestOutput() return this->Impl->CompressTestOutput; } -cmCTest::Part cmCTest::GetPartFromName(const char* name) +cmCTest::Part cmCTest::GetPartFromName(const std::string& name) { // Look up by lower-case to make names case-insensitive. std::string lower_name = cmSystemTools::LowerCase(name); @@ -458,8 +458,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) cm.GetCurrentSnapshot().SetDefaultDefinitions(); cmGlobalGenerator gg(&cm); cmMakefile mf(&gg, cm.GetCurrentSnapshot()); - if (!this->ReadCustomConfigurationFileTree(this->Impl->BinaryDir.c_str(), - &mf)) { + if (!this->ReadCustomConfigurationFileTree(this->Impl->BinaryDir, &mf)) { cmCTestOptionalLog( this, DEBUG, "Cannot find custom configuration file tree" << std::endl, quiet); @@ -523,7 +522,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) std::string model; if (cmSystemTools::GetLineFromStream(tfin, model) && !this->Impl->Parts[PartStart] && !command) { - this->Impl->TestModel = GetTestModelFromString(model.c_str()); + this->Impl->TestModel = GetTestModelFromString(model); } tfin.close(); } @@ -579,7 +578,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) cmSystemTools::GetLineFromStream(tfin, tag); cmSystemTools::GetLineFromStream(tfin, group); if (cmSystemTools::GetLineFromStream(tfin, modelStr)) { - model = GetTestModelFromString(modelStr.c_str()); + model = GetTestModelFromString(modelStr); } tfin.close(); } @@ -705,8 +704,7 @@ bool cmCTest::UpdateCTestConfiguration() if (!cmSystemTools::FileExists(fileName)) { // No need to exit if we are not producing XML if (this->Impl->ProduceXML) { - cmCTestLog(this, ERROR_MESSAGE, - "Cannot find file: " << fileName << std::endl); + cmCTestLog(this, WARNING, "Cannot find file: " << fileName << std::endl); return false; } } else { @@ -793,7 +791,7 @@ int cmCTest::GetTestModel() const return this->Impl->TestModel; } -bool cmCTest::SetTest(const char* ttype, bool report) +bool cmCTest::SetTest(const std::string& ttype, bool report) { if (cmSystemTools::LowerCase(ttype) == "all") { for (Part p = PartStart; p != PartCount; p = Part(p + 1)) { @@ -841,6 +839,7 @@ bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name, } } std::string filename = testingDir + "/" + name; + stream.SetTempExt("tmp"); stream.Open(filename); if (!stream) { cmCTestLog(this, ERROR_MESSAGE, @@ -855,7 +854,7 @@ bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name, return true; } -bool cmCTest::AddIfExists(Part part, const char* file) +bool cmCTest::AddIfExists(Part part, const std::string& file) { if (this->CTestFileExists(file)) { this->AddSubmitFile(part, file); @@ -1007,7 +1006,7 @@ int cmCTest::ProcessSteps() if (this->Impl->Parts[PartNotes]) { this->UpdateCTestConfiguration(); if (!this->Impl->NotesFiles.empty()) { - this->GenerateNotesFile(this->Impl->NotesFiles.c_str()); + this->GenerateNotesFile(this->Impl->NotesFiles); } } if (this->Impl->Parts[PartSubmit]) { @@ -1036,9 +1035,9 @@ std::string cmCTest::GetTestModelString() return "Experimental"; } -int cmCTest::GetTestModelFromString(const char* str) +int cmCTest::GetTestModelFromString(const std::string& str) { - if (!str) { + if (str.empty()) { return cmCTest::EXPERIMENTAL; } std::string rstr = cmSystemTools::LowerCase(str); @@ -1564,9 +1563,9 @@ int cmCTest::GenerateNotesFile(std::vector<std::string> const& files) return 0; } -int cmCTest::GenerateNotesFile(const char* cfiles) +int cmCTest::GenerateNotesFile(const std::string& cfiles) { - if (!cfiles) { + if (cfiles.empty()) { return 1; } @@ -1649,14 +1648,14 @@ bool cmCTest::SubmitExtraFiles(std::vector<std::string> const& files) << std::endl;); return false; } - this->AddSubmitFile(PartExtraFiles, file.c_str()); + this->AddSubmitFile(PartExtraFiles, file); } return true; } -bool cmCTest::SubmitExtraFiles(const char* cfiles) +bool cmCTest::SubmitExtraFiles(const std::string& cfiles) { - if (!cfiles) { + if (cfiles.empty()) { return true; } @@ -1940,7 +1939,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, else if (this->CheckArgument(arg, "-C"_s, "--build-config") && i < args.size() - 1) { i++; - this->SetConfigType(args[i].c_str()); + this->SetConfigType(args[i]); } else if (this->CheckArgument(arg, "--debug"_s)) { @@ -2015,7 +2014,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, else if (this->CheckArgument(arg, "-O"_s, "--output-log") && i < args.size() - 1) { i++; - this->SetOutputLogFileName(args[i].c_str()); + this->SetOutputLogFileName(args[i]); } else if (this->CheckArgument(arg, "--tomorrow-tag"_s)) { @@ -2047,7 +2046,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, this->Impl->ProduceXML = true; this->SetTest("Notes"); i++; - this->SetNotesFiles(args[i].c_str()); + this->SetNotesFiles(args[i]); return true; } @@ -2304,7 +2303,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) this->Impl->ProduceXML = true; this->SetTest("Submit"); i++; - if (!this->SubmitExtraFiles(args[i].c_str())) { + if (!this->SubmitExtraFiles(args[i])) { return 0; } } @@ -2375,7 +2374,7 @@ bool cmCTest::HandleTestActionArgument(const char* ctestExec, size_t& i, (i < args.size() - 1)) { this->Impl->ProduceXML = true; i++; - if (!this->SetTest(args[i].c_str(), false)) { + if (!this->SetTest(args[i], false)) { success = false; cmCTestLog(this, ERROR_MESSAGE, "CTest -T called with incorrect option: " << args[i] @@ -2490,11 +2489,8 @@ int cmCTest::RunCMakeAndTest(std::string* output) return retv; } -void cmCTest::SetNotesFiles(const char* notes) +void cmCTest::SetNotesFiles(const std::string& notes) { - if (!notes) { - return; - } this->Impl->NotesFiles = notes; } @@ -2560,7 +2556,8 @@ void cmCTest::SetScheduleType(std::string const& type) this->Impl->ScheduleType = type; } -int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf) +int cmCTest::ReadCustomConfigurationFileTree(const std::string& dir, + cmMakefile* mf) { bool found = false; cmCTestLog(this, DEBUG, @@ -2623,14 +2620,14 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf) void cmCTest::PopulateCustomVector(cmMakefile* mf, const std::string& def, std::vector<std::string>& vec) { - const char* dval = mf->GetDefinition(def); + cmProp dval = mf->GetDefinition(def); if (!dval) { return; } cmCTestLog(this, DEBUG, "PopulateCustomVector: " << def << std::endl); vec.clear(); - cmExpandList(dval, vec); + cmExpandList(*dval, vec); for (std::string const& it : vec) { cmCTestLog(this, DEBUG, " -- " << it << std::endl); @@ -2640,14 +2637,14 @@ void cmCTest::PopulateCustomVector(cmMakefile* mf, const std::string& def, void cmCTest::PopulateCustomInteger(cmMakefile* mf, const std::string& def, int& val) { - const char* dval = mf->GetDefinition(def); + cmProp dval = mf->GetDefinition(def); if (!dval) { return; } - val = atoi(dval); + val = atoi(dval->c_str()); } -std::string cmCTest::GetShortPathToFile(const char* cfname) +std::string cmCTest::GetShortPathToFile(const std::string& cfname) { const std::string& sourceDir = cmSystemTools::CollapseFullPath( this->GetCTestConfiguration("SourceDirectory")); @@ -2711,18 +2708,17 @@ void cmCTest::EmptyCTestConfiguration() this->Impl->CTestConfiguration.clear(); } -void cmCTest::SetCTestConfiguration(const char* name, const char* value, +void cmCTest::SetCTestConfiguration(const char* name, const std::string& value, bool suppress) { cmCTestOptionalLog(this, HANDLER_VERBOSE_OUTPUT, - "SetCTestConfiguration:" - << name << ":" << (value ? value : "(null)") << "\n", + "SetCTestConfiguration:" << name << ":" << value << "\n", suppress); if (!name) { return; } - if (!value) { + if (value.empty()) { this->Impl->CTestConfiguration.erase(name); return; } @@ -2927,7 +2923,7 @@ std::string cmCTest::GetBuildID() const return this->Impl->BuildID; } -void cmCTest::AddSubmitFile(Part part, const char* name) +void cmCTest::AddSubmitFile(Part part, const std::string& name) { this->Impl->Parts[part].SubmitFiles.emplace_back(name); } @@ -2963,9 +2959,9 @@ void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr) this->Impl->CTestConfigurationOverwrites[key] = value; } -void cmCTest::SetConfigType(const char* ct) +void cmCTest::SetConfigType(const std::string& ct) { - this->Impl->ConfigType = ct ? ct : ""; + this->Impl->ConfigType = ct; cmSystemTools::ReplaceString(this->Impl->ConfigType, ".\\", ""); std::string confTypeEnv = "CMAKE_CONFIG_TYPE=" + this->Impl->ConfigType; cmSystemTools::PutEnv(confTypeEnv); @@ -2975,8 +2971,7 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable( cmMakefile* mf, const char* dconfig, const std::string& cmake_var, bool suppress) { - const char* ctvar; - ctvar = mf->GetDefinition(cmake_var); + cmProp ctvar = mf->GetDefinition(cmake_var); if (!ctvar) { return false; } @@ -2984,7 +2979,7 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable( "SetCTestConfigurationFromCMakeVariable:" << dconfig << ":" << cmake_var << std::endl, suppress); - this->SetCTestConfiguration(dconfig, ctvar, suppress); + this->SetCTestConfiguration(dconfig, *ctvar, suppress); return true; } @@ -3085,9 +3080,9 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args, return result; } -void cmCTest::SetOutputLogFileName(const char* name) +void cmCTest::SetOutputLogFileName(const std::string& name) { - if (name) { + if (!name.empty()) { this->Impl->OutputLogFile = cm::make_unique<cmGeneratedFileStream>(name); } else { this->Impl->OutputLogFile.reset(); diff --git a/Source/cmCTest.h b/Source/cmCTest.h index a39b8fe..e12f8b0 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCTest_h -#define cmCTest_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -64,7 +63,7 @@ public: /** Get a testing part id from its string name. Returns PartCount if the string does not name a valid part. */ - Part GetPartFromName(const char* name); + Part GetPartFromName(const std::string& name); /** Process Command line arguments */ int Run(std::vector<std::string>&, std::string* output = nullptr); @@ -127,12 +126,12 @@ public: * Check if CTest file exists */ bool CTestFileExists(const std::string& filename); - bool AddIfExists(Part part, const char* file); + bool AddIfExists(Part part, const std::string& file); /** * Set the cmake test */ - bool SetTest(const char*, bool report = true); + bool SetTest(const std::string&, bool report = true); /** * Set the cmake test mode (experimental, nightly, continuous). @@ -141,11 +140,11 @@ public: int GetTestModel() const; std::string GetTestModelString(); - static int GetTestModelFromString(const char* str); + static int GetTestModelFromString(const std::string& str); static std::string CleanString(const std::string& str, std::string::size_type spos = 0); std::string GetCTestConfiguration(const std::string& name); - void SetCTestConfiguration(const char* name, const char* value, + void SetCTestConfiguration(const char* name, const std::string& value, bool suppress = false); void EmptyCTestConfiguration(); @@ -161,7 +160,7 @@ public: cmCTest& operator=(const cmCTest&) = delete; /** Set the notes files to be created. */ - void SetNotesFiles(const char* notes); + void SetNotesFiles(const std::string& notes); void PopulateCustomVector(cmMakefile* mf, const std::string& definition, std::vector<std::string>& vec); @@ -272,7 +271,7 @@ public: * This means if the file is in binary or * source directory, it will become /.../relative/path/to/file */ - std::string GetShortPathToFile(const char* fname); + std::string GetShortPathToFile(const std::string& fname); enum { @@ -354,14 +353,14 @@ public: int GenerateDoneFile(); /** Submit extra files to the server */ - bool SubmitExtraFiles(const char* files); + bool SubmitExtraFiles(const std::string& files); bool SubmitExtraFiles(std::vector<std::string> const& files); /** Set the output log file name */ - void SetOutputLogFileName(const char* name); + void SetOutputLogFileName(const std::string& name); /** Set the visual studio or Xcode config type */ - void SetConfigType(const char* ct); + void SetConfigType(const std::string& ct); /** Various log types */ enum @@ -399,14 +398,14 @@ public: std::string GetBuildID() const; /** Add file to be submitted */ - void AddSubmitFile(Part part, const char* name); + void AddSubmitFile(Part part, const std::string& name); std::vector<std::string> const& GetSubmitFiles(Part part) const; void ClearSubmitFiles(Part part); /** * Read the custom configuration files and apply them to the current ctest */ - int ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf); + int ReadCustomConfigurationFileTree(const std::string& dir, cmMakefile* mf); std::vector<std::string>& GetInitialCommandLineArguments(); @@ -462,7 +461,7 @@ public: void SetRunCurrentScript(bool value); private: - int GenerateNotesFile(const char* files); + int GenerateNotesFile(const std::string& files); void BlockTestErrorDiagnostics(); @@ -571,5 +570,3 @@ inline std::ostream& operator<<(std::ostream& os, const cmCTestLogWrite& c) (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__, \ cmCTestLog_msg.str().c_str(), suppress); \ } while (false) - -#endif diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 35bd681..95686ea 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -578,10 +578,7 @@ cmProp cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const bool cmCacheManager::CacheEntry::GetPropertyAsBool( const std::string& prop) const { - if (cmProp value = this->GetProperty(prop)) { - return cmIsOn(*value); - } - return false; + return cmIsOn(this->GetProperty(prop)); } void cmCacheManager::CacheEntry::SetProperty(const std::string& prop, diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index f036258..20d49a8 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCacheManager_h -#define cmCacheManager_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -210,5 +209,3 @@ private: unsigned int CacheMajorVersion = 0; unsigned int CacheMinorVersion = 0; }; - -#endif diff --git a/Source/cmCallVisualStudioMacro.h b/Source/cmCallVisualStudioMacro.h index 9b5b3a8..795b863 100644 --- a/Source/cmCallVisualStudioMacro.h +++ b/Source/cmCallVisualStudioMacro.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCallVisualStudioMacro_h -#define cmCallVisualStudioMacro_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -32,5 +31,3 @@ public: protected: private: }; - -#endif diff --git a/Source/cmCheckCustomOutputs.h b/Source/cmCheckCustomOutputs.h index 9f33d16..2752ed4 100644 --- a/Source/cmCheckCustomOutputs.h +++ b/Source/cmCheckCustomOutputs.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCheckCustomOutputs_h -#define cmCheckCustomOutputs_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -14,5 +13,3 @@ class cmExecutionStatus; bool cmCheckCustomOutputs(const std::vector<std::string>& outputs, cm::string_view keyword, cmExecutionStatus& status); - -#endif diff --git a/Source/cmCommand.h b/Source/cmCommand.h index bcb178d..68c56d9 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCommand_h -#define cmCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -96,5 +95,3 @@ public: private: std::unique_ptr<cmCommand> Command; }; - -#endif diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index 87eb91c..e3d014e 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -93,7 +93,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) if (this->FileLine >= 0 && strcmp(var, "CMAKE_CURRENT_LIST_LINE") == 0) { return this->AddString(std::to_string(this->FileLine)); } - const char* value = this->Makefile->GetDefinition(var); + cmProp value = this->Makefile->GetDefinition(var); if (!value) { this->Makefile->MaybeWarnUninitialized(var, this->FileName); if (!this->RemoveEmpty) { @@ -101,9 +101,9 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) } } if (this->EscapeQuotes && value) { - return this->AddString(cmEscapeQuotes(value)); + return this->AddString(cmEscapeQuotes(*value)); } - return this->AddString(value ? value : ""); + return this->AddString(cmToCStrSafe(value)); } const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var) @@ -205,23 +205,24 @@ bool cmCommandArgumentParserHelper::HandleEscapeSymbol( void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes); -int cmCommandArgumentParserHelper::ParseString(const char* str, int verb) +int cmCommandArgumentParserHelper::ParseString(std::string const& str, + int verb) { - if (!str) { + if (str.empty()) { return 0; } + this->InputSize = str.size(); this->Verbose = verb; - this->InputBuffer = str; - this->InputBufferPos = 0; - this->CurrentLine = 0; this->Result.clear(); yyscan_t yyscanner; cmCommandArgument_yylex_init(&yyscanner); + auto scanBuf = cmCommandArgument_yy_scan_string(str.c_str(), yyscanner); cmCommandArgument_yyset_extra(this, yyscanner); cmCommandArgument_SetupEscapes(yyscanner, this->NoEscapeMode); int res = cmCommandArgument_yyparse(yyscanner); + cmCommandArgument_yy_delete_buffer(scanBuf, yyscanner); cmCommandArgument_yylex_destroy(yyscanner); if (res != 0) { return 0; @@ -241,25 +242,14 @@ void cmCommandArgumentParserHelper::CleanupParser() this->Variables.clear(); } -int cmCommandArgumentParserHelper::LexInput(char* buf, int maxlen) +void cmCommandArgumentParserHelper::Error(const char* str) { - if (maxlen < 1) { - return 0; + auto pos = this->InputBufferPos; + auto const isEof = (this->InputSize < this->InputBufferPos); + if (!isEof) { + pos -= this->LastTokenLength; } - if (this->InputBufferPos < this->InputBuffer.size()) { - buf[0] = this->InputBuffer[this->InputBufferPos++]; - if (buf[0] == '\n') { - this->CurrentLine++; - } - return (1); - } - buf[0] = '\n'; - return (0); -} -void cmCommandArgumentParserHelper::Error(const char* str) -{ - unsigned long pos = static_cast<unsigned long>(this->InputBufferPos); std::ostringstream ostr; ostr << str << " (" << pos << ")"; this->SetError(ostr.str()); @@ -286,3 +276,9 @@ void cmCommandArgumentParserHelper::SetError(std::string const& msg) this->ErrorString = msg; } } + +void cmCommandArgumentParserHelper::UpdateInputPosition(int const tokenLength) +{ + this->InputBufferPos += tokenLength; + this->LastTokenLength = tokenLength; +} diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h index b46edcb..f79ca2c 100644 --- a/Source/cmCommandArgumentParserHelper.h +++ b/Source/cmCommandArgumentParserHelper.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCommandArgumentParserHelper_h -#define cmCommandArgumentParserHelper_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -26,7 +25,7 @@ public: cmCommandArgumentParserHelper& operator=( cmCommandArgumentParserHelper const&) = delete; - int ParseString(const char* str, int verb); + int ParseString(std::string const& str, int verb); // For the lexer: void AllocateParserType(cmCommandArgumentParserHelper::ParserType* pt, @@ -34,7 +33,6 @@ public: bool HandleEscapeSymbol(cmCommandArgumentParserHelper::ParserType* pt, char symbol); - int LexInput(char* buf, int maxlen); void Error(const char* str); // For yacc @@ -47,6 +45,8 @@ public: void SetMakefile(const cmMakefile* mf); + void UpdateInputPosition(int tokenLength); + std::string& GetResult() { return this->Result; } void SetLineFile(long line, const char* file); @@ -58,8 +58,9 @@ public: const char* GetError() { return this->ErrorString.c_str(); } private: - std::string::size_type InputBufferPos; - std::string InputBuffer; + std::string::size_type InputBufferPos{ 1 }; + std::string::size_type LastTokenLength{}; + std::string::size_type InputSize{}; std::vector<char> OutputBuffer; void Print(const char* place, const char* str); @@ -76,7 +77,6 @@ private: std::string ErrorString; const char* FileName; long FileLine; - int CurrentLine; int Verbose; bool EscapeQuotes; bool NoEscapeMode; @@ -89,5 +89,3 @@ private: #define YY_EXTRA_TYPE cmCommandArgumentParserHelper* #define YY_DECL \ int cmCommandArgument_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - -#endif diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index c94f128..37be542 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -17,6 +17,7 @@ #include "cmBreakCommand.h" #include "cmBuildCommand.h" #include "cmCMakeMinimumRequired.h" +#include "cmCMakePathCommand.h" #include "cmCMakePolicyCommand.h" #include "cmCommand.h" #include "cmConfigureFileCommand.h" @@ -120,6 +121,7 @@ void GetScriptingCommands(cmState* state) { state->AddBuiltinCommand("break", cmBreakCommand); state->AddBuiltinCommand("cmake_minimum_required", cmCMakeMinimumRequired); + state->AddBuiltinCommand("cmake_path", cmCMakePathCommand); state->AddBuiltinCommand("cmake_policy", cmCMakePolicyCommand); state->AddBuiltinCommand("configure_file", cmConfigureFileCommand); state->AddBuiltinCommand("continue", cmContinueCommand); diff --git a/Source/cmCommands.h b/Source/cmCommands.h index 1f8fafb..5605430 100644 --- a/Source/cmCommands.h +++ b/Source/cmCommands.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCommands_h -#define cmCommands_h +#pragma once class cmState; @@ -13,5 +12,3 @@ class cmState; void GetScriptingCommands(cmState* state); void GetProjectCommands(cmState* state); void GetProjectCommandsInScriptMode(cmState* state); - -#endif diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 051eff6..2b7c9f6 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -41,7 +41,7 @@ std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const const char* cmCommonTargetGenerator::GetFeature(const std::string& feature, const std::string& config) { - return this->GeneratorTarget->GetFeature(feature, config); + return this->GeneratorTarget->GetFeature(feature, config)->c_str(); } void cmCommonTargetGenerator::AddModuleDefinitionFlag( @@ -55,7 +55,7 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag( } // TODO: Create a per-language flag variable. - const char* defFileFlag = + cmProp defFileFlag = this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG"); if (!defFileFlag) { return; @@ -64,7 +64,7 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag( // Append the flag and value. Use ConvertToLinkReference to help // vs6's "cl -link" pass it to the linker. std::string flag = - cmStrCat(defFileFlag, + cmStrCat(*defFileFlag, this->LocalCommonGenerator->ConvertToOutputFormat( linkLineComputer->ConvertToLinkReference(mdi->DefFile), cmOutputConverter::SHELL)); @@ -270,7 +270,7 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags, { // Lookup the flag to specify the version. std::string fvar = cmStrCat("CMAKE_", lang, "_OSX_", name, "_VERSION_FLAG"); - const char* flag = this->Makefile->GetDefinition(fvar); + cmProp flag = this->Makefile->GetDefinition(fvar); // Skip if no such flag. if (!flag) { @@ -288,7 +288,7 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags, if (major > 0 || minor > 0 || patch > 0) { // Append the flag since a non-zero version is specified. std::ostringstream vflag; - vflag << flag << major << "." << minor << "." << patch; + vflag << *flag << major << "." << minor << "." << patch; this->LocalCommonGenerator->AppendFlags(flags, vflag.str()); } } diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index c3c3a3a..fba6b0a 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCommonTargetGenerator_h -#define cmCommonTargetGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -75,5 +74,3 @@ private: }; std::map<std::string, ByConfig> Configs; }; - -#endif diff --git a/Source/cmComputeComponentGraph.cxx b/Source/cmComputeComponentGraph.cxx index 81cd878..6591fb1 100644 --- a/Source/cmComputeComponentGraph.cxx +++ b/Source/cmComputeComponentGraph.cxx @@ -8,6 +8,12 @@ cmComputeComponentGraph::cmComputeComponentGraph(Graph const& input) : InputGraph(input) { +} + +cmComputeComponentGraph::~cmComputeComponentGraph() = default; + +void cmComputeComponentGraph::Compute() +{ // Identify components. this->Tarjan(); @@ -17,8 +23,6 @@ cmComputeComponentGraph::cmComputeComponentGraph(Graph const& input) this->TransferEdges(); } -cmComputeComponentGraph::~cmComputeComponentGraph() = default; - void cmComputeComponentGraph::Tarjan() { int n = static_cast<int>(this->InputGraph.size()); diff --git a/Source/cmComputeComponentGraph.h b/Source/cmComputeComponentGraph.h index 202888c..1d1d134 100644 --- a/Source/cmComputeComponentGraph.h +++ b/Source/cmComputeComponentGraph.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmComputeComponentGraph_h -#define cmComputeComponentGraph_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -31,6 +30,9 @@ public: cmComputeComponentGraph(Graph const& input); ~cmComputeComponentGraph(); + /** Run the computation. */ + void Compute(); + /** Get the adjacency list of the component graph. */ Graph const& GetComponentGraph() const { return this->ComponentGraph; } EdgeList const& GetComponentGraphEdges(int c) const @@ -75,5 +77,3 @@ private: // Connected components. }; - -#endif diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index e9bf5a5..5341e8d 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -5,7 +5,6 @@ #include <algorithm> #include <cassert> #include <cstdio> -#include <cstring> #include <iterator> #include <sstream> #include <utility> @@ -18,6 +17,7 @@ #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -253,13 +253,13 @@ cmComputeLinkDepends::Compute() // Compute the final set of link entries. // Iterate in reverse order so we can keep only the last occurrence // of a shared library. - std::set<int> emmitted; + std::set<int> emitted; for (int i : cmReverseRange(this->FinalLinkOrder)) { LinkEntry const& e = this->EntryList[i]; cmGeneratorTarget const* t = e.Target; // Entries that we know the linker will re-use do not need to be repeated. bool uniquify = t && t->GetType() == cmStateEnums::SHARED_LIBRARY; - if (!uniquify || emmitted.insert(i).second) { + if (!uniquify || emitted.insert(i).second) { this->FinalLinkEntries.push_back(e); } } @@ -315,9 +315,9 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) } else { // Look for an old-style <item>_LIB_DEPENDS variable. std::string var = cmStrCat(entry.Item.Value, "_LIB_DEPENDS"); - if (const char* val = this->Makefile->GetDefinition(var)) { + if (cmProp val = this->Makefile->GetDefinition(var)) { // The item dependencies are known. Follow them. - BFSEntry qe = { index, val }; + BFSEntry qe = { index, val->c_str() }; this->BFSQueue.push(qe); } else if (!entry.IsFlag) { // The item dependencies are not known. We need to infer them. @@ -454,10 +454,10 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, // lower. if (!haveLLT) { std::string var = cmStrCat(d, "_LINK_TYPE"); - if (const char* val = this->Makefile->GetDefinition(var)) { - if (strcmp(val, "debug") == 0) { + if (cmProp val = this->Makefile->GetDefinition(var)) { + if (*val == "debug") { llt = DEBUG_LibraryType; - } else if (strcmp(val, "optimized") == 0) { + } else if (*val == "optimized") { llt = OPTIMIZED_LibraryType; } } @@ -626,6 +626,7 @@ void cmComputeLinkDepends::OrderLinkEntires() // constraints disallow it. this->CCG = cm::make_unique<cmComputeComponentGraph>(this->EntryConstraintGraph); + this->CCG->Compute(); // The component graph is guaranteed to be acyclic. Start a DFS // from every entry to compute a topological order for the diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index e806dff..902500a 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmComputeLinkDepends_h -#define cmComputeLinkDepends_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -160,5 +159,3 @@ private: bool DebugMode; bool OldLinkDirMode; }; - -#endif diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 4c5f57d..4a331fb 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -4,7 +4,6 @@ #include <algorithm> #include <cctype> -#include <cstring> #include <sstream> #include <utility> @@ -284,27 +283,28 @@ cmComputeLinkInformation::cmComputeLinkInformation( this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) { std::string loader_flag_var = cmStrCat("CMAKE_SHARED_MODULE_LOADER_", this->LinkLanguage, "_FLAG"); - this->LoaderFlag = this->Makefile->GetDefinition(loader_flag_var); + this->LoaderFlag = + cmToCStr(this->Makefile->GetDefinition(loader_flag_var)); } // Get options needed to link libraries. - if (const char* flag = this->Makefile->GetDefinition( + if (cmProp flag = this->Makefile->GetDefinition( "CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_FLAG")) { - this->LibLinkFlag = flag; + this->LibLinkFlag = *flag; } else { this->LibLinkFlag = this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG"); } - if (const char* flag = this->Makefile->GetDefinition( + if (cmProp flag = this->Makefile->GetDefinition( "CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_FILE_FLAG")) { - this->LibLinkFileFlag = flag; + this->LibLinkFileFlag = *flag; } else { this->LibLinkFileFlag = this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FILE_FLAG"); } - if (const char* suffix = this->Makefile->GetDefinition( + if (cmProp suffix = this->Makefile->GetDefinition( "CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_SUFFIX")) { - this->LibLinkSuffix = suffix; + this->LibLinkSuffix = *suffix; } else { this->LibLinkSuffix = this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"); @@ -515,7 +515,7 @@ bool cmComputeLinkInformation::Compute() // Restore the target link type so the correct system runtime // libraries are found. cmProp lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC"); - if (lss && cmIsOn(*lss)) { + if (cmIsOn(lss)) { this->SetCurrentLinkType(LinkStatic); } else { this->SetCurrentLinkType(this->StartLinkType); @@ -593,9 +593,9 @@ void cmComputeLinkInformation::AddRuntimeLinkLibrary(std::string const& lang) if (runtimeLibrary.empty()) { return; } - if (const char* runtimeLinkOptions = this->Makefile->GetDefinition( + if (cmProp runtimeLinkOptions = this->Makefile->GetDefinition( "CMAKE_" + lang + "_RUNTIME_LIBRARY_LINK_OPTIONS_" + runtimeLibrary)) { - std::vector<std::string> libsVec = cmExpandedList(runtimeLinkOptions); + std::vector<std::string> libsVec = cmExpandedList(*runtimeLinkOptions); for (std::string const& i : libsVec) { if (!cm::contains(this->ImplicitLinkLibs, i)) { this->AddItem(i, nullptr); @@ -609,8 +609,8 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) // Add libraries for this language that are not implied by the // linker language. std::string libVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_LIBRARIES"); - if (const char* libs = this->Makefile->GetDefinition(libVar)) { - std::vector<std::string> libsVec = cmExpandedList(libs); + if (cmProp libs = this->Makefile->GetDefinition(libVar)) { + std::vector<std::string> libsVec = cmExpandedList(*libs); for (std::string const& i : libsVec) { if (!cm::contains(this->ImplicitLinkLibs, i)) { this->AddItem(i, nullptr); @@ -621,8 +621,8 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) // Add linker search paths for this language that are not // implied by the linker language. std::string dirVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_DIRECTORIES"); - if (const char* dirs = this->Makefile->GetDefinition(dirVar)) { - std::vector<std::string> dirsVec = cmExpandedList(dirs); + if (cmProp dirs = this->Makefile->GetDefinition(dirVar)) { + std::vector<std::string> dirsVec = cmExpandedList(*dirs); this->OrderLinkerSearchPath->AddLanguageDirectories(dirsVec); } } @@ -800,8 +800,8 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo() this->LinkTypeEnabled = false; // Lookup link type selection flags. - const char* static_link_type_flag = nullptr; - const char* shared_link_type_flag = nullptr; + cmProp static_link_type_flag = nullptr; + cmProp shared_link_type_flag = nullptr; const char* target_type_str = nullptr; switch (this->Target->GetType()) { case cmStateEnums::EXECUTABLE: @@ -832,16 +832,15 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo() // We can support link type switching only if all needed flags are // known. - if (static_link_type_flag && *static_link_type_flag && - shared_link_type_flag && *shared_link_type_flag) { + if (cmNonempty(static_link_type_flag) && cmNonempty(shared_link_type_flag)) { this->LinkTypeEnabled = true; - this->StaticLinkTypeFlag = static_link_type_flag; - this->SharedLinkTypeFlag = shared_link_type_flag; + this->StaticLinkTypeFlag = *static_link_type_flag; + this->SharedLinkTypeFlag = *shared_link_type_flag; } // Lookup the starting link type from the target (linked statically?). cmProp lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC"); - this->StartLinkType = (lss && cmIsOn(*lss)) ? LinkStatic : LinkShared; + this->StartLinkType = cmIsOn(lss) ? LinkStatic : LinkShared; this->CurrentLinkType = this->StartLinkType; } @@ -849,31 +848,30 @@ void cmComputeLinkInformation::ComputeItemParserInfo() { // Get possible library name prefixes. cmMakefile* mf = this->Makefile; - this->AddLinkPrefix(mf->GetDefinition("CMAKE_STATIC_LIBRARY_PREFIX")); - this->AddLinkPrefix(mf->GetDefinition("CMAKE_SHARED_LIBRARY_PREFIX")); + this->AddLinkPrefix(mf->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX")); + this->AddLinkPrefix(mf->GetSafeDefinition("CMAKE_SHARED_LIBRARY_PREFIX")); // Import library names should be matched and treated as shared // libraries for the purposes of linking. - this->AddLinkExtension(mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"), + this->AddLinkExtension(mf->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"), LinkShared); - this->AddLinkExtension(mf->GetDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"), + this->AddLinkExtension(mf->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"), LinkStatic); - this->AddLinkExtension(mf->GetDefinition("CMAKE_SHARED_LIBRARY_SUFFIX"), + this->AddLinkExtension(mf->GetSafeDefinition("CMAKE_SHARED_LIBRARY_SUFFIX"), LinkShared); - this->AddLinkExtension(mf->GetDefinition("CMAKE_LINK_LIBRARY_SUFFIX"), + this->AddLinkExtension(mf->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"), LinkUnknown); - if (const char* linkSuffixes = - mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS")) { - std::vector<std::string> linkSuffixVec = cmExpandedList(linkSuffixes); + if (cmProp linkSuffixes = mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS")) { + std::vector<std::string> linkSuffixVec = cmExpandedList(*linkSuffixes); for (std::string const& i : linkSuffixVec) { - this->AddLinkExtension(i.c_str(), LinkUnknown); + this->AddLinkExtension(i, LinkUnknown); } } - if (const char* sharedSuffixes = + if (cmProp sharedSuffixes = mf->GetDefinition("CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES")) { - std::vector<std::string> sharedSuffixVec = cmExpandedList(sharedSuffixes); + std::vector<std::string> sharedSuffixVec = cmExpandedList(*sharedSuffixes); for (std::string const& i : sharedSuffixVec) { - this->AddLinkExtension(i.c_str(), LinkShared); + this->AddLinkExtension(i, LinkShared); } } @@ -903,7 +901,7 @@ void cmComputeLinkInformation::ComputeItemParserInfo() #ifdef CM_COMPUTE_LINK_INFO_DEBUG fprintf(stderr, "any regex [%s]\n", reg_any.c_str()); #endif - this->ExtractAnyLibraryName.compile(reg_any.c_str()); + this->ExtractAnyLibraryName.compile(reg_any); // Create a regex to match static library names. if (!this->StaticLinkExtensions.empty()) { @@ -912,7 +910,7 @@ void cmComputeLinkInformation::ComputeItemParserInfo() #ifdef CM_COMPUTE_LINK_INFO_DEBUG fprintf(stderr, "static regex [%s]\n", reg_static.c_str()); #endif - this->ExtractStaticLibraryName.compile(reg_static.c_str()); + this->ExtractStaticLibraryName.compile(reg_static); } // Create a regex to match shared library names. @@ -924,20 +922,21 @@ void cmComputeLinkInformation::ComputeItemParserInfo() #ifdef CM_COMPUTE_LINK_INFO_DEBUG fprintf(stderr, "shared regex [%s]\n", reg_shared.c_str()); #endif - this->ExtractSharedLibraryName.compile(reg_shared.c_str()); + this->ExtractSharedLibraryName.compile(reg_shared); } } -void cmComputeLinkInformation::AddLinkPrefix(const char* p) +void cmComputeLinkInformation::AddLinkPrefix(std::string const& p) { - if (p && *p) { + if (!p.empty()) { this->LinkPrefixes.insert(p); } } -void cmComputeLinkInformation::AddLinkExtension(const char* e, LinkType type) +void cmComputeLinkInformation::AddLinkExtension(std::string const& e, + LinkType type) { - if (e && *e) { + if (!e.empty()) { if (type == LinkStatic) { this->StaticLinkExtensions.emplace_back(e); } @@ -962,7 +961,7 @@ std::string cmComputeLinkInformation::CreateExtensionRegex( // Store this extension choice with the "." escaped. libext += "\\"; #if defined(_WIN32) && !defined(__CYGWIN__) - libext += this->NoCaseExpression(i.c_str()); + libext += this->NoCaseExpression(i); #else libext += i; #endif @@ -980,21 +979,19 @@ std::string cmComputeLinkInformation::CreateExtensionRegex( return libext; } -std::string cmComputeLinkInformation::NoCaseExpression(const char* str) +std::string cmComputeLinkInformation::NoCaseExpression(std::string const& str) { std::string ret; - ret.reserve(strlen(str) * 4); - const char* s = str; - while (*s) { - if (*s == '.') { - ret += *s; + ret.reserve(str.size() * 4); + for (char c : str) { + if (c == '.') { + ret += c; } else { ret += '['; - ret += static_cast<char>(tolower(*s)); - ret += static_cast<char>(toupper(*s)); + ret += static_cast<char>(tolower(c)); + ret += static_cast<char>(toupper(c)); ret += ']'; } - s++; } return ret; } @@ -1555,10 +1552,10 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo() // Append library architecture to all implicit platform directories // and add them to the set - if (const char* libraryArch = + if (cmProp libraryArch = this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) { for (std::string const& i : implicitDirVec) { - this->ImplicitLinkDirs.insert(i + "/" + libraryArch); + this->ImplicitLinkDirs.insert(i + "/" + *libraryArch); } } @@ -1688,7 +1685,7 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo( } } -static void cmCLI_ExpandListUnique(const char* str, +static void cmCLI_ExpandListUnique(std::string const& str, std::vector<std::string>& out, std::set<std::string>& emitted) { @@ -1735,7 +1732,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, if (use_install_rpath) { std::string install_rpath; this->Target->GetInstallRPATH(this->Config, install_rpath); - cmCLI_ExpandListUnique(install_rpath.c_str(), runtimeDirs, emitted); + cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted); } if (use_build_rpath) { // Add directories explicitly specified by user @@ -1743,19 +1740,18 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, if (this->Target->GetBuildRPATH(this->Config, build_rpath)) { // This will not resolve entries to use $ORIGIN, the user is expected to // do that if necessary. - cmCLI_ExpandListUnique(build_rpath.c_str(), runtimeDirs, emitted); + cmCLI_ExpandListUnique(build_rpath, runtimeDirs, emitted); } } if (use_build_rpath || use_link_rpath) { std::string rootPath; - if (const char* sysrootLink = + if (cmProp sysrootLink = this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) { - rootPath = sysrootLink; + rootPath = *sysrootLink; } else { rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); } - const char* stagePath = - this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); + cmProp stagePath = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); std::string const& installPrefix = this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); cmSystemTools::ConvertToUnixSlashes(rootPath); @@ -1769,8 +1765,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, std::string d = ri; if (!rootPath.empty() && cmHasPrefix(d, rootPath)) { d.erase(0, rootPath.size()); - } else if (stagePath && *stagePath && cmHasPrefix(d, stagePath)) { - d.erase(0, strlen(stagePath)); + } else if (cmNonempty(stagePath) && cmHasPrefix(d, *stagePath)) { + d.erase(0, (*stagePath).size()); d = cmStrCat(installPrefix, '/', d); cmSystemTools::ConvertToUnixSlashes(d); } else if (use_relative_build_rpath) { @@ -1800,8 +1796,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, std::string d = ri; if (!rootPath.empty() && cmHasPrefix(d, rootPath)) { d.erase(0, rootPath.size()); - } else if (stagePath && *stagePath && cmHasPrefix(d, stagePath)) { - d.erase(0, strlen(stagePath)); + } else if (cmNonempty(stagePath) && cmHasPrefix(d, *stagePath)) { + d.erase(0, (*stagePath).size()); d = cmStrCat(installPrefix, '/', d); cmSystemTools::ConvertToUnixSlashes(d); } @@ -1823,8 +1819,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, "CMAKE_" + li + "_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH"; if (this->Makefile->IsOn(useVar)) { std::string dirVar = "CMAKE_" + li + "_IMPLICIT_LINK_DIRECTORIES"; - if (const char* dirs = this->Makefile->GetDefinition(dirVar)) { - cmCLI_ExpandListUnique(dirs, runtimeDirs, emitted); + if (cmProp dirs = this->Makefile->GetDefinition(dirVar)) { + cmCLI_ExpandListUnique(*dirs, runtimeDirs, emitted); } } } @@ -1832,7 +1828,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // Add runtime paths required by the platform to always be // present. This is done even when skipping rpath support. - cmCLI_ExpandListUnique(this->RuntimeAlways.c_str(), runtimeDirs, emitted); + cmCLI_ExpandListUnique(this->RuntimeAlways, runtimeDirs, emitted); } std::string cmComputeLinkInformation::GetRPathString(bool for_install) const diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index e50d369..543b6d7 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmComputeLinkInformation_h -#define cmComputeLinkInformation_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -144,11 +143,11 @@ private: cmsys::RegularExpression ExtractSharedLibraryName; cmsys::RegularExpression ExtractAnyLibraryName; std::string SharedRegexString; - void AddLinkPrefix(const char* p); - void AddLinkExtension(const char* e, LinkType type); + void AddLinkPrefix(std::string const& p); + void AddLinkExtension(std::string const& e, LinkType type); std::string CreateExtensionRegex(std::vector<std::string> const& exts, LinkType type); - std::string NoCaseExpression(const char* str); + std::string NoCaseExpression(std::string const& str); // Handling of link items. void AddTargetItem(BT<std::string> const& item, @@ -209,5 +208,3 @@ private: const cmGeneratorTarget* target); void AddLibraryRuntimeInfo(std::string const& fullPath); }; - -#endif diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 41f5346..1f22ce6 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -17,10 +17,12 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmSourceFile.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" @@ -115,18 +117,32 @@ bool cmComputeTargetDepends::Compute() if (this->DebugMode) { this->DisplayGraph(this->InitialGraph, "initial"); } + cmComputeComponentGraph ccg1(this->InitialGraph); + ccg1.Compute(); + if (!this->CheckComponents(ccg1)) { + return false; + } + + // Compute the intermediate graph. + this->CollectSideEffects(); + this->ComputeIntermediateGraph(); + if (this->DebugMode) { + this->DisplaySideEffects(); + this->DisplayGraph(this->IntermediateGraph, "intermediate"); + } // Identify components. - cmComputeComponentGraph ccg(this->InitialGraph); + cmComputeComponentGraph ccg2(this->IntermediateGraph); + ccg2.Compute(); if (this->DebugMode) { - this->DisplayComponents(ccg); + this->DisplayComponents(ccg2, "intermediate"); } - if (!this->CheckComponents(ccg)) { + if (!this->CheckComponents(ccg2)) { return false; } // Compute the final dependency graph. - if (!this->ComputeFinalDepends(ccg)) { + if (!this->ComputeFinalDepends(ccg2)) { return false; } if (this->DebugMode) { @@ -184,7 +200,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) { // Get the depender. cmGeneratorTarget const* depender = this->Targets[depender_index]; - if (depender->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!depender->IsInBuildSystem()) { return; } @@ -196,18 +212,20 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) std::set<cmLinkItem> emitted; std::vector<std::string> const& configs = - depender->Makefile->GetGeneratorConfigs(); + depender->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); for (std::string const& it : configs) { - cmLinkImplementation const* impl = depender->GetLinkImplementation(it); - // A target should not depend on itself. emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace())); emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace())); - for (cmLinkImplItem const& lib : impl->Libraries) { - // Don't emit the same library twice for this target. - if (emitted.insert(lib).second) { - this->AddTargetDepend(depender_index, lib, true, false); - this->AddInterfaceDepends(depender_index, lib, it, emitted); + + if (cmLinkImplementation const* impl = + depender->GetLinkImplementation(it)) { + for (cmLinkImplItem const& lib : impl->Libraries) { + // Don't emit the same library twice for this target. + if (emitted.insert(lib).second) { + this->AddTargetDepend(depender_index, lib, true, false); + this->AddInterfaceDepends(depender_index, lib, it, emitted); + } } } @@ -356,10 +374,9 @@ void cmComputeTargetDepends::AddTargetDepend( int depender_index, cmGeneratorTarget const* dependee, cmListFileBacktrace const& dependee_backtrace, bool linking, bool cross) { - if (dependee->IsImported() || - dependee->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - // Skip IMPORTED and INTERFACE targets but follow their utility - // dependencies. + if (!dependee->IsInBuildSystem()) { + // Skip targets that are not in the buildsystem but follow their + // utility dependencies. std::set<cmLinkItem> const& utils = dependee->GetUtilityItems(); for (cmLinkItem const& i : utils) { if (cmGeneratorTarget const* transitive_dependee = i.Target) { @@ -380,6 +397,111 @@ void cmComputeTargetDepends::AddTargetDepend( } } +void cmComputeTargetDepends::CollectSideEffects() +{ + this->SideEffects.resize(0); + this->SideEffects.resize(this->InitialGraph.size()); + + int n = static_cast<int>(this->InitialGraph.size()); + std::set<int> visited; + for (int i = 0; i < n; ++i) { + this->CollectSideEffectsForTarget(visited, i); + } +} + +void cmComputeTargetDepends::CollectSideEffectsForTarget( + std::set<int>& visited, int depender_index) +{ + if (!visited.count(depender_index)) { + auto& se = this->SideEffects[depender_index]; + visited.insert(depender_index); + this->Targets[depender_index]->AppendCustomCommandSideEffects( + se.CustomCommandSideEffects); + this->Targets[depender_index]->AppendLanguageSideEffects( + se.LanguageSideEffects); + + for (auto const& edge : this->InitialGraph[depender_index]) { + this->CollectSideEffectsForTarget(visited, edge); + auto const& dse = this->SideEffects[edge]; + se.CustomCommandSideEffects.insert(dse.CustomCommandSideEffects.cbegin(), + dse.CustomCommandSideEffects.cend()); + for (auto const& it : dse.LanguageSideEffects) { + se.LanguageSideEffects[it.first].insert(it.second.cbegin(), + it.second.cend()); + } + } + } +} + +void cmComputeTargetDepends::ComputeIntermediateGraph() +{ + this->IntermediateGraph.resize(0); + this->IntermediateGraph.resize(this->InitialGraph.size()); + + int n = static_cast<int>(this->InitialGraph.size()); + for (int i = 0; i < n; ++i) { + auto const& initialEdges = this->InitialGraph[i]; + auto& intermediateEdges = this->IntermediateGraph[i]; + cmGeneratorTarget const* gt = this->Targets[i]; + if (gt->GetType() != cmStateEnums::STATIC_LIBRARY && + gt->GetType() != cmStateEnums::OBJECT_LIBRARY) { + intermediateEdges = initialEdges; + } else { + if (cmProp optimizeDependencies = + gt->GetProperty("OPTIMIZE_DEPENDENCIES")) { + if (cmIsOn(optimizeDependencies)) { + this->OptimizeLinkDependencies(gt, intermediateEdges, initialEdges); + } else { + intermediateEdges = initialEdges; + } + } else { + intermediateEdges = initialEdges; + } + } + } +} + +void cmComputeTargetDepends::OptimizeLinkDependencies( + cmGeneratorTarget const* gt, cmGraphEdgeList& outputEdges, + cmGraphEdgeList const& inputEdges) +{ + std::set<int> emitted; + for (auto const& edge : inputEdges) { + if (edge.IsStrong()) { + // Preserve strong edges + outputEdges.push_back(edge); + } else { + auto const& dse = this->SideEffects[edge]; + + // Add edges that have custom command side effects + for (cmGeneratorTarget const* dep : dse.CustomCommandSideEffects) { + auto index = this->TargetIndex[dep]; + if (!emitted.count(index)) { + emitted.insert(index); + outputEdges.push_back( + cmGraphEdge(index, false, edge.IsCross(), edge.GetBacktrace())); + } + } + + // Add edges that have language side effects for languages we + // care about + for (auto const& lang : gt->GetAllConfigCompileLanguages()) { + auto it = dse.LanguageSideEffects.find(lang); + if (it != dse.LanguageSideEffects.end()) { + for (cmGeneratorTarget const* dep : it->second) { + auto index = this->TargetIndex[dep]; + if (!emitted.count(index)) { + emitted.insert(index); + outputEdges.push_back(cmGraphEdge(index, false, edge.IsCross(), + edge.GetBacktrace())); + } + } + } + } + } + } +} + void cmComputeTargetDepends::DisplayGraph(Graph const& graph, const std::string& name) { @@ -400,10 +522,39 @@ void cmComputeTargetDepends::DisplayGraph(Graph const& graph, fprintf(stderr, "\n"); } +void cmComputeTargetDepends::DisplaySideEffects() +{ + fprintf(stderr, "The side effects are:\n"); + int n = static_cast<int>(SideEffects.size()); + for (int depender_index = 0; depender_index < n; ++depender_index) { + cmGeneratorTarget const* depender = this->Targets[depender_index]; + fprintf(stderr, "target %d is [%s]\n", depender_index, + depender->GetName().c_str()); + if (!this->SideEffects[depender_index].CustomCommandSideEffects.empty()) { + fprintf(stderr, " custom commands\n"); + for (auto const* gt : + this->SideEffects[depender_index].CustomCommandSideEffects) { + fprintf(stderr, " from target %d [%s]\n", this->TargetIndex[gt], + gt->GetName().c_str()); + } + } + for (auto const& it : + this->SideEffects[depender_index].LanguageSideEffects) { + fprintf(stderr, " language %s\n", it.first.c_str()); + for (auto const* gt : it.second) { + fprintf(stderr, " from target %d [%s]\n", this->TargetIndex[gt], + gt->GetName().c_str()); + } + } + } + fprintf(stderr, "\n"); +} + void cmComputeTargetDepends::DisplayComponents( - cmComputeComponentGraph const& ccg) + cmComputeComponentGraph const& ccg, const std::string& name) { - fprintf(stderr, "The strongly connected components are:\n"); + fprintf(stderr, "The strongly connected components for the %s graph are:\n", + name.c_str()); std::vector<NodeList> const& components = ccg.GetComponents(); int n = static_cast<int>(components.size()); for (int c = 0; c < n; ++c) { diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index e0d625f..3517844 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmComputeTargetDepends_h -#define cmComputeTargetDepends_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -42,6 +41,13 @@ public: cmTargetDependSet& deps); private: + struct TargetSideEffects + { + std::set<cmGeneratorTarget const*> CustomCommandSideEffects; + std::map<std::string, std::set<cmGeneratorTarget const*>> + LanguageSideEffects; + }; + void CollectTargets(); void CollectDepends(); void CollectTargetDepends(int depender_index); @@ -50,6 +56,12 @@ private: void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee, cmListFileBacktrace const& dependee_backtrace, bool linking, bool cross); + void CollectSideEffects(); + void CollectSideEffectsForTarget(std::set<int>& visited, int depender_index); + void ComputeIntermediateGraph(); + void OptimizeLinkDependencies(cmGeneratorTarget const* gt, + cmGraphEdgeList& outputEdges, + cmGraphEdgeList const& inputEdges); bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name, const std::string& config, @@ -74,11 +86,15 @@ private: using EdgeList = cmGraphEdgeList; using Graph = cmGraphAdjacencyList; Graph InitialGraph; + Graph IntermediateGraph; Graph FinalGraph; + std::vector<TargetSideEffects> SideEffects; void DisplayGraph(Graph const& graph, const std::string& name); + void DisplaySideEffects(); // Deal with connected components. - void DisplayComponents(cmComputeComponentGraph const& ccg); + void DisplayComponents(cmComputeComponentGraph const& ccg, + const std::string& name); bool CheckComponents(cmComputeComponentGraph const& ccg); void ComplainAboutBadComponent(cmComputeComponentGraph const& ccg, int c, bool strong = false); @@ -88,5 +104,3 @@ private: bool IntraComponent(std::vector<int> const& cmap, int c, int i, int* head, std::set<int>& emitted, std::set<int>& visited); }; - -#endif diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 7a3a3e8..7ada8d8 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -4,7 +4,6 @@ #include <cstdio> #include <cstdlib> -#include <cstring> #include <functional> #include <sstream> #include <utility> @@ -15,6 +14,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -134,7 +134,7 @@ bool cmConditionEvaluator::IsTrue( } //========================================================================= -const char* cmConditionEvaluator::GetDefinitionIfUnquoted( +cmProp cmConditionEvaluator::GetDefinitionIfUnquoted( cmExpandedCommandArgument const& argument) const { if ((this->Policy54Status != cmPolicies::WARN && @@ -143,7 +143,7 @@ const char* cmConditionEvaluator::GetDefinitionIfUnquoted( return nullptr; } - const char* def = this->Makefile.GetDefinition(argument.GetValue()); + cmProp def = this->Makefile.GetDefinition(argument.GetValue()); if (def && argument.WasQuoted() && this->Policy54Status == cmPolicies::WARN) { @@ -165,13 +165,13 @@ const char* cmConditionEvaluator::GetDefinitionIfUnquoted( } //========================================================================= -const char* cmConditionEvaluator::GetVariableOrString( +cmProp cmConditionEvaluator::GetVariableOrString( const cmExpandedCommandArgument& argument) const { - const char* def = this->GetDefinitionIfUnquoted(argument); + cmProp def = this->GetDefinitionIfUnquoted(argument); if (!def) { - def = argument.c_str(); + def = &argument.GetValue(); } return def; @@ -231,7 +231,7 @@ bool cmConditionEvaluator::GetBooleanValue( // Check for numbers. if (!arg.empty()) { char* end; - double d = strtod(arg.c_str(), &end); + double d = strtod(arg.GetValue().c_str(), &end); if (*end == '\0') { // The whole string is a number. Use C conversion to bool. return static_cast<bool>(d); @@ -239,7 +239,7 @@ bool cmConditionEvaluator::GetBooleanValue( } // Check definition. - const char* def = this->GetDefinitionIfUnquoted(arg); + cmProp def = this->GetDefinitionIfUnquoted(arg); return !cmIsOff(def); } @@ -256,13 +256,13 @@ bool cmConditionEvaluator::GetBooleanValueOld( if (arg == "1") { return true; } - const char* def = this->GetDefinitionIfUnquoted(arg); + cmProp def = this->GetDefinitionIfUnquoted(arg); return !cmIsOff(def); } // Old GetVariableOrNumber behavior. - const char* def = this->GetDefinitionIfUnquoted(arg); - if (!def && atoi(arg.c_str())) { - def = arg.c_str(); + cmProp def = this->GetDefinitionIfUnquoted(arg); + if (!def && atoi(arg.GetValue().c_str())) { + def = &arg.GetValue(); } return !cmIsOff(def); } @@ -434,36 +434,38 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, this->IncrementArguments(newArgs, argP1, argP2); // does a file exist if (this->IsKeyword(keyEXISTS, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate(cmSystemTools::FileExists(argP1->c_str()), + this->HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), reducible, arg, newArgs, argP1, argP2); } // does a directory with this name exist if (this->IsKeyword(keyIS_DIRECTORY, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate(cmSystemTools::FileIsDirectory(argP1->c_str()), - reducible, arg, newArgs, argP1, argP2); + this->HandlePredicate( + cmSystemTools::FileIsDirectory(argP1->GetValue()), reducible, arg, + newArgs, argP1, argP2); } // does a symlink with this name exist if (this->IsKeyword(keyIS_SYMLINK, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate(cmSystemTools::FileIsSymlink(argP1->c_str()), + this->HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), reducible, arg, newArgs, argP1, argP2); } // is the given path an absolute path ? if (this->IsKeyword(keyIS_ABSOLUTE, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate(cmSystemTools::FileIsFullPath(argP1->c_str()), + this->HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), reducible, arg, newArgs, argP1, argP2); } // does a command exist if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) { cmState::Command command = - this->Makefile.GetState()->GetCommand(argP1->c_str()); + this->Makefile.GetState()->GetCommand(argP1->GetValue()); this->HandlePredicate(command != nullptr, reducible, arg, newArgs, argP1, argP2); } // does a policy exist if (this->IsKeyword(keyPOLICY, *arg) && argP1 != newArgs.end()) { cmPolicies::PolicyID pid; - this->HandlePredicate(cmPolicies::GetPolicyID(argP1->c_str(), pid), - reducible, arg, newArgs, argP1, argP2); + this->HandlePredicate( + cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), reducible, + arg, newArgs, argP1, argP2); } // does a target exist if (this->IsKeyword(keyTARGET, *arg) && argP1 != newArgs.end()) { @@ -475,7 +477,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, if (this->Policy64Status != cmPolicies::OLD && this->Policy64Status != cmPolicies::WARN) { if (this->IsKeyword(keyTEST, *arg) && argP1 != newArgs.end()) { - const cmTest* haveTest = this->Makefile.GetTest(argP1->c_str()); + const cmTest* haveTest = this->Makefile.GetTest(argP1->GetValue()); this->HandlePredicate(haveTest != nullptr, reducible, arg, newArgs, argP1, argP2); } @@ -522,8 +524,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, { int reducible; std::string def_buf; - const char* def; - const char* def2; + cmProp def; + cmProp def2; do { reducible = 0; auto arg = newArgs.begin(); @@ -534,15 +536,16 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->IncrementArguments(newArgs, argP1, argP2); if (argP1 != newArgs.end() && argP2 != newArgs.end() && IsKeyword(keyMATCHES, *argP1)) { - def = this->GetVariableOrString(*arg); - if (def != arg->c_str() // yes, we compare the pointer value - && cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) { + def = this->GetDefinitionIfUnquoted(*arg); + if (!def) { + def = &arg->GetValue(); + } else if (cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) { // The string to match is owned by our match result variables. // Move it to our own buffer before clearing them. - def_buf = def; - def = def_buf.c_str(); + def_buf = *def; + def = &def_buf; } - const char* rex = argP2->c_str(); + const std::string& rex = argP2->GetValue(); this->Makefile.ClearMatches(); cmsys::RegularExpression regEntry; if (!regEntry.compile(rex)) { @@ -552,7 +555,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, status = MessageType::FATAL_ERROR; return false; } - if (regEntry.find(def)) { + if (regEntry.find(*def)) { this->Makefile.StoreMatches(regEntry); *arg = cmExpandedCommandArgument("1", true); } else { @@ -584,7 +587,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, double lhs; double rhs; bool result; - if (sscanf(def, "%lg", &lhs) != 1 || sscanf(def2, "%lg", &rhs) != 1) { + if (sscanf(def->c_str(), "%lg", &lhs) != 1 || + sscanf(def2->c_str(), "%lg", &rhs) != 1) { result = false; } else if (*(argP1) == keyLESS) { result = (lhs < rhs); @@ -608,7 +612,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->IsKeyword(keySTREQUAL, *argP1))) { def = this->GetVariableOrString(*arg); def2 = this->GetVariableOrString(*argP2); - int val = strcmp(def, def2); + int val = (*def).compare(*def2); bool result; if (*(argP1) == keySTRLESS) { result = (val < 0); @@ -645,7 +649,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } else { // version_equal op = cmSystemTools::OP_EQUAL; } - bool result = cmSystemTools::VersionCompare(op, def, def2); + bool result = + cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str()); this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); } @@ -670,9 +675,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, def2 = this->Makefile.GetDefinition(argP2->GetValue()); if (def2) { - std::vector<std::string> list = cmExpandedList(def2, true); - - result = cm::contains(list, def); + std::vector<std::string> list = cmExpandedList(*def2, true); + result = cm::contains(list, *def); } this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index 082534c..a4cedff 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmConditionEvaluator_h -#define cmConditionEvaluator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -13,6 +12,7 @@ #include "cmListFileCache.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmProperty.h" class cmMakefile; @@ -32,11 +32,10 @@ public: private: // Filter the given variable definition based on policy CMP0054. - const char* GetDefinitionIfUnquoted( + cmProp GetDefinitionIfUnquoted( const cmExpandedCommandArgument& argument) const; - const char* GetVariableOrString( - const cmExpandedCommandArgument& argument) const; + cmProp GetVariableOrString(const cmExpandedCommandArgument& argument) const; bool IsKeyword(std::string const& keyword, cmExpandedCommandArgument& argument) const; @@ -87,5 +86,3 @@ private: cmPolicies::PolicyStatus Policy57Status; cmPolicies::PolicyStatus Policy64Status; }; - -#endif diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index 4de1c5d..ceb2a32 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmConfigure_h -#define cmConfigure_h +#pragma once #include "cmsys/Configure.hxx" // IWYU pragma: export @@ -19,7 +18,6 @@ #cmakedefine HAVE_UNSETENV #cmakedefine CMAKE_USE_ELF_PARSER #cmakedefine CMAKE_USE_MACH_PARSER -#cmakedefine CMake_HAVE_CXX_MAKE_UNIQUE #define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@ #define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@" #define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@" @@ -29,5 +27,3 @@ #if defined(_WIN32) && !defined(NOMINMAX) # define NOMINMAX #endif - -#endif diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx index 5b3045d..68322cc 100644 --- a/Source/cmConfigureFileCommand.cxx +++ b/Source/cmConfigureFileCommand.cxx @@ -60,6 +60,7 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args, } bool copyOnly = false; bool escapeQuotes = false; + bool use_source_permissions = true; static std::set<cm::string_view> noopOptions = { /* Legacy. */ @@ -87,6 +88,8 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args, escapeQuotes = true; } else if (args[i] == "@ONLY") { atOnly = true; + } else if (args[i] == "NO_SOURCE_PERMISSIONS") { + use_source_permissions = false; } else if (noopOptions.find(args[i]) != noopOptions.end()) { /* Ignore no-op options. */ } else { @@ -102,7 +105,8 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args, } if (!status.GetMakefile().ConfigureFile( - inputFile, outputFile, copyOnly, atOnly, escapeQuotes, newLineStyle)) { + inputFile, outputFile, copyOnly, atOnly, escapeQuotes, + use_source_permissions, newLineStyle)) { status.SetError("Problem configuring file"); return false; } diff --git a/Source/cmConfigureFileCommand.h b/Source/cmConfigureFileCommand.h index c7f95b8..009c145 100644 --- a/Source/cmConfigureFileCommand.h +++ b/Source/cmConfigureFileCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmConfigureFileCommand_h -#define cmConfigureFileCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,4 +11,3 @@ class cmExecutionStatus; bool cmConfigureFileCommand(std::vector<std::string> const& args, cmExecutionStatus& status); -#endif diff --git a/Source/cmContinueCommand.h b/Source/cmContinueCommand.h index ff903aa..29a219f 100644 --- a/Source/cmContinueCommand.h +++ b/Source/cmContinueCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmContinueCommand_h -#define cmContinueCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,5 +16,3 @@ class cmExecutionStatus; */ bool cmContinueCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 8550d04..77a6d4b 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -18,6 +18,7 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -25,77 +26,208 @@ #include "cmVersion.h" #include "cmake.h" -static std::string const kCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN = - "CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN"; -static std::string const kCMAKE_C_COMPILER_TARGET = "CMAKE_C_COMPILER_TARGET"; -static std::string const kCMAKE_C_LINK_NO_PIE_SUPPORTED = - "CMAKE_C_LINK_NO_PIE_SUPPORTED"; -static std::string const kCMAKE_C_LINK_PIE_SUPPORTED = - "CMAKE_C_LINK_PIE_SUPPORTED"; -static std::string const kCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN = - "CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN"; -static std::string const kCMAKE_CXX_COMPILER_TARGET = - "CMAKE_CXX_COMPILER_TARGET"; -static std::string const kCMAKE_CXX_LINK_NO_PIE_SUPPORTED = - "CMAKE_CXX_LINK_NO_PIE_SUPPORTED"; -static std::string const kCMAKE_CXX_LINK_PIE_SUPPORTED = - "CMAKE_CXX_LINK_PIE_SUPPORTED"; -static std::string const kCMAKE_CUDA_ARCHITECTURES = - "CMAKE_CUDA_ARCHITECTURES"; -static std::string const kCMAKE_CUDA_COMPILER_TARGET = - "CMAKE_CUDA_COMPILER_TARGET"; -static std::string const kCMAKE_CUDA_RUNTIME_LIBRARY = - "CMAKE_CUDA_RUNTIME_LIBRARY"; -static std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS"; -static std::string const kCMAKE_LINK_SEARCH_END_STATIC = +namespace { +class LanguageStandardState +{ +public: + LanguageStandardState(std::string&& lang) + : IsEnabled(false) + , DidStandard(false) + , DidStandardRequired(false) + , DidExtensions(false) + , StandardFlag(lang + "_STANDARD") + , RequiredFlag(lang + "_STANDARD_REQUIRED") + , ExtensionFlag(lang + "_EXTENSIONS") + { + } + + void Enabled(bool isEnabled) { this->IsEnabled = isEnabled; } + + bool UpdateIfMatches(std::vector<std::string> const& argv, size_t& index) + { + bool updated = false; + if (argv[index] == this->StandardFlag) { + this->DidStandard = true; + this->StandardValue = argv[++index]; + updated = true; + } else if (argv[index] == this->RequiredFlag) { + this->DidStandardRequired = true; + this->RequiredValue = argv[++index]; + updated = true; + } else if (argv[index] == this->ExtensionFlag) { + this->DidExtensions = true; + this->ExtensionValue = argv[++index]; + updated = true; + } + return updated; + } + + bool Validate(cmMakefile* const makefile) const + { + if (this->DidStandard) { + makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(this->StandardFlag, + " allowed only in source file signature.")); + return false; + } + if (this->DidStandardRequired) { + makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(this->RequiredFlag, + " allowed only in source file signature.")); + return false; + } + if (this->DidExtensions) { + makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(this->ExtensionFlag, + " allowed only in source file signature.")); + return false; + } + + return true; + } + + bool DidNone() const + { + return !this->DidStandard && !this->DidStandardRequired && + !this->DidExtensions; + } + + void LoadUnsetPropertyValues(cmMakefile* const makefile, bool honorStandard, + bool warnCMP0067, + std::vector<std::string>& warnCMP0067Variables) + { + if (!this->IsEnabled) { + return; + } + + auto lookupStdVar = [&](std::string const& var) -> std::string { + std::string value = makefile->GetSafeDefinition(var); + if (warnCMP0067 && !value.empty()) { + value.clear(); + warnCMP0067Variables.push_back(var); + } + return value; + }; + + if (honorStandard || warnCMP0067) { + if (!this->DidStandard) { + this->StandardValue = + lookupStdVar(cmStrCat("CMAKE_", this->StandardFlag)); + } + if (!this->DidStandardRequired) { + this->RequiredValue = + lookupStdVar(cmStrCat("CMAKE_", this->RequiredFlag)); + } + if (!this->DidExtensions) { + this->ExtensionValue = + lookupStdVar(cmStrCat("CMAKE_", this->ExtensionFlag)); + } + } + } + + void WriteProperties(FILE* fout, std::string const& targetName) const + { + if (!this->IsEnabled) { + return; + } + + auto writeProp = [&](std::string const& prop, std::string const& value) { + fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n", + targetName.c_str(), + cmOutputConverter::EscapeForCMake(prop).c_str(), + cmOutputConverter::EscapeForCMake(value).c_str()); + }; + + if (!this->StandardValue.empty()) { + writeProp(this->StandardFlag, this->StandardValue); + } + if (!this->RequiredValue.empty()) { + writeProp(this->RequiredFlag, this->RequiredValue); + } + if (!this->ExtensionValue.empty()) { + writeProp(this->ExtensionFlag, this->ExtensionValue); + } + } + +private: + bool IsEnabled; + bool DidStandard; + bool DidStandardRequired; + bool DidExtensions; + + std::string StandardFlag; + std::string RequiredFlag; + std::string ExtensionFlag; + + std::string StandardValue; + std::string RequiredValue; + std::string ExtensionValue; +}; + +constexpr size_t lang_property_start = 0; +constexpr size_t lang_property_size = 4; +constexpr size_t pie_property_start = 4; +constexpr size_t pie_property_size = 2; +#define SETUP_LANGUAGE(name, lang) \ + static const std::string name[lang_property_size + pie_property_size + 1] = \ + { "CMAKE_" #lang "_COMPILER_EXTERNAL_TOOLCHAIN", \ + "CMAKE_" #lang "_COMPILER_TARGET", \ + "CMAKE_" #lang "_LINK_NO_PIE_SUPPORTED", \ + "CMAKE_" #lang "_PIE_SUPPORTED", "" } + +// NOLINTNEXTLINE(bugprone-suspicious-missing-comma) +SETUP_LANGUAGE(c_properties, C); +// NOLINTNEXTLINE(bugprone-suspicious-missing-comma) +SETUP_LANGUAGE(cxx_properties, CXX); + +// NOLINTNEXTLINE(bugprone-suspicious-missing-comma) +SETUP_LANGUAGE(cuda_properties, CUDA); +// NOLINTNEXTLINE(bugprone-suspicious-missing-comma) +SETUP_LANGUAGE(fortran_properties, Fortran); +// NOLINTNEXTLINE(bugprone-suspicious-missing-comma) +SETUP_LANGUAGE(objc_properties, OBJC); +// NOLINTNEXTLINE(bugprone-suspicious-missing-comma) +SETUP_LANGUAGE(objcxx_properties, OBJCXX); +// NOLINTNEXTLINE(bugprone-suspicious-missing-comma) +SETUP_LANGUAGE(ispc_properties, ISPC); +// NOLINTNEXTLINE(bugprone-suspicious-missing-comma) +SETUP_LANGUAGE(swift_properties, Swift); +#undef SETUP_LANGUAGE + +std::string const kCMAKE_CUDA_ARCHITECTURES = "CMAKE_CUDA_ARCHITECTURES"; +std::string const kCMAKE_CUDA_RUNTIME_LIBRARY = "CMAKE_CUDA_RUNTIME_LIBRARY"; +std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS"; +std::string const kCMAKE_ISPC_INSTRUCTION_SETS = "CMAKE_ISPC_INSTRUCTION_SETS"; +std::string const kCMAKE_LINK_SEARCH_END_STATIC = "CMAKE_LINK_SEARCH_END_STATIC"; -static std::string const kCMAKE_LINK_SEARCH_START_STATIC = +std::string const kCMAKE_LINK_SEARCH_START_STATIC = "CMAKE_LINK_SEARCH_START_STATIC"; -static std::string const kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT = +std::string const kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT = "CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT"; -static std::string const kCMAKE_OSX_ARCHITECTURES = "CMAKE_OSX_ARCHITECTURES"; -static std::string const kCMAKE_OSX_DEPLOYMENT_TARGET = - "CMAKE_OSX_DEPLOYMENT_TARGET"; -static std::string const kCMAKE_OSX_SYSROOT = "CMAKE_OSX_SYSROOT"; -static std::string const kCMAKE_APPLE_ARCH_SYSROOTS = - "CMAKE_APPLE_ARCH_SYSROOTS"; -static std::string const kCMAKE_POSITION_INDEPENDENT_CODE = +std::string const kCMAKE_OSX_ARCHITECTURES = "CMAKE_OSX_ARCHITECTURES"; +std::string const kCMAKE_OSX_DEPLOYMENT_TARGET = "CMAKE_OSX_DEPLOYMENT_TARGET"; +std::string const kCMAKE_OSX_SYSROOT = "CMAKE_OSX_SYSROOT"; +std::string const kCMAKE_APPLE_ARCH_SYSROOTS = "CMAKE_APPLE_ARCH_SYSROOTS"; +std::string const kCMAKE_POSITION_INDEPENDENT_CODE = "CMAKE_POSITION_INDEPENDENT_CODE"; -static std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT"; -static std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE"; -static std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK"; -static std::string const kCMAKE_Swift_COMPILER_TARGET = - "CMAKE_Swift_COMPILER_TARGET"; -static std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES = +std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT"; +std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE"; +std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK"; +std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES = "CMAKE_TRY_COMPILE_OSX_ARCHITECTURES"; -static std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = +std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = "CMAKE_TRY_COMPILE_PLATFORM_VARIABLES"; -static std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED"; +std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED"; /* GHS Multi platform variables */ -static std::set<std::string> ghs_platform_vars{ +std::set<std::string> const ghs_platform_vars{ "GHS_TARGET_PLATFORM", "GHS_PRIMARY_TARGET", "GHS_TOOLSET_ROOT", "GHS_OS_ROOT", "GHS_OS_DIR", "GHS_BSP_NAME", "GHS_OS_DIR_OPTION" }; - -static void writeProperty(FILE* fout, std::string const& targetName, - std::string const& prop, std::string const& value) -{ - fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n", targetName.c_str(), - cmOutputConverter::EscapeForCMake(prop).c_str(), - cmOutputConverter::EscapeForCMake(value).c_str()); -} - -std::string cmCoreTryCompile::LookupStdVar(std::string const& var, - bool warnCMP0067) -{ - std::string value = this->Makefile->GetSafeDefinition(var); - if (warnCMP0067 && !value.empty()) { - value.clear(); - this->WarnCMP0067.push_back(var); - } - return value; } int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, @@ -107,9 +239,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, this->SrcFileSignature = true; cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE; - const std::string* tt = - this->Makefile->GetDef("CMAKE_TRY_COMPILE_TARGET_TYPE"); - if (!isTryRun && tt && !tt->empty()) { + cmProp tt = this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE"); + if (!isTryRun && cmNonempty(tt)) { if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) { targetType = cmStateEnums::EXECUTABLE; } else if (*tt == @@ -137,21 +268,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::string outputVariable; std::string copyFile; std::string copyFileError; - std::string cStandard; - std::string objcStandard; - std::string cxxStandard; - std::string objcxxStandard; - std::string cudaStandard; - std::string cStandardRequired; - std::string cxxStandardRequired; - std::string objcStandardRequired; - std::string objcxxStandardRequired; - std::string cudaStandardRequired; - std::string cExtensions; - std::string cxxExtensions; - std::string objcExtensions; - std::string objcxxExtensions; - std::string cudaExtensions; + LanguageStandardState cState("C"); + LanguageStandardState cudaState("CUDA"); + LanguageStandardState cxxState("CXX"); + LanguageStandardState objcState("OBJC"); + LanguageStandardState objcxxState("OBJCXX"); std::vector<std::string> targets; std::vector<std::string> linkOptions; std::string libsToLink = " "; @@ -160,21 +281,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, bool didOutputVariable = false; bool didCopyFile = false; bool didCopyFileError = false; - bool didCStandard = false; - bool didCxxStandard = false; - bool didObjCStandard = false; - bool didObjCxxStandard = false; - bool didCudaStandard = false; - bool didCStandardRequired = false; - bool didCxxStandardRequired = false; - bool didObjCStandardRequired = false; - bool didObjCxxStandardRequired = false; - bool didCudaStandardRequired = false; - bool didCExtensions = false; - bool didCxxExtensions = false; - bool didObjCExtensions = false; - bool didObjCxxExtensions = false; - bool didCudaExtensions = false; bool useSources = argv[2] == "SOURCES"; std::vector<std::string> sources; @@ -188,21 +294,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, DoingOutputVariable, DoingCopyFile, DoingCopyFileError, - DoingCStandard, - DoingCxxStandard, - DoingObjCStandard, - DoingObjCxxStandard, - DoingCudaStandard, - DoingCStandardRequired, - DoingCxxStandardRequired, - DoingObjCStandardRequired, - DoingObjCxxStandardRequired, - DoingCudaStandardRequired, - DoingCExtensions, - DoingCxxExtensions, - DoingObjCExtensions, - DoingObjCxxExtensions, - DoingCudaExtensions, DoingSources, DoingCMakeInternal }; @@ -226,51 +317,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } else if (argv[i] == "COPY_FILE_ERROR") { doing = DoingCopyFileError; didCopyFileError = true; - } else if (argv[i] == "C_STANDARD") { - doing = DoingCStandard; - didCStandard = true; - } else if (argv[i] == "CXX_STANDARD") { - doing = DoingCxxStandard; - didCxxStandard = true; - } else if (argv[i] == "OBJC_STANDARD") { - doing = DoingObjCStandard; - didObjCStandard = true; - } else if (argv[i] == "OBJCXX_STANDARD") { - doing = DoingObjCxxStandard; - didObjCxxStandard = true; - } else if (argv[i] == "CUDA_STANDARD") { - doing = DoingCudaStandard; - didCudaStandard = true; - } else if (argv[i] == "C_STANDARD_REQUIRED") { - doing = DoingCStandardRequired; - didCStandardRequired = true; - } else if (argv[i] == "CXX_STANDARD_REQUIRED") { - doing = DoingCxxStandardRequired; - didCxxStandardRequired = true; - } else if (argv[i] == "OBJC_STANDARD_REQUIRED") { - doing = DoingObjCStandardRequired; - didObjCStandardRequired = true; - } else if (argv[i] == "OBJCXX_STANDARD_REQUIRED") { - doing = DoingObjCxxStandardRequired; - didObjCxxStandardRequired = true; - } else if (argv[i] == "CUDA_STANDARD_REQUIRED") { - doing = DoingCudaStandardRequired; - didCudaStandardRequired = true; - } else if (argv[i] == "C_EXTENSIONS") { - doing = DoingCExtensions; - didCExtensions = true; - } else if (argv[i] == "CXX_EXTENSIONS") { - doing = DoingCxxExtensions; - didCxxExtensions = true; - } else if (argv[i] == "OBJC_EXTENSIONS") { - doing = DoingObjCExtensions; - didObjCExtensions = true; - } else if (argv[i] == "OBJCXX_EXTENSIONS") { - doing = DoingObjCxxExtensions; - didObjCxxExtensions = true; - } else if (argv[i] == "CUDA_EXTENSIONS") { - doing = DoingCudaExtensions; - didCudaExtensions = true; + } else if (cState.UpdateIfMatches(argv, i) || + cxxState.UpdateIfMatches(argv, i) || + cudaState.UpdateIfMatches(argv, i) || + objcState.UpdateIfMatches(argv, i) || + objcxxState.UpdateIfMatches(argv, i)) { + continue; } else if (argv[i] == "__CMAKE_INTERNAL") { doing = DoingCMakeInternal; } else if (doing == DoingCMakeFlags) { @@ -315,51 +367,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } else if (doing == DoingCopyFileError) { copyFileError = argv[i]; doing = DoingNone; - } else if (doing == DoingCStandard) { - cStandard = argv[i]; - doing = DoingNone; - } else if (doing == DoingCxxStandard) { - cxxStandard = argv[i]; - doing = DoingNone; - } else if (doing == DoingObjCStandard) { - objcStandard = argv[i]; - doing = DoingNone; - } else if (doing == DoingObjCxxStandard) { - objcxxStandard = argv[i]; - doing = DoingNone; - } else if (doing == DoingCudaStandard) { - cudaStandard = argv[i]; - doing = DoingNone; - } else if (doing == DoingCStandardRequired) { - cStandardRequired = argv[i]; - doing = DoingNone; - } else if (doing == DoingCxxStandardRequired) { - cxxStandardRequired = argv[i]; - doing = DoingNone; - } else if (doing == DoingObjCStandardRequired) { - objcStandardRequired = argv[i]; - doing = DoingNone; - } else if (doing == DoingObjCxxStandardRequired) { - objcxxStandardRequired = argv[i]; - doing = DoingNone; - } else if (doing == DoingCudaStandardRequired) { - cudaStandardRequired = argv[i]; - doing = DoingNone; - } else if (doing == DoingCExtensions) { - cExtensions = argv[i]; - doing = DoingNone; - } else if (doing == DoingCxxExtensions) { - cxxExtensions = argv[i]; - doing = DoingNone; - } else if (doing == DoingObjCExtensions) { - objcExtensions = argv[i]; - doing = DoingNone; - } else if (doing == DoingObjCxxExtensions) { - objcxxExtensions = argv[i]; - doing = DoingNone; - } else if (doing == DoingCudaExtensions) { - cudaExtensions = argv[i]; - doing = DoingNone; } else if (doing == DoingSources) { sources.push_back(argv[i]); } else if (doing == DoingCMakeInternal) { @@ -411,59 +418,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, return -1; } - if (didCStandard && !this->SrcFileSignature) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "C_STANDARD allowed only in source file signature."); - return -1; - } - if (didCxxStandard && !this->SrcFileSignature) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "CXX_STANDARD allowed only in source file signature."); - return -1; - } - if (didCudaStandard && !this->SrcFileSignature) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "CUDA_STANDARD allowed only in source file signature."); - return -1; - } - if (didCStandardRequired && !this->SrcFileSignature) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "C_STANDARD_REQUIRED allowed only in source file signature."); - return -1; - } - if (didCxxStandardRequired && !this->SrcFileSignature) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "CXX_STANDARD_REQUIRED allowed only in source file signature."); - return -1; - } - if (didCudaStandardRequired && !this->SrcFileSignature) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "CUDA_STANDARD_REQUIRED allowed only in source file signature."); - return -1; - } - if (didCExtensions && !this->SrcFileSignature) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "C_EXTENSIONS allowed only in source file signature."); - return -1; - } - if (didCxxExtensions && !this->SrcFileSignature) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "CXX_EXTENSIONS allowed only in source file signature."); - return -1; - } - if (didCudaExtensions && !this->SrcFileSignature) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "CUDA_EXTENSIONS allowed only in source file signature."); - return -1; + if (!this->SrcFileSignature) { + if (!cState.Validate(this->Makefile)) { + return -1; + } + if (!cudaState.Validate(this->Makefile)) { + return -1; + } + if (!cxxState.Validate(this->Makefile)) { + return -1; + } + if (!objcState.Validate(this->Makefile)) { + return -1; + } + if (!objcxxState.Validate(this->Makefile)) { + return -1; + } } // compute the binary dir when TRY_COMPILE is called with a src file @@ -532,6 +502,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } } + // when the only language is ISPC we know that the output + // type must by a static library + if (testLangs.size() == 1 && testLangs.count("ISPC") == 1) { + targetType = cmStateEnums::STATIC_LIBRARY; + } + std::string const tcConfig = this->Makefile->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"); @@ -552,19 +528,19 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, return -1; } - const char* def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH"); + cmProp def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH"); fprintf(fout, "cmake_minimum_required(VERSION %u.%u.%u.%u)\n", cmVersion::GetMajorVersion(), cmVersion::GetMinorVersion(), cmVersion::GetPatchVersion(), cmVersion::GetTweakVersion()); if (def) { - fprintf(fout, "set(CMAKE_MODULE_PATH \"%s\")\n", def); + fprintf(fout, "set(CMAKE_MODULE_PATH \"%s\")\n", def->c_str()); } /* Set MSVC runtime library policy to match our selection. */ - if (const char* msvcRuntimeLibraryDefault = + if (cmProp msvcRuntimeLibraryDefault = this->Makefile->GetDefinition(kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)) { fprintf(fout, "cmake_policy(SET CMP0091 %s)\n", - *msvcRuntimeLibraryDefault ? "NEW" : "OLD"); + !msvcRuntimeLibraryDefault->empty() ? "NEW" : "OLD"); } /* Set CUDA architectures policy to match outer project. */ @@ -580,14 +556,14 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, projectLangs += " " + li; std::string rulesOverrideBase = "CMAKE_USER_MAKE_RULES_OVERRIDE"; std::string rulesOverrideLang = cmStrCat(rulesOverrideBase, "_", li); - if (const char* rulesOverridePath = + if (cmProp rulesOverridePath = this->Makefile->GetDefinition(rulesOverrideLang)) { fprintf(fout, "set(%s \"%s\")\n", rulesOverrideLang.c_str(), - rulesOverridePath); - } else if (const char* rulesOverridePath2 = + rulesOverridePath->c_str()); + } else if (cmProp rulesOverridePath2 = this->Makefile->GetDefinition(rulesOverrideBase)) { fprintf(fout, "set(%s \"%s\")\n", rulesOverrideBase.c_str(), - rulesOverridePath2); + rulesOverridePath2->c_str()); } } fprintf(fout, "project(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str()); @@ -602,9 +578,9 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, fprintf(fout, "set(CMAKE_VERBOSE_MAKEFILE 1)\n"); for (std::string const& li : testLangs) { std::string langFlags = "CMAKE_" + li + "_FLAGS"; - const char* flags = this->Makefile->GetDefinition(langFlags); + cmProp flags = this->Makefile->GetDefinition(langFlags); fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li.c_str(), - cmOutputConverter::EscapeForCMake(flags ? flags : "").c_str()); + cmOutputConverter::EscapeForCMake(cmToCStrSafe(flags)).c_str()); fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}" " ${COMPILE_DEFINITIONS}\")\n", @@ -641,10 +617,10 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, for (std::string const& li : testLangs) { std::string const langFlagsCfg = cmStrCat("CMAKE_", li, "_FLAGS_", cfg); - const char* flagsCfg = this->Makefile->GetDefinition(langFlagsCfg); - fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(), - cmOutputConverter::EscapeForCMake(flagsCfg ? flagsCfg : "") - .c_str()); + cmProp flagsCfg = this->Makefile->GetDefinition(langFlagsCfg); + fprintf( + fout, "set(%s %s)\n", langFlagsCfg.c_str(), + cmOutputConverter::EscapeForCMake(cmToCStrSafe(flagsCfg)).c_str()); } } break; } @@ -674,12 +650,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, case cmPolicies::NEW: // NEW behavior is to pass linker flags. { - const char* exeLinkFlags = + cmProp exeLinkFlags = this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS"); - fprintf( - fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n", - cmOutputConverter::EscapeForCMake(exeLinkFlags ? exeLinkFlags : "") - .c_str()); + fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n", + cmOutputConverter::EscapeForCMake(cmToCStrSafe(exeLinkFlags)) + .c_str()); } break; } @@ -721,14 +696,28 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, // Forward a set of variables to the inner project cache. { std::set<std::string> vars; - vars.insert(kCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN); - vars.insert(kCMAKE_C_COMPILER_TARGET); - vars.insert(kCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN); - vars.insert(kCMAKE_CXX_COMPILER_TARGET); + vars.insert(&c_properties[lang_property_start], + &c_properties[lang_property_start + lang_property_size]); + vars.insert(&cxx_properties[lang_property_start], + &cxx_properties[lang_property_start + lang_property_size]); + vars.insert(&cuda_properties[lang_property_start], + &cuda_properties[lang_property_start + lang_property_size]); + vars.insert( + &fortran_properties[lang_property_start], + &fortran_properties[lang_property_start + lang_property_size]); + vars.insert(&objc_properties[lang_property_start], + &objc_properties[lang_property_start + lang_property_size]); + vars.insert( + &objcxx_properties[lang_property_start], + &objcxx_properties[lang_property_start + lang_property_size]); + vars.insert(&ispc_properties[lang_property_start], + &ispc_properties[lang_property_start + lang_property_size]); + vars.insert(&swift_properties[lang_property_start], + &swift_properties[lang_property_start + lang_property_size]); vars.insert(kCMAKE_CUDA_ARCHITECTURES); - vars.insert(kCMAKE_CUDA_COMPILER_TARGET); vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY); vars.insert(kCMAKE_ENABLE_EXPORTS); + vars.insert(kCMAKE_ISPC_INSTRUCTION_SETS); vars.insert(kCMAKE_LINK_SEARCH_END_STATIC); vars.insert(kCMAKE_LINK_SEARCH_START_STATIC); vars.insert(kCMAKE_OSX_ARCHITECTURES); @@ -739,13 +728,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, vars.insert(kCMAKE_SYSROOT); vars.insert(kCMAKE_SYSROOT_COMPILE); vars.insert(kCMAKE_SYSROOT_LINK); - vars.insert(kCMAKE_Swift_COMPILER_TARGET); vars.insert(kCMAKE_WARN_DEPRECATED); vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s); - if (const char* varListStr = this->Makefile->GetDefinition( + if (cmProp varListStr = this->Makefile->GetDefinition( kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) { - std::vector<std::string> varList = cmExpandedList(varListStr); + std::vector<std::string> varList = cmExpandedList(*varListStr); vars.insert(varList.begin(), varList.end()); } @@ -753,10 +741,24 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, cmPolicies::NEW) { // To ensure full support of PIE, propagate cache variables // driving the link options - vars.insert(kCMAKE_C_LINK_PIE_SUPPORTED); - vars.insert(kCMAKE_C_LINK_NO_PIE_SUPPORTED); - vars.insert(kCMAKE_CXX_LINK_PIE_SUPPORTED); - vars.insert(kCMAKE_CXX_LINK_NO_PIE_SUPPORTED); + vars.insert(&c_properties[pie_property_start], + &c_properties[pie_property_start + pie_property_size]); + vars.insert(&cxx_properties[pie_property_start], + &cxx_properties[pie_property_start + pie_property_size]); + vars.insert(&cuda_properties[pie_property_start], + &cuda_properties[pie_property_start + pie_property_size]); + vars.insert( + &fortran_properties[pie_property_start], + &fortran_properties[pie_property_start + pie_property_size]); + vars.insert(&objc_properties[pie_property_start], + &objc_properties[pie_property_start + pie_property_size]); + vars.insert( + &objcxx_properties[pie_property_start], + &objcxx_properties[pie_property_start + pie_property_size]); + vars.insert(&ispc_properties[pie_property_start], + &ispc_properties[pie_property_start + pie_property_size]); + vars.insert(&swift_properties[pie_property_start], + &swift_properties[pie_property_start + pie_property_size]); } /* for the TRY_COMPILEs we want to be able to specify the architecture. @@ -766,16 +768,16 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, cmLocalGenerator doesn't allow building for "the other" architecture only via CMAKE_OSX_ARCHITECTURES. */ - if (const char* tcArchs = this->Makefile->GetDefinition( + if (cmProp tcArchs = this->Makefile->GetDefinition( kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) { vars.erase(kCMAKE_OSX_ARCHITECTURES); - std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + std::string(tcArchs); + std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + *tcArchs; cmakeFlags.push_back(std::move(flag)); } for (std::string const& var : vars) { - if (const char* val = this->Makefile->GetDefinition(var)) { - std::string flag = "-D" + var + "=" + val; + if (cmProp val = this->Makefile->GetDefinition(var)) { + std::string flag = "-D" + var + "=" + *val; cmakeFlags.push_back(std::move(flag)); } } @@ -819,21 +821,17 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } fprintf(fout, ")\n"); - bool const testC = testLangs.find("C") != testLangs.end(); - bool const testObjC = testLangs.find("OBJC") != testLangs.end(); - bool const testCxx = testLangs.find("CXX") != testLangs.end(); - bool const testObjCxx = testLangs.find("OBJCXX") != testLangs.end(); - bool const testCuda = testLangs.find("CUDA") != testLangs.end(); + cState.Enabled(testLangs.find("C") != testLangs.end()); + cxxState.Enabled(testLangs.find("CXX") != testLangs.end()); + cudaState.Enabled(testLangs.find("CUDA") != testLangs.end()); + objcState.Enabled(testLangs.find("OBJC") != testLangs.end()); + objcxxState.Enabled(testLangs.find("OBJCXX") != testLangs.end()); bool warnCMP0067 = false; bool honorStandard = true; - if (!didCStandard && !didCxxStandard && !didObjCStandard && - !didObjCxxStandard && !didCudaStandard && !didCStandardRequired && - !didCxxStandardRequired && !didObjCStandardRequired && - !didObjCxxStandardRequired && !didCudaStandardRequired && - !didCExtensions && !didCxxExtensions && !didObjCExtensions && - !didObjCxxExtensions && !didCudaExtensions) { + if (cState.DidNone() && cxxState.DidNone() && objcState.DidNone() && + objcxxState.DidNone() && cudaState.DidNone()) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) { case cmPolicies::WARN: warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled( @@ -855,46 +853,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } } - if (honorStandard || warnCMP0067) { + std::vector<std::string> warnCMP0067Variables; - auto testLanguage = - [&](bool testLang, bool didLangStandard, bool didLangStandardRequired, - bool didLangExtensions, std::string& langStandard, - std::string& langStandardRequired, std::string& langExtensions, - const std::string& lang) { - if (testLang) { - if (!didLangStandard) { - langStandard = this->LookupStdVar( - cmStrCat("CMAKE_", lang, "_STANDARD"), warnCMP0067); - } - if (!didLangStandardRequired) { - langStandardRequired = this->LookupStdVar( - cmStrCat("CMAKE_", lang, "_STANDARD_REQUIRED"), warnCMP0067); - } - if (!didLangExtensions) { - langExtensions = this->LookupStdVar( - cmStrCat("CMAKE_", lang, "_EXTENSIONS"), warnCMP0067); - } - } - }; - - testLanguage(testC, didCStandard, didCStandardRequired, didCExtensions, - cStandard, cStandardRequired, cExtensions, "C"); - testLanguage(testObjC, didObjCStandard, didObjCStandardRequired, - didObjCExtensions, objcStandard, objcStandardRequired, - objcExtensions, "OBJC"); - testLanguage(testCxx, didCxxStandard, didCxxStandardRequired, - didCxxExtensions, cxxStandard, cxxStandardRequired, - cxxExtensions, "CXX"); - testLanguage(testObjCxx, didObjCxxStandard, didObjCxxStandardRequired, - didObjCxxExtensions, objcxxStandard, objcxxStandardRequired, - objcxxExtensions, "OBJCXX"); - testLanguage(testCuda, didCudaStandard, didCudaStandardRequired, - didCudaExtensions, cudaStandard, cudaStandardRequired, - cudaExtensions, "CUDA"); - } + cState.LoadUnsetPropertyValues(this->Makefile, honorStandard, warnCMP0067, + warnCMP0067Variables); + cxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard, + warnCMP0067, warnCMP0067Variables); + cudaState.LoadUnsetPropertyValues(this->Makefile, honorStandard, + warnCMP0067, warnCMP0067Variables); + objcState.LoadUnsetPropertyValues(this->Makefile, honorStandard, + warnCMP0067, warnCMP0067Variables); + objcxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard, + warnCMP0067, warnCMP0067Variables); - if (!this->WarnCMP0067.empty()) { + if (!warnCMP0067Variables.empty()) { std::ostringstream w; /* clang-format off */ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0067) << "\n" @@ -902,43 +874,17 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, "is not honoring language standard variables in the test project:\n" ; /* clang-format on */ - for (std::string const& vi : this->WarnCMP0067) { + for (std::string const& vi : warnCMP0067Variables) { w << " " << vi << "\n"; } this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } - auto writeLanguageProperties = [&](bool testLang, - const std::string& langStandard, - const std::string& langStandardRequired, - const std::string& langExtensions, - const std::string& lang) { - if (testLang) { - if (!langStandard.empty()) { - writeProperty(fout, targetName, cmStrCat(lang, "_STANDARD"), - langStandard); - } - if (!langStandardRequired.empty()) { - writeProperty(fout, targetName, cmStrCat(lang, "_STANDARD_REQUIRED"), - langStandardRequired); - } - if (!langExtensions.empty()) { - writeProperty(fout, targetName, cmStrCat(lang, "_EXTENSIONS"), - langExtensions); - } - } - }; - - writeLanguageProperties(testC, cStandard, cStandardRequired, cExtensions, - "C"); - writeLanguageProperties(testObjC, objcStandard, objcStandardRequired, - objcExtensions, "OBJC"); - writeLanguageProperties(testCxx, cxxStandard, cxxStandardRequired, - cxxExtensions, "CXX"); - writeLanguageProperties(testObjCxx, objcxxStandard, objcxxStandardRequired, - objcxxExtensions, "OBJCXX"); - writeLanguageProperties(testCuda, cudaStandard, cudaStandardRequired, - cudaExtensions, "CUDA"); + cState.WriteProperties(fout, targetName); + cxxState.WriteProperties(fout, targetName); + cudaState.WriteProperties(fout, targetName); + objcState.WriteProperties(fout, targetName); + objcxxState.WriteProperties(fout, targetName); if (!linkOptions.empty()) { std::vector<std::string> options; @@ -971,8 +917,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, if (this->Makefile->GetState()->UseGhsMultiIDE()) { // Forward the GHS variables to the inner project cache. for (std::string const& var : ghs_platform_vars) { - if (const char* val = this->Makefile->GetDefinition(var)) { - std::string flag = "-D" + var + "=" + "'" + val + "'"; + if (cmProp val = this->Makefile->GetDefinition(var)) { + std::string flag = "-D" + var + "=" + "'" + *val + "'"; cmakeFlags.push_back(std::move(flag)); } } @@ -1109,18 +1055,18 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName, std::vector<std::string> searchDirs; searchDirs.emplace_back(); - const char* config = + cmProp config = this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"); // if a config was specified try that first - if (config && config[0]) { - std::string tmp = cmStrCat('/', config); + if (cmNonempty(config)) { + std::string tmp = cmStrCat('/', *config); searchDirs.push_back(std::move(tmp)); } searchDirs.emplace_back("/Debug"); #if defined(__APPLE__) std::string app = "/" + targetName + ".app"; - if (config && config[0]) { - std::string tmp = cmStrCat('/', config, app); + if (cmNonempty(config)) { + std::string tmp = cmStrCat('/', *config, app); searchDirs.push_back(std::move(tmp)); } std::string tmp = "/Debug" + app; diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h index ae714a6..594fd7f 100644 --- a/Source/cmCoreTryCompile.h +++ b/Source/cmCoreTryCompile.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCoreTryCompile_h -#define cmCoreTryCompile_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -47,10 +46,4 @@ protected: std::string OutputFile; std::string FindErrorMessage; bool SrcFileSignature = false; - -private: - std::vector<std::string> WarnCMP0067; - std::string LookupStdVar(std::string const& var, bool warnCMP0067); }; - -#endif diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx index 9d492ba..9c4deea 100644 --- a/Source/cmCreateTestSourceList.cxx +++ b/Source/cmCreateTestSourceList.cxx @@ -127,7 +127,7 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args, mf.AddDefinition("CMAKE_FORWARD_DECLARE_TESTS", forwardDeclareCode); mf.AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES", functionMapCode); bool res = true; - if (!mf.ConfigureFile(configFile, driver, false, true, false)) { + if (!mf.ConfigureFile(configFile, driver, false, true, false, true)) { res = false; } diff --git a/Source/cmCreateTestSourceList.h b/Source/cmCreateTestSourceList.h index 19503f4..a7f11a6 100644 --- a/Source/cmCreateTestSourceList.h +++ b/Source/cmCreateTestSourceList.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCreateTestSourceList_h -#define cmCreateTestSourceList_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmCreateTestSourceList(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index f27bb5d..a2d45e7 100644 --- a/Source/cmCryptoHash.h +++ b/Source/cmCryptoHash.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCryptoHash_h -#define cmCryptoHash_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -85,5 +84,3 @@ private: unsigned int Id; struct rhash_context* CTX; }; - -#endif diff --git a/Source/cmCurl.h b/Source/cmCurl.h index 7bd036e..fb716f8 100644 --- a/Source/cmCurl.h +++ b/Source/cmCurl.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCurl_h -#define cmCurl_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = nullptr); std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level, const std::string& netrc_file); - -#endif diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h index aa572ad..2036e90 100644 --- a/Source/cmCustomCommand.h +++ b/Source/cmCustomCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCustomCommand_h -#define cmCustomCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -114,5 +113,3 @@ private: bool CommandExpandLists = false; bool StdPipesUTF8 = false; }; - -#endif diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 67ee9e0..412eba8 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCustomCommandGenerator_h -#define cmCustomCommandGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -47,5 +46,3 @@ public: std::vector<std::string> const& GetDepends() const; bool HasOnlyEmptyCommandLines() const; }; - -#endif diff --git a/Source/cmCustomCommandLines.h b/Source/cmCustomCommandLines.h index ead5792..ee8d080 100644 --- a/Source/cmCustomCommandLines.h +++ b/Source/cmCustomCommandLines.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCustomCommandLines_h -#define cmCustomCommandLines_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -28,5 +27,3 @@ cmCustomCommandLine cmMakeCommandLine( /** Return a command line vector with a single command line. */ cmCustomCommandLines cmMakeSingleCommandLine( std::initializer_list<cm::string_view> ilist); - -#endif diff --git a/Source/cmCustomCommandTypes.h b/Source/cmCustomCommandTypes.h index d4bf1f9..5c900ce 100644 --- a/Source/cmCustomCommandTypes.h +++ b/Source/cmCustomCommandTypes.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCustomCommandTypes_h -#define cmCustomCommandTypes_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -35,5 +34,3 @@ struct cmUtilityOutput std::string Name; std::string NameCMP0049; }; - -#endif diff --git a/Source/cmDefinePropertyCommand.h b/Source/cmDefinePropertyCommand.h index 60dd76a..3c478b3 100644 --- a/Source/cmDefinePropertyCommand.h +++ b/Source/cmDefinePropertyCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmDefinesPropertyCommand_h -#define cmDefinesPropertyCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmDefinePropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index 69a6427..4a4f87d 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -19,7 +19,6 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key, { auto it = begin->Map.find(cm::String::borrow(key)); if (it != begin->Map.end()) { - it->second.Used = true; return it->second; } } @@ -108,16 +107,3 @@ void cmDefinitions::Unset(const std::string& key) { this->Map[key] = Def(); } - -std::vector<std::string> cmDefinitions::UnusedKeys() const -{ - std::vector<std::string> keys; - keys.reserve(this->Map.size()); - // Consider local definitions. - for (auto const& mi : this->Map) { - if (!mi.second.Used) { - keys.push_back(*mi.first.str_if_stable()); - } - } - return keys; -} diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index 0e38fb1..b650aa8 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmDefinitions_h -#define cmDefinitions_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -48,9 +47,6 @@ public: /** Unset a definition. */ void Unset(const std::string& key); - /** List of unused keys. */ - std::vector<std::string> UnusedKeys() const; - private: /** String with existence boolean. */ struct Def @@ -62,7 +58,6 @@ private: { } cm::String Value; - bool Used = false; }; static Def NoDef; @@ -71,5 +66,3 @@ private: static Def const& GetInternal(const std::string& key, StackIter begin, StackIter end, bool raise); }; - -#endif diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index d8aa730..d092f4f 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -11,6 +11,7 @@ #include "cmGeneratedFileStream.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -228,19 +229,19 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends, void cmDepends::SetIncludePathFromLanguage(const std::string& lang) { // Look for the new per "TARGET_" variant first: - const char* includePath = nullptr; + cmProp includePath = nullptr; std::string includePathVar = cmStrCat("CMAKE_", lang, "_TARGET_INCLUDE_PATH"); cmMakefile* mf = this->LocalGenerator->GetMakefile(); includePath = mf->GetDefinition(includePathVar); if (includePath) { - cmExpandList(includePath, this->IncludePath); + cmExpandList(*includePath, this->IncludePath); } else { // Fallback to the old directory level variable if no per-target var: includePathVar = cmStrCat("CMAKE_", lang, "_INCLUDE_PATH"); includePath = mf->GetDefinition(includePathVar); if (includePath) { - cmExpandList(includePath, this->IncludePath); + cmExpandList(*includePath, this->IncludePath); } } } diff --git a/Source/cmDepends.h b/Source/cmDepends.h index 8cf528f..0240da9 100644 --- a/Source/cmDepends.h +++ b/Source/cmDepends.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmDepends_h -#define cmDepends_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -112,5 +111,3 @@ protected: void SetIncludePathFromLanguage(const std::string& lang); }; - -#endif diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index e05c964..e6aef92 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -9,6 +9,7 @@ #include "cmFileTime.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -38,13 +39,13 @@ cmDependsC::cmDependsC(cmLocalUnixMakefileGenerator3* lg, std::string complainRegex = "^$"; { std::string scanRegexVar = cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_SCAN"); - if (const char* sr = mf->GetDefinition(scanRegexVar)) { - scanRegex = sr; + if (cmProp sr = mf->GetDefinition(scanRegexVar)) { + scanRegex = *sr; } std::string complainRegexVar = cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_COMPLAIN"); - if (const char* cr = mf->GetDefinition(complainRegexVar)) { - complainRegex = cr; + if (cmProp cr = mf->GetDefinition(complainRegexVar)) { + complainRegex = *cr; } } diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index e01faa4..c79da1a 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmDependsC_h -#define cmDependsC_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -93,5 +92,3 @@ protected: void WriteCacheFile() const; void ReadCacheFile(); }; - -#endif diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 8f02d95..a239418 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -15,6 +15,7 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmOutputConverter.h" +#include "cmProperty.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" @@ -394,9 +395,9 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << modFile << ' ' << stampFileForShell; cmMakefile* mf = this->LocalGenerator->GetMakefile(); - const char* cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID"); - if (cid && *cid) { - makeDepends << ' ' << cid; + cmProp cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID"); + if (cmNonempty(cid)) { + makeDepends << ' ' << *cid; } makeDepends << '\n'; } diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index 3e306dd..e377a2c 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFortran_h -#define cmFortran_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -91,5 +90,3 @@ private: std::string MaybeConvertToRelativePath(std::string const& base, std::string const& path); }; - -#endif diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h index 2a90251..1db7ce1 100644 --- a/Source/cmDependsJava.h +++ b/Source/cmDependsJava.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmDependsJava_h -#define cmDependsJava_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -36,5 +35,3 @@ protected: const std::string& internalDependsFileName, DependencyMap& validDeps) override; }; - -#endif diff --git a/Source/cmDependsJavaParserHelper.h b/Source/cmDependsJavaParserHelper.h index c545ee2..869b7d4 100644 --- a/Source/cmDependsJavaParserHelper.h +++ b/Source/cmDependsJavaParserHelper.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmDependsJavaParserHelper_h -#define cmDependsJavaParserHelper_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -97,5 +96,3 @@ private: #define YYSTYPE_IS_DECLARED #define YY_EXTRA_TYPE cmDependsJavaParserHelper* #define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - -#endif diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 3768e1a..313be32 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef _cmDocumentation_h -#define _cmDocumentation_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -125,5 +124,3 @@ private: static void WarnFormFromFilename(RequestedHelpItem& request, bool& result); }; - -#endif diff --git a/Source/cmDocumentationEntry.h b/Source/cmDocumentationEntry.h index afbca5e..89a2899 100644 --- a/Source/cmDocumentationEntry.h +++ b/Source/cmDocumentationEntry.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmDocumentationEntry_h -#define cmDocumentationEntry_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -33,5 +32,3 @@ struct cmDocumentationEntry } } }; - -#endif diff --git a/Source/cmDocumentationFormatter.h b/Source/cmDocumentationFormatter.h index 17b63da..cb3038a 100644 --- a/Source/cmDocumentationFormatter.h +++ b/Source/cmDocumentationFormatter.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef _cmDocumentationFormatter_h -#define _cmDocumentationFormatter_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -62,5 +61,3 @@ private: int TextWidth = 77; const char* TextIndent = ""; }; - -#endif diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h index 641263d..276e520 100644 --- a/Source/cmDocumentationSection.h +++ b/Source/cmDocumentationSection.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef _cmDocumentationSection_h -#define _cmDocumentationSection_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -67,5 +66,3 @@ private: std::string Name; std::vector<cmDocumentationEntry> Entries; }; - -#endif diff --git a/Source/cmDynamicLoader.h b/Source/cmDynamicLoader.h index 4b89388..53ea5cb 100644 --- a/Source/cmDynamicLoader.h +++ b/Source/cmDynamicLoader.h @@ -5,8 +5,7 @@ // cmDynamicLoader provides a portable interface to loading dynamic // libraries into a process. -#ifndef cmDynamicLoader_h -#define cmDynamicLoader_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -29,5 +28,3 @@ protected: cmDynamicLoader() = default; ~cmDynamicLoader() = default; }; - -#endif diff --git a/Source/cmELF.h b/Source/cmELF.h index 123bf9b..99eb4f4 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmELF_h -#define cmELF_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -112,5 +111,3 @@ private: std::unique_ptr<cmELFInternal> Internal; std::string ErrorMessage; }; - -#endif diff --git a/Source/cmEnableLanguageCommand.h b/Source/cmEnableLanguageCommand.h index 1f8c4ce..730ba65 100644 --- a/Source/cmEnableLanguageCommand.h +++ b/Source/cmEnableLanguageCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmEnableLanguageCommand_h -#define cmEnableLanguageCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmEnableLanguageCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmEnableTestingCommand.h b/Source/cmEnableTestingCommand.h index e4593f2..1722511 100644 --- a/Source/cmEnableTestingCommand.h +++ b/Source/cmEnableTestingCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmEnableTestingCommand_h -#define cmEnableTestingCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -25,5 +24,3 @@ class cmExecutionStatus; */ bool cmEnableTestingCommand(std::vector<std::string> const&, cmExecutionStatus&); - -#endif diff --git a/Source/cmExecProgramCommand.h b/Source/cmExecProgramCommand.h index 7c751e1..111a56e 100644 --- a/Source/cmExecProgramCommand.h +++ b/Source/cmExecProgramCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExecProgramCommand_h -#define cmExecProgramCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -19,5 +18,3 @@ class cmExecutionStatus; */ bool cmExecProgramCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmExecuteProcessCommand.h b/Source/cmExecuteProcessCommand.h index 9c4b600..cc8cc38 100644 --- a/Source/cmExecuteProcessCommand.h +++ b/Source/cmExecuteProcessCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExecuteProcessCommand_h -#define cmExecuteProcessCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -18,5 +17,3 @@ class cmExecutionStatus; */ bool cmExecuteProcessCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h index d2cc9b8..0feaedf 100644 --- a/Source/cmExecutionStatus.h +++ b/Source/cmExecutionStatus.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExecutionStatus_h -#define cmExecutionStatus_h +#pragma once #include <cmConfigure.h> // IWYU pragma: keep @@ -48,5 +47,3 @@ private: bool ContinueInvoked = false; bool NestedError = false; }; - -#endif diff --git a/Source/cmExpandedCommandArgument.cxx b/Source/cmExpandedCommandArgument.cxx index 43f648b..1f14fc4 100644 --- a/Source/cmExpandedCommandArgument.cxx +++ b/Source/cmExpandedCommandArgument.cxx @@ -37,8 +37,3 @@ bool cmExpandedCommandArgument::empty() const { return this->Value.empty(); } - -const char* cmExpandedCommandArgument::c_str() const -{ - return this->Value.c_str(); -} diff --git a/Source/cmExpandedCommandArgument.h b/Source/cmExpandedCommandArgument.h index 69d35de..1ff6ed1 100644 --- a/Source/cmExpandedCommandArgument.h +++ b/Source/cmExpandedCommandArgument.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExpandedCommandArgument_h -#define cmExpandedCommandArgument_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -29,11 +28,7 @@ public: bool empty() const; - const char* c_str() const; - private: std::string Value; bool Quoted = false; }; - -#endif diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h index a9b6107..250564f 100644 --- a/Source/cmExportBuildAndroidMKGenerator.h +++ b/Source/cmExportBuildAndroidMKGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExportBuildAndroidMKGenerator_h -#define cmExportBuildAndroidMKGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -63,5 +62,3 @@ protected: cmGeneratorTarget const* target, std::ostream& os, const ImportPropertyMap& properties) override; }; - -#endif diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 66e8cbb..264494d 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExportBuildFileGenerator_h -#define cmExportBuildFileGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -85,5 +84,3 @@ protected: std::vector<cmGeneratorTarget*> Exports; cmLocalGenerator* LG; }; - -#endif diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 9f8a821..352eaf2 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -223,11 +223,9 @@ bool cmExportCommand(std::vector<std::string> const& args, ebfg->SetExportOld(arguments.ExportOld); // Compute the set of configurations exported. - std::vector<std::string> configurationTypes; - mf.GetConfigurations(configurationTypes); - if (configurationTypes.empty()) { - configurationTypes.emplace_back(); - } + std::vector<std::string> configurationTypes = + mf.GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + for (std::string const& ct : configurationTypes) { ebfg->AddConfiguration(ct); } diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h index 9655628..3f87bcf 100644 --- a/Source/cmExportCommand.h +++ b/Source/cmExportCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExportCommand_h -#define cmExportCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmExportCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 4d0e099..58aa391 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -567,8 +567,9 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( if (gtarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) { getCompatibleInterfaceProperties(gtarget, ifaceProperties, ""); - std::vector<std::string> configNames; - gtarget->Target->GetMakefile()->GetConfigurations(configNames); + std::vector<std::string> configNames = + gtarget->Target->GetMakefile()->GetGeneratorConfigs( + cmMakefile::ExcludeEmptyConfig); for (std::string const& cn : configNames) { getCompatibleInterfaceProperties(gtarget, ifaceProperties, cn); diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index e9d0da7..45eaed0 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExportFileGenerator_h -#define cmExportFileGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -223,5 +222,3 @@ private: virtual std::string InstallNameDir(cmGeneratorTarget* target, const std::string& config) = 0; }; - -#endif diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h index 8883ffa..40978e0 100644 --- a/Source/cmExportInstallAndroidMKGenerator.h +++ b/Source/cmExportInstallAndroidMKGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExportInstallAndroidMKGenerator_h -#define cmExportInstallAndroidMKGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -69,5 +68,3 @@ protected: bool GenerateImportFileConfig(const std::string& config, std::vector<std::string>&) override; }; - -#endif diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 5fa812c..2d8de9d 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExportInstallFileGenerator_h -#define cmExportInstallFileGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -103,5 +102,3 @@ protected: // The import file generated for each configuration. std::map<std::string, std::string> ConfigImportFiles; }; - -#endif diff --git a/Source/cmExportLibraryDependenciesCommand.h b/Source/cmExportLibraryDependenciesCommand.h index 230c906..1834bfa 100644 --- a/Source/cmExportLibraryDependenciesCommand.h +++ b/Source/cmExportLibraryDependenciesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExportLibraryDependenciesCommand_h -#define cmExportLibraryDependenciesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmExportLibraryDependenciesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h index f0d921f..07deb11 100644 --- a/Source/cmExportSet.h +++ b/Source/cmExportSet.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExportSet_h -#define cmExportSet_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -61,5 +60,3 @@ public: */ cmExportSet& operator[](const std::string& name); }; - -#endif diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index 7573427..6bf5781 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExportTryCompileFileGenerator_h -#define cmExportTryCompileFileGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -58,5 +57,3 @@ private: std::string Config; std::vector<std::string> Languages; }; - -#endif diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h index 717acdc..54dd6a4 100644 --- a/Source/cmExprParserHelper.h +++ b/Source/cmExprParserHelper.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExprParserHelper_h -#define cmExprParserHelper_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -58,5 +57,3 @@ private: #define YYSTYPE_IS_DECLARED #define YY_EXTRA_TYPE cmExprParserHelper* #define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - -#endif diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h index 2b8d505..3ade67b 100644 --- a/Source/cmExternalMakefileProjectGenerator.h +++ b/Source/cmExternalMakefileProjectGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExternalMakefileProjectGenerator_h -#define cmExternalMakefileProjectGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -109,5 +108,3 @@ public: return p; } }; - -#endif diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 32b0ca9..87b8f9b 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -16,6 +16,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmSourceFile.h" #include "cmStateTypes.h" @@ -95,7 +96,7 @@ struct Tree std::string path; // only one component of the path std::vector<Tree> folders; std::set<std::string> files; - void InsertPath(const std::vector<std::string>& splitted, + void InsertPath(const std::vector<std::string>& split, std::vector<std::string>::size_type start, const std::string& fileName); void BuildVirtualFolder(cmXMLWriter& xml) const; @@ -106,34 +107,34 @@ struct Tree const std::string& fsPath) const; }; -void Tree::InsertPath(const std::vector<std::string>& splitted, +void Tree::InsertPath(const std::vector<std::string>& split, std::vector<std::string>::size_type start, const std::string& fileName) { - if (start == splitted.size()) { + if (start == split.size()) { files.insert(fileName); return; } for (Tree& folder : folders) { - if (folder.path == splitted[start]) { - if (start + 1 < splitted.size()) { - folder.InsertPath(splitted, start + 1, fileName); + if (folder.path == split[start]) { + if (start + 1 < split.size()) { + folder.InsertPath(split, start + 1, fileName); return; } - // last part of splitted + // last part of split folder.files.insert(fileName); return; } } // Not found in folders, thus insert Tree newFolder; - newFolder.path = splitted[start]; - if (start + 1 < splitted.size()) { - newFolder.InsertPath(splitted, start + 1, fileName); + newFolder.path = split[start]; + if (start + 1 < split.size()) { + newFolder.InsertPath(split, start + 1, fileName); folders.push_back(newFolder); return; } - // last part of splitted + // last part of split newFolder.files.insert(fileName); folders.push_back(newFolder); } @@ -224,11 +225,11 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( const std::string& relative = cmSystemTools::RelativePath( it.second[0]->GetSourceDirectory(), listFile); - std::vector<std::string> splitted; - cmSystemTools::SplitPath(relative, splitted, false); + std::vector<std::string> split; + cmSystemTools::SplitPath(relative, split, false); // Split filename from path - std::string fileName = *(splitted.end() - 1); - splitted.erase(splitted.end() - 1, splitted.end()); + std::string fileName = *(split.end() - 1); + split.erase(split.end() - 1, split.end()); // We don't want paths with CMakeFiles in them // or do we? @@ -236,13 +237,12 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // // Also we can disable external (outside the project) files by setting ON // CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable. - const bool excludeExternal = - cmIsOn(it.second[0]->GetMakefile()->GetSafeDefinition( - "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES")); - if (!splitted.empty() && + const bool excludeExternal = it.second[0]->GetMakefile()->IsOn( + "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES"); + if (!split.empty() && (!excludeExternal || (relative.find("..") == std::string::npos)) && relative.find("CMakeFiles") == std::string::npos) { - tree.InsertPath(splitted, 1, fileName); + tree.InsertPath(split, 1, fileName); } } } @@ -370,7 +370,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( std::string lang = s->GetOrDetermineLanguage(); if (lang == "C" || lang == "CXX" || lang == "CUDA") { std::string const& srcext = s->GetExtension(); - isCFile = cm->IsSourceExtension(srcext); + isCFile = cm->IsACLikeSourceExtension(srcext); } std::string const& fullPath = s->ResolveFullPath(); @@ -380,9 +380,8 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( cmSystemTools::RelativePath(lg->GetSourceDirectory(), fullPath); // Do not add this file if it has ".." in relative path and // if CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable is on. - const bool excludeExternal = - cmIsOn(lg->GetMakefile()->GetSafeDefinition( - "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES")); + const bool excludeExternal = lg->GetMakefile()->IsOn( + "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES"); if (excludeExternal && (relative.find("..") != std::string::npos)) { continue; @@ -498,15 +497,15 @@ void cmExtraCodeBlocksGenerator::AppendTarget( if (target->GetType() == cmStateEnums::EXECUTABLE) { // Determine the directory where the executable target is created, and // set the working directory to this dir. - const char* runtimeOutputDir = + cmProp runtimeOutputDir = makefile->GetDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY"); - if (runtimeOutputDir != nullptr) { - workingDir = runtimeOutputDir; + if (runtimeOutputDir) { + workingDir = *runtimeOutputDir; } else { - const char* executableOutputDir = + cmProp executableOutputDir = makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"); - if (executableOutputDir != nullptr) { - workingDir = executableOutputDir; + if (executableOutputDir) { + workingDir = *executableOutputDir; } } } @@ -691,7 +690,8 @@ int cmExtraCodeBlocksGenerator::GetCBTargetType(cmGeneratorTarget* target) { switch (target->GetType()) { case cmStateEnums::EXECUTABLE: - if ((target->GetPropertyAsBool("WIN32_EXECUTABLE")) || + if ((target->IsWin32Executable( + target->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) || (target->GetPropertyAsBool("MACOSX_BUNDLE"))) { return 0; } diff --git a/Source/cmExtraCodeBlocksGenerator.h b/Source/cmExtraCodeBlocksGenerator.h index d9f92bd..cada5dd 100644 --- a/Source/cmExtraCodeBlocksGenerator.h +++ b/Source/cmExtraCodeBlocksGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExtraCodeBlocksGenerator_h -#define cmExtraCodeBlocksGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -51,5 +50,3 @@ private: const cmLocalGenerator* lg, const std::string& compiler, const std::string& makeFlags); }; - -#endif diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index bf7555d..95cfb0a 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -227,8 +227,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles( cmSystemTools::LowerCase(s->GetExtension()); // check whether it is a source or a include file // then put it accordingly into one of the two containers - if (cm->IsSourceExtension(extLower) || cm->IsCudaExtension(extLower) || - cm->IsFortranExtension(extLower)) { + if (cm->IsAKnownSourceExtension(extLower)) { cFiles[fullPath] = s; } else { otherFiles.insert(fullPath); diff --git a/Source/cmExtraCodeLiteGenerator.h b/Source/cmExtraCodeLiteGenerator.h index 0ce90b0..2478585 100644 --- a/Source/cmExtraCodeLiteGenerator.h +++ b/Source/cmExtraCodeLiteGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalCodeLiteGenerator_h -#define cmGlobalCodeLiteGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -68,5 +67,3 @@ public: void CreateNewProjectFile(const cmGeneratorTarget* lg, const std::string& filename); }; - -#endif diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 7bc4536..ccfd727 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -189,9 +189,9 @@ void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile() } fout << "eclipse.preferences.version=1\n"; - const char* encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING"); + cmProp encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING"); if (encoding) { - fout << "encoding/<project>=" << encoding << '\n'; + fout << "encoding/<project>=" << *encoding << '\n'; } } @@ -604,7 +604,7 @@ void cmExtraEclipseCDT4Generator::AppendIncludeDirectories( void cmExtraEclipseCDT4Generator::CreateCProjectFile() const { - std::set<std::string> emmited; + std::set<std::string> emitted; const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; const cmMakefile* mf = lg->GetMakefile(); @@ -751,7 +751,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const xml.EndElement(); // add pre-processor definitions to allow eclipse to gray out sections - emmited.clear(); + emitted.clear(); for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { if (cmProp cdefs = @@ -780,8 +780,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const } // insert the definition if not already added. - if (emmited.find(def) == emmited.end()) { - emmited.insert(def); + if (emitted.find(def) == emitted.end()) { + emitted.insert(def); xml.StartElement("pathentry"); xml.Attribute("kind", "mac"); xml.Attribute("name", def); @@ -793,11 +793,11 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const } } // add system defined c macros - const char* cDefs = + cmProp cDefs = mf->GetDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS"); if (this->CEnabled && cDefs) { // Expand the list. - std::vector<std::string> defs = cmExpandedList(cDefs, true); + std::vector<std::string> defs = cmExpandedList(*cDefs, true); // the list must contain only definition-value pairs: if ((defs.size() % 2) == 0) { @@ -812,8 +812,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const } // insert the definition if not already added. - if (emmited.find(def) == emmited.end()) { - emmited.insert(def); + if (emitted.find(def) == emitted.end()) { + emitted.insert(def); xml.StartElement("pathentry"); xml.Attribute("kind", "mac"); xml.Attribute("name", def); @@ -825,11 +825,11 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const } } // add system defined c++ macros - const char* cxxDefs = + cmProp cxxDefs = mf->GetDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS"); if (this->CXXEnabled && cxxDefs) { // Expand the list. - std::vector<std::string> defs = cmExpandedList(cxxDefs, true); + std::vector<std::string> defs = cmExpandedList(*cxxDefs, true); // the list must contain only definition-value pairs: if ((defs.size() % 2) == 0) { @@ -844,8 +844,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const } // insert the definition if not already added. - if (emmited.find(def) == emmited.end()) { - emmited.insert(def); + if (emitted.find(def) == emitted.end()) { + emitted.insert(def); xml.StartElement("pathentry"); xml.Attribute("kind", "mac"); xml.Attribute("name", def); @@ -858,7 +858,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const } // include dirs - emmited.clear(); + emitted.clear(); for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { const auto& targets = lgen->GetGeneratorTargets(); for (const auto& target : targets) { @@ -868,7 +868,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const std::vector<std::string> includeDirs; std::string config = mf->GetSafeDefinition("CMAKE_BUILD_TYPE"); lgen->GetIncludeDirectories(includeDirs, target.get(), "C", config); - this->AppendIncludeDirectories(xml, includeDirs, emmited); + this->AppendIncludeDirectories(xml, includeDirs, emitted); } } // now also the system include directories, in case we found them in @@ -879,14 +879,14 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const std::string systemIncludeDirs = mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS"); std::vector<std::string> dirs = cmExpandedList(systemIncludeDirs); - this->AppendIncludeDirectories(xml, dirs, emmited); + this->AppendIncludeDirectories(xml, dirs, emitted); } compiler = mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); if (this->CXXEnabled && !compiler.empty()) { std::string systemIncludeDirs = mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS"); std::vector<std::string> dirs = cmExpandedList(systemIncludeDirs); - this->AppendIncludeDirectories(xml, dirs, emmited); + this->AppendIncludeDirectories(xml, dirs, emitted); } xml.EndElement(); // storageModule @@ -895,7 +895,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const xml.StartElement("storageModule"); xml.Attribute("moduleId", "org.eclipse.cdt.make.core.buildtargets"); xml.StartElement("buildTargets"); - emmited.clear(); + emitted.clear(); const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); const std::string& makeArgs = mf->GetSafeDefinition("CMAKE_ECLIPSE_MAKE_ARGUMENTS"); diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h index a7aa549..c4ed577 100644 --- a/Source/cmExtraEclipseCDT4Generator.h +++ b/Source/cmExtraEclipseCDT4Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExtraEclipseCDT4Generator_h -#define cmExtraEclipseCDT4Generator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -106,5 +105,3 @@ private: bool CEnabled; bool CXXEnabled; }; - -#endif diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index 01fac5a..54c3114 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -13,6 +13,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -127,10 +128,10 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator& lg, // only add the "edit_cache" target if it's not ccmake, because // this will not work within the IDE if (targetName == "edit_cache") { - const char* editCommand = + cmProp editCommand = localGen->GetMakefile()->GetDefinition("CMAKE_EDIT_COMMAND"); if (editCommand == nullptr || - strstr(editCommand, "ccmake") != nullptr) { + strstr(editCommand->c_str(), "ccmake") != nullptr) { insertTarget = false; } } diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h index 1fb81b4..c66ddbf 100644 --- a/Source/cmExtraKateGenerator.h +++ b/Source/cmExtraKateGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExtraKateGenerator_h -#define cmExtraKateGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -43,5 +42,3 @@ private: std::string ProjectName; bool UseNinja; }; - -#endif diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 613a943..3e265a0 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -349,6 +349,13 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject( if (language.empty()) { language = "C"; } + + // explicitly add the explicit language flag before any other flag + // this way backwards compatibility with user flags is maintained + if (source->GetProperty("LANGUAGE")) { + lg->AppendFeatureOptions(flags, language, "EXPLICIT_LANGUAGE"); + } + std::string const& config = lg->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h index 078cfe7..671b65a 100644 --- a/Source/cmExtraSublimeTextGenerator.h +++ b/Source/cmExtraSublimeTextGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmExtraSublimeTextGenerator_h -#define cmExtraSublimeTextGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -75,5 +74,3 @@ private: bool ExcludeBuildFolder; std::string EnvSettings; }; - -#endif diff --git a/Source/cmFLTKWrapUICommand.h b/Source/cmFLTKWrapUICommand.h index bb56dbd..7c1fc52 100644 --- a/Source/cmFLTKWrapUICommand.h +++ b/Source/cmFLTKWrapUICommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFLTKWrapUICommand_h -#define cmFLTKWrapUICommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmFLTKWrapUICommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmFSPermissions.h b/Source/cmFSPermissions.h index fef72e6..78f2240 100644 --- a/Source/cmFSPermissions.h +++ b/Source/cmFSPermissions.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFSPermissions_h -#define cmFSPermissions_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -41,5 +40,3 @@ static const mode_t mode_setgid = S_ISGID; bool stringToModeT(std::string const& arg, mode_t& permissions); } // ns - -#endif diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx index 594969b..c2ab2f1 100644 --- a/Source/cmFileAPI.cxx +++ b/Source/cmFileAPI.cxx @@ -665,7 +665,7 @@ std::string cmFileAPI::NoSupportedVersion( // The "codemodel" object kind. -static unsigned int const CodeModelV2Minor = 1; +static unsigned int const CodeModelV2Minor = 2; void cmFileAPI::BuildClientRequestCodeModel( ClientRequest& r, std::vector<RequestVersion> const& versions) diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h index ae07612..086a92a 100644 --- a/Source/cmFileAPI.h +++ b/Source/cmFileAPI.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileAPI_h -#define cmFileAPI_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -205,5 +204,3 @@ private: ClientRequest& r, std::vector<RequestVersion> const& versions); Json::Value BuildInternalTest(Object const& object); }; - -#endif diff --git a/Source/cmFileAPICMakeFiles.h b/Source/cmFileAPICMakeFiles.h index 1ae1e4f..5b48ed3 100644 --- a/Source/cmFileAPICMakeFiles.h +++ b/Source/cmFileAPICMakeFiles.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileAPICMakeFiles_h -#define cmFileAPICMakeFiles_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -11,5 +10,3 @@ class cmFileAPI; extern Json::Value cmFileAPICMakeFilesDump(cmFileAPI& fileAPI, unsigned long version); - -#endif diff --git a/Source/cmFileAPICache.h b/Source/cmFileAPICache.h index 2f30c76..bd9feeb 100644 --- a/Source/cmFileAPICache.h +++ b/Source/cmFileAPICache.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileAPICache_h -#define cmFileAPICache_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -11,5 +10,3 @@ class cmFileAPI; extern Json::Value cmFileAPICacheDump(cmFileAPI& fileAPI, unsigned long version); - -#endif diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index fe331ec..4a53c8a 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -175,6 +175,38 @@ public: } }; +template <typename T> +class JBTs +{ +public: + JBTs(T v = T(), std::vector<JBTIndex> ids = std::vector<JBTIndex>()) + : Value(std::move(v)) + , Backtraces(std::move(ids)) + { + } + T Value; + std::vector<JBTIndex> Backtraces; + friend bool operator==(JBTs<T> const& l, JBTs<T> const& r) + { + if ((l.Value == r.Value) && (l.Backtraces.size() == r.Backtraces.size())) { + for (size_t i = 0; i < l.Backtraces.size(); i++) { + if (l.Backtraces[i].Index != r.Backtraces[i].Index) { + return false; + } + } + } + return true; + } + static bool ValueEq(JBTs<T> const& l, JBTs<T> const& r) + { + return l.Value == r.Value; + } + static bool ValueLess(JBTs<T> const& l, JBTs<T> const& r) + { + return l.Value < r.Value; + } +}; + class BacktraceData { std::string TopSource; @@ -277,6 +309,7 @@ struct CompileData std::string Language; std::string Sysroot; + JBTs<std::string> LanguageStandard; std::vector<JBT<std::string>> Flags; std::vector<JBT<std::string>> Defines; std::vector<JBT<std::string>> PrecompileHeaders; @@ -287,6 +320,7 @@ struct CompileData return (l.Language == r.Language && l.Sysroot == r.Sysroot && l.Flags == r.Flags && l.Defines == r.Defines && l.PrecompileHeaders == r.PrecompileHeaders && + l.LanguageStandard == r.LanguageStandard && l.Includes == r.Includes); } }; @@ -320,6 +354,12 @@ struct hash<CompileData> result = result ^ hash<std::string>()(i.Value) ^ hash<Json::ArrayIndex>()(i.Backtrace.Index); } + if (!in.LanguageStandard.Value.empty()) { + result = result ^ hash<std::string>()(in.LanguageStandard.Value); + for (JBTIndex backtrace : in.LanguageStandard.Backtraces) { + result = result ^ hash<Json::ArrayIndex>()(backtrace.Index); + } + } return result; } }; @@ -363,6 +403,16 @@ class Target return JBT<T>(bt.Value, this->Backtraces.Add(bt.Backtrace)); } + template <typename T> + JBTs<T> ToJBTs(BTs<T> const& bts) + { + std::vector<JBTIndex> ids; + for (cmListFileBacktrace const& backtrace : bts.Backtraces) { + ids.emplace_back(this->Backtraces.Add(backtrace)); + } + return JBTs<T>(bts.Value, ids); + } + void ProcessLanguages(); void ProcessLanguage(std::string const& lang); @@ -377,6 +427,7 @@ class Target Json::Value DumpCompileData(CompileData const& cd); Json::Value DumpInclude(CompileData::IncludeEntry const& inc); Json::Value DumpPrecompileHeader(JBT<std::string> const& header); + Json::Value DumpLanguageStandard(JBTs<std::string> const& standard); Json::Value DumpDefine(JBT<std::string> const& def); Json::Value DumpSources(); Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk, @@ -438,7 +489,7 @@ Json::Value Codemodel::DumpConfigurations() const auto& makefiles = gg->GetMakefiles(); if (!makefiles.empty()) { std::vector<std::string> const& configs = - makefiles[0]->GetGeneratorConfigs(); + makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); for (std::string const& config : configs) { configurations.append(this->DumpConfiguration(config)); } @@ -574,7 +625,7 @@ Json::Value CodemodelConfig::DumpTargets() for (cmGeneratorTarget* gt : targetList) { if (gt->GetType() == cmStateEnums::GLOBAL_TARGET || - gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + !gt->IsInBuildSystem()) { continue; } @@ -801,12 +852,12 @@ void Target::ProcessLanguage(std::string const& lang) { CompileData& cd = this->CompileDataMap[lang]; cd.Language = lang; - if (const char* sysrootCompile = + if (cmProp sysrootCompile = this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { - cd.Sysroot = sysrootCompile; - } else if (const char* sysroot = + cd.Sysroot = *sysrootCompile; + } else if (cmProp sysroot = this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) { - cd.Sysroot = sysroot; + cd.Sysroot = *sysroot; } cmLocalGenerator* lg = this->GT->GetLocalGenerator(); { @@ -838,6 +889,11 @@ void Target::ProcessLanguage(std::string const& lang) for (BT<std::string> const& pch : precompileHeaders) { cd.PrecompileHeaders.emplace_back(this->ToJBT(pch)); } + BTs<std::string> const* languageStandard = + this->GT->GetLanguageStandardProperty(lang, this->Config); + if (languageStandard) { + cd.LanguageStandard = this->ToJBTs(*languageStandard); + } } Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si) @@ -996,6 +1052,9 @@ CompileData Target::MergeCompileData(CompileData const& fd) // All compile groups share the precompile headers of the target. cd.PrecompileHeaders = td.PrecompileHeaders; + // All compile groups share the language standard of the target. + cd.LanguageStandard = td.LanguageStandard; + // Use target-wide flags followed by source-specific flags. cd.Flags.reserve(td.Flags.size() + fd.Flags.size()); cd.Flags.insert(cd.Flags.end(), td.Flags.begin(), td.Flags.end()); @@ -1153,6 +1212,10 @@ Json::Value Target::DumpCompileData(CompileData const& cd) } result["precompileHeaders"] = std::move(precompileHeaders); } + if (!cd.LanguageStandard.Value.empty()) { + result["languageStandard"] = + this->DumpLanguageStandard(cd.LanguageStandard); + } return result; } @@ -1176,6 +1239,20 @@ Json::Value Target::DumpPrecompileHeader(JBT<std::string> const& header) return precompileHeader; } +Json::Value Target::DumpLanguageStandard(JBTs<std::string> const& standard) +{ + Json::Value languageStandard = Json::objectValue; + languageStandard["standard"] = standard.Value; + if (!standard.Backtraces.empty()) { + Json::Value backtraces = Json::arrayValue; + for (JBTIndex backtrace : standard.Backtraces) { + backtraces.append(backtrace.Index); + } + languageStandard["backtraces"] = backtraces; + } + return languageStandard; +} + Json::Value Target::DumpDefine(JBT<std::string> const& def) { Json::Value define = Json::objectValue; @@ -1327,12 +1404,12 @@ Json::Value Target::DumpLink() link["commandFragments"] = std::move(commandFragments); } } - if (const char* sysrootLink = + if (cmProp sysrootLink = this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) { - link["sysroot"] = this->DumpSysroot(sysrootLink); - } else if (const char* sysroot = + link["sysroot"] = this->DumpSysroot(*sysrootLink); + } else if (cmProp sysroot = this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) { - link["sysroot"] = this->DumpSysroot(sysroot); + link["sysroot"] = this->DumpSysroot(*sysroot); } if (this->GT->IsIPOEnabled(lang, this->Config)) { link["lto"] = true; diff --git a/Source/cmFileAPICodemodel.h b/Source/cmFileAPICodemodel.h index a6c6bdd..263f675 100644 --- a/Source/cmFileAPICodemodel.h +++ b/Source/cmFileAPICodemodel.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileAPICodemodel_h -#define cmFileAPICodemodel_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -11,5 +10,3 @@ class cmFileAPI; extern Json::Value cmFileAPICodemodelDump(cmFileAPI& fileAPI, unsigned long version); - -#endif diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 7101e22..84639a7 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -28,8 +28,10 @@ #include "cmAlgorithms.h" #include "cmArgumentParser.h" +#include "cmCMakePath.h" #include "cmCryptoHash.h" #include "cmExecutionStatus.h" +#include "cmFSPermissions.h" #include "cmFileCopier.h" #include "cmFileInstaller.h" #include "cmFileLockPool.h" @@ -43,6 +45,7 @@ #include "cmMessageType.h" #include "cmNewLineStyle.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmRuntimeDependencyArchive.h" #include "cmState.h" @@ -1232,6 +1235,50 @@ bool HandleInstallCommand(std::vector<std::string> const& args, return installer.Run(args); } +bool HandleRealPathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() < 3) { + status.SetError("REAL_PATH requires a path and an output variable"); + return false; + } + + struct Arguments + { + std::string BaseDirectory; + }; + static auto const parser = cmArgumentParser<Arguments>{}.Bind( + "BASE_DIRECTORY"_s, &Arguments::BaseDirectory); + + std::vector<std::string> unparsedArguments; + std::vector<std::string> keywordsMissingValue; + std::vector<std::string> parsedKeywords; + auto arguments = + parser.Parse(cmMakeRange(args).advance(3), &unparsedArguments, + &keywordsMissingValue, &parsedKeywords); + + if (!unparsedArguments.empty()) { + status.SetError("REAL_PATH called with unexpected arguments"); + return false; + } + if (!keywordsMissingValue.empty()) { + status.SetError("BASE_DIRECTORY requires a value"); + return false; + } + + if (parsedKeywords.empty()) { + arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory(); + } + + cmCMakePath path(args[1]); + path = path.Absolute(arguments.BaseDirectory).Normal(); + auto realPath = cmSystemTools::GetRealPath(path.GenericString()); + + status.GetMakefile().AddDefinition(args[2], realPath); + + return true; +} + bool HandleRelativePathCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -1394,8 +1441,10 @@ size_t cmWriteToFileCallback(void* ptr, size_t size, size_t nmemb, void* data) { int realsize = static_cast<int>(size * nmemb); cmsys::ofstream* fout = static_cast<cmsys::ofstream*>(data); - const char* chPtr = static_cast<char*>(ptr); - fout->write(chPtr, realsize); + if (fout) { + const char* chPtr = static_cast<char*>(ptr); + fout->write(chPtr, realsize); + } return realsize; } @@ -1551,22 +1600,21 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, { #if !defined(CMAKE_BOOTSTRAP) auto i = args.begin(); - if (args.size() < 3) { - status.SetError("DOWNLOAD must be called with at least three arguments."); + if (args.size() < 2) { + status.SetError("DOWNLOAD must be called with at least two arguments."); return false; } ++i; // Get rid of subcommand std::string url = *i; ++i; - std::string file = *i; - ++i; + std::string file; long timeout = 0; long inactivity_timeout = 0; std::string logVar; std::string statusVar; bool tls_verify = status.GetMakefile().IsOn("CMAKE_TLS_VERIFY"); - const char* cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO"); + cmProp cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO"); std::string netrc_level = status.GetMakefile().GetSafeDefinition("CMAKE_NETRC"); std::string netrc_file = @@ -1621,7 +1669,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, } else if (*i == "TLS_CAINFO") { ++i; if (i != args.end()) { - cainfo = i->c_str(); + cainfo = &(*i); } else { status.SetError("DOWNLOAD missing file value for TLS_CAINFO."); return false; @@ -1690,6 +1738,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, return false; } curl_headers.push_back(*i); + } else if (file.empty()) { + file = *i; } else { // Do not return error for compatibility reason. std::string err = cmStrCat("Unexpected argument: ", *i); @@ -1697,11 +1747,18 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, } ++i; } + // Can't calculate hash if we don't save the file. + // TODO Incrementally calculate hash in the write callback as the file is + // being downloaded so this check can be relaxed. + if (file.empty() && hash) { + status.SetError("DOWNLOAD cannot calculate hash if file is not saved."); + return false; + } // If file exists already, and caller specified an expected md5 or sha, // and the existing file already has the expected hash, then simply // return. // - if (cmSystemTools::FileExists(file) && hash.get()) { + if (!file.empty() && cmSystemTools::FileExists(file) && hash.get()) { std::string msg; std::string actualHash = hash->HashFile(file); if (actualHash == expectedHash) { @@ -1716,20 +1773,26 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, // Make sure parent directory exists so we can write to the file // as we receive downloaded bits from curl... // - std::string dir = cmSystemTools::GetFilenamePath(file); - if (!dir.empty() && !cmSystemTools::FileExists(dir) && - !cmSystemTools::MakeDirectory(dir)) { - std::string errstring = "DOWNLOAD error: cannot create directory '" + dir + - "' - Specify file by full path name and verify that you " - "have directory creation and file write privileges."; - status.SetError(errstring); - return false; + if (!file.empty()) { + std::string dir = cmSystemTools::GetFilenamePath(file); + if (!dir.empty() && !cmSystemTools::FileExists(dir) && + !cmSystemTools::MakeDirectory(dir)) { + std::string errstring = "DOWNLOAD error: cannot create directory '" + + dir + + "' - Specify file by full path name and verify that you " + "have directory creation and file write privileges."; + status.SetError(errstring); + return false; + } } - cmsys::ofstream fout(file.c_str(), std::ios::binary); - if (!fout) { - status.SetError("DOWNLOAD cannot open file for write."); - return false; + cmsys::ofstream fout; + if (!file.empty()) { + fout.open(file.c_str(), std::ios::binary); + if (!fout) { + status.SetError("DOWNLOAD cannot open file for write."); + return false; + } } # if defined(_WIN32) @@ -1773,7 +1836,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, // check to see if a CAINFO file has been specified // command arg comes first - std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo); + std::string const& cainfo_err = cmCurlSetCAInfo(curl, cmToCStr(cainfo)); if (!cainfo_err.empty()) { status.SetError(cainfo_err); return false; @@ -1791,7 +1854,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, cmFileCommandVectorOfChar chunkDebug; - res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fout); + res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, + file.empty() ? nullptr : &fout); check_curl_result(res, "DOWNLOAD cannot set write data: "); res = ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &chunkDebug); @@ -1865,8 +1929,10 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, // Explicitly flush/close so we can measure the md5 accurately. // - fout.flush(); - fout.close(); + if (!file.empty()) { + fout.flush(); + fout.close(); + } // Verify MD5 sum if requested: // @@ -1936,7 +2002,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args, std::string statusVar; bool showProgress = false; bool tls_verify = status.GetMakefile().IsOn("CMAKE_TLS_VERIFY"); - const char* cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO"); + cmProp cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO"); std::string userpwd; std::string netrc_level = status.GetMakefile().GetSafeDefinition("CMAKE_NETRC"); @@ -1989,7 +2055,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args, } else if (*i == "TLS_CAINFO") { ++i; if (i != args.end()) { - cainfo = i->c_str(); + cainfo = &(*i); } else { status.SetError("UPLOAD missing file value for TLS_CAINFO."); return false; @@ -2090,7 +2156,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args, // check to see if a CAINFO file has been specified // command arg comes first - std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo); + std::string const& cainfo_err = cmCurlSetCAInfo(curl, cmToCStr(cainfo)); if (!cainfo_err.empty()) { status.SetError(cainfo_err); return false; @@ -2221,6 +2287,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args, } void AddEvaluationFile(const std::string& inputName, + const std::string& targetName, const std::string& outputExpr, const std::string& condition, bool inputIsContent, cmExecutionStatus& status) @@ -2236,7 +2303,8 @@ void AddEvaluationFile(const std::string& inputName, conditionGe.Parse(condition); status.GetMakefile().AddEvaluationFile( - inputName, std::move(outputCge), std::move(conditionCge), inputIsContent); + inputName, targetName, std::move(outputCge), std::move(conditionCge), + inputIsContent); } bool HandleGenerateCommand(std::vector<std::string> const& args, @@ -2250,23 +2318,36 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, status.SetError("Incorrect arguments to GENERATE subcommand."); return false; } + std::string condition; - if (args.size() > 5) { - if (args[5] != "CONDITION") { + std::string target; + + for (std::size_t i = 5; i < args.size();) { + const std::string& arg = args[i++]; + + if (args.size() - i == 0) { status.SetError("Incorrect arguments to GENERATE subcommand."); return false; } - if (args.size() != 7) { - status.SetError("Incorrect arguments to GENERATE subcommand."); + + const std::string& value = args[i++]; + + if (value.empty()) { + status.SetError( + arg + " of sub-command GENERATE must not be empty if specified."); return false; } - condition = args[6]; - if (condition.empty()) { - status.SetError("CONDITION of sub-command GENERATE must not be empty if " - "specified."); + + if (arg == "CONDITION") { + condition = value; + } else if (arg == "TARGET") { + target = value; + } else { + status.SetError("Unknown argument to GENERATE subcommand."); return false; } } + std::string output = args[2]; const bool inputIsContent = args[3] != "INPUT"; if (inputIsContent && args[3] != "CONTENT") { @@ -2275,7 +2356,7 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, } std::string input = args[4]; - AddEvaluationFile(input, output, condition, inputIsContent, status); + AddEvaluationFile(input, target, output, condition, inputIsContent, status); return true; } @@ -2918,7 +2999,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args, } fout.SetCopyIfDifferent(true); - // copy intput to output and expand variables from input at the same time + // copy input to output and expand variables from input at the same time std::stringstream sin(input, std::ios::in); std::string inLine; std::string outLine; @@ -3126,6 +3207,163 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args, return true; } +bool ValidateAndConvertPermissions(const std::vector<std::string>& permissions, + mode_t& perms, cmExecutionStatus& status) +{ + for (const auto& i : permissions) { + if (!cmFSPermissions::stringToModeT(i, perms)) { + status.SetError(i + " is an invalid permission specifier"); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + } + return true; +} + +bool SetPermissions(const std::string& filename, const mode_t& perms, + cmExecutionStatus& status) +{ + if (!cmSystemTools::SetPermissions(filename, perms)) { + status.SetError("Failed to set permissions for " + filename); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + return true; +} + +bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse, + cmExecutionStatus& status) +{ + mode_t perms = 0; + mode_t fperms = 0; + mode_t dperms = 0; + cmsys::Glob globber; + + globber.SetRecurse(recurse); + globber.SetRecurseListDirs(recurse); + + struct Arguments + { + std::vector<std::string> Permissions; + std::vector<std::string> FilePermissions; + std::vector<std::string> DirectoryPermissions; + }; + + static auto const parser = + cmArgumentParser<Arguments>{} + .Bind("PERMISSIONS"_s, &Arguments::Permissions) + .Bind("FILE_PERMISSIONS"_s, &Arguments::FilePermissions) + .Bind("DIRECTORY_PERMISSIONS"_s, &Arguments::DirectoryPermissions); + + std::vector<std::string> pathEntries; + std::vector<std::string> keywordsMissingValues; + Arguments parsedArgs = parser.Parse(cmMakeRange(args).advance(1), + &pathEntries, &keywordsMissingValues); + + // check validity of arguments + if (parsedArgs.Permissions.empty() && parsedArgs.FilePermissions.empty() && + parsedArgs.DirectoryPermissions.empty()) // no permissions given + { + status.SetError("No permissions given"); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (!parsedArgs.Permissions.empty() && !parsedArgs.FilePermissions.empty() && + !parsedArgs.DirectoryPermissions.empty()) // all keywords are used + { + status.SetError("Remove either PERMISSIONS or FILE_PERMISSIONS or " + "DIRECTORY_PERMISSIONS from the invocation"); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (!keywordsMissingValues.empty()) { + for (const auto& i : keywordsMissingValues) { + status.SetError(i + " is not given any arguments"); + cmSystemTools::SetFatalErrorOccured(); + } + return false; + } + + // validate permissions + bool validatePermissions = + ValidateAndConvertPermissions(parsedArgs.Permissions, perms, status) && + ValidateAndConvertPermissions(parsedArgs.FilePermissions, fperms, + status) && + ValidateAndConvertPermissions(parsedArgs.DirectoryPermissions, dperms, + status); + if (!validatePermissions) { + return false; + } + + std::vector<std::string> allPathEntries; + + if (recurse) { + std::vector<std::string> tempPathEntries; + for (const auto& i : pathEntries) { + if (cmSystemTools::FileIsDirectory(i)) { + globber.FindFiles(i + "/*"); + tempPathEntries = globber.GetFiles(); + allPathEntries.insert(allPathEntries.end(), tempPathEntries.begin(), + tempPathEntries.end()); + allPathEntries.emplace_back(i); + } else { + allPathEntries.emplace_back(i); // We validate path entries below + } + } + } else { + allPathEntries = std::move(pathEntries); + } + + // chmod + for (const auto& i : allPathEntries) { + if (!(cmSystemTools::FileExists(i) || cmSystemTools::FileIsDirectory(i))) { + status.SetError(cmStrCat("does not exist:\n ", i)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (cmSystemTools::FileExists(i, true)) { + bool success = true; + const mode_t& filePermissions = + parsedArgs.FilePermissions.empty() ? perms : fperms; + if (filePermissions) { + success = SetPermissions(i, filePermissions, status); + } + if (!success) { + return false; + } + } + + else if (cmSystemTools::FileIsDirectory(i)) { + bool success = true; + const mode_t& directoryPermissions = + parsedArgs.DirectoryPermissions.empty() ? perms : dperms; + if (directoryPermissions) { + success = SetPermissions(i, directoryPermissions, status); + } + if (!success) { + return false; + } + } + } + + return true; +} + +bool HandleChmodCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleChmodCommandImpl(args, false, status); +} + +bool HandleChmodRecurseCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleChmodCommandImpl(args, true, status); +} + } // namespace bool cmFileCommand(std::vector<std::string> const& args, @@ -3167,6 +3405,7 @@ bool cmFileCommand(std::vector<std::string> const& args, { "RPATH_CHECK"_s, HandleRPathCheckCommand }, { "RPATH_REMOVE"_s, HandleRPathRemoveCommand }, { "READ_ELF"_s, HandleReadElfCommand }, + { "REAL_PATH"_s, HandleRealPathCommand }, { "RELATIVE_PATH"_s, HandleRelativePathCommand }, { "TO_CMAKE_PATH"_s, HandleCMakePathCommand }, { "TO_NATIVE_PATH"_s, HandleNativePathCommand }, @@ -3182,6 +3421,8 @@ bool cmFileCommand(std::vector<std::string> const& args, { "CONFIGURE"_s, HandleConfigureCommand }, { "ARCHIVE_CREATE"_s, HandleArchiveCreateCommand }, { "ARCHIVE_EXTRACT"_s, HandleArchiveExtractCommand }, + { "CHMOD"_s, HandleChmodCommand }, + { "CHMOD_RECURSE"_s, HandleChmodRecurseCommand }, }; return subcommand(args[0], args, status); diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 8c9b219..ec9ee47 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileCommand_h -#define cmFileCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmFileCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx index 627e05b..48fc286 100644 --- a/Source/cmFileCopier.cxx +++ b/Source/cmFileCopier.cxx @@ -10,6 +10,7 @@ #include "cmFSPermissions.h" #include "cmFileTimes.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -171,11 +172,11 @@ void cmFileCopier::DefaultDirectoryPermissions() bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode) { // check if default dir creation permissions were set - const char* default_dir_install_permissions = this->Makefile->GetDefinition( + cmProp default_dir_install_permissions = this->Makefile->GetDefinition( "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); - if (default_dir_install_permissions && *default_dir_install_permissions) { + if (cmNonempty(default_dir_install_permissions)) { std::vector<std::string> items = - cmExpandedList(default_dir_install_permissions); + cmExpandedList(*default_dir_install_permissions); for (const auto& arg : items) { if (!this->CheckPermissions(arg, **mode)) { this->Status.SetError( diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h index 612a57f..217d58d 100644 --- a/Source/cmFileCopier.h +++ b/Source/cmFileCopier.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileCopier_h -#define cmFileCopier_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -120,5 +119,3 @@ protected: bool GetDefaultDirectoryPermissions(mode_t** mode); }; - -#endif diff --git a/Source/cmFileInstaller.h b/Source/cmFileInstaller.h index 537cd53..3a905d3 100644 --- a/Source/cmFileInstaller.h +++ b/Source/cmFileInstaller.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileInstaller_h -#define cmFileInstaller_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -50,5 +49,3 @@ protected: bool GetTargetTypeFromString(const std::string& stype); bool HandleInstallDestination(); }; - -#endif diff --git a/Source/cmFileLock.h b/Source/cmFileLock.h index 5fe068e..2b125af 100644 --- a/Source/cmFileLock.h +++ b/Source/cmFileLock.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileLock_h -#define cmFileLock_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -63,5 +62,3 @@ private: std::string Filename; }; - -#endif // cmFileLock_h diff --git a/Source/cmFileLockPool.h b/Source/cmFileLockPool.h index d45c82c..f2f9f23 100644 --- a/Source/cmFileLockPool.h +++ b/Source/cmFileLockPool.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileLockPool_h -#define cmFileLockPool_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -86,5 +85,3 @@ private: List FileScopes; ScopePool ProcessScope; }; - -#endif // cmFileLockPool_h diff --git a/Source/cmFileLockResult.h b/Source/cmFileLockResult.h index 81c1906..8a58d1f 100644 --- a/Source/cmFileLockResult.h +++ b/Source/cmFileLockResult.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileLockResult_h -#define cmFileLockResult_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -73,5 +72,3 @@ private: ErrorType Type; Error ErrorValue; }; - -#endif // cmFileLockResult_h diff --git a/Source/cmFilePathChecksum.h b/Source/cmFilePathChecksum.h index b7d5cd2..a6f7bd3 100644 --- a/Source/cmFilePathChecksum.h +++ b/Source/cmFilePathChecksum.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFilePathChecksum_h -#define cmFilePathChecksum_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -60,5 +59,3 @@ private: /// List of (directory name, seed name) pairs std::array<std::pair<std::string, std::string>, 4> parentDirs; }; - -#endif diff --git a/Source/cmFileTime.h b/Source/cmFileTime.h index e9a8559..f496cdc 100644 --- a/Source/cmFileTime.h +++ b/Source/cmFileTime.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileTime_h -#define cmFileTime_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -126,5 +125,3 @@ public: private: NSC NS = 0; }; - -#endif diff --git a/Source/cmFileTimeCache.h b/Source/cmFileTimeCache.h index 83b77b6..336136e 100644 --- a/Source/cmFileTimeCache.h +++ b/Source/cmFileTimeCache.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileTimeCache_h -#define cmFileTimeCache_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -53,5 +52,3 @@ public: private: std::unordered_map<std::string, cmFileTime> Cache; }; - -#endif diff --git a/Source/cmFileTimes.h b/Source/cmFileTimes.h index 191d89e..f1916f7 100644 --- a/Source/cmFileTimes.h +++ b/Source/cmFileTimes.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileTimes_h -#define cmFileTimes_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -36,5 +35,3 @@ private: class Times; std::unique_ptr<Times> times; }; - -#endif diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 743ac75..bf52d75 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -294,11 +294,10 @@ void cmFindBase::FillUserGuessPath() bool cmFindBase::CheckForVariableInCache() { - if (const char* cacheValue = - this->Makefile->GetDefinition(this->VariableName)) { + if (cmProp cacheValue = this->Makefile->GetDefinition(this->VariableName)) { cmState* state = this->Makefile->GetState(); cmProp cacheEntry = state->GetCacheEntryValue(this->VariableName); - bool found = !cmIsNOTFOUND(cacheValue); + bool found = !cmIsNOTFOUND(*cacheValue); bool cached = cacheEntry != nullptr; if (found) { // If the user specifies the entry on the command line without a diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h index 4cbf09e..57a40be 100644 --- a/Source/cmFindBase.h +++ b/Source/cmFindBase.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFindBase_h -#define cmFindBase_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -94,5 +93,3 @@ private: std::vector<DebugLibState> FailedSearchLocations; DebugLibState FoundSearchLocation; }; - -#endif diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 3e97150..dee91d7 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -11,6 +11,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -182,9 +183,9 @@ void cmFindCommon::SelectDefaultSearchModes() }; for (auto& path : search_paths) { - const char* def = this->Makefile->GetDefinition(path.second); + cmProp def = this->Makefile->GetDefinition(path.second); if (def) { - path.first = !cmIsOn(def); + path.first = !cmIsOn(*def); } } } @@ -202,16 +203,15 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) return; } - const char* sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT"); - const char* sysrootCompile = + cmProp sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT"); + cmProp sysrootCompile = this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE"); - const char* sysrootLink = - this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK"); - const char* rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH"); - const bool noSysroot = !sysroot || !*sysroot; - const bool noCompileSysroot = !sysrootCompile || !*sysrootCompile; - const bool noLinkSysroot = !sysrootLink || !*sysrootLink; - const bool noRootPath = !rootPath || !*rootPath; + cmProp sysrootLink = this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK"); + cmProp rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH"); + const bool noSysroot = !cmNonempty(sysroot); + const bool noCompileSysroot = !cmNonempty(sysrootCompile); + const bool noLinkSysroot = !cmNonempty(sysrootLink); + const bool noRootPath = !cmNonempty(rootPath); if (noSysroot && noCompileSysroot && noLinkSysroot && noRootPath) { return; } @@ -219,23 +219,22 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) // Construct the list of path roots with no trailing slashes. std::vector<std::string> roots; if (rootPath) { - cmExpandList(rootPath, roots); + cmExpandList(*rootPath, roots); } if (sysrootCompile) { - roots.emplace_back(sysrootCompile); + roots.emplace_back(*sysrootCompile); } if (sysrootLink) { - roots.emplace_back(sysrootLink); + roots.emplace_back(*sysrootLink); } if (sysroot) { - roots.emplace_back(sysroot); + roots.emplace_back(*sysroot); } for (std::string& r : roots) { cmSystemTools::ConvertToUnixSlashes(r); } - const char* stagePrefix = - this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); + cmProp stagePrefix = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); // Copy the original set of unrooted paths. std::vector<std::string> unrootedPaths = paths; @@ -248,7 +247,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) // a user home directory or is empty. std::string rootedDir; if (cmSystemTools::IsSubDirectory(up, r) || - (stagePrefix && cmSystemTools::IsSubDirectory(up, stagePrefix))) { + (stagePrefix && cmSystemTools::IsSubDirectory(up, *stagePrefix))) { rootedDir = up; } else if (!up.empty() && up[0] != '~') { // Start with the new root. diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h index 916f3bc..f84242e 100644 --- a/Source/cmFindCommon.h +++ b/Source/cmFindCommon.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFindCommon_h -#define cmFindCommon_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -143,5 +142,3 @@ protected: cmMakefile* Makefile; cmExecutionStatus& Status; }; - -#endif diff --git a/Source/cmFindFileCommand.h b/Source/cmFindFileCommand.h index 7dc6e55..368a7c9 100644 --- a/Source/cmFindFileCommand.h +++ b/Source/cmFindFileCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFindFileCommand_h -#define cmFindFileCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -28,5 +27,3 @@ public: bool cmFindFile(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 3242b6d..b87dfe3 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -13,6 +13,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -50,9 +51,9 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn) // add custom lib<qual> paths instead of using fixed lib32, lib64 or // libx32 - if (const char* customLib = this->Makefile->GetDefinition( + if (cmProp customLib = this->Makefile->GetDefinition( "CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX")) { - this->AddArchitecturePaths(customLib); + this->AddArchitecturePaths(customLib->c_str()); } // add special 32 bit paths if this is a 32 bit compile. else if (this->Makefile->PlatformIs32Bit() && diff --git a/Source/cmFindLibraryCommand.h b/Source/cmFindLibraryCommand.h index b2f71b3..f3874ff 100644 --- a/Source/cmFindLibraryCommand.h +++ b/Source/cmFindLibraryCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFindLibraryCommand_h -#define cmFindLibraryCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -44,5 +43,3 @@ private: bool cmFindLibrary(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 8d5b177..c462651 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -154,10 +154,10 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } // Lookup required version of CMake. - if (const char* rv = + if (cmProp rv = this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { unsigned int v[3] = { 0, 0, 0 }; - sscanf(rv, "%u.%u.%u", &v[0], &v[1], &v[2]); + sscanf(rv->c_str(), "%u.%u.%u", &v[0], &v[1], &v[2]); this->RequiredCMakeVersion = CMake_VERSION_ENCODE(v[0], v[1], v[2]); } @@ -165,9 +165,9 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->DebugBuffer.clear(); // Lookup target architecture, if any. - if (const char* arch = + if (cmProp arch = this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) { - this->LibraryArchitecture = arch; + this->LibraryArchitecture = *arch; } // Lookup whether lib32 paths should be used. @@ -194,9 +194,9 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) // Check if User Package Registry should be disabled // The `CMAKE_FIND_USE_PACKAGE_REGISTRY` has // priority over the deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY - if (const char* def = + if (cmProp def = this->Makefile->GetDefinition("CMAKE_FIND_USE_PACKAGE_REGISTRY")) { - this->NoUserRegistry = !cmIsOn(def); + this->NoUserRegistry = !cmIsOn(*def); } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) { this->NoUserRegistry = true; } @@ -204,9 +204,9 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) // Check if System Package Registry should be disabled // The `CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY` has // priority over the deprecated CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY - if (const char* def = this->Makefile->GetDefinition( + if (cmProp def = this->Makefile->GetDefinition( "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY")) { - this->NoSystemRegistry = !cmIsOn(def); + this->NoSystemRegistry = !cmIsOn(*def); } else if (this->Makefile->IsOn( "CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY")) { this->NoSystemRegistry = true; @@ -218,20 +218,20 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } // Check if Sorting should be enabled - if (const char* so = + if (cmProp so = this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) { - if (strcmp(so, "NAME") == 0) { + if (*so == "NAME") { this->SortOrder = Name_order; - } else if (strcmp(so, "NATURAL") == 0) { + } else if (*so == "NATURAL") { this->SortOrder = Natural; } else { this->SortOrder = None; } } - if (const char* sd = + if (cmProp sd = this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_DIRECTION")) { - this->SortDirection = strcmp(sd, "ASC") == 0 ? Asc : Dec; + this->SortDirection = (*sd == "ASC") ? Asc : Dec; } // Find what search path locations have been enabled/disable @@ -675,9 +675,9 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components) void cmFindPackageCommand::AddFindDefinition(const std::string& var, const char* val) { - if (const char* old = this->Makefile->GetDefinition(var)) { + if (cmProp old = this->Makefile->GetDefinition(var)) { this->OriginalDefs[var].exists = true; - this->OriginalDefs[var].value = old; + this->OriginalDefs[var].value = *old; } else { this->OriginalDefs[var].exists = false; } @@ -759,14 +759,14 @@ bool cmFindPackageCommand::HandlePackageMode( this->ConsideredConfigs.clear(); // Try to find the config file. - const char* def = this->Makefile->GetDefinition(this->Variable); + cmProp def = this->Makefile->GetDefinition(this->Variable); // Try to load the config file if the directory is known bool fileFound = false; if (this->UseConfigFiles) { if (!cmIsOff(def)) { // Get the directory from the variable value. - std::string dir = def; + std::string dir = *def; cmSystemTools::ConvertToUnixSlashes(dir); // Treat relative paths with respect to the current source dir. @@ -1121,7 +1121,7 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found) std::vector<std::string> foundContents; cmProp foundProp = this->Makefile->GetState()->GetGlobalProperty("PACKAGES_FOUND"); - if (foundProp && !foundProp->empty()) { + if (cmNonempty(foundProp)) { cmExpandList(*foundProp, foundContents, false); auto nameIt = std::find(foundContents.begin(), foundContents.end(), this->Name); @@ -1133,7 +1133,7 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found) std::vector<std::string> notFoundContents; cmProp notFoundProp = this->Makefile->GetState()->GetGlobalProperty("PACKAGES_NOT_FOUND"); - if (notFoundProp && !notFoundProp->empty()) { + if (cmNonempty(notFoundProp)) { cmExpandList(*notFoundProp, notFoundContents, false); auto nameIt = std::find(notFoundContents.begin(), notFoundContents.end(), this->Name); @@ -1166,9 +1166,9 @@ void cmFindPackageCommand::AppendSuccessInformation() std::string found = cmStrCat(this->Name, "_FOUND"); std::string upperFound = cmSystemTools::UpperCase(found); - const char* upperResult = this->Makefile->GetDefinition(upperFound); - const char* result = this->Makefile->GetDefinition(found); - bool packageFound = ((cmIsOn(result)) || (cmIsOn(upperResult))); + bool upperResult = this->Makefile->IsOn(upperFound); + bool result = this->Makefile->IsOn(found); + bool packageFound = (result || upperResult); this->AppendToFoundProperty(packageFound); diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 7058a54..eacd1ce 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFindPackageCommand_h -#define cmFindPackageCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -233,5 +232,3 @@ struct hash<cmFindPackageCommand::ConfigFileInfo> bool cmFindPackage(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h index 18bfb7d..b9fe673 100644 --- a/Source/cmFindPathCommand.h +++ b/Source/cmFindPathCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFindPathCommand_h -#define cmFindPathCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -38,5 +37,3 @@ private: bool cmFindPath(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 4b88bea..77728ec 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -4,6 +4,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -19,6 +20,7 @@ struct cmFindProgramHelper cmFindProgramHelper(cmMakefile* makefile, cmFindBase const* base) : DebugSearches("find_program", base) , Makefile(makefile) + , PolicyCMP0109(makefile->GetPolicyStatus(cmPolicies::CMP0109)) { #if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) // Consider platform-specific extensions. @@ -48,6 +50,8 @@ struct cmFindProgramHelper cmFindBaseDebugState DebugSearches; cmMakefile* Makefile; + cmPolicies::PolicyStatus PolicyCMP0109; + void AddName(std::string const& name) { this->Names.push_back(name); } void SetName(std::string const& name) { @@ -85,7 +89,7 @@ struct cmFindProgramHelper this->TestNameExt = cmStrCat(name, ext); this->TestPath = cmSystemTools::CollapseFullPath(this->TestNameExt, path); - bool exists = cmSystemTools::FileExists(this->TestPath, true); + bool exists = this->FileIsExecutable(this->TestPath); exists ? this->DebugSearches.FoundAt(this->TestPath) : this->DebugSearches.FailedAt(this->TestPath); if (exists) { @@ -95,6 +99,48 @@ struct cmFindProgramHelper } return false; } + bool FileIsExecutable(std::string const& file) const + { + switch (this->PolicyCMP0109) { + case cmPolicies::OLD: + return cmSystemTools::FileExists(file, true); + case cmPolicies::NEW: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + return cmSystemTools::FileIsExecutable(file); + default: + break; + } + bool const isExeOld = cmSystemTools::FileExists(file, true); + bool const isExeNew = cmSystemTools::FileIsExecutable(file); + if (isExeNew == isExeOld) { + return isExeNew; + } + if (isExeNew) { + this->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0109), + "\n" + "The file\n" + " ", + file, + "\n" + "is executable but not readable. " + "CMake is ignoring it for compatibility.")); + } else { + this->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0109), + "\n" + "The file\n" + " ", + file, + "\n" + "is readable but not executable. " + "CMake is using it for compatibility.")); + } + return isExeOld; + } }; cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status) @@ -266,14 +312,13 @@ std::string cmFindProgramCommand::GetBundleExecutable( if (executableURL != nullptr) { const int MAX_OSX_PATH_SIZE = 1024; - char buffer[MAX_OSX_PATH_SIZE]; + UInt8 buffer[MAX_OSX_PATH_SIZE]; - // Convert the CFString to a C string - CFStringGetCString(CFURLGetString(executableURL), buffer, - MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8); - - // And finally to a c++ string - executable = bundlePath + "/Contents/MacOS/" + std::string(buffer); + if (CFURLGetFileSystemRepresentation(executableURL, false, buffer, + MAX_OSX_PATH_SIZE)) { + executable = bundlePath + "/Contents/MacOS/" + + std::string(reinterpret_cast<char*>(buffer)); + } // Only release CFURLRef if it's not null CFRelease(executableURL); } diff --git a/Source/cmFindProgramCommand.h b/Source/cmFindProgramCommand.h index 043b43c..161a680 100644 --- a/Source/cmFindProgramCommand.h +++ b/Source/cmFindProgramCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFindProgramCommand_h -#define cmFindProgramCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -38,5 +37,3 @@ private: bool cmFindProgram(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 3b82e0a..12fb55a 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -25,6 +25,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -113,8 +114,8 @@ bool cmForEachFunctionBlocker::ReplayItems( // At end of for each execute recorded commands // store the old value std::string oldDef; - if (auto d = mf.GetDefinition(this->Args.front())) { - oldDef = d; + if (cmProp d = mf.GetDefinition(this->Args.front())) { + oldDef = *d; } auto restore = false; @@ -186,8 +187,8 @@ bool cmForEachFunctionBlocker::ReplayZipLists( // Store old values for iteration variables std::map<std::string, std::string> oldDefs; for (auto i = 0u; i < values.size(); ++i) { - if (auto d = mf.GetDefinition(iterationVars[i])) { - oldDefs.emplace(iterationVars[i], d); + if (cmProp d = mf.GetDefinition(iterationVars[i])) { + oldDefs.emplace(iterationVars[i], *d); } } diff --git a/Source/cmForEachCommand.h b/Source/cmForEachCommand.h index 1feb965..6476fea 100644 --- a/Source/cmForEachCommand.h +++ b/Source/cmForEachCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmForEachCommand_h -#define cmForEachCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -13,4 +12,3 @@ class cmExecutionStatus; /// Starts foreach() ... endforeach() block bool cmForEachCommand(std::vector<std::string> const& args, cmExecutionStatus& status); -#endif diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h index 6f97b42..1b14d17 100644 --- a/Source/cmFortranParser.h +++ b/Source/cmFortranParser.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFortranParser_h -#define cmFortranParser_h +#pragma once #if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx) # include "cmConfigure.h" // IWYU pragma: keep @@ -181,5 +180,3 @@ struct cmFortranParser_s cmFortranSourceInfo& Info; }; #endif - -#endif diff --git a/Source/cmFunctionBlocker.h b/Source/cmFunctionBlocker.h index 59bb892..b4b493b 100644 --- a/Source/cmFunctionBlocker.h +++ b/Source/cmFunctionBlocker.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFunctionBlocker_h -#define cmFunctionBlocker_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -50,5 +49,3 @@ private: std::vector<cmListFileFunction> Functions; unsigned int ScopeDepth = 1; }; - -#endif diff --git a/Source/cmFunctionCommand.h b/Source/cmFunctionCommand.h index d6b549c..07ff4f7 100644 --- a/Source/cmFunctionCommand.h +++ b/Source/cmFunctionCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFunctionCommand_h -#define cmFunctionCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -13,5 +12,3 @@ class cmExecutionStatus; /// Starts function() ... endfunction() block bool cmFunctionCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmGccDepfileLexerHelper.h b/Source/cmGccDepfileLexerHelper.h index e6b2fcf..07ca61d 100644 --- a/Source/cmGccDepfileLexerHelper.h +++ b/Source/cmGccDepfileLexerHelper.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGccDepfileLexerHelper_h -#define cmGccDepfileLexerHelper_h +#pragma once #include <utility> @@ -36,5 +35,3 @@ private: }; #define YY_EXTRA_TYPE cmGccDepfileLexerHelper* - -#endif diff --git a/Source/cmGccDepfileReader.h b/Source/cmGccDepfileReader.h index 9313010..395dd77 100644 --- a/Source/cmGccDepfileReader.h +++ b/Source/cmGccDepfileReader.h @@ -1,10 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGccDepfileReader_h -#define cmGccDepfileReader_h +#pragma once #include "cmGccDepfileReaderTypes.h" cmGccDepfileContent cmReadGccDepfile(const char* filePath); - -#endif diff --git a/Source/cmGccDepfileReaderTypes.h b/Source/cmGccDepfileReaderTypes.h index 8b15c73..246e355 100644 --- a/Source/cmGccDepfileReaderTypes.h +++ b/Source/cmGccDepfileReaderTypes.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGccDepfileReaderTypes_h -#define cmGccDepfileReaderTypes_h +#pragma once #include <string> #include <vector> @@ -13,5 +12,3 @@ struct cmGccStyleDependency }; using cmGccDepfileContent = std::vector<cmGccStyleDependency>; - -#endif diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 9cee0e6..2768547 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -14,10 +14,11 @@ #endif cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding) + : OriginalLocale(getloc()) { #ifndef CMAKE_BOOTSTRAP if (encoding != codecvt::None) { - imbue(std::locale(getloc(), new codecvt(encoding))); + imbue(std::locale(OriginalLocale, new codecvt(encoding))); } #else static_cast<void>(encoding); @@ -122,10 +123,17 @@ void cmGeneratedFileStreamBase::Open(std::string const& name) // Create the name of the temporary file. this->TempName = name; #if defined(__VMS) - this->TempName += "_tmp"; + this->TempName += "_"; #else - this->TempName += ".tmp"; + this->TempName += "."; #endif + if (!this->TempExt.empty()) { + this->TempName += this->TempExt; + } else { + char buf[64]; + sprintf(buf, "tmp%05x", cmSystemTools::RandomSeed() & 0xFFFFF); + this->TempName += buf; + } // Make sure the temporary file that will be used is not present. cmSystemTools::RemoveFile(this->TempName); @@ -216,3 +224,19 @@ void cmGeneratedFileStream::SetName(const std::string& fname) { this->Name = fname; } + +void cmGeneratedFileStream::SetTempExt(std::string const& ext) +{ + this->TempExt = ext; +} + +void cmGeneratedFileStream::WriteRaw(std::string const& data) +{ +#ifndef CMAKE_BOOTSTRAP + std::locale activeLocale = this->imbue(this->OriginalLocale); + this->write(data.data(), data.size()); + this->imbue(activeLocale); +#else + this->write(data.data(), data.size()); +#endif +} diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h index a9088ac..bb7e3bf 100644 --- a/Source/cmGeneratedFileStream.h +++ b/Source/cmGeneratedFileStream.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGeneratedFileStream_h -#define cmGeneratedFileStream_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -43,6 +42,9 @@ protected: // The name of the final destination file for the output. std::string Name; + // The extension of the temporary file. + std::string TempExt; + // The name of the temporary file. std::string TempName; @@ -138,6 +140,20 @@ public: * the output file to be changed during the use of cmGeneratedFileStream. */ void SetName(const std::string& fname); -}; -#endif + /** + * Set set a custom temporary file extension used with 'Open'. + * This does not work if the file was opened by the constructor. + */ + void SetTempExt(std::string const& ext); + + /** + * Writes the given string directly to the file without changing the + * encoding. + */ + void WriteRaw(std::string const& data); + +private: + // The original locale of the stream (performs no encoding conversion). + std::locale OriginalLocale; +}; diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 6e293d5..840f511 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -406,9 +406,3 @@ const std::string& cmGeneratorExpressionInterpreter::Evaluate( this->LocalGenerator, this->Config, this->HeadTarget, &dagChecker, nullptr, this->Language); } - -const std::string& cmGeneratorExpressionInterpreter::Evaluate( - const char* expression, const std::string& property) -{ - return this->Evaluate(std::string(expression ? expression : ""), property); -} diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 75bba02..03be782 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGeneratorExpression_h -#define cmGeneratorExpression_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -199,8 +198,6 @@ public: const std::string& Evaluate(std::string expression, const std::string& property); - const std::string& Evaluate(const char* expression, - const std::string& property); protected: cmGeneratorExpression GeneratorExpression; @@ -210,5 +207,3 @@ protected: cmGeneratorTarget const* HeadTarget = nullptr; std::string Language; }; - -#endif diff --git a/Source/cmGeneratorExpressionContext.h b/Source/cmGeneratorExpressionContext.h index bceff12..22e7463 100644 --- a/Source/cmGeneratorExpressionContext.h +++ b/Source/cmGeneratorExpressionContext.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGeneratorExpressionContext_h -#define cmGeneratorExpressionContext_h +#pragma once #include <map> #include <set> @@ -43,5 +42,3 @@ struct cmGeneratorExpressionContext bool HadLinkLanguageSensitiveCondition; bool EvaluateForBuildsystem; }; - -#endif diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 4f379cd..e223f15 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -154,6 +154,14 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression() const return this->Top()->Property == "INTERFACE_POSITION_INDEPENDENT_CODE"; } +bool cmGeneratorExpressionDAGChecker::EvaluatingCompileExpression() const +{ + cm::string_view property(this->Top()->Property); + + return property == "INCLUDE_DIRECTORIES"_s || + property == "COMPILE_DEFINITIONS"_s || property == "COMPILE_OPTIONS"_s; +} + bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression() const { cm::string_view property(this->Top()->Property); diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index c2c5b6b..53225cd 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGeneratorExpressionDAGChecker_h -#define cmGeneratorExpressionDAGChecker_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -68,6 +67,7 @@ struct cmGeneratorExpressionDAGChecker bool EvaluatingGenexExpression() const; bool EvaluatingPICExpression() const; + bool EvaluatingCompileExpression() const; bool EvaluatingLinkExpression() const; bool EvaluatingLinkOptionsExpression() const; @@ -99,5 +99,3 @@ private: Result CheckResult; bool TransitivePropertiesOnly; }; - -#endif diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index 9e8707d..9e5023d 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -19,11 +19,12 @@ #include "cmSystemTools.h" cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile( - std::string input, + std::string input, std::string target, std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070) : Input(std::move(input)) + , Target(std::move(target)) , OutputFileExpr(std::move(outputFileExpr)) , Condition(std::move(condition)) , InputIsContent(inputIsContent) @@ -37,9 +38,10 @@ void cmGeneratorExpressionEvaluationFile::Generate( std::map<std::string, std::string>& outputFiles, mode_t perm) { std::string rawCondition = this->Condition->GetInput(); + cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(Target); if (!rawCondition.empty()) { std::string condResult = - this->Condition->Evaluate(lg, config, nullptr, nullptr, nullptr, lang); + this->Condition->Evaluate(lg, config, target, nullptr, nullptr, lang); if (condResult == "0") { return; } @@ -54,16 +56,10 @@ void cmGeneratorExpressionEvaluationFile::Generate( } } - std::string outputFileName = this->OutputFileExpr->Evaluate( - lg, config, nullptr, nullptr, nullptr, lang); + const std::string outputFileName = + this->GetOutputFileName(lg, target, config, lang); const std::string& outputContent = - inputExpression->Evaluate(lg, config, nullptr, nullptr, nullptr, lang); - - if (cmSystemTools::FileIsFullPath(outputFileName)) { - outputFileName = cmSystemTools::CollapseFullPath(outputFileName); - } else { - outputFileName = this->FixRelativePath(outputFileName, PathForOutput, lg); - } + inputExpression->Evaluate(lg, config, target, nullptr, nullptr, lang); auto it = outputFiles.find(outputFileName); @@ -98,11 +94,11 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile( { std::vector<std::string> enabledLanguages; cmGlobalGenerator* gg = lg->GetGlobalGenerator(); + cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(Target); gg->GetEnabledLanguages(enabledLanguages); for (std::string const& le : enabledLanguages) { - std::string name = this->OutputFileExpr->Evaluate(lg, config, nullptr, - nullptr, nullptr, le); + std::string const name = this->GetOutputFileName(lg, target, config, le); cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource( name, false, cmSourceFileLocationKind::Known); // Tell TraceDependencies that the file is not expected to exist @@ -125,12 +121,7 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg) if (this->InputIsContent) { inputContent = this->Input; } else { - std::string inputFileName = this->Input; - if (cmSystemTools::FileIsFullPath(inputFileName)) { - inputFileName = cmSystemTools::CollapseFullPath(inputFileName); - } else { - inputFileName = this->FixRelativePath(inputFileName, PathForInput, lg); - } + const std::string inputFileName = this->GetInputFileName(lg); lg->GetMakefile()->AddCMakeDependFile(inputFileName); cmSystemTools::GetPermissions(inputFileName.c_str(), perm); cmsys::ifstream fin(inputFileName.c_str()); @@ -157,12 +148,8 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg) std::map<std::string, std::string> outputFiles; - std::vector<std::string> allConfigs; - lg->GetMakefile()->GetConfigurations(allConfigs); - - if (allConfigs.empty()) { - allConfigs.emplace_back(); - } + std::vector<std::string> allConfigs = + lg->GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); std::vector<std::string> enabledLanguages; cmGlobalGenerator* gg = lg->GetGlobalGenerator(); @@ -178,6 +165,36 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg) } } +std::string cmGeneratorExpressionEvaluationFile::GetInputFileName( + cmLocalGenerator* lg) +{ + std::string inputFileName = this->Input; + + if (cmSystemTools::FileIsFullPath(inputFileName)) { + inputFileName = cmSystemTools::CollapseFullPath(inputFileName); + } else { + inputFileName = this->FixRelativePath(inputFileName, PathForInput, lg); + } + + return inputFileName; +} + +std::string cmGeneratorExpressionEvaluationFile::GetOutputFileName( + cmLocalGenerator* lg, cmGeneratorTarget* target, const std::string& config, + const std::string& lang) +{ + std::string outputFileName = + this->OutputFileExpr->Evaluate(lg, config, target, nullptr, nullptr, lang); + + if (cmSystemTools::FileIsFullPath(outputFileName)) { + outputFileName = cmSystemTools::CollapseFullPath(outputFileName); + } else { + outputFileName = this->FixRelativePath(outputFileName, PathForOutput, lg); + } + + return outputFileName; +} + std::string cmGeneratorExpressionEvaluationFile::FixRelativePath( std::string const& relativePath, PathRole role, cmLocalGenerator* lg) { diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h index c3bc4c8..2cd35ae 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.h +++ b/Source/cmGeneratorExpressionEvaluationFile.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGeneratorExpressionEvaluationFile_h -#define cmGeneratorExpressionEvaluationFile_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -15,13 +14,14 @@ #include "cmGeneratorExpression.h" #include "cmPolicies.h" +class cmGeneratorTarget; class cmLocalGenerator; class cmGeneratorExpressionEvaluationFile { public: cmGeneratorExpressionEvaluationFile( - std::string input, + std::string input, std::string target, std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070); @@ -38,6 +38,11 @@ private: cmCompiledGeneratorExpression* inputExpression, std::map<std::string, std::string>& outputFiles, mode_t perm); + std::string GetInputFileName(cmLocalGenerator* lg); + std::string GetOutputFileName(cmLocalGenerator* lg, + cmGeneratorTarget* target, + const std::string& config, + const std::string& lang); enum PathRole { PathForInput, @@ -48,11 +53,10 @@ private: private: const std::string Input; + const std::string Target; const std::unique_ptr<cmCompiledGeneratorExpression> OutputFileExpr; const std::unique_ptr<cmCompiledGeneratorExpression> Condition; std::vector<std::string> Files; const bool InputIsContent; cmPolicies::PolicyStatus PolicyStatusCMP0070; }; - -#endif diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index 10496fd..3e7737e 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGeneratorExpressionEvaluator_h -#define cmGeneratorExpressionEvaluator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -115,5 +114,3 @@ private: const char* StartContent; size_t ContentLength; }; - -#endif diff --git a/Source/cmGeneratorExpressionLexer.h b/Source/cmGeneratorExpressionLexer.h index 9e01948..a4321d1 100644 --- a/Source/cmGeneratorExpressionLexer.h +++ b/Source/cmGeneratorExpressionLexer.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGeneratorExpressionLexer_h -#define cmGeneratorExpressionLexer_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -49,5 +48,3 @@ private: bool SawBeginExpression = false; bool SawGeneratorExpression = false; }; - -#endif diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index e4fb67e..d3308e2 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -37,6 +37,7 @@ #include "cmPolicies.h" #include "cmProperty.h" #include "cmRange.h" +#include "cmStandardLevelResolver.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" @@ -714,7 +715,8 @@ struct CompilerIdNode : public cmGeneratorExpressionNode static const CompilerIdNode cCompilerIdNode("C"), cxxCompilerIdNode("CXX"), cudaCompilerIdNode("CUDA"), objcCompilerIdNode("OBJC"), - objcxxCompilerIdNode("OBJCXX"), fortranCompilerIdNode("Fortran"); + objcxxCompilerIdNode("OBJCXX"), fortranCompilerIdNode("Fortran"), + ispcCompilerIdNode("ISPC"); struct CompilerVersionNode : public cmGeneratorExpressionNode { @@ -779,7 +781,7 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode static const CompilerVersionNode cCompilerVersionNode("C"), cxxCompilerVersionNode("CXX"), cudaCompilerVersionNode("CUDA"), objcCompilerVersionNode("OBJC"), objcxxCompilerVersionNode("OBJCXX"), - fortranCompilerVersionNode("Fortran"); + fortranCompilerVersionNode("Fortran"), ispcCompilerVersionNode("ISPC"); struct PlatformIdNode : public cmGeneratorExpressionNode { @@ -881,7 +883,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode { ConfigurationTestNode() {} // NOLINT(modernize-use-equals-default) - int NumExpectedParameters() const override { return OneOrZeroParameters; } + int NumExpectedParameters() const override { return ZeroOrMoreParameters; } std::string Evaluate( const std::vector<std::string>& parameters, @@ -899,13 +901,15 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode return std::string(); } context->HadContextSensitiveCondition = true; - if (context->Config.empty()) { - return parameters.front().empty() ? "1" : "0"; - } - - if (cmsysString_strcasecmp(parameters.front().c_str(), - context->Config.c_str()) == 0) { - return "1"; + for (auto& param : parameters) { + if (context->Config.empty()) { + if (param.empty()) { + return "1"; + } + } else if (cmsysString_strcasecmp(param.c_str(), + context->Config.c_str()) == 0) { + return "1"; + } } if (context->CurrentTarget && context->CurrentTarget->IsImported()) { @@ -922,10 +926,12 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode "MAP_IMPORTED_CONFIG_", cmSystemTools::UpperCase(context->Config)); if (cmProp mapValue = context->CurrentTarget->GetProperty(mapProp)) { cmExpandList(cmSystemTools::UpperCase(*mapValue), mappedConfigs); - return cm::contains(mappedConfigs, - cmSystemTools::UpperCase(parameters.front())) - ? "1" - : "0"; + + for (auto& param : parameters) { + if (cm::contains(mappedConfigs, cmSystemTools::UpperCase(param))) { + return "1"; + } + } } } } @@ -962,9 +968,10 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode const std::vector<std::string>& parameters, cmGeneratorExpressionContext* context, const GeneratorExpressionContent* content, - cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override + cmGeneratorExpressionDAGChecker* dagChecker) const override { - if (context->Language.empty()) { + if (context->Language.empty() && + (!dagChecker || !dagChecker->EvaluatingCompileExpression())) { reportError( context, content->GetOriginalExpression(), "$<COMPILE_LANGUAGE:...> may only be used to specify include " @@ -1009,7 +1016,9 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* dagChecker) const override { - if (!context->HeadTarget || context->Language.empty()) { + if (!context->HeadTarget || + (context->Language.empty() && + (!dagChecker || !dagChecker->EvaluatingCompileExpression()))) { // reportError(context, content->GetOriginalExpression(), ""); reportError( context, content->GetOriginalExpression(), @@ -1468,8 +1477,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } if (isInterfaceProperty) { - return target->EvaluateInterfaceProperty(propertyName, context, - dagCheckerParent); + return cmGeneratorExpression::StripEmptyListElements( + target->EvaluateInterfaceProperty(propertyName, context, + dagCheckerParent)); } cmGeneratorExpressionDAGChecker dagChecker( @@ -1555,8 +1565,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } if (!interfacePropertyName.empty()) { - result = this->EvaluateDependentExpression(result, context->LG, context, - target, &dagChecker, target); + result = cmGeneratorExpression::StripEmptyListElements( + this->EvaluateDependentExpression(result, context->LG, context, target, + &dagChecker, target)); std::string linkedTargetsContent = getLinkedTargetsContent( target, interfacePropertyName, context, &dagChecker); if (!linkedTargetsContent.empty()) { @@ -1703,12 +1714,12 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode static LangMap availableFeatures; LangMap testedFeatures; - + cmStandardLevelResolver standardResolver(context->LG->GetMakefile()); for (std::string const& p : parameters) { std::string error; std::string lang; - if (!context->LG->GetMakefile()->CompileFeatureKnown( - context->HeadTarget->Target, p, lang, &error)) { + if (!standardResolver.CompileFeatureKnown( + context->HeadTarget->Target->GetName(), p, lang, &error)) { reportError(context, content->GetOriginalExpression(), error); return std::string(); } @@ -1716,7 +1727,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode if (availableFeatures.find(lang) == availableFeatures.end()) { const char* featuresKnown = - context->LG->GetMakefile()->CompileFeaturesAvailable(lang, &error); + standardResolver.CompileFeaturesAvailable(lang, &error); if (!featuresKnown) { reportError(context, content->GetOriginalExpression(), error); return std::string(); @@ -1730,7 +1741,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode for (auto const& lit : testedFeatures) { std::vector<std::string> const& langAvailable = availableFeatures[lit.first]; - cmProp standardDefault = context->LG->GetMakefile()->GetDef( + cmProp standardDefault = context->LG->GetMakefile()->GetDefinition( "CMAKE_" + lit.first + "_STANDARD_DEFAULT"); for (std::string const& it : lit.second) { if (!cm::contains(langAvailable, it)) { @@ -1741,10 +1752,10 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode // All features known for the language are always available. continue; } - if (!context->LG->GetMakefile()->HaveStandardAvailable( - target->Target, lit.first, it)) { + if (!standardResolver.HaveStandardAvailable(target, lit.first, + context->Config, it)) { if (evalLL) { - cmProp l = target->GetProperty(lit.first + "_STANDARD"); + cmProp l = target->GetLanguageStandard(lit.first, context->Config); if (!l) { l = standardDefault; } @@ -1891,6 +1902,70 @@ class ArtifactSonameTag; class ArtifactBundleDirTag; class ArtifactBundleContentDirTag; +template <typename ArtifactT, typename ComponentT> +struct TargetFilesystemArtifactDependency +{ + static void AddDependency(cmGeneratorTarget* target, + cmGeneratorExpressionContext* context) + { + context->DependTargets.insert(target); + context->AllTargets.insert(target); + } +}; + +struct TargetFilesystemArtifactDependencyCMP0112 +{ + static void AddDependency(cmGeneratorTarget* target, + cmGeneratorExpressionContext* context) + { + context->AllTargets.insert(target); + cmLocalGenerator* lg = context->LG; + switch (target->GetPolicyStatusCMP0112()) { + case cmPolicies::WARN: + if (lg->GetMakefile()->PolicyOptionalWarningEnabled( + "CMAKE_POLICY_WARNING_CMP0112")) { + std::string err = + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0112), + "\nDependency being added to target:\n \"", + target->GetName(), "\"\n"); + lg->GetCMakeInstance()->IssueMessage(MessageType ::AUTHOR_WARNING, + err, context->Backtrace); + } + CM_FALLTHROUGH; + case cmPolicies::OLD: + context->DependTargets.insert(target); + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + break; + } + } +}; + +template <typename ArtifactT> +struct TargetFilesystemArtifactDependency<ArtifactT, ArtifactNameTag> + : TargetFilesystemArtifactDependencyCMP0112 +{ +}; +template <typename ArtifactT> +struct TargetFilesystemArtifactDependency<ArtifactT, ArtifactDirTag> + : TargetFilesystemArtifactDependencyCMP0112 +{ +}; +template <> +struct TargetFilesystemArtifactDependency<ArtifactBundleDirTag, + ArtifactPathTag> + : TargetFilesystemArtifactDependencyCMP0112 +{ +}; +template <> +struct TargetFilesystemArtifactDependency<ArtifactBundleContentDirTag, + ArtifactPathTag> + : TargetFilesystemArtifactDependencyCMP0112 +{ +}; + template <typename ArtifactT> struct TargetFilesystemArtifactResultCreator { @@ -2143,8 +2218,10 @@ struct TargetFilesystemArtifact : public TargetArtifactBase if (!target) { return std::string(); } - context->DependTargets.insert(target); - context->AllTargets.insert(target); + // Not a dependent target if we are querying for ArtifactDirTag, + // ArtifactNameTag, ArtifactBundleDirTag, and ArtifactBundleContentDirTag + TargetFilesystemArtifactDependency<ArtifactT, ComponentT>::AddDependency( + target, context); std::string result = TargetFilesystemArtifactResultCreator<ArtifactT>::Create(target, context, diff --git a/Source/cmGeneratorExpressionNode.h b/Source/cmGeneratorExpressionNode.h index 13e8484..f068b02 100644 --- a/Source/cmGeneratorExpressionNode.h +++ b/Source/cmGeneratorExpressionNode.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGeneratorExpressionNode_h -#define cmGeneratorExpressionNode_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -52,5 +51,3 @@ struct cmGeneratorExpressionNode void reportError(cmGeneratorExpressionContext* context, const std::string& expr, const std::string& result); - -#endif diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h index 1ba1654..d49bf3e 100644 --- a/Source/cmGeneratorExpressionParser.h +++ b/Source/cmGeneratorExpressionParser.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGeneratorExpressionParser_h -#define cmGeneratorExpressionParser_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -30,5 +29,3 @@ private: const std::vector<cmGeneratorExpressionToken> Tokens; unsigned int NestingLevel; }; - -#endif diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index ab6a26c..1bb069f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -43,6 +43,7 @@ #include "cmSourceFile.h" #include "cmSourceFileLocation.h" #include "cmSourceFileLocationKind.h" +#include "cmStandardLevelResolver.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -364,7 +365,7 @@ std::string cmGeneratorTarget::GetExportName() const { cmProp exportName = this->GetProperty("EXPORT_NAME"); - if (exportName && !exportName->empty()) { + if (cmNonempty(exportName)) { if (!cmGeneratorExpression::IsValidTargetName(*exportName)) { std::ostringstream e; e << "EXPORT_NAME property \"" << *exportName << "\" for \"" @@ -379,11 +380,6 @@ std::string cmGeneratorTarget::GetExportName() const cmProp cmGeneratorTarget::GetProperty(const std::string& prop) const { - if (!cmTargetPropertyComputer::PassesWhitelist( - this->GetType(), prop, this->Makefile->GetMessenger(), - this->GetBacktrace())) { - return nullptr; - } if (cmProp result = cmTargetPropertyComputer::GetProperty( this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) { return result; @@ -629,13 +625,13 @@ const char* cmGeneratorTarget::GetFilePrefixInternal( const char* prefixVar = this->Target->GetPrefixVariableInternal(artifact); if (!language.empty() && prefixVar && *prefixVar) { std::string langPrefix = prefixVar + std::string("_") + language; - targetPrefix = this->Makefile->GetDef(langPrefix); + targetPrefix = this->Makefile->GetDefinition(langPrefix); } // if there is no prefix on the target nor specific language // use the cmake definition. if (!targetPrefix && prefixVar) { - targetPrefix = this->Makefile->GetDef(prefixVar); + targetPrefix = this->Makefile->GetDefinition(prefixVar); } } @@ -679,13 +675,13 @@ const char* cmGeneratorTarget::GetFileSuffixInternal( const char* suffixVar = this->Target->GetSuffixVariableInternal(artifact); if (!language.empty() && suffixVar && *suffixVar) { std::string langSuffix = suffixVar + std::string("_") + language; - targetSuffix = this->Makefile->GetDef(langSuffix); + targetSuffix = this->Makefile->GetDefinition(langSuffix); } // if there is no suffix on the target nor specific language // use the cmake definition. if (!targetSuffix && suffixVar) { - targetSuffix = this->Makefile->GetDef(suffixVar); + targetSuffix = this->Makefile->GetDefinition(suffixVar); } } @@ -801,7 +797,8 @@ void cmGeneratorTarget::GetObjectSources( void cmGeneratorTarget::ComputeObjectMapping() { - auto const& configs = this->Makefile->GetGeneratorConfigs(); + auto const& configs = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); std::set<std::string> configSet(configs.begin(), configs.end()); if (configSet == this->VisitedConfigsForObjects) { return; @@ -813,18 +810,18 @@ void cmGeneratorTarget::ComputeObjectMapping() } } -const char* cmGeneratorTarget::GetFeature(const std::string& feature, - const std::string& config) const +cmProp cmGeneratorTarget::GetFeature(const std::string& feature, + const std::string& config) const { if (!config.empty()) { std::string featureConfig = cmStrCat(feature, '_', cmSystemTools::UpperCase(config)); if (cmProp value = this->GetProperty(featureConfig)) { - return value->c_str(); + return value; } } if (cmProp value = this->GetProperty(feature)) { - return value->c_str(); + return value; } return this->LocalGenerator->GetFeature(feature, config); } @@ -851,10 +848,9 @@ const char* cmGeneratorTarget::GetLinkPIEProperty( bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, std::string const& config) const { - const char* feature = "INTERPROCEDURAL_OPTIMIZATION"; - const bool result = cmIsOn(this->GetFeature(feature, config)); + cmProp feature = this->GetFeature("INTERPROCEDURAL_OPTIMIZATION", config); - if (!result) { + if (!cmIsOn(feature)) { // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies return false; } @@ -947,6 +943,61 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const return it != this->ExplicitObjectName.end(); } +BTs<std::string> const* cmGeneratorTarget::GetLanguageStandardProperty( + std::string const& lang, std::string const& config) const +{ + std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang); + auto langStandardIter = this->LanguageStandardMap.find(key); + if (langStandardIter != this->LanguageStandardMap.end()) { + return &langStandardIter->second; + } + + return this->Target->GetLanguageStandardProperty( + cmStrCat(lang, "_STANDARD")); +} + +cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang, + std::string const& config) const +{ + BTs<std::string> const* languageStandard = + this->GetLanguageStandardProperty(lang, config); + + if (languageStandard) { + return &(languageStandard->Value); + } + + return nullptr; +} + +cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport( + std::string const& lang, const char* suffix) const +{ + cmProp propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix)); + if (propertyValue == nullptr) { + // Check if we should use the value set by another language. + if (lang == "OBJC") { + propertyValue = this->GetPropertyWithPairedLanguageSupport("C", suffix); + } else if (lang == "OBJCXX" || lang == "CUDA") { + propertyValue = + this->GetPropertyWithPairedLanguageSupport("CXX", suffix); + } + } + return propertyValue; +} + +cmProp cmGeneratorTarget::GetLanguageExtensions(std::string const& lang) const +{ + return this->GetPropertyWithPairedLanguageSupport(lang, "_EXTENSIONS"); +} + +bool cmGeneratorTarget::GetLanguageStandardRequired( + std::string const& lang) const +{ + cmProp p = + this->GetPropertyWithPairedLanguageSupport(lang, "_STANDARD_REQUIRED"); + return cmIsOn(p); +} + void cmGeneratorTarget::GetModuleDefinitionSources( std::vector<cmSourceFile const*>& data, const std::string& config) const { @@ -1033,6 +1084,62 @@ std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPostBuildCommands() return this->Target->GetPostBuildCommands(); } +void cmGeneratorTarget::AppendCustomCommandSideEffects( + std::set<cmGeneratorTarget const*>& sideEffects) const +{ + if (!this->GetPreBuildCommands().empty() || + !this->GetPreLinkCommands().empty() || + !this->GetPostBuildCommands().empty()) { + sideEffects.insert(this); + } else { + for (auto const& source : this->GetAllConfigSources()) { + if (source.Source->GetCustomCommand() != nullptr) { + sideEffects.insert(this); + break; + } + } + } +} + +void cmGeneratorTarget::AppendLanguageSideEffects( + std::map<std::string, std::set<cmGeneratorTarget const*>>& sideEffects) const +{ + static const std::set<cm::string_view> LANGS_WITH_NO_SIDE_EFFECTS = { + "C"_s, "CXX"_s, "OBJC"_s, "OBJCXX"_s, "ASM"_s, "CUDA"_s, + }; + + for (auto const& lang : this->GetAllConfigCompileLanguages()) { + if (!LANGS_WITH_NO_SIDE_EFFECTS.count(lang)) { + sideEffects[lang].insert(this); + } + } +} + +bool cmGeneratorTarget::IsInBuildSystem() const +{ + if (this->IsImported()) { + return false; + } + switch (this->Target->GetType()) { + case cmStateEnums::EXECUTABLE: + case cmStateEnums::STATIC_LIBRARY: + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::OBJECT_LIBRARY: + case cmStateEnums::UTILITY: + case cmStateEnums::GLOBAL_TARGET: + return true; + case cmStateEnums::INTERFACE_LIBRARY: + // An INTERFACE library is in the build system if it has SOURCES. + if (!this->SourceEntries.empty()) { + return true; + } + case cmStateEnums::UNKNOWN_LIBRARY: + break; + } + return false; +} + bool cmGeneratorTarget::IsImported() const { return this->Target->IsImported(); @@ -1043,6 +1150,11 @@ bool cmGeneratorTarget::IsImportedGloballyVisible() const return this->Target->IsImportedGloballyVisible(); } +bool cmGeneratorTarget::CanCompileSources() const +{ + return this->Target->CanCompileSources(); +} + const std::string& cmGeneratorTarget::GetLocationForBuild() const { static std::string location; @@ -1055,10 +1167,10 @@ const std::string& cmGeneratorTarget::GetLocationForBuild() const // Now handle the deprecated build-time configuration location. std::string const noConfig; location = this->GetDirectory(noConfig); - const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); - if (cfgid && strcmp(cfgid, ".") != 0) { + cmProp cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); + if (cfgid && (*cfgid != ".")) { location += "/"; - location += cfgid; + location += *cfgid; } if (this->IsAppBundleOnApple()) { @@ -1137,7 +1249,7 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty( // If this target itself has a non-empty property value, we are done. cmProp p = this->GetProperty(prop); - maybeInterfaceProp = p && !p->empty(); + maybeInterfaceProp = cmNonempty(p); // Otherwise, recurse to interface dependencies. if (!maybeInterfaceProp) { @@ -1251,18 +1363,25 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( } namespace { -std::string AddSwiftInterfaceIncludeDirectories( + +enum class IncludeDirectoryFallBack +{ + BINARY, + OBJECT +}; + +std::string AddLangSpecificInterfaceIncludeDirectories( const cmGeneratorTarget* root, const cmGeneratorTarget* target, - const std::string& config, cmGeneratorExpressionDAGChecker* context) + const std::string& lang, const std::string& config, + const std::string& propertyName, IncludeDirectoryFallBack mode, + cmGeneratorExpressionDAGChecker* context) { cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, - "Swift_MODULE_DIRECTORY", nullptr, - context }; + propertyName, nullptr, context }; switch (dag.Check()) { case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: - dag.ReportError(nullptr, - "$<TARGET_PROPERTY:" + target->GetName() + - ",Swift_MODULE_DIRECTORY>"); + dag.ReportError( + nullptr, "$<TARGET_PROPERTY:" + target->GetName() + ",propertyName"); CM_FALLTHROUGH; case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: // No error. We just skip cyclic references. @@ -1278,13 +1397,16 @@ std::string AddSwiftInterfaceIncludeDirectories( target->GetLinkInterfaceLibraries(config, root, true)) { for (const cmLinkItem& library : interface->Libraries) { if (const cmGeneratorTarget* dependency = library.Target) { - if (cm::contains(dependency->GetAllConfigCompileLanguages(), - "Swift")) { - std::string value = - dependency->GetSafeProperty("Swift_MODULE_DIRECTORY"); + if (cm::contains(dependency->GetAllConfigCompileLanguages(), lang)) { + auto* lg = dependency->GetLocalGenerator(); + std::string value = dependency->GetSafeProperty(propertyName); if (value.empty()) { - value = - dependency->GetLocalGenerator()->GetCurrentBinaryDirectory(); + if (mode == IncludeDirectoryFallBack::BINARY) { + value = lg->GetCurrentBinaryDirectory(); + } else if (mode == IncludeDirectoryFallBack::OBJECT) { + value = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', + lg->GetTargetDirectory(dependency)); + } } if (!directories.empty()) { @@ -1298,35 +1420,39 @@ std::string AddSwiftInterfaceIncludeDirectories( return directories; } -void AddSwiftImplicitIncludeDirectories( - const cmGeneratorTarget* target, const std::string& config, - EvaluatedTargetPropertyEntries& entries) +void AddLangSpecificImplicitIncludeDirectories( + const cmGeneratorTarget* target, const std::string& lang, + const std::string& config, const std::string& propertyName, + IncludeDirectoryFallBack mode, EvaluatedTargetPropertyEntries& entries) { if (const auto* libraries = target->GetLinkImplementationLibraries(config)) { cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, - "Swift_MODULE_DIRECTORY", nullptr, - nullptr }; + propertyName, nullptr, nullptr }; for (const cmLinkImplItem& library : libraries->Libraries) { if (const cmGeneratorTarget* dependency = library.Target) { - if (dependency->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!dependency->IsInBuildSystem()) { continue; } - if (cm::contains(dependency->GetAllConfigCompileLanguages(), - "Swift")) { + if (cm::contains(dependency->GetAllConfigCompileLanguages(), lang)) { + auto* lg = dependency->GetLocalGenerator(); EvaluatedTargetPropertyEntry entry{ library, library.Backtrace }; - if (cmProp val = dependency->GetProperty("Swift_MODULE_DIRECTORY")) { + if (cmProp val = dependency->GetProperty(propertyName)) { entry.Values.emplace_back(*val); } else { - entry.Values.emplace_back( - dependency->GetLocalGenerator()->GetCurrentBinaryDirectory()); + if (mode == IncludeDirectoryFallBack::BINARY) { + entry.Values.emplace_back(lg->GetCurrentBinaryDirectory()); + } else if (mode == IncludeDirectoryFallBack::OBJECT) { + entry.Values.emplace_back( + dependency->GetObjectDirectory(config)); + } } - cmExpandList(AddSwiftInterfaceIncludeDirectories(target, dependency, - config, &dag), - entry.Values); - + cmExpandList( + AddLangSpecificInterfaceIncludeDirectories( + target, dependency, lang, config, propertyName, mode, &dag), + entry.Values); entries.Entries.emplace_back(std::move(entry)); } } @@ -1466,7 +1592,6 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( std::string const& config) const { std::vector<BT<std::string>> files; - assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY); if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) { // At configure-time, this method can be called as part of getting the @@ -1658,9 +1783,11 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); if (sf->GetCustomCommand()) { kind = SourceKindCustomCommand; - // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 - // NOLINTNEXTLINE(bugprone-branch-clone) - } else if (this->Target->GetType() == cmStateEnums::UTILITY) { + } else if (this->Target->GetType() == cmStateEnums::UTILITY || + this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY + // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 + // NOLINTNEXTLINE(bugprone-branch-clone) + ) { kind = SourceKindExtra; } else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) { kind = SourceKindUnityBatched; @@ -1726,8 +1853,8 @@ cmGeneratorTarget::GetAllConfigSources() const void cmGeneratorTarget::ComputeAllConfigSources() const { - std::vector<std::string> configs; - this->Makefile->GetConfigurations(configs); + std::vector<std::string> configs = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); std::map<cmSourceFile const*, size_t> index; @@ -1787,12 +1914,12 @@ std::string cmGeneratorTarget::GetCompilePDBName( std::string configUpper = cmSystemTools::UpperCase(config); std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper); cmProp config_name = this->GetProperty(configProp); - if (config_name && !config_name->empty()) { + if (cmNonempty(config_name)) { return prefix + *config_name + ".pdb"; } cmProp name = this->GetProperty("COMPILE_PDB_NAME"); - if (name && !name->empty()) { + if (cmNonempty(name)) { return prefix + *name + ".pdb"; } @@ -1938,13 +2065,13 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const if (!ll.empty()) { std::string sepVar = cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP"); - const char* sep = this->Makefile->GetDefinition(sepVar); - if (sep && *sep) { + cmProp sep = this->Makefile->GetDefinition(sepVar); + if (cmNonempty(sep)) { // TODO: Add ELF check to ABI detection and get rid of // CMAKE_EXECUTABLE_FORMAT. - if (const char* fmt = + if (cmProp fmt = this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) { - return strcmp(fmt, "ELF") == 0; + return (*fmt == "ELF"); } } } @@ -2153,6 +2280,12 @@ bool cmGeneratorTarget::IsBundleOnApple() const this->IsCFBundleOnApple(); } +bool cmGeneratorTarget::IsWin32Executable(const std::string& config) const +{ + return cmIsOn(cmGeneratorExpression::Evaluate( + this->GetSafeProperty("WIN32_EXECUTABLE"), this->LocalGenerator, config)); +} + std::string cmGeneratorTarget::GetCFBundleDirectory( const std::string& config, BundleDirectoryLevel level) const { @@ -2239,7 +2372,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree( cmProp install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) { - if (install_name_dir && !install_name_dir->empty()) { + if (cmNonempty(install_name_dir)) { dir = *install_name_dir; cmGeneratorExpression::ReplaceInstallPrefix(dir, installPrefix); dir = @@ -2385,6 +2518,12 @@ private: cmGeneratorTarget::LinkClosure const* cmGeneratorTarget::GetLinkClosure( const std::string& config) const { + // There is no link implementation for targets that cannot compile sources. + if (!this->CanCompileSources()) { + static LinkClosure const empty = { {}, {} }; + return ∅ + } + std::string key(cmSystemTools::UpperCase(config)); auto i = this->LinkClosureMap.find(key); if (i == this->LinkClosureMap.end()) { @@ -2701,6 +2840,12 @@ const std::vector<const cmGeneratorTarget*>& cmGeneratorTarget::GetLinkImplementationClosure( const std::string& config) const { + // There is no link implementation for targets that cannot compile sources. + if (!this->CanCompileSources()) { + static std::vector<const cmGeneratorTarget*> const empty; + return empty; + } + LinkImplClosure& tgts = this->LinkImplClosureMap[config]; if (!tgts.Done) { tgts.Done = true; @@ -2708,6 +2853,7 @@ cmGeneratorTarget::GetLinkImplementationClosure( cmLinkImplementationLibraries const* impl = this->GetLinkImplementationLibraries(config); + assert(impl); for (cmLinkImplItem const& lib : impl->Libraries) { processILibs(config, this, lib, @@ -2757,29 +2903,26 @@ cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target) this->CurrentEntry = nullptr; // Queue all the source files already specified for the target. - if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - std::set<cmSourceFile*> emitted; - std::vector<std::string> const& configs = - this->Makefile->GetGeneratorConfigs(); - for (std::string const& c : configs) { - std::vector<cmSourceFile*> sources; - this->GeneratorTarget->GetSourceFiles(sources, c); - for (cmSourceFile* sf : sources) { - const std::set<cmGeneratorTarget const*> tgts = - this->GlobalGenerator->GetFilenameTargetDepends(sf); - if (cm::contains(tgts, this->GeneratorTarget)) { - std::ostringstream e; - e << "Evaluation output file\n \"" << sf->ResolveFullPath() - << "\"\ndepends on the sources of a target it is used in. This " - "is a dependency loop and is not allowed."; - this->GeneratorTarget->LocalGenerator->IssueMessage( - MessageType::FATAL_ERROR, e.str()); - return; - } - if (emitted.insert(sf).second && - this->SourcesQueued.insert(sf).second) { - this->SourceQueue.push(sf); - } + std::set<cmSourceFile*> emitted; + std::vector<std::string> const& configs = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + for (std::string const& c : configs) { + std::vector<cmSourceFile*> sources; + this->GeneratorTarget->GetSourceFiles(sources, c); + for (cmSourceFile* sf : sources) { + const std::set<cmGeneratorTarget const*> tgts = + this->GlobalGenerator->GetFilenameTargetDepends(sf); + if (cm::contains(tgts, this->GeneratorTarget)) { + std::ostringstream e; + e << "Evaluation output file\n \"" << sf->ResolveFullPath() + << "\"\ndepends on the sources of a target it is used in. This " + "is a dependency loop and is not allowed."; + this->GeneratorTarget->LocalGenerator->IssueMessage( + MessageType::FATAL_ERROR, e.str()); + return; + } + if (emitted.insert(sf).second && this->SourcesQueued.insert(sf).second) { + this->SourceQueue.push(sf); } } } @@ -2971,7 +3114,7 @@ void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc) // Queue the custom command dependencies. std::set<std::string> emitted; std::vector<std::string> const& configs = - this->Makefile->GetGeneratorConfigs(); + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); for (std::string const& conf : configs) { this->FollowCommandDepends(cc, conf, emitted); } @@ -3111,7 +3254,7 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const } else { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, - "Uknown CUDA architecture specifier \"" + std::string(specifier) + + "Unknown CUDA architecture specifier \"" + std::string(specifier) + "\"."); } } @@ -3159,6 +3302,27 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const } } +void cmGeneratorTarget::AddISPCTargetFlags(std::string& flags) const +{ + const std::string& property = this->GetSafeProperty("ISPC_INSTRUCTION_SETS"); + + // If ISPC_TARGET is false we don't add any architectures. + if (cmIsOff(property)) { + return; + } + + std::string const& compiler = + this->Makefile->GetSafeDefinition("CMAKE_ISPC_COMPILER_ID"); + + if (compiler == "Intel") { + std::vector<std::string> targets; + cmExpandList(property, targets); + if (!targets.empty()) { + flags += cmStrCat(" --target=", cmWrap("", targets, "", ",")); + } + } +} + void cmGeneratorTarget::AddCUDAToolkitFlags(std::string& flags) const { std::string const& compiler = @@ -3353,30 +3517,52 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( this, config, lang, &dagChecker, this->IncludeDirectoriesEntries); if (lang == "Swift") { - AddSwiftImplicitIncludeDirectories(this, config, entries); + AddLangSpecificImplicitIncludeDirectories( + this, lang, config, "Swift_MODULE_DIRECTORY", + IncludeDirectoryFallBack::BINARY, entries); + } + + if (this->CanCompileSources() && (lang != "Swift" && lang != "Fortran")) { + + const std::string propertyName = "ISPC_HEADER_DIRECTORY"; + + // If this target has ISPC sources make sure to add the header + // directory to other compilation units + if (cm::contains(this->GetAllConfigCompileLanguages(), "ISPC")) { + if (cmProp val = this->GetProperty(propertyName)) { + includes.emplace_back(*val); + } else { + includes.emplace_back(this->GetObjectDirectory(config)); + } + } + + AddLangSpecificImplicitIncludeDirectories( + this, "ISPC", config, propertyName, IncludeDirectoryFallBack::OBJECT, + entries); } AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang, &dagChecker, entries); if (this->Makefile->IsOn("APPLE")) { - cmLinkImplementationLibraries const* impl = - this->GetLinkImplementationLibraries(config); - for (cmLinkImplItem const& lib : impl->Libraries) { - std::string libDir = cmSystemTools::CollapseFullPath( - lib.AsStr(), this->Makefile->GetHomeOutputDirectory()); - - static cmsys::RegularExpression frameworkCheck( - "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); - if (!frameworkCheck.find(libDir)) { - continue; - } + if (cmLinkImplementationLibraries const* impl = + this->GetLinkImplementationLibraries(config)) { + for (cmLinkImplItem const& lib : impl->Libraries) { + std::string libDir = cmSystemTools::CollapseFullPath( + lib.AsStr(), this->Makefile->GetHomeOutputDirectory()); + + static cmsys::RegularExpression frameworkCheck( + "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); + if (!frameworkCheck.find(libDir)) { + continue; + } - libDir = frameworkCheck.match(1); + libDir = frameworkCheck.match(1); - EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace()); - ee.Values.emplace_back(std::move(libDir)); - entries.Entries.emplace_back(std::move(ee)); + EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace()); + ee.Values.emplace_back(std::move(libDir)); + entries.Entries.emplace_back(std::move(ee)); + } } } @@ -3744,8 +3930,8 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, const std::string filename_tmp = cmStrCat(filename, ".tmp"); if (!pchReuseFrom) { - auto pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE"); - auto pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE"); + cmProp pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE"); + cmProp pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE"); std::string firstHeaderOnDisk; { @@ -3754,7 +3940,7 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, this->GetGlobalGenerator()->GetMakefileEncoding()); file << "/* generated by CMake */\n\n"; if (pchPrologue) { - file << pchPrologue << "\n"; + file << *pchPrologue << "\n"; } if (this->GetGlobalGenerator()->IsXcode()) { file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n"; @@ -3784,7 +3970,7 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, file << "#endif // CMAKE_SKIP_PRECOMPILE_HEADERS\n"; } if (pchEpilogue) { - file << pchEpilogue << "\n"; + file << *pchEpilogue << "\n"; } } @@ -3827,7 +4013,7 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config, cmStrCat(generatorTarget->LocalGenerator->GetCurrentBinaryDirectory(), "/CMakeFiles/", generatorTarget->GetName(), ".dir/cmake_pch"); - // For GCC the source extension will be tranformed into .h[xx].gch + // For GCC the source extension will be transformed into .h[xx].gch if (!this->Makefile->IsOn("CMAKE_LINK_PCH")) { const std::map<std::string, std::string> languageToExtension = { { "C", ".h.c" }, @@ -4414,12 +4600,75 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const { + // Compute the language standard based on the compile features. + cmStandardLevelResolver standardResolver(this->Makefile); std::vector<BT<std::string>> features = this->GetCompileFeatures(config); for (BT<std::string> const& f : features) { - if (!this->Makefile->AddRequiredTargetFeature(this->Target, f.Value)) { + std::string lang; + if (!standardResolver.CompileFeatureKnown(this->Target->GetName(), f.Value, + lang, nullptr)) { + return false; + } + + std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang); + cmProp currentLanguageStandard = this->GetLanguageStandard(lang, config); + + std::string newRequiredStandard; + if (!standardResolver.GetNewRequiredStandard( + this->Target->GetName(), f.Value, currentLanguageStandard, + newRequiredStandard)) { return false; } + + if (!newRequiredStandard.empty()) { + BTs<std::string>& languageStandardProperty = + this->LanguageStandardMap[key]; + if (languageStandardProperty.Value != newRequiredStandard) { + languageStandardProperty.Value = newRequiredStandard; + languageStandardProperty.Backtraces.clear(); + } + languageStandardProperty.Backtraces.emplace_back(f.Backtrace); + } + } + + return true; +} + +bool cmGeneratorTarget::ComputeCompileFeatures( + std::string const& config, std::set<LanguagePair> const& languagePairs) const +{ + for (const auto& language : languagePairs) { + BTs<std::string> const* generatorTargetLanguageStandard = + this->GetLanguageStandardProperty(language.first, config); + if (!generatorTargetLanguageStandard) { + // If the standard isn't explicitly set we copy it over from the + // specified paired language. + std::string key = + cmStrCat(cmSystemTools::UpperCase(config), '-', language.first); + BTs<std::string> const* standardToCopy = + this->GetLanguageStandardProperty(language.second, config); + if (standardToCopy != nullptr) { + this->LanguageStandardMap[key] = *standardToCopy; + generatorTargetLanguageStandard = &this->LanguageStandardMap[key]; + } else { + cmProp defaultStandard = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", language.second, "_STANDARD_DEFAULT")); + if (defaultStandard != nullptr) { + this->LanguageStandardMap[key] = BTs<std::string>(*defaultStandard); + generatorTargetLanguageStandard = &this->LanguageStandardMap[key]; + } + } + + // Custom updates for the CUDA standard. + if (generatorTargetLanguageStandard != nullptr && + language.first == "CUDA") { + if (generatorTargetLanguageStandard->Value == "98") { + this->LanguageStandardMap[key].Value = "03"; + } + } + } } + return true; } @@ -4547,12 +4796,11 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames( // The library's soname. this->ComputeVersionedName(targetNames.SharedObject, prefix, targetNames.Base, suffix, targetNames.Output, - (soversion ? soversion->c_str() : nullptr)); + cmToCStr(soversion)); // The library's real name on disk. this->ComputeVersionedName(targetNames.Real, prefix, targetNames.Base, - suffix, targetNames.Output, - (version ? version->c_str() : nullptr)); + suffix, targetNames.Output, cmToCStr(version)); } // The import library name. @@ -4588,10 +4836,7 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames( const char* version = nullptr; #else // Check for executable version properties. - const char* version = nullptr; - if (cmProp p = this->GetProperty("VERSION")) { - version = p->c_str(); - } + const char* version = cmToCStr(this->GetProperty("VERSION")); if (this->GetType() != cmStateEnums::EXECUTABLE || this->Makefile->IsOn("XCODE")) { version = nullptr; @@ -4843,6 +5088,11 @@ void cmGeneratorTarget::GetTargetObjectNames( assert(!map_it->second.empty()); objects.push_back(map_it->second); } + + auto ispcObjects = this->GetGeneratedISPCObjects(config); + for (std::string const& output : ispcObjects) { + objects.push_back(cmSystemTools::GetFilenameName(output)); + } } bool cmGeneratorTarget::StrictTargetComparison::operator()( @@ -5297,8 +5547,7 @@ bool getTypedProperty<bool>(cmGeneratorTarget const* tgt, } cmProp value = tgt->GetProperty(prop); - return cmIsOn( - genexInterpreter->Evaluate(value ? value->c_str() : nullptr, prop)); + return cmIsOn(genexInterpreter->Evaluate(value ? *value : "", prop)); } template <> @@ -5309,11 +5558,10 @@ const char* getTypedProperty<const char*>( cmProp value = tgt->GetProperty(prop); if (genexInterpreter == nullptr) { - return value ? value->c_str() : nullptr; + return cmToCStr(value); } - return genexInterpreter->Evaluate(value ? value->c_str() : nullptr, prop) - .c_str(); + return genexInterpreter->Evaluate(value ? *value : "", prop).c_str(); } template <> @@ -5324,10 +5572,10 @@ std::string getTypedProperty<std::string>( cmProp value = tgt->GetProperty(prop); if (genexInterpreter == nullptr) { - return valueAsString(value ? value->c_str() : nullptr); + return valueAsString(cmToCStr(value)); } - return genexInterpreter->Evaluate(value ? value->c_str() : nullptr, prop); + return genexInterpreter->Evaluate(value ? *value : "", prop); } template <typename PropertyType> @@ -5726,9 +5974,9 @@ std::string cmGeneratorTarget::GetRuntimeLinkLibrary( { // This is activated by the presence of a default selection whether or // not it is overridden by a property. - cmProp runtimeLibraryDefault = this->Makefile->GetDef( + cmProp runtimeLibraryDefault = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_RUNTIME_LIBRARY_DEFAULT")); - if (!runtimeLibraryDefault || runtimeLibraryDefault->empty()) { + if (!cmNonempty(runtimeLibraryDefault)) { return std::string(); } cmProp runtimeLibraryValue = @@ -5766,7 +6014,7 @@ std::string cmGeneratorTarget::CreateFortranModuleDirectory( target_mod_dir = default_mod_dir; } } - const char* moddir_flag = + cmProp moddir_flag = this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG"); if (!target_mod_dir.empty() && moddir_flag) { // Compute the full path to the module directory. @@ -5785,6 +6033,66 @@ std::string cmGeneratorTarget::CreateFortranModuleDirectory( return mod_dir; } +void cmGeneratorTarget::AddISPCGeneratedHeader(std::string const& header, + std::string const& config) +{ + std::string config_upper; + if (!config.empty()) { + config_upper = cmSystemTools::UpperCase(config); + } + auto iter = this->ISPCGeneratedHeaders.find(config_upper); + if (iter == this->ISPCGeneratedHeaders.end()) { + std::vector<std::string> headers; + headers.emplace_back(header); + this->ISPCGeneratedHeaders.insert({ config_upper, headers }); + } else { + iter->second.emplace_back(header); + } +} + +std::vector<std::string> cmGeneratorTarget::GetGeneratedISPCHeaders( + std::string const& config) const +{ + std::string config_upper; + if (!config.empty()) { + config_upper = cmSystemTools::UpperCase(config); + } + auto iter = this->ISPCGeneratedHeaders.find(config_upper); + if (iter == this->ISPCGeneratedHeaders.end()) { + return std::vector<std::string>{}; + } + return iter->second; +} + +void cmGeneratorTarget::AddISPCGeneratedObject(std::vector<std::string>&& objs, + std::string const& config) +{ + std::string config_upper; + if (!config.empty()) { + config_upper = cmSystemTools::UpperCase(config); + } + auto iter = this->ISPCGeneratedObjects.find(config_upper); + if (iter == this->ISPCGeneratedObjects.end()) { + this->ISPCGeneratedObjects.insert({ config_upper, objs }); + } else { + iter->second.insert(iter->second.end(), objs.begin(), objs.end()); + } +} + +std::vector<std::string> cmGeneratorTarget::GetGeneratedISPCObjects( + std::string const& config) const +{ + std::string config_upper; + if (!config.empty()) { + config_upper = cmSystemTools::UpperCase(config); + } + auto iter = this->ISPCGeneratedObjects.find(config_upper); + if (iter == this->ISPCGeneratedObjects.end()) { + return std::vector<std::string>{}; + } + return iter->second; +} + std::string cmGeneratorTarget::GetFrameworkVersion() const { assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY); @@ -6164,21 +6472,16 @@ bool cmGeneratorTarget::ComputeOutputDir(const std::string& config, // Look for a target property defining the target output directory // based on the target type. std::string targetTypeName = this->GetOutputTargetType(artifact); - const char* propertyName = nullptr; - std::string propertyNameStr = targetTypeName; - if (!propertyNameStr.empty()) { - propertyNameStr += "_OUTPUT_DIRECTORY"; - propertyName = propertyNameStr.c_str(); + std::string propertyName; + if (!targetTypeName.empty()) { + propertyName = cmStrCat(targetTypeName, "_OUTPUT_DIRECTORY"); } // Check for a per-configuration output directory target property. std::string configUpper = cmSystemTools::UpperCase(conf); - const char* configProp = nullptr; - std::string configPropStr = targetTypeName; - if (!configPropStr.empty()) { - configPropStr += "_OUTPUT_DIRECTORY_"; - configPropStr += configUpper; - configProp = configPropStr.c_str(); + std::string configProp; + if (!targetTypeName.empty()) { + configProp = cmStrCat(targetTypeName, "_OUTPUT_DIRECTORY_", configUpper); } // Select an output directory. @@ -6239,22 +6542,17 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind, { // Look for a target property defining the target output directory // based on the target type. - const char* propertyName = nullptr; - std::string propertyNameStr = kind; - if (!propertyNameStr.empty()) { - propertyNameStr += "_OUTPUT_DIRECTORY"; - propertyName = propertyNameStr.c_str(); + std::string propertyName; + if (!kind.empty()) { + propertyName = cmStrCat(kind, "_OUTPUT_DIRECTORY"); } std::string conf = config; // Check for a per-configuration output directory target property. std::string configUpper = cmSystemTools::UpperCase(conf); - const char* configProp = nullptr; - std::string configPropStr = kind; - if (!configPropStr.empty()) { - configPropStr += "_OUTPUT_DIRECTORY_"; - configPropStr += configUpper; - configProp = configPropStr.c_str(); + std::string configProp; + if (!kind.empty()) { + configProp = cmStrCat(kind, "_OUTPUT_DIRECTORY_", configUpper); } // Select an output directory. @@ -6410,15 +6708,20 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( iface.HadHeadSensitiveCondition, iface.HadContextSensitiveCondition, iface.HadLinkLanguageSensitiveCondition); - } else if (!cmp0022NEW) + return; + } + // If CMP0022 is NEW then the plain tll signature sets the // INTERFACE_LINK_LIBRARIES, so if we get here then the project // cleared the property explicitly and we should not fall back // to the link implementation. - { - // The link implementation is the default link interface. - cmLinkImplementationLibraries const* impl = - this->GetLinkImplementationLibrariesInternal(config, headTarget); + if (cmp0022NEW) { + return; + } + + // The link implementation is the default link interface. + if (cmLinkImplementationLibraries const* impl = + this->GetLinkImplementationLibrariesInternal(config, headTarget)) { iface.Libraries.insert(iface.Libraries.end(), impl->Libraries.begin(), impl->Libraries.end()); if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN && @@ -6712,8 +7015,8 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation( const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation( const std::string& config, bool secondPass) const { - // There is no link implementation for imported targets. - if (this->IsImported()) { + // There is no link implementation for targets that cannot compile sources. + if (!this->CanCompileSources()) { return nullptr; } @@ -6737,7 +7040,7 @@ bool cmGeneratorTarget::GetConfigCommonSourceFiles( std::vector<cmSourceFile*>& files) const { std::vector<std::string> const& configs = - this->Makefile->GetGeneratorConfigs(); + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); auto it = configs.begin(); const std::string& firstConfig = *it; @@ -6861,7 +7164,7 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const bool cmGeneratorTarget::IsDeprecated() const { cmProp deprecation = this->GetProperty("DEPRECATION"); - return deprecation && !deprecation->empty(); + return cmNonempty(deprecation); } std::string cmGeneratorTarget::GetDeprecation() const @@ -6876,6 +7179,11 @@ std::string cmGeneratorTarget::GetDeprecation() const void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages, const std::string& config) const { + // Targets that do not compile anything have no languages. + if (!this->CanCompileSources()) { + return; + } + std::vector<cmSourceFile*> sourceFiles; this->GetSourceFiles(sourceFiles, config); for (cmSourceFile* src : sourceFiles) { @@ -6926,7 +7234,7 @@ bool cmGeneratorTarget::IsCSharpOnly() const // Consider an explicit linker language property, but *not* the // computed linker language that may depend on linked targets. cmProp linkLang = this->GetProperty("LINKER_LANGUAGE"); - if (linkLang && !linkLang->empty()) { + if (cmNonempty(linkLang)) { languages.insert(*linkLang); } return languages.size() == 1 && languages.count("CSharp") > 0; @@ -6971,8 +7279,8 @@ cmLinkImplementationLibraries const* cmGeneratorTarget::GetLinkImplementationLibrariesInternal( const std::string& config, cmGeneratorTarget const* head) const { - // There is no link implementation for imported targets. - if (this->IsImported()) { + // There is no link implementation for targets that cannot compile sources. + if (!this->CanCompileSources()) { return nullptr; } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 3aedbf5..330d784 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGeneratorTarget_h -#define cmGeneratorTarget_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -45,14 +44,22 @@ public: cmGlobalGenerator* GetGlobalGenerator() const; + bool IsInBuildSystem() const; bool IsImported() const; bool IsImportedGloballyVisible() const; + bool CanCompileSources() const; const std::string& GetLocation(const std::string& config) const; std::vector<cmCustomCommand> const& GetPreBuildCommands() const; std::vector<cmCustomCommand> const& GetPreLinkCommands() const; std::vector<cmCustomCommand> const& GetPostBuildCommands() const; + void AppendCustomCommandSideEffects( + std::set<cmGeneratorTarget const*>& sideEffects) const; + void AppendLanguageSideEffects( + std::map<std::string, std::set<cmGeneratorTarget const*>>& sideEffects) + const; + #define DECLARE_TARGET_POLICY(POLICY) \ cmPolicies::PolicyStatus GetPolicyStatus##POLICY() const \ { \ @@ -148,6 +155,16 @@ public: bool HasExplicitObjectName(cmSourceFile const* file) const; void AddExplicitObjectName(cmSourceFile const* sf); + BTs<std::string> const* GetLanguageStandardProperty( + std::string const& lang, std::string const& config) const; + + cmProp GetLanguageStandard(std::string const& lang, + std::string const& config) const; + + cmProp GetLanguageExtensions(std::string const& lang) const; + + bool GetLanguageStandardRequired(std::string const& lang) const; + void GetModuleDefinitionSources(std::vector<cmSourceFile const*>&, const std::string& config) const; void GetExternalObjects(std::vector<cmSourceFile const*>&, @@ -165,8 +182,8 @@ public: void ComputeObjectMapping(); - const char* GetFeature(const std::string& feature, - const std::string& config) const; + cmProp GetFeature(const std::string& feature, + const std::string& config) const; const char* GetLinkPIEProperty(const std::string& config) const; @@ -266,6 +283,9 @@ public: or CFBundle on Apple. */ bool IsBundleOnApple() const; + /** Return whether this target is a Win32 executable */ + bool IsWin32Executable(const std::string& config) const; + /** Get the full name of the target according to the settings in its makefile. */ std::string GetFullName(const std::string& config, @@ -428,6 +448,8 @@ public: void AddCUDAArchitectureFlags(std::string& flags) const; void AddCUDAToolkitFlags(std::string& flags) const; + void AddISPCTargetFlags(std::string& flags) const; + std::string GetFeatureSpecificLinkRuleVariable( std::string const& var, std::string const& lang, std::string const& config) const; @@ -515,6 +537,11 @@ public: bool ComputeCompileFeatures(std::string const& config) const; + using LanguagePair = std::pair<std::string, std::string>; + bool ComputeCompileFeatures( + std::string const& config, + std::set<LanguagePair> const& languagePairs) const; + /** * Trace through the source files in this target and add al source files * that they depend on, used by all generators @@ -790,6 +817,16 @@ public: const std::string& GetSourcesProperty() const; + void AddISPCGeneratedHeader(std::string const& header, + std::string const& config); + std::vector<std::string> GetGeneratedISPCHeaders( + std::string const& config) const; + + void AddISPCGeneratedObject(std::vector<std::string>&& objs, + std::string const& config); + std::vector<std::string> GetGeneratedISPCObjects( + std::string const& config) const; + private: void AddSourceCommon(const std::string& src, bool before = false); @@ -968,6 +1005,11 @@ private: std::unordered_set<std::string> UnityBatchedSourceFiles; + std::unordered_map<std::string, std::vector<std::string>> + ISPCGeneratedHeaders; + std::unordered_map<std::string, std::vector<std::string>> + ISPCGeneratedObjects; + bool IsLinkLookupScope(std::string const& n, cmLocalGenerator const*& lg) const; @@ -1038,6 +1080,11 @@ private: bool GetRPATH(const std::string& config, const std::string& prop, std::string& rpath) const; + mutable std::map<std::string, BTs<std::string>> LanguageStandardMap; + + cmProp GetPropertyWithPairedLanguageSupport(std::string const& lang, + const char* suffix) const; + public: const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure( const std::string& config) const; @@ -1054,5 +1101,3 @@ public: cmGeneratorTarget const* t2) const; }; }; - -#endif diff --git a/Source/cmGetCMakePropertyCommand.h b/Source/cmGetCMakePropertyCommand.h index 7a6728c..3a2e702 100644 --- a/Source/cmGetCMakePropertyCommand.h +++ b/Source/cmGetCMakePropertyCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGetCMakePropertyCommand_h -#define cmGetCMakePropertyCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmGetCMakePropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index fa4a40b..c2098c0 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -86,9 +86,7 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args, break; } } - if (cmProp p = dir->GetProperty(*i)) { - prop = p->c_str(); - } + prop = cmToCStr(dir->GetProperty(*i)); } StoreResult(status.GetMakefile(), variable, prop); return true; diff --git a/Source/cmGetDirectoryPropertyCommand.h b/Source/cmGetDirectoryPropertyCommand.h index f356ea5..4b0883c 100644 --- a/Source/cmGetDirectoryPropertyCommand.h +++ b/Source/cmGetDirectoryPropertyCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGetDirectoryPropertyCommand_h -#define cmGetDirectoryPropertyCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index 811421a..40e8a05 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -4,6 +4,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -14,14 +15,15 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args, { if (args.size() < 3) { status.SetError("called with incorrect number of arguments"); + cmSystemTools::SetFatalErrorOccured(); return false; } // Check and see if the value has been stored in the cache // already, if so use that value if (args.size() >= 4 && args.back() == "CACHE") { - const char* cacheValue = status.GetMakefile().GetDefinition(args.front()); - if (cacheValue && !cmIsNOTFOUND(cacheValue)) { + cmProp cacheValue = status.GetMakefile().GetDefinition(args.front()); + if (cacheValue && !cmIsNOTFOUND(*cacheValue)) { return true; } } @@ -114,6 +116,7 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args, } else { std::string err = "unknown component " + args[2]; status.SetError(err); + cmSystemTools::SetFatalErrorOccured(); return false; } diff --git a/Source/cmGetFilenameComponentCommand.h b/Source/cmGetFilenameComponentCommand.h index db5293b..4e1addf 100644 --- a/Source/cmGetFilenameComponentCommand.h +++ b/Source/cmGetFilenameComponentCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGetFilenameComponentCommand_h -#define cmGetFilenameComponentCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -18,5 +17,3 @@ class cmExecutionStatus; */ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmGetPipes.h b/Source/cmGetPipes.h index 2a46b51..6b1b495 100644 --- a/Source/cmGetPipes.h +++ b/Source/cmGetPipes.h @@ -1,8 +1,5 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGetPipes_h -#define cmGetPipes_h +#pragma once int cmGetPipes(int* fds); - -#endif diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index cba7704..3a5b39d 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -17,7 +17,6 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmTargetPropertyComputer.h" #include "cmTest.h" #include "cmake.h" @@ -282,8 +281,7 @@ bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name, // Get the property. cmake* cm = status.GetMakefile().GetCMakeInstance(); cmProp p = cm->GetState()->GetGlobalProperty(propertyName); - return StoreResult(infoType, status.GetMakefile(), variable, - p ? p->c_str() : nullptr); + return StoreResult(infoType, status.GetMakefile(), variable, cmToCStr(p)); } bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name, @@ -330,8 +328,7 @@ bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name, // Get the property. cmProp p = mf->GetProperty(propertyName); - return StoreResult(infoType, status.GetMakefile(), variable, - p ? p->c_str() : nullptr); + return StoreResult(infoType, status.GetMakefile(), variable, cmToCStr(p)); } bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, @@ -364,12 +361,9 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, cmProp prop_cstr = nullptr; cmListFileBacktrace bt = status.GetMakefile().GetBacktrace(); cmMessenger* messenger = status.GetMakefile().GetMessenger(); - if (cmTargetPropertyComputer::PassesWhitelist( - target->GetType(), propertyName, messenger, bt)) { - prop_cstr = target->GetComputedProperty(propertyName, messenger, bt); - if (!prop_cstr) { - prop_cstr = target->GetProperty(propertyName); - } + prop_cstr = target->GetComputedProperty(propertyName, messenger, bt); + if (!prop_cstr) { + prop_cstr = target->GetProperty(propertyName); } return StoreResult(infoType, status.GetMakefile(), variable, prop_cstr ? prop_cstr->c_str() : nullptr); @@ -434,8 +428,9 @@ bool HandleVariableMode(cmExecutionStatus& status, const std::string& name, return false; } - return StoreResult(infoType, status.GetMakefile(), variable, - status.GetMakefile().GetDefinition(propertyName)); + return StoreResult( + infoType, status.GetMakefile(), variable, + cmToCStr(status.GetMakefile().GetDefinition(propertyName))); } bool HandleCacheMode(cmExecutionStatus& status, const std::string& name, @@ -452,8 +447,7 @@ bool HandleCacheMode(cmExecutionStatus& status, const std::string& name, value = status.GetMakefile().GetState()->GetCacheEntryProperty( name, propertyName); } - StoreResult(infoType, status.GetMakefile(), variable, - value ? value->c_str() : nullptr); + StoreResult(infoType, status.GetMakefile(), variable, cmToCStr(value)); return true; } diff --git a/Source/cmGetPropertyCommand.h b/Source/cmGetPropertyCommand.h index cc600f4..fac3202 100644 --- a/Source/cmGetPropertyCommand.h +++ b/Source/cmGetPropertyCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGetPropertyCommand_h -#define cmGetPropertyCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmGetPropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmGetSourceFilePropertyCommand.h b/Source/cmGetSourceFilePropertyCommand.h index f0c319b..4f8eab2 100644 --- a/Source/cmGetSourceFilePropertyCommand.h +++ b/Source/cmGetSourceFilePropertyCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGetSourceFilePropertyCommand_h -#define cmGetSourceFilePropertyCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index 8a304be..78a17d2 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -12,7 +12,6 @@ #include "cmPolicies.h" #include "cmProperty.h" #include "cmTarget.h" -#include "cmTargetPropertyComputer.h" class cmMessenger; @@ -46,12 +45,9 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args, cmProp prop_cstr = nullptr; cmListFileBacktrace bt = mf.GetBacktrace(); cmMessenger* messenger = mf.GetMessenger(); - if (cmTargetPropertyComputer::PassesWhitelist(tgt->GetType(), args[2], - messenger, bt)) { - prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt); - if (!prop_cstr) { - prop_cstr = tgt->GetProperty(args[2]); - } + prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt); + if (!prop_cstr) { + prop_cstr = tgt->GetProperty(args[2]); } if (prop_cstr) { prop = *prop_cstr; diff --git a/Source/cmGetTargetPropertyCommand.h b/Source/cmGetTargetPropertyCommand.h index c13078f..0fbd23d 100644 --- a/Source/cmGetTargetPropertyCommand.h +++ b/Source/cmGetTargetPropertyCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGetTargetPropertyCommand_h -#define cmGetTargetPropertyCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmGetTargetPropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmGetTestPropertyCommand.h b/Source/cmGetTestPropertyCommand.h index 30beb8f..f1d6010 100644 --- a/Source/cmGetTestPropertyCommand.h +++ b/Source/cmGetTestPropertyCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGetTestPropertyCommand_h -#define cmGetTestPropertyCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmGetTestPropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h index fbbef5d..1cae660 100644 --- a/Source/cmGhsMultiGpj.h +++ b/Source/cmGhsMultiGpj.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGhsMultiGpj_h -#define cmGhsMultiGpj_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -25,5 +24,3 @@ public: static const char* GetGpjTag(Types gpjType); }; - -#endif // ! cmGhsMultiGpjType_h diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 97580d6..a8f8f57 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -43,9 +43,9 @@ cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target) #endif { // Store the configuration name that is being used - if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { + if (cmProp config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { // Use the build type given by the user. - this->ConfigName = config; + this->ConfigName = *config; } else { // No configuration type given. this->ConfigName.clear(); @@ -550,10 +550,9 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) */ for (auto& sg : groupFilesList) { std::ostream* fout; - cmProp noSourceGroupFile = - this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE"); - bool useProjectFile = (noSourceGroupFile && cmIsOn(*noSourceGroupFile)) || - cmIsOn(this->Makefile->GetDefinition("CMAKE_GHS_NO_SOURCE_GROUP_FILE")); + bool useProjectFile = + cmIsOn(this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE")) || + this->Makefile->IsOn("CMAKE_GHS_NO_SOURCE_GROUP_FILE"); if (useProjectFile || sg.empty()) { fout = &fout_proj; } else { diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h index f03ca44..e9d7537 100644 --- a/Source/cmGhsMultiTargetGenerator.h +++ b/Source/cmGhsMultiTargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGhsMultiTargetGenerator_h -#define cmGhsMultiTargetGenerator_h +#pragma once #include <iosfwd> #include <map> @@ -43,7 +42,7 @@ private: void SetCompilerFlags(std::string const& config, const std::string& language); - std::string GetDefines(const std::string& langugae, + std::string GetDefines(const std::string& language, std::string const& config); void WriteIncludes(std::ostream& fout, const std::string& config, @@ -82,5 +81,3 @@ private: std::string ConfigName; /* CMAKE_BUILD_TYPE */ bool const CmdWindowsShell; /* custom commands run in cmd.exe or /bin/sh */ }; - -#endif // ! cmGhsMultiTargetGenerator_h diff --git a/Source/cmGlobVerificationManager.h b/Source/cmGlobVerificationManager.h index 2e7e1ca..b618fb0 100644 --- a/Source/cmGlobVerificationManager.h +++ b/Source/cmGlobVerificationManager.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobVerificationManager_h -#define cmGlobVerificationManager_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -81,5 +80,3 @@ private: // cmGlobVerificationManager should never be used directly. friend class cmState; // allow access to add cache values }; - -#endif diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h index 3c97955..5a4e8c2 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.h +++ b/Source/cmGlobalBorlandMakefileGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalBorlandMakefileGenerator_h -#define cmGlobalBorlandMakefileGenerator_h +#pragma once #include <iosfwd> #include <memory> @@ -58,5 +57,3 @@ protected: void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override; }; - -#endif diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index 9dc86f4..9e5bbca 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -5,8 +5,12 @@ #include <memory> #include <utility> +#include <cmext/algorithm> + +#include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" +#include "cmMakefile.h" #include "cmProperty.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" @@ -31,26 +35,30 @@ cmGlobalCommonGenerator::ComputeDirectoryTargets() const lg->GetStateSnapshot().GetDirectory().GetCurrentBinary()); DirectoryTarget& dirTarget = dirTargets[currentBinaryDir]; dirTarget.LG = lg.get(); + const std::vector<std::string>& configs = + lg->GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); // The directory-level rule should depend on the target-level rules // for all targets in the directory. for (const auto& gt : lg->GetGeneratorTargets()) { cmStateEnums::TargetType const type = gt->GetType(); - if (type != cmStateEnums::EXECUTABLE && - type != cmStateEnums::STATIC_LIBRARY && - type != cmStateEnums::SHARED_LIBRARY && - type != cmStateEnums::MODULE_LIBRARY && - type != cmStateEnums::OBJECT_LIBRARY && - type != cmStateEnums::UTILITY) { + if (type == cmStateEnums::GLOBAL_TARGET || !gt->IsInBuildSystem()) { continue; } DirectoryTarget::Target t; t.GT = gt.get(); - if (cmProp exclude = gt->GetProperty("EXCLUDE_FROM_ALL")) { - if (cmIsOn(*exclude)) { - // This target has been explicitly excluded. - t.ExcludeFromAll = true; - } else { + const std::string EXCLUDE_FROM_ALL("EXCLUDE_FROM_ALL"); + if (cmProp exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) { + for (const std::string& config : configs) { + cmGeneratorExpressionInterpreter genexInterpreter(lg.get(), config, + gt.get()); + if (cmIsOn(genexInterpreter.Evaluate(*exclude, EXCLUDE_FROM_ALL))) { + // This target has been explicitly excluded. + t.ExcludedFromAllInConfigs.push_back(config); + } + } + + if (t.ExcludedFromAllInConfigs.empty()) { // This target has been explicitly un-excluded. The directory-level // rule for every directory between this and the root should depend // on the target-level rule for this target. @@ -78,3 +86,12 @@ cmGlobalCommonGenerator::ComputeDirectoryTargets() const return dirTargets; } + +bool cmGlobalCommonGenerator::IsExcludedFromAllInConfig( + const DirectoryTarget::Target& t, const std::string& config) +{ + if (this->IsMultiConfig()) { + return cm::contains(t.ExcludedFromAllInConfigs, config); + } + return !t.ExcludedFromAllInConfigs.empty(); +} diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h index 7d16dac..2aa9d27 100644 --- a/Source/cmGlobalCommonGenerator.h +++ b/Source/cmGlobalCommonGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalCommonGenerator_h -#define cmGlobalCommonGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -30,7 +29,7 @@ public: struct Target { cmGeneratorTarget const* GT = nullptr; - bool ExcludeFromAll = false; + std::vector<std::string> ExcludedFromAllInConfigs; }; std::vector<Target> Targets; struct Dir @@ -41,6 +40,6 @@ public: std::vector<Dir> Children; }; std::map<std::string, DirectoryTarget> ComputeDirectoryTargets() const; + bool IsExcludedFromAllInConfig(const DirectoryTarget::Target& t, + const std::string& config); }; - -#endif diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 4dc4092..8688b1b 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -235,6 +235,14 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, } cmProp cname = this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp); + + // Split compiler from arguments + std::vector<std::string> cnameArgVec; + if (cname && !cname->empty()) { + cmExpandList(*cname, cnameArgVec); + cname = &cnameArgVec.front(); + } + std::string changeVars; if (cname && !optional) { std::string cnameString; @@ -302,31 +310,12 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const bool failed = false; for (const auto& localGen : this->LocalGenerators) { for (const auto& target : localGen->GetGeneratorTargets()) { - if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET || - target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY || - target->GetType() == cmStateEnums::TargetType::UTILITY) { + if (!target->CanCompileSources() || + cmIsOn(target->GetProperty("ghs_integrity_app"))) { continue; } - if (cmProp p = target->GetProperty("ghs_integrity_app")) { - if (cmIsOn(*p)) { - continue; - } - } - std::vector<std::string> configs; - target->Makefile->GetConfigurations(configs); - std::vector<cmSourceFile*> srcs; - if (configs.empty()) { - target->GetSourceFiles(srcs, ""); - } else { - for (std::string const& config : configs) { - target->GetSourceFiles(srcs, config); - if (!srcs.empty()) { - break; - } - } - } - if (srcs.empty()) { + if (target->GetAllConfigSources().empty()) { std::ostringstream e; e << "No SOURCES given to target: " << target->GetName(); this->GetCMakeInstance()->IssueMessage( @@ -346,12 +335,13 @@ bool cmGlobalGenerator::CheckTargetsForType() const bool failed = false; for (const auto& generator : this->LocalGenerators) { for (const auto& target : generator->GetGeneratorTargets()) { - if (target->GetType() == cmStateEnums::EXECUTABLE && - target->GetPropertyAsBool("WIN32_EXECUTABLE")) { + if (target->GetType() == cmStateEnums::EXECUTABLE) { std::vector<std::string> const& configs = - target->Makefile->GetGeneratorConfigs(); + target->Makefile->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig); for (std::string const& config : configs) { - if (target->GetLinkerLanguage(config) == "Swift") { + if (target->IsWin32Executable(config) && + target->GetLinkerLanguage(config) == "Swift") { this->GetCMakeInstance()->IssueMessage( MessageType::FATAL_ERROR, "WIN32_EXECUTABLE property is not supported on Swift " @@ -374,16 +364,10 @@ bool cmGlobalGenerator::CheckTargetsForPchCompilePdb() const bool failed = false; for (const auto& generator : this->LocalGenerators) { for (const auto& target : generator->GetGeneratorTargets()) { - if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET || - target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY || - target->GetType() == cmStateEnums::TargetType::UTILITY) { + if (!target->CanCompileSources() || + cmIsOn(target->GetProperty("ghs_integrity_app"))) { continue; } - if (cmProp p = target->GetProperty("ghs_integrity_app")) { - if (cmIsOn(*p)) { - continue; - } - } std::string const& reuseFrom = target->GetSafeProperty("PRECOMPILE_HEADERS_REUSE_FROM"); @@ -425,15 +409,13 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) "all generators must specify this->FindMakeProgramFile"); return false; } - if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") || - cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { + if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { std::string setMakeProgram = mf->GetModulesFile(this->FindMakeProgramFile); if (!setMakeProgram.empty()) { mf->ReadListFile(setMakeProgram); } } - if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") || - cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { + if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { std::ostringstream err; err << "CMake was unable to find a build program corresponding to \"" << this->GetName() << "\". CMAKE_MAKE_PROGRAM is not set. You " @@ -596,6 +578,16 @@ void cmGlobalGenerator::EnableLanguage( mf->ReadListFile(fpath); } } + + if (readCMakeSystem) { + // Find the native build tool for this generator. + // This has to be done early so that MSBuild can be used to examine the + // cross-compilation environment. + if (!this->FindMakeProgram(mf)) { + return; + } + } + // Load the CMakeDetermineSystem.cmake file and find out // what platform we are running on if (!mf->GetDefinition("CMAKE_SYSTEM")) { @@ -667,11 +659,6 @@ void cmGlobalGenerator::EnableLanguage( cmSystemTools::SetFatalErrorOccured(); return; } - - // Find the native build tool for this generator. - if (!this->FindMakeProgram(mf)) { - return; - } } // Check that the languages are supported by the generator and its @@ -793,27 +780,27 @@ void cmGlobalGenerator::EnableLanguage( std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER"); std::string compilerEnv = cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR"); std::ostringstream noCompiler; - const char* compilerFile = mf->GetDefinition(compilerName); - if (!compilerFile || !*compilerFile || cmIsNOTFOUND(compilerFile)) { + cmProp compilerFile = mf->GetDefinition(compilerName); + if (!cmNonempty(compilerFile) || cmIsNOTFOUND(*compilerFile)) { /* clang-format off */ noCompiler << "No " << compilerName << " could be found.\n" ; /* clang-format on */ } else if ((lang != "RC") && (lang != "ASM_MASM")) { - if (!cmSystemTools::FileIsFullPath(compilerFile)) { + if (!cmSystemTools::FileIsFullPath(*compilerFile)) { /* clang-format off */ noCompiler << "The " << compilerName << ":\n" - " " << compilerFile << "\n" + " " << *compilerFile << "\n" "is not a full path and was not found in the PATH.\n" ; /* clang-format on */ - } else if (!cmSystemTools::FileExists(compilerFile)) { + } else if (!cmSystemTools::FileExists(*compilerFile)) { /* clang-format off */ noCompiler << "The " << compilerName << ":\n" - " " << compilerFile << "\n" + " " << *compilerFile << "\n" "is not a full path to an existing compiler tool.\n" ; /* clang-format on */ @@ -830,7 +817,7 @@ void cmGlobalGenerator::EnableLanguage( cmSystemTools::RemoveFile(compilerLangFile); if (!this->CMakeInstance->GetIsInTryCompile()) { this->PrintCompilerAdvice(noCompiler, lang, - mf->GetDefinition(compilerEnv)); + cmToCStr(mf->GetDefinition(compilerEnv))); mf->IssueMessage(MessageType::FATAL_ERROR, noCompiler.str()); fatalError = true; } @@ -1108,17 +1095,16 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l, return; } - std::string linkerPrefVar = - std::string("CMAKE_") + std::string(l) + std::string("_LINKER_PREFERENCE"); - const char* linkerPref = mf->GetDefinition(linkerPrefVar); + std::string linkerPrefVar = "CMAKE_" + l + "_LINKER_PREFERENCE"; + cmProp linkerPref = mf->GetDefinition(linkerPrefVar); int preference = 0; - if (linkerPref) { - if (sscanf(linkerPref, "%d", &preference) != 1) { + if (cmNonempty(linkerPref)) { + if (sscanf(linkerPref->c_str(), "%d", &preference) != 1) { // backward compatibility: before 2.6 LINKER_PREFERENCE // was either "None" or "Preferred", and only the first character was // tested. So if there is a custom language out there and it is // "Preferred", set its preference high - if (linkerPref[0] == 'P') { + if ((*linkerPref)[0] == 'P') { preference = 100; } else { preference = 0; @@ -1135,14 +1121,14 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l, this->LanguageToLinkerPreference[l] = preference; - std::string outputExtensionVar = - std::string("CMAKE_") + std::string(l) + std::string("_OUTPUT_EXTENSION"); - const char* outputExtension = mf->GetDefinition(outputExtensionVar); - if (outputExtension) { + std::string outputExtensionVar = "CMAKE_" + l + "_OUTPUT_EXTENSION"; + if (cmProp p = mf->GetDefinition(outputExtensionVar)) { + std::string outputExtension = *p; this->LanguageToOutputExtension[l] = outputExtension; this->OutputExtensions[outputExtension] = outputExtension; - if (outputExtension[0] == '.') { - this->OutputExtensions[outputExtension + 1] = outputExtension + 1; + if (cmHasPrefix(outputExtension, ".")) { + outputExtension = outputExtension.substr(1); + this->OutputExtensions[outputExtension] = outputExtension; } } @@ -1175,7 +1161,7 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l, const char* cmGlobalGenerator::GetGlobalSetting(std::string const& name) const { assert(!this->Makefiles.empty()); - return this->Makefiles[0]->GetDefinition(name); + return cmToCStr(this->Makefiles[0]->GetDefinition(name)); } bool cmGlobalGenerator::GlobalSettingIsOn(std::string const& name) const @@ -1442,12 +1428,10 @@ bool cmGlobalGenerator::Compute() localGen->AddHelperCommands(); } - // Finalize the set of compile features for each target. - // FIXME: This turns into calls to cmMakefile::AddRequiredTargetFeature - // which actually modifies the <lang>_STANDARD target property - // on the original cmTarget instance. It accumulates features - // across all configurations. Some refactoring is needed to - // compute a per-config resulta purely during generation. + // Perform up-front computation in order to handle errors (such as unknown + // features) at this point. While processing the compile features we also + // calculate and cache the language standard required by the compile + // features. for (const auto& localGen : this->LocalGenerators) { if (!localGen->ComputeTargetCompileFeatures()) { return false; @@ -1487,6 +1471,7 @@ bool cmGlobalGenerator::Compute() if (!this->ComputeTargetDepends()) { return false; } + this->ComputeTargetOrder(); if (this->CheckTargetsForType()) { return false; @@ -1597,6 +1582,50 @@ bool cmGlobalGenerator::ComputeTargetDepends() return true; } +std::vector<cmGeneratorTarget*> +cmGlobalGenerator::GetLocalGeneratorTargetsInOrder(cmLocalGenerator* lg) const +{ + std::vector<cmGeneratorTarget*> gts; + cm::append(gts, lg->GetGeneratorTargets()); + std::sort(gts.begin(), gts.end(), + [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) { + return this->TargetOrderIndex.at(l) < + this->TargetOrderIndex.at(r); + }); + return gts; +} + +void cmGlobalGenerator::ComputeTargetOrder() +{ + size_t index = 0; + auto const& lgens = this->GetLocalGenerators(); + for (auto const& lgen : lgens) { + const auto& targets = lgen->GetGeneratorTargets(); + for (const auto& gt : targets) { + this->ComputeTargetOrder(gt.get(), index); + } + } + assert(index == this->TargetOrderIndex.size()); +} + +void cmGlobalGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt, + size_t& index) +{ + std::map<cmGeneratorTarget const*, size_t>::value_type value(gt, 0); + auto insertion = this->TargetOrderIndex.insert(value); + if (!insertion.second) { + return; + } + auto entry = insertion.first; + + auto& deps = this->GetTargetDirectDepends(gt); + for (auto& d : deps) { + this->ComputeTargetOrder(d, index); + } + + entry->second = index++; +} + bool cmGlobalGenerator::QtAutoGen() { #ifndef CMAKE_BOOTSTRAP @@ -1612,12 +1641,11 @@ bool cmGlobalGenerator::AddAutomaticSources() for (const auto& lg : this->LocalGenerators) { lg->CreateEvaluationFileOutputs(); for (const auto& gt : lg->GetGeneratorTargets()) { - if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY || - gt->GetType() == cmStateEnums::UTILITY || - gt->GetType() == cmStateEnums::GLOBAL_TARGET) { + if (!gt->CanCompileSources()) { continue; } lg->AddUnityBuild(gt.get()); + lg->AddISPCDependencies(gt.get()); // Targets that re-use a PCH are handled below. if (!gt->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) { lg->AddPchDependencies(gt.get()); @@ -1626,9 +1654,7 @@ bool cmGlobalGenerator::AddAutomaticSources() } for (const auto& lg : this->LocalGenerators) { for (const auto& gt : lg->GetGeneratorTargets()) { - if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY || - gt->GetType() == cmStateEnums::UTILITY || - gt->GetType() == cmStateEnums::GLOBAL_TARGET) { + if (!gt->CanCompileSources()) { continue; } // Handle targets that re-use a PCH from an above-handled target. @@ -1698,8 +1724,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() cmPolicies::PolicyStatus polSt = mf->GetPolicyStatus(cmPolicies::CMP0043); if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) { - std::vector<std::string> configs; - mf->GetConfigurations(configs); + std::vector<std::string> configs = + mf->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); for (std::string const& c : configs) { std::string defPropName = @@ -1779,6 +1805,7 @@ void cmGlobalGenerator::ClearGeneratorMembers() this->GeneratorTargetSearchIndex.clear(); this->MakefileSearchIndex.clear(); this->LocalGeneratorSearchIndex.clear(); + this->TargetOrderIndex.clear(); this->ProjectMap.clear(); this->RuleHashes.clear(); this->DirectoryContentMap.clear(); @@ -1988,8 +2015,9 @@ int cmGlobalGenerator::Build( std::string makeCommandStr; output += "\nRun Build Command(s):"; - for (auto command = makeCommand.begin(); command != makeCommand.end(); - ++command) { + retVal = 0; + for (auto command = makeCommand.begin(); + command != makeCommand.end() && retVal == 0; ++command) { makeCommandStr = command->Printable(); if (command != makeCommand.end()) { makeCommandStr += " && "; @@ -2179,13 +2207,38 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root, } bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root, - cmGeneratorTarget* target) const + const cmGeneratorTarget* target) const { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!target->IsInBuildSystem()) { return true; } - if (cmProp exclude = target->GetProperty("EXCLUDE_FROM_ALL")) { - return cmIsOn(*exclude); + cmMakefile* mf = root->GetMakefile(); + const std::string EXCLUDE_FROM_ALL = "EXCLUDE_FROM_ALL"; + if (cmProp exclude = target->GetProperty(EXCLUDE_FROM_ALL)) { + // Expand the property value per configuration. + unsigned int trueCount = 0; + unsigned int falseCount = 0; + const std::vector<std::string>& configs = + mf->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + for (const std::string& config : configs) { + cmGeneratorExpressionInterpreter genexInterpreter(root, config, target); + if (cmIsOn(genexInterpreter.Evaluate(*exclude, EXCLUDE_FROM_ALL))) { + ++trueCount; + } else { + ++falseCount; + } + } + + // Check whether the genex expansion of the property agrees in all + // configurations. + if (trueCount && falseCount) { + std::ostringstream e; + e << "The EXCLUDE_FROM_ALL property of target \"" << target->GetName() + << "\" varies by configuration. This is not supported by the \"" + << root->GetGlobalGenerator()->GetName() << "\" generator."; + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + } + return trueCount; } // This target is included in its directory. Check whether the // directory is excluded. @@ -2445,7 +2498,7 @@ void cmGlobalGenerator::AddGlobalTarget_Package( gti.WorkingDir = mf->GetCurrentBinaryDirectory(); cmCustomCommandLine singleLine; singleLine.push_back(cmSystemTools::GetCPackCommand()); - if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { + if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') { singleLine.push_back("-C"); singleLine.push_back(cmakeCfgIntDir); } @@ -2455,9 +2508,9 @@ void cmGlobalGenerator::AddGlobalTarget_Package( if (this->GetPreinstallTargetName()) { gti.Depends.emplace_back(this->GetPreinstallTargetName()); } else { - const char* noPackageAll = + cmProp noPackageAll = mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY"); - if (!noPackageAll || cmIsOff(noPackageAll)) { + if (cmIsOff(noPackageAll)) { gti.Depends.emplace_back(this->GetAllTargetName()); } } @@ -2530,7 +2583,7 @@ void cmGlobalGenerator::AddGlobalTarget_Test( singleLine.push_back(arg); } } - if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { + if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') { singleLine.push_back("-C"); singleLine.push_back(cmakeCfgIntDir); } else // TODO: This is a hack. Should be something to do with the @@ -2611,7 +2664,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( "installation rules have been specified", mf->GetBacktrace()); } else if (this->InstallTargetEnabled && !skipInstallRules) { - if (!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.') { + if (!(cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.')) { std::set<std::string>* componentsSet = &this->InstallComponents; std::ostringstream ostr; if (!componentsSet->empty()) { @@ -2636,9 +2689,8 @@ void cmGlobalGenerator::AddGlobalTarget_Install( if (this->GetPreinstallTargetName()) { gti.Depends.emplace_back(this->GetPreinstallTargetName()); } else { - const char* noall = - mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); - if (!noall || cmIsOff(noall)) { + cmProp noall = mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); + if (cmIsOff(noall)) { gti.Depends.emplace_back(this->GetAllTargetName()); } } @@ -2650,7 +2702,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( cmd = "cmake"; } singleLine.push_back(cmd); - if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { + if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') { std::string cfgArg = "-DBUILD_TYPE="; bool useEPN = this->UseEffectivePlatformName(mf.get()); if (useEPN) { @@ -2658,7 +2710,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( singleLine.push_back(cfgArg); cfgArg = "-DEFFECTIVE_PLATFORM_NAME=$(EFFECTIVE_PLATFORM_NAME)"; } else { - cfgArg += mf->GetDefinition("CMAKE_CFG_INTDIR"); + cfgArg += cmToCStr(mf->GetDefinition("CMAKE_CFG_INTDIR")); } singleLine.push_back(cfgArg); } @@ -3045,7 +3097,7 @@ void cmGlobalGenerator::WriteSummary() for (const auto& lg : this->LocalGenerators) { for (const auto& tgt : lg->GetGeneratorTargets()) { - if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!tgt->IsInBuildSystem()) { continue; } this->WriteSummary(tgt.get()); @@ -3066,7 +3118,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) cmProp targetLabels = target->GetProperty("LABELS"); cmProp directoryLabels = target->Target->GetMakefile()->GetProperty("LABELS"); - const char* cmakeDirectoryLabels = + cmProp cmakeDirectoryLabels = target->Target->GetMakefile()->GetDefinition("CMAKE_DIRECTORY_LABELS"); if (targetLabels || directoryLabels || cmakeDirectoryLabels) { Json::Value lj_root(Json::objectValue); @@ -3102,7 +3154,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) } if (cmakeDirectoryLabels) { - cmExpandList(cmakeDirectoryLabels, cmakeDirectoryLabelsList); + cmExpandList(*cmakeDirectoryLabels, cmakeDirectoryLabelsList); } if (!directoryLabelsList.empty() || !cmakeDirectoryLabelsList.empty()) { @@ -3123,7 +3175,8 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) fout << "# Source files and their labels\n"; std::vector<cmSourceFile*> sources; std::vector<std::string> const& configs = - target->Target->GetMakefile()->GetGeneratorConfigs(); + target->Target->GetMakefile()->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig); for (std::string const& c : configs) { target->GetSourceFiles(sources, c); } @@ -3222,8 +3275,9 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile() const auto& lg = this->LocalGenerators[0]; cmMakefile* mf = lg->GetMakefile(); - std::vector<std::string> configs; - std::string config = mf->GetConfigurations(configs, false); + std::vector<std::string> configs = + mf->GetGeneratorConfigs(cmMakefile::OnlyMultiConfig); + std::string config = mf->GetDefaultConfiguration(); std::string path = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), "/CPackProperties.cmake"); diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 57c7808..478028e 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -1,10 +1,10 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalGenerator_h -#define cmGlobalGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <iosfwd> #include <map> #include <memory> @@ -265,6 +265,9 @@ public: return this->LocalGenerators; } + std::vector<cmGeneratorTarget*> GetLocalGeneratorTargetsInOrder( + cmLocalGenerator* lg) const; + cmMakefile* GetCurrentMakefile() const { return this->CurrentConfigureMakefile; @@ -542,7 +545,8 @@ protected: bool IsExcluded(cmStateSnapshot const& root, cmStateSnapshot const& snp) const; bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const; - bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) const; + bool IsExcluded(cmLocalGenerator* root, + const cmGeneratorTarget* target) const; virtual void InitializeProgressMarks() {} struct GlobalTargetInfo @@ -613,6 +617,10 @@ private: // Its order is not deterministic. LocalGeneratorMap LocalGeneratorSearchIndex; + void ComputeTargetOrder(); + void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index); + std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex; + cmMakefile* TryCompileOuterMakefile; // If you add a new map here, make sure it is copied // in EnableLanguagesFromGenerator @@ -716,5 +724,3 @@ protected: bool InstallTargetEnabled; bool ConfigureDoneCMP0026AndCMP0024; }; - -#endif diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h index 3709365..3a7f806 100644 --- a/Source/cmGlobalGeneratorFactory.h +++ b/Source/cmGlobalGeneratorFactory.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalGeneratorFactory_h -#define cmGlobalGeneratorFactory_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -44,7 +43,7 @@ public: /** Get the list of supported platforms name for this generator */ virtual std::vector<std::string> GetKnownPlatforms() const = 0; - /** If the generator suports platforms, get its default. */ + /** If the generator supports platforms, get its default. */ virtual std::string GetDefaultPlatformName() const = 0; }; @@ -95,5 +94,3 @@ public: std::string GetDefaultPlatformName() const override { return std::string(); } }; - -#endif diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index d36adfb..cbaf0ab 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -100,13 +100,13 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, /* set the build tool to use */ std::string gbuild(tsp + ((tsp.back() == '/') ? "" : "/") + DEFAULT_BUILD_PROGRAM); - const char* prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM"); + cmProp prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM"); /* check if the toolset changed from last generate */ - if (prevTool != nullptr && (gbuild != prevTool)) { + if (prevTool && (gbuild != *prevTool)) { std::string message = cmStrCat("toolset build tool: ", gbuild, - "\nDoes not match the previously used build tool: ", prevTool, + "\nDoes not match the previously used build tool: ", *prevTool, "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."); cmSystemTools::Error(message); @@ -187,7 +187,8 @@ void cmGlobalGhsMultiGenerator::EnableLanguage( mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files - const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM"); + const char* tgtPlatform = + cmToCStrSafe(mf->GetDefinition("GHS_TARGET_PLATFORM")); if (!tgtPlatform) { cmSystemTools::Message("Green Hills MULTI: GHS_TARGET_PLATFORM not " "specified; defaulting to \"integrity\""); @@ -216,12 +217,13 @@ bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* /*mf*/) void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd, const std::string& ts) { - const char* ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT"); + cmProp ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT"); - if (!ghsRoot || ghsRoot[0] == '\0') { - ghsRoot = DEFAULT_TOOLSET_ROOT; + if (cmNonempty(ghsRoot)) { + tsd = *ghsRoot; + } else { + tsd = DEFAULT_TOOLSET_ROOT; } - tsd = ghsRoot; if (ts.empty()) { std::vector<std::string> output; @@ -467,11 +469,10 @@ void cmGlobalGhsMultiGenerator::WriteAllTarget( this->ProjectTargets.push_back(t); } for (cmGeneratorTarget const* t : sortedProjectTargets) { - if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!t->IsInBuildSystem()) { continue; } - cmProp p = t->GetProperty("EXCLUDE_FROM_ALL"); - if (!(p && cmIsOn(*p))) { + if (!IsExcluded(t->GetLocalGenerator(), t)) { defaultTargets.push_back(t); } } @@ -635,7 +636,7 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives( std::string tgt; const char* t = this->GetCMakeInstance()->GetCacheDefinition("GHS_PRIMARY_TARGET"); - if (t && *t != '\0') { + if (cmNonempty(t)) { tgt = t; this->GetCMakeInstance()->MarkCliAsUsed("GHS_PRIMARY_TARGET"); } else { diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index 12ca8b6..7753b31 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGhsMultiGenerator_h -#define cmGhsMultiGenerator_h +#pragma once #include <iosfwd> #include <memory> @@ -158,5 +157,3 @@ public: using TargetDependSet = cmGlobalGenerator::TargetDependSet; OrderedTargetDependSet(TargetDependSet const&, std::string const& first); }; - -#endif diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index 9f1ec8b..2d58f91 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalJOMMakefileGenerator_h -#define cmGlobalJOMMakefileGenerator_h +#pragma once #include <iosfwd> #include <memory> @@ -53,5 +52,3 @@ private: void PrintCompilerAdvice(std::ostream& os, std::string const& lang, const char* envVar) const override; }; - -#endif diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h index b2de4ff..1a47b4f 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.h +++ b/Source/cmGlobalMSYSMakefileGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalMSYSMakefileGenerator_h -#define cmGlobalMSYSMakefileGenerator_h +#pragma once #include <memory> @@ -42,5 +41,3 @@ public: private: std::string FindMinGW(std::string const& makeloc); }; - -#endif diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h index a9f92a1..ffc9ebe 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.h +++ b/Source/cmGlobalMinGWMakefileGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalMinGWMakefileGenerator_h -#define cmGlobalMinGWMakefileGenerator_h +#pragma once #include <memory> @@ -38,5 +37,3 @@ public: virtual void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*, bool optional); }; - -#endif diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index fdf6006..abe64ff 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalNMakeMakefileGenerator_h -#define cmGlobalNMakeMakefileGenerator_h +#pragma once #include <iosfwd> #include <memory> @@ -59,5 +58,3 @@ private: void PrintCompilerAdvice(std::ostream& os, std::string const& lang, const char* envVar) const override; }; - -#endif diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index f11cd50..006925d 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -5,9 +5,9 @@ #include <algorithm> #include <cctype> #include <cstdio> -#include <iterator> #include <sstream> +#include <cm/iterator> #include <cm/memory> #include <cmext/algorithm> #include <cmext/memory> @@ -32,6 +32,7 @@ #include "cmMessageType.h" #include "cmNinjaLinkLineComputer.h" #include "cmOutputConverter.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -518,7 +519,8 @@ void cmGlobalNinjaGenerator::Generate() if (cmSystemTools::GetErrorOccuredFlag()) { this->RulesFileStream->setstate(std::ios::failbit); - for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig)) { this->GetImplFileStream(config)->setstate(std::ios::failbit); this->GetConfigFileStream(config)->setstate(std::ios::failbit); } @@ -613,8 +615,8 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) if (!this->cmGlobalGenerator::FindMakeProgram(mf)) { return false; } - if (const char* ninjaCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) { - this->NinjaCommand = ninjaCommand; + if (cmProp ninjaCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) { + this->NinjaCommand = *ninjaCommand; std::vector<std::string> command; command.push_back(this->NinjaCommand); command.emplace_back("--version"); @@ -679,6 +681,9 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() this->NinjaSupportsRestatTool = !cmSystemTools::VersionCompare( cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), RequiredNinjaVersionForRestatTool().c_str()); + this->NinjaSupportsMultipleOutputs = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForMultipleOutputs().c_str()); } bool cmGlobalNinjaGenerator::CheckLanguages( @@ -687,6 +692,9 @@ bool cmGlobalNinjaGenerator::CheckLanguages( if (cm::contains(languages, "Fortran")) { return this->CheckFortran(mf); } + if (cm::contains(languages, "ISPC")) { + return this->CheckISPC(mf); + } if (cm::contains(languages, "Swift")) { const std::string architectures = mf->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES"); @@ -720,6 +728,25 @@ bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const return false; } +bool cmGlobalNinjaGenerator::CheckISPC(cmMakefile* mf) const +{ + if (this->NinjaSupportsMultipleOutputs) { + return true; + } + + std::ostringstream e; + /* clang-format off */ + e << + "The Ninja generator does not support ISPC using Ninja version\n" + " " << this->NinjaVersion << "\n" + "due to lack of required features. Ninja 1.10 or higher is required." + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; +} + void cmGlobalNinjaGenerator::EnableLanguage( std::vector<std::string> const& langs, cmMakefile* mf, bool optional) { @@ -1092,6 +1119,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( } // FALLTHROUGH case cmStateEnums::GLOBAL_TARGET: + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::UTILITY: { std::string path = cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', @@ -1104,8 +1132,8 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( break; } - default: - return; + case cmStateEnums::UNKNOWN_LIBRARY: + break; } } @@ -1125,15 +1153,38 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( } } else { cmNinjaDeps outs; + + auto computeISPCOuputs = [](cmGlobalNinjaGenerator* gg, + cmGeneratorTarget const* depTarget, + cmNinjaDeps& outputDeps, + const std::string& targetConfig) { + if (depTarget->CanCompileSources()) { + auto headers = depTarget->GetGeneratedISPCHeaders(targetConfig); + if (!headers.empty()) { + std::transform(headers.begin(), headers.end(), headers.begin(), + gg->MapToNinjaPath()); + outputDeps.insert(outputDeps.end(), headers.begin(), headers.end()); + } + auto objs = depTarget->GetGeneratedISPCObjects(targetConfig); + if (!objs.empty()) { + std::transform(objs.begin(), objs.end(), objs.begin(), + gg->MapToNinjaPath()); + outputDeps.insert(outputDeps.end(), objs.begin(), objs.end()); + } + } + }; + for (cmTargetDepend const& targetDep : this->GetTargetDirectDepends(target)) { - if (targetDep->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!targetDep->IsInBuildSystem()) { continue; } if (targetDep.IsCross()) { this->AppendTargetOutputs(targetDep, outs, fileConfig, depends); + computeISPCOuputs(this, targetDep, outs, fileConfig); } else { this->AppendTargetOutputs(targetDep, outs, config, depends); + computeISPCOuputs(this, targetDep, outs, config); } } std::sort(outs.begin(), outs.end()); @@ -1169,7 +1220,7 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure( cmNinjaOuts this_outs; // this will be the new cache entry for (auto const& dep_target : this->GetTargetDirectDepends(target)) { - if (dep_target->GetType() == cmStateEnums::INTERFACE_LIBRARY || + if (!dep_target->IsInBuildSystem() || (target->GetType() != cmStateEnums::UTILITY && this->EnableCrossConfigBuild() && !dep_target.IsCross())) { continue; @@ -1189,7 +1240,7 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure( // finally generate the outputs of the target itself, if applicable cmNinjaDeps outs; if (!omit_self) { - this->AppendTargetOutputs(target, outs, config); + this->AppendTargetOutputs(target, outs, config, DependOnTargetArtifact); } outputs.insert(outs.begin(), outs.end()); } @@ -1201,14 +1252,15 @@ void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias, std::string outputPath = this->NinjaOutputPath(alias); std::string buildAlias = this->BuildAlias(outputPath, config); cmNinjaDeps outputs; - this->AppendTargetOutputs(target, outputs, config); + this->AppendTargetOutputs(target, outputs, config, DependOnTargetArtifact); // Mark the target's outputs as ambiguous to ensure that no other target // uses the output as an alias. for (std::string const& output : outputs) { this->TargetAliases[output].GeneratorTarget = nullptr; this->DefaultTargetAliases[output].GeneratorTarget = nullptr; for (const std::string& config2 : - this->Makefiles.front()->GetGeneratorConfigs()) { + this->Makefiles.front()->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig)) { this->Configs[config2].TargetAliases[output].GeneratorTarget = nullptr; } } @@ -1266,11 +1318,12 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) if (ta.second.Config == "all") { for (auto const& config : this->CrossConfigs) { this->AppendTargetOutputs(ta.second.GeneratorTarget, - build.ExplicitDeps, config); + build.ExplicitDeps, config, + DependOnTargetArtifact); } } else { this->AppendTargetOutputs(ta.second.GeneratorTarget, build.ExplicitDeps, - ta.second.Config); + ta.second.Config, DependOnTargetArtifact); } this->WriteBuild(this->EnableCrossConfigBuild() && (ta.second.Config == "all" || @@ -1281,7 +1334,8 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) } if (this->IsMultiConfig()) { - for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) { + for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig)) { for (auto const& ta : this->Configs[config].TargetAliases) { // Don't write ambiguous aliases. if (!ta.second.GeneratorTarget) { @@ -1297,7 +1351,8 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) build.Outputs.front() = ta.first; build.ExplicitDeps.clear(); this->AppendTargetOutputs(ta.second.GeneratorTarget, - build.ExplicitDeps, config); + build.ExplicitDeps, config, + DependOnTargetArtifact); this->WriteBuild(*this->GetConfigFileStream(config), build); } } @@ -1319,7 +1374,8 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) build.ExplicitDeps.clear(); for (auto const& config : this->DefaultConfigs) { this->AppendTargetOutputs(ta.second.GeneratorTarget, - build.ExplicitDeps, config); + build.ExplicitDeps, config, + DependOnTargetArtifact); } this->WriteBuild(*this->GetDefaultFileStream(), build); } @@ -1340,11 +1396,9 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); std::string const& currentBinaryDir = it.first; DirectoryTarget const& dt = it.second; - std::vector<std::string> configs; - dt.LG->GetMakefile()->GetConfigurations(configs, true); - if (configs.empty()) { - configs.emplace_back(); - } + std::vector<std::string> configs = + dt.LG->GetMakefile()->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig); // Setup target cmNinjaDeps configDeps; @@ -1357,8 +1411,9 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) build.Outputs.front() = this->BuildAlias(buildDirAllTarget, config); configDeps.emplace_back(build.Outputs.front()); for (DirectoryTarget::Target const& t : dt.Targets) { - if (!t.ExcludeFromAll) { - this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config); + if (!IsExcludedFromAllInConfig(t, config)) { + this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config, + DependOnTargetArtifact); } } for (DirectoryTarget::Dir const& d : dt.Children) { @@ -1539,7 +1594,8 @@ void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os) this->WriteTargetClean(os); this->WriteTargetHelp(os); - for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig)) { this->WriteTargetDefault(*this->GetConfigFileStream(config)); } @@ -1713,11 +1769,8 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake"; std::string cleanScriptAbs = cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel); - std::vector<std::string> configs; - this->Makefiles[0]->GetConfigurations(configs, true); - if (configs.empty()) { - configs.emplace_back(); - } + std::vector<std::string> configs = + this->Makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); // Check if there are additional files to clean bool empty = true; @@ -1811,7 +1864,8 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) WriteRule(*this->RulesFileStream, rule); } - auto const configs = this->Makefiles.front()->GetGeneratorConfigs(); + auto const configs = this->Makefiles.front()->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig); // Write build { @@ -2491,7 +2545,8 @@ bool cmGlobalNinjaMultiGenerator::OpenBuildFileStreams() << "# This file contains build statements common to all " "configurations.\n\n"; - for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig)) { // Open impl file. if (!this->OpenFileStream(this->ImplFileStreams[config], GetNinjaImplFilename(config))) { @@ -2531,7 +2586,8 @@ void cmGlobalNinjaMultiGenerator::CloseBuildFileStreams() this->DefaultFileStream.reset(); } // No error if it wasn't open - for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig)) { if (this->ImplFileStreams[config]) { this->ImplFileStreams[config].reset(); } else { @@ -2573,7 +2629,8 @@ std::string cmGlobalNinjaMultiGenerator::GetNinjaConfigFilename( void cmGlobalNinjaMultiGenerator::AddRebuildManifestOutputs( cmNinjaDeps& outputs) const { - for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) { + for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig)) { outputs.push_back(this->NinjaOutputPath(GetNinjaImplFilename(config))); outputs.push_back(this->NinjaOutputPath(GetNinjaConfigFilename(config))); } @@ -2585,11 +2642,9 @@ void cmGlobalNinjaMultiGenerator::AddRebuildManifestOutputs( void cmGlobalNinjaMultiGenerator::GetQtAutoGenConfigs( std::vector<std::string>& configs) const { - auto const oldSize = configs.size(); - this->Makefiles.front()->GetConfigurations(configs); - if (configs.size() == oldSize) { - configs.emplace_back(); - } + auto allConfigs = + this->Makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + configs.insert(configs.end(), cm::cbegin(allConfigs), cm::cend(allConfigs)); } bool cmGlobalNinjaMultiGenerator::InspectConfigTypeVariables() diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 44e632f..884a711 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalNinjaGenerator_h -#define cmGlobalNinjaGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -318,14 +317,13 @@ public: virtual std::string OrderDependsTargetForTarget( cmGeneratorTarget const* target, const std::string& config) const; - void AppendTargetOutputs( - cmGeneratorTarget const* target, cmNinjaDeps& outputs, - const std::string& config, - cmNinjaTargetDepends depends = DependOnTargetArtifact); - void AppendTargetDepends( - cmGeneratorTarget const* target, cmNinjaDeps& outputs, - const std::string& config, const std::string& fileConfig, - cmNinjaTargetDepends depends = DependOnTargetArtifact); + void AppendTargetOutputs(cmGeneratorTarget const* target, + cmNinjaDeps& outputs, const std::string& config, + cmNinjaTargetDepends depends); + void AppendTargetDepends(cmGeneratorTarget const* target, + cmNinjaDeps& outputs, const std::string& config, + const std::string& fileConfig, + cmNinjaTargetDepends depends); void AppendTargetDependsClosure(cmGeneratorTarget const* target, cmNinjaDeps& outputs, const std::string& config); @@ -371,6 +369,10 @@ public: return "1.10"; } static std::string RequiredNinjaVersionForCleanDeadTool() { return "1.10"; } + static std::string RequiredNinjaVersionForMultipleOutputs() + { + return "1.10"; + } bool SupportsConsolePool() const; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; @@ -448,6 +450,7 @@ private: bool CheckLanguages(std::vector<std::string> const& languages, cmMakefile* mf) const override; bool CheckFortran(cmMakefile* mf) const; + bool CheckISPC(cmMakefile* mf) const; void CloseCompileCommandsStream(); @@ -534,6 +537,7 @@ private: bool NinjaSupportsRestatTool = false; bool NinjaSupportsUnconditionalRecompactTool = false; bool NinjaSupportsCleanDeadTool = false; + bool NinjaSupportsMultipleOutputs = false; private: void InitOutputPathPrefix(); @@ -664,5 +668,3 @@ private: std::unique_ptr<cmGeneratedFileStream> CommonFileStream; std::unique_ptr<cmGeneratedFileStream> DefaultFileStream; }; - -#endif // ! cmGlobalNinjaGenerator_h diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index c31983b..37a77fa 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -143,7 +143,7 @@ void cmGlobalUnixMakefileGenerator3::Generate() total += pmi.second.NumberOfActions; } - // write each target's progress.make this loop is done twice. Bascially the + // write each target's progress.make this loop is done twice. Basically the // Generate pass counts all the actions, the first loop below determines // how many actions have progress updates for each target and writes to // corrrect variable values for everything except the all targets. The @@ -387,12 +387,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules( cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(lGenerator); // for all of out targets for (const auto& tgt : lg.GetGeneratorTargets()) { - if ((tgt->GetType() == cmStateEnums::EXECUTABLE) || - (tgt->GetType() == cmStateEnums::STATIC_LIBRARY) || - (tgt->GetType() == cmStateEnums::SHARED_LIBRARY) || - (tgt->GetType() == cmStateEnums::MODULE_LIBRARY) || - (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) || - (tgt->GetType() == cmStateEnums::UTILITY)) { + if (tgt->IsInBuildSystem() && + tgt->GetType() != cmStateEnums::GLOBAL_TARGET) { std::string tname = cmStrCat(lg.GetRelativeTargetDirectory(tgt.get()), "/DependInfo.cmake"); cmSystemTools::ConvertToUnixSlashes(tname); @@ -416,7 +412,7 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2( std::vector<std::string> depends; for (DirectoryTarget::Target const& t : dt.Targets) { // Add this to the list of depends rules in this directory. - if ((!check_all || !t.ExcludeFromAll) && + if ((!check_all || t.ExcludedFromAllInConfigs.empty()) && (!check_relink || t.GT->NeedRelinkBeforeInstall(lg->GetConfigName()))) { // The target may be from a different directory; use its local gen. @@ -635,17 +631,12 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( for (const auto& gtarget : lg.GetGeneratorTargets()) { // Don't emit the same rule twice (e.g. two targets with the same // simple name) - int type = gtarget->GetType(); std::string name = gtarget->GetName(); if (!name.empty() && emitted.insert(name).second && // Handle user targets here. Global targets are handled in // the local generator on a per-directory basis. - ((type == cmStateEnums::EXECUTABLE) || - (type == cmStateEnums::STATIC_LIBRARY) || - (type == cmStateEnums::SHARED_LIBRARY) || - (type == cmStateEnums::MODULE_LIBRARY) || - (type == cmStateEnums::OBJECT_LIBRARY) || - (type == cmStateEnums::UTILITY))) { + (gtarget->IsInBuildSystem() && + gtarget->GetType() != cmStateEnums::GLOBAL_TARGET)) { // Add a rule to build the target by name. lg.WriteDivider(ruleFileStream); ruleFileStream << "# Target rules for targets named " << name @@ -709,15 +700,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( // for each target Generate the rule files for each target. for (const auto& gtarget : lg.GetGeneratorTargets()) { - int type = gtarget->GetType(); std::string name = gtarget->GetName(); if (!name.empty() && - ((type == cmStateEnums::EXECUTABLE) || - (type == cmStateEnums::STATIC_LIBRARY) || - (type == cmStateEnums::SHARED_LIBRARY) || - (type == cmStateEnums::MODULE_LIBRARY) || - (type == cmStateEnums::OBJECT_LIBRARY) || - (type == cmStateEnums::UTILITY))) { + (gtarget->IsInBuildSystem() && + gtarget->GetType() != cmStateEnums::GLOBAL_TARGET)) { std::string makefileName; // Add a rule to build the target by name. localName = lg.GetRelativeTargetDirectory(gtarget.get()); @@ -845,8 +831,7 @@ void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks() for (const auto& gt : lg->GetGeneratorTargets()) { cmLocalGenerator* tlg = gt->GetLocalGenerator(); - if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY || - gt->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { + if (!gt->IsInBuildSystem() || IsExcluded(lg.get(), gt.get())) { continue; } @@ -881,7 +866,7 @@ size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInTarget( if (emitted.insert(target).second) { count = this->ProgressMap[target].Marks.size(); for (cmTargetDepend const& depend : this->GetTargetDirectDepends(target)) { - if (depend->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!depend->IsInBuildSystem()) { continue; } count += this->CountProgressMarksInTarget(depend, emitted); @@ -938,7 +923,7 @@ void cmGlobalUnixMakefileGenerator3::AppendGlobalTargetDepends( for (cmTargetDepend const& i : this->GetTargetDirectDepends(target)) { // Create the target-level dependency. cmGeneratorTarget const* dep = i; - if (dep->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!dep->IsInBuildSystem()) { continue; } cmLocalUnixMakefileGenerator3* lg3 = @@ -986,7 +971,9 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule( (type == cmStateEnums::STATIC_LIBRARY) || (type == cmStateEnums::SHARED_LIBRARY) || (type == cmStateEnums::MODULE_LIBRARY) || - (type == cmStateEnums::OBJECT_LIBRARY)) { + (type == cmStateEnums::OBJECT_LIBRARY) || + (type == cmStateEnums::INTERFACE_LIBRARY && + target->IsInBuildSystem())) { project_targets.insert(target->GetName()); } else if (type == cmStateEnums::GLOBAL_TARGET) { globals_targets.insert(target->GetName()); diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 1caa4b7..77d0827 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalUnixMakefileGenerator3_h -#define cmGlobalUnixMakefileGenerator3_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -259,5 +258,3 @@ private: DirectoryTargetsMap; void InitializeProgressMarks() override; }; - -#endif diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 5dac072..3805546 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -138,9 +138,6 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( "ProductDir", vc10Express, cmSystemTools::KeyWOW64_32); this->CudaEnabled = false; - this->SystemIsWindowsCE = false; - this->SystemIsWindowsPhone = false; - this->SystemIsWindowsStore = false; this->MSBuildCommandInitialized = false; { std::string envPlatformToolset; @@ -511,18 +508,16 @@ bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } - std::string v = this->GetInstalledNsightTegraVersion(); - if (v.empty()) { - mf->IssueMessage(MessageType::FATAL_ERROR, - "CMAKE_SYSTEM_NAME is 'Android' but " - "'NVIDIA Nsight Tegra Visual Studio Edition' " - "is not installed."); - return false; + if (mf->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM") == "Tegra-Android") { + if (!this->InitializeTegraAndroid(mf)) { + return false; + } + } else { + this->SystemIsAndroid = true; + if (!this->InitializeAndroid(mf)) { + return false; + } } - this->DefaultPlatformName = "Tegra-Android"; - this->DefaultPlatformToolset = "Default"; - this->NsightTegraVersion = v; - mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v); } return true; @@ -564,6 +559,31 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsStore(cmMakefile* mf) return false; } +bool cmGlobalVisualStudio10Generator::InitializeTegraAndroid(cmMakefile* mf) +{ + std::string v = this->GetInstalledNsightTegraVersion(); + if (v.empty()) { + mf->IssueMessage(MessageType::FATAL_ERROR, + "CMAKE_SYSTEM_NAME is 'Android' but " + "'NVIDIA Nsight Tegra Visual Studio Edition' " + "is not installed."); + return false; + } + this->DefaultPlatformName = "Tegra-Android"; + this->DefaultPlatformToolset = "Default"; + this->NsightTegraVersion = v; + mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v); + return true; +} + +bool cmGlobalVisualStudio10Generator::InitializeAndroid(cmMakefile* mf) +{ + std::ostringstream e; + e << this->GetName() << " does not support Android."; + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; +} + bool cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset( std::string& toolset) const { @@ -598,6 +618,28 @@ void cmGlobalVisualStudio10Generator::Generate() { this->LongestSource = LongestSourcePath(); this->cmGlobalVisualStudio8Generator::Generate(); + if (!this->AndroidExecutableWarnings.empty() && + !this->CMakeInstance->GetIsInTryCompile()) { + std::ostringstream e; + /* clang-format off */ + e << + "You are using Visual Studio tools for Android, which does not support " + "standalone executables. However, the following executable targets do " + "not have the ANDROID_GUI property set, and thus will not be built as " + "expected. They will be built as shared libraries with executable " + "filenames:\n" + " "; + /* clang-format on */ + bool first = true; + for (auto const& name : this->AndroidExecutableWarnings) { + if (!first) { + e << ", "; + } + first = false; + e << name; + } + this->CMakeInstance->IssueMessage(MessageType::WARNING, e.str()); + } if (this->LongestSource.Length > 0) { cmLocalGenerator* lg = this->LongestSource.Target->GetLocalGenerator(); std::ostringstream e; @@ -664,8 +706,14 @@ std::string const& cmGlobalVisualStudio10Generator::GetPlatformToolsetString() if (!this->GeneratorToolset.empty()) { return this->GeneratorToolset; } - if (!this->DefaultPlatformToolset.empty()) { - return this->DefaultPlatformToolset; + if (this->SystemIsAndroid) { + if (!this->DefaultAndroidToolset.empty()) { + return this->DefaultAndroidToolset; + } + } else { + if (!this->DefaultPlatformToolset.empty()) { + return this->DefaultPlatformToolset; + } } static std::string const empty; return empty; @@ -879,7 +927,10 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) epg.Attribute("Label", "Globals"); cmXMLElement(epg, "ProjectGuid") .Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}"); - cmXMLElement(epg, "Keyword").Content("Win32Proj"); + cmXMLElement(epg, "Keyword") + .Content(mf->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android" + ? "Android" + : "Win32Proj"); cmXMLElement(epg, "Platform").Content(this->GetPlatformName()); if (this->GetSystemName() == "WindowsPhone") { cmXMLElement(epg, "ApplicationType").Content("Windows Phone"); @@ -889,15 +940,21 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) cmXMLElement(epg, "ApplicationType").Content("Windows Store"); cmXMLElement(epg, "ApplicationTypeRevision") .Content(this->GetApplicationTypeRevision()); + } else if (this->GetSystemName() == "Android") { + cmXMLElement(epg, "ApplicationType").Content("Android"); + cmXMLElement(epg, "ApplicationTypeRevision") + .Content(this->GetApplicationTypeRevision()); } if (!this->WindowsTargetPlatformVersion.empty()) { cmXMLElement(epg, "WindowsTargetPlatformVersion") .Content(this->WindowsTargetPlatformVersion); } - if (this->GetPlatformName() == "ARM64") { - cmXMLElement(epg, "WindowsSDKDesktopARM64Support").Content("true"); - } else if (this->GetPlatformName() == "ARM") { - cmXMLElement(epg, "WindowsSDKDesktopARMSupport").Content("true"); + if (this->GetSystemName() != "Android") { + if (this->GetPlatformName() == "ARM64") { + cmXMLElement(epg, "WindowsSDKDesktopARM64Support").Content("true"); + } else if (this->GetPlatformName() == "ARM") { + cmXMLElement(epg, "WindowsSDKDesktopARMSupport").Content("true"); + } } } cmXMLElement(eprj, "Import") @@ -1209,6 +1266,10 @@ std::string cmGlobalVisualStudio10Generator::GetInstalledNsightTegraVersion() std::string cmGlobalVisualStudio10Generator::GetApplicationTypeRevision() const { + if (this->GetSystemName() == "Android") { + return this->GetAndroidApplicationTypeRevision(); + } + // Return the first two '.'-separated components of the Windows version. std::string::size_type end1 = this->SystemVersion.find('.'); std::string::size_type end2 = diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index b8c18b4..65ea33f 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -1,9 +1,9 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio10Generator_h -#define cmGlobalVisualStudio10Generator_h +#pragma once #include <memory> +#include <set> #include "cmGlobalVisualStudio8Generator.h" #include "cmVisualStudio10ToolsetOptions.h" @@ -43,6 +43,11 @@ public: void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*, bool optional) override; + void AddAndroidExecutableWarning(const std::string& name) + { + this->AndroidExecutableWarnings.insert(name); + } + bool IsCudaEnabled() const { return this->CudaEnabled; } /** Generating for Nsight Tegra VS plugin? */ @@ -100,6 +105,9 @@ public: /** Return true if building for WindowsStore */ bool TargetsWindowsStore() const { return this->SystemIsWindowsStore; } + /** Return true if building for Android */ + bool TargetsAndroid() const { return this->SystemIsAndroid; } + const char* GetCMakeCFGIntDir() const override { return "$(Configuration)"; } bool Find64BitTools(cmMakefile* mf); @@ -128,6 +136,8 @@ public: /** Return the first two components of CMAKE_SYSTEM_VERSION. */ std::string GetApplicationTypeRevision() const; + virtual const char* GetAndroidApplicationTypeRevision() const { return ""; } + cmIDEFlagTable const* GetClFlagTable() const; cmIDEFlagTable const* GetCSharpFlagTable() const; cmIDEFlagTable const* GetRcFlagTable() const; @@ -148,6 +158,8 @@ protected: virtual bool InitializeWindowsCE(cmMakefile* mf); virtual bool InitializeWindowsPhone(cmMakefile* mf); virtual bool InitializeWindowsStore(cmMakefile* mf); + virtual bool InitializeTegraAndroid(cmMakefile* mf); + virtual bool InitializeAndroid(cmMakefile* mf); virtual bool ProcessGeneratorToolsetField(std::string const& key, std::string const& value); @@ -171,6 +183,7 @@ protected: std::string GeneratorToolsetCudaCustomDir; std::string DefaultPlatformToolset; std::string DefaultPlatformToolsetHostArchitecture; + std::string DefaultAndroidToolset; std::string WindowsTargetPlatformVersion; std::string SystemName; std::string SystemVersion; @@ -185,9 +198,10 @@ protected: std::string DefaultNasmFlagTableName; std::string DefaultRCFlagTableName; bool SupportsUnityBuilds = false; - bool SystemIsWindowsCE; - bool SystemIsWindowsPhone; - bool SystemIsWindowsStore; + bool SystemIsWindowsCE = false; + bool SystemIsWindowsPhone = false; + bool SystemIsWindowsStore = false; + bool SystemIsAndroid = false; private: class Factory; @@ -211,6 +225,7 @@ private: std::string MSBuildCommand; bool MSBuildCommandInitialized; cmVisualStudio10ToolsetOptions ToolsetOptions; + std::set<std::string> AndroidExecutableWarnings; virtual std::string FindMSBuildCommand(); std::string FindDevEnvCommand() override; std::string GetVSMakeProgram() override { return this->GetMSBuildCommand(); } @@ -228,4 +243,3 @@ private: // We do not use the reload macros for VS >= 10. std::string GetUserMacrosDirectory() override { return ""; } }; -#endif diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index 5f1ff73..6e409cf 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio11Generator_h -#define cmGlobalVisualStudio11Generator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -53,4 +52,3 @@ private: class Factory; friend class Factory; }; -#endif diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index bdd40ff..c220d40 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio12Generator_h -#define cmGlobalVisualStudio12Generator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -48,4 +47,3 @@ private: class Factory; friend class Factory; }; -#endif diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index f549b6a..a12b7e1 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -109,6 +109,7 @@ cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator( "ProductDir", vc14Express, cmSystemTools::KeyWOW64_32); this->DefaultPlatformToolset = "v140"; + this->DefaultAndroidToolset = "Clang_3_8"; this->DefaultCLFlagTableName = "v140"; this->DefaultCSharpFlagTableName = "v140"; this->DefaultLibFlagTableName = "v14"; @@ -159,11 +160,17 @@ bool cmGlobalVisualStudio14Generator::InitializeWindowsStore(cmMakefile* mf) return true; } +bool cmGlobalVisualStudio14Generator::InitializeAndroid(cmMakefile*) +{ + return true; +} + bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf, bool required) { // Find the default version of the Windows 10 SDK. - std::string const version = this->GetWindows10SDKVersion(); + std::string const version = this->GetWindows10SDKVersion(mf); + if (required && version.empty()) { std::ostringstream e; e << "Could not find an appropriate version of the Windows 10 SDK" @@ -227,8 +234,25 @@ bool cmGlobalVisualStudio14Generator::IsWindowsStoreToolsetInstalled() const cmSystemTools::KeyWOW64_32); } -std::string cmGlobalVisualStudio14Generator::GetWindows10SDKMaxVersion() const +std::string cmGlobalVisualStudio14Generator::GetWindows10SDKMaxVersion( + cmMakefile* mf) const { + // if the given value is set, it can either be OFF/FALSE or a valid SDK + // string + if (cmProp value = mf->GetDefinition( + "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM")) { + + // If the value is some off/false value, then there is NO maximum set. + if (cmIsOff(value)) { + return std::string(); + } + // If the value is something else, trust that it is a valid SDK value. + else if (value) { + return *value; + } + // If value is an invalid pointer, leave result unchanged. + } + // The last Windows 10 SDK version that VS 2015 can target is 10.0.14393.0. // // "VS 2015 Users: The Windows 10 SDK (15063, 16299, 17134, 17763) is @@ -261,7 +285,8 @@ public: }; #endif -std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() +std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion( + cmMakefile* mf) { #if defined(_WIN32) && !defined(__CYGWIN__) std::vector<std::string> win10Roots; @@ -311,8 +336,10 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() i = cmSystemTools::GetFilenameName(i); } - // Skip SDKs that cannot be used with our toolset. - std::string maxVersion = this->GetWindows10SDKMaxVersion(); + // Skip SDKs that cannot be used with our toolset, unless the user does not + // want to limit the highest supported SDK according to the Microsoft + // documentation. + std::string maxVersion = this->GetWindows10SDKMaxVersion(mf); if (!maxVersion.empty()) { cm::erase_if(sdks, WindowsSDKTooRecent(maxVersion)); } diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index ccc2917..1ccd4c7 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio14Generator_h -#define cmGlobalVisualStudio14Generator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -23,12 +22,18 @@ public: bool MatchesGeneratorName(const std::string& name) const override; + const char* GetAndroidApplicationTypeRevision() const override + { + return "2.0"; + } + protected: cmGlobalVisualStudio14Generator(cmake* cm, const std::string& name, std::string const& platformInGeneratorName); bool InitializeWindows(cmMakefile* mf) override; bool InitializeWindowsStore(cmMakefile* mf) override; + bool InitializeAndroid(cmMakefile* mf) override; bool SelectWindowsStoreToolset(std::string& toolset) const override; // These aren't virtual because we need to check if the selected version @@ -37,7 +42,7 @@ protected: // Used to make sure that the Windows 10 SDK selected can work with the // version of the toolset. - virtual std::string GetWindows10SDKMaxVersion() const; + virtual std::string GetWindows10SDKMaxVersion(cmMakefile* mf) const; virtual bool SelectWindows10SDK(cmMakefile* mf, bool required); @@ -48,10 +53,9 @@ protected: // installed on the machine. bool IsWindowsDesktopToolsetInstalled() const override; - std::string GetWindows10SDKVersion(); + std::string GetWindows10SDKVersion(cmMakefile* mf); private: class Factory; friend class Factory; }; -#endif diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 7ada325..0083c40 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -19,8 +19,8 @@ void cmGlobalVisualStudio71Generator::WriteSLNFile( std::ostream& fout, cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { - std::vector<std::string> configs; - root->GetMakefile()->GetConfigurations(configs); + std::vector<std::string> configs = + root->GetMakefile()->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); // Write out the header for a SLN file this->WriteSLNHeader(fout); diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index 7eadaf3..7d38199 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio71Generator_h -#define cmGlobalVisualStudio71Generator_h +#pragma once #include "cmGlobalVisualStudio7Generator.h" @@ -42,4 +41,3 @@ protected: std::string ProjectConfigurationSectionName; }; -#endif diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 428c748..84cfaeb 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -339,7 +339,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( // loop over again and write out configurations for each target // in the solution for (cmGeneratorTarget const* target : projectTargets) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!target->IsInBuildSystem()) { continue; } cmProp expath = target->GetProperty("EXTERNAL_MSPROJECT"); @@ -369,7 +369,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( std::string rootBinaryDir = root->GetCurrentBinaryDirectory(); for (cmGeneratorTarget const* target : projectTargets) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!target->IsInBuildSystem()) { continue; } bool written = false; @@ -381,8 +381,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( std::string location = *expath; cmProp p = target->GetProperty("VS_PROJECT_TYPE"); - this->WriteExternalProject(fout, project, location, - p ? p->c_str() : nullptr, + this->WriteExternalProject(fout, project, location, cmToCStr(p), target->GetUtilities()); written = true; } else { @@ -436,7 +435,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetDepends( std::ostream& fout, OrderedTargetDependSet const& projectTargets) { for (cmGeneratorTarget const* target : projectTargets) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!target->IsInBuildSystem()) { continue; } cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); @@ -568,8 +567,9 @@ void cmGlobalVisualStudio7Generator::WriteSLNFooter(std::ostream& fout) std::string cmGlobalVisualStudio7Generator::WriteUtilityDepend( cmGeneratorTarget const* target) { - std::vector<std::string> configs; - target->Target->GetMakefile()->GetConfigurations(configs); + std::vector<std::string> configs = + target->Target->GetMakefile()->GetGeneratorConfigs( + cmMakefile::ExcludeEmptyConfig); std::string pname = cmStrCat(target->GetName(), "_UTILITY"); std::string fname = cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', @@ -675,11 +675,11 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( "CMAKE_VS_INCLUDE_" + t + "_TO_DEFAULT_BUILD"; // inspect CMAKE_VS_INCLUDE_<t>_TO_DEFAULT_BUILD properties for (std::string const& i : configs) { - const char* propertyValue = + cmProp propertyValue = target->Target->GetMakefile()->GetDefinition(propertyName); if (propertyValue && cmIsOn(cmGeneratorExpression::Evaluate( - propertyValue, target->GetLocalGenerator(), i))) { + *propertyValue, target->GetLocalGenerator(), i))) { activeConfigs.insert(i); } } @@ -693,9 +693,7 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( } // inspect EXCLUDE_FROM_DEFAULT_BUILD[_<CONFIG>] properties for (std::string const& i : configs) { - const char* propertyValue = - target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i); - if (cmIsOff(propertyValue)) { + if (cmIsOff(target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i))) { activeConfigs.insert(i); } } diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 6cc1cf8..148762e 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio7Generator_h -#define cmGlobalVisualStudio7Generator_h +#pragma once #include <memory> @@ -174,5 +173,3 @@ private: }; #define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK" - -#endif diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 29ca154..fcdfc50 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -325,7 +325,7 @@ void cmGlobalVisualStudio8Generator::WriteProjectDepends( TargetDependSet const& unordered = this->GetTargetDirectDepends(gt); OrderedTargetDependSet depends(unordered, std::string()); for (cmTargetDepend const& i : depends) { - if (i->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!i->IsInBuildSystem()) { continue; } std::string guid = this->GetGUID(i->GetName()); @@ -341,7 +341,7 @@ bool cmGlobalVisualStudio8Generator::NeedLinkLibraryDependencies( if (cmGeneratorTarget* depTarget = target->GetLocalGenerator()->FindGeneratorTargetToUse( ui.Value.first)) { - if (depTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY && + if (depTarget->IsInBuildSystem() && depTarget->GetProperty("EXTERNAL_MSPROJECT")) { // This utility dependency names an external .vcproj target. // We use LinkLibraryDependencies="true" to link to it without diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index 6ce67d3..96e3553 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio8Generator_h -#define cmGlobalVisualStudio8Generator_h +#pragma once #include "cmGlobalVisualStudio71Generator.h" @@ -78,4 +77,3 @@ protected: std::string Name; std::string WindowsCEVersion; }; -#endif diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h index 53318a6..6f4d159 100644 --- a/Source/cmGlobalVisualStudio9Generator.h +++ b/Source/cmGlobalVisualStudio9Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio9Generator_h -#define cmGlobalVisualStudio9Generator_h +#pragma once #include <memory> @@ -38,4 +37,3 @@ private: class Factory; friend class Factory; }; -#endif diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index c688da2..001d876 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -368,7 +368,7 @@ cmGlobalVisualStudioGenerator::GetTargetLinkClosure(cmGeneratorTarget* target) void cmGlobalVisualStudioGenerator::FollowLinkDepends( const cmGeneratorTarget* target, std::set<const cmGeneratorTarget*>& linked) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!target->IsInBuildSystem()) { return; } if (linked.insert(target).second && @@ -509,7 +509,7 @@ std::string cmGlobalVisualStudioGenerator::GetStartupProjectName( cmLocalGenerator const* root) const { cmProp n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT"); - if (n && !n->empty()) { + if (cmNonempty(n)) { std::string startup = *n; if (this->FindTarget(startup)) { return startup; @@ -810,7 +810,7 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly( // a target with none of its own sources, e.g. when also using // object libraries. cmProp linkLang = gt->GetProperty("LINKER_LANGUAGE"); - if (linkLang && !linkLang->empty()) { + if (cmNonempty(linkLang)) { languages.insert(*linkLang); } diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 29a5c2c..3c46408 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudioGenerator_h -#define cmGlobalVisualStudioGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -224,5 +223,3 @@ public: OrderedTargetDependSet(TargetDependSet const&, std::string const& first); OrderedTargetDependSet(TargetSet const&, std::string const& first); }; - -#endif diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 605dc8b..4b877ce 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -100,6 +100,24 @@ static const char* VSVersionToToolset( return ""; } +static const char* VSVersionToAndroidToolset( + cmGlobalVisualStudioGenerator::VSVersion v) +{ + switch (v) { + case cmGlobalVisualStudioGenerator::VS9: + case cmGlobalVisualStudioGenerator::VS10: + case cmGlobalVisualStudioGenerator::VS11: + case cmGlobalVisualStudioGenerator::VS12: + return ""; + case cmGlobalVisualStudioGenerator::VS14: + return "Clang_3_8"; + case cmGlobalVisualStudioGenerator::VS15: + case cmGlobalVisualStudioGenerator::VS16: + return "Clang_5_0"; + } + return ""; +} + static const char vs15generatorName[] = "Visual Studio 15 2017"; // Map generator name without year to name with year. @@ -284,6 +302,7 @@ cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator( this->Version = version; this->ExpressEdition = false; this->DefaultPlatformToolset = VSVersionToToolset(this->Version); + this->DefaultAndroidToolset = VSVersionToAndroidToolset(this->Version); this->DefaultCLFlagTableName = VSVersionToToolset(this->Version); this->DefaultCSharpFlagTableName = VSVersionToToolset(this->Version); this->DefaultLinkFlagTableName = VSVersionToToolset(this->Version); @@ -408,6 +427,25 @@ bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const vsInstanceVersion > vsInstanceVersion16_7_P2); } +const char* +cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision() + const +{ + switch (this->Version) { + case cmGlobalVisualStudioGenerator::VS9: + case cmGlobalVisualStudioGenerator::VS10: + case cmGlobalVisualStudioGenerator::VS11: + case cmGlobalVisualStudioGenerator::VS12: + return ""; + case cmGlobalVisualStudioGenerator::VS14: + return "2.0"; + case cmGlobalVisualStudioGenerator::VS15: + case cmGlobalVisualStudioGenerator::VS16: + return "3.0"; + } + return ""; +} + std::string cmGlobalVisualStudioVersionedGenerator::GetAuxiliaryToolset() const { const char* version = this->GetPlatformToolsetVersion(); @@ -502,8 +540,8 @@ bool cmGlobalVisualStudioVersionedGenerator::IsWin81SDKInstalled() const return false; } -std::string cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersion() - const +std::string cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersion( + cmMakefile*) const { return std::string(); } diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index cbd3ba7..af09cbd 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudioVersionedGenerator_h -#define cmGlobalVisualStudioVersionedGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -36,6 +35,8 @@ public: bool IsStdOutEncodingSupported() const override; + const char* GetAndroidApplicationTypeRevision() const override; + protected: cmGlobalVisualStudioVersionedGenerator( VSVersion version, cmake* cm, const std::string& name, @@ -55,7 +56,7 @@ protected: // Check for a Win 8 SDK known to the registry or VS installer tool. bool IsWin81SDKInstalled() const; - std::string GetWindows10SDKMaxVersion() const override; + std::string GetWindows10SDKMaxVersion(cmMakefile*) const override; std::string FindMSBuildCommand() override; std::string FindDevEnvCommand() override; @@ -67,4 +68,3 @@ private: friend class Factory16; mutable cmVSSetupAPIHelper vsSetupAPIHelper; }; -#endif diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h index c47127f..da39d3f 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.h +++ b/Source/cmGlobalWatcomWMakeGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalWatcomWMakeGenerator_h -#define cmGlobalWatcomWMakeGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -64,5 +63,3 @@ protected: void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override; }; - -#endif diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index b28395a..2f27128 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -173,6 +173,7 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator( this->RootObject = nullptr; this->MainGroupChildren = nullptr; + this->FrameworkGroup = nullptr; this->CurrentMakefile = nullptr; this->CurrentLocalGenerator = nullptr; this->XcodeBuildCommandInitialized = false; @@ -423,37 +424,6 @@ void cmGlobalXCodeGenerator::AddExtraIDETargets() } } -void cmGlobalXCodeGenerator::ComputeTargetOrder() -{ - size_t index = 0; - auto const& lgens = this->GetLocalGenerators(); - for (auto const& lgen : lgens) { - const auto& targets = lgen->GetGeneratorTargets(); - for (const auto& gt : targets) { - this->ComputeTargetOrder(gt.get(), index); - } - } - assert(index == this->TargetOrderIndex.size()); -} - -void cmGlobalXCodeGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt, - size_t& index) -{ - std::map<cmGeneratorTarget const*, size_t>::value_type value(gt, 0); - auto insertion = this->TargetOrderIndex.insert(value); - if (!insertion.second) { - return; - } - auto entry = insertion.first; - - auto& deps = this->GetTargetDirectDepends(gt); - for (auto& d : deps) { - this->ComputeTargetOrder(d, index); - } - - entry->second = index++; -} - void cmGlobalXCodeGenerator::Generate() { this->cmGlobalGenerator::Generate(); @@ -461,8 +431,6 @@ void cmGlobalXCodeGenerator::Generate() return; } - this->ComputeTargetOrder(); - for (auto keyVal : this->ProjectMap) { cmLocalGenerator* root = keyVal.second[0]; @@ -476,6 +444,9 @@ void cmGlobalXCodeGenerator::Generate() } } + // cache the enabled languages for source file type queries + this->GetEnabledLanguages(this->EnabledLangs); + this->SetGenerationRoot(root); // now create the project this->OutputXCodeProject(root, keyVal.second); @@ -673,6 +644,9 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects() this->GroupNameMap.clear(); this->TargetGroup.clear(); this->FileRefs.clear(); + this->ExternalLibRefs.clear(); + this->FileRefToBuildFileMap.clear(); + this->CommandsVisited.clear(); } void cmGlobalXCodeGenerator::addObject(std::unique_ptr<cmXCodeObject> obj) @@ -741,21 +715,28 @@ std::string GetGroupMapKeyFromPath(cmGeneratorTarget* target, return key; } -cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath( +cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeBuildFileFromPath( const std::string& fullpath, cmGeneratorTarget* target, const std::string& lang, cmSourceFile* sf) { // Using a map and the full path guarantees that we will always get the same - // fileRef object for any given full path. - // + // fileRef object for any given full path. Same goes for the buildFile + // object. cmXCodeObject* fileRef = this->CreateXCodeFileReferenceFromPath(fullpath, target, lang, sf); - - cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); - buildFile->SetComment(fileRef->GetComment()); - buildFile->AddAttribute("fileRef", this->CreateObjectReference(fileRef)); - - return buildFile; + if (fileRef) { + auto it = this->FileRefToBuildFileMap.find(fileRef); + if (it == this->FileRefToBuildFileMap.end()) { + cmXCodeObject* buildFile = + this->CreateObject(cmXCodeObject::PBXBuildFile); + buildFile->SetComment(fileRef->GetComment()); + buildFile->AddAttribute("fileRef", this->CreateObjectReference(fileRef)); + this->FileRefToBuildFileMap[fileRef] = buildFile; + return buildFile; + } + return it->second; + } + return nullptr; } class XCodeGeneratorExpressionInterpreter @@ -827,6 +808,14 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( default: break; } + + // explicitly add the explicit language flag before any other flag + // this way backwards compatibility with user flags is maintained + if (sf->GetProperty("LANGUAGE")) { + this->CurrentLocalGenerator->AppendFeatureOptions(flags, lang, + "EXPLICIT_LANGUAGE"); + } + const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (cmProp cflags = sf->GetProperty(COMPILE_FLAGS)) { lg->AppendFlags(flags, genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS)); @@ -869,7 +858,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true)); cmXCodeObject* buildFile = - this->CreateXCodeSourceFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf); + this->CreateXCodeBuildFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf); cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); settings->AddAttributeIfNotEmpty("COMPILER_FLAGS", @@ -905,7 +894,9 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( settings->AddAttributeIfNotEmpty("ATTRIBUTES", attrs); - buildFile->AddAttributeIfNotEmpty("settings", settings); + if (buildFile) { + buildFile->AddAttributeIfNotEmpty("settings", settings); + } return buildFile; } @@ -922,14 +913,45 @@ void cmGlobalXCodeGenerator::AddXCodeProjBuildRule( } } -std::string GetSourcecodeValueFromFileExtension(const std::string& _ext, - const std::string& lang, - bool& keepLastKnownFileType) +namespace { + +bool IsLinkPhaseLibraryExtension(const std::string& fileExt) +{ + // Empty file extension is a special case for paths to framework's + // internal binary which could be MyFw.framework/Versions/*/MyFw + return (fileExt == ".framework" || fileExt == ".a" || fileExt == ".o" || + fileExt == ".dylib" || fileExt == ".tbd" || fileExt.empty()); +} +bool IsLibraryType(const std::string& fileType) +{ + return (fileType == "wrapper.framework" || fileType == "archive.ar" || + fileType == "compiled.mach-o.objfile" || + fileType == "compiled.mach-o.dylib" || + fileType == "compiled.mach-o.executable" || + fileType == "sourcecode.text-based-dylib-definition"); +} + +std::string GetDirectoryValueFromFileExtension(const std::string& dirExt) +{ + std::string ext = cmSystemTools::LowerCase(dirExt); + if (ext == "framework") { + return "wrapper.framework"; + } + if (ext == "xcassets") { + return "folder.assetcatalog"; + } + return "folder"; +} + +std::string GetSourcecodeValueFromFileExtension( + const std::string& _ext, const std::string& lang, + bool& keepLastKnownFileType, const std::vector<std::string>& enabled_langs) { std::string ext = cmSystemTools::LowerCase(_ext); std::string sourcecode = "sourcecode"; if (ext == "o") { + keepLastKnownFileType = true; sourcecode = "compiled.mach-o.objfile"; } else if (ext == "xctest") { sourcecode = "wrapper.cfbundle"; @@ -939,9 +961,9 @@ std::string GetSourcecodeValueFromFileExtension(const std::string& _ext, } else if (ext == "storyboard") { keepLastKnownFileType = true; sourcecode = "file.storyboard"; - } else if (ext == "mm") { + } else if (ext == "mm" && !cm::contains(enabled_langs, "OBJCXX")) { sourcecode += ".cpp.objcpp"; - } else if (ext == "m") { + } else if (ext == "m" && !cm::contains(enabled_langs, "OBJC")) { sourcecode += ".c.objc"; } else if (ext == "swift") { sourcecode += ".swift"; @@ -973,6 +995,20 @@ std::string GetSourcecodeValueFromFileExtension(const std::string& _ext, sourcecode += ".metal"; } else if (ext == "mig") { sourcecode += ".mig"; + } else if (ext == "tbd") { + sourcecode += ".text-based-dylib-definition"; + } else if (ext == "a") { + keepLastKnownFileType = true; + sourcecode = "archive.ar"; + } else if (ext == "dylib") { + keepLastKnownFileType = true; + sourcecode = "compiled.mach-o.dylib"; + } else if (ext == "framework") { + keepLastKnownFileType = true; + sourcecode = "wrapper.framework"; + } else if (ext == "xcassets") { + keepLastKnownFileType = true; + sourcecode = "folder.assetcatalog"; } // else // { @@ -985,24 +1021,51 @@ std::string GetSourcecodeValueFromFileExtension(const std::string& _ext, return sourcecode; } +// If the file has no extension it's either a raw executable or might +// be a direct reference to a binary within a framework (bad practice!). +// This is where we change the path to point to the framework directory. +// .tbd files also can be located in SDK frameworks (they are +// placeholders for actual libraries shipped with the OS) +std::string GetLibraryOrFrameworkPath(const std::string& path) +{ + auto ext = cmSystemTools::GetFilenameLastExtension(path); + if (ext.empty() || ext == ".tbd") { + auto name = cmSystemTools::GetFilenameWithoutExtension(path); + // Check for iOS framework structure: + // FwName.framework/FwName (and also on macOS where FwName lib is a + // symlink) + auto parentDir = cmSystemTools::GetParentDirectory(path); + auto parentName = cmSystemTools::GetFilenameWithoutExtension(parentDir); + ext = cmSystemTools::GetFilenameLastExtension(parentDir); + if (ext == ".framework" && name == parentName) { + return parentDir; + } + // Check for macOS framework structure: + // FwName.framework/Versions/*/FwName + std::vector<std::string> components; + cmSystemTools::SplitPath(path, components); + if (components.size() > 3 && + components[components.size() - 3] == "Versions") { + ext = cmSystemTools::GetFilenameLastExtension( + components[components.size() - 4]); + parentName = cmSystemTools::GetFilenameWithoutExtension( + components[components.size() - 4]); + if (ext == ".framework" && name == parentName) { + components.erase(components.begin() + components.size() - 3, + components.end()); + return cmSystemTools::JoinPath(components); + } + } + } + return path; +} + +} // anonymous + cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( const std::string& fullpath, cmGeneratorTarget* target, const std::string& lang, cmSourceFile* sf) { - std::string key = GetGroupMapKeyFromPath(target, fullpath); - cmXCodeObject* fileRef = this->FileRefs[key]; - if (!fileRef) { - fileRef = this->CreateObject(cmXCodeObject::PBXFileReference); - fileRef->SetComment(fullpath); - this->FileRefs[key] = fileRef; - } - cmXCodeObject* group = this->GroupMap[key]; - cmXCodeObject* children = group->GetObject("children"); - if (!children->HasObject(fileRef)) { - children->AddObject(fileRef); - } - fileRef->AddAttribute("fileEncoding", this->CreateString("4")); - bool useLastKnownFileType = false; std::string fileType; if (sf) { @@ -1013,38 +1076,76 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( fileType = *l; } } + // Make a copy so that we can override it later + std::string path = fullpath; + // Compute the extension without leading '.'. + std::string ext = cmSystemTools::GetFilenameLastExtension(path); + if (!ext.empty()) { + ext = ext.substr(1); + } if (fileType.empty()) { - // Compute the extension without leading '.'. - std::string ext = cmSystemTools::GetFilenameLastExtension(fullpath); + path = GetLibraryOrFrameworkPath(path); + ext = cmSystemTools::GetFilenameLastExtension(path); if (!ext.empty()) { ext = ext.substr(1); } - // If fullpath references a directory, then we need to specify // lastKnownFileType as folder in order for Xcode to be able to // open the contents of the folder. // (Xcode 4.6 does not like explicitFileType=folder). - if (cmSystemTools::FileIsDirectory(fullpath)) { - fileType = (ext == "xcassets" ? "folder.assetcatalog" : "folder"); + if (cmSystemTools::FileIsDirectory(path)) { + fileType = GetDirectoryValueFromFileExtension(ext); useLastKnownFileType = true; } else { - fileType = - GetSourcecodeValueFromFileExtension(ext, lang, useLastKnownFileType); + if (ext.empty() && !sf) { + // Special case for executable or library without extension + // that is not a source file. We can't tell which without reading + // its Mach-O header, but the file might not exist yet, so we + // have to pick one here. + useLastKnownFileType = true; + fileType = "compiled.mach-o.executable"; + } else { + fileType = GetSourcecodeValueFromFileExtension( + ext, lang, useLastKnownFileType, this->EnabledLangs); + } } } + std::string key = GetGroupMapKeyFromPath(target, path); + cmXCodeObject* fileRef = this->FileRefs[key]; + if (!fileRef) { + fileRef = this->CreateObject(cmXCodeObject::PBXFileReference); + fileRef->SetComment(path); + this->FileRefs[key] = fileRef; + } + fileRef->AddAttribute("fileEncoding", this->CreateString("4")); fileRef->AddAttribute(useLastKnownFileType ? "lastKnownFileType" : "explicitFileType", this->CreateString(fileType)); - // Store the file path relative to the top of the source tree. - std::string path = this->RelativeToSource(fullpath); + if (!IsLibraryType(fileType)) { + path = this->RelativeToSource(path); + } std::string name = cmSystemTools::GetFilenameName(path); const char* sourceTree = cmSystemTools::FileIsFullPath(path) ? "<absolute>" : "SOURCE_ROOT"; fileRef->AddAttribute("name", this->CreateString(name)); fileRef->AddAttribute("path", this->CreateString(path)); fileRef->AddAttribute("sourceTree", this->CreateString(sourceTree)); + + cmXCodeObject* group = this->GroupMap[key]; + if (!group && IsLibraryType(fileType)) { + group = this->FrameworkGroup; + this->GroupMap[key] = group; + } + if (!group) { + cmSystemTools::Error("Could not find a PBX group for " + key); + return nullptr; + } + cmXCodeObject* children = group->GetAttribute("children"); + if (!children->HasObject(fileRef)) { + children->AddObject(fileRef); + } return fileRef; } @@ -1077,11 +1178,8 @@ void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen) this->CurrentMakefile = gen->GetMakefile(); // Select the current set of configuration types. - this->CurrentConfigurationTypes.clear(); - this->CurrentMakefile->GetConfigurations(this->CurrentConfigurationTypes); - if (this->CurrentConfigurationTypes.empty()) { - this->CurrentConfigurationTypes.emplace_back(); - } + this->CurrentConfigurationTypes = + this->CurrentMakefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); } struct cmSourceFilePathCompare @@ -1112,12 +1210,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets) { this->SetCurrentLocalGenerator(gen); - std::vector<cmGeneratorTarget*> gts; - cm::append(gts, this->CurrentLocalGenerator->GetGeneratorTargets()); - std::sort(gts.begin(), gts.end(), - [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) { - return this->TargetOrderIndex[l] < this->TargetOrderIndex[r]; - }); + std::vector<cmGeneratorTarget*> gts = + this->GetLocalGeneratorTargetsInOrder(gen); for (auto gtgt : gts) { if (!this->CreateXCodeTarget(gtgt, targets)) { return false; @@ -1137,11 +1231,22 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( return true; } - if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!gtgt->IsInBuildSystem()) { return true; } + auto& gtgt_visited = this->CommandsVisited[gtgt]; + auto& deps = this->GetTargetDirectDepends(gtgt); + for (auto& d : deps) { + // Take the union of visited source files of custom commands so far. + // ComputeTargetOrder ensures our dependencies already visited their + // custom commands and updated CommandsVisited. + auto& dep_visited = this->CommandsVisited[d]; + gtgt_visited.insert(dep_visited.begin(), dep_visited.end()); + } + if (gtgt->GetType() == cmStateEnums::UTILITY || + gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY || gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { cmXCodeObject* t = this->CreateUtilityTarget(gtgt); if (!t) { @@ -1152,23 +1257,24 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( } // organize the sources - std::vector<cmSourceFile*> classes; - if (!gtgt->GetConfigCommonSourceFiles(classes)) { + std::vector<cmSourceFile*> commonSourceFiles; + if (!gtgt->GetConfigCommonSourceFiles(commonSourceFiles)) { return false; } // Add CMakeLists.txt file for user convenience. - this->AddXCodeProjBuildRule(gtgt, classes); + this->AddXCodeProjBuildRule(gtgt, commonSourceFiles); // Add the Info.plist we are about to generate for an App Bundle. if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) { std::string plist = this->ComputeInfoPListLocation(gtgt); cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource( plist, true, cmSourceFileLocationKind::Known); - classes.push_back(sf); + commonSourceFiles.push_back(sf); } - std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); + std::sort(commonSourceFiles.begin(), commonSourceFiles.end(), + cmSourceFilePathCompare()); gtgt->ComputeObjectMapping(); @@ -1176,16 +1282,20 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( std::vector<cmXCodeObject*> headerFiles; std::vector<cmXCodeObject*> resourceFiles; std::vector<cmXCodeObject*> sourceFiles; - for (auto sourceFile : classes) { + for (auto sourceFile : commonSourceFiles) { cmXCodeObject* xsf = this->CreateXCodeSourceFile( this->CurrentLocalGenerator, sourceFile, gtgt); - cmXCodeObject* fr = xsf->GetObject("fileRef"); - cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); + cmXCodeObject* fr = xsf->GetAttribute("fileRef"); + cmXCodeObject* filetype = + fr->GetObject()->GetAttribute("explicitFileType"); + if (!filetype) { + filetype = fr->GetObject()->GetAttribute("lastKnownFileType"); + } cmGeneratorTarget::SourceFileFlags tsFlags = gtgt->GetTargetSourceFileFlags(sourceFile); - if (filetype && filetype->GetString() == "compiled.mach-o.objfile") { + if (filetype && IsLibraryType(filetype->GetString())) { if (sourceFile->GetObjectLibrary().empty()) { externalObjFiles.push_back(xsf); } @@ -1275,7 +1385,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( using mapOfVectorOfSourceFiles = std::map<std::string, std::vector<cmSourceFile*>>; mapOfVectorOfSourceFiles bundleFiles; - for (auto sourceFile : classes) { + for (auto sourceFile : commonSourceFiles) { cmGeneratorTarget::SourceFileFlags tsFlags = gtgt->GetTargetSourceFileFlags(sourceFile); if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { @@ -1323,7 +1433,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( using mapOfVectorOfSourceFiles = std::map<std::string, std::vector<cmSourceFile*>>; mapOfVectorOfSourceFiles bundleFiles; - for (auto sourceFile : classes) { + for (auto sourceFile : commonSourceFiles) { cmGeneratorTarget::SourceFileFlags tsFlags = gtgt->GetTargetSourceFileFlags(sourceFile); if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) { @@ -1353,22 +1463,20 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( } } - // create framework build phase + // always create framework build phase cmXCodeObject* frameworkBuildPhase = nullptr; - if (!externalObjFiles.empty()) { - frameworkBuildPhase = - this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase); - frameworkBuildPhase->SetComment("Frameworks"); - frameworkBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - frameworkBuildPhase->AddAttribute("files", buildFiles); - for (auto& externalObjFile : externalObjFiles) { - buildFiles->AddObject(externalObjFile); - } - frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - } + frameworkBuildPhase = + this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase); + frameworkBuildPhase->SetComment("Frameworks"); + frameworkBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + frameworkBuildPhase->AddAttribute("files", buildFiles); + for (auto& externalObjFile : externalObjFiles) { + buildFiles->AddObject(externalObjFile); + } + frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); // create list of build phases and create the Xcode target cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST); @@ -1494,8 +1602,9 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( } // add all the sources std::vector<cmCustomCommand> commands; + auto& visited = this->CommandsVisited[gtgt]; for (auto sourceFile : classes) { - if (sourceFile->GetCustomCommand()) { + if (sourceFile->GetCustomCommand() && visited.insert(sourceFile).second) { commands.push_back(*sourceFile->GetCustomCommand()); } } @@ -1705,6 +1814,15 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( for (auto const& command : commands) { cmCustomCommandGenerator ccg(command, configName, this->CurrentLocalGenerator); + std::vector<std::string> realDepends; + realDepends.reserve(ccg.GetDepends().size()); + for (auto const& d : ccg.GetDepends()) { + std::string dep; + if (this->CurrentLocalGenerator->GetRealDependency(d, configName, dep)) { + realDepends.emplace_back(std::move(dep)); + } + } + if (ccg.GetNumberOfCommands() > 0) { makefileStream << "\n"; const std::vector<std::string>& outputs = ccg.GetOutputs(); @@ -1720,12 +1838,8 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( // There are no outputs. Use the generated force rule name. makefileStream << tname[&ccg.GetCC()] << ": "; } - for (auto const& d : ccg.GetDepends()) { - std::string dep; - if (this->CurrentLocalGenerator->GetRealDependency(d, configName, - dep)) { - makefileStream << "\\\n" << this->ConvertToRelativeForMake(dep); - } + for (auto const& dep : realDepends) { + makefileStream << "\\\n" << this->ConvertToRelativeForMake(dep); } makefileStream << "\n"; @@ -1754,6 +1868,17 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( ccg.AppendArguments(c, cmd); makefileStream << "\t" << cmd << "\n"; } + + // Symbolic inputs are not expected to exist, so add dummy rules. + for (auto const& dep : realDepends) { + if (cmSourceFile* dsf = + target->GetLocalGenerator()->GetMakefile()->GetSource( + dep, cmSourceFileLocationKind::Known)) { + if (dsf->GetPropertyAsBool("SYMBOLIC")) { + makefileStream << this->ConvertToRelativeForMake(dep) << ":\n"; + } + } + } } } } @@ -1781,7 +1906,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, cmXCodeObject* buildSettings, const std::string& configName) { - if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!gtgt->IsInBuildSystem()) { return; } @@ -2256,7 +2381,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, if (stdlib.size() > 8) { const auto cxxLibrary = stdlib.substr(8); if (language == "CXX" || - !buildSettings->GetObject("CLANG_CXX_LIBRARY")) { + !buildSettings->GetAttribute("CLANG_CXX_LIBRARY")) { buildSettings->AddAttribute("CLANG_CXX_LIBRARY", this->CreateString(cxxLibrary)); } @@ -2278,7 +2403,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, std::string flags = cflags[language] + " " + defFlags; if (language == "CXX" || language == "OBJCXX") { if (language == "CXX" || - !buildSettings->GetObject("OTHER_CPLUSPLUSFLAGS")) { + !buildSettings->GetAttribute("OTHER_CPLUSPLUSFLAGS")) { buildSettings->AddAttribute("OTHER_CPLUSPLUSFLAGS", this->CreateString(flags)); } @@ -2286,7 +2411,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("IFORT_OTHER_FLAGS", this->CreateString(flags)); } else if (language == "C" || language == "OBJC") { - if (language == "C" || !buildSettings->GetObject("OTHER_CFLAGS")) { + if (language == "C" || !buildSettings->GetAttribute("OTHER_CFLAGS")) { buildSettings->AddAttribute("OTHER_CFLAGS", this->CreateString(flags)); } } else if (language == "Swift") { @@ -2472,7 +2597,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( this->XCodeObjectMap[gtgt] = target; // Add source files without build rules for editing convenience. - if (gtgt->GetType() == cmStateEnums::UTILITY && + if (gtgt->GetType() != cmStateEnums::GLOBAL_TARGET && gtgt->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { std::vector<cmSourceFile*> sources; if (!gtgt->GetConfigCommonSourceFiles(sources)) { @@ -2614,7 +2739,7 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType( cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget( cmGeneratorTarget* gtgt, cmXCodeObject* buildPhases) { - if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!gtgt->IsInBuildSystem()) { return nullptr; } cmXCodeObject* target = this->CreateObject(cmXCodeObject::PBXNativeTarget); @@ -2706,7 +2831,7 @@ void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target, targetdep->AddAttribute("targetProxy", this->CreateObjectReference(container)); - cmXCodeObject* depends = target->GetObject("dependencies"); + cmXCodeObject* depends = target->GetAttribute("dependencies"); if (!depends) { cmSystemTools::Error( "target does not have dependencies attribute error.."); @@ -2718,33 +2843,60 @@ void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target, void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings, const char* attribute, - const char* value) + cmXCodeObject* value) { if (settings) { - cmXCodeObject* attr = settings->GetObject(attribute); + cmXCodeObject* attr = settings->GetAttribute(attribute); if (!attr) { - settings->AddAttribute(attribute, this->CreateString(value)); + settings->AddAttribute(attribute, value); } else { - std::string oldValue = cmStrCat(attr->GetString(), ' ', value); - attr->SetString(oldValue); + if (value->GetType() != cmXCodeObject::OBJECT_LIST && + value->GetType() != cmXCodeObject::STRING) { + cmSystemTools::Error("Unsupported value type for appending: " + + std::string(attribute)); + return; + } + if (attr->GetType() == cmXCodeObject::OBJECT_LIST) { + if (value->GetType() == cmXCodeObject::OBJECT_LIST) { + for (auto* obj : value->GetObjectList()) { + attr->AddObject(obj); + } + } else { + attr->AddObject(value); + } + } else if (attr->GetType() == cmXCodeObject::STRING) { + if (value->GetType() == cmXCodeObject::OBJECT_LIST) { + // Add old value as a list item to new object list + // and replace the attribute with the new list + value->PrependObject(attr); + settings->AddAttribute(attribute, value); + } else { + std::string newValue = + cmStrCat(attr->GetString(), ' ', value->GetString()); + attr->SetString(newValue); + } + } else { + cmSystemTools::Error("Unsupported attribute type for appending: " + + std::string(attribute)); + } } } } void cmGlobalXCodeGenerator::AppendBuildSettingAttribute( - cmXCodeObject* target, const char* attribute, const char* value, + cmXCodeObject* target, const char* attribute, cmXCodeObject* value, const std::string& configName) { // There are multiple configurations. Add the setting to the // buildSettings of the configuration name given. cmXCodeObject* configurationList = - target->GetObject("buildConfigurationList")->GetObject(); + target->GetAttribute("buildConfigurationList")->GetObject(); cmXCodeObject* buildConfigs = - configurationList->GetObject("buildConfigurations"); + configurationList->GetAttribute("buildConfigurations"); for (auto obj : buildConfigs->GetObjectList()) { if (configName.empty() || - obj->GetObject("name")->GetString() == configName) { - cmXCodeObject* settings = obj->GetObject("buildSettings"); + obj->GetAttribute("name")->GetString() == configName) { + cmXCodeObject* settings = obj->GetAttribute("buildSettings"); this->AppendOrAddBuildSetting(settings, attribute, value); } } @@ -2757,7 +2909,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) cmSystemTools::Error("Error no target on xobject\n"); return; } - if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!gt->IsInBuildSystem()) { return; } @@ -2768,24 +2920,263 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) } } + // Separate libraries into ones that can be linked using "Link Binary With + // Libraries" build phase and the ones that can't. Only targets that build + // Apple bundles (.app, .framework, .bundle), executables and dylibs can use + // this feature and only targets that represent actual libraries (object, + // static, dynamic or bundle, excluding executables) will be used. These are + // limitations imposed by CMake use-cases - otherwise a lot of things break. + // The rest will be linked using linker flags (OTHER_LDFLAGS setting in Xcode + // project). + std::map<std::string, std::vector<cmComputeLinkInformation::Item const*>> + configItemMap; + auto addToLinkerArguments = + [&configItemMap](const std::string& configName, + cmComputeLinkInformation::Item const* libItemPtr) { + auto& linkVector = configItemMap[configName]; + if (std::find_if(linkVector.begin(), linkVector.end(), + [libItemPtr](cmComputeLinkInformation::Item const* p) { + return p == libItemPtr; + }) == linkVector.end()) { + linkVector.push_back(libItemPtr); + } + }; + std::vector<cmComputeLinkInformation::Item const*> linkPhaseTargetVector; + std::map<std::string, std::vector<std::string>> targetConfigMap; + using ConfigItemPair = + std::pair<std::string, cmComputeLinkInformation::Item const*>; + std::map<std::string, std::vector<ConfigItemPair>> targetItemMap; + std::map<std::string, std::vector<std::string>> targetProductNameMap; + bool useLinkPhase = false; + bool forceLinkPhase = false; + cmProp prop = + target->GetTarget()->GetProperty("XCODE_LINK_BUILD_PHASE_MODE"); + if (prop) { + if (*prop == "BUILT_ONLY") { + useLinkPhase = true; + } else if (*prop == "KNOWN_LOCATION") { + useLinkPhase = true; + forceLinkPhase = true; + } else if (*prop != "NONE") { + cmSystemTools::Error("Invalid value for XCODE_LINK_BUILD_PHASE_MODE: " + + *prop); + return; + } + } + for (auto const& configName : this->CurrentConfigurationTypes) { + cmComputeLinkInformation* cli = gt->GetLinkInformation(configName); + if (!cli) { + continue; + } + for (auto const& libItem : cli->GetItems()) { + // We want to put only static libraries, dynamic libraries, frameworks + // and bundles that are built from targets that are not imported in "Link + // Binary With Libraries" build phase. Except if the target property + // XCODE_LINK_BUILD_PHASE_MODE is KNOWN_LOCATION then all imported and + // non-target libraries will be added as well. + if (useLinkPhase && + (gt->GetType() == cmStateEnums::EXECUTABLE || + gt->GetType() == cmStateEnums::SHARED_LIBRARY || + gt->GetType() == cmStateEnums::MODULE_LIBRARY) && + ((libItem.Target && + (!libItem.Target->IsImported() || forceLinkPhase) && + (libItem.Target->GetType() == cmStateEnums::STATIC_LIBRARY || + libItem.Target->GetType() == cmStateEnums::SHARED_LIBRARY || + libItem.Target->GetType() == cmStateEnums::MODULE_LIBRARY || + libItem.Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY)) || + (!libItem.Target && libItem.IsPath && forceLinkPhase))) { + std::string libName; + bool canUseLinkPhase = true; + if (libItem.Target) { + if (libItem.Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY) { + canUseLinkPhase = canUseLinkPhase && forceLinkPhase; + } else { + // If a library target uses custom build output directory Xcode + // won't pick it up so we have to resort back to linker flags, but + // that's OK as long as the custom output dir is absolute path. + for (auto const& libConfigName : this->CurrentConfigurationTypes) { + canUseLinkPhase = canUseLinkPhase && + libItem.Target->UsesDefaultOutputDir( + libConfigName, cmStateEnums::RuntimeBinaryArtifact); + } + } + libName = libItem.Target->GetName(); + } else { + libName = cmSystemTools::GetFilenameName(libItem.Value.Value); + // We don't want all the possible files here, just standard libraries + const auto libExt = cmSystemTools::GetFilenameExtension(libName); + if (!IsLinkPhaseLibraryExtension(libExt)) { + canUseLinkPhase = false; + } + } + if (canUseLinkPhase) { + // Add unique configuration name to target-config map for later + // checks + auto& configVector = targetConfigMap[libName]; + if (std::find(configVector.begin(), configVector.end(), + configName) == configVector.end()) { + configVector.push_back(configName); + } + // Add a pair of config and item to target-item map + auto& itemVector = targetItemMap[libName]; + itemVector.emplace_back(ConfigItemPair(configName, &libItem)); + // Add product file-name to a lib-product map + auto productName = + cmSystemTools::GetFilenameName(libItem.Value.Value); + auto& productVector = targetProductNameMap[libName]; + if (std::find(productVector.begin(), productVector.end(), + productName) == productVector.end()) { + productVector.push_back(productName); + } + continue; + } + } + // Add this library item to a regular linker flag list + addToLinkerArguments(configName, &libItem); + } + } + + // Go through target library map and separate libraries that are linked + // in all configurations and produce only single product, from the rest. + // Only these will be linked through "Link Binary With Libraries" build + // phase. + for (auto const& targetLibConfigs : targetConfigMap) { + // Add this library to "Link Binary With Libraries" build phase if it's + // linked in all configurations and it has only one product name + auto& itemVector = targetItemMap[targetLibConfigs.first]; + auto& productVector = targetProductNameMap[targetLibConfigs.first]; + if (targetLibConfigs.second == this->CurrentConfigurationTypes && + productVector.size() == 1) { + // Add this library to "Link Binary With Libraries" list + linkPhaseTargetVector.push_back(itemVector[0].second); + } else { + for (auto const& libItem : targetItemMap[targetLibConfigs.first]) { + // Add this library item to a regular linker flag list + addToLinkerArguments(libItem.first, libItem.second); + } + } + } + + // Add libraries to "Link Binary With Libraries" build phase and collect + // their search paths. Xcode does not support per-configuration linking + // in this build phase so we don't have to do this for each configuration + // separately. + std::vector<std::string> linkSearchPaths; + std::vector<std::string> frameworkSearchPaths; + for (auto const& libItem : linkPhaseTargetVector) { + // Add target output directory as a library search path + std::string linkDir; + if (libItem->Target) { + linkDir = libItem->Target->GetLocationForBuild(); + } else { + linkDir = libItem->Value.Value; + } + linkDir = GetLibraryOrFrameworkPath(linkDir); + bool isFramework = cmSystemTools::IsPathToFramework(linkDir); + linkDir = cmSystemTools::GetParentDirectory(linkDir); + if (isFramework) { + if (std::find(frameworkSearchPaths.begin(), frameworkSearchPaths.end(), + linkDir) == frameworkSearchPaths.end()) { + frameworkSearchPaths.push_back(linkDir); + } + } else { + if (std::find(linkSearchPaths.begin(), linkSearchPaths.end(), linkDir) == + linkSearchPaths.end()) { + linkSearchPaths.push_back(linkDir); + } + } + // Add target dependency + if (libItem->Target && !libItem->Target->IsImported()) { + for (auto const& configName : this->CurrentConfigurationTypes) { + target->AddDependTarget(configName, libItem->Target->GetName()); + } + } + // Get the library target + auto* libTarget = FindXCodeTarget(libItem->Target); + cmXCodeObject* buildFile; + if (!libTarget) { + if (libItem->IsPath) { + // Get or create a direct file ref in the root project + auto it = this->ExternalLibRefs.find(libItem->Value.Value); + if (it == this->ExternalLibRefs.end()) { + buildFile = CreateXCodeBuildFileFromPath(libItem->Value.Value, gt, + "", nullptr); + if (!buildFile) { + // Add this library item back to a regular linker flag list + for (const auto& conf : configItemMap) { + addToLinkerArguments(conf.first, libItem); + } + continue; + } + this->ExternalLibRefs.emplace(libItem->Value.Value, buildFile); + } else { + buildFile = it->second; + } + } else { + // Add this library item back to a regular linker flag list + for (const auto& conf : configItemMap) { + addToLinkerArguments(conf.first, libItem); + } + continue; + } + } else { + // Add the target output file as a build reference for other targets + // to link against + auto* fileRefObject = libTarget->GetAttribute("productReference"); + if (!fileRefObject) { + // Add this library item back to a regular linker flag list + for (const auto& conf : configItemMap) { + addToLinkerArguments(conf.first, libItem); + } + continue; + } + auto it = FileRefToBuildFileMap.find(fileRefObject); + if (it == FileRefToBuildFileMap.end()) { + buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); + buildFile->AddAttribute("fileRef", fileRefObject); + FileRefToBuildFileMap[fileRefObject] = buildFile; + } else { + buildFile = it->second; + } + } + // Add this reference to current target + auto* buildPhases = target->GetAttribute("buildPhases"); + if (!buildPhases) { + cmSystemTools::Error("Missing buildPhase of target"); + continue; + } + auto* frameworkBuildPhase = + buildPhases->GetObject(cmXCodeObject::PBXFrameworksBuildPhase); + if (!frameworkBuildPhase) { + cmSystemTools::Error("Missing PBXFrameworksBuildPhase of buildPhase"); + continue; + } + auto* buildFiles = frameworkBuildPhase->GetAttribute("files"); + if (!buildFiles) { + cmSystemTools::Error("Missing files of PBXFrameworksBuildPhase"); + continue; + } + if (buildFile && !buildFiles->HasObject(buildFile)) { + buildFiles->AddObject(buildFile); + } + } + // Loop over configuration types and set per-configuration info. for (auto const& configName : this->CurrentConfigurationTypes) { { // Add object library contents as link flags. - std::string linkObjs; - const char* sep = ""; + BuildObjectListOrString libSearchPaths(this, true); std::vector<cmSourceFile const*> objs; gt->GetExternalObjects(objs, configName); for (auto sourceFile : objs) { if (sourceFile->GetObjectLibrary().empty()) { continue; } - linkObjs += sep; - sep = " "; - linkObjs += this->XCodeEscapePath(sourceFile->GetFullPath()); + libSearchPaths.Add(this->XCodeEscapePath(sourceFile->GetFullPath())); } this->AppendBuildSettingAttribute( - target, this->GetTargetLinkFlagsVar(gt), linkObjs.c_str(), configName); + target, this->GetTargetLinkFlagsVar(gt), libSearchPaths.CreateList(), + configName); } // Skip link information for object libraries. @@ -2795,55 +3186,82 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) } // Compute the link library and directory information. - cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); - if (!pcli) { + cmComputeLinkInformation* cli = gt->GetLinkInformation(configName); + if (!cli) { continue; } - cmComputeLinkInformation& cli = *pcli; // Add dependencies directly on library files. - for (auto const& libDep : cli.GetDepends()) { + for (auto const& libDep : cli->GetDepends()) { target->AddDependLibrary(configName, libDep); } // add the library search paths { + BuildObjectListOrString libSearchPaths(this, true); std::string linkDirs; - for (auto const& libDir : cli.GetDirectories()) { + for (auto const& libDir : cli->GetDirectories()) { if (!libDir.empty() && libDir != "/usr/lib") { - // Now add the same one but append - // $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it: - linkDirs += " "; - linkDirs += this->XCodeEscapePath( - libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"); - linkDirs += " "; - linkDirs += this->XCodeEscapePath(libDir); + libSearchPaths.Add(this->XCodeEscapePath( + libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)")); + libSearchPaths.Add(this->XCodeEscapePath(libDir)); } } + // Add previously collected paths where to look for libraries + // that were added to "Link Binary With Libraries" + for (auto& libDir : linkSearchPaths) { + libSearchPaths.Add(this->XCodeEscapePath(libDir)); + } this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS", - linkDirs.c_str(), configName); + libSearchPaths.CreateList(), + configName); + } + + // add framework search paths + { + BuildObjectListOrString fwSearchPaths(this, true); + // Add previously collected paths where to look for frameworks + // that were added to "Link Binary With Libraries" + for (auto& fwDir : frameworkSearchPaths) { + fwSearchPaths.Add(this->XCodeEscapePath(fwDir)); + } + this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS", + fwSearchPaths.CreateList(), + configName); } - // now add the link libraries + // now add the left-over link libraries { - std::string linkLibs; - const char* sep = ""; - for (auto const& libName : cli.GetItems()) { - linkLibs += sep; - sep = " "; + BuildObjectListOrString libPaths(this, true); + for (auto const& libItem : configItemMap[configName]) { + auto const& libName = *libItem; if (libName.IsPath) { - linkLibs += this->XCodeEscapePath(libName.Value.Value); + libPaths.Add(this->XCodeEscapePath(libName.Value.Value)); + const auto libPath = GetLibraryOrFrameworkPath(libName.Value.Value); + if ((!libName.Target || libName.Target->IsImported()) && + IsLinkPhaseLibraryExtension(libPath)) { + // Create file reference for embedding + auto it = this->ExternalLibRefs.find(libName.Value.Value); + if (it == this->ExternalLibRefs.end()) { + auto* buildFile = this->CreateXCodeBuildFileFromPath( + libName.Value.Value, gt, "", nullptr); + if (buildFile) { + this->ExternalLibRefs.emplace(libName.Value.Value, buildFile); + } + } + } } else if (!libName.Target || libName.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - linkLibs += libName.Value.Value; + libPaths.Add(libName.Value.Value); } if (libName.Target && !libName.Target->IsImported()) { target->AddDependTarget(configName, libName.Target->GetName()); } } - this->AppendBuildSettingAttribute( - target, this->GetTargetLinkFlagsVar(gt), linkLibs.c_str(), configName); + this->AppendBuildSettingAttribute(target, + this->GetTargetLinkFlagsVar(gt), + libPaths.CreateList(), configName); } } } @@ -2859,13 +3277,9 @@ bool cmGlobalXCodeGenerator::CreateGroups( // end up with (empty anyhow) ZERO_CHECK, install, or test source // groups: // - if (gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { - continue; - } - if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - continue; - } - if (gtgt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) { + if (!gtgt->IsInBuildSystem() || + gtgt->GetType() == cmStateEnums::GLOBAL_TARGET || + gtgt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) { continue; } @@ -2915,7 +3329,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreatePBXGroup(cmXCodeObject* parent, { cmXCodeObject* parentChildren = nullptr; if (parent) { - parentChildren = parent->GetObject("children"); + parentChildren = parent->GetAttribute("children"); } cmXCodeObject* group = this->CreateObject(cmXCodeObject::PBXGroup); cmXCodeObject* groupChildren = @@ -3009,6 +3423,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->ClearXCodeObjects(); this->RootObject = nullptr; this->MainGroupChildren = nullptr; + this->FrameworkGroup = nullptr; cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO")); cmXCodeObject* listObjs = this->CreateObject(cmXCodeObject::OBJECT_LIST); @@ -3043,6 +3458,15 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( productGroup->AddAttribute("children", productGroupChildren); this->MainGroupChildren->AddObject(productGroup); + this->FrameworkGroup = this->CreateObject(cmXCodeObject::PBXGroup); + this->FrameworkGroup->AddAttribute("name", this->CreateString("Frameworks")); + this->FrameworkGroup->AddAttribute("sourceTree", + this->CreateString("<group>")); + cmXCodeObject* frameworkGroupChildren = + this->CreateObject(cmXCodeObject::OBJECT_LIST); + this->FrameworkGroup->AddAttribute("children", frameworkGroupChildren); + this->MainGroupChildren->AddObject(this->FrameworkGroup); + this->RootObject = this->CreateObject(cmXCodeObject::PBXProject); this->RootObject->SetComment("Project object"); @@ -3106,12 +3530,11 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->CreateString(defaultConfigName)); cmXCodeObject* buildSettings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); - const char* sysroot = - this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT"); - const char* deploymentTarget = + cmProp sysroot = this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT"); + cmProp deploymentTarget = this->CurrentMakefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET"); if (sysroot) { - buildSettings->AddAttribute("SDKROOT", this->CreateString(sysroot)); + buildSettings->AddAttribute("SDKROOT", this->CreateString(*sysroot)); } // recompute this as it may have been changed since enable language this->ComputeArchitectures(this->CurrentMakefile); @@ -3121,8 +3544,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( buildSettings->AddAttribute("ONLY_ACTIVE_ARCH", this->CreateString("YES")); // When targeting macOS, use only the host architecture. if (this->SystemName == "Darwin"_s && - (!sysroot || !*sysroot || - cmSystemTools::LowerCase(sysroot).find("macos") != + (!cmNonempty(sysroot) || + cmSystemTools::LowerCase(*sysroot).find("macos") != std::string::npos)) { buildSettings->AddAttribute("ARCHS", this->CreateString("$(NATIVE_ARCH_ACTUAL)")); @@ -3131,9 +3554,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( // Tell Xcode to use ARCHS (ONLY_ACTIVE_ARCH defaults to NO). buildSettings->AddAttribute("ARCHS", this->CreateString(archs)); } - if (deploymentTarget && *deploymentTarget) { + if (cmNonempty(deploymentTarget)) { buildSettings->AddAttribute(GetDeploymentPlatform(root->GetMakefile()), - this->CreateString(deploymentTarget)); + this->CreateString(*deploymentTarget)); } if (!this->GeneratorToolset.empty()) { buildSettings->AddAttribute("GCC_VERSION", @@ -3141,9 +3564,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( } if (this->GetLanguageEnabled("Swift")) { std::string swiftVersion; - if (const char* vers = this->CurrentMakefile->GetDefinition( + if (cmProp vers = this->CurrentMakefile->GetDefinition( "CMAKE_Swift_LANGUAGE_VERSION")) { - swiftVersion = vers; + swiftVersion = *vers; } else if (this->XcodeVersion >= 102) { swiftVersion = "4.0"; } else if (this->XcodeVersion >= 83) { @@ -3204,7 +3627,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST); for (auto t : targets) { allTargets->AddObject(t); - cmXCodeObject* productRef = t->GetObject("productReference"); + cmXCodeObject* productRef = t->GetAttribute("productReference"); if (productRef) { productGroupChildren->AddObject(productRef->GetObject()); } @@ -3226,7 +3649,7 @@ std::string cmGlobalXCodeGenerator::GetObjectsDirectory( void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf) { this->Architectures.clear(); - const char* sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT"); + cmProp sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT"); if (sysroot) { mf->GetDefExpandList("CMAKE_OSX_ARCHITECTURES", this->Architectures); } @@ -3235,8 +3658,8 @@ void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf) // With no ARCHS we use ONLY_ACTIVE_ARCH and possibly a // platform-specific default ARCHS placeholder value. // Look up the arch that Xcode chooses in this case. - if (const char* arch = mf->GetDefinition("CMAKE_XCODE_ARCHS")) { - this->ObjectDirArchDefault = arch; + if (cmProp arch = mf->GetDefinition("CMAKE_XCODE_ARCHS")) { + this->ObjectDirArchDefault = *arch; // We expect only one arch but choose the first just in case. std::string::size_type pos = this->ObjectDirArchDefault.find(';'); if (pos != std::string::npos) { @@ -3602,9 +4025,9 @@ std::string cmGlobalXCodeGenerator::LookupFlags( { if (!varNameLang.empty()) { std::string varName = cmStrCat(varNamePrefix, varNameLang, varNameSuffix); - if (const char* varValue = this->CurrentMakefile->GetDefinition(varName)) { - if (*varValue) { - return varValue; + if (cmProp varValue = this->CurrentMakefile->GetDefinition(varName)) { + if (!varValue->empty()) { + return *varValue; } } } diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index e2d1b3a..c7524e8 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalXCodeGenerator_h -#define cmGlobalXCodeGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -28,7 +27,7 @@ struct cmDocumentationEntry; /** \class cmGlobalXCodeGenerator * \brief Write a Unix makefiles. * - * cmGlobalXCodeGenerator manages UNIX build process for a tree + * cmGlobalXCodeGenerator manages Xcode build process for a tree */ class cmGlobalXCodeGenerator : public cmGlobalGenerator { @@ -116,8 +115,6 @@ public: protected: void AddExtraIDETargets() override; - void ComputeTargetOrder(); - void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index); void Generate() override; private: @@ -168,9 +165,9 @@ private: std::string AddConfigurations(cmXCodeObject* target, cmGeneratorTarget* gtgt); void AppendOrAddBuildSetting(cmXCodeObject* settings, const char* attr, - const char* value); + cmXCodeObject* value); void AppendBuildSettingAttribute(cmXCodeObject* target, const char* attr, - const char* value, + cmXCodeObject* value, const std::string& configName); cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt); void AddDependAndLinkInformation(cmXCodeObject* target); @@ -204,10 +201,10 @@ private: cmGeneratorTarget* target, const std::string& lang, cmSourceFile* sf); - cmXCodeObject* CreateXCodeSourceFileFromPath(const std::string& fullpath, - cmGeneratorTarget* target, - const std::string& lang, - cmSourceFile* sf); + cmXCodeObject* CreateXCodeBuildFileFromPath(const std::string& fullpath, + cmGeneratorTarget* target, + const std::string& lang, + cmSourceFile* sf); cmXCodeObject* CreateXCodeFileReference(cmSourceFile* sf, cmGeneratorTarget* target); cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen, cmSourceFile* sf, @@ -282,6 +279,7 @@ private: std::string PostBuildMakeTarget(std::string const& tName, std::string const& configName); cmXCodeObject* MainGroupChildren; + cmXCodeObject* FrameworkGroup; cmMakefile* CurrentMakefile; cmLocalGenerator* CurrentLocalGenerator; std::vector<std::string> CurrentConfigurationTypes; @@ -295,13 +293,15 @@ private: std::map<std::string, cmXCodeObject*> GroupNameMap; std::map<std::string, cmXCodeObject*> TargetGroup; std::map<std::string, cmXCodeObject*> FileRefs; + std::map<std::string, cmXCodeObject*> ExternalLibRefs; std::map<cmGeneratorTarget const*, cmXCodeObject*> XCodeObjectMap; + std::map<cmXCodeObject*, cmXCodeObject*> FileRefToBuildFileMap; std::vector<std::string> Architectures; std::string ObjectDirArchDefault; std::string ObjectDirArch; std::string SystemName; std::string GeneratorToolset; - std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex; + std::vector<std::string> EnabledLangs; + std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>> + CommandsVisited; }; - -#endif diff --git a/Source/cmGraphAdjacencyList.h b/Source/cmGraphAdjacencyList.h index 4e1f128..fe9fbe2 100644 --- a/Source/cmGraphAdjacencyList.h +++ b/Source/cmGraphAdjacencyList.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGraphAdjacencyList_h -#define cmGraphAdjacencyList_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -48,5 +47,3 @@ struct cmGraphNodeList : public std::vector<int> struct cmGraphAdjacencyList : public std::vector<cmGraphEdgeList> { }; - -#endif diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index c23156d..cf4ba93 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGraphVizWriter.h" +#include <algorithm> #include <cctype> #include <iostream> #include <memory> @@ -16,6 +17,7 @@ #include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" @@ -125,14 +127,6 @@ cmGraphVizWriter::cmGraphVizWriter(std::string const& fileName, cmGraphVizWriter::~cmGraphVizWriter() { this->WriteFooter(this->GlobalFileStream); - - for (auto& fileStream : this->PerTargetFileStreams) { - this->WriteFooter(*fileStream.second); - } - - for (auto& fileStream : this->TargetDependersFileStreams) { - this->WriteFooter(*fileStream.second); - } } void cmGraphVizWriter::VisitGraph(std::string const&) @@ -151,20 +145,10 @@ void cmGraphVizWriter::OnItem(cmLinkItem const& item) ++NextNodeId; this->WriteNode(this->GlobalFileStream, item); - - if (this->GeneratePerTarget) { - this->CreateTargetFile(this->PerTargetFileStreams, item); - } - - if (this->GenerateDependers) { - this->CreateTargetFile(this->TargetDependersFileStreams, item, - ".dependers"); - } } -void cmGraphVizWriter::CreateTargetFile(FileStreamMap& fileStreamMap, - cmLinkItem const& item, - std::string const& fileNameSuffix) +std::unique_ptr<cmGeneratedFileStream> cmGraphVizWriter::CreateTargetFile( + cmLinkItem const& item, std::string const& fileNameSuffix) { auto const pathSafeItemName = PathSafeString(item.AsStr()); auto const perTargetFileName = @@ -175,7 +159,7 @@ void cmGraphVizWriter::CreateTargetFile(FileStreamMap& fileStreamMap, this->WriteHeader(*perTargetFileStream, item.AsStr()); this->WriteNode(*perTargetFileStream, item); - fileStreamMap.emplace(item.AsStr(), std::move(perTargetFileStream)); + return perTargetFileStream; } void cmGraphVizWriter::OnDirectLink(cmLinkItem const& depender, @@ -246,9 +230,9 @@ void cmGraphVizWriter::ReadSettings( #define __set_if_set(var, cmakeDefinition) \ do { \ - const char* value = mf.GetDefinition(cmakeDefinition); \ + cmProp value = mf.GetDefinition(cmakeDefinition); \ if (value) { \ - (var) = value; \ + (var) = *value; \ } \ } while (false) @@ -258,9 +242,9 @@ void cmGraphVizWriter::ReadSettings( #define __set_bool_if_set(var, cmakeDefinition) \ do { \ - const char* value = mf.GetDefinition(cmakeDefinition); \ + cmProp value = mf.GetDefinition(cmakeDefinition); \ if (value) { \ - (var) = mf.IsOn(cmakeDefinition); \ + (var) = cmIsOn(*value); \ } \ } while (false) @@ -323,13 +307,12 @@ void cmGraphVizWriter::Write() } if (this->GeneratePerTarget) { - WritePerTargetConnections<DependeesDir>(PerTargetConnections, - PerTargetFileStreams); + WritePerTargetConnections<DependeesDir>(PerTargetConnections); } if (this->GenerateDependers) { WritePerTargetConnections<DependersDir>(TargetDependersConnections, - TargetDependersFileStreams); + ".dependers"); } } @@ -368,7 +351,7 @@ void cmGraphVizWriter::FindAllConnections(const ConnectionsMap& connectionMap, template <typename DirFunc> void cmGraphVizWriter::WritePerTargetConnections( - const ConnectionsMap& connections, const FileStreamMap& streams) + const ConnectionsMap& connections, const std::string& fileNameSuffix) { // the per target connections must be extended by indirect dependencies ConnectionsMap extendedConnections; @@ -387,7 +370,9 @@ void cmGraphVizWriter::WritePerTargetConnections( } const Connections& cons = conPerTarget.second; - auto fileStream = streams.at(rootItem.AsStr()).get(); + + std::unique_ptr<cmGeneratedFileStream> fileStream = + this->CreateTargetFile(rootItem, fileNameSuffix); for (const Connection& con : cons) { const cmLinkItem& src = DirFunc::src(con); @@ -395,6 +380,8 @@ void cmGraphVizWriter::WritePerTargetConnections( this->WriteNode(*fileStream, con.dst); this->WriteConnection(*fileStream, src, dst, con.scopeType); } + + this->WriteFooter(*fileStream); } } @@ -567,16 +554,23 @@ bool cmGraphVizWriter::TargetTypeEnabled( std::string cmGraphVizWriter::ItemNameWithAliases( std::string const& itemName) const { - auto nameWithAliases = itemName; - + std::vector<std::string> items; for (auto const& lg : this->GlobalGenerator->GetLocalGenerators()) { for (auto const& aliasTargets : lg->GetMakefile()->GetAliasTargets()) { if (aliasTargets.second == itemName) { - nameWithAliases += "\\n(" + aliasTargets.first + ")"; + items.push_back(aliasTargets.first); } } } + std::sort(items.begin(), items.end()); + items.erase(std::unique(items.begin(), items.end()), items.end()); + + auto nameWithAliases = itemName; + for(auto const& item : items) { + nameWithAliases += "\\n(" + item + ")"; + } + return nameWithAliases; } diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h index 9766068..0912fc8 100644 --- a/Source/cmGraphVizWriter.h +++ b/Source/cmGraphVizWriter.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef CMGRAPHVIZWRITER_H -#define CMGRAPHVIZWRITER_H +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -46,9 +45,6 @@ public: void Write(); private: - using FileStreamMap = - std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>; - struct Connection { Connection(cmLinkItem s, cmLinkItem d, std::string scope) @@ -76,8 +72,8 @@ private: void WriteNode(cmGeneratedFileStream& fs, cmLinkItem const& item); - void CreateTargetFile(FileStreamMap& fileStreamMap, cmLinkItem const& target, - std::string const& fileNameSuffix = ""); + std::unique_ptr<cmGeneratedFileStream> CreateTargetFile( + cmLinkItem const& target, std::string const& fileNameSuffix = ""); void WriteConnection(cmGeneratedFileStream& fs, cmLinkItem const& dependerTargetName, @@ -95,7 +91,7 @@ private: template <typename DirFunc> void WritePerTargetConnections(const ConnectionsMap& connections, - const FileStreamMap& streams); + const std::string& fileNameSuffix = ""); bool ItemExcluded(cmLinkItem const& item); bool ItemNameFilteredOut(std::string const& itemName); @@ -111,8 +107,6 @@ private: std::string FileName; cmGeneratedFileStream GlobalFileStream; - FileStreamMap PerTargetFileStreams; - FileStreamMap TargetDependersFileStreams; ConnectionsMap PerTargetConnections; ConnectionsMap TargetDependersConnections; @@ -141,5 +135,3 @@ private: bool GeneratePerTarget; bool GenerateDependers; }; - -#endif diff --git a/Source/cmHexFileConverter.h b/Source/cmHexFileConverter.h index 26f9ea8..35a91ed 100644 --- a/Source/cmHexFileConverter.h +++ b/Source/cmHexFileConverter.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmHexFileConverter_h -#define cmHexFileConverter_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -25,5 +24,3 @@ public: static bool TryConvert(const std::string& inFileName, const std::string& outFileName); }; - -#endif diff --git a/Source/cmIDEFlagTable.h b/Source/cmIDEFlagTable.h index ff93432..5901771 100644 --- a/Source/cmIDEFlagTable.h +++ b/Source/cmIDEFlagTable.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmIDEFlagTable_h -#define cmIDEFlagTable_h +#pragma once #include <string> @@ -37,5 +36,3 @@ struct cmIDEFlagTable UserValueRequired = UserValue | UserRequired }; }; - -#endif diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h index f949ae3..fbe9c37 100644 --- a/Source/cmIDEOptions.h +++ b/Source/cmIDEOptions.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmIDEOptions_h -#define cmIDEOptions_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -112,5 +111,3 @@ protected: std::string const& new_value); virtual void StoreUnknownFlag(std::string const& flag) = 0; }; - -#endif diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h index 820ffa4..f056587 100644 --- a/Source/cmIfCommand.h +++ b/Source/cmIfCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmIfCommand_h -#define cmIfCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -13,5 +12,3 @@ struct cmListFileArgument; /// Starts an if block bool cmIfCommand(std::vector<cmListFileArgument> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmIncludeCommand.h b/Source/cmIncludeCommand.h index b0dd779..af26163 100644 --- a/Source/cmIncludeCommand.h +++ b/Source/cmIncludeCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmIncludeCommand_h -#define cmIncludeCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -18,5 +17,3 @@ class cmExecutionStatus; */ bool cmIncludeCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h index 66caff7..d830dbf 100644 --- a/Source/cmIncludeDirectoryCommand.h +++ b/Source/cmIncludeDirectoryCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmIncludeDirectoryCommand_h -#define cmIncludeDirectoryCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmIncludeDirectoryCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmIncludeExternalMSProjectCommand.h b/Source/cmIncludeExternalMSProjectCommand.h index 1013c44..fd77407 100644 --- a/Source/cmIncludeExternalMSProjectCommand.h +++ b/Source/cmIncludeExternalMSProjectCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmIncludeExternalMSProjectCommand_h -#define cmIncludeExternalMSProjectCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmIncludeExternalMSProjectCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmIncludeGuardCommand.cxx b/Source/cmIncludeGuardCommand.cxx index ccb4496..aefd098 100644 --- a/Source/cmIncludeGuardCommand.cxx +++ b/Source/cmIncludeGuardCommand.cxx @@ -75,7 +75,7 @@ bool cmIncludeGuardCommand(std::vector<std::string> const& args, } std::string includeGuardVar = GetIncludeGuardVariableName( - status.GetMakefile().GetDefinition("CMAKE_CURRENT_LIST_FILE")); + *status.GetMakefile().GetDefinition("CMAKE_CURRENT_LIST_FILE")); cmMakefile* const mf = &status.GetMakefile(); diff --git a/Source/cmIncludeGuardCommand.h b/Source/cmIncludeGuardCommand.h index b86b760..c4de3d4 100644 --- a/Source/cmIncludeGuardCommand.h +++ b/Source/cmIncludeGuardCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmIncludeGuardCommand_h -#define cmIncludeGuardCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -18,5 +17,3 @@ class cmExecutionStatus; */ bool cmIncludeGuardCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmIncludeRegularExpressionCommand.h b/Source/cmIncludeRegularExpressionCommand.h index ca152b0..a402f97 100644 --- a/Source/cmIncludeRegularExpressionCommand.h +++ b/Source/cmIncludeRegularExpressionCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmIncludeRegularExpressionCommand_h -#define cmIncludeRegularExpressionCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmIncludeRegularExpressionCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 178af73..83609e2 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -680,7 +680,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) { cmProp files = target.GetProperty("PRIVATE_HEADER"); - if (files && !files->empty()) { + if (cmNonempty(files)) { std::vector<std::string> relFiles = cmExpandedList(*files); std::vector<std::string> absFiles; if (!helper.MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) { @@ -702,7 +702,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, } files = target.GetProperty("PUBLIC_HEADER"); - if (files && !files->empty()) { + if (cmNonempty(files)) { std::vector<std::string> relFiles = cmExpandedList(*files); std::vector<std::string> absFiles; if (!helper.MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) { @@ -724,7 +724,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, } files = target.GetProperty("RESOURCE"); - if (files && !files->empty()) { + if (cmNonempty(files)) { std::vector<std::string> relFiles = cmExpandedList(*files); std::vector<std::string> absFiles; if (!helper.MakeFilesFullPath("RESOURCE", relFiles, absFiles)) { @@ -1157,7 +1157,7 @@ bool HandleDirectoryMode(std::vector<std::string> const& args, } else if (doing == DoingRegex) { literal_args += " REGEX \""; // Match rules are case-insensitive on some platforms. -#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__) +#if defined(_WIN32) || defined(__APPLE__) std::string regex = cmSystemTools::LowerCase(args[i]); #else std::string regex = args[i]; diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 32f00ce..f0ba44e 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallCommand_h -#define cmInstallCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmInstallCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h index 5d2ee0a..f318a1a 100644 --- a/Source/cmInstallCommandArguments.h +++ b/Source/cmInstallCommandArguments.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallCommandArguments_h -#define cmInstallCommandArguments_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -72,5 +71,3 @@ public: private: std::vector<std::string> IncludeDirs; }; - -#endif diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h index bec89df..af310f3 100644 --- a/Source/cmInstallDirectoryGenerator.h +++ b/Source/cmInstallDirectoryGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallDirectoryGenerator_h -#define cmInstallDirectoryGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -48,5 +47,3 @@ protected: std::string const LiteralArguments; bool const Optional; }; - -#endif diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index 43dd00d..dd8624b 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallExportGenerator_h -#define cmInstallExportGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -68,5 +67,3 @@ protected: std::string MainImportFile; std::unique_ptr<cmExportInstallFileGenerator> EFGen; }; - -#endif diff --git a/Source/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h index f4ebbde..219bb97 100644 --- a/Source/cmInstallFilesCommand.h +++ b/Source/cmInstallFilesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallFilesCommand_h -#define cmInstallFilesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmInstallFilesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index 8266603..b5a1ef4 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallFilesGenerator_h -#define cmInstallFilesGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -48,5 +47,3 @@ protected: bool const Programs; bool const Optional; }; - -#endif diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index d786d24..ee55ee9 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallGenerator_h -#define cmInstallGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -74,5 +73,3 @@ protected: MessageLevel const Message; bool const ExcludeFromAll; }; - -#endif diff --git a/Source/cmInstallProgramsCommand.h b/Source/cmInstallProgramsCommand.h index c567f3b..e3c3e81 100644 --- a/Source/cmInstallProgramsCommand.h +++ b/Source/cmInstallProgramsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallProgramsCommand_h -#define cmInstallProgramsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmInstallProgramsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h index 0a9c4ba..338d866 100644 --- a/Source/cmInstallScriptGenerator.h +++ b/Source/cmInstallScriptGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallScriptGenerator_h -#define cmInstallScriptGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -38,5 +37,3 @@ protected: cmLocalGenerator* LocalGenerator; bool AllowGenex; }; - -#endif diff --git a/Source/cmInstallSubdirectoryGenerator.h b/Source/cmInstallSubdirectoryGenerator.h index f9cd0f1..3e46d6b 100644 --- a/Source/cmInstallSubdirectoryGenerator.h +++ b/Source/cmInstallSubdirectoryGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallSubdirectoryGenerator_h -#define cmInstallSubdirectoryGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -37,5 +36,3 @@ protected: std::string const BinaryDirectory; cmLocalGenerator* LocalGenerator; }; - -#endif diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 178d5df..b3da202 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -820,7 +820,7 @@ void cmInstallTargetGenerator::AddStripRule(std::ostream& os, Indent indent, os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n"; os << indent << " execute_process(COMMAND \"" - << this->Target->Target->GetMakefile()->GetDefinition("CMAKE_STRIP") + << this->Target->Target->GetMakefile()->GetSafeDefinition("CMAKE_STRIP") << "\" " << stripArgs << "\"" << toDestDirPath << "\")\n"; os << indent << "endif()\n"; } @@ -858,9 +858,9 @@ void cmInstallTargetGenerator::AddUniversalInstallRule( return; } - const char* xcodeVersion = mf->GetDefinition("XCODE_VERSION"); + cmProp xcodeVersion = mf->GetDefinition("XCODE_VERSION"); if (!xcodeVersion || - cmSystemTools::VersionCompareGreater("6", xcodeVersion)) { + cmSystemTools::VersionCompareGreater("6", *xcodeVersion)) { return; } diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index e21001f..a53a75a 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallTargetGenerator_h -#define cmInstallTargetGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -114,5 +113,3 @@ protected: bool const Optional; cmListFileBacktrace const Backtrace; }; - -#endif diff --git a/Source/cmInstallTargetsCommand.h b/Source/cmInstallTargetsCommand.h index 0c5850c..716e7ce 100644 --- a/Source/cmInstallTargetsCommand.h +++ b/Source/cmInstallTargetsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallTargetsCommand_h -#define cmInstallTargetsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmInstallTargetsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmInstallType.h b/Source/cmInstallType.h index e2602cb..33fa7a9 100644 --- a/Source/cmInstallType.h +++ b/Source/cmInstallType.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstallType_h -#define cmInstallType_h +#pragma once /** * Enumerate types known to file(INSTALL). @@ -16,5 +15,3 @@ enum cmInstallType cmInstallType_PROGRAMS, cmInstallType_DIRECTORY }; - -#endif diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h index 07f7081..82474f5 100644 --- a/Source/cmInstalledFile.h +++ b/Source/cmInstalledFile.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmInstalledFile_h -#define cmInstalledFile_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -76,5 +75,3 @@ private: CompiledGeneratorExpressionPtrType NameExpression; PropertyMapType Properties; }; - -#endif diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h new file mode 100644 index 0000000..2da2a03 --- /dev/null +++ b/Source/cmJSONHelpers.h @@ -0,0 +1,304 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include <algorithm> +#include <cstddef> +#include <functional> +#include <map> +#include <string> +#include <vector> + +#include <cm/optional> +#include <cm/string_view> + +#include <cm3p/json/value.h> + +template <typename T, typename E> +using cmJSONHelper = std::function<E(T& out, const Json::Value* value)>; + +template <typename T, typename E> +class cmJSONObjectHelper +{ +public: + cmJSONObjectHelper(E&& success, E&& fail, bool allowExtra = true); + + template <typename U, typename M, typename F> + cmJSONObjectHelper& Bind(const cm::string_view& name, M U::*member, F func, + bool required = true); + template <typename M, typename F> + cmJSONObjectHelper& Bind(const cm::string_view& name, std::nullptr_t, F func, + bool required = true); + + E operator()(T& out, const Json::Value* value) const; + +private: + // Not a true cmJSONHelper, it just happens to match the signature + using MemberFunction = std::function<E(T& out, const Json::Value* value)>; + struct Member + { + cm::string_view Name; + MemberFunction Function; + bool Required; + }; + std::vector<Member> Members; + bool AnyRequired = false; + E Success; + E Fail; + bool AllowExtra; + + cmJSONObjectHelper& BindPrivate(const cm::string_view& name, + MemberFunction&& func, bool required); +}; + +template <typename T, typename E> +cmJSONObjectHelper<T, E>::cmJSONObjectHelper(E&& success, E&& fail, + bool allowExtra) + : Success(std::move(success)) + , Fail(std::move(fail)) + , AllowExtra(allowExtra) +{ +} + +template <typename T, typename E> +template <typename U, typename M, typename F> +cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind( + const cm::string_view& name, M U::*member, F func, bool required) +{ + return this->BindPrivate( + name, + [func, member](T& out, const Json::Value* value) -> E { + return func(out.*member, value); + }, + required); +} + +template <typename T, typename E> +template <typename M, typename F> +cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind( + const cm::string_view& name, std::nullptr_t, F func, bool required) +{ + return this->BindPrivate(name, + [func](T& /*out*/, const Json::Value* value) -> E { + M dummy; + return func(dummy, value); + }, + required); +} + +template <typename T, typename E> +cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::BindPrivate( + const cm::string_view& name, MemberFunction&& func, bool required) +{ + Member m; + m.Name = name; + m.Function = std::move(func); + m.Required = required; + this->Members.push_back(std::move(m)); + if (required) { + this->AnyRequired = true; + } + return *this; +} + +template <typename T, typename E> +E cmJSONObjectHelper<T, E>::operator()(T& out, const Json::Value* value) const +{ + if (!value && this->AnyRequired) { + return this->Fail; + } + if (value && !value->isObject()) { + return this->Fail; + } + Json::Value::Members extraFields; + if (value) { + extraFields = value->getMemberNames(); + } + + for (auto const& m : this->Members) { + std::string name(m.Name.data(), m.Name.size()); + if (value && value->isMember(name)) { + E result = m.Function(out, &(*value)[name]); + if (result != this->Success) { + return result; + } + extraFields.erase( + std::find(extraFields.begin(), extraFields.end(), name)); + } else if (!m.Required) { + E result = m.Function(out, nullptr); + if (result != this->Success) { + return result; + } + } else { + return this->Fail; + } + } + + return this->AllowExtra || extraFields.empty() ? this->Success : this->Fail; +} + +template <typename E> +cmJSONHelper<std::string, E> cmJSONStringHelper(E success, E fail, + const std::string& defval = "") +{ + return + [success, fail, defval](std::string& out, const Json::Value* value) -> E { + if (!value) { + out = defval; + return success; + } + if (!value->isString()) { + return fail; + } + out = value->asString(); + return success; + }; +} + +template <typename E> +cmJSONHelper<int, E> cmJSONIntHelper(E success, E fail, int defval = 0) +{ + return [success, fail, defval](int& out, const Json::Value* value) -> E { + if (!value) { + out = defval; + return success; + } + if (!value->isInt()) { + return fail; + } + out = value->asInt(); + return success; + }; +} + +template <typename E> +cmJSONHelper<unsigned int, E> cmJSONUIntHelper(E success, E fail, + unsigned int defval = 0) +{ + return + [success, fail, defval](unsigned int& out, const Json::Value* value) -> E { + if (!value) { + out = defval; + return success; + } + if (!value->isUInt()) { + return fail; + } + out = value->asUInt(); + return success; + }; +} + +template <typename E> +cmJSONHelper<bool, E> cmJSONBoolHelper(E success, E fail, bool defval = false) +{ + return [success, fail, defval](bool& out, const Json::Value* value) -> E { + if (!value) { + out = defval; + return success; + } + if (!value->isBool()) { + return fail; + } + out = value->asBool(); + return success; + }; +} + +template <typename T, typename E, typename F, typename Filter> +cmJSONHelper<std::vector<T>, E> cmJSONVectorFilterHelper(E success, E fail, + F func, Filter filter) +{ + return [success, fail, func, filter](std::vector<T>& out, + const Json::Value* value) -> E { + if (!value) { + out.clear(); + return success; + } + if (!value->isArray()) { + return fail; + } + out.clear(); + for (auto const& item : *value) { + T t; + E result = func(t, &item); + if (result != success) { + return result; + } + if (!filter(t)) { + continue; + } + out.push_back(t); + } + return success; + }; +} + +template <typename T, typename E, typename F> +cmJSONHelper<std::vector<T>, E> cmJSONVectorHelper(E success, E fail, F func) +{ + return cmJSONVectorFilterHelper<T, E, F>(success, fail, func, + [](const T&) { return true; }); +} + +template <typename T, typename E, typename F, typename Filter> +cmJSONHelper<std::map<std::string, T>, E> cmJSONMapFilterHelper(E success, + E fail, F func, + Filter filter) +{ + return [success, fail, func, filter](std::map<std::string, T>& out, + const Json::Value* value) -> E { + if (!value) { + out.clear(); + return success; + } + if (!value->isObject()) { + return fail; + } + out.clear(); + for (auto const& key : value->getMemberNames()) { + if (!filter(key)) { + continue; + } + T t; + E result = func(t, &(*value)[key]); + if (result != success) { + return result; + } + out[key] = std::move(t); + } + return success; + }; +} + +template <typename T, typename E, typename F> +cmJSONHelper<std::map<std::string, T>, E> cmJSONMapHelper(E success, E fail, + F func) +{ + return cmJSONMapFilterHelper<T, E, F>( + success, fail, func, [](const std::string&) { return true; }); +} + +template <typename T, typename E, typename F> +cmJSONHelper<cm::optional<T>, E> cmJSONOptionalHelper(E success, F func) +{ + return [success, func](cm::optional<T>& out, const Json::Value* value) -> E { + if (!value) { + out.reset(); + return success; + } + out.emplace(); + return func(*out, value); + }; +} + +template <typename T, typename E, typename F> +cmJSONHelper<T, E> cmJSONRequiredHelper(E fail, F func) +{ + return [fail, func](T& out, const Json::Value* value) -> E { + if (!value) { + return fail; + } + return func(out, value); + }; +} diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx index 9f17f15..3a7ae0c 100644 --- a/Source/cmJsonObjects.cxx +++ b/Source/cmJsonObjects.cxx @@ -51,11 +51,7 @@ std::vector<std::string> getConfigurations(const cmake* cm) return configurations; } - makefiles[0]->GetConfigurations(configurations); - if (configurations.empty()) { - configurations.emplace_back(); - } - return configurations; + return makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); } bool hasString(const Json::Value& v, const std::string& s) @@ -635,8 +631,8 @@ static Json::Value DumpProjectList(const cmake* cm, std::string const& config) // Project structure information: const cmMakefile* mf = lg->GetMakefile(); - auto minVersion = mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); - pObj[kMINIMUM_CMAKE_VERSION] = minVersion ? minVersion : ""; + auto minVersion = mf->GetSafeDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); + pObj[kMINIMUM_CMAKE_VERSION] = minVersion; pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory(); pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory(); pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config); diff --git a/Source/cmJsonObjects.h b/Source/cmJsonObjects.h index 2fd4b26..80a4834 100644 --- a/Source/cmJsonObjects.h +++ b/Source/cmJsonObjects.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmJsonObjects_h -#define cmJsonObjects_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -23,5 +22,3 @@ extern void cmGetCMakeInputs(const cmGlobalGenerator* gg, extern Json::Value cmDumpCodeModel(const cmake* cm); extern Json::Value cmDumpCTestInfo(const cmake* cm); extern Json::Value cmDumpCMakeInputs(const cmake* cm); - -#endif diff --git a/Source/cmLDConfigLDConfigTool.h b/Source/cmLDConfigLDConfigTool.h index 34bf6c6..eeb86dd 100644 --- a/Source/cmLDConfigLDConfigTool.h +++ b/Source/cmLDConfigLDConfigTool.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLDConfigLDConfigTool_h -#define cmLDConfigLDConfigTool_h +#pragma once #include <string> #include <vector> @@ -18,5 +17,3 @@ public: bool GetLDConfigPaths(std::vector<std::string>& paths) override; }; - -#endif diff --git a/Source/cmLDConfigTool.h b/Source/cmLDConfigTool.h index c816562..3116f80 100644 --- a/Source/cmLDConfigTool.h +++ b/Source/cmLDConfigTool.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLDConfigTool_h -#define cmLDConfigTool_h +#pragma once #include <string> #include <vector> @@ -20,5 +19,3 @@ public: protected: cmRuntimeDependencyArchive* Archive; }; - -#endif diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h index a7caa5c..2a3499d 100644 --- a/Source/cmLinkDirectoriesCommand.h +++ b/Source/cmLinkDirectoriesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLinkDirectoriesCommand_h -#define cmLinkDirectoriesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmLinkDirectoriesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index 3d92935..5a90e7e 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLinkItem_h -#define cmLinkItem_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -140,5 +139,3 @@ inline cmTargetLinkLibraryType CMP0003_ComputeLinkType( // The current configuration is not a debug configuration. return OPTIMIZED_LibraryType; } - -#endif diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx index acc23c8..dfdd3ff 100644 --- a/Source/cmLinkItemGraphVisitor.cxx +++ b/Source/cmLinkItemGraphVisitor.cxx @@ -24,15 +24,12 @@ void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item) void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, cmLinkItem const& rootItem) { - if (this->LinkVisited(item, rootItem)) { - return; - } - if (item.Target == nullptr) { return; } - for (auto const& config : item.Target->Makefile->GetGeneratorConfigs()) { + for (auto const& config : item.Target->Makefile->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig)) { this->VisitLinks(item, rootItem, config); } } diff --git a/Source/cmLinkItemGraphVisitor.h b/Source/cmLinkItemGraphVisitor.h index 21dc659..0d6676a 100644 --- a/Source/cmLinkItemGraphVisitor.h +++ b/Source/cmLinkItemGraphVisitor.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLinkItemGraphVisitor_h -#define cmLinkItemGraphVisitor_h +#pragma once #include <map> #include <set> @@ -71,5 +70,3 @@ private: std::string const& config, DependencyMap& dependencies); }; - -#endif diff --git a/Source/cmLinkLibrariesCommand.h b/Source/cmLinkLibrariesCommand.h index 3412251..27c410f 100644 --- a/Source/cmLinkLibrariesCommand.h +++ b/Source/cmLinkLibrariesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLinkLibrariesCommand_h -#define cmLinkLibrariesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmLinkLibrariesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h index df42468..a1dafc4 100644 --- a/Source/cmLinkLineComputer.h +++ b/Source/cmLinkLineComputer.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLinkLineComputer_h -#define cmLinkLineComputer_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -73,5 +72,3 @@ protected: bool UseNinjaMulti; bool Relink; }; - -#endif diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index c50a786..5739fec 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -191,21 +191,18 @@ bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg, target.GetLinkClosure(config); if (cm::contains(closure->Languages, "CUDA")) { - if (cmProp separableCompilation = - target.GetProperty("CUDA_SEPARABLE_COMPILATION")) { - if (cmIsOn(*separableCompilation)) { - bool doDeviceLinking = false; - switch (target.GetType()) { - case cmStateEnums::SHARED_LIBRARY: - case cmStateEnums::MODULE_LIBRARY: - case cmStateEnums::EXECUTABLE: - doDeviceLinking = true; - break; - default: - break; - } - return doDeviceLinking; + if (cmIsOn(target.GetProperty("CUDA_SEPARABLE_COMPILATION"))) { + bool doDeviceLinking = false; + switch (target.GetType()) { + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::EXECUTABLE: + doDeviceLinking = true; + break; + default: + break; } + return doDeviceLinking; } cmComputeLinkInformation* pcli = target.GetLinkInformation(config); diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h index a9b01cd..dee625b 100644 --- a/Source/cmLinkLineDeviceComputer.h +++ b/Source/cmLinkLineDeviceComputer.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLinkLineDeviceComputer_h -#define cmLinkLineDeviceComputer_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -42,5 +41,3 @@ public: bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg, const std::string& config); - -#endif diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h index c7453ea..d70176d 100644 --- a/Source/cmLinkedTree.h +++ b/Source/cmLinkedTree.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLinkedTree_h -#define cmLinkedTree_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -188,5 +187,3 @@ private: std::vector<T> Data; std::vector<PositionType> UpPositions; }; - -#endif diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index edec613..a2c14bd 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -27,6 +27,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmStringReplaceHelper.h" @@ -44,11 +45,11 @@ bool GetListString(std::string& listString, const std::string& var, const cmMakefile& makefile) { // get the old value - const char* cacheValue = makefile.GetDefinition(var); + cmProp cacheValue = makefile.GetDefinition(var); if (!cacheValue) { return false; } - listString = cacheValue; + listString = *cacheValue; return true; } diff --git a/Source/cmListCommand.h b/Source/cmListCommand.h index 274d9fd..6efab16 100644 --- a/Source/cmListCommand.h +++ b/Source/cmListCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmListCommand_h -#define cmListCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -16,5 +15,3 @@ class cmExecutionStatus; */ bool cmListCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 89902ff..c9556ab 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmListFileCache_h -#define cmListFileCache_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -175,6 +174,32 @@ public: std::ostream& operator<<(std::ostream& os, BT<std::string> const& s); +// Wrap type T as a value with potentially multiple backtraces. For purposes +// of ordering and equality comparison, only the original value is used. The +// backtrace is considered incidental. +template <typename T> +class BTs +{ +public: + BTs(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace()) + : Value(std::move(v)) + { + Backtraces.emplace_back(std::move(bt)); + } + T Value; + std::vector<cmListFileBacktrace> Backtraces; + friend bool operator==(BTs<T> const& l, BTs<T> const& r) + { + return l.Value == r.Value; + } + friend bool operator<(BTs<T> const& l, BTs<T> const& r) + { + return l.Value < r.Value; + } + friend bool operator==(BTs<T> const& l, T const& r) { return l.Value == r; } + friend bool operator==(T const& l, BTs<T> const& r) { return l == r.Value; } +}; + std::vector<BT<std::string>> ExpandListWithBacktrace( std::string const& list, cmListFileBacktrace const& bt = cmListFileBacktrace()); @@ -189,5 +214,3 @@ struct cmListFile std::vector<cmListFileFunction> Functions; }; - -#endif diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h index ec6b3cd..3c89f63 100644 --- a/Source/cmListFileLexer.h +++ b/Source/cmListFileLexer.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmListFileLexer_h -#define cmListFileLexer_h +#pragma once #ifdef __cplusplus extern "C" { @@ -67,5 +66,3 @@ void cmListFileLexer_Delete(cmListFileLexer*); #ifdef __cplusplus } /* extern "C" */ #endif - -#endif diff --git a/Source/cmLoadCacheCommand.h b/Source/cmLoadCacheCommand.h index 7cee663..5f5b705 100644 --- a/Source/cmLoadCacheCommand.h +++ b/Source/cmLoadCacheCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLoadCacheCommand_h -#define cmLoadCacheCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmLoadCacheCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h index f5fd754..d30ba16 100644 --- a/Source/cmLoadCommandCommand.h +++ b/Source/cmLoadCommandCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLoadCommandCommand_h -#define cmLoadCommandCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmLoadCommandCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index 278ec8b..5daaeff 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -8,6 +8,7 @@ #include "cmGeneratorTarget.h" #include "cmMakefile.h" #include "cmOutputConverter.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" class cmGlobalGenerator; @@ -17,10 +18,8 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, : cmLocalGenerator(gg, mf) , WorkingDirectory(std::move(wd)) { - this->Makefile->GetConfigurations(this->ConfigNames); - if (this->ConfigNames.empty()) { - this->ConfigNames.emplace_back(); - } + this->ConfigNames = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); } cmLocalCommonGenerator::~cmLocalCommonGenerator() = default; @@ -64,13 +63,13 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags( // If there is a separate module path flag then duplicate the // include path with it. This compiler does not search the include // path for modules. - if (const char* modpath_flag = + if (cmProp modpath_flag = this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG")) { std::vector<std::string> includes; this->GetIncludeDirectories(includes, target, "C", config); for (std::string const& id : includes) { std::string flg = - cmStrCat(modpath_flag, + cmStrCat(*modpath_flag, this->ConvertToOutputFormat(id, cmOutputConverter::SHELL)); this->AppendFlags(flags, flg); } diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h index 378ca63..f1eaf61 100644 --- a/Source/cmLocalCommonGenerator.h +++ b/Source/cmLocalCommonGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLocalCommonGenerator_h -#define cmLocalCommonGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -47,5 +46,3 @@ protected: friend class cmCommonTargetGenerator; }; - -#endif diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index d1ab62b..47931b0 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -39,6 +39,7 @@ #include "cmSourceFile.h" #include "cmSourceFileLocation.h" #include "cmSourceFileLocationKind.h" +#include "cmStandardLevelResolver.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" @@ -115,22 +116,22 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) std::vector<std::string> enabledLanguages = this->GetState()->GetEnabledLanguages(); - if (const char* sysrootCompile = + if (cmProp sysrootCompile = this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { - this->CompilerSysroot = sysrootCompile; + this->CompilerSysroot = *sysrootCompile; } else { this->CompilerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); } - if (const char* sysrootLink = + if (cmProp sysrootLink = this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) { - this->LinkerSysroot = sysrootLink; + this->LinkerSysroot = *sysrootLink; } else { this->LinkerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); } - if (std::string const* appleArchSysroots = - this->Makefile->GetDef("CMAKE_APPLE_ARCH_SYSROOTS")) { + if (cmProp appleArchSysroots = + this->Makefile->GetDefinition("CMAKE_APPLE_ARCH_SYSROOTS")) { std::string const& appleArchs = this->Makefile->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES"); std::vector<std::string> archs; @@ -219,10 +220,10 @@ void cmLocalGenerator::ComputeObjectMaxPath() #else this->ObjectPathMax = 1000; #endif - const char* plen = this->Makefile->GetDefinition("CMAKE_OBJECT_PATH_MAX"); - if (plen && *plen) { + cmProp plen = this->Makefile->GetDefinition("CMAKE_OBJECT_PATH_MAX"); + if (cmNonempty(plen)) { unsigned int pmax; - if (sscanf(plen, "%u", &pmax) == 1) { + if (sscanf(plen->c_str(), "%u", &pmax) == 1) { if (pmax >= 128) { this->ObjectPathMax = pmax; } else { @@ -234,7 +235,7 @@ void cmLocalGenerator::ComputeObjectMaxPath() } } else { std::ostringstream w; - w << "CMAKE_OBJECT_PATH_MAX is set to \"" << plen + w << "CMAKE_OBJECT_PATH_MAX is set to \"" << *plen << "\", which fails to parse as a positive integer. " << "The value will be ignored."; this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); @@ -283,7 +284,7 @@ void cmLocalGenerator::TraceDependencies() // Generate the rule files for each target. const auto& targets = this->GetGeneratorTargets(); for (const auto& target : targets) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!target->IsInBuildSystem()) { continue; } target->TraceDependencies(); @@ -297,9 +298,9 @@ void cmLocalGenerator::GenerateTestFiles() } // Compute the set of configurations. - std::vector<std::string> configurationTypes; - const std::string& config = - this->Makefile->GetConfigurations(configurationTypes, false); + std::vector<std::string> configurationTypes = + this->Makefile->GetGeneratorConfigs(cmMakefile::OnlyMultiConfig); + std::string config = this->Makefile->GetDefaultConfiguration(); std::string file = cmStrCat(this->StateSnapshot.GetDirectory().GetCurrentBinary(), @@ -357,7 +358,7 @@ void cmLocalGenerator::GenerateTestFiles() } // Add directory labels property - const char* directoryLabels = + cmProp directoryLabels = this->Makefile->GetDefinition("CMAKE_DIRECTORY_LABELS"); cmProp labels = this->Makefile->GetProperty("LABELS"); @@ -370,7 +371,7 @@ void cmLocalGenerator::GenerateTestFiles() fout << ";"; } if (directoryLabels) { - fout << cmOutputConverter::EscapeForCMake(directoryLabels); + fout << cmOutputConverter::EscapeForCMake(*directoryLabels); } fout << ")\n"; } @@ -379,7 +380,7 @@ void cmLocalGenerator::GenerateTestFiles() void cmLocalGenerator::CreateEvaluationFileOutputs() { std::vector<std::string> const& configs = - this->Makefile->GetGeneratorConfigs(); + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); for (std::string const& c : configs) { this->CreateEvaluationFileOutputs(c); } @@ -424,7 +425,8 @@ void cmLocalGenerator::ProcessEvaluationFiles( void cmLocalGenerator::GenerateInstallRules() { // Compute the install prefix. - const char* prefix = this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX"); + const char* prefix = + cmToCStr(this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX")); #if defined(_WIN32) && !defined(__CYGWIN__) std::string prefix_win32; @@ -432,10 +434,10 @@ void cmLocalGenerator::GenerateInstallRules() if (!cmSystemTools::GetEnv("SystemDrive", prefix_win32)) { prefix_win32 = "C:"; } - const char* project_name = this->Makefile->GetDefinition("PROJECT_NAME"); - if (project_name && project_name[0]) { + cmProp project_name = this->Makefile->GetDefinition("PROJECT_NAME"); + if (cmNonempty(project_name)) { prefix_win32 += "/Program Files/"; - prefix_win32 += project_name; + prefix_win32 += *project_name; } else { prefix_win32 += "/InstalledCMakeProject"; } @@ -456,15 +458,15 @@ void cmLocalGenerator::GenerateInstallRules() prefix = "/usr/local"; } #endif - if (const char* stagingPrefix = + if (cmProp stagingPrefix = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX")) { - prefix = stagingPrefix; + prefix = stagingPrefix->c_str(); } // Compute the set of configurations. - std::vector<std::string> configurationTypes; - const std::string& config = - this->Makefile->GetConfigurations(configurationTypes, false); + std::vector<std::string> configurationTypes = + this->Makefile->GetGeneratorConfigs(cmMakefile::OnlyMultiConfig); + std::string config = this->Makefile->GetDefaultConfiguration(); // Choose a default install configuration. std::string default_config = config; @@ -538,40 +540,40 @@ void cmLocalGenerator::GenerateInstallRules() /* clang-format on */ // Copy user-specified install options to the install code. - if (const char* so_no_exe = + if (cmProp so_no_exe = this->Makefile->GetDefinition("CMAKE_INSTALL_SO_NO_EXE")) { /* clang-format off */ fout << "# Install shared libraries without execute permission?\n" "if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)\n" - " set(CMAKE_INSTALL_SO_NO_EXE \"" << so_no_exe << "\")\n" + " set(CMAKE_INSTALL_SO_NO_EXE \"" << *so_no_exe << "\")\n" "endif()\n" "\n"; /* clang-format on */ } // Copy cmake cross compile state to install code. - if (const char* crosscompiling = + if (cmProp crosscompiling = this->Makefile->GetDefinition("CMAKE_CROSSCOMPILING")) { /* clang-format off */ fout << "# Is this installation the result of a crosscompile?\n" "if(NOT DEFINED CMAKE_CROSSCOMPILING)\n" - " set(CMAKE_CROSSCOMPILING \"" << crosscompiling << "\")\n" + " set(CMAKE_CROSSCOMPILING \"" << *crosscompiling << "\")\n" "endif()\n" "\n"; /* clang-format on */ } // Write default directory permissions. - if (const char* defaultDirPermissions = this->Makefile->GetDefinition( + if (cmProp defaultDirPermissions = this->Makefile->GetDefinition( "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS")) { /* clang-format off */ fout << "# Set default install directory permissions.\n" "if(NOT DEFINED CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS)\n" " set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS \"" - << defaultDirPermissions << "\")\n" + << *defaultDirPermissions << "\")\n" "endif()\n" "\n"; /* clang-format on */ @@ -580,14 +582,14 @@ void cmLocalGenerator::GenerateInstallRules() // Write out CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM so that // installed code that uses `file(GET_RUNTIME_DEPENDENCIES)` // has same platform variable as when running cmake - if (const char* platform = this->Makefile->GetDefinition( + if (cmProp platform = this->Makefile->GetDefinition( "CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM")) { /* clang-format off */ fout << "# Set default install directory permissions.\n" "if(NOT DEFINED CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM)\n" " set(CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM \"" - << platform << "\")\n" + << *platform << "\")\n" "endif()\n" "\n"; /* clang-format on */ @@ -596,14 +598,14 @@ void cmLocalGenerator::GenerateInstallRules() // Write out CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL so that // installed code that uses `file(GET_RUNTIME_DEPENDENCIES)` // has same tool selected as when running cmake - if (const char* command = + if (cmProp command = this->Makefile->GetDefinition("CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL")) { /* clang-format off */ fout << "# Set default install directory permissions.\n" "if(NOT DEFINED CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL)\n" " set(CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL \"" - << command << "\")\n" + << *command << "\")\n" "endif()\n" "\n"; /* clang-format on */ @@ -612,14 +614,14 @@ void cmLocalGenerator::GenerateInstallRules() // Write out CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND so that // installed code that uses `file(GET_RUNTIME_DEPENDENCIES)` // has same path to the tool as when running cmake - if (const char* command = this->Makefile->GetDefinition( + if (cmProp command = this->Makefile->GetDefinition( "CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND")) { /* clang-format off */ fout << "# Set default install directory permissions.\n" "if(NOT DEFINED CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND)\n" " set(CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND \"" - << command << "\")\n" + << *command << "\")\n" "endif()\n" "\n"; /* clang-format on */ @@ -630,13 +632,13 @@ void cmLocalGenerator::GenerateInstallRules() // CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND has consistent // logic to fallback to CMAKE_OBJDUMP when `objdump` is // not on the path - if (const char* command = this->Makefile->GetDefinition("CMAKE_OBJDUMP")) { + if (cmProp command = this->Makefile->GetDefinition("CMAKE_OBJDUMP")) { /* clang-format off */ fout << "# Set default install directory permissions.\n" "if(NOT DEFINED CMAKE_OBJDUMP)\n" " set(CMAKE_OBJDUMP \"" - << command << "\")\n" + << *command << "\")\n" "endif()\n" "\n"; /* clang-format on */ @@ -753,16 +755,13 @@ cmGeneratorTarget* cmLocalGenerator::FindLocalNonAliasGeneratorTarget( void cmLocalGenerator::ComputeTargetManifest() { // Collect the set of configuration types. - std::vector<std::string> configNames; - this->Makefile->GetConfigurations(configNames); - if (configNames.empty()) { - configNames.emplace_back(); - } + std::vector<std::string> configNames = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); // Add our targets to the manifest for each configuration. const auto& targets = this->GetGeneratorTargets(); for (const auto& target : targets) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!target->IsInBuildSystem()) { continue; } for (std::string const& c : configNames) { @@ -774,11 +773,8 @@ void cmLocalGenerator::ComputeTargetManifest() bool cmLocalGenerator::ComputeTargetCompileFeatures() { // Collect the set of configuration types. - std::vector<std::string> configNames; - this->Makefile->GetConfigurations(configNames); - if (configNames.empty()) { - configNames.emplace_back(); - } + std::vector<std::string> configNames = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); using LanguagePair = std::pair<std::string, std::string>; std::vector<LanguagePair> pairedLanguages{ { "OBJC", "C" }, @@ -802,40 +798,9 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures() // Now that C/C++ _STANDARD values have been computed // set the values to ObjC/ObjCXX _STANDARD variables - if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - auto copyStandardToObjLang = [&](LanguagePair const& lang) -> bool { - if (!target->GetProperty(cmStrCat(lang.first, "_STANDARD"))) { - cmProp standard = - target->GetProperty(cmStrCat(lang.second, "_STANDARD")); - if (!standard) { - standard = this->Makefile->GetDef( - cmStrCat("CMAKE_", lang.second, "_STANDARD_DEFAULT")); - } - target->Target->SetProperty(cmStrCat(lang.first, "_STANDARD"), - standard ? standard->c_str() : nullptr); - return true; - } - return false; - }; - auto copyPropertyToObjLang = [&](LanguagePair const& lang, - const char* property) { - if (!target->GetProperty(cmStrCat(lang.first, property)) && - target->GetProperty(cmStrCat(lang.second, property))) { - cmProp p = target->GetProperty(cmStrCat(lang.second, property)); - target->Target->SetProperty(cmStrCat(lang.first, property), - p ? p->c_str() : nullptr); - } - }; - for (auto const& lang : pairedLanguages) { - if (copyStandardToObjLang(lang)) { - copyPropertyToObjLang(lang, "_STANDARD_REQUIRED"); - copyPropertyToObjLang(lang, "_EXTENSIONS"); - } - } - if (cmProp standard = target->GetProperty("CUDA_STANDARD")) { - if (*standard == "98") { - target->Target->SetProperty("CUDA_STANDARD", "03"); - } + if (target->CanCompileSources()) { + for (std::string const& c : configNames) { + target->ComputeCompileFeatures(c, inferredEnabledLanguages); } } } @@ -894,8 +859,8 @@ std::string cmLocalGenerator::GetIncludeFlags( std::string const& includeFlag = this->Makefile->GetSafeDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_", lang)); - const char* sep = - this->Makefile->GetDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_SEP_", lang)); + const char* sep = cmToCStr( + this->Makefile->GetDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_SEP_", lang))); bool quotePaths = false; if (this->Makefile->GetDefinition("CMAKE_QUOTE_INCLUDE_PATHS")) { quotePaths = true; @@ -912,15 +877,15 @@ std::string cmLocalGenerator::GetIncludeFlags( // Support special system include flag if it is available and the // normal flag is repeated for each directory. - const char* sysIncludeFlag = nullptr; + cmProp sysIncludeFlag = nullptr; if (repeatFlag) { sysIncludeFlag = this->Makefile->GetDefinition( cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", lang)); } - const char* fwSearchFlag = this->Makefile->GetDefinition( + cmProp fwSearchFlag = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_FRAMEWORK_SEARCH_FLAG")); - const char* sysFwSearchFlag = this->Makefile->GetDefinition( + cmProp sysFwSearchFlag = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_SYSTEM_FRAMEWORK_SEARCH_FLAG")); bool flagUsed = false; @@ -929,16 +894,16 @@ std::string cmLocalGenerator::GetIncludeFlags( emitted.insert("/System/Library/Frameworks"); #endif for (std::string const& i : includes) { - if (fwSearchFlag && *fwSearchFlag && this->Makefile->IsOn("APPLE") && + if (cmNonempty(fwSearchFlag) && this->Makefile->IsOn("APPLE") && cmSystemTools::IsPathToFramework(i)) { std::string const frameworkDir = cmSystemTools::CollapseFullPath(cmStrCat(i, "/../")); if (emitted.insert(frameworkDir).second) { if (sysFwSearchFlag && target && target->IsSystemIncludeDirectory(i, config, lang)) { - includeFlags << sysFwSearchFlag; + includeFlags << *sysFwSearchFlag; } else { - includeFlags << fwSearchFlag; + includeFlags << *fwSearchFlag; } includeFlags << this->ConvertToOutputFormat(frameworkDir, shellFormat) << " "; @@ -949,7 +914,7 @@ std::string cmLocalGenerator::GetIncludeFlags( if (!flagUsed || repeatFlag) { if (sysIncludeFlag && target && target->IsSystemIncludeDirectory(i, config, lang)) { - includeFlags << sysIncludeFlag; + includeFlags << *sysIncludeFlag; } else { includeFlags << includeFlag; } @@ -989,9 +954,9 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, const std::string& lang, const std::string& config) { - std::string langFlagRegexVar = std::string("CMAKE_") + lang + "_FLAG_REGEX"; + std::string langFlagRegexVar = cmStrCat("CMAKE_", lang, "_FLAG_REGEX"); - if (const char* langFlagRegexStr = + if (cmProp langFlagRegexStr = this->Makefile->GetDefinition(langFlagRegexVar)) { // Filter flags acceptable to this language. if (cmProp targetFlags = target->GetProperty("COMPILE_FLAGS")) { @@ -1000,7 +965,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, // Re-escape these flags since COMPILE_FLAGS were already parsed // as a command line above. std::string compileOpts; - this->AppendCompileOptions(compileOpts, opts, langFlagRegexStr); + this->AppendCompileOptions(compileOpts, opts, langFlagRegexStr->c_str()); if (!compileOpts.empty()) { flags.emplace_back(std::move(compileOpts)); } @@ -1008,7 +973,8 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, std::vector<BT<std::string>> targetCompileOpts = target->GetCompileOptions(config, lang); // COMPILE_OPTIONS are escaped. - this->AppendCompileOptions(flags, targetCompileOpts, langFlagRegexStr); + this->AppendCompileOptions(flags, targetCompileOpts, + langFlagRegexStr->c_str()); } else { // Use all flags. if (cmProp targetFlags = target->GetProperty("COMPILE_FLAGS")) { @@ -1025,12 +991,13 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, this->AppendCompileOptions(flags, targetCompileOpts); } + cmStandardLevelResolver standardResolver(this->Makefile); for (auto const& it : target->GetMaxLanguageStandards()) { - cmProp standard = target->GetProperty(it.first + "_STANDARD"); + cmProp standard = target->GetLanguageStandard(it.first, config); if (!standard) { continue; } - if (this->Makefile->IsLaterStandard(it.first, *standard, it.second)) { + if (standardResolver.IsLaterStandard(it.first, *standard, it.second)) { std::ostringstream e; e << "The COMPILE_FEATURES property of target \"" << target->GetName() << "\" was evaluated when computing the link " @@ -1050,14 +1017,14 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, } std::string compReqFlag; - this->AddCompilerRequirementFlag(compReqFlag, target, lang); + this->AddCompilerRequirementFlag(compReqFlag, target, lang, config); if (!compReqFlag.empty()) { flags.emplace_back(std::move(compReqFlag)); } // Add compile flag for the MSVC compiler only. cmMakefile* mf = this->GetMakefile(); - if (const char* jmc = + if (cmProp jmc = mf->GetDefinition("CMAKE_" + lang + "_COMPILE_OPTIONS_JMC")) { // Handle Just My Code debugging flags, /JMC. @@ -1071,7 +1038,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, std::string isJMCEnabled = cmGeneratorExpression::Evaluate(*jmcExprGen, this, config); if (cmIsOn(isJMCEnabled)) { - std::vector<std::string> optVec = cmExpandedList(jmc); + std::vector<std::string> optVec = cmExpandedList(*jmc); std::string jmcFlags; this->AppendCompileOptions(jmcFlags, optVec); if (!jmcFlags.empty()) { @@ -1308,7 +1275,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( } } - // Emit remaining non implicit user direcories. + // Emit remaining non implicit user directories. for (BT<std::string> const& udr : userDirs) { if (notExcluded(udr.Value)) { emitBT(udr); @@ -1555,7 +1522,7 @@ void cmLocalGenerator::GetTargetFlags( return; } - if (target->GetPropertyAsBool("WIN32_EXECUTABLE")) { + if (target->IsWin32Executable(config)) { exeFlags += this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE"); exeFlags += " "; @@ -1578,9 +1545,8 @@ void cmLocalGenerator::GetTargetFlags( frameworkPath, linkPath); } - if (cmIsOn(this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) { - std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_") + - linkLanguage + std::string("_FLAGS"); + if (this->Makefile->IsOn("BUILD_SHARED_LIBS")) { + std::string sFlagVar = "CMAKE_SHARED_BUILD_" + linkLanguage + "_FLAGS"; exeFlags += this->Makefile->GetSafeDefinition(sFlagVar); exeFlags += " "; } @@ -1688,8 +1654,8 @@ static std::string GetFrameworkFlags(const std::string& lang, } std::string fwSearchFlagVar = "CMAKE_" + lang + "_FRAMEWORK_SEARCH_FLAG"; - const char* fwSearchFlag = mf->GetDefinition(fwSearchFlagVar); - if (!(fwSearchFlag && *fwSearchFlag)) { + cmProp fwSearchFlag = mf->GetDefinition(fwSearchFlagVar); + if (!cmNonempty(fwSearchFlag)) { return std::string(); } @@ -1715,7 +1681,7 @@ static std::string GetFrameworkFlags(const std::string& lang, std::vector<std::string> const& frameworks = cli->GetFrameworkPaths(); for (std::string const& framework : frameworks) { if (emitted.insert(framework).second) { - flags += fwSearchFlag; + flags += *fwSearchFlag; flags += lg->ConvertToOutputFormat(framework, cmOutputConverter::SHELL); flags += " "; @@ -1797,18 +1763,18 @@ void cmLocalGenerator::OutputLinkLibraries( std::string linkLanguage = cli.GetLinkLanguage(); std::string libPathFlag; - if (const char* value = this->Makefile->GetDefinition( + if (cmProp value = this->Makefile->GetDefinition( "CMAKE_" + cli.GetLinkLanguage() + "_LIBRARY_PATH_FLAG")) { - libPathFlag = value; + libPathFlag = *value; } else { libPathFlag = this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG"); } std::string libPathTerminator; - if (const char* value = this->Makefile->GetDefinition( + if (cmProp value = this->Makefile->GetDefinition( "CMAKE_" + cli.GetLinkLanguage() + "_LIBRARY_PATH_TERMINATOR")) { - libPathTerminator = value; + libPathTerminator = *value; } else { libPathTerminator = this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_TERMINATOR"); @@ -1911,8 +1877,9 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, if (this->Makefile->IsOn("APPLE") && this->EmitUniversalBinaryFlags) { std::vector<std::string> archs; target->GetAppleArchs(config, archs); - if (!archs.empty() && !lang.empty() && - (lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) { + if (!archs.empty() && + (lang == "C" || lang == "CXX" || lang == "OBJ" || lang == "OBJCXX" || + cmHasLiteralPrefix(lang, "ASM"))) { for (std::string const& arch : archs) { if (filterArch.empty() || filterArch == arch) { flags += " -arch "; @@ -1921,16 +1888,15 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, } } - const char* sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT"); - if (sysroot && sysroot[0] == '/' && !sysroot[1]) { + cmProp sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT"); + if (sysroot && *sysroot == "/") { sysroot = nullptr; } - std::string sysrootFlagVar = - std::string("CMAKE_") + lang + "_SYSROOT_FLAG"; - const char* sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar); - if (sysrootFlag && *sysrootFlag) { + std::string sysrootFlagVar = "CMAKE_" + lang + "_SYSROOT_FLAG"; + cmProp sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar); + if (cmNonempty(sysrootFlag)) { if (!this->AppleArchSysroots.empty() && - !this->AllAppleArchSysrootsAreTheSame(archs, sysroot)) { + !this->AllAppleArchSysrootsAreTheSame(archs, cmToCStr(sysroot))) { for (std::string const& arch : archs) { std::string const& archSysroot = this->AppleArchSysroots[arch]; if (cmIsOff(archSysroot)) { @@ -1939,29 +1905,28 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, if (filterArch.empty() || filterArch == arch) { flags += " -Xarch_" + arch + " "; // Combine sysroot flag and path to work with -Xarch - std::string arch_sysroot = sysrootFlag + archSysroot; + std::string arch_sysroot = *sysrootFlag + archSysroot; flags += this->ConvertToOutputFormat(arch_sysroot, SHELL); } } - } else if (sysroot && *sysroot) { + } else if (cmNonempty(sysroot)) { flags += " "; - flags += sysrootFlag; + flags += *sysrootFlag; flags += " "; - flags += this->ConvertToOutputFormat(sysroot, SHELL); + flags += this->ConvertToOutputFormat(*sysroot, SHELL); } } - const char* deploymentTarget = + cmProp deploymentTarget = this->Makefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET"); std::string deploymentTargetFlagVar = - std::string("CMAKE_") + lang + "_OSX_DEPLOYMENT_TARGET_FLAG"; - const char* deploymentTargetFlag = + "CMAKE_" + lang + "_OSX_DEPLOYMENT_TARGET_FLAG"; + cmProp deploymentTargetFlag = this->Makefile->GetDefinition(deploymentTargetFlagVar); - if (deploymentTargetFlag && *deploymentTargetFlag && deploymentTarget && - *deploymentTarget) { + if (cmNonempty(deploymentTargetFlag) && cmNonempty(deploymentTarget)) { flags += " "; - flags += deploymentTargetFlag; - flags += deploymentTarget; + flags += *deploymentTargetFlag; + flags += *deploymentTarget; } } } @@ -1975,12 +1940,15 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, this->AddConfigVariableFlags(flags, cmStrCat("CMAKE_", lang, "_FLAGS"), config); + std::string const& compiler = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_COMPILER_ID")); + if (lang == "Swift") { if (cmProp v = target->GetProperty("Swift_LANGUAGE_VERSION")) { - if (cmSystemTools::VersionCompare( - cmSystemTools::OP_GREATER_EQUAL, - this->Makefile->GetDefinition("CMAKE_Swift_COMPILER_VERSION"), - "4.2")) { + if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL, + cmToCStr(this->Makefile->GetDefinition( + "CMAKE_Swift_COMPILER_VERSION")), + "4.2")) { this->AppendFlags(flags, "-swift-version " + *v); } } @@ -1988,9 +1956,6 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, target->AddCUDAArchitectureFlags(flags); target->AddCUDAToolkitFlags(flags); - std::string const& compiler = - this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID"); - if (compiler == "Clang") { bool separable = target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION"); @@ -2001,13 +1966,32 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, "See CMake issue #20726."); } } + } else if (lang == "ISPC") { + target->AddISPCTargetFlags(flags); + } + // Add VFS Overlay for Clang compiliers + if (compiler == "Clang") { + if (cmProp vfsOverlay = + this->Makefile->GetDefinition("CMAKE_CLANG_VFS_OVERLAY")) { + std::string const& compilerSimulateId = + this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_SIMULATE_ID")); + if (compilerSimulateId == "MSVC") { + this->AppendCompileOptions( + flags, + std::vector<std::string>{ "-Xclang", "-ivfsoverlay", "-Xclang", + *vfsOverlay }); + } else { + this->AppendCompileOptions( + flags, std::vector<std::string>{ "-ivfsoverlay", *vfsOverlay }); + } + } } - // Add MSVC runtime library flags. This is activated by the presence // of a default selection whether or not it is overridden by a property. cmProp msvcRuntimeLibraryDefault = - this->Makefile->GetDef("CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT"); - if (msvcRuntimeLibraryDefault && !msvcRuntimeLibraryDefault->empty()) { + this->Makefile->GetDefinition("CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT"); + if (cmNonempty(msvcRuntimeLibraryDefault)) { cmProp msvcRuntimeLibraryValue = target->GetProperty("MSVC_RUNTIME_LIBRARY"); if (!msvcRuntimeLibraryValue) { @@ -2016,11 +2000,10 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, std::string const msvcRuntimeLibrary = cmGeneratorExpression::Evaluate( *msvcRuntimeLibraryValue, this, config, target); if (!msvcRuntimeLibrary.empty()) { - if (const char* msvcRuntimeLibraryOptions = - this->Makefile->GetDefinition( - "CMAKE_" + lang + "_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_" + - msvcRuntimeLibrary)) { - this->AppendCompileOptions(flags, msvcRuntimeLibraryOptions); + if (cmProp msvcRuntimeLibraryOptions = this->Makefile->GetDefinition( + "CMAKE_" + lang + "_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_" + + msvcRuntimeLibrary)) { + this->AppendCompileOptions(flags, *msvcRuntimeLibraryOptions); } else if ((this->Makefile->GetSafeDefinition( "CMAKE_" + lang + "_COMPILER_ID") == "MSVC" || this->Makefile->GetSafeDefinition( @@ -2046,7 +2029,7 @@ void cmLocalGenerator::AddLanguageFlagsForLinking( // when linking in order to use the matching standard library. // FIXME: If CMake gains an abstraction for standard library // selection, this will have to be reconciled with it. - this->AddCompilerRequirementFlag(flags, target, lang); + this->AddCompilerRequirementFlag(flags, target, lang, config); } this->AddLanguageFlags(flags, target, lang, config); @@ -2189,156 +2172,20 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags, } void cmLocalGenerator::AddCompilerRequirementFlag( - std::string& flags, cmGeneratorTarget const* target, const std::string& lang) + std::string& flags, cmGeneratorTarget const* target, const std::string& lang, + const std::string& config) { - if (lang.empty()) { - return; - } - const char* defaultStd = - this->Makefile->GetDefinition("CMAKE_" + lang + "_STANDARD_DEFAULT"); - if (!defaultStd || !*defaultStd) { - // This compiler has no notion of language standard levels. - return; - } - std::string extProp = lang + "_EXTENSIONS"; - bool ext = true; - if (cmProp extPropValue = target->GetProperty(extProp)) { - if (cmIsOff(*extPropValue)) { - ext = false; - } - } - std::string stdProp = lang + "_STANDARD"; - cmProp standardProp = target->GetProperty(stdProp); - if (!standardProp) { - if (ext) { - // No language standard is specified and extensions are not disabled. - // Check if this compiler needs a flag to enable extensions. - std::string const option_flag = - "CMAKE_" + lang + "_EXTENSION_COMPILE_OPTION"; - if (const char* opt = - target->Target->GetMakefile()->GetDefinition(option_flag)) { - std::vector<std::string> optVec = cmExpandedList(opt); - for (std::string const& i : optVec) { - this->AppendFlagEscape(flags, i); - } - } - } - return; - } - - std::string const type = ext ? "EXTENSION" : "STANDARD"; - - if (target->GetPropertyAsBool(lang + "_STANDARD_REQUIRED")) { - std::string option_flag = - "CMAKE_" + lang + *standardProp + "_" + type + "_COMPILE_OPTION"; - - const char* opt = - target->Target->GetMakefile()->GetDefinition(option_flag); - if (!opt) { - std::ostringstream e; - e << "Target \"" << target->GetName() - << "\" requires the language " - "dialect \"" - << lang << *standardProp << "\" " - << (ext ? "(with compiler extensions)" : "") - << ", but CMake " - "does not know the compile flags to use to enable it."; - this->IssueMessage(MessageType::FATAL_ERROR, e.str()); - } else { - std::vector<std::string> optVec = cmExpandedList(opt); - for (std::string const& i : optVec) { - this->AppendFlagEscape(flags, i); - } - } - return; - } - - static std::map<std::string, std::vector<std::string>> langStdMap; - if (langStdMap.empty()) { - // Maintain sorted order, most recent first. - langStdMap["CXX"].emplace_back("20"); - langStdMap["CXX"].emplace_back("17"); - langStdMap["CXX"].emplace_back("14"); - langStdMap["CXX"].emplace_back("11"); - langStdMap["CXX"].emplace_back("98"); - - langStdMap["OBJCXX"].emplace_back("20"); - langStdMap["OBJCXX"].emplace_back("17"); - langStdMap["OBJCXX"].emplace_back("14"); - langStdMap["OBJCXX"].emplace_back("11"); - langStdMap["OBJCXX"].emplace_back("98"); - - langStdMap["C"].emplace_back("11"); - langStdMap["C"].emplace_back("99"); - langStdMap["C"].emplace_back("90"); - - langStdMap["OBJC"].emplace_back("11"); - langStdMap["OBJC"].emplace_back("99"); - langStdMap["OBJC"].emplace_back("90"); - - langStdMap["CUDA"].emplace_back("20"); - langStdMap["CUDA"].emplace_back("17"); - langStdMap["CUDA"].emplace_back("14"); - langStdMap["CUDA"].emplace_back("11"); - langStdMap["CUDA"].emplace_back("03"); - } - - std::string standard(*standardProp); - if (lang == "CUDA" && standard == "98") { - standard = "03"; - } - std::vector<std::string>& stds = langStdMap[lang]; - - auto stdIt = std::find(stds.begin(), stds.end(), standard); - if (stdIt == stds.end()) { - - std::string e = - lang + "_STANDARD is set to invalid value '" + standard + "'"; - this->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - MessageType::FATAL_ERROR, e, target->GetBacktrace()); - return; - } - - auto defaultStdIt = std::find(stds.begin(), stds.end(), defaultStd); - if (defaultStdIt == stds.end()) { - std::string e = "CMAKE_" + lang + - "_STANDARD_DEFAULT is set to invalid value '" + std::string(defaultStd) + - "'"; - this->IssueMessage(MessageType::INTERNAL_ERROR, e); - return; - } - - // If the standard requested is older than the compiler's default - // then we need to use a flag to change it. The comparison is - // greater-or-equal because the standards are stored in backward - // chronological order. - if (stdIt >= defaultStdIt) { - std::string option_flag = - "CMAKE_" + lang + *stdIt + "_" + type + "_COMPILE_OPTION"; - - std::string const& opt = - target->Target->GetMakefile()->GetRequiredDefinition(option_flag); - std::vector<std::string> optVec = cmExpandedList(opt); - for (std::string const& i : optVec) { - this->AppendFlagEscape(flags, i); - } - return; - } - - // The standard requested is at least as new as the compiler's default, - // and the standard request is not required. Decay to the newest standard - // for which a flag is defined. - for (; stdIt < defaultStdIt; ++stdIt) { - std::string option_flag = - cmStrCat("CMAKE_", lang, *stdIt, "_", type, "_COMPILE_OPTION"); - - if (const char* opt = - target->Target->GetMakefile()->GetDefinition(option_flag)) { - std::vector<std::string> optVec = cmExpandedList(opt); + cmStandardLevelResolver standardResolver(this->Makefile); + + std::string const& optionFlagDef = + standardResolver.GetCompileOptionDef(target, lang, config); + if (!optionFlagDef.empty()) { + cmProp opt = target->Target->GetMakefile()->GetDefinition(optionFlagDef); + if (opt) { + std::vector<std::string> optVec = cmExpandedList(*opt); for (std::string const& i : optVec) { this->AppendFlagEscape(flags, i); } - return; } } } @@ -2350,7 +2197,7 @@ static void AddVisibilityCompileOption(std::string& flags, std::string* warnCMP0063) { std::string compileOption = "CMAKE_" + lang + "_COMPILE_OPTIONS_VISIBILITY"; - const char* opt = lg->GetMakefile()->GetDefinition(compileOption); + cmProp opt = lg->GetMakefile()->GetDefinition(compileOption); if (!opt) { return; } @@ -2374,7 +2221,7 @@ static void AddVisibilityCompileOption(std::string& flags, cmSystemTools::Error(e.str()); return; } - std::string option = opt + *prop; + std::string option = *opt + *prop; lg->AppendFlags(flags, option); } @@ -2386,7 +2233,7 @@ static void AddInlineVisibilityCompileOption(std::string& flags, { std::string compileOption = cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN"); - const char* opt = lg->GetMakefile()->GetDefinition(compileOption); + cmProp opt = lg->GetMakefile()->GetDefinition(compileOption); if (!opt) { return; } @@ -2399,7 +2246,7 @@ static void AddInlineVisibilityCompileOption(std::string& flags, *warnCMP0063 += " VISIBILITY_INLINES_HIDDEN\n"; return; } - lg->AppendFlags(flags, opt); + lg->AppendFlags(flags, *opt); } void cmLocalGenerator::AddVisibilityPresetFlags( @@ -2581,13 +2428,58 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags, this->EscapeForShell(rawFlag, false, false, false, this->IsNinjaMulti())); } -void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) +void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target) { - std::vector<std::string> configsList; - std::string configDefault = this->Makefile->GetConfigurations(configsList); - if (configsList.empty()) { - configsList.push_back(configDefault); + std::vector<std::string> enabledLanguages = + this->GetState()->GetEnabledLanguages(); + if (std::find(enabledLanguages.begin(), enabledLanguages.end(), "ISPC") == + enabledLanguages.end()) { + return; + } + + std::vector<std::string> ispcSuffixes = + detail::ComputeISPCObjectSuffixes(target); + const bool extra_objects = (ispcSuffixes.size() > 1); + + std::vector<std::string> configsList = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + for (std::string const& config : configsList) { + + std::string perConfigDir = target->GetObjectDirectory(config); + if (cmProp prop = target->GetProperty("ISPC_HEADER_DIRECTORY")) { + perConfigDir = cmSystemTools::CollapseFullPath( + cmStrCat(this->GetBinaryDirectory(), '/', *prop)); + } + + std::vector<cmSourceFile*> sources; + target->GetSourceFiles(sources, config); + + // build up the list of ispc headers and extra objects that this target is + // generating + for (cmSourceFile const* sf : sources) { + // Generate this object file's rule file. + const std::string& lang = sf->GetLanguage(); + if (lang == "ISPC") { + std::string const& objectName = target->GetObjectName(sf); + std::string ispcSource = + cmSystemTools::GetFilenameWithoutLastExtension(objectName); + + auto headerPath = cmStrCat(perConfigDir, '/', ispcSource, ".h"); + target->AddISPCGeneratedHeader(headerPath, config); + if (extra_objects) { + std::vector<std::string> objs = detail::ComputeISPCExtraObjects( + objectName, perConfigDir, ispcSuffixes); + target->AddISPCGeneratedObject(std::move(objs), config); + } + } + } } +} + +void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) +{ + std::vector<std::string> configsList = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); for (std::string const& config : configsList) { // FIXME: Refactor collection of sources to not evaluate object @@ -3055,12 +2947,12 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, } const std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_IPO"; - const char* rawFlagsList = this->Makefile->GetDefinition(name); + cmProp rawFlagsList = this->Makefile->GetDefinition(name); if (rawFlagsList == nullptr) { return; } - std::vector<std::string> flagsList = cmExpandedList(rawFlagsList); + std::vector<std::string> flagsList = cmExpandedList(*rawFlagsList); for (std::string const& o : flagsList) { this->AppendFlagEscape(flags, o); } @@ -3246,10 +3138,10 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines, // Lookup the define flag for the current language. std::string dflag = "-D"; if (!lang.empty()) { - const char* df = + cmProp df = this->Makefile->GetDefinition(cmStrCat("CMAKE_", lang, "_DEFINE_FLAG")); - if (df && *df) { - dflag = df; + if (cmNonempty(df)) { + dflag = *df; } } const char* itemSeparator = definesString.empty() ? "" : " "; @@ -3293,18 +3185,18 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags, const std::string& lang, const char* feature) { - const char* optionList = this->Makefile->GetDefinition( + cmProp optionList = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_", feature)); if (optionList != nullptr) { - std::vector<std::string> options = cmExpandedList(optionList); + std::vector<std::string> options = cmExpandedList(*optionList); for (std::string const& o : options) { this->AppendFlagEscape(flags, o); } } } -const char* cmLocalGenerator::GetFeature(const std::string& feature, - const std::string& config) +cmProp cmLocalGenerator::GetFeature(const std::string& feature, + const std::string& config) { std::string featureName = feature; // TODO: Define accumulation policy for features (prepend, append, @@ -3316,7 +3208,7 @@ const char* cmLocalGenerator::GetFeature(const std::string& feature, cmStateSnapshot snp = this->StateSnapshot; while (snp.IsValid()) { if (cmProp value = snp.GetDirectory().GetProperty(featureName)) { - return value->c_str(); + return value; } snp = snp.GetBuildsystemDirectoryParent(); } @@ -3751,9 +3643,9 @@ KWIML_INT_uint64_t cmLocalGenerator::GetBackwardsCompatibility() unsigned int major = 0; unsigned int minor = 0; unsigned int patch = 0; - if (const char* value = + if (cmProp value = this->Makefile->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY")) { - switch (sscanf(value, "%u.%u.%u", &major, &minor, &patch)) { + switch (sscanf(value->c_str(), "%u.%u.%u", &major, &minor, &patch)) { case 2: patch = 0; break; @@ -3857,8 +3749,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target, { // Find the Info.plist template. cmProp in = target->GetProperty("MACOSX_BUNDLE_INFO_PLIST"); - std::string inFile = - (in && !in->empty()) ? *in : "MacOSXBundleInfo.plist.in"; + std::string inFile = cmNonempty(in) ? *in : "MacOSXBundleInfo.plist.in"; if (!cmSystemTools::FileIsFullPath(inFile)) { std::string inMod = this->Makefile->GetModulesFile(inFile); if (!inMod.empty()) { @@ -3888,7 +3779,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target, cmLGInfoProp(mf, target, "MACOSX_BUNDLE_SHORT_VERSION_STRING"); cmLGInfoProp(mf, target, "MACOSX_BUNDLE_BUNDLE_VERSION"); cmLGInfoProp(mf, target, "MACOSX_BUNDLE_COPYRIGHT"); - mf->ConfigureFile(inFile, fname, false, false, false); + mf->ConfigureFile(inFile, fname, false, false, false, true); } void cmLocalGenerator::GenerateFrameworkInfoPList( @@ -3897,8 +3788,7 @@ void cmLocalGenerator::GenerateFrameworkInfoPList( { // Find the Info.plist template. cmProp in = target->GetProperty("MACOSX_FRAMEWORK_INFO_PLIST"); - std::string inFile = - (in && !in->empty()) ? *in : "MacOSXFrameworkInfo.plist.in"; + std::string inFile = cmNonempty(in) ? *in : "MacOSXFrameworkInfo.plist.in"; if (!cmSystemTools::FileIsFullPath(inFile)) { std::string inMod = this->Makefile->GetModulesFile(inFile); if (!inMod.empty()) { @@ -3924,7 +3814,7 @@ void cmLocalGenerator::GenerateFrameworkInfoPList( cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_IDENTIFIER"); cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_SHORT_VERSION_STRING"); cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_BUNDLE_VERSION"); - mf->ConfigureFile(inFile, fname, false, false, false); + mf->ConfigureFile(inFile, fname, false, false, false, true); } namespace { @@ -4168,4 +4058,44 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, target->AddSource(force.NameCMP0049); } } + +std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target) +{ + const std::string& targetProperty = + target->GetSafeProperty("ISPC_INSTRUCTION_SETS"); + std::vector<std::string> ispcTargets; + + if (!cmIsOff(targetProperty)) { + cmExpandList(targetProperty, ispcTargets); + for (auto& ispcTarget : ispcTargets) { + // transform targets into the suffixes + auto pos = ispcTarget.find('-'); + auto target_suffix = ispcTarget.substr(0, pos); + if (target_suffix == + "avx1") { // when targetting avx1 ISPC uses the 'avx' output string + target_suffix = "avx"; + } + ispcTarget = target_suffix; + } + } + return ispcTargets; +} + +std::vector<std::string> ComputeISPCExtraObjects( + std::string const& objectName, std::string const& buildDirectory, + std::vector<std::string> const& ispcSuffixes) +{ + std::vector<std::string> computedObjects; + computedObjects.reserve(ispcSuffixes.size()); + + auto extension = cmSystemTools::GetFilenameLastExtension(objectName); + auto objNameNoExt = + cmSystemTools::GetFilenameWithoutLastExtension(objectName); + for (const auto& ispcTarget : ispcSuffixes) { + computedObjects.emplace_back( + cmStrCat(buildDirectory, "/", objNameNoExt, "_", ispcTarget, extension)); + } + + return computedObjects; +} } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index f2d9145..fad6136 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLocalGenerator_h -#define cmLocalGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -20,6 +19,7 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmStateSnapshot.h" class cmComputeLinkInformation; @@ -123,7 +123,8 @@ public: const std::string& config); void AddCompilerRequirementFlag(std::string& flags, cmGeneratorTarget const* target, - const std::string& lang); + const std::string& lang, + const std::string& config); //! Append flags to a string. virtual void AppendFlags(std::string& flags, const std::string& newFlags) const; @@ -131,6 +132,7 @@ public: const std::vector<BT<std::string>>& newFlags) const; virtual void AppendFlagEscape(std::string& flags, const std::string& rawFlag) const; + void AddISPCDependencies(cmGeneratorTarget* target); void AddPchDependencies(cmGeneratorTarget* target); void AddUnityBuild(cmGeneratorTarget* target); void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, @@ -208,8 +210,7 @@ public: void AppendFeatureOptions(std::string& flags, const std::string& lang, const char* feature); - const char* GetFeature(const std::string& feature, - const std::string& config); + cmProp GetFeature(const std::string& feature, const std::string& config); /** \brief Get absolute path to dependency \a name * @@ -593,6 +594,9 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, bool escapeOldStyle, const char* comment, bool uses_terminal, bool command_expand_lists, const std::string& job_pool, bool stdPipesUTF8); -} -#endif +std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target); +std::vector<std::string> ComputeISPCExtraObjects( + std::string const& objectName, std::string const& buildDirectory, + std::vector<std::string> const& ispcSuffixes); +} diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx index 098fa5a..b223813 100644 --- a/Source/cmLocalGhsMultiGenerator.cxx +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -2,16 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLocalGhsMultiGenerator.h" -#include <algorithm> #include <utility> - -#include <cmext/algorithm> +#include <vector> #include "cmGeneratorTarget.h" #include "cmGhsMultiTargetGenerator.h" #include "cmGlobalGenerator.h" #include "cmSourceFile.h" -#include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -30,34 +27,16 @@ std::string cmLocalGhsMultiGenerator::GetTargetDirectory( return dir; } -void cmLocalGhsMultiGenerator::GenerateTargetsDepthFirst( - cmGeneratorTarget* target, std::vector<cmGeneratorTarget*>& remaining) -{ - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - return; - } - // Find this target in the list of remaining targets. - auto it = std::find(remaining.begin(), remaining.end(), target); - if (it == remaining.end()) { - // This target was already handled. - return; - } - // Remove this target from the list of remaining targets because - // we are handling it now. - *it = nullptr; - - cmGhsMultiTargetGenerator tg(target); - tg.Generate(); -} - void cmLocalGhsMultiGenerator::Generate() { - std::vector<cmGeneratorTarget*> remaining; - cm::append(remaining, this->GetGeneratorTargets()); - for (auto& t : remaining) { - if (t) { - this->GenerateTargetsDepthFirst(t, remaining); + for (cmGeneratorTarget* gt : + this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this)) { + if (!gt->IsInBuildSystem()) { + continue; } + + cmGhsMultiTargetGenerator tg(gt); + tg.Generate(); } } diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h index 2250e57..be32a94 100644 --- a/Source/cmLocalGhsMultiGenerator.h +++ b/Source/cmLocalGhsMultiGenerator.h @@ -1,11 +1,9 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLocalGhsMultiGenerator_h -#define cmLocalGhsMultiGenerator_h +#pragma once #include <map> #include <string> -#include <vector> #include "cmLocalGenerator.h" @@ -38,10 +36,4 @@ public: void ComputeObjectFilenames( std::map<cmSourceFile const*, std::string>& mapping, cmGeneratorTarget const* gt = nullptr) override; - -private: - void GenerateTargetsDepthFirst(cmGeneratorTarget* target, - std::vector<cmGeneratorTarget*>& remaining); }; - -#endif diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 87e8aa4..ad782ee 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -84,13 +84,31 @@ void cmLocalNinjaGenerator::Generate() if (!showIncludesPrefix.empty()) { cmGlobalNinjaGenerator::WriteComment(this->GetRulesFileStream(), "localized /showIncludes string"); - this->GetRulesFileStream() - << "msvc_deps_prefix = " << showIncludesPrefix << "\n\n"; + this->GetRulesFileStream() << "msvc_deps_prefix = "; +#ifdef WIN32 + // Ninja uses the ANSI Windows APIs, so strings in the rules file + // typically need to be ANSI encoded. However, in this case the compiler + // is being invoked using the UTF-8 codepage so the /showIncludes prefix + // will be UTF-8 encoded on stdout. Ninja can't successfully compare this + // UTF-8 encoded prefix to the ANSI encoded msvc_deps_prefix if it + // contains any non-ASCII characters and dependency checking will fail. + // As a workaround, leave the msvc_deps_prefix UTF-8 encoded even though + // the rest of the file is ANSI encoded. + if (GetConsoleOutputCP() == CP_UTF8 && GetACP() != CP_UTF8) { + this->GetRulesFileStream().WriteRaw(showIncludesPrefix); + } else { + this->GetRulesFileStream() << showIncludesPrefix; + } +#else + // It's safe to use the standard encoding on other platforms. + this->GetRulesFileStream() << showIncludesPrefix; +#endif + this->GetRulesFileStream() << "\n\n"; } } for (const auto& target : this->GetGeneratorTargets()) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!target->IsInBuildSystem()) { continue; } auto tg = cmNinjaTargetGenerator::New(target.get()); @@ -102,9 +120,10 @@ void cmLocalNinjaGenerator::Generate() this->GetGlobalGenerator()->IsMultiConfig()) { cmNinjaBuild phonyAlias("phony"); this->GetGlobalNinjaGenerator()->AppendTargetOutputs( - target.get(), phonyAlias.Outputs, ""); + target.get(), phonyAlias.Outputs, "", DependOnTargetArtifact); this->GetGlobalNinjaGenerator()->AppendTargetOutputs( - target.get(), phonyAlias.ExplicitDeps, config); + target.get(), phonyAlias.ExplicitDeps, config, + DependOnTargetArtifact); this->GetGlobalNinjaGenerator()->WriteBuild( *this->GetGlobalNinjaGenerator()->GetConfigFileStream(config), phonyAlias); @@ -115,11 +134,12 @@ void cmLocalNinjaGenerator::Generate() if (!this->GetGlobalNinjaGenerator()->GetDefaultConfigs().empty()) { cmNinjaBuild phonyAlias("phony"); this->GetGlobalNinjaGenerator()->AppendTargetOutputs( - target.get(), phonyAlias.Outputs, ""); + target.get(), phonyAlias.Outputs, "", DependOnTargetArtifact); for (auto const& config : this->GetGlobalNinjaGenerator()->GetDefaultConfigs()) { this->GetGlobalNinjaGenerator()->AppendTargetOutputs( - target.get(), phonyAlias.ExplicitDeps, config); + target.get(), phonyAlias.ExplicitDeps, config, + DependOnTargetArtifact); } this->GetGlobalNinjaGenerator()->WriteBuild( *this->GetGlobalNinjaGenerator()->GetDefaultFileStream(), @@ -127,10 +147,11 @@ void cmLocalNinjaGenerator::Generate() } cmNinjaBuild phonyAlias("phony"); this->GetGlobalNinjaGenerator()->AppendTargetOutputs( - target.get(), phonyAlias.Outputs, "all"); + target.get(), phonyAlias.Outputs, "all", DependOnTargetArtifact); for (auto const& config : this->GetConfigNames()) { this->GetGlobalNinjaGenerator()->AppendTargetOutputs( - target.get(), phonyAlias.ExplicitDeps, config); + target.get(), phonyAlias.ExplicitDeps, config, + DependOnTargetArtifact); } this->GetGlobalNinjaGenerator()->WriteBuild( *this->GetGlobalNinjaGenerator()->GetDefaultFileStream(), @@ -291,7 +312,7 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os) cmProp jobpools = this->GetCMakeInstance()->GetState()->GetGlobalProperty("JOB_POOLS"); if (!jobpools) { - jobpools = this->GetMakefile()->GetDef("CMAKE_JOB_POOLS"); + jobpools = this->GetMakefile()->GetDefinition("CMAKE_JOB_POOLS"); } if (jobpools) { cmGlobalNinjaGenerator::WriteComment( @@ -342,7 +363,7 @@ void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); os << "# Write statements declared in CMakeLists.txt:\n" - << "# " << this->Makefile->GetDefinition("CMAKE_CURRENT_LIST_FILE") + << "# " << this->Makefile->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE") << '\n'; if (this->IsRootMakefile()) { os << "# Which is the root file.\n"; @@ -355,8 +376,8 @@ void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs, const std::string& config) { - this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs, - config); + this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs, config, + DependOnTargetArtifact); } void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target, @@ -668,7 +689,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( { cmProp property_value = this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM"); - if (!property_value || property_value->empty()) { + if (!cmNonempty(property_value)) { return std::string(); } diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index ef160e7..e81402c 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLocalNinjaGenerator_h -#define cmLocalNinjaGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -66,10 +65,10 @@ public: void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs, const std::string& config); - void AppendTargetDepends( - cmGeneratorTarget* target, cmNinjaDeps& outputs, const std::string& config, - const std::string& fileConfig, - cmNinjaTargetDepends depends = DependOnTargetArtifact); + void AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs, + const std::string& config, + const std::string& fileConfig, + cmNinjaTargetDepends depends); void AddCustomCommandTarget(cmCustomCommand const* cc, cmGeneratorTarget* target); @@ -121,5 +120,3 @@ private: CustomCommandTargetMap CustomCommandTargets; std::vector<cmCustomCommand const*> CustomCommands; }; - -#endif // ! cmLocalNinjaGenerator_h diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index de1461a..c877cf8 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -38,6 +38,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTargetDepend.h" #include "cmVersion.h" #include "cmake.h" @@ -100,12 +101,22 @@ void cmLocalUnixMakefileGenerator3::Generate() // Generate the rule files for each target. cmGlobalUnixMakefileGenerator3* gg = static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator); - for (const auto& target : this->GetGeneratorTargets()) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + for (cmGeneratorTarget* gt : + this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this)) { + if (!gt->IsInBuildSystem()) { continue; } + + auto& gtVisited = this->GetCommandsVisited(gt); + auto& deps = this->GlobalGenerator->GetTargetDirectDepends(gt); + for (auto& d : deps) { + // Take the union of visited source files of custom commands + auto depVisited = this->GetCommandsVisited(d); + gtVisited.insert(depVisited.begin(), depVisited.end()); + } + std::unique_ptr<cmMakefileTargetGenerator> tg( - cmMakefileTargetGenerator::New(target.get())); + cmMakefileTargetGenerator::New(gt)); if (tg) { tg->WriteRuleFiles(); gg->RecordTargetProgress(tg.get()); @@ -137,7 +148,7 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles( std::map<std::string, LocalObjectInfo>& localObjectFiles) { for (const auto& gt : this->GetGeneratorTargets()) { - if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!gt->CanCompileSources()) { continue; } std::vector<cmSourceFile const*> objectSources; @@ -235,7 +246,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() for (LocalObjectEntry const& entry : localObjectFile.second) { if (entry.Language == "C" || entry.Language == "CXX" || - entry.Language == "CUDA" || entry.Language == "Fortran") { + entry.Language == "CUDA" || entry.Language == "Fortran" || + entry.Language == "ISPC") { // Right now, C, C++, Fortran and CUDA have both a preprocessor and the // ability to generate assembly code lang_has_preprocessor = true; @@ -518,9 +530,9 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule( // Mark the rule as symbolic if requested. if (symbolic) { - if (const char* sym = + if (cmProp sym = this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE")) { - os << tgt << space << ": " << sym << "\n"; + os << tgt << space << ": " << *sym << "\n"; } } @@ -832,9 +844,8 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepend( { // Add a dependency on the rule file itself unless an option to skip // it is specifically enabled by the user or project. - const char* nodep = - this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY"); - if (!nodep || cmIsOff(nodep)) { + cmProp nodep = this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY"); + if (cmIsOff(nodep)) { depends.emplace_back(ruleFileName); } } @@ -950,7 +961,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( std::string launcher; // Short-circuit if there is no launcher. const char* val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM"); - if (val && *val) { + if (cmNonempty(val)) { // Expand rule variables referenced in the given launcher command. cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = target->GetName().c_str(); @@ -1394,22 +1405,22 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( // Lookup useful directory information. if (haveDirectoryInfo) { // Test whether we need to force Unix paths. - if (const char* force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS")) { + if (cmProp force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS")) { if (!cmIsOff(force)) { cmSystemTools::SetForceUnixPaths(true); } } // Setup relative path top directories. - if (const char* relativePathTopSource = + if (cmProp relativePathTopSource = mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE")) { this->StateSnapshot.GetDirectory().SetRelativePathTopSource( - relativePathTopSource); + relativePathTopSource->c_str()); } - if (const char* relativePathTopBinary = + if (cmProp relativePathTopBinary = mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY")) { this->StateSnapshot.GetDirectory().SetRelativePathTopBinary( - relativePathTopBinary); + relativePathTopBinary->c_str()); } } else { cmSystemTools::Error("Directory Information file not found"); @@ -1444,7 +1455,8 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( // Create the scanner for this language std::unique_ptr<cmDepends> scanner; if (lang == "C" || lang == "CXX" || lang == "RC" || lang == "ASM" || - lang == "OBJC" || lang == "OBJCXX" || lang == "CUDA") { + lang == "OBJC" || lang == "OBJCXX" || lang == "CUDA" || + lang == "ISPC") { // TODO: Handle RC (resource files) dependencies correctly. scanner = cm::make_unique<cmDependsC>(this, targetDir, lang, &validDeps); } @@ -1476,13 +1488,13 @@ void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose) cmMakefile* mf = this->Makefile; // Get the string listing the multiple output pairs. - const char* pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS"); + cmProp pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS"); if (!pairs_string) { return; } // Convert the string to a list and preserve empty entries. - std::vector<std::string> pairs = cmExpandedList(pairs_string, true); + std::vector<std::string> pairs = cmExpandedList(*pairs_string, true); for (auto i = pairs.begin(); i != pairs.end() && (i + 1) != pairs.end();) { const std::string& depender = *i++; const std::string& dependee = *i++; @@ -1648,9 +1660,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/preinstall"); commands.clear(); depends.clear(); - const char* noall = + cmProp noall = this->Makefile->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); - if (!noall || cmIsOff(noall)) { + if (cmIsOff(noall)) { // Drive the build before installing. depends.emplace_back("all"); } else if (regenerate) { @@ -1698,11 +1710,11 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf, bool verbose) { // Get the list of target files to check - const char* infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES"); + cmProp infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES"); if (!infoDef) { return; } - std::vector<std::string> files = cmExpandedList(infoDef); + std::vector<std::string> files = cmExpandedList(*infoDef); // Each depend information file corresponds to a target. Clear the // dependencies for that target. @@ -1744,7 +1756,7 @@ public: return false; } // If it's an absolute path, check if it starts with the source - // direcotory: + // directory: return ( !(IsInDirectory(SourceDir, path) || IsInDirectory(BinaryDir, path))); } @@ -1806,10 +1818,10 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( // Tell the dependency scanner what compiler is used. std::string cidVar = cmStrCat("CMAKE_", implicitLang.first, "_COMPILER_ID"); - const char* cid = this->Makefile->GetDefinition(cidVar); - if (cid && *cid) { + cmProp cid = this->Makefile->GetDefinition(cidVar); + if (cmNonempty(cid)) { cmakefileStream << "set(CMAKE_" << implicitLang.first - << "_COMPILER_ID \"" << cid << "\")\n"; + << "_COMPILER_ID \"" << *cid << "\")\n"; } if (implicitLang.first == "Fortran") { diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 2b07952..8286d67 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLocalUnixMakefileGenerator3_h -#define cmLocalUnixMakefileGenerator3_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -20,6 +19,7 @@ class cmCustomCommandGenerator; class cmGeneratorTarget; class cmGlobalGenerator; class cmMakefile; +class cmSourceFile; /** \class cmLocalUnixMakefileGenerator3 * \brief Write a LocalUnix makefiles. @@ -295,6 +295,13 @@ private: bool ColorMakefile; bool SkipPreprocessedSourceRules; bool SkipAssemblySourceRules; -}; -#endif + std::set<cmSourceFile const*>& GetCommandsVisited( + cmGeneratorTarget const* target) + { + return this->CommandsVisited[target]; + }; + + std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>> + CommandsVisited; +}; diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index 9076e26..3ed49a0 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -66,33 +66,11 @@ cmLocalVisualStudio10Generator::~cmLocalVisualStudio10Generator() { } -void cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst( - cmGeneratorTarget* target, std::vector<cmGeneratorTarget*>& remaining) +void cmLocalVisualStudio10Generator::GenerateTarget(cmGeneratorTarget* target) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - return; - } - // Find this target in the list of remaining targets. - auto it = std::find(remaining.begin(), remaining.end(), target); - if (it == remaining.end()) { - // This target was already handled. - return; - } - // Remove this target from the list of remaining targets because - // we are handling it now. - *it = nullptr; - auto& deps = this->GlobalGenerator->GetTargetDirectDepends(target); - for (auto& d : deps) { - // FIXME: Revise CreateSingleVCProj so we do not have to drop `const` here. - auto dependee = const_cast<cmGeneratorTarget*>(&*d); - GenerateTargetsDepthFirst(dependee, remaining); - // Take the union of visited source files of custom commands - auto visited = GetSourcesVisited(dependee); - GetSourcesVisited(target).insert(visited.begin(), visited.end()); - } if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator) ->TargetIsFortranOnly(target)) { - this->CreateSingleVCProj(target->GetName(), target); + this->cmLocalVisualStudio7Generator::GenerateTarget(target); } else { cmVisualStudio10TargetGenerator tg( target, @@ -102,18 +80,6 @@ void cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst( } } -void cmLocalVisualStudio10Generator::Generate() -{ - std::vector<cmGeneratorTarget*> remaining; - cm::append(remaining, this->GetGeneratorTargets()); - for (auto& t : remaining) { - if (t) { - this->GenerateTargetsDepthFirst(t, remaining); - } - } - this->WriteStampFiles(); -} - void cmLocalVisualStudio10Generator::ReadAndStoreExternalGUID( const std::string& name, const char* path) { diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h index 5c6400e..45ee082 100644 --- a/Source/cmLocalVisualStudio10Generator.h +++ b/Source/cmLocalVisualStudio10Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLocalVisualStudio10Generator_h -#define cmLocalVisualStudio10Generator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -26,26 +25,13 @@ public: virtual ~cmLocalVisualStudio10Generator(); - /** - * Generate the makefile for this directory. - */ - void Generate() override; void ReadAndStoreExternalGUID(const std::string& name, const char* path) override; - std::set<cmSourceFile const*>& GetSourcesVisited(cmGeneratorTarget* target) - { - return SourcesVisited[target]; - }; - protected: const char* ReportErrorLabel() const override; bool CustomCommandUseLocal() const override { return true; } private: - void GenerateTargetsDepthFirst(cmGeneratorTarget* target, - std::vector<cmGeneratorTarget*>& remaining); - - std::map<cmGeneratorTarget*, std::set<cmSourceFile const*>> SourcesVisited; + void GenerateTarget(cmGeneratorTarget* target) override; }; -#endif diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 5d50e2d..7795654 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -66,7 +66,7 @@ void cmLocalVisualStudio7Generator::AddHelperCommands() // Now create GUIDs for targets const auto& tgts = this->GetGeneratorTargets(); for (const auto& l : tgts) { - if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!l->IsInBuildSystem()) { continue; } cmProp path = l->GetProperty("EXTERNAL_MSPROJECT"); @@ -80,7 +80,24 @@ void cmLocalVisualStudio7Generator::AddHelperCommands() void cmLocalVisualStudio7Generator::Generate() { - this->WriteProjectFiles(); + // Create the project file for each target. + for (cmGeneratorTarget* gt : + this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this)) { + if (!gt->IsInBuildSystem() || gt->GetProperty("EXTERNAL_MSPROJECT")) { + continue; + } + + auto& gtVisited = this->GetSourcesVisited(gt); + auto& deps = this->GlobalGenerator->GetTargetDirectDepends(gt); + for (auto& d : deps) { + // Take the union of visited source files of custom commands + auto depVisited = this->GetSourcesVisited(d); + gtVisited.insert(depVisited.begin(), depVisited.end()); + } + + this->GenerateTarget(gt); + } + this->WriteStampFiles(); } @@ -111,35 +128,6 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() } } -// TODO -// for CommandLine= need to repleace quotes with " -// write out configurations -void cmLocalVisualStudio7Generator::WriteProjectFiles() -{ - // If not an in source build, then create the output directory - if (this->GetCurrentBinaryDirectory() != this->GetSourceDirectory()) { - if (!cmSystemTools::MakeDirectory(this->GetCurrentBinaryDirectory())) { - cmSystemTools::Error("Error creating directory " + - this->GetCurrentBinaryDirectory()); - } - } - - // Get the set of targets in this directory. - const auto& tgts = this->GetGeneratorTargets(); - - // Create the project file for each target. - for (const auto& l : tgts) { - if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - continue; - } - // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace - // so don't build a projectfile for it - if (!l->GetProperty("EXTERNAL_MSPROJECT")) { - this->CreateSingleVCProj(l->GetName(), l.get()); - } - } -} - void cmLocalVisualStudio7Generator::WriteStampFiles() { // Touch a timestamp file used to determine when the project file is @@ -178,9 +166,9 @@ void cmLocalVisualStudio7Generator::WriteStampFiles() } } -void cmLocalVisualStudio7Generator::CreateSingleVCProj( - const std::string& lname, cmGeneratorTarget* target) +void cmLocalVisualStudio7Generator::GenerateTarget(cmGeneratorTarget* target) { + std::string const& lname = target->GetName(); cmGlobalVisualStudioGenerator* gg = static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator); this->FortranProject = gg->TargetIsFortranOnly(target); @@ -593,8 +581,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( std::ostream& fout, const std::string& configName, const std::string& libName, cmGeneratorTarget* target) { - const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG"); - if (!mfcFlag) { + std::string mfcFlag; + if (cmProp p = this->Makefile->GetDefinition("CMAKE_MFC_FLAG")) { + mfcFlag = *p; + } else { mfcFlag = "0"; } cmGlobalVisualStudio7Generator* gg = @@ -629,9 +619,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( break; case cmStateEnums::UTILITY: case cmStateEnums::GLOBAL_TARGET: + case cmStateEnums::INTERFACE_LIBRARY: configType = "10"; CM_FALLTHROUGH; - default: + case cmStateEnums::UNKNOWN_LIBRARY: targetBuilds = false; break; } @@ -1086,9 +1077,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( } } std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE"); - const char* stackVal = this->Makefile->GetDefinition(stackVar); + cmProp stackVal = this->Makefile->GetDefinition(stackVar); if (stackVal) { - fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"\n"; + fout << "\t\t\t\tStackReserveSize=\"" << *stackVal << "\"\n"; } temp = cmStrCat( target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact), @@ -1112,7 +1103,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( cmComputeLinkInformation& cli = *pcli; std::string linkLanguage = cli.GetLinkLanguage(); - bool isWin32Executable = target->GetPropertyAsBool("WIN32_EXECUTABLE"); + bool isWin32Executable = target->IsWin32Executable(configName); // Compute the variable name to lookup standard libraries for this // language. @@ -1175,9 +1166,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( << "\"\n"; } std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE"); - const char* stackVal = this->Makefile->GetDefinition(stackVar); + cmProp stackVal = this->Makefile->GetDefinition(stackVar); if (stackVal) { - fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\""; + fout << "\t\t\t\tStackReserveSize=\"" << *stackVal << "\""; } temp = cmStrCat( target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact), @@ -1331,8 +1322,8 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, const std::string& libName, cmGeneratorTarget* target) { - std::vector<std::string> configs; - this->Makefile->GetConfigurations(configs); + std::vector<std::string> configs = + this->Makefile->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); // We may be modifying the source groups temporarily, so make a copy. std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); @@ -1580,8 +1571,9 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( std::string cmLocalVisualStudio7Generator::ComputeLongestObjectDirectory( cmGeneratorTarget const* target) const { - std::vector<std::string> configs; - target->Target->GetMakefile()->GetConfigurations(configs); + std::vector<std::string> configs = + target->Target->GetMakefile()->GetGeneratorConfigs( + cmMakefile::ExcludeEmptyConfig); // Compute the maximum length configuration name. std::string config_max; @@ -1632,12 +1624,15 @@ bool cmLocalVisualStudio7Generator::WriteGroup( this->WriteVCProjBeginGroup(fout, name.c_str(), ""); } + auto& sourcesVisited = this->GetSourcesVisited(target); + // Loop through each source in the source group. for (const cmSourceFile* sf : sourceFiles) { std::string source = sf->GetFullPath(); if (source != libName || target->GetType() == cmStateEnums::UTILITY || - target->GetType() == cmStateEnums::GLOBAL_TARGET) { + target->GetType() == cmStateEnums::GLOBAL_TARGET || + target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { // Look up the source kind and configs. std::map<cmSourceFile const*, size_t>::const_iterator map_it = sources.Index.find(sf); @@ -1654,7 +1649,10 @@ bool cmLocalVisualStudio7Generator::WriteGroup( // build it, then it will. fout << "\t\t\t\tRelativePath=\"" << d << "\">\n"; if (cmCustomCommand const* command = sf->GetCustomCommand()) { - this->WriteCustomRule(fout, configs, source.c_str(), *command, fcinfo); + if (sourcesVisited.insert(sf).second) { + this->WriteCustomRule(fout, configs, source.c_str(), *command, + fcinfo); + } } else if (!fcinfo.FileConfigMap.empty()) { const char* aCompilerTool = "VCCLCompilerTool"; std::string ppLang = "CXX"; @@ -1936,6 +1934,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran( const char* keyword = p ? p->c_str() : "Console Application"; const char* projectType = 0; switch (target->GetType()) { + case cmStateEnums::OBJECT_LIBRARY: case cmStateEnums::STATIC_LIBRARY: projectType = "typeStaticLibrary"; if (keyword) { @@ -1957,7 +1956,8 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran( break; case cmStateEnums::UTILITY: case cmStateEnums::GLOBAL_TARGET: - default: + case cmStateEnums::INTERFACE_LIBRARY: + case cmStateEnums::UNKNOWN_LIBRARY: break; } if (projectType) { diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 8b9b8ad..6e06c09 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLocalVisualStudio7Generator_h -#define cmLocalVisualStudio7Generator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -84,8 +83,14 @@ public: virtual void ReadAndStoreExternalGUID(const std::string& name, const char* path); + std::set<cmSourceFile const*>& GetSourcesVisited( + cmGeneratorTarget const* target) + { + return this->SourcesVisited[target]; + }; + protected: - void CreateSingleVCProj(const std::string& lname, cmGeneratorTarget* tgt); + virtual void GenerateTarget(cmGeneratorTarget* target); private: using Options = cmVS7GeneratorOptions; @@ -93,7 +98,6 @@ private: std::string GetBuildTypeLinkerFlags(std::string rootLinkerFlags, const std::string& configName); void FixGlobalTargets(); - void WriteProjectFiles(); void WriteVCProjHeader(std::ostream& fout, const std::string& libName, cmGeneratorTarget* tgt, std::vector<cmSourceGroup>& sgs); @@ -150,6 +154,7 @@ private: bool FortranProject; bool WindowsCEProject; std::unique_ptr<cmLocalVisualStudio7GeneratorInternals> Internal; -}; -#endif + std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>> + SourcesVisited; +}; diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index ebd4f96..6d6ed9f 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -172,13 +172,12 @@ std::string cmLocalVisualStudioGenerator::ConstructScript( // for visual studio IDE add extra stuff to the PATH // if CMAKE_MSVCIDE_RUN_PATH is set. if (this->Makefile->GetDefinition("MSVC_IDE")) { - const char* extraPath = - this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH"); + cmProp extraPath = this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH"); if (extraPath) { script += newline; newline = newline_text; script += "set PATH="; - script += extraPath; + script += *extraPath; script += ";%PATH%"; } } diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index 585eb3c..91fb6b0 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLocalVisualStudioGenerator_h -#define cmLocalVisualStudioGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -56,5 +55,3 @@ protected: std::unique_ptr<cmCustomCommand> MaybeCreateImplibDir( cmGeneratorTarget* target, const std::string& config, bool isFortran); }; - -#endif diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h index 42de20b..dd038b4 100644 --- a/Source/cmLocalXCodeGenerator.h +++ b/Source/cmLocalXCodeGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLocalXCodeGenerator_h -#define cmLocalXCodeGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -40,5 +39,3 @@ public: private: }; - -#endif diff --git a/Source/cmLocale.h b/Source/cmLocale.h index c44a42d..f7636ac 100644 --- a/Source/cmLocale.h +++ b/Source/cmLocale.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmLocale_h -#define cmLocale_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -25,5 +24,3 @@ public: private: std::string OldLocale; }; - -#endif diff --git a/Source/cmMSVC60LinkLineComputer.h b/Source/cmMSVC60LinkLineComputer.h index d767914..0a303ab 100644 --- a/Source/cmMSVC60LinkLineComputer.h +++ b/Source/cmMSVC60LinkLineComputer.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMSVC60LinkLineComputer_h -#define cmMSVC60LinkLineComputer_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -25,5 +24,3 @@ public: std::string ConvertToLinkReference(std::string const& input) const override; }; - -#endif diff --git a/Source/cmMachO.h b/Source/cmMachO.h index 0c44b55..be92c95 100644 --- a/Source/cmMachO.h +++ b/Source/cmMachO.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMachO_h -#define cmMachO_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -43,5 +42,3 @@ private: bool Valid() const; std::unique_ptr<cmMachOInternal> Internal; }; - -#endif diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h index 25091ea..b65a887 100644 --- a/Source/cmMacroCommand.h +++ b/Source/cmMacroCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMacroCommand_h -#define cmMacroCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -13,5 +12,3 @@ class cmExecutionStatus; /// Starts macro() ... endmacro() block bool cmMacroCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmMakeDirectoryCommand.h b/Source/cmMakeDirectoryCommand.h index 2474383..340bca8 100644 --- a/Source/cmMakeDirectoryCommand.h +++ b/Source/cmMakeDirectoryCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMakeDirectoryCommand_h -#define cmMakeDirectoryCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -21,5 +20,3 @@ class cmExecutionStatus; */ bool cmMakeDirectoryCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index db5cee9..d77c4af 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -20,8 +20,10 @@ #include <cmext/algorithm> #include <cmext/string_view> -#include <cm3p/json/value.h> -#include <cm3p/json/writer.h> +#ifndef CMAKE_BOOTSTRAP +# include <cm3p/json/value.h> +# include <cm3p/json/writer.h> +#endif #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" @@ -34,6 +36,7 @@ #include "cmExecutionStatus.h" #include "cmExpandedCommandArgument.h" // IWYU pragma: keep #include "cmExportBuildFileGenerator.h" +#include "cmFSPermissions.h" #include "cmFileLockPool.h" #include "cmFunctionBlocker.h" #include "cmGeneratedFileStream.h" @@ -68,6 +71,8 @@ class cmMessenger; +using namespace cmFSPermissions; + cmDirectoryId::cmDirectoryId(std::string s) : String(std::move(s)) { @@ -82,7 +87,6 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, { this->IsSourceFileTryCompile = false; - this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused(); this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars(); this->SuppressSideEffects = false; @@ -190,18 +194,18 @@ void cmMakefile::MaybeWarnCMP0074(std::string const& pkg) { // Warn if a <pkg>_ROOT variable we may use is set. std::string const varName = pkg + "_ROOT"; - const char* var = this->GetDefinition(varName); + cmProp var = this->GetDefinition(varName); std::string env; cmSystemTools::GetEnv(varName, env); - bool const haveVar = var && *var; + bool const haveVar = cmNonempty(var); bool const haveEnv = !env.empty(); if ((haveVar || haveEnv) && this->WarnedCMP0074.insert(varName).second) { std::ostringstream w; w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0074) << "\n"; if (haveVar) { w << "CMake variable " << varName << " is set to:\n" - << " " << var << "\n"; + << " " << *var << "\n"; } if (haveEnv) { w << "Environment variable " << varName << " is set to:\n" @@ -437,9 +441,9 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, // Check for maximum recursion depth. int depth = CMake_DEFAULT_RECURSION_LIMIT; - const char* depthStr = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); + cmProp depthStr = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); if (depthStr) { - std::istringstream s(depthStr); + std::istringstream s(*depthStr); int d; if (s >> d) { depth = d; @@ -623,8 +627,8 @@ void cmMakefile::IncludeScope::EnforceCMP0011() bool cmMakefile::ReadDependentFile(const std::string& filename, bool noPolicyScope) { - if (const char* def = this->GetDefinition("CMAKE_CURRENT_LIST_FILE")) { - this->AddDefinition("CMAKE_PARENT_LIST_FILE", def); + if (cmProp def = this->GetDefinition("CMAKE_CURRENT_LIST_FILE")) { + this->AddDefinition("CMAKE_PARENT_LIST_FILE", *def); } std::string filenametoread = cmSystemTools::CollapseFullPath( filename, this->GetCurrentSourceDirectory()); @@ -750,7 +754,6 @@ void cmMakefile::ReadListFile(cmListFile const& listFile, break; } } - this->CheckForUnusedVariables(); this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile); this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile); @@ -798,15 +801,15 @@ void cmMakefile::EnforceDirectoryLevelRules() const } void cmMakefile::AddEvaluationFile( - const std::string& inputFile, + const std::string& inputFile, const std::string& targetName, std::unique_ptr<cmCompiledGeneratorExpression> outputName, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent) { this->EvaluationFiles.push_back( cm::make_unique<cmGeneratorExpressionEvaluationFile>( - inputFile, std::move(outputName), std::move(condition), inputIsContent, - this->GetPolicyStatus(cmPolicies::CMP0070))); + inputFile, targetName, std::move(outputName), std::move(condition), + inputIsContent, this->GetPolicyStatus(cmPolicies::CMP0070))); } const std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>& @@ -888,9 +891,10 @@ void cmMakefile::DoGenerate(cmLocalGenerator& lg) void cmMakefile::Generate(cmLocalGenerator& lg) { this->DoGenerate(lg); - const char* oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); + cmProp oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); if (oldValue && - cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) { + cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue->c_str(), + "2.4")) { this->GetCMakeInstance()->IssueMessage( MessageType::FATAL_ERROR, "You have set CMAKE_BACKWARDS_COMPATIBILITY to a CMake version less " @@ -1426,31 +1430,31 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent) { const char* prop = "IMPLICIT_DEPENDS_INCLUDE_TRANSFORM"; cmProp p = parent->GetProperty(prop); - this->SetProperty(prop, p ? p->c_str() : nullptr); + this->SetProperty(prop, cmToCStr(p)); } // compile definitions property and per-config versions cmPolicies::PolicyStatus polSt = this->GetPolicyStatus(cmPolicies::CMP0043); if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) { cmProp p = parent->GetProperty("COMPILE_DEFINITIONS"); - this->SetProperty("COMPILE_DEFINITIONS", p ? p->c_str() : nullptr); - std::vector<std::string> configs; - this->GetConfigurations(configs); + this->SetProperty("COMPILE_DEFINITIONS", cmToCStr(p)); + std::vector<std::string> configs = + this->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); for (std::string const& config : configs) { std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config)); cmProp prop = parent->GetProperty(defPropName); - this->SetProperty(defPropName, prop ? prop->c_str() : nullptr); + this->SetProperty(defPropName, cmToCStr(prop)); } } // labels cmProp p = parent->GetProperty("LABELS"); - this->SetProperty("LABELS", p ? p->c_str() : nullptr); + this->SetProperty("LABELS", cmToCStr(p)); // link libraries p = parent->GetProperty("LINK_LIBRARIES"); - this->SetProperty("LINK_LIBRARIES", p ? p->c_str() : nullptr); + this->SetProperty("LINK_LIBRARIES", cmToCStr(p)); // the initial project name this->StateSnapshot.SetProjectName(parent->StateSnapshot.GetProjectName()); @@ -1513,8 +1517,6 @@ void cmMakefile::PopFunctionScope(bool reportError) #endif this->PopLoopBlockBarrier(); - - this->CheckForUnusedVariables(); } void cmMakefile::PushMacroScope(std::string const& fileName, @@ -1661,7 +1663,8 @@ void cmMakefile::Configure() this->SetCheckCMP0000(true); // Implicitly set the version for the user. - this->SetPolicyVersion("2.4", std::string()); + cmPolicies::ApplyPolicyVersion(this, 2, 4, 0, + cmPolicies::WarnCompat::Off); } } bool hasProject = false; @@ -1860,9 +1863,6 @@ void cmMakefile::AddSystemIncludeDirectories(const std::set<std::string>& incs) void cmMakefile::AddDefinition(const std::string& name, cm::string_view value) { - if (this->VariableInitialized(name)) { - this->LogUnused("changing definition", name); - } this->StateSnapshot.SetDefinition(name, value); #ifndef CMAKE_BOOTSTRAP @@ -1923,16 +1923,6 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, this->StateSnapshot.RemoveDefinition(name); } -void cmMakefile::CheckForUnusedVariables() const -{ - if (!this->WarnUnused) { - return; - } - for (const std::string& key : this->StateSnapshot.UnusedKeys()) { - this->LogUnused("out of scope", key); - } -} - void cmMakefile::MarkVariableAsUsed(const std::string& var) { this->StateSnapshot.GetDefinition(var); @@ -1960,29 +1950,8 @@ void cmMakefile::MaybeWarnUninitialized(std::string const& variable, } } -void cmMakefile::LogUnused(const char* reason, const std::string& name) const -{ - if (this->WarnUnused) { - std::string path; - if (!this->ExecutionStatusStack.empty()) { - path = this->GetExecutionContext().FilePath; - } else { - path = cmStrCat(this->GetCurrentSourceDirectory(), "/CMakeLists.txt"); - } - - if (this->CheckSystemVars || this->IsProjectFile(path.c_str())) { - std::ostringstream msg; - msg << "unused variable (" << reason << ") \'" << name << "\'"; - this->IssueMessage(MessageType::AUTHOR_WARNING, msg.str()); - } - } -} - void cmMakefile::RemoveDefinition(const std::string& name) { - if (this->VariableInitialized(name)) { - this->LogUnused("unsetting", name); - } this->StateSnapshot.RemoveDefinition(name); #ifndef CMAKE_BOOTSTRAP cmVariableWatch* vv = this->GetVariableWatch(); @@ -2410,8 +2379,10 @@ cmSourceGroup* cmMakefile::GetOrCreateSourceGroup( cmSourceGroup* cmMakefile::GetOrCreateSourceGroup(const std::string& name) { - const char* delimiters = this->GetDefinition("SOURCE_GROUP_DELIMITER"); - if (delimiters == nullptr) { + std::string delimiters; + if (cmProp p = this->GetDefinition("SOURCE_GROUP_DELIMITER")) { + delimiters = *p; + } else { delimiters = "/\\"; } return this->GetOrCreateSourceGroup(cmTokenize(name, delimiters)); @@ -2555,22 +2526,21 @@ void cmMakefile::ExpandVariablesCMP0019() bool cmMakefile::IsOn(const std::string& name) const { - const char* value = this->GetDefinition(name); - return cmIsOn(value); + return cmIsOn(this->GetDefinition(name)); } bool cmMakefile::IsSet(const std::string& name) const { - const char* value = this->GetDefinition(name); + cmProp value = this->GetDefinition(name); if (!value) { return false; } - if (!*value) { + if (value->empty()) { return false; } - if (cmIsNOTFOUND(value)) { + if (cmIsNOTFOUND(*value)) { return false; } @@ -2579,31 +2549,29 @@ bool cmMakefile::IsSet(const std::string& name) const bool cmMakefile::PlatformIs32Bit() const { - if (const char* plat_abi = - this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) { - if (strcmp(plat_abi, "ELF X32") == 0) { + if (cmProp plat_abi = this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) { + if (*plat_abi == "ELF X32") { return false; } } - if (const char* sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) { - return atoi(sizeof_dptr) == 4; + if (cmProp sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) { + return atoi(sizeof_dptr->c_str()) == 4; } return false; } bool cmMakefile::PlatformIs64Bit() const { - if (const char* sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) { - return atoi(sizeof_dptr) == 8; + if (cmProp sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) { + return atoi(sizeof_dptr->c_str()) == 8; } return false; } bool cmMakefile::PlatformIsx32() const { - if (const char* plat_abi = - this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) { - if (strcmp(plat_abi, "ELF X32") == 0) { + if (cmProp plat_abi = this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) { + if (*plat_abi == "ELF X32") { return true; } } @@ -2652,7 +2620,7 @@ const char* cmMakefile::GetSONameFlag(const std::string& language) const name += language; } name += "_FLAG"; - return GetDefinition(name); + return cmToCStr(GetDefinition(name)); } bool cmMakefile::CanIWriteThisFile(std::string const& fileName) const @@ -2675,7 +2643,7 @@ const std::string& cmMakefile::GetRequiredDefinition( const std::string& name) const { static std::string const empty; - const std::string* def = GetDef(name); + const std::string* def = GetDefinition(name); if (!def) { cmSystemTools::Error("Error required internal CMake variable not " "set, cmake may not be built correctly.\n" @@ -2703,7 +2671,7 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const return def != nullptr; } -const std::string* cmMakefile::GetDef(const std::string& name) const +cmProp cmMakefile::GetDefinition(const std::string& name) const { cmProp def = this->StateSnapshot.GetDefinition(name); if (!def) { @@ -2716,7 +2684,7 @@ const std::string* cmMakefile::GetDef(const std::string& name) const vv->VariableAccessed(name, def ? cmVariableWatch::VARIABLE_READ_ACCESS : cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS, - (def ? def->c_str() : nullptr), this); + cmToCStr(def), this); if (watch_function_executed) { // A callback was executed and may have caused re-allocation of the @@ -2732,19 +2700,10 @@ const std::string* cmMakefile::GetDef(const std::string& name) const return def; } -const char* cmMakefile::GetDefinition(const std::string& name) const -{ - const std::string* def = GetDef(name); - if (!def) { - return nullptr; - } - return def->c_str(); -} - const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const { static std::string const empty; - const std::string* def = GetDef(name); + const std::string* def = GetDefinition(name); if (!def) { return empty; } @@ -2755,7 +2714,7 @@ bool cmMakefile::GetDefExpandList(const std::string& name, std::vector<std::string>& out, bool emptyArgs) const { - cmProp def = this->GetDef(name); + cmProp def = this->GetDefinition(name); if (!def) { return false; } @@ -2908,12 +2867,12 @@ MessageType cmMakefile::ExpandVariablesInStringOld( // Lookup the definition of VAR. std::string var(first + 1, last - first - 2); - if (const char* val = this->GetDefinition(var)) { + if (cmProp val = this->GetDefinition(var)) { // Store the value in the output escaping as requested. if (escapeQuotes) { - source.append(cmEscapeQuotes(val)); + source.append(cmEscapeQuotes(*val)); } else { - source.append(val); + source.append(*val); } } @@ -2939,7 +2898,7 @@ MessageType cmMakefile::ExpandVariablesInStringOld( parser.SetNoEscapeMode(noEscapes); parser.SetReplaceAtSyntax(replaceAt); parser.SetRemoveEmpty(removeEmpty); - int res = parser.ParseString(source.c_str(), 0); + int res = parser.ParseString(source, 0); const char* emsg = parser.GetError(); MessageType mtype = MessageType::LOG; if (res && !emsg[0]) { @@ -3059,7 +3018,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( if (filename && lookup == lineVar) { varresult = std::to_string(line); } else { - value = this->GetDef(lookup); + value = this->GetDefinition(lookup); } break; case ENVIRONMENT: @@ -3191,7 +3150,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( if (filename && variable == lineVar) { varresult = std::to_string(line); } else { - const std::string* def = this->GetDef(variable); + const std::string* def = this->GetDefinition(variable); if (def) { varresult = *def; } else if (!this->SuppressSideEffects) { @@ -3287,25 +3246,28 @@ void cmMakefile::RemoveVariablesInString(std::string& source, } } -std::string cmMakefile::GetConfigurations(std::vector<std::string>& configs, - bool singleConfig) const +std::string cmMakefile::GetDefaultConfiguration() const { if (this->GetGlobalGenerator()->IsMultiConfig()) { - this->GetDefExpandList("CMAKE_CONFIGURATION_TYPES", configs); - return ""; - } - const std::string& buildType = this->GetSafeDefinition("CMAKE_BUILD_TYPE"); - if (singleConfig && !buildType.empty()) { - configs.push_back(buildType); + return std::string{}; } - return buildType; + return this->GetSafeDefinition("CMAKE_BUILD_TYPE"); } -std::vector<std::string> cmMakefile::GetGeneratorConfigs() const +std::vector<std::string> cmMakefile::GetGeneratorConfigs( + GeneratorConfigQuery mode) const { std::vector<std::string> configs; - GetConfigurations(configs); - if (configs.empty()) { + if (this->GetGlobalGenerator()->IsMultiConfig() || + mode == cmMakefile::OnlyMultiConfig) { + this->GetDefExpandList("CMAKE_CONFIGURATION_TYPES", configs); + } else { + const std::string& buildType = this->GetSafeDefinition("CMAKE_BUILD_TYPE"); + if (!buildType.empty()) { + configs.emplace_back(buildType); + } + } + if (mode == cmMakefile::IncludeEmptyConfig && configs.empty()) { configs.emplace_back(); } return configs; @@ -3385,7 +3347,7 @@ bool cmMakefile::IsLoopBlock() const return !this->LoopBlockCounter.empty() && this->LoopBlockCounter.top() > 0; } -std::string cmMakefile::GetExecutionFilePath() const +std::string const& cmMakefile::GetExecutionFilePath() const { assert(this->StateSnapshot.IsValid()); return this->StateSnapshot.GetExecutionListFile(); @@ -3395,8 +3357,8 @@ bool cmMakefile::ExpandArguments(std::vector<cmListFileArgument> const& inArgs, std::vector<std::string>& outArgs, const char* filename) const { - std::string efp = this->GetExecutionFilePath(); if (!filename) { + auto const& efp = this->GetExecutionFilePath(); filename = efp.c_str(); } std::string value; @@ -3427,8 +3389,8 @@ bool cmMakefile::ExpandArguments( std::vector<cmListFileArgument> const& inArgs, std::vector<cmExpandedCommandArgument>& outArgs, const char* filename) const { - std::string efp = this->GetExecutionFilePath(); if (!filename) { + auto const& efp = this->GetExecutionFilePath(); filename = efp.c_str(); } std::string value; @@ -3706,26 +3668,25 @@ int cmMakefile::TryCompile(const std::string& srcdir, cm.SetGeneratorToolset(this->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET")); cm.LoadCache(); if (!cm.GetGlobalGenerator()->IsMultiConfig()) { - if (const char* config = + if (cmProp config = this->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION")) { // Tell the single-configuration generator which one to use. // Add this before the user-provided CMake arguments in case // one of the arguments is -DCMAKE_BUILD_TYPE=... - cm.AddCacheEntry("CMAKE_BUILD_TYPE", config, "Build configuration", - cmStateEnums::STRING); + cm.AddCacheEntry("CMAKE_BUILD_TYPE", config->c_str(), + "Build configuration", cmStateEnums::STRING); } } - const char* recursionDepth = - this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); + cmProp recursionDepth = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); if (recursionDepth) { - cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth, + cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth->c_str(), "Maximum recursion depth", cmStateEnums::STRING); } // if cmake args were provided then pass them in if (cmakeArgs) { // FIXME: Workaround to ignore unused CLI variables in try-compile. // - // Ideally we should use SetArgs to honor options like --warn-unused-vars. + // Ideally we should use SetArgs for options like --no-warn-unused-cli. // However, there is a subtle problem when certain arguments are passed to // a macro wrapping around try_compile or try_run that does not escape // semicolons in its parameters but just passes ${ARGV} or ${ARGN}. In @@ -3744,7 +3705,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, // the value VAR=a is sufficient for the try_compile or try_run to get the // correct result. Calling SetArgs here would break such projects that // previously built. Instead we work around the issue by never reporting - // unused arguments and ignoring options such as --warn-unused-vars. + // unused arguments and ignoring options such as --no-warn-unused-cli. cm.SetWarnUnusedCli(false); // cm.SetArgs(*cmakeArgs, true); @@ -3851,9 +3812,9 @@ std::string cmMakefile::GetModulesFile(const std::string& filename, std::string moduleInCMakeModulePath; // Always search in CMAKE_MODULE_PATH: - const char* cmakeModulePath = this->GetDefinition("CMAKE_MODULE_PATH"); + cmProp cmakeModulePath = this->GetDefinition("CMAKE_MODULE_PATH"); if (cmakeModulePath) { - std::vector<std::string> modulePath = cmExpandedList(cmakeModulePath); + std::vector<std::string> modulePath = cmExpandedList(*cmakeModulePath); // Look through the possible module directories. for (std::string itempl : modulePath) { @@ -3892,14 +3853,14 @@ std::string cmMakefile::GetModulesFile(const std::string& filename, } if (!moduleInCMakeModulePath.empty() && !moduleInCMakeRoot.empty()) { - const char* currentFile = this->GetDefinition("CMAKE_CURRENT_LIST_FILE"); + cmProp currentFile = this->GetDefinition("CMAKE_CURRENT_LIST_FILE"); std::string mods = cmSystemTools::GetCMakeRoot() + "/Modules/"; - if (currentFile && cmSystemTools::IsSubDirectory(currentFile, mods)) { + if (currentFile && cmSystemTools::IsSubDirectory(*currentFile, mods)) { switch (this->GetPolicyStatus(cmPolicies::CMP0017)) { case cmPolicies::WARN: { std::ostringstream e; /* clang-format off */ - e << "File " << currentFile << " includes " + e << "File " << *currentFile << " includes " << moduleInCMakeModulePath << " (found via CMAKE_MODULE_PATH) which shadows " << moduleInCMakeRoot << ". This may cause errors later on .\n" @@ -3949,7 +3910,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output, // Replace #cmakedefine instances. if (this->cmDefineRegex.find(line)) { - const char* def = this->GetDefinition(this->cmDefineRegex.match(2)); + cmProp def = this->GetDefinition(this->cmDefineRegex.match(2)); if (!cmIsOff(def)) { const std::string indentation = this->cmDefineRegex.match(1); cmSystemTools::ReplaceString(line, "#" + indentation + "cmakedefine", @@ -3962,7 +3923,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output, } } else if (this->cmDefine01Regex.find(line)) { const std::string indentation = this->cmDefine01Regex.match(1); - const char* def = this->GetDefinition(this->cmDefine01Regex.match(2)); + cmProp def = this->GetDefinition(this->cmDefine01Regex.match(2)); cmSystemTools::ReplaceString(line, "#" + indentation + "cmakedefine01", "#" + indentation + "define"); output += line; @@ -3998,6 +3959,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output, int cmMakefile::ConfigureFile(const std::string& infile, const std::string& outfile, bool copyonly, bool atOnly, bool escapeQuotes, + bool use_source_permissions, cmNewLineStyle newLine) { int res = 1; @@ -4021,7 +3983,13 @@ int cmMakefile::ConfigureFile(const std::string& infile, this->AddCMakeOutputFile(soutfile); mode_t perm = 0; - cmSystemTools::GetPermissions(sinfile, perm); + if (!use_source_permissions) { + perm = perm | mode_owner_read | mode_owner_write | mode_group_read | + mode_world_read; + } else { + cmSystemTools::GetPermissions(sinfile, perm); + } + std::string::size_type pos = soutfile.rfind('/'); if (pos != std::string::npos) { std::string path = soutfile.substr(0, pos); @@ -4030,6 +3998,13 @@ int cmMakefile::ConfigureFile(const std::string& infile, if (copyonly) { if (!cmSystemTools::CopyFileIfDifferent(sinfile, soutfile)) { + this->IssueMessage(MessageType::FATAL_ERROR, + cmSystemTools::GetLastSystemError()); + return 0; + } + if (!cmSystemTools::SetPermissions(soutfile, perm)) { + this->IssueMessage(MessageType::FATAL_ERROR, + cmSystemTools::GetLastSystemError()); return 0; } } else { @@ -4080,9 +4055,15 @@ int cmMakefile::ConfigureFile(const std::string& infile, fin.close(); fout.close(); if (!cmSystemTools::CopyFileIfDifferent(tempOutputFile, soutfile)) { + this->IssueMessage(MessageType::FATAL_ERROR, + cmSystemTools::GetLastSystemError()); res = 0; } else { - cmSystemTools::SetPermissions(soutfile, perm); + if (!cmSystemTools::SetPermissions(soutfile, perm)) { + this->IssueMessage(MessageType::FATAL_ERROR, + cmSystemTools::GetLastSystemError()); + res = 0; + } } cmSystemTools::RemoveFile(tempOutputFile); } @@ -4127,8 +4108,7 @@ cmProp cmMakefile::GetProperty(const std::string& prop, bool chain) const bool cmMakefile::GetPropertyAsBool(const std::string& prop) const { - cmProp p = this->GetProperty(prop); - return p && cmIsOn(*p); + return cmIsOn(this->GetProperty(prop)); } std::vector<std::string> cmMakefile::GetPropertyKeys() const @@ -4240,8 +4220,6 @@ void cmMakefile::PopScope() this->PopLoopBlockBarrier(); - this->CheckForUnusedVariables(); - this->PopSnapshot(); } @@ -4470,11 +4448,11 @@ static std::string const nMatchesVariable = "CMAKE_MATCH_COUNT"; void cmMakefile::ClearMatches() { - const char* nMatchesStr = this->GetDefinition(nMatchesVariable); + cmProp nMatchesStr = this->GetDefinition(nMatchesVariable); if (!nMatchesStr) { return; } - int nMatches = atoi(nMatchesStr); + int nMatches = atoi(nMatchesStr->c_str()); for (int i = 0; i <= nMatches; i++) { std::string const& var = matchVariables[i]; std::string const& s = this->GetSafeDefinition(var); @@ -4523,7 +4501,7 @@ cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id, bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var) { // Check for an explicit CMAKE_POLICY_WARNING_CMP<NNNN> setting. - if (const char* val = this->GetDefinition(var)) { + if (cmProp val = this->GetDefinition(var)) { return cmIsOn(val); } // Enable optional policy warnings with --debug-output, --trace, @@ -4557,7 +4535,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, // Deprecate old policies, especially those that require a lot // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0071 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0072 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. @@ -4599,7 +4577,7 @@ void cmMakefile::PopSnapshot(bool reportError) // cmStateSnapshot manages nested policy scopes within it. // Since the scope corresponding to the snapshot is closing, // reject any still-open nested policy scopes with an error. - while (!this->StateSnapshot.CanPopPolicyScope()) { + while (this->StateSnapshot.CanPopPolicyScope()) { if (reportError) { this->IssueMessage(MessageType::FATAL_ERROR, "cmake_policy PUSH without matching POP"); @@ -4615,7 +4593,8 @@ void cmMakefile::PopSnapshot(bool reportError) bool cmMakefile::SetPolicyVersion(std::string const& version_min, std::string const& version_max) { - return cmPolicies::ApplyPolicyVersion(this, version_min, version_max); + return cmPolicies::ApplyPolicyVersion(this, version_min, version_max, + cmPolicies::WarnCompat::On); } bool cmMakefile::HasCMP0054AlreadyBeenReported( @@ -4651,674 +4630,6 @@ bool cmMakefile::IgnoreErrorsCMP0061() const return ignoreErrors; } -#define FEATURE_STRING(F) , #F -static const char* const C_FEATURES[] = { nullptr FOR_EACH_C_FEATURE( - FEATURE_STRING) }; - -static const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE( - FEATURE_STRING) }; - -static const char* const CUDA_FEATURES[] = { nullptr FOR_EACH_CUDA_FEATURE( - FEATURE_STRING) }; -#undef FEATURE_STRING - -static const char* const C_STANDARDS[] = { "90", "99", "11" }; -static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17", "20" }; -static const char* const CUDA_STANDARDS[] = { "03", "11", "14", "17", "20" }; - -bool cmMakefile::AddRequiredTargetFeature(cmTarget* target, - const std::string& feature, - std::string* error) const -{ - if (cmGeneratorExpression::Find(feature) != std::string::npos) { - target->AppendProperty("COMPILE_FEATURES", feature); - return true; - } - - std::string lang; - if (!this->CompileFeatureKnown(target, feature, lang, error)) { - return false; - } - - const char* features = this->CompileFeaturesAvailable(lang, error); - if (!features) { - return false; - } - - std::vector<std::string> availableFeatures = cmExpandedList(features); - if (!cm::contains(availableFeatures, feature)) { - std::ostringstream e; - e << "The compiler feature \"" << feature << "\" is not known to " << lang - << " compiler\n\"" - << this->GetDefinition("CMAKE_" + lang + "_COMPILER_ID") - << "\"\nversion " - << this->GetDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << "."; - if (error) { - *error = e.str(); - } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), - this->Backtrace); - } - return false; - } - - target->AppendProperty("COMPILE_FEATURES", feature); - - if (lang == "C" || lang == "OBJC") { - return this->AddRequiredTargetCFeature(target, feature, lang, error); - } - if (lang == "CUDA") { - return this->AddRequiredTargetCudaFeature(target, feature, lang, error); - } - return this->AddRequiredTargetCxxFeature(target, feature, lang, error); -} - -bool cmMakefile::CompileFeatureKnown(cmTarget const* target, - const std::string& feature, - std::string& lang, - std::string* error) const -{ - assert(cmGeneratorExpression::Find(feature) == std::string::npos); - - bool isCFeature = - std::find_if(cm::cbegin(C_FEATURES) + 1, cm::cend(C_FEATURES), - cmStrCmp(feature)) != cm::cend(C_FEATURES); - if (isCFeature) { - lang = "C"; - return true; - } - bool isCxxFeature = - std::find_if(cm::cbegin(CXX_FEATURES) + 1, cm::cend(CXX_FEATURES), - cmStrCmp(feature)) != cm::cend(CXX_FEATURES); - if (isCxxFeature) { - lang = "CXX"; - return true; - } - bool isCudaFeature = - std::find_if(cm::cbegin(CUDA_FEATURES) + 1, cm::cend(CUDA_FEATURES), - cmStrCmp(feature)) != cm::cend(CUDA_FEATURES); - if (isCudaFeature) { - lang = "CUDA"; - return true; - } - std::ostringstream e; - if (error) { - e << "specified"; - } else { - e << "Specified"; - } - e << " unknown feature \"" << feature - << "\" for " - "target \"" - << target->GetName() << "\"."; - if (error) { - *error = e.str(); - } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), - this->Backtrace); - } - return false; -} - -const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang, - std::string* error) const -{ - if (!this->GlobalGenerator->GetLanguageEnabled(lang)) { - std::ostringstream e; - if (error) { - e << "cannot"; - } else { - e << "Cannot"; - } - e << " use features from non-enabled language " << lang; - if (error) { - *error = e.str(); - } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), - this->Backtrace); - } - return nullptr; - } - - const char* featuresKnown = - this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES"); - - if (!featuresKnown || !*featuresKnown) { - std::ostringstream e; - if (error) { - e << "no"; - } else { - e << "No"; - } - e << " known features for " << lang << " compiler\n\"" - << this->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID") - << "\"\nversion " - << this->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << "."; - if (error) { - *error = e.str(); - } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), - this->Backtrace); - } - return nullptr; - } - return featuresKnown; -} - -bool cmMakefile::HaveStandardAvailable(cmTarget const* target, - std::string const& lang, - const std::string& feature) const -{ - if (lang == "C" || lang == "OBJC") { - return this->HaveCStandardAvailable(target, feature, lang); - } - if (lang == "CUDA") { - return this->HaveCudaStandardAvailable(target, feature, lang); - } - return this->HaveCxxStandardAvailable(target, feature, lang); -} - -bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, - const std::string& feature, - std::string const& lang) const -{ - cmProp defaultCStandard = - this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); - if (!defaultCStandard) { - this->IssueMessage( - MessageType::INTERNAL_ERROR, - cmStrCat("CMAKE_", lang, - "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " - "not fully configured for this compiler.")); - // Return true so the caller does not try to lookup the default standard. - return true; - } - if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), - cmStrCmp(*defaultCStandard)) == cm::cend(C_STANDARDS)) { - const std::string e = cmStrCat("The CMAKE_", lang, - "_STANDARD_DEFAULT variable contains an " - "invalid value: \"", - *defaultCStandard, "\"."); - this->IssueMessage(MessageType::INTERNAL_ERROR, e); - return false; - } - - bool needC90 = false; - bool needC99 = false; - bool needC11 = false; - - this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11); - - cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD")); - if (!existingCStandard) { - existingCStandard = defaultCStandard; - } - - if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), - cmStrCmp(*existingCStandard)) == cm::cend(C_STANDARDS)) { - const std::string e = cmStrCat( - "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", *existingCStandard, "\"."); - this->IssueMessage(MessageType::FATAL_ERROR, e); - return false; - } - - const char* const* existingCIt = existingCStandard - ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), - cmStrCmp(*existingCStandard)) - : cm::cend(C_STANDARDS); - - if (needC11 && existingCStandard && - existingCIt < std::find_if(cm::cbegin(C_STANDARDS), - cm::cend(C_STANDARDS), cmStrCmp("11"))) { - return false; - } - if (needC99 && existingCStandard && - existingCIt < std::find_if(cm::cbegin(C_STANDARDS), - cm::cend(C_STANDARDS), cmStrCmp("99"))) { - return false; - } - if (needC90 && existingCStandard && - existingCIt < std::find_if(cm::cbegin(C_STANDARDS), - cm::cend(C_STANDARDS), cmStrCmp("90"))) { - return false; - } - return true; -} - -bool cmMakefile::IsLaterStandard(std::string const& lang, - std::string const& lhs, - std::string const& rhs) -{ - if (lang == "C" || lang == "OBJC") { - const char* const* rhsIt = std::find_if( - cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(rhs)); - - return std::find_if(rhsIt, cm::cend(C_STANDARDS), cmStrCmp(lhs)) != - cm::cend(C_STANDARDS); - } - if (lang == "CUDA") { - const char* const* rhsIt = std::find_if( - cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), cmStrCmp(rhs)); - - return std::find_if(rhsIt, cm::cend(CUDA_STANDARDS), cmStrCmp(lhs)) != - cm::cend(CUDA_STANDARDS); - } - - const char* const* rhsIt = std::find_if( - cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(rhs)); - - return std::find_if(rhsIt, cm::cend(CXX_STANDARDS), cmStrCmp(lhs)) != - cm::cend(CXX_STANDARDS); -} - -bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, - const std::string& feature, - std::string const& lang) const -{ - cmProp defaultCxxStandard = - this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); - if (!defaultCxxStandard) { - this->IssueMessage( - MessageType::INTERNAL_ERROR, - cmStrCat("CMAKE_", lang, - "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " - "not fully configured for this compiler.")); - // Return true so the caller does not try to lookup the default standard. - return true; - } - if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), - cmStrCmp(*defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) { - const std::string e = - cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ", - "invalid value: \"", *defaultCxxStandard, "\"."); - this->IssueMessage(MessageType::INTERNAL_ERROR, e); - return false; - } - - bool needCxx98 = false; - bool needCxx11 = false; - bool needCxx14 = false; - bool needCxx17 = false; - bool needCxx20 = false; - this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14, - needCxx17, needCxx20); - - cmProp existingCxxStandard = - target->GetProperty(cmStrCat(lang, "_STANDARD")); - if (!existingCxxStandard) { - existingCxxStandard = defaultCxxStandard; - } - - const char* const* existingCxxLevel = - std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), - cmStrCmp(*existingCxxStandard)); - if (existingCxxLevel == cm::cend(CXX_STANDARDS)) { - const std::string e = cmStrCat( - "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", *existingCxxStandard, "\"."); - this->IssueMessage(MessageType::FATAL_ERROR, e); - return false; - } - - /* clang-format off */ - const char* const* needCxxLevel = - needCxx20 ? &CXX_STANDARDS[4] - : needCxx17 ? &CXX_STANDARDS[3] - : needCxx14 ? &CXX_STANDARDS[2] - : needCxx11 ? &CXX_STANDARDS[1] - : needCxx98 ? &CXX_STANDARDS[0] - : nullptr; - /* clang-format on */ - - return !needCxxLevel || needCxxLevel <= existingCxxLevel; -} - -void cmMakefile::CheckNeededCxxLanguage(const std::string& feature, - std::string const& lang, - bool& needCxx98, bool& needCxx11, - bool& needCxx14, bool& needCxx17, - bool& needCxx20) const -{ - if (const char* propCxx98 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "98_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propCxx98); - needCxx98 = cm::contains(props, feature); - } - if (const char* propCxx11 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propCxx11); - needCxx11 = cm::contains(props, feature); - } - if (const char* propCxx14 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propCxx14); - needCxx14 = cm::contains(props, feature); - } - if (const char* propCxx17 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propCxx17); - needCxx17 = cm::contains(props, feature); - } - if (const char* propCxx20 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propCxx20); - needCxx20 = cm::contains(props, feature); - } -} - -bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, - const std::string& feature, - std::string const& lang, - std::string* error) const -{ - bool needCxx98 = false; - bool needCxx11 = false; - bool needCxx14 = false; - bool needCxx17 = false; - bool needCxx20 = false; - - this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14, - needCxx17, needCxx20); - - cmProp existingCxxStandard = - target->GetProperty(cmStrCat(lang, "_STANDARD")); - if (existingCxxStandard == nullptr) { - cmProp defaultCxxStandard = - this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); - if (defaultCxxStandard && !defaultCxxStandard->empty()) { - existingCxxStandard = defaultCxxStandard; - } - } - const char* const* existingCxxLevel = nullptr; - if (existingCxxStandard) { - existingCxxLevel = - std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), - cmStrCmp(*existingCxxStandard)); - if (existingCxxLevel == cm::cend(CXX_STANDARDS)) { - const std::string e = cmStrCat( - "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", *existingCxxStandard, "\"."); - if (error) { - *error = e; - } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e, - this->Backtrace); - } - return false; - } - } - - /* clang-format off */ - const char* const* needCxxLevel = - needCxx20 ? &CXX_STANDARDS[4] - : needCxx17 ? &CXX_STANDARDS[3] - : needCxx14 ? &CXX_STANDARDS[2] - : needCxx11 ? &CXX_STANDARDS[1] - : needCxx98 ? &CXX_STANDARDS[0] - : nullptr; - /* clang-format on */ - - if (needCxxLevel) { - // Ensure the C++ language level is high enough to support - // the needed C++ features. - if (!existingCxxLevel || existingCxxLevel < needCxxLevel) { - target->SetProperty(cmStrCat(lang, "_STANDARD"), *needCxxLevel); - } - } - - return true; -} - -bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target, - const std::string& feature, - std::string const& lang) const -{ - cmProp defaultCudaStandard = - this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); - if (!defaultCudaStandard) { - this->IssueMessage( - MessageType::INTERNAL_ERROR, - cmStrCat("CMAKE_", lang, - "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " - "not fully configured for this compiler.")); - // Return true so the caller does not try to lookup the default standard. - return true; - } - if (std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), - cmStrCmp(*defaultCudaStandard)) == - cm::cend(CUDA_STANDARDS)) { - const std::string e = - cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ", - "invalid value: \"", *defaultCudaStandard, "\"."); - this->IssueMessage(MessageType::INTERNAL_ERROR, e); - return false; - } - - bool needCuda03 = false; - bool needCuda11 = false; - bool needCuda14 = false; - bool needCuda17 = false; - bool needCuda20 = false; - this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11, - needCuda14, needCuda17, needCuda20); - - cmProp existingCudaStandard = - target->GetProperty(cmStrCat(lang, "_STANDARD")); - if (!existingCudaStandard) { - existingCudaStandard = defaultCudaStandard; - } - - const char* const* existingCudaLevel = - std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), - cmStrCmp(*existingCudaStandard)); - if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) { - const std::string e = cmStrCat( - "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", *existingCudaStandard, "\"."); - this->IssueMessage(MessageType::FATAL_ERROR, e); - return false; - } - - /* clang-format off */ - const char* const* needCudaLevel = - needCuda20 ? &CUDA_STANDARDS[4] - : needCuda17 ? &CUDA_STANDARDS[3] - : needCuda14 ? &CUDA_STANDARDS[2] - : needCuda11 ? &CUDA_STANDARDS[1] - : needCuda03 ? &CUDA_STANDARDS[0] - : nullptr; - /* clang-format on */ - - return !needCudaLevel || needCudaLevel <= existingCudaLevel; -} - -void cmMakefile::CheckNeededCudaLanguage(const std::string& feature, - std::string const& lang, - bool& needCuda03, bool& needCuda11, - bool& needCuda14, bool& needCuda17, - bool& needCuda20) const -{ - if (const char* propCuda03 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "03_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propCuda03); - needCuda03 = cm::contains(props, feature); - } - if (const char* propCuda11 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propCuda11); - needCuda11 = cm::contains(props, feature); - } - if (const char* propCuda14 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propCuda14); - needCuda14 = cm::contains(props, feature); - } - if (const char* propCuda17 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propCuda17); - needCuda17 = cm::contains(props, feature); - } - if (const char* propCuda20 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propCuda20); - needCuda20 = cm::contains(props, feature); - } -} - -bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target, - const std::string& feature, - std::string const& lang, - std::string* error) const -{ - bool needCuda03 = false; - bool needCuda11 = false; - bool needCuda14 = false; - bool needCuda17 = false; - bool needCuda20 = false; - - this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11, - needCuda14, needCuda17, needCuda20); - - cmProp existingCudaStandard = - target->GetProperty(cmStrCat(lang, "_STANDARD")); - if (existingCudaStandard == nullptr) { - cmProp defaultCudaStandard = - this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); - if (defaultCudaStandard && !defaultCudaStandard->empty()) { - existingCudaStandard = defaultCudaStandard; - } - } - const char* const* existingCudaLevel = nullptr; - if (existingCudaStandard) { - existingCudaLevel = - std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), - cmStrCmp(*existingCudaStandard)); - if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) { - const std::string e = cmStrCat( - "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", *existingCudaStandard, "\"."); - if (error) { - *error = e; - } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e, - this->Backtrace); - } - return false; - } - } - - /* clang-format off */ - const char* const* needCudaLevel = - needCuda20 ? &CUDA_STANDARDS[4] - : needCuda17 ? &CUDA_STANDARDS[3] - : needCuda14 ? &CUDA_STANDARDS[2] - : needCuda11 ? &CUDA_STANDARDS[1] - : needCuda03 ? &CUDA_STANDARDS[0] - : nullptr; - /* clang-format on */ - - if (needCudaLevel) { - // Ensure the CUDA language level is high enough to support - // the needed CUDA features. - if (!existingCudaLevel || existingCudaLevel < needCudaLevel) { - target->SetProperty("CUDA_STANDARD", *needCudaLevel); - } - } - - return true; -} - -void cmMakefile::CheckNeededCLanguage(const std::string& feature, - std::string const& lang, bool& needC90, - bool& needC99, bool& needC11) const -{ - if (const char* propC90 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "90_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propC90); - needC90 = cm::contains(props, feature); - } - if (const char* propC99 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "99_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propC99); - needC99 = cm::contains(props, feature); - } - if (const char* propC11 = - this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) { - std::vector<std::string> props = cmExpandedList(propC11); - needC11 = cm::contains(props, feature); - } -} - -bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, - const std::string& feature, - std::string const& lang, - std::string* error) const -{ - bool needC90 = false; - bool needC99 = false; - bool needC11 = false; - - this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11); - - cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD")); - if (existingCStandard == nullptr) { - cmProp defaultCStandard = - this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); - if (defaultCStandard && !defaultCStandard->empty()) { - existingCStandard = defaultCStandard; - } - } - if (existingCStandard) { - if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), - cmStrCmp(*existingCStandard)) == cm::cend(C_STANDARDS)) { - const std::string e = cmStrCat( - "The ", lang, "_STANDARD property on target \"", target->GetName(), - "\" contained an invalid value: \"", *existingCStandard, "\"."); - if (error) { - *error = e; - } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e, - this->Backtrace); - } - return false; - } - } - const char* const* existingCIt = existingCStandard - ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), - cmStrCmp(*existingCStandard)) - : cm::cend(C_STANDARDS); - - bool setC90 = needC90 && !existingCStandard; - bool setC99 = needC99 && !existingCStandard; - bool setC11 = needC11 && !existingCStandard; - - if (needC11 && existingCStandard && - existingCIt < std::find_if(cm::cbegin(C_STANDARDS), - cm::cend(C_STANDARDS), cmStrCmp("11"))) { - setC11 = true; - } else if (needC99 && existingCStandard && - existingCIt < std::find_if(cm::cbegin(C_STANDARDS), - cm::cend(C_STANDARDS), - cmStrCmp("99"))) { - setC99 = true; - } else if (needC90 && existingCStandard && - existingCIt < std::find_if(cm::cbegin(C_STANDARDS), - cm::cend(C_STANDARDS), - cmStrCmp("90"))) { - setC90 = true; - } - - if (setC11) { - target->SetProperty(cmStrCat(lang, "_STANDARD"), "11"); - } else if (setC99) { - target->SetProperty(cmStrCat(lang, "_STANDARD"), "99"); - } else if (setC90) { - target->SetProperty(cmStrCat(lang, "_STANDARD"), "90"); - } - return true; -} - cmMakefile::FunctionPushPop::FunctionPushPop(cmMakefile* mf, const std::string& fileName, cmPolicies::PolicyMap const& pm) diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 45d7109..0a6e6e2 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMakefile_h -#define cmMakefile_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -342,12 +341,19 @@ public: */ void SetProjectName(std::string const& name); - /** Get the configurations to be generated. */ - std::string GetConfigurations(std::vector<std::string>& configs, - bool single = true) const; + /* Get the default configuration */ + std::string GetDefaultConfiguration() const; + + enum GeneratorConfigQuery + { + IncludeEmptyConfig, // Include "" aka noconfig + ExcludeEmptyConfig, // Exclude "" aka noconfig + OnlyMultiConfig, + }; /** Get the configurations for dependency checking. */ - std::vector<std::string> GetGeneratorConfigs() const; + std::vector<std::string> GetGeneratorConfigs( + GeneratorConfigQuery mode) const; /** * Set the name of the library. @@ -508,8 +514,7 @@ public: * If the variable is not found in this makefile instance, the * cache is then queried. */ - const char* GetDefinition(const std::string&) const; - const std::string* GetDef(const std::string&) const; + cmProp GetDefinition(const std::string&) const; const std::string& GetSafeDefinition(const std::string&) const; const std::string& GetRequiredDefinition(const std::string& name) const; bool IsDefinitionSet(const std::string&) const; @@ -686,6 +691,7 @@ public: */ int ConfigureFile(const std::string& infile, const std::string& outfile, bool copyonly, bool atOnly, bool escapeQuotes, + bool use_source_permissions, cmNewLineStyle = cmNewLineStyle()); /** @@ -925,21 +931,6 @@ public: bool PolicyOptionalWarningEnabled(std::string const& var); - bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature, - std::string* error = nullptr) const; - - bool CompileFeatureKnown(cmTarget const* target, const std::string& feature, - std::string& lang, std::string* error) const; - - const char* CompileFeaturesAvailable(const std::string& lang, - std::string* error) const; - - bool HaveStandardAvailable(cmTarget const* target, std::string const& lang, - const std::string& feature) const; - - bool IsLaterStandard(std::string const& lang, std::string const& lhs, - std::string const& rhs); - void PushLoopBlock(); void PopLoopBlock(); bool IsLoopBlock() const; @@ -951,12 +942,12 @@ public: const char* GetDefineFlagsCMP0059() const; - std::string GetExecutionFilePath() const; + std::string const& GetExecutionFilePath() const; void EnforceDirectoryLevelRules() const; void AddEvaluationFile( - const std::string& inputFile, + const std::string& inputFile, const std::string& targetName, std::unique_ptr<cmCompiledGeneratorExpression> outputName, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent); @@ -985,9 +976,6 @@ protected: // add link libraries and directories to the target void AddGlobalLinkInformation(cmTarget& target); - // Check for a an unused variable - void LogUnused(const char* reason, const std::string& name) const; - mutable std::set<cmListFileContext> CMP0054ReportedIds; // libraries, classes, and executables @@ -1162,49 +1150,9 @@ private: */ bool MightHaveCustomCommand(const std::string& name) const; - bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature, - std::string const& lang, - std::string* error = nullptr) const; - bool AddRequiredTargetCxxFeature(cmTarget* target, - const std::string& feature, - std::string const& lang, - std::string* error = nullptr) const; - bool AddRequiredTargetCudaFeature(cmTarget* target, - const std::string& feature, - std::string const& lang, - std::string* error = nullptr) const; - - void CheckNeededCLanguage(const std::string& feature, - std::string const& lang, bool& needC90, - bool& needC99, bool& needC11) const; - void CheckNeededCxxLanguage(const std::string& feature, - std::string const& lang, bool& needCxx98, - bool& needCxx11, bool& needCxx14, - bool& needCxx17, bool& needCxx20) const; - void CheckNeededCudaLanguage(const std::string& feature, - std::string const& lang, bool& needCuda03, - bool& needCuda11, bool& needCuda14, - bool& needCuda17, bool& needCuda20) const; - - bool HaveCStandardAvailable(cmTarget const* target, - const std::string& feature, - std::string const& lang) const; - bool HaveCxxStandardAvailable(cmTarget const* target, - const std::string& feature, - std::string const& lang) const; - bool HaveCudaStandardAvailable(cmTarget const* target, - const std::string& feature, - std::string const& lang) const; - - void CheckForUnusedVariables() const; - - // Unused variable flags - bool WarnUnused; bool CheckSystemVars; bool CheckCMP0000; std::set<std::string> WarnedCMP0074; bool IsSourceFileTryCompile; mutable bool SuppressSideEffects; }; - -#endif diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 446f225..9b5c6e6 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -218,7 +218,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_LINK"); - if (val && *val) { + if (cmNonempty(val)) { launcher = cmStrCat(val, ' '); } @@ -371,7 +371,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->AddConfigVariableFlags( linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->GetConfigName()); - if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) { + if (this->GeneratorTarget->IsWin32Executable( + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) { this->LocalGenerator->AppendFlags( linkFlags, this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE")); } else { @@ -583,7 +584,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_LINK"); - if (val && *val) { + if (cmNonempty(val)) { launcher = cmStrCat(val, ' '); } diff --git a/Source/cmMakefileExecutableTargetGenerator.h b/Source/cmMakefileExecutableTargetGenerator.h index b9bbe86..782692a 100644 --- a/Source/cmMakefileExecutableTargetGenerator.h +++ b/Source/cmMakefileExecutableTargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMakefileExecutableTargetGenerator_h -#define cmMakefileExecutableTargetGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -28,5 +27,3 @@ protected: private: std::string DeviceLinkObject; }; - -#endif diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 5809b4a..1c25fc4 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -356,7 +356,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( std::string launcher; const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_LINK"); - if (val && *val) { + if (cmNonempty(val)) { launcher = cmStrCat(val, ' '); } @@ -809,7 +809,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string launcher; const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_LINK"); - if (val && *val) { + if (cmNonempty(val)) { launcher = cmStrCat(val, ' '); } diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h index ca22b09..6a38e18 100644 --- a/Source/cmMakefileLibraryTargetGenerator.h +++ b/Source/cmMakefileLibraryTargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMakefileLibraryTargetGenerator_h -#define cmMakefileLibraryTargetGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -39,5 +38,3 @@ protected: private: std::string DeviceLinkObject; }; - -#endif diff --git a/Source/cmMakefileProfilingData.h b/Source/cmMakefileProfilingData.h index 1babd97..a3f128b 100644 --- a/Source/cmMakefileProfilingData.h +++ b/Source/cmMakefileProfilingData.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMakefileProfilingData_h -#define cmMakefileProfilingData_h +#pragma once #include <memory> #include <string> @@ -26,4 +25,3 @@ private: cmsys::ofstream ProfileStream; std::unique_ptr<Json::StreamWriter> JsonWriter; }; -#endif diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 8396fa3..e1fe0e5 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -26,10 +26,12 @@ #include "cmMakefileLibraryTargetGenerator.h" #include "cmMakefileUtilityTargetGenerator.h" #include "cmOutputConverter.h" +#include "cmPolicies.h" #include "cmProperty.h" #include "cmRange.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" +#include "cmSourceFileLocationKind.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" @@ -51,6 +53,17 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) if (cmProp ruleStatus = cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) { this->NoRuleMessages = cmIsOff(*ruleStatus); } + switch (this->GeneratorTarget->GetPolicyStatusCMP0113()) { + case cmPolicies::WARN: + case cmPolicies::OLD: + this->CMP0113New = false; + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + this->CMP0113New = true; + break; + } MacOSXContentGenerator = cm::make_unique<MacOSXContentGeneratorType>(this); } @@ -71,6 +84,7 @@ std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New( case cmStateEnums::OBJECT_LIBRARY: result = cm::make_unique<cmMakefileLibraryTargetGenerator>(tgt); break; + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::UTILITY: result = cm::make_unique<cmMakefileUtilityTargetGenerator>(tgt); break; @@ -196,18 +210,32 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } + std::string currentBinDir = + this->LocalGenerator->GetCurrentBinaryDirectory(); + + // Look for ISPC extra object files generated by this target + auto ispcAdditionalObjs = + this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName()); + for (std::string const& ispcObj : ispcAdditionalObjs) { + this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( + currentBinDir, ispcObj)); + } + // add custom commands to the clean rules? - cmProp clean_no_custom = this->Makefile->GetProperty("CLEAN_NO_CUSTOM"); - bool clean = clean_no_custom ? cmIsOff(*clean_no_custom) : true; + bool clean = cmIsOff(this->Makefile->GetProperty("CLEAN_NO_CUSTOM")); // First generate the object rule files. Save a list of all object // files for this target. std::vector<cmSourceFile const*> customCommands; this->GeneratorTarget->GetCustomCommands(customCommands, this->GetConfigName()); - std::string currentBinDir = - this->LocalGenerator->GetCurrentBinaryDirectory(); for (cmSourceFile const* sf : customCommands) { + if (this->CMP0113New && + !this->LocalGenerator->GetCommandsVisited(this->GeneratorTarget) + .insert(sf) + .second) { + continue; + } cmCustomCommandGenerator ccg(*sf->GetCustomCommand(), this->GetConfigName(), this->LocalGenerator); this->GenerateCustomRuleFile(ccg); @@ -257,17 +285,18 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() this->GeneratorTarget->GetExtraSources(extraSources, this->GetConfigName()); this->OSXBundleGenerator->GenerateMacOSXContentStatements( extraSources, this->MacOSXContentGenerator.get(), this->GetConfigName()); - const char* pchExtension = - this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector<cmSourceFile const*> externalObjects; this->GeneratorTarget->GetExternalObjects(externalObjects, this->GetConfigName()); for (cmSourceFile const* sf : externalObjects) { auto const& objectFileName = sf->GetFullPath(); - if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + if (!cmSystemTools::StringEndsWith(objectFileName, + cmToCStr(pchExtension))) { this->ExternalObjects.push_back(objectFileName); } } + std::vector<cmSourceFile const*> objectSources; this->GeneratorTarget->GetObjectSources(objectSources, this->GetConfigName()); @@ -525,6 +554,14 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } } + if (lang != "ISPC") { + auto const& headers = + this->GeneratorTarget->GetGeneratedISPCHeaders(config); + if (!headers.empty()) { + depends.insert(depends.end(), headers.begin(), headers.end()); + } + } + std::string relativeObj = cmStrCat(this->LocalGenerator->GetHomeRelativeOutputPath(), obj); // Write the build rule. @@ -532,6 +569,13 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Build the set of compiler flags. std::string flags; + // explicitly add the explicit language flag before any other flag + // this way backwards compatibility with user flags is maintained + if (source.GetProperty("LANGUAGE")) { + this->LocalGenerator->AppendFeatureOptions(flags, lang, + "EXPLICIT_LANGUAGE"); + } + // Add language-specific flags. std::string langFlags = cmStrCat("$(", lang, "_FLAGS", filterArch, ")"); this->LocalGenerator->AppendFlags(flags, langFlags); @@ -545,6 +589,23 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( this->AppendFortranPreprocessFlags(flags, source); } + std::string ispcHeaderRelative; + std::string ispcHeaderForShell; + if (lang == "ISPC") { + std::string ispcSource = + cmSystemTools::GetFilenameWithoutLastExtension(objectName); + + std::string directory = this->GeneratorTarget->GetObjectDirectory(config); + if (cmProp prop = + this->GeneratorTarget->GetProperty("ISPC_HEADER_DIRECTORY")) { + directory = + cmStrCat(this->LocalGenerator->GetBinaryDirectory(), '/', *prop); + } + ispcHeaderRelative = cmStrCat(directory, '/', ispcSource, ".h"); + ispcHeaderForShell = this->LocalGenerator->ConvertToOutputFormat( + ispcHeaderRelative, cmOutputConverter::SHELL); + } + // Add flags from source file properties. const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (cmProp cflags = source.GetProperty(COMPILE_FLAGS)) { @@ -710,6 +771,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmOutputConverter::SHELL); vars.ObjectFileDir = objectFileDir.c_str(); vars.Flags = flags.c_str(); + vars.ISPCHeader = ispcHeaderForShell.c_str(); std::string definesString = cmStrCat("$(", lang, "_DEFINES)"); @@ -728,7 +790,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // ability to export compile commands bool lang_has_preprocessor = ((lang == "C") || (lang == "CXX") || (lang == "OBJC") || - (lang == "OBJCXX") || (lang == "Fortran") || (lang == "CUDA")); + (lang == "OBJCXX") || (lang == "Fortran") || (lang == "CUDA") || + lang == "ISPC"); bool const lang_has_assembly = lang_has_preprocessor; bool const lang_can_export_cmds = lang_has_preprocessor; @@ -779,13 +842,13 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( langIncludes.size(), this->GetIncludes(lang, this->GetConfigName())); - const char* eliminate[] = { + cmProp eliminate[] = { this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"), this->Makefile->GetDefinition("CMAKE_END_TEMP_FILE") }; - for (const char* el : eliminate) { + for (cmProp el : eliminate) { if (el) { - cmSystemTools::ReplaceString(compileCommand, el, ""); + cmSystemTools::ReplaceString(compileCommand, *el, ""); } } @@ -797,10 +860,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string compilerLauncher; if (!compileCommands.empty() && (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" || - lang == "OBJC" || lang == "OBJCXX")) { + lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); - if (clauncher && !clauncher->empty()) { + if (cmNonempty(clauncher)) { compilerLauncher = *clauncher; } } @@ -815,8 +878,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmProp cpplint = this->GeneratorTarget->GetProperty(cpplint_prop); std::string const cppcheck_prop = lang + "_CPPCHECK"; cmProp cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop); - if ((iwyu && !iwyu->empty()) || (tidy && !tidy->empty()) || - (cpplint && !cpplint->empty()) || (cppcheck && !cppcheck->empty())) { + if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) || + cmNonempty(cppcheck)) { std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile"; if (!compilerLauncher.empty()) { // In __run_co_compile case the launcher command is supplied @@ -825,30 +888,33 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher); compilerLauncher.clear(); } - if (iwyu && !iwyu->empty()) { + if (cmNonempty(iwyu)) { run_iwyu += " --iwyu="; run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu); } - if (tidy && !tidy->empty()) { + if (cmNonempty(tidy)) { run_iwyu += " --tidy="; - const char* driverMode = this->Makefile->GetDefinition( - "CMAKE_" + lang + "_CLANG_TIDY_DRIVER_MODE"); - if (!(driverMode && *driverMode)) { + cmProp p = this->Makefile->GetDefinition("CMAKE_" + lang + + "_CLANG_TIDY_DRIVER_MODE"); + std::string driverMode; + if (cmNonempty(p)) { + driverMode = *p; + } else { driverMode = lang == "C" ? "gcc" : "g++"; } run_iwyu += this->LocalGenerator->EscapeForShell( cmStrCat(*tidy, ";--extra-arg-before=--driver-mode=", driverMode)); } - if (cpplint && !cpplint->empty()) { + if (cmNonempty(cpplint)) { run_iwyu += " --cpplint="; run_iwyu += this->LocalGenerator->EscapeForShell(*cpplint); } - if (cppcheck && !cppcheck->empty()) { + if (cmNonempty(cppcheck)) { run_iwyu += " --cppcheck="; run_iwyu += this->LocalGenerator->EscapeForShell(*cppcheck); } - if ((tidy && !tidy->empty()) || (cpplint && !cpplint->empty()) || - (cppcheck && !cppcheck->empty())) { + if (cmNonempty(tidy) || (cmNonempty(cpplint)) || + (cmNonempty(cppcheck))) { run_iwyu += " --source="; run_iwyu += sourceFile; } @@ -875,7 +941,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( { const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_COMPILE"); - if (val && *val) { + if (cmNonempty(val)) { launcher = cmStrCat(val, ' '); } } @@ -903,9 +969,16 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( if (!evaluated_outputs.empty()) { // Register these as extra files to clean. cmExpandList(evaluated_outputs, outputs); - this->CleanFiles.insert(outputs.begin() + 1, outputs.end()); } } + if (!ispcHeaderRelative + .empty()) { // can't move ispcHeader as vars is using it + outputs.emplace_back(ispcHeaderRelative); + } + + if (outputs.size() > 1) { + this->CleanFiles.insert(outputs.begin() + 1, outputs.end()); + } // Write the rule. this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends, @@ -935,10 +1008,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string preprocessRuleVar = cmStrCat("CMAKE_", lang, "_CREATE_PREPROCESSED_SOURCE"); - if (const char* preprocessRule = + if (cmProp preprocessRule = this->Makefile->GetDefinition(preprocessRuleVar)) { std::vector<std::string> preprocessCommands = - cmExpandedList(preprocessRule); + cmExpandedList(*preprocessRule); std::string shellObjI = this->LocalGenerator->ConvertToOutputFormat( objI, cmOutputConverter::SHELL); @@ -980,10 +1053,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string assemblyRuleVar = cmStrCat("CMAKE_", lang, "_CREATE_ASSEMBLY_SOURCE"); - if (const char* assemblyRule = + if (cmProp assemblyRule = this->Makefile->GetDefinition(assemblyRuleVar)) { std::vector<std::string> assemblyCommands = - cmExpandedList(assemblyRule); + cmExpandedList(*assemblyRule); std::string shellObjS = this->LocalGenerator->ConvertToOutputFormat( objS, cmOutputConverter::SHELL); @@ -1236,16 +1309,7 @@ void cmMakefileTargetGenerator::DriveCustomCommands( std::vector<std::string>& depends) { // Depend on all custom command outputs. - std::vector<cmSourceFile*> sources; - this->GeneratorTarget->GetSourceFiles( - sources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); - for (cmSourceFile* source : sources) { - if (cmCustomCommand* cc = source->GetCustomCommand()) { - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), - this->LocalGenerator); - cm::append(depends, ccg.GetOutputs()); - } - } + cm::append(depends, this->CustomCommandOutputs); } void cmMakefileTargetGenerator::WriteObjectDependRules( @@ -1292,6 +1356,22 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( bool symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends, commands); + // Symbolic inputs are not expected to exist, so add dummy rules. + if (this->CMP0113New && !depends.empty()) { + std::vector<std::string> no_depends; + std::vector<std::string> no_commands; + for (std::string const& dep : depends) { + if (cmSourceFile* dsf = + this->Makefile->GetSource(dep, cmSourceFileLocationKind::Known)) { + if (dsf->GetPropertyAsBool("SYMBOLIC")) { + this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr, + dep, no_depends, no_commands, + true); + } + } + } + } + // If the rule has changed make sure the output is rebuilt. if (!symbolic) { this->GlobalGenerator->AddRuleHash(ccg.GetOutputs(), content.str()); @@ -1306,6 +1386,8 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, idi.first, objFullPath, srcFullPath); } + + this->CustomCommandOutputs.insert(outputs.begin(), outputs.end()); } void cmMakefileTargetGenerator::MakeEchoProgress( @@ -1330,17 +1412,17 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( << this->GeneratorTarget->GetName() << "\n" << variableName << " ="; std::string object; - const char* lineContinue = - this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE"); - if (!lineContinue) { + std::string lineContinue; + if (cmProp p = this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE")) { + lineContinue = *p; + } else { lineContinue = "\\"; } - const char* pchExtension = - this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); for (std::string const& obj : this->Objects) { - if (cmSystemTools::StringEndsWith(obj, pchExtension)) { + if (cmSystemTools::StringEndsWith(obj, cmToCStr(pchExtension))) { continue; } *this->BuildFileStream << " " << lineContinue << "\n"; @@ -1435,14 +1517,13 @@ private: void cmMakefileTargetGenerator::WriteObjectsStrings( std::vector<std::string>& objStrings, std::string::size_type limit) { - const char* pchExtension = - this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); cmMakefileTargetGeneratorObjectStrings helper( objStrings, this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory(), limit); for (std::string const& obj : this->Objects) { - if (cmSystemTools::StringEndsWith(obj, pchExtension)) { + if (cmSystemTools::StringEndsWith(obj, cmToCStr(pchExtension))) { continue; } helper.Feed(obj); @@ -1450,6 +1531,11 @@ void cmMakefileTargetGenerator::WriteObjectsStrings( for (std::string const& obj : this->ExternalObjects) { helper.Feed(obj); } + auto ispcAdditionalObjs = + this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName()); + for (std::string const& obj : ispcAdditionalObjs) { + helper.Feed(obj); + } helper.Done(); } @@ -1565,8 +1651,8 @@ std::string cmMakefileTargetGenerator::GetLinkRule( cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), "_GNUtoMS_RULE"); - if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { - linkRule += rule; + if (cmProp rule = this->Makefile->GetDefinition(ruleVar)) { + linkRule += *rule; } } return linkRule; @@ -1615,8 +1701,8 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects( // Check for an explicit setting one way or the other. std::string const responseVar = "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_OBJECTS"; - if (const char* val = this->Makefile->GetDefinition(responseVar)) { - if (*val) { + if (cmProp val = this->Makefile->GetDefinition(responseVar)) { + if (!val->empty()) { return cmIsOn(val); } } @@ -1654,8 +1740,8 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries( // Check for an explicit setting one way or the other. std::string const responseVar = "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_LIBRARIES"; - if (const char* val = this->Makefile->GetDefinition(responseVar)) { - if (*val) { + if (cmProp val = this->Makefile->GetDefinition(responseVar)) { + if (!val->empty()) { return cmIsOn(val); } } @@ -1716,8 +1802,10 @@ void cmMakefileTargetGenerator::CreateLinkLibs( cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), "_RESPONSE_FILE_LINK_FLAG"); - const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); - if (!responseFlag) { + std::string responseFlag; + if (cmProp p = this->Makefile->GetDefinition(responseFlagVar)) { + responseFlag = *p; + } else { responseFlag = "@"; } @@ -1754,8 +1842,10 @@ void cmMakefileTargetGenerator::CreateObjectLists( cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), "_RESPONSE_FILE_LINK_FLAG"); - const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); - if (!responseFlag) { + std::string responseFlag; + if (cmProp p = this->Makefile->GetDefinition(responseFlagVar)) { + responseFlag = *p; + } else { responseFlag = "@"; } @@ -1850,11 +1940,11 @@ void cmMakefileTargetGenerator::GenDefFile( this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file), cmOutputConverter::SHELL); - const char* nm_executable = this->Makefile->GetDefinition("CMAKE_NM"); - if (nm_executable && *nm_executable) { + cmProp nm_executable = this->Makefile->GetDefinition("CMAKE_NM"); + if (cmNonempty(nm_executable)) { cmd += " --nm="; cmd += this->LocalCommonGenerator->ConvertToOutputFormat( - nm_executable, cmOutputConverter::SHELL); + *nm_executable, cmOutputConverter::SHELL); } real_link_commands.insert(real_link_commands.begin(), cmd); // create a list of obj files for the -E __create_def to read diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index f38f862..1740d54 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMakefileTargetGenerator_h -#define cmMakefileTargetGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -197,6 +196,8 @@ protected: unsigned long NumberOfProgressActions; bool NoRuleMessages; + bool CMP0113New = false; + // the path to the directory the build file is in std::string TargetBuildDirectory; std::string TargetBuildDirectoryFull; @@ -229,6 +230,9 @@ protected: // Set of extra output files to be driven by the build. std::set<std::string> ExtraFiles; + // Set of custom command output files to be driven by the build. + std::set<std::string> CustomCommandOutputs; + using MultipleOutputPairsType = std::map<std::string, std::string>; MultipleOutputPairsType MultipleOutputPairs; bool WriteMakeRule(std::ostream& os, const char* comment, @@ -245,5 +249,3 @@ protected: std::unique_ptr<cmOSXBundleGenerator> OSXBundleGenerator; std::unique_ptr<MacOSXContentGeneratorType> MacOSXContentGenerator; }; - -#endif diff --git a/Source/cmMakefileUtilityTargetGenerator.h b/Source/cmMakefileUtilityTargetGenerator.h index be243a7..d2b4ba5 100644 --- a/Source/cmMakefileUtilityTargetGenerator.h +++ b/Source/cmMakefileUtilityTargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMakefileUtilityTargetGenerator_h -#define cmMakefileUtilityTargetGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -21,5 +20,3 @@ public: protected: }; - -#endif diff --git a/Source/cmMarkAsAdvancedCommand.h b/Source/cmMarkAsAdvancedCommand.h index de7bf08..e420e64 100644 --- a/Source/cmMarkAsAdvancedCommand.h +++ b/Source/cmMarkAsAdvancedCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMarkAsAdvancedCommand_h -#define cmMarkAsAdvancedCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,5 +16,3 @@ class cmExecutionStatus; */ bool cmMarkAsAdvancedCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmMathCommand.h b/Source/cmMathCommand.h index ac1957c..e6b347b 100644 --- a/Source/cmMathCommand.h +++ b/Source/cmMathCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMathCommand_h -#define cmMathCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -13,5 +12,3 @@ class cmExecutionStatus; /// Mathematical expressions: math(EXPR ...) command. bool cmMathCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmMessageCommand.h b/Source/cmMessageCommand.h index 7d544c4..c37098c 100644 --- a/Source/cmMessageCommand.h +++ b/Source/cmMessageCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMessageCommand_h -#define cmMessageCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -16,5 +15,3 @@ class cmExecutionStatus; */ bool cmMessageCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmMessageType.h b/Source/cmMessageType.h index b57b86b..44de429 100644 --- a/Source/cmMessageType.h +++ b/Source/cmMessageType.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMessageType_h -#define cmMessageType_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,5 +16,3 @@ enum class MessageType DEPRECATION_ERROR, DEPRECATION_WARNING }; - -#endif diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h index 8c09782..b6f5712 100644 --- a/Source/cmMessenger.h +++ b/Source/cmMessenger.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmMessenger_h -#define cmMessenger_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -57,5 +56,3 @@ private: bool DevWarningsAsErrors = false; bool DeprecatedWarningsAsErrors = false; }; - -#endif diff --git a/Source/cmNewLineStyle.h b/Source/cmNewLineStyle.h index ab9002e..a2b985b 100644 --- a/Source/cmNewLineStyle.h +++ b/Source/cmNewLineStyle.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmNewLineStyle_h -#define cmNewLineStyle_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -35,5 +34,3 @@ public: private: Style NewLineStyle = Invalid; }; - -#endif diff --git a/Source/cmNinjaLinkLineComputer.h b/Source/cmNinjaLinkLineComputer.h index b2b2e84..5d22f3e 100644 --- a/Source/cmNinjaLinkLineComputer.h +++ b/Source/cmNinjaLinkLineComputer.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmNinjaLinkLineComputer_h -#define cmNinjaLinkLineComputer_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -29,5 +28,3 @@ public: private: cmGlobalNinjaGenerator const* GG; }; - -#endif diff --git a/Source/cmNinjaLinkLineDeviceComputer.h b/Source/cmNinjaLinkLineDeviceComputer.h index 84ced5b..457f036 100644 --- a/Source/cmNinjaLinkLineDeviceComputer.h +++ b/Source/cmNinjaLinkLineDeviceComputer.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmNinjaLinkLineDeviceComputer_h -#define cmNinjaLinkLineDeviceComputer_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -30,5 +29,3 @@ public: private: cmGlobalNinjaGenerator const* GG; }; - -#endif diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 32ab9f8..210b36e 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -239,7 +239,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule( std::string launcher; const char* val = this->GetLocalGenerator()->GetRuleLauncher( this->GetGeneratorTarget(), "RULE_LAUNCH_LINK"); - if (val && *val) { + if (cmNonempty(val)) { launcher = cmStrCat(val, ' '); } @@ -307,10 +307,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; - const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar); + cmProp flag = GetMakefile()->GetDefinition(cmakeLinkVar); if (flag) { - responseFlag = flag; + responseFlag = *flag; } else { responseFlag = "@"; } @@ -376,7 +376,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, std::string launcher; const char* val = this->GetLocalGenerator()->GetRuleLauncher( this->GetGeneratorTarget(), "RULE_LAUNCH_LINK"); - if (val && *val) { + if (cmNonempty(val)) { launcher = cmStrCat(val, ' '); } @@ -478,15 +478,15 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( // CMAKE_<lang>_CREATE_STATIC_LIBRARY_IPO define instead. std::string linkCmdVar = this->GetGeneratorTarget()->GetCreateRuleVariable( this->TargetLinkLanguage(config), config); - const char* linkCmd = mf->GetDefinition(linkCmdVar); + cmProp linkCmd = mf->GetDefinition(linkCmdVar); if (linkCmd) { - std::string linkCmdStr = linkCmd; + std::string linkCmdStr = *linkCmd; if (this->GetGeneratorTarget()->HasImplibGNUtoMS(config)) { std::string ruleVar = cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(config), "_GNUtoMS_RULE"); - if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { - linkCmdStr += rule; + if (cmProp rule = this->Makefile->GetDefinition(ruleVar)) { + linkCmdStr += *rule; } } cmExpandList(linkCmdStr, linkCmds); @@ -739,7 +739,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( // Gather order-only dependencies. this->GetLocalGenerator()->AppendTargetDepends( - this->GetGeneratorTarget(), build.OrderOnlyDeps, config, config); + this->GetGeneratorTarget(), build.OrderOnlyDeps, config, config, + DependOnTargetArtifact); // Write the build statement for this target. bool usedResponseFile = false; @@ -910,11 +911,16 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( linkBuild.ExplicitDeps.push_back( this->ConvertToNinjaPath(this->GetSourceFilePath(source))); } - linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]); } else { linkBuild.ExplicitDeps = this->GetObjects(config); } + + std::vector<std::string> extraISPCObjects = + this->GetGeneratorTarget()->GetGeneratedISPCObjects(config); + std::transform(extraISPCObjects.begin(), extraISPCObjects.end(), + std::back_inserter(linkBuild.ExplicitDeps), MapToNinjaPath()); + linkBuild.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage(config), config); @@ -1026,8 +1032,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( gt->GetFullNameComponents(prefix, base, suffix, config); std::string dbg_suffix = ".dbg"; // TODO: Where to document? - if (auto d = mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) { - dbg_suffix = d; + if (cmProp d = mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) { + dbg_suffix = *d; } vars["TARGET_PDB"] = base + suffix + dbg_suffix; } @@ -1090,11 +1096,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( cmd += this->GetLocalGenerator()->ConvertToOutputFormat( obj_list_file, cmOutputConverter::SHELL); - const char* nm_executable = GetMakefile()->GetDefinition("CMAKE_NM"); - if (nm_executable && *nm_executable) { + cmProp nm_executable = GetMakefile()->GetDefinition("CMAKE_NM"); + if (cmNonempty(nm_executable)) { cmd += " --nm="; cmd += this->LocalCommonGenerator->ConvertToOutputFormat( - nm_executable, cmOutputConverter::SHELL); + *nm_executable, cmOutputConverter::SHELL); } preLinkCmdLines.push_back(std::move(cmd)); @@ -1143,7 +1149,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; - const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar); + cmProp flag = GetMakefile()->GetDefinition(cmakeLinkVar); bool const lang_supports_response = !(this->TargetLinkLanguage(config) == "RC" || @@ -1160,8 +1166,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( globalGen->IsMultiConfig() ? cmStrCat('.', config) : "", ".rsp")); // Gather order-only dependencies. - this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps, - config, fileConfig); + this->GetLocalGenerator()->AppendTargetDepends( + gt, linkBuild.OrderOnlyDeps, config, fileConfig, DependOnTargetArtifact); // Add order-only dependencies on versioning symlinks of shared libs we link. if (!this->GeneratorTarget->IsDLLPlatform()) { diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h index 9de99b9..25e40d0 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmNinjaNormalTargetGenerator_h -#define cmNinjaNormalTargetGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -46,5 +45,3 @@ private: std::string TargetLinkLanguage(const std::string& config) const; std::string DeviceLinkObject; }; - -#endif // ! cmNinjaNormalTargetGenerator_h diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index d406c99..accdcf1 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -51,6 +51,7 @@ std::unique_ptr<cmNinjaTargetGenerator> cmNinjaTargetGenerator::New( return cm::make_unique<cmNinjaNormalTargetGenerator>(target); case cmStateEnums::UTILITY: + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::GLOBAL_TARGET: return cm::make_unique<cmNinjaUtilityTargetGenerator>(target); @@ -65,7 +66,8 @@ cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target) , LocalGenerator( static_cast<cmLocalNinjaGenerator*>(target->GetLocalGenerator())) { - for (auto const& fileConfig : target->Makefile->GetGeneratorConfigs()) { + for (auto const& fileConfig : + target->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig)) { this->Configs[fileConfig].MacOSXContentGenerator = cm::make_unique<MacOSXContentGeneratorType>(this, fileConfig); } @@ -188,7 +190,16 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( } } - std::string flags = this->GetFlags(language, config, filterArch); + std::string flags; + // explicitly add the explicit language flag before any other flag + // this way backwards compatibility with user flags is maintained + if (source->GetProperty("LANGUAGE")) { + this->LocalGenerator->AppendFeatureOptions(flags, language, + "EXPLICIT_LANGUAGE"); + flags += " "; + } + + flags += this->GetFlags(language, config, filterArch); // Add Fortran format flags. if (language == "Fortran") { @@ -620,6 +631,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, vars.TargetCompilePDB = "$TARGET_COMPILE_PDB"; vars.ObjectDir = "$OBJECT_DIR"; vars.ObjectFileDir = "$OBJECT_FILE_DIR"; + vars.ISPCHeader = "$ISPC_HEADER_FILE"; cmMakefile* mf = this->GetMakefile(); @@ -652,7 +664,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, std::string launcher; const char* val = this->GetLocalGenerator()->GetRuleLauncher( this->GetGeneratorTarget(), "RULE_LAUNCH_COMPILE"); - if (val && *val) { + if (cmNonempty(val)) { launcher = cmStrCat(val, ' '); } @@ -750,9 +762,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, if (!mf->GetIsSourceFileTryCompile()) { rule.DepType = "gcc"; rule.DepFile = "$DEP_FILE"; - auto d = mf->GetDefinition("CMAKE_C_COMPILER"); + cmProp d = mf->GetDefinition("CMAKE_C_COMPILER"); const std::string cl = - d ? d : mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); + d ? *d : mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); cldeps = cmStrCat('"', cmSystemTools::GetCMClDepsCommand(), "\" ", lang, ' ', vars.Source, " $DEP_FILE $out \"", mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"), @@ -766,8 +778,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, if (!depfileFlags.empty()) { cmSystemTools::ReplaceString(depfileFlags, "<DEPFILE>", "$DEP_FILE"); cmSystemTools::ReplaceString(depfileFlags, "<OBJECT>", "$out"); - cmSystemTools::ReplaceString(depfileFlags, "<CMAKE_C_COMPILER>", - mf->GetDefinition("CMAKE_C_COMPILER")); + cmSystemTools::ReplaceString( + depfileFlags, "<CMAKE_C_COMPILER>", + cmToCStr(mf->GetDefinition("CMAKE_C_COMPILER"))); flags += cmStrCat(' ', depfileFlags); } } @@ -800,10 +813,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, std::string compilerLauncher; if (!compileCmds.empty() && (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" || - lang == "OBJC" || lang == "OBJCXX")) { + lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) { std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER"); cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); - if (clauncher && !clauncher->empty()) { + if (cmNonempty(clauncher)) { compilerLauncher = *clauncher; } } @@ -818,8 +831,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, cmProp cpplint = this->GeneratorTarget->GetProperty(cpplint_prop); std::string const cppcheck_prop = cmStrCat(lang, "_CPPCHECK"); cmProp cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop); - if ((iwyu && !iwyu->empty()) || (tidy && !tidy->empty()) || - (cpplint && !cpplint->empty()) || (cppcheck && !cppcheck->empty())) { + if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) || + cmNonempty(cppcheck)) { std::string run_iwyu = cmStrCat(cmakeCmd, " -E __run_co_compile"); if (!compilerLauncher.empty()) { // In __run_co_compile case the launcher command is supplied @@ -829,31 +842,33 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, this->LocalGenerator->EscapeForShell(compilerLauncher)); compilerLauncher.clear(); } - if (iwyu && !iwyu->empty()) { + if (cmNonempty(iwyu)) { run_iwyu += cmStrCat(" --iwyu=", this->GetLocalGenerator()->EscapeForShell(*iwyu)); } - if (tidy && !tidy->empty()) { + if (cmNonempty(tidy)) { run_iwyu += " --tidy="; - const char* driverMode = this->Makefile->GetDefinition( + cmProp p = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_CLANG_TIDY_DRIVER_MODE")); - if (!(driverMode && *driverMode)) { + std::string driverMode; + if (cmNonempty(p)) { + driverMode = *p; + } else { driverMode = lang == "C" ? "gcc" : "g++"; } run_iwyu += this->GetLocalGenerator()->EscapeForShell( cmStrCat(*tidy, ";--extra-arg-before=--driver-mode=", driverMode)); } - if (cpplint && !cpplint->empty()) { + if (cmNonempty(cpplint)) { run_iwyu += cmStrCat( " --cpplint=", this->GetLocalGenerator()->EscapeForShell(*cpplint)); } - if (cppcheck && !cppcheck->empty()) { + if (cmNonempty(cppcheck)) { run_iwyu += cmStrCat(" --cppcheck=", this->GetLocalGenerator()->EscapeForShell(*cppcheck)); } - if ((tidy && !tidy->empty()) || (cpplint && !cpplint->empty()) || - (cppcheck && !cppcheck->empty())) { + if (cmNonempty(tidy) || cmNonempty(cpplint) || cmNonempty(cppcheck)) { run_iwyu += " --source=$in"; } run_iwyu += " -- "; @@ -931,15 +946,15 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( config); } if (firstForConfig) { - const char* pchExtension = - GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); + cmProp pchExtension = GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector<cmSourceFile const*> externalObjects; this->GeneratorTarget->GetExternalObjects(externalObjects, config); for (cmSourceFile const* sf : externalObjects) { auto objectFileName = this->GetGlobalGenerator()->ExpandCFGIntDir( this->GetSourceFilePath(sf), config); - if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + if (!cmSystemTools::StringEndsWith(objectFileName, + cmToCStr(pchExtension))) { this->Configs[config].Objects.push_back(objectFileName); } } @@ -1148,7 +1163,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( // build response file name std::string cmakeLinkVar = cmStrCat(cmakeVarLang, "_RESPONSE_FILE_FLAG"); - const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar); + cmProp flag = GetMakefile()->GetDefinition(cmakeLinkVar); bool const lang_supports_response = !(language == "RC" || (language == "CUDA" && !flag)); @@ -1189,9 +1204,10 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( objBuild.Outputs.push_back(objectFileName); if (firstForConfig) { - const char* pchExtension = + cmProp pchExtension = this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); - if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + if (!cmSystemTools::StringEndsWith(objectFileName, + cmToCStr(pchExtension))) { // Add this object to the list of object files. this->Configs[config].Objects.push_back(objectFileName); } @@ -1359,6 +1375,55 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( objBuild.RspFile = cmStrCat(objectFileName, ".rsp"); + if (language == "ISPC") { + std::string const& objectName = + this->GeneratorTarget->GetObjectName(source); + std::string ispcSource = + cmSystemTools::GetFilenameWithoutLastExtension(objectName); + + std::string ispcDirectory = objectFileDir; + if (cmProp prop = + this->GeneratorTarget->GetProperty("ISPC_HEADER_DIRECTORY")) { + ispcDirectory = *prop; + } + ispcDirectory = + cmStrCat(this->LocalGenerator->GetBinaryDirectory(), '/', ispcDirectory); + + std::string ispcHeader = cmStrCat(ispcDirectory, '/', ispcSource, ".h"); + ispcHeader = this->ConvertToNinjaPath(ispcHeader); + + // Make sure ninja knows what command generates the header + objBuild.ImplicitOuts.push_back(ispcHeader); + + // Make sure ninja knows how to clean the generated header + this->GetGlobalGenerator()->AddAdditionalCleanFile(ispcHeader, config); + + auto ispcSuffixes = + detail::ComputeISPCObjectSuffixes(this->GeneratorTarget); + if (ispcSuffixes.size() > 1) { + auto ispcSideEfffectObjects = detail::ComputeISPCExtraObjects( + objectName, ispcDirectory, ispcSuffixes); + + for (auto sideEffect : ispcSideEfffectObjects) { + sideEffect = this->ConvertToNinjaPath(sideEffect); + objBuild.ImplicitOuts.emplace_back(sideEffect); + this->GetGlobalGenerator()->AddAdditionalCleanFile(sideEffect, config); + } + } + + vars["ISPC_HEADER_FILE"] = + this->GetLocalGenerator()->ConvertToOutputFormat( + ispcHeader, cmOutputConverter::SHELL); + } else { + auto headers = this->GeneratorTarget->GetGeneratedISPCHeaders(config); + if (!headers.empty()) { + std::transform(headers.begin(), headers.end(), headers.begin(), + MapToNinjaPath()); + objBuild.OrderOnlyDeps.insert(objBuild.OrderOnlyDeps.end(), + headers.begin(), headers.end()); + } + } + if (language == "Swift") { this->EmitSwiftDependencyInfo(source, config); } else { diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 8d4372e..9d9ce60 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmNinjaTargetGenerator_h -#define cmNinjaTargetGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -219,5 +218,3 @@ private: std::map<std::string, ByConfig> Configs; }; - -#endif // ! cmNinjaTargetGenerator_h diff --git a/Source/cmNinjaTypes.h b/Source/cmNinjaTypes.h index bd0e83f..320f41b 100644 --- a/Source/cmNinjaTypes.h +++ b/Source/cmNinjaTypes.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmNinjaTypes_h -#define cmNinjaTypes_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -60,5 +59,3 @@ public: cmNinjaVars Variables; std::string RspFile; }; - -#endif // ! cmNinjaTypes_h diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index c964bc1..ad1d5f1 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -103,7 +103,8 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config) std::copy(util_outputs.begin(), util_outputs.end(), std::back_inserter(gg->GetByproductsForCleanTarget())); } - lg->AppendTargetDepends(genTarget, deps, config, config); + lg->AppendTargetDepends(genTarget, deps, config, config, + DependOnTargetArtifact); if (commands.empty()) { phonyBuild.Comment = "Utility command for " + this->GetTargetName(); diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h index ca3f0a4..24b47f8 100644 --- a/Source/cmNinjaUtilityTargetGenerator.h +++ b/Source/cmNinjaUtilityTargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmNinjaUtilityTargetGenerator_h -#define cmNinjaUtilityTargetGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -19,5 +18,3 @@ public: void Generate(const std::string& config) override; }; - -#endif // ! cmNinjaUtilityTargetGenerator_h diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index 5bf1d98..4c33fcc 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmOSXBundleGenerator_h -#define cmOSXBundleGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -69,5 +68,3 @@ private: cmLocalGenerator* LocalGenerator; std::set<std::string>* MacContentFolders; }; - -#endif diff --git a/Source/cmOptionCommand.h b/Source/cmOptionCommand.h index cbd1cb8..912e0ee 100644 --- a/Source/cmOptionCommand.h +++ b/Source/cmOptionCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmOptionCommand_h -#define cmOptionCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,4 +16,3 @@ class cmExecutionStatus; */ bool cmOptionCommand(std::vector<std::string> const& args, cmExecutionStatus& status); -#endif diff --git a/Source/cmOrderDirectories.h b/Source/cmOrderDirectories.h index 8ce53e0..7788ea8 100644 --- a/Source/cmOrderDirectories.h +++ b/Source/cmOrderDirectories.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmOrderDirectories_h -#define cmOrderDirectories_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -95,5 +94,3 @@ private: friend class cmOrderDirectoriesConstraint; friend class cmOrderDirectoriesConstraintLibrary; }; - -#endif diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index a8b4528..655bc87 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmOutputConverter_h -#define cmOutputConverter_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -117,5 +116,3 @@ private: bool LinkScriptShell; }; - -#endif diff --git a/Source/cmOutputRequiredFilesCommand.h b/Source/cmOutputRequiredFilesCommand.h index 4c11894..9daba8f 100644 --- a/Source/cmOutputRequiredFilesCommand.h +++ b/Source/cmOutputRequiredFilesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmOutputRequiredFilesCommand_h -#define cmOutputRequiredFilesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmOutputRequiredFilesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index d712edb..2465069 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -13,6 +13,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -195,7 +196,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args, for (unsigned long i = argvStart; i < count; ++i) { std::ostringstream argName; argName << "ARGV" << i; - const char* arg = status.GetMakefile().GetDefinition(argName.str()); + cmProp arg = status.GetMakefile().GetDefinition(argName.str()); if (!arg) { status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, "PARSE_ARGV called with " + @@ -203,7 +204,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args, cmSystemTools::SetFatalErrorOccured(); return true; } - list.emplace_back(arg); + list.emplace_back(*arg); } } diff --git a/Source/cmParseArgumentsCommand.h b/Source/cmParseArgumentsCommand.h index b2e436d..008977b 100644 --- a/Source/cmParseArgumentsCommand.h +++ b/Source/cmParseArgumentsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmParseArgumentsCommand_h -#define cmParseArgumentsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmParseArgumentsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmPathLabel.h b/Source/cmPathLabel.h index 55dffab..d19d2be 100644 --- a/Source/cmPathLabel.h +++ b/Source/cmPathLabel.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmPathLabel_h -#define cmPathLabel_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -33,5 +32,3 @@ protected: std::string Label; unsigned int Hash; }; - -#endif diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index dea3f8a..01e8c04 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -7,9 +7,11 @@ #include <sstream> #include <vector> +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmState.h" +#include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -157,7 +159,8 @@ static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy, bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, std::string const& version_min, - std::string const& version_max) + std::string const& version_max, + WarnCompat warnCompat) { // Parse components of the minimum version. unsigned int minMajor = 2; @@ -244,13 +247,34 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, polPatch = maxPatch; } - return cmPolicies::ApplyPolicyVersion(mf, polMajor, polMinor, polPatch); + return cmPolicies::ApplyPolicyVersion(mf, polMajor, polMinor, polPatch, + warnCompat); } bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer, unsigned int minorVer, - unsigned int patchVer) + unsigned int patchVer, + WarnCompat warnCompat) { + // Warn about policy versions for which support will be removed. + if (warnCompat == WarnCompat::On && + (majorVer < 2 || (majorVer == 2 && minorVer < 8) || + (majorVer == 2 && minorVer == 8 && patchVer < 12)) && + // Avoid warning on calls generated by install(EXPORT) + // in CMake versions prior to 3.18. + !(majorVer == 2 && minorVer == 6 && patchVer == 0 && + mf->GetStateSnapshot().CanPopPolicyScope() && + cmSystemTools::Strucmp(mf->GetBacktrace().Top().Name.c_str(), + "cmake_policy") == 0)) { + mf->IssueMessage( + MessageType::DEPRECATION_WARNING, + "Compatibility with CMake < 2.8.12 will be removed from " + "a future version of CMake.\n" + "Update the VERSION argument <min> value or use a ...<max> suffix " + "to tell CMake that the project does not need compatibility with " + "older versions."); + } + // now loop over all the policies and set them as appropriate std::vector<cmPolicies::PolicyID> ancientPolicies; for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index a82f421..f9ec0d6 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmPolicies_h -#define cmPolicies_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -320,7 +319,25 @@ class cmMakefile; SELECT(POLICY, CMP0107, "An ALIAS target cannot overwrite another target.", \ 3, 18, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0108, "A target cannot link to itself through an alias.", \ - 3, 18, 0, cmPolicies::WARN) + 3, 18, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0109, \ + "find_program() requires permission to execute but not to read.", 3, \ + 19, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0110, \ + "add_test() supports arbitrary characters in test names.", 3, 19, 0, \ + cmPolicies::WARN) \ + SELECT(POLICY, CMP0111, \ + "An imported target with a missing location fails during " \ + "generation.", \ + 3, 19, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0112, \ + "Target file component generator expressions do not add target " \ + "dependencies.", \ + 3, 19, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0113, \ + "Makefile generators do not repeat custom commands from target " \ + "dependencies.", \ + 3, 19, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -353,7 +370,9 @@ class cmMakefile; F(CMP0099) \ F(CMP0104) \ F(CMP0105) \ - F(CMP0108) + F(CMP0108) \ + F(CMP0112) \ + F(CMP0113) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies @@ -396,12 +415,20 @@ public: //! Get the default status for a policy static cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id); + enum class WarnCompat + { + Off, + On + }; + //! Set a policy level for this listfile static bool ApplyPolicyVersion(cmMakefile* mf, std::string const& version_min, - std::string const& version_max); + std::string const& version_max, + WarnCompat warnCompat); static bool ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer, - unsigned int minorVer, unsigned int patchVer); + unsigned int minorVer, unsigned int patchVer, + WarnCompat warnCompat); //! return a warning string for a given policy static std::string GetPolicyWarning(cmPolicies::PolicyID id); @@ -426,5 +453,3 @@ public: std::bitset<cmPolicies::CMPCOUNT * POLICY_STATUS_COUNT> Status; }; }; - -#endif diff --git a/Source/cmProcessOutput.h b/Source/cmProcessOutput.h index 3db47a4..a1f73bd 100644 --- a/Source/cmProcessOutput.h +++ b/Source/cmProcessOutput.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmProcessOutput_h -#define cmProcessOutput_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -84,5 +83,3 @@ private: bool DoDecodeText(std::string raw, std::string& decoded, wchar_t* lastChar); #endif }; - -#endif diff --git a/Source/cmProcessTools.h b/Source/cmProcessTools.h index 21d59c4..74ec5e0 100644 --- a/Source/cmProcessTools.h +++ b/Source/cmProcessTools.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmProcessTools_h -#define cmProcessTools_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -86,5 +85,3 @@ public: OutputParser* err = nullptr, Encoding encoding = cmProcessOutput::Auto); }; - -#endif diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 2ec66d9..0cfba63 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -15,6 +15,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -302,8 +303,8 @@ bool cmProjectCommand(std::vector<std::string> const& args, } std::string vw; for (std::string const& i : vv) { - const char* const v = mf.GetDefinition(i); - if (v && *v) { + cmProp v = mf.GetDefinition(i); + if (cmNonempty(v)) { if (cmp0048 == cmPolicies::WARN) { if (!injectedProjectCommand) { vw += "\n "; @@ -352,12 +353,12 @@ static bool IncludeByVariable(cmExecutionStatus& status, const std::string& variable) { cmMakefile& mf = status.GetMakefile(); - const char* const include = mf.GetDefinition(variable); + cmProp include = mf.GetDefinition(variable); if (!include) { return true; } - const bool readit = mf.ReadDependentFile(include); + const bool readit = mf.ReadDependentFile(*include); if (readit) { return true; } @@ -366,7 +367,7 @@ static bool IncludeByVariable(cmExecutionStatus& status, return true; } - status.SetError(cmStrCat("could not find file:\n ", include)); + status.SetError(cmStrCat("could not find file:\n ", *include)); return false; } diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h index c06b459..33f0955 100644 --- a/Source/cmProjectCommand.h +++ b/Source/cmProjectCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmProjectCommand_h -#define cmProjectCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmProjectCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmProperty.h b/Source/cmProperty.h index b0fcce7..1e03c3f 100644 --- a/Source/cmProperty.h +++ b/Source/cmProperty.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmProperty_h -#define cmProperty_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -26,4 +25,12 @@ public: using cmProp = const std::string*; -#endif +inline const char* cmToCStr(cmProp p) +{ + return p ? p->c_str() : nullptr; +} + +inline const char* cmToCStrSafe(cmProp p) +{ + return p ? p->c_str() : ""; +} diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h index f83bc4f..fca936e 100644 --- a/Source/cmPropertyDefinition.h +++ b/Source/cmPropertyDefinition.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmPropertyDefinition_h -#define cmPropertyDefinition_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -65,5 +64,3 @@ private: using key_type = std::pair<std::string, cmProperty::ScopeType>; std::map<key_type, cmPropertyDefinition> Map_; }; - -#endif diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h index 5fc46a2..cda585a 100644 --- a/Source/cmPropertyMap.h +++ b/Source/cmPropertyMap.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmPropertyMap_h -#define cmPropertyMap_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -49,5 +48,3 @@ public: private: std::unordered_map<std::string, std::string> Map_; }; - -#endif diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx index 795c2ee..de462db 100644 --- a/Source/cmQTWrapCPPCommand.cxx +++ b/Source/cmQTWrapCPPCommand.cxx @@ -41,7 +41,7 @@ bool cmQTWrapCPPCommand(std::vector<std::string> const& args, cmSourceFile* sf = mf.GetOrCreateSource(newName, true); if (curr) { cmProp p = curr->GetProperty("ABSTRACT"); - sf->SetProperty("ABSTRACT", p ? p->c_str() : nullptr); + sf->SetProperty("ABSTRACT", cmToCStr(p)); } // Compute the name of the header from which to generate the file. diff --git a/Source/cmQTWrapCPPCommand.h b/Source/cmQTWrapCPPCommand.h index 75fa180..28ceb3a 100644 --- a/Source/cmQTWrapCPPCommand.h +++ b/Source/cmQTWrapCPPCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQTWrapCPPCommand_h -#define cmQTWrapCPPCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmQTWrapCPPCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmQTWrapUICommand.h b/Source/cmQTWrapUICommand.h index a17ef54..3f92ea9 100644 --- a/Source/cmQTWrapUICommand.h +++ b/Source/cmQTWrapUICommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQTWrapUICommand_h -#define cmQTWrapUICommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmQTWrapUICommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index a740ba3..cf90417 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoGen_h -#define cmQtAutoGen_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -141,5 +140,3 @@ public: std::vector<std::string> ListOptions_; }; }; - -#endif diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index 3d4f5d7..fac2bbf 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -50,7 +50,7 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( { cmMakefile* makefile = localGen->GetMakefile(); // Detect global autogen target name - if (cmIsOn(makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET"))) { + if (makefile->IsOn("CMAKE_GLOBAL_AUTOGEN_TARGET")) { std::string targetName = makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET_NAME"); if (targetName.empty()) { @@ -61,7 +61,7 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( } // Detect global autorcc target name - if (cmIsOn(makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET"))) { + if (makefile->IsOn("CMAKE_GLOBAL_AUTORCC_TARGET")) { std::string targetName = makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET_NAME"); if (targetName.empty()) { diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h index 2f6e581..cdae137 100644 --- a/Source/cmQtAutoGenGlobalInitializer.h +++ b/Source/cmQtAutoGenGlobalInitializer.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoGenGlobalInitializer_h -#define cmQtAutoGenGlobalInitializer_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -82,5 +81,3 @@ private: CompilerFeatures_; Keywords const Keywords_; }; - -#endif diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index bd0d6bf..3b62e9c 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -315,10 +315,9 @@ bool cmQtAutoGenInitializer::InitCustomTargets() { // Configurations this->MultiConfig = this->GlobalGen->IsMultiConfig(); - this->ConfigDefault = this->Makefile->GetConfigurations(this->ConfigsList); - if (this->ConfigsList.empty()) { - this->ConfigsList.push_back(this->ConfigDefault); - } + this->ConfigDefault = this->Makefile->GetDefaultConfiguration(); + this->ConfigsList = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); // Verbosity { @@ -490,7 +489,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() if (this->Moc.Enabled) { // Path prefix - if (cmIsOn(this->GenTarget->GetSafeProperty("AUTOMOC_PATH_PREFIX"))) { + if (cmIsOn(this->GenTarget->GetProperty("AUTOMOC_PATH_PREFIX"))) { this->Moc.PathPrefix = true; } @@ -789,9 +788,9 @@ bool cmQtAutoGenInitializer::InitScanFiles() // Register files that will be scanned by moc or uic if (this->MocOrUicEnabled()) { - if (cm->IsHeaderExtension(extLower)) { + if (cm->IsAHeaderExtension(extLower)) { addMUHeader(makeMUFile(sf, fullPath, true), extLower); - } else if (cm->IsSourceExtension(extLower)) { + } else if (cm->IsACLikeSourceExtension(extLower)) { addMUSource(makeMUFile(sf, fullPath, true)); } } @@ -863,7 +862,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (sf != nullptr) { auto eMuf = makeMUFile(sf, fullPath, true); - // Ony process moc/uic when the parent is processed as well + // Only process moc/uic when the parent is processed as well if (!muf.MocIt) { eMuf->MocIt = false; } @@ -895,14 +894,14 @@ bool cmQtAutoGenInitializer::InitScanFiles() std::string const& extLower = cmSystemTools::LowerCase(sf->GetExtension()); - if (cm->IsHeaderExtension(extLower)) { + if (cm->IsAHeaderExtension(extLower)) { if (!cm::contains(this->AutogenTarget.Headers, sf.get())) { auto muf = makeMUFile(sf.get(), fullPath, false); if (muf->SkipMoc || muf->SkipUic) { addMUHeader(std::move(muf), extLower); } } - } else if (cm->IsSourceExtension(extLower)) { + } else if (cm->IsACLikeSourceExtension(extLower)) { if (!cm::contains(this->AutogenTarget.Sources, sf.get())) { auto muf = makeMUFile(sf.get(), fullPath, false); if (muf->SkipMoc || muf->SkipUic) { @@ -1659,7 +1658,7 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, }; for (std::string const& prop : props) { cmProp propName = this->Makefile->GetState()->GetGlobalProperty(prop); - if (propName && !propName->empty()) { + if (cmNonempty(propName)) { groupName = *propName; property = prop; break; @@ -1759,8 +1758,8 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) // Read versions from variables for (auto const& keyPair : keys) { - addVersion(target->Makefile->GetDef(std::string(keyPair.first)), - target->Makefile->GetDef(std::string(keyPair.second))); + addVersion(target->Makefile->GetDefinition(std::string(keyPair.first)), + target->Makefile->GetDefinition(std::string(keyPair.second))); } // Read versions from directory properties diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 48ec1a0..3ab303a 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoGenInitializer_h -#define cmQtAutoGenInitializer_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -249,5 +248,3 @@ private: std::vector<Qrc> Qrcs; } Rcc; }; - -#endif diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index 83fb3ed..b4f057d 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoGenerator_h -#define cmQtAutoGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -177,5 +176,3 @@ private: // -- Directories ProjectDirsT ProjectDirs_; }; - -#endif diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h index ffcc2db..20f9d6e 100644 --- a/Source/cmQtAutoMocUic.h +++ b/Source/cmQtAutoMocUic.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoMocUic_h -#define cmQtAutoMocUic_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ * @return true on success */ bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config); - -#endif diff --git a/Source/cmQtAutoRcc.h b/Source/cmQtAutoRcc.h index a74b33a..d525efa 100644 --- a/Source/cmQtAutoRcc.h +++ b/Source/cmQtAutoRcc.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoRcc_h -#define cmQtAutoRcc_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ * @return true on success */ bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config); - -#endif diff --git a/Source/cmRST.h b/Source/cmRST.h index 6b5d416..17cdfe8 100644 --- a/Source/cmRST.h +++ b/Source/cmRST.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef _cmRST_h -#define _cmRST_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -97,5 +96,3 @@ private: std::set<std::string> Replaced; std::string ReplaceName; }; - -#endif diff --git a/Source/cmRange.h b/Source/cmRange.h index 3be5193..30af7d2 100644 --- a/Source/cmRange.h +++ b/Source/cmRange.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmRange_h -#define cmRange_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -235,5 +234,3 @@ auto cmReverseRange(Range const& range) -> cmRange<decltype(range.rbegin())> { return { range.rbegin(), range.rend() }; } - -#endif diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx index 457b708..1345588 100644 --- a/Source/cmRemoveCommand.cxx +++ b/Source/cmRemoveCommand.cxx @@ -4,6 +4,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" // cmRemoveCommand @@ -16,7 +17,7 @@ bool cmRemoveCommand(std::vector<std::string> const& args, std::string const& variable = args[0]; // VAR is always first // get the old value - const char* cacheValue = status.GetMakefile().GetDefinition(variable); + cmProp cacheValue = status.GetMakefile().GetDefinition(variable); // if there is no old value then return if (!cacheValue) { @@ -24,7 +25,7 @@ bool cmRemoveCommand(std::vector<std::string> const& args, } // expand the variable - std::vector<std::string> const varArgsExpanded = cmExpandedList(cacheValue); + std::vector<std::string> const varArgsExpanded = cmExpandedList(*cacheValue); // expand the args // check for REMOVE(VAR v1 v2 ... vn) diff --git a/Source/cmRemoveCommand.h b/Source/cmRemoveCommand.h index fb72ab5..37bfd8c 100644 --- a/Source/cmRemoveCommand.h +++ b/Source/cmRemoveCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmRemoveCommand_h -#define cmRemoveCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,5 +16,3 @@ class cmExecutionStatus; */ bool cmRemoveCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmRemoveDefinitionsCommand.h b/Source/cmRemoveDefinitionsCommand.h index 868416b..8d0fe18 100644 --- a/Source/cmRemoveDefinitionsCommand.h +++ b/Source/cmRemoveDefinitionsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmRemoveDefinitionsCommand_h -#define cmRemoveDefinitionsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmRemoveDefinitionsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmReturnCommand.h b/Source/cmReturnCommand.h index 2404a36..abae1a4 100644 --- a/Source/cmReturnCommand.h +++ b/Source/cmReturnCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmReturnCommand_h -#define cmReturnCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -13,5 +12,3 @@ class cmExecutionStatus; /// Return from a directory or function bool cmReturnCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx index 254131b..6f40ec6 100644 --- a/Source/cmRulePlaceholderExpander.cxx +++ b/Source/cmRulePlaceholderExpander.cxx @@ -90,6 +90,11 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( return replaceValues.AIXExports; } } + if (replaceValues.ISPCHeader) { + if (variable == "ISPC_HEADER") { + return replaceValues.ISPCHeader; + } + } if (replaceValues.Defines && variable == "DEFINES") { return replaceValues.Defines; } @@ -261,7 +266,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( this->VariableMappings["CMAKE_" + compIt->second + "_COMPILE_OPTIONS_SYSROOT"]; - // if there is a required first argument to the compiler add it + // if there are required arguments to the compiler add it // to the compiler string if (!compilerArg1.empty()) { ret += " "; diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h index 09e8a3b..dfce8bb 100644 --- a/Source/cmRulePlaceholderExpander.h +++ b/Source/cmRulePlaceholderExpander.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmRulePlaceholderExpander_h -#define cmRulePlaceholderExpander_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -64,6 +63,7 @@ public: const char* SwiftModuleName; const char* SwiftOutputFileMap; const char* SwiftSources; + const char* ISPCHeader; }; // Expand rule variables in CMake of the type found in language rules @@ -84,5 +84,3 @@ private: std::string CompilerSysroot; std::string LinkerSysroot; }; - -#endif diff --git a/Source/cmRuntimeDependencyArchive.h b/Source/cmRuntimeDependencyArchive.h index 9e2dfb6..7f3b8e9 100644 --- a/Source/cmRuntimeDependencyArchive.h +++ b/Source/cmRuntimeDependencyArchive.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmRuntimeDependencyArchive_h -#define cmRuntimeDependencyArchive_h +#pragma once #include <map> #include <memory> @@ -66,5 +65,3 @@ private: std::map<std::string, std::set<std::string>> ResolvedPaths; std::set<std::string> UnresolvedPaths; }; - -#endif // cmRuntimeDependencyArchive_h diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h index 7d676c9..46d794c 100644 --- a/Source/cmScriptGenerator.h +++ b/Source/cmScriptGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmScriptGenerator_h -#define cmScriptGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -90,5 +89,3 @@ private: void GenerateScriptActionsOnce(std::ostream& os, Indent indent); void GenerateScriptActionsPerConfig(std::ostream& os, Indent indent); }; - -#endif diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index 766d347..a58be62 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -8,6 +8,7 @@ #include "cmFindCommon.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -77,8 +78,8 @@ void cmSearchPath::AddCMakePath(const std::string& variable) assert(this->FC != nullptr); // Get a path from a CMake variable. - if (const char* value = this->FC->Makefile->GetDefinition(variable)) { - std::vector<std::string> expanded = cmExpandedList(value); + if (cmProp value = this->FC->Makefile->GetDefinition(variable)) { + std::vector<std::string> expanded = cmExpandedList(*value); for (std::string const& p : expanded) { this->AddPathInternal( @@ -101,8 +102,8 @@ void cmSearchPath::AddCMakePrefixPath(const std::string& variable) assert(this->FC != nullptr); // Get a path from a CMake variable. - if (const char* value = this->FC->Makefile->GetDefinition(variable)) { - std::vector<std::string> expanded = cmExpandedList(value); + if (cmProp value = this->FC->Makefile->GetDefinition(variable)) { + std::vector<std::string> expanded = cmExpandedList(*value); this->AddPrefixPaths( expanded, this->FC->Makefile->GetCurrentSourceDirectory().c_str()); @@ -178,15 +179,15 @@ void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths, dir += "/"; } if (subdir == "include" || subdir == "lib") { - const char* arch = + cmProp arch = this->FC->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); - if (arch && *arch) { + if (cmNonempty(arch)) { if (this->FC->Makefile->IsDefinitionSet("CMAKE_SYSROOT") && this->FC->Makefile->IsDefinitionSet( "CMAKE_PREFIX_LIBRARY_ARCHITECTURE")) { - this->AddPathInternal(cmStrCat('/', arch, dir, subdir), base); + this->AddPathInternal(cmStrCat('/', *arch, dir, subdir), base); } else { - this->AddPathInternal(cmStrCat(dir, subdir, '/', arch), base); + this->AddPathInternal(cmStrCat(dir, subdir, '/', *arch), base); } } } diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h index 3ecc73b..c15cb97 100644 --- a/Source/cmSearchPath.h +++ b/Source/cmSearchPath.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSearchPath_h -#define cmSearchPath_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -50,5 +49,3 @@ protected: cmFindCommon* FC; std::vector<std::string> Paths; }; - -#endif diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx index cfe3087..e45f3b0 100644 --- a/Source/cmSeparateArgumentsCommand.cxx +++ b/Source/cmSeparateArgumentsCommand.cxx @@ -6,6 +6,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -65,8 +66,8 @@ bool cmSeparateArgumentsCommand(std::vector<std::string> const& args, if (mode == ModeOld) { // Original space-replacement version of command. - if (const char* def = status.GetMakefile().GetDefinition(var)) { - std::string value = def; + if (cmProp def = status.GetMakefile().GetDefinition(var)) { + std::string value = *def; std::replace(value.begin(), value.end(), ' ', ';'); status.GetMakefile().AddDefinition(var, value); } diff --git a/Source/cmSeparateArgumentsCommand.h b/Source/cmSeparateArgumentsCommand.h index e000c51..d284a40 100644 --- a/Source/cmSeparateArgumentsCommand.h +++ b/Source/cmSeparateArgumentsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSeparateArgumentsCommand_h -#define cmSeparateArgumentsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,5 +16,3 @@ class cmExecutionStatus; */ bool cmSeparateArgumentsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 4f7131f..e586fd9 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -136,6 +136,7 @@ bool cmServerProtocol::Activate(cmServer* server, this->m_Server = server; this->m_CMakeInstance = cm::make_unique<cmake>(cmake::RoleProject, cmState::Project); + this->m_WarnUnused = false; const bool result = this->DoActivate(request, errorMessage); if (!result) { this->m_CMakeInstance = nullptr; @@ -636,7 +637,7 @@ cmServerResponse cmServerProtocol1::ProcessGlobalSettings( obj[kTRACE_KEY] = cm->GetTrace(); obj[kTRACE_EXPAND_KEY] = cm->GetTraceExpand(); obj[kWARN_UNINITIALIZED_KEY] = cm->GetWarnUninitialized(); - obj[kWARN_UNUSED_KEY] = cm->GetWarnUnused(); + obj[kWARN_UNUSED_KEY] = m_WarnUnused; obj[kWARN_UNUSED_CLI_KEY] = cm->GetWarnUnusedCli(); obj[kCHECK_SYSTEM_VARS_KEY] = cm->GetCheckSystemVars(); @@ -682,7 +683,7 @@ cmServerResponse cmServerProtocol1::ProcessSetGlobalSettings( setBool(request, kTRACE_EXPAND_KEY, [cm](bool e) { cm->SetTraceExpand(e); }); setBool(request, kWARN_UNINITIALIZED_KEY, [cm](bool e) { cm->SetWarnUninitialized(e); }); - setBool(request, kWARN_UNUSED_KEY, [cm](bool e) { cm->SetWarnUnused(e); }); + setBool(request, kWARN_UNUSED_KEY, [this](bool e) { m_WarnUnused = e; }); setBool(request, kWARN_UNUSED_CLI_KEY, [cm](bool e) { cm->SetWarnUnusedCli(e); }); setBool(request, kCHECK_SYSTEM_VARS_KEY, diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index c71b7bf..6009e23 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -94,6 +94,7 @@ protected: // Implement protocol specific activation tasks here. Called from Activate(). virtual bool DoActivate(const cmServerRequest& request, std::string* errorMessage); + bool m_WarnUnused = false; // storage for legacy option private: std::unique_ptr<cmake> m_CMakeInstance; diff --git a/Source/cmSetCommand.h b/Source/cmSetCommand.h index 0973d33..695b185 100644 --- a/Source/cmSetCommand.h +++ b/Source/cmSetCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSetCommand_h -#define cmSetCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,5 +16,3 @@ class cmExecutionStatus; */ bool cmSetCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmSetDirectoryPropertiesCommand.h b/Source/cmSetDirectoryPropertiesCommand.h index c243dd7..f5b6406 100644 --- a/Source/cmSetDirectoryPropertiesCommand.h +++ b/Source/cmSetDirectoryPropertiesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSetDirectoryPropertiesCommand_h -#define cmSetDirectoryPropertiesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmSetDirectoryPropertiesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h index af566a3..89fdd9a 100644 --- a/Source/cmSetPropertyCommand.h +++ b/Source/cmSetPropertyCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSetsPropertiesCommand_h -#define cmSetsPropertiesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -41,5 +40,3 @@ void MakeSourceFilePathsAbsoluteIfNeeded( std::vector<std::string>::const_iterator files_it_begin, std::vector<std::string>::const_iterator files_it_end, bool needed); } - -#endif diff --git a/Source/cmSetSourceFilesPropertiesCommand.h b/Source/cmSetSourceFilesPropertiesCommand.h index 5eef785..8f88522 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.h +++ b/Source/cmSetSourceFilesPropertiesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSetSourceFilesPropertiesCommand_h -#define cmSetSourceFilesPropertiesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h index 9d40c74..0c04f31 100644 --- a/Source/cmSetTargetPropertiesCommand.h +++ b/Source/cmSetTargetPropertiesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSetTargetsPropertiesCommand_h -#define cmSetTargetsPropertiesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmSetTestsPropertiesCommand.h b/Source/cmSetTestsPropertiesCommand.h index 4b75464..b4f1641 100644 --- a/Source/cmSetTestsPropertiesCommand.h +++ b/Source/cmSetTestsPropertiesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSetTestsPropertiesCommand_h -#define cmSetTestsPropertiesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmSetTestsPropertiesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index b2d905e..58af8f0 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -6,6 +6,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -26,15 +27,15 @@ bool cmSiteNameCommand(std::vector<std::string> const& args, paths.emplace_back("/sbin"); paths.emplace_back("/usr/local/bin"); - const char* cacheValue = status.GetMakefile().GetDefinition(args[0]); + cmProp cacheValue = status.GetMakefile().GetDefinition(args[0]); if (cacheValue) { return true; } - const char* temp = status.GetMakefile().GetDefinition("HOSTNAME"); + cmProp temp = status.GetMakefile().GetDefinition("HOSTNAME"); std::string hostname_cmd; if (temp) { - hostname_cmd = temp; + hostname_cmd = *temp; } else { hostname_cmd = cmSystemTools::FindProgram("hostname", paths); } diff --git a/Source/cmSiteNameCommand.h b/Source/cmSiteNameCommand.h index e8fc608..432ba37 100644 --- a/Source/cmSiteNameCommand.h +++ b/Source/cmSiteNameCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSiteNameCommand_h -#define cmSiteNameCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,5 +16,3 @@ class cmExecutionStatus; */ bool cmSiteNameCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index f525439..ef44a57 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSourceFile.h" -#include <array> #include <utility> #include "cmGlobalGenerator.h" @@ -130,13 +129,11 @@ bool cmSourceFile::FindFullPath(std::string* error) // Location path std::string const& lPath = this->Location.GetFullPath(); // List of extension lists - std::array<std::vector<std::string> const*, 2> const extsLists = { - { &makefile->GetCMakeInstance()->GetSourceExtensions(), - &makefile->GetCMakeInstance()->GetHeaderExtensions() } - }; + std::vector<std::string> exts = + makefile->GetCMakeInstance()->GetAllExtensions(); // Tries to find the file in a given directory - auto findInDir = [this, &extsLists, &lPath](std::string const& dir) -> bool { + auto findInDir = [this, &exts, &lPath](std::string const& dir) -> bool { // Compute full path std::string const fullPath = cmSystemTools::CollapseFullPath(lPath, dir); // Try full path @@ -145,14 +142,12 @@ bool cmSourceFile::FindFullPath(std::string* error) return true; } // Try full path with extension - for (auto& exts : extsLists) { - for (std::string const& ext : *exts) { - if (!ext.empty()) { - std::string extPath = cmStrCat(fullPath, '.', ext); - if (cmSystemTools::FileExists(extPath)) { - this->FullPath = extPath; - return true; - } + for (std::string const& ext : exts) { + if (!ext.empty()) { + std::string extPath = cmStrCat(fullPath, '.', ext); + if (cmSystemTools::FileExists(extPath)) { + this->FullPath = extPath; + return true; } } } @@ -175,11 +170,9 @@ bool cmSourceFile::FindFullPath(std::string* error) // Compose error std::string err = cmStrCat("Cannot find source file:\n ", lPath, "\nTried extensions"); - for (auto exts : extsLists) { - for (std::string const& ext : *exts) { - err += " ."; - err += ext; - } + for (std::string const& ext : exts) { + err += " ."; + err += ext; } if (error != nullptr) { *error = std::move(err); @@ -387,8 +380,7 @@ const char* cmSourceFile::GetSafeProperty(const std::string& prop) const bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const { - cmProp p = this->GetProperty(prop); - return p && cmIsOn(*p); + return cmIsOn(this->GetProperty(prop)); } void cmSourceFile::SetProperties(cmPropertyMap properties) diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index e669015..39ea8e3 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSourceFile_h -#define cmSourceFile_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -161,5 +160,3 @@ private: #define CM_PCH_REGEX "cmake_pch(_[^.]+)?\\.(h|hxx)$" #define CM_RESOURCE_REGEX "\\.(pdf|plist|png|jpeg|jpg|storyboard|xcassets)$" - -#endif diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index e852c05..222bafa 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -101,7 +101,7 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name) cmMakefile const* mf = this->Makefile; auto cm = mf->GetCMakeInstance(); if (!gg->GetLanguageFromExtension(ext.c_str()).empty() || - cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext)) { + cm->IsAKnownExtension(ext)) { // This is a known extension. Use the given filename with extension. this->Name = cmSystemTools::GetFilenameName(name); this->AmbiguousExtension = false; @@ -157,7 +157,7 @@ bool cmSourceFileLocation::MatchesAmbiguousExtension( auto ext = cm::string_view(this->Name).substr(loc.Name.size() + 1); cmMakefile const* mf = this->Makefile; auto cm = mf->GetCMakeInstance(); - return cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext); + return cm->IsAKnownExtension(ext); } bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc) diff --git a/Source/cmSourceFileLocation.h b/Source/cmSourceFileLocation.h index 87040b8..b373d3d 100644 --- a/Source/cmSourceFileLocation.h +++ b/Source/cmSourceFileLocation.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSourceFileLocation_h -#define cmSourceFileLocation_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -102,5 +101,3 @@ private: void Update(cmSourceFileLocation const& loc); void UpdateExtension(const std::string& name); }; - -#endif diff --git a/Source/cmSourceFileLocationKind.h b/Source/cmSourceFileLocationKind.h index dd4c6dd..73108f1 100644 --- a/Source/cmSourceFileLocationKind.h +++ b/Source/cmSourceFileLocationKind.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSourceFileLocationKind_h -#define cmSourceFileLocationKind_h +#pragma once enum class cmSourceFileLocationKind { @@ -11,5 +10,3 @@ enum class cmSourceFileLocationKind // extensions or absolute path. Known }; - -#endif diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h index 623cded..295240d 100644 --- a/Source/cmSourceGroup.h +++ b/Source/cmSourceGroup.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSourceGroup_h -#define cmSourceGroup_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -125,5 +124,3 @@ private: std::unique_ptr<cmSourceGroupInternals> Internal; }; - -#endif diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h index ad39701..44e1f8e 100644 --- a/Source/cmSourceGroupCommand.h +++ b/Source/cmSourceGroupCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSourceGroupCommand_h -#define cmSourceGroupCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmSourceGroupCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx new file mode 100644 index 0000000..8672f61 --- /dev/null +++ b/Source/cmStandardLevelResolver.cxx @@ -0,0 +1,538 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmStandardLevelResolver.h" + +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <sstream> +#include <stdexcept> +#include <unordered_map> +#include <utility> +#include <vector> + +#include <cm/iterator> +#include <cmext/algorithm> + +#include "cmGeneratorExpression.h" +#include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmProperty.h" +#include "cmStringAlgorithms.h" +#include "cmTarget.h" +#include "cmake.h" + +namespace { + +#define FEATURE_STRING(F) , #F +const char* const C_FEATURES[] = { nullptr FOR_EACH_C_FEATURE( + FEATURE_STRING) }; + +const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE( + FEATURE_STRING) }; + +const char* const CUDA_FEATURES[] = { nullptr FOR_EACH_CUDA_FEATURE( + FEATURE_STRING) }; +#undef FEATURE_STRING + +struct StandardNeeded +{ + int index; + int value; +}; + +struct StanardLevelComputer +{ + explicit StanardLevelComputer(std::string lang, std::vector<int> levels, + std::vector<std::string> levelsStr) + : Language(std::move(lang)) + , Levels(std::move(levels)) + , LevelsAsStrings(std::move(levelsStr)) + { + assert(levels.size() == levelsStr.size()); + } + + std::string GetCompileOptionDef(cmMakefile* makefile, + cmGeneratorTarget const* target, + std::string const& config) const + { + + const auto& stds = this->Levels; + const auto& stdsStrings = this->LevelsAsStrings; + + cmProp defaultStd = makefile->GetDefinition( + cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT")); + if (!cmNonempty(defaultStd)) { + // this compiler has no notion of language standard levels + return std::string{}; + } + + bool ext = true; + if (cmProp extPropValue = target->GetLanguageExtensions(this->Language)) { + if (cmIsOff(*extPropValue)) { + ext = false; + } + } + + cmProp standardProp = target->GetLanguageStandard(this->Language, config); + if (!standardProp) { + if (ext) { + // No language standard is specified and extensions are not disabled. + // Check if this compiler needs a flag to enable extensions. + return cmStrCat("CMAKE_", this->Language, "_EXTENSION_COMPILE_OPTION"); + } + return std::string{}; + } + + std::string const type = ext ? "EXTENSION" : "STANDARD"; + + if (target->GetLanguageStandardRequired(this->Language)) { + std::string option_flag = cmStrCat( + "CMAKE_", this->Language, *standardProp, "_", type, "_COMPILE_OPTION"); + + cmProp opt = target->Target->GetMakefile()->GetDefinition(option_flag); + if (!opt) { + std::ostringstream e; + e << "Target \"" << target->GetName() + << "\" requires the language " + "dialect \"" + << this->Language << *standardProp << "\" " + << (ext ? "(with compiler extensions)" : "") + << ", but CMake " + "does not know the compile flags to use to enable it."; + makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + } + return option_flag; + } + + std::string standardStr(*standardProp); + if (this->Language == "CUDA" && standardStr == "98") { + standardStr = "03"; + } + + int standardValue = -1; + int defaultValue = -1; + try { + standardValue = std::stoi(standardStr); + defaultValue = std::stoi(*defaultStd); + } catch (std::invalid_argument&) { + // fall through as we want an error + // when we can't find the bad value in the `stds` vector + } + + auto stdIt = std::find(cm::cbegin(stds), cm::cend(stds), standardValue); + if (stdIt == cm::cend(stds)) { + std::string e = + cmStrCat(this->Language, "_STANDARD is set to invalid value '", + standardStr, "'"); + makefile->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e, + target->GetBacktrace()); + return std::string{}; + } + + auto defaultStdIt = + std::find(cm::cbegin(stds), cm::cend(stds), defaultValue); + if (defaultStdIt == cm::cend(stds)) { + std::string e = cmStrCat("CMAKE_", this->Language, + "_STANDARD_DEFAULT is set to invalid value '", + *defaultStd, "'"); + makefile->IssueMessage(MessageType::INTERNAL_ERROR, e); + return std::string{}; + } + + // If the standard requested is older than the compiler's default + // then we need to use a flag to change it. + if (stdIt <= defaultStdIt) { + auto offset = std::distance(cm::cbegin(stds), stdIt); + return cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type, + "_COMPILE_OPTION"); + } + + // The standard requested is at least as new as the compiler's default, + // and the standard request is not required. Decay to the newest standard + // for which a flag is defined. + for (; defaultStdIt < stdIt; --stdIt) { + auto offset = std::distance(cm::cbegin(stds), stdIt); + std::string option_flag = + cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type, + "_COMPILE_OPTION"); + if (target->Target->GetMakefile()->GetDefinition(option_flag)) { + return option_flag; + } + } + + return std::string{}; + } + + bool GetNewRequiredStandard(cmMakefile* makefile, + std::string const& targetName, + const std::string& feature, + cmProp currentLangStandardValue, + std::string& newRequiredStandard, + std::string* error) const + { + if (currentLangStandardValue) { + newRequiredStandard = *currentLangStandardValue; + } else { + newRequiredStandard.clear(); + } + + auto needed = this->HighestStandardNeeded(makefile, feature); + + cmProp existingStandard = currentLangStandardValue; + if (existingStandard == nullptr) { + cmProp defaultStandard = makefile->GetDefinition( + cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT")); + if (cmNonempty(defaultStandard)) { + existingStandard = defaultStandard; + } + } + + auto existingLevelIter = cm::cend(this->Levels); + if (existingStandard) { + existingLevelIter = + std::find(cm::cbegin(this->Levels), cm::cend(this->Levels), + std::stoi(*existingStandard)); + if (existingLevelIter == cm::cend(this->Levels)) { + const std::string e = + cmStrCat("The ", this->Language, "_STANDARD property on target \"", + targetName, "\" contained an invalid value: \"", + *existingStandard, "\"."); + if (error) { + *error = e; + } else { + makefile->IssueMessage(MessageType::FATAL_ERROR, e); + } + return false; + } + } + + if (needed.index != -1) { + // Ensure the C++ language level is high enough to support + // the needed C++ features. + if (existingLevelIter == cm::cend(this->Levels) || + existingLevelIter < this->Levels.begin() + needed.index) { + newRequiredStandard = this->LevelsAsStrings[needed.index]; + } + } + + return true; + } + + bool HaveStandardAvailable(cmMakefile* makefile, + cmGeneratorTarget const* target, + std::string const& config, + std::string const& feature) const + { + cmProp defaultStandard = makefile->GetDefinition( + cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT")); + if (!defaultStandard) { + makefile->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("CMAKE_", this->Language, + "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " + "not fully configured for this compiler.")); + // Return true so the caller does not try to lookup the default standard. + return true; + } + // convert defaultStandard to an integer + if (std::find(cm::cbegin(this->Levels), cm::cend(this->Levels), + std::stoi(*defaultStandard)) == cm::cend(this->Levels)) { + const std::string e = cmStrCat("The CMAKE_", this->Language, + "_STANDARD_DEFAULT variable contains an " + "invalid value: \"", + *defaultStandard, "\"."); + makefile->IssueMessage(MessageType::INTERNAL_ERROR, e); + return false; + } + + cmProp existingStandard = + target->GetLanguageStandard(this->Language, config); + if (!existingStandard) { + existingStandard = defaultStandard; + } + + auto existingLevelIter = + std::find(cm::cbegin(this->Levels), cm::cend(this->Levels), + std::stoi(*existingStandard)); + if (existingLevelIter == cm::cend(this->Levels)) { + const std::string e = + cmStrCat("The ", this->Language, "_STANDARD property on target \"", + target->GetName(), "\" contained an invalid value: \"", + *existingStandard, "\"."); + makefile->IssueMessage(MessageType::FATAL_ERROR, e); + return false; + } + + auto needed = this->HighestStandardNeeded(makefile, feature); + + return (needed.index == -1) || + (this->Levels.begin() + needed.index) <= existingLevelIter; + } + + StandardNeeded HighestStandardNeeded(cmMakefile* makefile, + std::string const& feature) const + { + std::string prefix = cmStrCat("CMAKE_", this->Language); + StandardNeeded maxLevel = { -1, -1 }; + for (size_t i = 0; i < this->Levels.size(); ++i) { + if (cmProp prop = makefile->GetDefinition( + cmStrCat(prefix, this->LevelsAsStrings[i], "_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(*prop); + if (cm::contains(props, feature)) { + maxLevel = { static_cast<int>(i), this->Levels[i] }; + } + } + } + return maxLevel; + } + + bool IsLaterStandard(int lhs, int rhs) const + { + auto rhsIt = + std::find(cm::cbegin(this->Levels), cm::cend(this->Levels), rhs); + + return std::find(rhsIt, cm::cend(this->Levels), lhs) != + cm::cend(this->Levels); + } + + std::string Language; + std::vector<int> Levels; + std::vector<std::string> LevelsAsStrings; +}; + +std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping = + { + { "C", + StanardLevelComputer{ "C", std::vector<int>{ 90, 99, 11 }, + std::vector<std::string>{ "90", "99", "11" } } }, + { "CXX", + StanardLevelComputer{ + "CXX", std::vector<int>{ 98, 11, 14, 17, 20 }, + std::vector<std::string>{ "98", "11", "14", "17", "20" } } }, + { "CUDA", + StanardLevelComputer{ + "CUDA", std::vector<int>{ 03, 11, 14, 17, 20 }, + std::vector<std::string>{ "03", "11", "14", "17", "20" } } }, + { "OBJC", + StanardLevelComputer{ "OBJC", std::vector<int>{ 90, 99, 11 }, + std::vector<std::string>{ "90", "99", "11" } } }, + { "OBJCXX", + StanardLevelComputer{ + "OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20 }, + std::vector<std::string>{ "98", "11", "14", "17", "20" } } }, + }; +} + +std::string cmStandardLevelResolver::GetCompileOptionDef( + cmGeneratorTarget const* target, std::string const& lang, + std::string const& config) const +{ + const auto& mapping = StandardComputerMapping.find(lang); + if (mapping == cm::cend(StandardComputerMapping)) { + return std::string{}; + } + + return mapping->second.GetCompileOptionDef(this->Makefile, target, config); +} + +bool cmStandardLevelResolver::AddRequiredTargetFeature( + cmTarget* target, const std::string& feature, std::string* error) const +{ + if (cmGeneratorExpression::Find(feature) != std::string::npos) { + target->AppendProperty("COMPILE_FEATURES", feature); + return true; + } + + std::string lang; + if (!this->CheckCompileFeaturesAvailable(target->GetName(), feature, lang, + error)) { + return false; + } + + target->AppendProperty("COMPILE_FEATURES", feature); + + // FIXME: Add a policy to avoid updating the <LANG>_STANDARD target + // property due to COMPILE_FEATURES. The language standard selection + // should be done purely at generate time based on whatever the project + // code put in these properties explicitly. That is mostly true now, + // but for compatibility we need to continue updating the property here. + std::string newRequiredStandard; + bool newRequired = this->GetNewRequiredStandard( + target->GetName(), feature, + target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard, + error); + if (!newRequiredStandard.empty()) { + target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard); + } + return newRequired; +} + +bool cmStandardLevelResolver::CheckCompileFeaturesAvailable( + const std::string& targetName, const std::string& feature, std::string& lang, + std::string* error) const +{ + if (!this->CompileFeatureKnown(targetName, feature, lang, error)) { + return false; + } + + const char* features = this->CompileFeaturesAvailable(lang, error); + if (!features) { + return false; + } + + std::vector<std::string> availableFeatures = cmExpandedList(features); + if (!cm::contains(availableFeatures, feature)) { + std::ostringstream e; + e << "The compiler feature \"" << feature << "\" is not known to " << lang + << " compiler\n\"" + << this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID") + << "\"\nversion " + << this->Makefile->GetSafeDefinition("CMAKE_" + lang + + "_COMPILER_VERSION") + << "."; + if (error) { + *error = e.str(); + } else { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + } + return false; + } + + return true; +} + +bool cmStandardLevelResolver::CompileFeatureKnown( + const std::string& targetName, const std::string& feature, std::string& lang, + std::string* error) const +{ + assert(cmGeneratorExpression::Find(feature) == std::string::npos); + + bool isCFeature = + std::find_if(cm::cbegin(C_FEATURES) + 1, cm::cend(C_FEATURES), + cmStrCmp(feature)) != cm::cend(C_FEATURES); + if (isCFeature) { + lang = "C"; + return true; + } + bool isCxxFeature = + std::find_if(cm::cbegin(CXX_FEATURES) + 1, cm::cend(CXX_FEATURES), + cmStrCmp(feature)) != cm::cend(CXX_FEATURES); + if (isCxxFeature) { + lang = "CXX"; + return true; + } + bool isCudaFeature = + std::find_if(cm::cbegin(CUDA_FEATURES) + 1, cm::cend(CUDA_FEATURES), + cmStrCmp(feature)) != cm::cend(CUDA_FEATURES); + if (isCudaFeature) { + lang = "CUDA"; + return true; + } + std::ostringstream e; + if (error) { + e << "specified"; + } else { + e << "Specified"; + } + e << " unknown feature \"" << feature + << "\" for " + "target \"" + << targetName << "\"."; + if (error) { + *error = e.str(); + } else { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + } + return false; +} + +const char* cmStandardLevelResolver::CompileFeaturesAvailable( + const std::string& lang, std::string* error) const +{ + if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) { + std::ostringstream e; + if (error) { + e << "cannot"; + } else { + e << "Cannot"; + } + e << " use features from non-enabled language " << lang; + if (error) { + *error = e.str(); + } else { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + } + return nullptr; + } + + cmProp featuresKnown = + this->Makefile->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES"); + + if (!cmNonempty(featuresKnown)) { + std::ostringstream e; + if (error) { + e << "no"; + } else { + e << "No"; + } + e << " known features for " << lang << " compiler\n\"" + << this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID") + << "\"\nversion " + << this->Makefile->GetSafeDefinition("CMAKE_" + lang + + "_COMPILER_VERSION") + << "."; + if (error) { + *error = e.str(); + } else { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + } + return nullptr; + } + return cmToCStr(featuresKnown); +} + +bool cmStandardLevelResolver::GetNewRequiredStandard( + const std::string& targetName, const std::string& feature, + cmProp currentLangStandardValue, std::string& newRequiredStandard, + std::string* error) const +{ + std::string lang; + if (!this->CheckCompileFeaturesAvailable(targetName, feature, lang, error)) { + return false; + } + + auto mapping = StandardComputerMapping.find(lang); + if (mapping != cm::cend(StandardComputerMapping)) { + return mapping->second.GetNewRequiredStandard( + this->Makefile, targetName, feature, currentLangStandardValue, + newRequiredStandard, error); + } + return false; +} + +bool cmStandardLevelResolver::HaveStandardAvailable( + cmGeneratorTarget const* target, std::string const& lang, + std::string const& config, const std::string& feature) const +{ + auto mapping = StandardComputerMapping.find(lang); + if (mapping != cm::cend(StandardComputerMapping)) { + return mapping->second.HaveStandardAvailable(this->Makefile, target, + config, feature); + } + return false; +} + +bool cmStandardLevelResolver::IsLaterStandard(std::string const& lang, + std::string const& lhs, + std::string const& rhs) const +{ + auto mapping = StandardComputerMapping.find(lang); + if (mapping != cm::cend(StandardComputerMapping)) { + return mapping->second.IsLaterStandard(std::stoi(lhs), std::stoi(rhs)); + } + return false; +} diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h new file mode 100644 index 0000000..d84fbcb --- /dev/null +++ b/Source/cmStandardLevelResolver.h @@ -0,0 +1,57 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include <string> + +#include "cmProperty.h" + +class cmMakefile; +class cmGeneratorTarget; +class cmTarget; + +class cmStandardLevelResolver +{ + +public: + explicit cmStandardLevelResolver(cmMakefile* makefile) + : Makefile(makefile) + { + } + + std::string GetCompileOptionDef(cmGeneratorTarget const* target, + std::string const& lang, + std::string const& config) const; + + bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature, + std::string* error = nullptr) const; + + bool CompileFeatureKnown(const std::string& targetName, + const std::string& feature, std::string& lang, + std::string* error) const; + + const char* CompileFeaturesAvailable(const std::string& lang, + std::string* error) const; + + bool GetNewRequiredStandard(const std::string& targetName, + const std::string& feature, + cmProp currentLangStandardValue, + std::string& newRequiredStandard, + std::string* error = nullptr) const; + + bool HaveStandardAvailable(cmGeneratorTarget const* target, + std::string const& lang, + std::string const& config, + const std::string& feature) const; + + bool IsLaterStandard(std::string const& lang, std::string const& lhs, + std::string const& rhs) const; + +private: + bool CheckCompileFeaturesAvailable(const std::string& targetName, + const std::string& feature, + std::string& lang, + std::string* error) const; + + cmMakefile* Makefile; +}; diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h index e0b2116..0203779 100644 --- a/Source/cmStandardLexer.h +++ b/Source/cmStandardLexer.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmStandardLexer_h -#define cmStandardLexer_h +#pragma once #if defined(__linux) /* Needed for glibc < 2.12 */ @@ -74,5 +73,3 @@ typedef KWIML_INT_int16_t flex_int16_t; typedef KWIML_INT_uint16_t flex_uint16_t; typedef KWIML_INT_int32_t flex_int32_t; typedef KWIML_INT_uint32_t flex_uint32_t; - -#endif diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 0b6b40f..e96c82f 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -469,9 +469,10 @@ void cmState::AddUnexpectedCommand(std::string const& name, const char* error) name, [name, error](std::vector<cmListFileArgument> const&, cmExecutionStatus& status) -> bool { - const char* versionValue = + cmProp versionValue = status.GetMakefile().GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); - if (name == "endif" && (!versionValue || atof(versionValue) <= 1.4)) { + if (name == "endif" && + (!versionValue || atof(versionValue->c_str()) <= 1.4)) { return true; } status.SetError(error); @@ -623,8 +624,7 @@ cmProp cmState::GetGlobalProperty(const std::string& prop) bool cmState::GetGlobalPropertyAsBool(const std::string& prop) { - cmProp p = this->GetGlobalProperty(prop); - return p && cmIsOn(*p); + return cmIsOn(this->GetGlobalProperty(prop)); } void cmState::SetSourceDirectory(std::string const& sourceDirectory) diff --git a/Source/cmState.h b/Source/cmState.h index 885496a..14870eb 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmState_h -#define cmState_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -249,5 +248,3 @@ private: bool NinjaMulti = false; Mode CurrentMode = Unknown; }; - -#endif diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index a4fe663..796bb1f 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -648,8 +648,7 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const bool cmStateDirectory::GetPropertyAsBool(const std::string& prop) const { - cmProp p = this->GetProperty(prop); - return p && cmIsOn(*p); + return cmIsOn(this->GetProperty(prop)); } std::vector<std::string> cmStateDirectory::GetPropertyKeys() const diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index 765af6f..56a262d 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmStateDirectory_h -#define cmStateDirectory_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -104,5 +103,3 @@ private: cmStateSnapshot Snapshot_; friend class cmStateSnapshot; }; - -#endif diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h index 4efaf97..4892644 100644 --- a/Source/cmStatePrivate.h +++ b/Source/cmStatePrivate.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmStatePrivate_h -#define cmStatePrivate_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -99,5 +98,3 @@ struct cmStateDetail::BuildsystemDirectoryStateType std::vector<cmStateSnapshot> Children; }; - -#endif diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index c223431..1e20abb 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -53,7 +53,7 @@ void cmStateSnapshot::SetListFile(const std::string& listfile) *this->Position->ExecutionListFile = listfile; } -std::string cmStateSnapshot::GetExecutionListFile() const +std::string const& cmStateSnapshot::GetExecutionListFile() const { return *this->Position->ExecutionListFile; } @@ -148,7 +148,7 @@ bool cmStateSnapshot::PopPolicy() bool cmStateSnapshot::CanPopPolicyScope() { - return this->Position->Policies == this->Position->PolicyScope; + return this->Position->Policies != this->Position->PolicyScope; } void cmStateSnapshot::SetPolicy(cmPolicies::PolicyID id, @@ -232,11 +232,6 @@ void cmStateSnapshot::RemoveDefinition(std::string const& name) this->Position->Vars->Unset(name); } -std::vector<std::string> cmStateSnapshot::UnusedKeys() const -{ - return this->Position->Vars->UnusedKeys(); -} - std::vector<std::string> cmStateSnapshot::ClosureKeys() const { return cmDefinitions::ClosureKeys(this->Position->Vars, @@ -328,7 +323,7 @@ void cmStateSnapshot::SetDefaultDefinitions() #if defined(__CYGWIN__) std::string legacy; if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) && - cmIsOn(legacy.c_str())) { + cmIsOn(legacy)) { this->SetDefinition("WIN32", "1"); this->SetDefinition("CMAKE_HOST_WIN32", "1"); } @@ -416,8 +411,7 @@ void cmStateSnapshot::InitializeFromParent() parent->BuildSystemDirectory->Properties.GetPropertyValue( "INCLUDE_REGULAR_EXPRESSION"); this->Position->BuildSystemDirectory->Properties.SetProperty( - "INCLUDE_REGULAR_EXPRESSION", - include_regex ? include_regex->c_str() : nullptr); + "INCLUDE_REGULAR_EXPRESSION", cmToCStr(include_regex)); } cmState* cmStateSnapshot::GetState() const diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h index 021fd53..d06cba3 100644 --- a/Source/cmStateSnapshot.h +++ b/Source/cmStateSnapshot.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmStateSnapshot_h -#define cmStateSnapshot_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -28,13 +27,12 @@ public: bool IsInitialized(std::string const& name) const; void SetDefinition(std::string const& name, cm::string_view value); void RemoveDefinition(std::string const& name); - std::vector<std::string> UnusedKeys() const; std::vector<std::string> ClosureKeys() const; bool RaiseScope(std::string const& var, const char* varDef); void SetListFile(std::string const& listfile); - std::string GetExecutionListFile() const; + std::string const& GetExecutionListFile() const; std::vector<cmStateSnapshot> GetChildren(); @@ -88,5 +86,3 @@ private: bool operator==(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs); bool operator!=(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs); - -#endif diff --git a/Source/cmStateTypes.h b/Source/cmStateTypes.h index d089ea7..b8c1cca 100644 --- a/Source/cmStateTypes.h +++ b/Source/cmStateTypes.h @@ -1,8 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmStateTypes_h -#define cmStateTypes_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -60,5 +59,3 @@ enum ArtifactType ImportLibraryArtifact }; } - -#endif diff --git a/Source/cmString.cxx b/Source/cmString.cxx index 2a0c125..898b828 100644 --- a/Source/cmString.cxx +++ b/Source/cmString.cxx @@ -17,7 +17,7 @@ static std::string const empty_string_; void String::internally_mutate_to_stable_string() { // We assume that only one thread mutates this instance at - // a time even if we point to a shared string buffer refernced + // a time even if we point to a shared string buffer referenced // by other threads. *this = String(data(), size()); } diff --git a/Source/cmString.hxx b/Source/cmString.hxx index 87bfdff..b41b960 100644 --- a/Source/cmString.hxx +++ b/Source/cmString.hxx @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmString_hxx -#define cmString_hxx +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -383,7 +382,7 @@ public: instance is mutated or destroyed. */ std::string const* str_if_stable() const; - /** Get a refernce to a normal std::string. The reference + /** Get a reference to a normal std::string. The reference is valid until this instance is mutated or destroyed. */ std::string const& str(); @@ -928,5 +927,3 @@ struct hash<cm::String> } }; } - -#endif diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx index 71d28a4..e0af281 100644 --- a/Source/cmStringAlgorithms.cxx +++ b/Source/cmStringAlgorithms.cxx @@ -7,6 +7,7 @@ #include <cstddef> // IWYU pragma: keep #include <cstdio> #include <cstdlib> +#include <iterator> std::string cmTrimWhitespace(cm::string_view str) { @@ -323,3 +324,52 @@ bool cmStrToULong(std::string const& str, unsigned long* value) { return cmStrToULong(str.c_str(), value); } + +template <typename Range> +std::size_t getJoinedLength(Range const& rng, cm::string_view separator) +{ + std::size_t rangeLength{}; + for (auto const& item : rng) { + rangeLength += item.size(); + } + + auto const separatorsLength = (rng.size() - 1) * separator.size(); + + return rangeLength + separatorsLength; +} + +template <typename Range> +std::string cmJoinImpl(Range const& rng, cm::string_view separator, + cm::string_view initial) +{ + if (rng.empty()) { + return { std::begin(initial), std::end(initial) }; + } + + std::string result; + result.reserve(initial.size() + getJoinedLength(rng, separator)); + result.append(std::begin(initial), std::end(initial)); + + auto begin = std::begin(rng); + auto end = std::end(rng); + result += *begin; + + for (++begin; begin != end; ++begin) { + result.append(std::begin(separator), std::end(separator)); + result += *begin; + } + + return result; +} + +std::string cmJoin(std::vector<std::string> const& rng, + cm::string_view separator, cm::string_view initial) +{ + return cmJoinImpl(rng, separator, initial); +} + +std::string cmJoin(cmStringRange const& rng, cm::string_view separator, + cm::string_view initial) +{ + return cmJoinImpl(rng, separator, initial); +} diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index a5ecca7..01e3d94 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmStringAlgorithms_h -#define cmStringAlgorithms_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -20,6 +19,27 @@ /** String range type. */ using cmStringRange = cmRange<std::vector<std::string>::const_iterator>; +/** Check for non-empty string. */ +inline bool cmNonempty(const char* str) +{ + return str && *str; +} +inline bool cmNonempty(cm::string_view str) +{ + return !str.empty(); +} +inline bool cmNonempty(std::string const* str) +{ + return str && !str->empty(); +} + +/** Returns length of a literal string. */ +template <size_t N> +constexpr size_t cmStrLen(const char (&/*str*/)[N]) +{ + return N - 1; +} + /** Callable string comparison struct. */ struct cmStrCmp { @@ -67,6 +87,17 @@ std::string cmJoin(Range const& rng, cm::string_view separator) return os.str(); } +/** + * Faster overloads for std::string ranges. + * If @a initial is provided, it prepends the resulted string without + * @a separator between them. + */ +std::string cmJoin(std::vector<std::string> const& rng, + cm::string_view separator, cm::string_view initial = {}); + +std::string cmJoin(cmStringRange const& rng, cm::string_view separator, + cm::string_view initial = {}); + /** Extract tokens that are separated by any of the characters in @a sep. */ std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep); @@ -205,10 +236,11 @@ bool cmIsNOTFOUND(cm::string_view val); bool cmIsOn(cm::string_view val); inline bool cmIsOn(const char* val) { - if (!val) { - return false; - } - return cmIsOn(cm::string_view(val)); + return val && cmIsOn(cm::string_view(val)); +} +inline bool cmIsOn(std::string const* val) +{ + return val && cmIsOn(*val); } /** @@ -221,10 +253,11 @@ inline bool cmIsOn(const char* val) bool cmIsOff(cm::string_view val); inline bool cmIsOff(const char* val) { - if (!val) { - return true; - } - return cmIsOff(cm::string_view(val)); + return !val || cmIsOff(cm::string_view(val)); +} +inline bool cmIsOff(std::string const* val) +{ + return !val || cmIsOff(*val); } /** Returns true if string @a str starts with the character @a prefix. */ @@ -290,5 +323,3 @@ bool cmStrToLong(std::string const& str, long* value); * integer */ bool cmStrToULong(const char* str, unsigned long* value); bool cmStrToULong(std::string const& str, unsigned long* value); - -#endif diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index a7c21cc..4000a7d 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -11,6 +11,7 @@ #include <memory> #include <cm/iterator> +#include <cm/string_view> #include <cmext/string_view> #include "cmsys/RegularExpression.hxx" @@ -20,6 +21,7 @@ #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmStringReplaceHelper.h" @@ -533,15 +535,14 @@ bool HandleAppendCommand(std::vector<std::string> const& args, return true; } - const std::string& variable = args[1]; + auto const& variableName = args[1]; + + cm::string_view oldView{ status.GetMakefile().GetSafeDefinition( + variableName) }; + + auto const newValue = cmJoin(cmMakeRange(args).advance(2), {}, oldView); + status.GetMakefile().AddDefinition(variableName, newValue); - std::string value; - const char* oldValue = status.GetMakefile().GetDefinition(variable); - if (oldValue) { - value = oldValue; - } - value += cmJoin(cmMakeRange(args).advance(2), std::string()); - status.GetMakefile().AddDefinition(variable, value); return true; } @@ -561,9 +562,9 @@ bool HandlePrependCommand(std::vector<std::string> const& args, const std::string& variable = args[1]; std::string value = cmJoin(cmMakeRange(args).advance(2), std::string()); - const char* oldValue = status.GetMakefile().GetDefinition(variable); + cmProp oldValue = status.GetMakefile().GetDefinition(variable); if (oldValue) { - value += oldValue; + value += *oldValue; } status.GetMakefile().AddDefinition(variable, value); return true; diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index bd71ba2..5320ea5 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmStringCommand_h -#define cmStringCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -16,5 +15,3 @@ class cmExecutionStatus; */ bool cmStringCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmStringReplaceHelper.h b/Source/cmStringReplaceHelper.h index 74d481d..fd59d17 100644 --- a/Source/cmStringReplaceHelper.h +++ b/Source/cmStringReplaceHelper.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmStringReplaceHelper_h -#define cmStringReplaceHelper_h +#pragma once #include <string> #include <utility> @@ -64,5 +63,3 @@ private: std::vector<RegexReplacement> Replacements; cmMakefile* Makefile = nullptr; }; - -#endif diff --git a/Source/cmSubcommandTable.h b/Source/cmSubcommandTable.h index 7deaaed..80d8c6d 100644 --- a/Source/cmSubcommandTable.h +++ b/Source/cmSubcommandTable.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSubcommandTable_h -#define cmSubcommandTable_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -32,5 +31,3 @@ public: private: std::vector<Elem> Impl; }; - -#endif diff --git a/Source/cmSubdirCommand.h b/Source/cmSubdirCommand.h index 3254e84..6770874 100644 --- a/Source/cmSubdirCommand.h +++ b/Source/cmSubdirCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSubdirCommand_h -#define cmSubdirCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmSubdirCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmSubdirDependsCommand.h b/Source/cmSubdirDependsCommand.h index bf99bd1..133d702 100644 --- a/Source/cmSubdirDependsCommand.h +++ b/Source/cmSubdirDependsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSubdirDependsCommand_h -#define cmSubdirDependsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmSubdirDependsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 1e78d36..87176d6 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -749,33 +749,140 @@ std::string cmSystemTools::FileExistsInParentDirectories( } #ifdef _WIN32 -cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry() +namespace { + +/* Helper class to save and restore the specified file (or directory) + attribute bits. Instantiate this class as an automatic variable on the + stack. Its constructor saves a copy of the file attributes, and then its + destructor restores the original attribute settings. */ +class SaveRestoreFileAttributes { - static WindowsFileRetry retry = { 0, 0 }; - if (!retry.Count) { - unsigned int data[2] = { 0, 0 }; - HKEY const keys[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }; - wchar_t const* const values[2] = { L"FilesystemRetryCount", - L"FilesystemRetryDelay" }; - for (int k = 0; k < 2; ++k) { - HKEY hKey; - if (RegOpenKeyExW(keys[k], L"Software\\Kitware\\CMake\\Config", 0, - KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { - for (int v = 0; v < 2; ++v) { - DWORD dwData, dwType, dwSize = 4; - if (!data[v] && - RegQueryValueExW(hKey, values[v], 0, &dwType, (BYTE*)&dwData, - &dwSize) == ERROR_SUCCESS && - dwType == REG_DWORD && dwSize == 4) { - data[v] = static_cast<unsigned int>(dwData); - } +public: + SaveRestoreFileAttributes(std::wstring const& path, + uint32_t file_attrs_to_set); + ~SaveRestoreFileAttributes(); + + SaveRestoreFileAttributes(SaveRestoreFileAttributes const&) = delete; + SaveRestoreFileAttributes& operator=(SaveRestoreFileAttributes const&) = + delete; + + void SetPath(std::wstring const& path) { path_ = path; } + +private: + std::wstring path_; + uint32_t original_attr_bits_; +}; + +SaveRestoreFileAttributes::SaveRestoreFileAttributes( + std::wstring const& path, uint32_t file_attrs_to_set) + : path_(path) + , original_attr_bits_(0) +{ + // Set the specified attributes for the source file/directory. + original_attr_bits_ = GetFileAttributesW(path_.c_str()); + if ((INVALID_FILE_ATTRIBUTES != original_attr_bits_) && + ((file_attrs_to_set & original_attr_bits_) != file_attrs_to_set)) { + SetFileAttributesW(path_.c_str(), original_attr_bits_ | file_attrs_to_set); + } +} + +// We set attribute bits. Now we need to restore their original state. +SaveRestoreFileAttributes::~SaveRestoreFileAttributes() +{ + DWORD last_error = GetLastError(); + // Verify or restore the original attributes. + const DWORD source_attr_bits = GetFileAttributesW(path_.c_str()); + if (INVALID_FILE_ATTRIBUTES != source_attr_bits) { + if (original_attr_bits_ != source_attr_bits) { + // The file still exists, and its attributes aren't our saved values. + // Time to restore them. + SetFileAttributesW(path_.c_str(), original_attr_bits_); + } + } + SetLastError(last_error); +} + +struct WindowsFileRetryInit +{ + cmSystemTools::WindowsFileRetry Retry; + bool Explicit; +}; + +WindowsFileRetryInit InitWindowsFileRetry(wchar_t const* const values[2], + unsigned int const defaults[2]) +{ + unsigned int data[2] = { 0, 0 }; + HKEY const keys[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }; + for (int k = 0; k < 2; ++k) { + HKEY hKey; + if (RegOpenKeyExW(keys[k], L"Software\\Kitware\\CMake\\Config", 0, + KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { + for (int v = 0; v < 2; ++v) { + DWORD dwData, dwType, dwSize = 4; + if (!data[v] && + RegQueryValueExW(hKey, values[v], 0, &dwType, (BYTE*)&dwData, + &dwSize) == ERROR_SUCCESS && + dwType == REG_DWORD && dwSize == 4) { + data[v] = static_cast<unsigned int>(dwData); } - RegCloseKey(hKey); } + RegCloseKey(hKey); } - retry.Count = data[0] ? data[0] : 5; - retry.Delay = data[1] ? data[1] : 500; } + WindowsFileRetryInit init; + init.Explicit = data[0] || data[1]; + init.Retry.Count = data[0] ? data[0] : defaults[0]; + init.Retry.Delay = data[1] ? data[1] : defaults[1]; + return init; +} + +WindowsFileRetryInit InitWindowsFileRetry() +{ + static wchar_t const* const values[2] = { L"FilesystemRetryCount", + L"FilesystemRetryDelay" }; + static unsigned int const defaults[2] = { 5, 500 }; + return InitWindowsFileRetry(values, defaults); +} + +WindowsFileRetryInit InitWindowsDirectoryRetry() +{ + static wchar_t const* const values[2] = { L"FilesystemDirectoryRetryCount", + L"FilesystemDirectoryRetryDelay" }; + static unsigned int const defaults[2] = { 120, 500 }; + WindowsFileRetryInit dirInit = InitWindowsFileRetry(values, defaults); + if (dirInit.Explicit) { + return dirInit; + } + WindowsFileRetryInit fileInit = InitWindowsFileRetry(); + if (fileInit.Explicit) { + return fileInit; + } + return dirInit; +} + +cmSystemTools::WindowsFileRetry GetWindowsRetry(std::wstring const& path) +{ + // If we are performing a directory operation, then try and get the + // appropriate timing info. + DWORD const attrs = GetFileAttributesW(path.c_str()); + if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) { + return cmSystemTools::GetWindowsDirectoryRetry(); + } + return cmSystemTools::GetWindowsFileRetry(); +} + +} // end of anonymous namespace + +cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry() +{ + static WindowsFileRetry retry = InitWindowsFileRetry().Retry; + return retry; +} + +cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsDirectoryRetry() +{ + static cmSystemTools::WindowsFileRetry retry = + InitWindowsDirectoryRetry().Retry; return retry; } #endif @@ -836,6 +943,21 @@ void cmSystemTools::InitializeLibUV() #endif } +#ifdef _WIN32 +namespace { +bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname) +{ + // Not only ignore any previous error, but clear any memory of it. + SetLastError(0); + + // Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file. + // Use MOVEFILE_WRITE_THROUGH to flush the change to disk before returning. + return MoveFileExW(oldname.c_str(), newname.c_str(), + MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH); +} +} +#endif + bool cmSystemTools::RenameFile(const std::string& oldname, const std::string& newname) { @@ -843,35 +965,63 @@ bool cmSystemTools::RenameFile(const std::string& oldname, # ifndef INVALID_FILE_ATTRIBUTES # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) # endif + std::wstring const oldname_wstr = + SystemTools::ConvertToWindowsExtendedPath(oldname); + std::wstring const newname_wstr = + SystemTools::ConvertToWindowsExtendedPath(newname); + /* Windows MoveFileEx may not replace read-only or in-use files. If it fails then remove the read-only attribute from any existing destination. Try multiple times since we may be racing against another process creating/opening the destination file just before our MoveFileEx. */ - WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry(); - while ( - !MoveFileExW(SystemTools::ConvertToWindowsExtendedPath(oldname).c_str(), - SystemTools::ConvertToWindowsExtendedPath(newname).c_str(), - MOVEFILE_REPLACE_EXISTING) && - --retry.Count) { - DWORD last_error = GetLastError(); + WindowsFileRetry retry = GetWindowsRetry(oldname_wstr); + + // Use RAII to set the attribute bit blocking Microsoft Search Indexing, + // and restore the previous value upon return. + SaveRestoreFileAttributes save_restore_file_attributes( + oldname_wstr, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); + + DWORD move_last_error = 0; + while (!cmMoveFile(oldname_wstr, newname_wstr) && --retry.Count) { + move_last_error = GetLastError(); + + // There was no error ==> the operation is not yet complete. + if (move_last_error == NO_ERROR) { + break; + } + // Try again only if failure was due to access/sharing permissions. - if (last_error != ERROR_ACCESS_DENIED && - last_error != ERROR_SHARING_VIOLATION) { + // Most often ERROR_ACCESS_DENIED (a.k.a. I/O error) for a directory, and + // ERROR_SHARING_VIOLATION for a file, are caused by one of the following: + // 1) Anti-Virus Software + // 2) Windows Search Indexer + // 3) Windows Explorer has an associated directory already opened. + if (move_last_error != ERROR_ACCESS_DENIED && + move_last_error != ERROR_SHARING_VIOLATION) { return false; } - DWORD attrs = GetFileAttributesW( - SystemTools::ConvertToWindowsExtendedPath(newname).c_str()); + + DWORD const attrs = GetFileAttributesW(newname_wstr.c_str()); if ((attrs != INVALID_FILE_ATTRIBUTES) && - (attrs & FILE_ATTRIBUTE_READONLY)) { + (attrs & FILE_ATTRIBUTE_READONLY) && + // FILE_ATTRIBUTE_READONLY is not honored on directories. + !(attrs & FILE_ATTRIBUTE_DIRECTORY)) { // Remove the read-only attribute from the destination file. - SetFileAttributesW( - SystemTools::ConvertToWindowsExtendedPath(newname).c_str(), - attrs & ~FILE_ATTRIBUTE_READONLY); + SetFileAttributesW(newname_wstr.c_str(), + attrs & ~FILE_ATTRIBUTE_READONLY); } else { // The file may be temporarily in use so wait a bit. cmSystemTools::Delay(retry.Delay); } } + + // If we were successful, then there was no error. + if (retry.Count > 0) { + move_last_error = 0; + // Restore the attributes on the new name. + save_restore_file_attributes.SetPath(newname_wstr); + } + SetLastError(move_last_error); return retry.Count > 0; #else /* On UNIX we have an OS-provided call to do this atomically. */ @@ -1213,7 +1363,7 @@ bool cmSystemTools::UnsetEnv(const char* value) { # if !defined(HAVE_UNSETENV) std::string var = cmStrCat(value, '='); - return cmSystemTools::PutEnv(var.c_str()); + return cmSystemTools::PutEnv(var); # else unsetenv(value); return true; diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index b886c58..1362af8 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmSystemTools_h -#define cmSystemTools_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -434,6 +433,7 @@ public: unsigned int Delay; }; static WindowsFileRetry GetWindowsFileRetry(); + static WindowsFileRetry GetWindowsDirectoryRetry(); #endif /** Get the real path for a given path, removing all symlinks. @@ -464,5 +464,3 @@ private: static bool s_FatalErrorOccured; static bool s_DisableRunCommandOutput; }; - -#endif diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 36e1ad5..ececee7 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -7,6 +7,7 @@ #include <cstring> #include <initializer_list> #include <iterator> +#include <map> #include <set> #include <sstream> #include <unordered_set> @@ -185,6 +186,7 @@ public: std::vector<cmInstallTargetGenerator*> InstallGenerators; std::set<std::string> SystemIncludeDirectories; cmTarget::LinkLibraryVectorType OriginalLinkLibraries; + std::map<std::string, BTs<std::string>> LanguageStandardProperties; std::vector<std::string> IncludeDirectoriesEntries; std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces; std::vector<std::string> CompileOptionsEntries; @@ -214,6 +216,15 @@ public: std::string ProcessSourceItemCMP0049(const std::string& s); }; +namespace { +#define SETUP_COMMON_LANGUAGE_PROPERTIES(lang) \ + initProp(#lang "_COMPILER_LAUNCHER"); \ + initProp(#lang "_STANDARD"); \ + initProp(#lang "_STANDARD_REQUIRED"); \ + initProp(#lang "_EXTENSIONS"); \ + initProp(#lang "_VISIBILITY_PRESET") +} + cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, Visibility vis, cmMakefile* mf, PerConfig perConfig) : impl(cm::make_unique<cmTargetInternals>()) @@ -254,24 +265,30 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, auto initProp = [this, mf, &defKey](const std::string& property) { // Replace everything after "CMAKE_" defKey.replace(defKey.begin() + 6, defKey.end(), property); - if (const char* value = mf->GetDefinition(defKey)) { - this->SetProperty(property, value); + if (cmProp value = mf->GetDefinition(defKey)) { + this->SetProperty(property, *value); } }; auto initPropValue = [this, mf, &defKey](const std::string& property, const char* default_value) { // Replace everything after "CMAKE_" defKey.replace(defKey.begin() + 6, defKey.end(), property); - if (const char* value = mf->GetDefinition(defKey)) { - this->SetProperty(property, value); + if (cmProp value = mf->GetDefinition(defKey)) { + this->SetProperty(property, *value); } else if (default_value) { this->SetProperty(property, default_value); } }; // Setup default property values. - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && - this->GetType() != cmStateEnums::UTILITY) { + if (this->CanCompileSources()) { + + SETUP_COMMON_LANGUAGE_PROPERTIES(C); + SETUP_COMMON_LANGUAGE_PROPERTIES(OBJC); + SETUP_COMMON_LANGUAGE_PROPERTIES(CXX); + SETUP_COMMON_LANGUAGE_PROPERTIES(OBJCXX); + SETUP_COMMON_LANGUAGE_PROPERTIES(CUDA); + initProp("ANDROID_API"); initProp("ANDROID_API_MIN"); initProp("ANDROID_ARCH"); @@ -308,6 +325,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("Fortran_MODULE_DIRECTORY"); initProp("Fortran_COMPILER_LAUNCHER"); initProp("Fortran_PREPROCESS"); + initProp("Fortran_VISIBILITY_PRESET"); initProp("GNUtoMS"); initProp("OSX_ARCHITECTURES"); initProp("IOS_INSTALL_COMBINED"); @@ -333,38 +351,25 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("NO_SYSTEM_FROM_IMPORTED"); initProp("BUILD_WITH_INSTALL_NAME_DIR"); initProp("C_CLANG_TIDY"); - initProp("C_COMPILER_LAUNCHER"); initProp("C_CPPLINT"); initProp("C_CPPCHECK"); initProp("C_INCLUDE_WHAT_YOU_USE"); initProp("LINK_WHAT_YOU_USE"); - initProp("C_STANDARD"); - initProp("C_STANDARD_REQUIRED"); - initProp("C_EXTENSIONS"); - initProp("OBJC_COMPILER_LAUNCHER"); - initProp("OBJC_STANDARD"); - initProp("OBJC_STANDARD_REQUIRED"); - initProp("OBJC_EXTENSIONS"); initProp("CXX_CLANG_TIDY"); - initProp("CXX_COMPILER_LAUNCHER"); initProp("CXX_CPPLINT"); initProp("CXX_CPPCHECK"); initProp("CXX_INCLUDE_WHAT_YOU_USE"); - initProp("CXX_STANDARD"); - initProp("CXX_STANDARD_REQUIRED"); - initProp("CXX_EXTENSIONS"); - initProp("OBJCXX_COMPILER_LAUNCHER"); - initProp("OBJCXX_STANDARD"); - initProp("OBJCXX_STANDARD_REQUIRED"); - initProp("OBJCXX_EXTENSIONS"); - initProp("CUDA_STANDARD"); - initProp("CUDA_STANDARD_REQUIRED"); - initProp("CUDA_EXTENSIONS"); - initProp("CUDA_COMPILER_LAUNCHER"); initProp("CUDA_SEPARABLE_COMPILATION"); initProp("CUDA_RESOLVE_DEVICE_SYMBOLS"); initProp("CUDA_RUNTIME_LIBRARY"); initProp("CUDA_ARCHITECTURES"); + initProp("VISIBILITY_INLINES_HIDDEN"); + initProp("JOB_POOL_COMPILE"); + initProp("JOB_POOL_LINK"); + initProp("JOB_POOL_PRECOMPILE_HEADER"); + initProp("ISPC_COMPILER_LAUNCHER"); + initProp("ISPC_HEADER_DIRECTORY"); + initProp("ISPC_INSTRUCTION_SETS"); initProp("LINK_SEARCH_START_STATIC"); initProp("LINK_SEARCH_END_STATIC"); initProp("Swift_LANGUAGE_VERSION"); @@ -372,9 +377,11 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("VS_JUST_MY_CODE_DEBUGGING"); initProp("DISABLE_PRECOMPILE_HEADERS"); initProp("UNITY_BUILD"); + initProp("OPTIMIZE_DEPENDENCIES"); initPropValue("UNITY_BUILD_BATCH_SIZE", "8"); initPropValue("UNITY_BUILD_MODE", "BATCH"); initPropValue("PCH_WARN_INVALID", "ON"); + #ifdef __APPLE__ if (this->GetGlobalGenerator()->IsXcode()) { initProp("XCODE_SCHEME_ADDRESS_SANITIZER"); @@ -395,20 +402,20 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE"); initProp("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS"); initProp("XCODE_SCHEME_ENVIRONMENT"); + initPropValue("XCODE_LINK_BUILD_PHASE_MODE", "NONE"); } #endif } - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - initProp("FOLDER"); + initProp("FOLDER"); - if (this->GetGlobalGenerator()->IsXcode()) { - initProp("XCODE_GENERATE_SCHEME"); - } + if (this->GetGlobalGenerator()->IsXcode()) { + initProp("XCODE_GENERATE_SCHEME"); } // Setup per-configuration property default values. - if (this->GetType() != cmStateEnums::UTILITY) { + if (this->GetType() != cmStateEnums::UTILITY && + this->GetType() != cmStateEnums::GLOBAL_TARGET) { static const auto configProps = { /* clang-format needs this comment to break after the opening brace */ "ARCHIVE_OUTPUT_DIRECTORY_", "LIBRARY_OUTPUT_DIRECTORY_", @@ -417,8 +424,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, "INTERPROCEDURAL_OPTIMIZATION_" }; // Collect the set of configuration types. - std::vector<std::string> configNames; - mf->GetConfigurations(configNames); + std::vector<std::string> configNames = + mf->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); for (std::string const& configName : configNames) { std::string configUpper = cmSystemTools::UpperCase(configName); for (auto const& prop : configProps) { @@ -485,16 +492,6 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, impl->Makefile->GetLinkDirectoriesBacktraces()); } - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && - this->GetType() != cmStateEnums::UTILITY) { - initProp("C_VISIBILITY_PRESET"); - initProp("CXX_VISIBILITY_PRESET"); - initProp("OBJC_VISIBILITY_PRESET"); - initProp("OBJCXX_VISIBILITY_PRESET"); - initProp("CUDA_VISIBILITY_PRESET"); - initProp("VISIBILITY_INLINES_HIDDEN"); - } - if (impl->TargetType == cmStateEnums::EXECUTABLE) { initProp("ANDROID_GUI"); initProp("CROSSCOMPILING_EMULATOR"); @@ -503,6 +500,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, if (impl->TargetType == cmStateEnums::SHARED_LIBRARY || impl->TargetType == cmStateEnums::MODULE_LIBRARY) { this->SetProperty("POSITION_INDEPENDENT_CODE", "True"); + } else if (this->CanCompileSources()) { + initProp("POSITION_INDEPENDENT_CODE"); } if (impl->TargetType == cmStateEnums::SHARED_LIBRARY || impl->TargetType == cmStateEnums::EXECUTABLE) { @@ -510,11 +509,6 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("WINDOWS_EXPORT_ALL_SYMBOLS"); } - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && - this->GetType() != cmStateEnums::UTILITY) { - initProp("POSITION_INDEPENDENT_CODE"); - } - // Record current policies for later use. impl->Makefile->RecordPolicies(impl->PolicyMap); @@ -526,36 +520,26 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, impl->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW); } - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && - this->GetType() != cmStateEnums::UTILITY) { - initProp("JOB_POOL_COMPILE"); - initProp("JOB_POOL_LINK"); - initProp("JOB_POOL_PRECOMPILE_HEADER"); - } - if (impl->TargetType <= cmStateEnums::GLOBAL_TARGET) { initProp("DOTNET_TARGET_FRAMEWORK"); initProp("DOTNET_TARGET_FRAMEWORK_VERSION"); } - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - - // check for "CMAKE_VS_GLOBALS" variable and set up target properties - // if any - const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS"); - if (globals) { - const std::string genName = mf->GetGlobalGenerator()->GetName(); - if (cmHasLiteralPrefix(genName, "Visual Studio")) { - std::vector<std::string> props = cmExpandedList(globals); - const std::string vsGlobal = "VS_GLOBAL_"; - for (const std::string& i : props) { - // split NAME=VALUE - const std::string::size_type assignment = i.find('='); - if (assignment != std::string::npos) { - const std::string propName = vsGlobal + i.substr(0, assignment); - const std::string propValue = i.substr(assignment + 1); - initPropValue(propName, propValue.c_str()); - } + // check for "CMAKE_VS_GLOBALS" variable and set up target properties + // if any + cmProp globals = mf->GetDefinition("CMAKE_VS_GLOBALS"); + if (globals) { + const std::string genName = mf->GetGlobalGenerator()->GetName(); + if (cmHasLiteralPrefix(genName, "Visual Studio")) { + std::vector<std::string> props = cmExpandedList(*globals); + const std::string vsGlobal = "VS_GLOBAL_"; + for (const std::string& i : props) { + // split NAME=VALUE + const std::string::size_type assignment = i.find('='); + if (assignment != std::string::npos) { + const std::string propName = vsGlobal + i.substr(0, assignment); + const std::string propValue = i.substr(assignment + 1); + initPropValue(propName, propValue.c_str()); } } } @@ -598,6 +582,40 @@ cmGlobalGenerator* cmTarget::GetGlobalGenerator() const return impl->Makefile->GetGlobalGenerator(); } +BTs<std::string> const* cmTarget::GetLanguageStandardProperty( + const std::string& propertyName) const +{ + auto entry = impl->LanguageStandardProperties.find(propertyName); + if (entry != impl->LanguageStandardProperties.end()) { + return &entry->second; + } + + return nullptr; +} + +void cmTarget::SetLanguageStandardProperty(std::string const& lang, + std::string const& value, + const std::string& feature) +{ + cmListFileBacktrace featureBacktrace; + for (size_t i = 0; i < impl->CompileFeaturesEntries.size(); i++) { + if (impl->CompileFeaturesEntries[i] == feature) { + if (i < impl->CompileFeaturesBacktraces.size()) { + featureBacktrace = impl->CompileFeaturesBacktraces[i]; + } + break; + } + } + + BTs<std::string>& languageStandardProperty = + impl->LanguageStandardProperties[cmStrCat(lang, "_STANDARD")]; + if (languageStandardProperty.Value != value) { + languageStandardProperty.Value = value; + languageStandardProperty.Backtraces.clear(); + } + languageStandardProperty.Backtraces.emplace_back(featureBacktrace); +} + void cmTarget::AddUtility(std::string const& name, bool cross, cmMakefile* mf) { impl->Utilities.insert(BT<std::pair<std::string, bool>>( @@ -636,6 +654,12 @@ bool cmTarget::IsAppBundleOnApple() const this->GetPropertyAsBool("MACOSX_BUNDLE")); } +bool cmTarget::IsAndroidGuiExecutable() const +{ + return (this->GetType() == cmStateEnums::EXECUTABLE && impl->IsAndroid && + this->GetPropertyAsBool("ANDROID_GUI")); +} + std::vector<cmCustomCommand> const& cmTarget::GetPreBuildCommands() const { return impl->PreBuildCommands; @@ -996,9 +1020,9 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) { std::string targetEntry = cmStrCat(impl->Name, "_LIB_DEPENDS"); std::string dependencies; - const char* old_val = mf.GetDefinition(targetEntry); + cmProp old_val = mf.GetDefinition(targetEntry); if (old_val) { - dependencies += old_val; + dependencies += *old_val; } switch (llt) { case GENERAL_LibraryType: @@ -1121,12 +1145,12 @@ cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const void cmTarget::SetProperty(const std::string& prop, const char* value) { - if (!cmTargetPropertyComputer::PassesWhitelist( - this->GetType(), prop, impl->Makefile->GetMessenger(), - impl->Makefile->GetBacktrace())) { - return; - } #define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP + MAKE_STATIC_PROP(C_STANDARD); + MAKE_STATIC_PROP(CXX_STANDARD); + MAKE_STATIC_PROP(CUDA_STANDARD); + MAKE_STATIC_PROP(OBJC_STANDARD); + MAKE_STATIC_PROP(OBJCXX_STANDARD); MAKE_STATIC_PROP(COMPILE_DEFINITIONS); MAKE_STATIC_PROP(COMPILE_FEATURES); MAKE_STATIC_PROP(COMPILE_OPTIONS); @@ -1308,8 +1332,17 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmStrCat(reusedFrom, ".dir/")); cmProp tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME"); - this->SetProperty("COMPILE_PDB_NAME", tmp ? tmp->c_str() : nullptr); + this->SetProperty("COMPILE_PDB_NAME", cmToCStr(tmp)); this->AddUtility(reusedFrom, false, impl->Makefile); + } else if (prop == propC_STANDARD || prop == propCXX_STANDARD || + prop == propCUDA_STANDARD || prop == propOBJC_STANDARD || + prop == propOBJCXX_STANDARD) { + if (value) { + impl->LanguageStandardProperties[prop] = + BTs<std::string>(value, impl->Makefile->GetBacktrace()); + } else { + impl->LanguageStandardProperties.erase(prop); + } } else { impl->Properties.SetProperty(prop, value); } @@ -1318,11 +1351,6 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) void cmTarget::AppendProperty(const std::string& prop, const std::string& value, bool asString) { - if (!cmTargetPropertyComputer::PassesWhitelist( - this->GetType(), prop, impl->Makefile->GetMessenger(), - impl->Makefile->GetBacktrace())) { - return; - } if (prop == "NAME") { impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, "NAME property is read-only\n"); @@ -1413,6 +1441,11 @@ void cmTarget::AppendProperty(const std::string& prop, } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) { impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, prop + " property may not be APPENDed."); + } else if (prop == "C_STANDARD" || prop == "CXX_STANDARD" || + prop == "CUDA_STANDARD" || prop == "OBJC_STANDARD" || + prop == "OBJCXX_STANDARD") { + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + prop + " property may not be appended."); } else { impl->Properties.AppendProperty(prop, value, asString); } @@ -1626,6 +1659,11 @@ cmProp cmTarget::GetComputedProperty(const std::string& prop, cmProp cmTarget::GetProperty(const std::string& prop) const { #define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP + MAKE_STATIC_PROP(C_STANDARD); + MAKE_STATIC_PROP(CXX_STANDARD); + MAKE_STATIC_PROP(CUDA_STANDARD); + MAKE_STATIC_PROP(OBJC_STANDARD); + MAKE_STATIC_PROP(OBJCXX_STANDARD); MAKE_STATIC_PROP(LINK_LIBRARIES); MAKE_STATIC_PROP(TYPE); MAKE_STATIC_PROP(INCLUDE_DIRECTORIES); @@ -1646,6 +1684,11 @@ cmProp cmTarget::GetProperty(const std::string& prop) const MAKE_STATIC_PROP(TRUE); #undef MAKE_STATIC_PROP static std::unordered_set<std::string> const specialProps{ + propC_STANDARD, + propCXX_STANDARD, + propCUDA_STANDARD, + propOBJC_STANDARD, + propOBJCXX_STANDARD, propLINK_LIBRARIES, propTYPE, propINCLUDE_DIRECTORIES, @@ -1664,6 +1707,15 @@ cmProp cmTarget::GetProperty(const std::string& prop) const propSOURCES }; if (specialProps.count(prop)) { + if (prop == propC_STANDARD || prop == propCXX_STANDARD || + prop == propCUDA_STANDARD || prop == propOBJC_STANDARD || + prop == propOBJCXX_STANDARD) { + auto propertyIter = impl->LanguageStandardProperties.find(prop); + if (propertyIter == impl->LanguageStandardProperties.end()) { + return nullptr; + } + return &(propertyIter->second.Value); + } if (prop == propLINK_LIBRARIES) { if (impl->LinkImplementationPropertyEntries.empty()) { return nullptr; @@ -1804,8 +1856,7 @@ std::string const& cmTarget::GetSafeProperty(std::string const& prop) const bool cmTarget::GetPropertyAsBool(const std::string& prop) const { - cmProp p = this->GetProperty(prop); - return p && cmIsOn(*p); + return cmIsOn(this->GetProperty(prop)); } cmPropertyMap const& cmTarget::GetProperties() const @@ -1838,6 +1889,27 @@ bool cmTarget::IsPerConfig() const return impl->PerConfig; } +bool cmTarget::CanCompileSources() const +{ + if (this->IsImported()) { + return false; + } + switch (this->GetType()) { + case cmStateEnums::EXECUTABLE: + case cmStateEnums::STATIC_LIBRARY: + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::OBJECT_LIBRARY: + return true; + case cmStateEnums::UTILITY: + case cmStateEnums::INTERFACE_LIBRARY: + case cmStateEnums::GLOBAL_TARGET: + case cmStateEnums::UNKNOWN_LIBRARY: + break; + } + return false; +} + const char* cmTarget::GetSuffixVariableInternal( cmStateEnums::ArtifactType artifact) const { @@ -1865,7 +1937,7 @@ const char* cmTarget::GetSuffixVariableInternal( case cmStateEnums::RuntimeBinaryArtifact: // Android GUI application packages store the native // binary as a shared library. - return (impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI") + return (this->IsAndroidGuiExecutable() ? "CMAKE_SHARED_LIBRARY_SUFFIX" : "CMAKE_EXECUTABLE_SUFFIX"); case cmStateEnums::ImportLibraryArtifact: @@ -1906,7 +1978,7 @@ const char* cmTarget::GetPrefixVariableInternal( case cmStateEnums::RuntimeBinaryArtifact: // Android GUI application packages store the native // binary as a shared library. - return (impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI") + return (this->IsAndroidGuiExecutable() ? "CMAKE_SHARED_LIBRARY_PREFIX" : ""); case cmStateEnums::ImportLibraryArtifact: @@ -1972,6 +2044,37 @@ std::string cmTarget::ImportedGetFullPath( } if (result.empty()) { + auto message = [&]() -> std::string { + std::string unset; + std::string configuration; + + if (artifact == cmStateEnums::RuntimeBinaryArtifact) { + unset = "IMPORTED_LOCATION"; + } else if (artifact == cmStateEnums::ImportLibraryArtifact) { + unset = "IMPORTED_IMPLIB"; + } + + if (!config.empty()) { + configuration = cmStrCat(" configuration \"", config, "\""); + } + + return cmStrCat(unset, " not set for imported target \"", + this->GetName(), "\"", configuration, "."); + }; + + switch (this->GetPolicyStatus(cmPolicies::CMP0111)) { + case cmPolicies::WARN: + impl->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(cmPolicies::CMP0111) + "\n" + + message()); + CM_FALLTHROUGH; + case cmPolicies::OLD: + break; + default: + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, message()); + } + result = cmStrCat(this->GetName(), "-NOTFOUND"); } return result; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index f0ddb68..d8f66bc 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTarget_h -#define cmTarget_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -196,6 +195,7 @@ public: bool IsImported() const; bool IsImportedGloballyVisible() const; bool IsPerConfig() const; + bool CanCompileSources() const; bool GetMappedConfig(std::string const& desired_config, cmProp& loc, cmProp& imp, std::string& suffix) const; @@ -209,6 +209,9 @@ public: //! Return whether this target is an executable Bundle on Apple. bool IsAppBundleOnApple() const; + //! Return whether this target is a GUI executable on Android. + bool IsAndroidGuiExecutable() const; + //! Get a backtrace from the creation of the target. cmListFileBacktrace const& GetBacktrace() const; @@ -233,6 +236,13 @@ public: void AddSystemIncludeDirectories(std::set<std::string> const& incs); std::set<std::string> const& GetSystemIncludeDirectories() const; + BTs<std::string> const* GetLanguageStandardProperty( + const std::string& propertyName) const; + + void SetLanguageStandardProperty(std::string const& lang, + std::string const& value, + const std::string& feature); + cmStringRange GetIncludeDirectoriesEntries() const; cmBacktraceRange GetIncludeDirectoriesBacktraces() const; @@ -280,5 +290,3 @@ private: private: std::unique_ptr<cmTargetInternals> impl; }; - -#endif diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h index 05ff092..54a20fd 100644 --- a/Source/cmTargetCompileDefinitionsCommand.h +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetCompileDefinitionsCommand_h -#define cmTargetCompileDefinitionsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmTargetCompileDefinitionsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx index 06be4f0..aa1abdd 100644 --- a/Source/cmTargetCompileFeaturesCommand.cxx +++ b/Source/cmTargetCompileFeaturesCommand.cxx @@ -4,6 +4,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStandardLevelResolver.h" #include "cmStringAlgorithms.h" #include "cmTargetPropCommandBase.h" @@ -29,9 +30,10 @@ private: const std::vector<std::string>& content, bool /*prepend*/, bool /*system*/) override { + cmStandardLevelResolver standardResolver(this->Makefile); for (std::string const& it : content) { std::string error; - if (!this->Makefile->AddRequiredTargetFeature(tgt, it, &error)) { + if (!standardResolver.AddRequiredTargetFeature(tgt, it, &error)) { this->SetError(error); return false; // Not (successfully) handled. } diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h index db0c04b..9dbf486 100644 --- a/Source/cmTargetCompileFeaturesCommand.h +++ b/Source/cmTargetCompileFeaturesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetCompileFeaturesCommand_h -#define cmTargetCompileFeaturesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmTargetCompileFeaturesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h index 3ab1a89..1f7c684 100644 --- a/Source/cmTargetCompileOptionsCommand.h +++ b/Source/cmTargetCompileOptionsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetCompileOptionsCommand_h -#define cmTargetCompileOptionsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmTargetCompileOptionsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h index 5452cc7..36702bd 100644 --- a/Source/cmTargetDepend.h +++ b/Source/cmTargetDepend.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetDepend_h -#define cmTargetDepend_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -60,5 +59,3 @@ public: class cmTargetDependSet : public std::set<cmTargetDepend> { }; - -#endif diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h index 9304eab..cb4d8da 100644 --- a/Source/cmTargetExport.h +++ b/Source/cmTargetExport.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetExport_h -#define cmTargetExport_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -33,5 +32,3 @@ public: std::string InterfaceIncludeDirectories; ///@} }; - -#endif diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h index 9958f41..223da7d 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.h +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetIncludeDirectoriesCommand_h -#define cmTargetIncludeDirectoriesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmTargetIncludeDirectoriesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmTargetLinkDirectoriesCommand.h b/Source/cmTargetLinkDirectoriesCommand.h index 3724d6c..e305709 100644 --- a/Source/cmTargetLinkDirectoriesCommand.h +++ b/Source/cmTargetLinkDirectoriesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetLinkDirectoriesCommand_h -#define cmTargetLinkDirectoriesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmTargetLinkDirectoriesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index df751da..7db2c46 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetLinkLibrariesCommand.h" -#include <cstring> #include <memory> #include <sstream> #include <unordered_set> @@ -14,6 +13,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -277,12 +277,12 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, // with old versions of CMake and new) llt = GENERAL_LibraryType; std::string linkType = cmStrCat(args[0], "_LINK_TYPE"); - const char* linkTypeString = mf.GetDefinition(linkType); + cmProp linkTypeString = mf.GetDefinition(linkType); if (linkTypeString) { - if (strcmp(linkTypeString, "debug") == 0) { + if (*linkTypeString == "debug") { llt = DEBUG_LibraryType; } - if (strcmp(linkTypeString, "optimized") == 0) { + if (*linkTypeString == "optimized") { llt = OPTIMIZED_LibraryType; } } diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index 4b2deab..bc76f3e 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetLinkLibrariesCommand_h -#define cmTargetLinkLibrariesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmTargetLinkLibraryType.h b/Source/cmTargetLinkLibraryType.h index 192c6da..16ac41a 100644 --- a/Source/cmTargetLinkLibraryType.h +++ b/Source/cmTargetLinkLibraryType.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetLinkLibraryType_h -#define cmTargetLinkLibraryType_h +#pragma once enum cmTargetLinkLibraryType { @@ -9,5 +8,3 @@ enum cmTargetLinkLibraryType DEBUG_LibraryType, OPTIMIZED_LibraryType }; - -#endif diff --git a/Source/cmTargetLinkOptionsCommand.h b/Source/cmTargetLinkOptionsCommand.h index 13fb40c..fbe7d49 100644 --- a/Source/cmTargetLinkOptionsCommand.h +++ b/Source/cmTargetLinkOptionsCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetLinkOptionsCommand_h -#define cmTargetLinkOptionsCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmTargetLinkOptionsCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmTargetPrecompileHeadersCommand.h b/Source/cmTargetPrecompileHeadersCommand.h index 8b0ac97..dd08a6d 100644 --- a/Source/cmTargetPrecompileHeadersCommand.h +++ b/Source/cmTargetPrecompileHeadersCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetPrecompileHeadersCommand_h -#define cmTargetPrecompileHeadersCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmTargetPrecompileHeadersCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index e714720..9e30136 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -123,7 +123,7 @@ bool cmTargetPropCommandBase::ProcessContentArgs( } if (!content.empty()) { if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && - scope != "INTERFACE") { + scope != "INTERFACE" && this->Property != "SOURCES") { this->SetError("may only set INTERFACE properties on INTERFACE targets"); return false; } diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index 601ad01..50ac1aa 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetPropCommandBase_h -#define cmTargetPropCommandBase_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -58,5 +57,3 @@ private: cmExecutionStatus& Status; }; - -#endif diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index f37995c..b9c9365 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -3,15 +3,12 @@ #include "cmTargetPropertyComputer.h" -#include <cctype> #include <sstream> -#include <unordered_set> #include "cmMessageType.h" #include "cmMessenger.h" #include "cmPolicies.h" #include "cmStateSnapshot.h" -#include "cmStringAlgorithms.h" bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( std::string const& tgtName, cmMessenger* messenger, @@ -44,69 +41,3 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( return messageType != MessageType::FATAL_ERROR; } - -bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( - const std::string& prop) -{ - if (cmHasLiteralPrefix(prop, "INTERFACE_")) { - return true; - } - if (cmHasLiteralPrefix(prop, "_")) { - return true; - } - if (std::islower(prop[0])) { - return true; - } - static std::unordered_set<std::string> const builtIns{ - "COMPATIBLE_INTERFACE_BOOL", - "COMPATIBLE_INTERFACE_NUMBER_MAX", - "COMPATIBLE_INTERFACE_NUMBER_MIN", - "COMPATIBLE_INTERFACE_STRING", - "DEPRECATION", - "EXPORT_NAME", - "EXPORT_PROPERTIES", - "IMPORTED", - "IMPORTED_GLOBAL", - "MANUALLY_ADDED_DEPENDENCIES", - "NAME", - "PRIVATE_HEADER", - "PUBLIC_HEADER", - "TYPE" - }; - - if (builtIns.count(prop)) { - return true; - } - - if (prop == "IMPORTED_CONFIGURATIONS" || prop == "IMPORTED_LIBNAME" || - cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME_") || - cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_")) { - return true; - } - - // This property should not be allowed but was incorrectly added in - // CMake 3.8. We can't remove it from the whitelist without breaking - // projects that try to set it. One day we could warn about this, but - // for now silently accept it. - if (prop == "NO_SYSTEM_FROM_IMPORTED") { - return true; - } - - return false; -} - -bool cmTargetPropertyComputer::PassesWhitelist( - cmStateEnums::TargetType tgtType, std::string const& prop, - cmMessenger* messenger, cmListFileBacktrace const& context) -{ - if (tgtType == cmStateEnums::INTERFACE_LIBRARY && - !WhiteListedInterfaceProperty(prop)) { - std::ostringstream e; - e << "INTERFACE_LIBRARY targets may only have whitelisted properties. " - "The property \"" - << prop << "\" is not allowed."; - messenger->IssueMessage(MessageType::FATAL_ERROR, e.str(), context); - return false; - } - return true; -} diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h index f87b7c2..f2be318 100644 --- a/Source/cmTargetPropertyComputer.h +++ b/Source/cmTargetPropertyComputer.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetPropertyComputer_h -#define cmTargetPropertyComputer_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -35,12 +34,6 @@ public: return nullptr; } - static bool WhiteListedInterfaceProperty(const std::string& prop); - - static bool PassesWhitelist(cmStateEnums::TargetType tgtType, - std::string const& prop, cmMessenger* messenger, - cmListFileBacktrace const& context); - private: static bool HandleLocationPropertyPolicy(std::string const& tgtName, cmMessenger* messenger, @@ -107,5 +100,3 @@ private: static cmProp GetSources(Target const* tgt, cmMessenger* messenger, cmListFileBacktrace const& context); }; - -#endif diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h index 5eecf34..306226c 100644 --- a/Source/cmTargetSourcesCommand.h +++ b/Source/cmTargetSourcesCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTargetSourcesCommand_h -#define cmTargetSourcesCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmTargetSourcesCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmTest.h b/Source/cmTest.h index 72d4ed9..f33b7e2 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTest_h -#define cmTest_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -66,5 +65,3 @@ private: cmMakefile* Makefile; cmListFileBacktrace Backtrace; }; - -#endif diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index af91177..da4593f 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -2,8 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTestGenerator.h" +#include <algorithm> +#include <cstddef> // IWYU pragma: keep +#include <iterator> #include <memory> #include <ostream> +#include <string> #include <utility> #include <vector> @@ -11,7 +15,10 @@ #include "cmGeneratorTarget.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" +#include "cmPolicies.h" #include "cmProperty.h" #include "cmPropertyMap.h" #include "cmRange.h" @@ -20,6 +27,52 @@ #include "cmSystemTools.h" #include "cmTest.h" +namespace /* anonymous */ +{ + +bool needToQuoteTestName(const cmMakefile& mf, const std::string& name) +{ + // Determine if policy CMP0110 is set to NEW. + switch (mf.GetPolicyStatus(cmPolicies::CMP0110)) { + case cmPolicies::WARN: + // Only warn if a forbidden character is used in the name. + if (name.find_first_of("$[] #;\t\n\"\\") != std::string::npos) { + mf.IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0110), + "\nThe following name given to add_test() is invalid if " + "CMP0110 is not set or set to OLD:\n `", + name, "´\n")); + } + CM_FALLTHROUGH; + case cmPolicies::OLD: + // OLD behavior is to not quote the test's name. + return false; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + default: + // NEW behavior is to quote the test's name. + return true; + } +} + +std::size_t countMaxConsecutiveEqualSigns(const std::string& name) +{ + std::size_t max = 0; + auto startIt = find(name.begin(), name.end(), '='); + auto endIt = startIt; + for (; startIt != name.end(); startIt = find(endIt, name.end(), '=')) { + endIt = + find_if_not(startIt + 1, name.end(), [](char c) { return c == '='; }); + max = + std::max(max, static_cast<std::size_t>(std::distance(startIt, endIt))); + } + return max; +} + +} // End: anonymous namespace + cmTestGenerator::cmTestGenerator( cmTest* test, std::vector<std::string> const& configurations) : cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations) @@ -76,8 +129,21 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, // Set up generator expression evaluation context. cmGeneratorExpression ge(this->Test->GetBacktrace()); + // Determine if policy CMP0110 is set to NEW. + const bool quote_test_name = + needToQuoteTestName(*this->Test->GetMakefile(), this->Test->GetName()); + // Determine the number of equal-signs needed for quoting test name with + // [==[...]==] syntax. + const std::string equalSigns( + 1 + countMaxConsecutiveEqualSigns(this->Test->GetName()), '='); + // Start the test command. - os << indent << "add_test(" << this->Test->GetName() << " "; + if (quote_test_name) { + os << indent << "add_test([" << equalSigns << "[" << this->Test->GetName() + << "]" << equalSigns << "] "; + } else { + os << indent << "add_test(" << this->Test->GetName() << " "; + } // Evaluate command line arguments std::vector<std::string> argv = @@ -102,7 +168,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, // Prepend with the emulator when cross compiling if required. cmProp emulator = target->GetProperty("CROSSCOMPILING_EMULATOR"); - if (emulator != nullptr && !emulator->empty()) { + if (cmNonempty(emulator)) { std::vector<std::string> emulatorWithArgs = cmExpandedList(*emulator); std::string emulatorExe(emulatorWithArgs[0]); cmSystemTools::ConvertToUnixSlashes(emulatorExe); @@ -127,8 +193,13 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, os << ")\n"; // Output properties for the test. - os << indent << "set_tests_properties(" << this->Test->GetName() - << " PROPERTIES "; + if (quote_test_name) { + os << indent << "set_tests_properties([" << equalSigns << "[" + << this->Test->GetName() << "]" << equalSigns << "] PROPERTIES "; + } else { + os << indent << "set_tests_properties(" << this->Test->GetName() + << " PROPERTIES "; + } for (auto const& i : this->Test->GetProperties().GetList()) { os << " " << i.first << " " << cmOutputConverter::EscapeForCMake( @@ -140,7 +211,21 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent) { - os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n"; + // Determine if policy CMP0110 is set to NEW. + const bool quote_test_name = + needToQuoteTestName(*this->Test->GetMakefile(), this->Test->GetName()); + // Determine the number of equal-signs needed for quoting test name with + // [==[...]==] syntax. + const std::string equalSigns( + 1 + countMaxConsecutiveEqualSigns(this->Test->GetName()), '='); + + if (quote_test_name) { + os << indent << "add_test([" << equalSigns << "[" << this->Test->GetName() + << "]" << equalSigns << "] NOT_AVAILABLE)\n"; + } else { + os << indent << "add_test(" << this->Test->GetName() + << " NOT_AVAILABLE)\n"; + } } bool cmTestGenerator::NeedsScriptNoConfig() const @@ -155,14 +240,27 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent) { this->TestGenerated = true; + // Determine if policy CMP0110 is set to NEW. + const bool quote_test_name = + needToQuoteTestName(*this->Test->GetMakefile(), this->Test->GetName()); + // Determine the number of equal-signs needed for quoting test name with + // [==[...]==] syntax. + const std::string equalSigns( + 1 + countMaxConsecutiveEqualSigns(this->Test->GetName()), '='); + // Get the test command line to be executed. std::vector<std::string> const& command = this->Test->GetCommand(); std::string exe = command[0]; cmSystemTools::ConvertToUnixSlashes(exe); - fout << indent; - fout << "add_test("; - fout << this->Test->GetName() << " \"" << exe << "\""; + if (quote_test_name) { + fout << indent << "add_test([" << equalSigns << "[" + << this->Test->GetName() << "]" << equalSigns << "] \"" << exe + << "\""; + } else { + fout << indent << "add_test(" << this->Test->GetName() << " \"" << exe + << "\""; + } for (std::string const& arg : cmMakeRange(command).advance(1)) { // Just double-quote all arguments so they are re-parsed @@ -182,8 +280,13 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent) fout << ")\n"; // Output properties for the test. - fout << indent << "set_tests_properties(" << this->Test->GetName() - << " PROPERTIES "; + if (quote_test_name) { + fout << indent << "set_tests_properties([" << equalSigns << "[" + << this->Test->GetName() << "]" << equalSigns << "] PROPERTIES "; + } else { + fout << indent << "set_tests_properties(" << this->Test->GetName() + << " PROPERTIES "; + } for (auto const& i : this->Test->GetProperties().GetList()) { fout << " " << i.first << " " << cmOutputConverter::EscapeForCMake(i.second); diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h index e388c16..6903140 100644 --- a/Source/cmTestGenerator.h +++ b/Source/cmTestGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTestGenerator_h -#define cmTestGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -56,5 +55,3 @@ protected: cmTest* Test; bool TestGenerated; }; - -#endif diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 13f73dc..bd6bb3d 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -164,7 +164,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag, break; case 's': // Seconds since UNIX epoch (midnight 1-jan-1970) { - // Build a time_t for UNIX epoch and substract from the input "timeT": + // Build a time_t for UNIX epoch and subtract from the input "timeT": struct tm tmUnixEpoch; memset(&tmUnixEpoch, 0, sizeof(tmUnixEpoch)); tmUnixEpoch.tm_mday = 1; diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h index 40338f8..8941abe 100644 --- a/Source/cmTimestamp.h +++ b/Source/cmTimestamp.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTimestamp_h -#define cmTimestamp_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -30,5 +29,3 @@ private: std::string AddTimestampComponent(char flag, struct tm& timeStruct, time_t timeT) const; }; - -#endif diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h index e525e85..d8cc16e 100644 --- a/Source/cmTryCompileCommand.h +++ b/Source/cmTryCompileCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTryCompileCommand_h -#define cmTryCompileCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -38,5 +37,3 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; }; - -#endif diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index 64d71bc..3f89641 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -146,10 +146,10 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, if (!this->OutputVariable.empty()) { // if the TryCompileCore saved output in this outputVariable then // prepend that output to this output - const char* compileOutput = + cmProp compileOutput = this->Makefile->GetDefinition(this->OutputVariable); if (compileOutput) { - runOutputContents = compileOutput + runOutputContents; + runOutputContents = *compileOutput + runOutputContents; } this->Makefile->AddDefinition(this->OutputVariable, runOutputContents); } @@ -328,12 +328,12 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, file << comment << "\n\n"; file << "set( " << this->RunResultVariable << " \n \"" - << this->Makefile->GetDefinition(this->RunResultVariable) + << this->Makefile->GetSafeDefinition(this->RunResultVariable) << "\"\n CACHE STRING \"Result from TRY_RUN\" FORCE)\n\n"; if (out) { file << "set( " << internalRunOutputName << " \n \"" - << this->Makefile->GetDefinition(internalRunOutputName) + << this->Makefile->GetSafeDefinition(internalRunOutputName) << "\"\n CACHE STRING \"Output from TRY_RUN\" FORCE)\n\n"; } file.close(); @@ -354,6 +354,6 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, } if (out) { - (*out) = this->Makefile->GetDefinition(internalRunOutputName); + (*out) = *this->Makefile->GetDefinition(internalRunOutputName); } } diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h index c53a694..070c63c 100644 --- a/Source/cmTryRunCommand.h +++ b/Source/cmTryRunCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmTryRunCommand_h -#define cmTryRunCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -51,5 +50,3 @@ private: std::string RunOutputVariable; std::string CompileOutputVariable; }; - -#endif diff --git a/Source/cmUVProcessChain.h b/Source/cmUVProcessChain.h index b5ccb19..5e8e7e6 100644 --- a/Source/cmUVProcessChain.h +++ b/Source/cmUVProcessChain.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmUVProcessChain_h -#define cmUVProcessChain_h +#pragma once #include <array> #include <cstddef> // IWYU pragma: keep @@ -96,5 +95,3 @@ private: struct InternalData; std::unique_ptr<InternalData> Data; }; - -#endif diff --git a/Source/cmUVStreambuf.h b/Source/cmUVStreambuf.h index 50faede..efe45de 100644 --- a/Source/cmUVStreambuf.h +++ b/Source/cmUVStreambuf.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmUVStreambuf_h -#define cmUVStreambuf_h +#pragma once #include <algorithm> #include <cstring> @@ -215,5 +214,3 @@ void cmBasicUVStreambuf<CharT, Traits>::StreamRead(ssize_t nread) } using cmUVStreambuf = cmBasicUVStreambuf<char>; - -#endif diff --git a/Source/cmUnsetCommand.h b/Source/cmUnsetCommand.h index be4c166..3faa053 100644 --- a/Source/cmUnsetCommand.h +++ b/Source/cmUnsetCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmUnsetCommand_h -#define cmUnsetCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -17,5 +16,3 @@ class cmExecutionStatus; */ bool cmUnsetCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmUseMangledMesaCommand.h b/Source/cmUseMangledMesaCommand.h index 215e4a3..5670c5d 100644 --- a/Source/cmUseMangledMesaCommand.h +++ b/Source/cmUseMangledMesaCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmUseMangledMesaCommand_h -#define cmUseMangledMesaCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmUseMangledMesaCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index 6de78ff..d276c8a 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -6,6 +6,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -24,7 +25,7 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args, // The first argument is the cache entry name. std::string const& cacheEntry = *arg++; - const char* cacheValue = status.GetMakefile().GetDefinition(cacheEntry); + cmProp cacheValue = status.GetMakefile().GetDefinition(cacheEntry); // If it exists already and appears up to date then we are done. If // the string contains "(IntDir)" but that is not the // CMAKE_CFG_INTDIR setting then the value is out of date. @@ -45,7 +46,7 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args, } else { cmState* state = status.GetMakefile().GetState(); haveCacheValue = (cacheValue && - (strstr(cacheValue, "(IntDir)") == nullptr || + (strstr(cacheValue->c_str(), "(IntDir)") == nullptr || (intDir == "$(IntDir)")) && (state->GetCacheMajorVersion() != 0 && state->GetCacheMinorVersion() != 0)); @@ -84,8 +85,9 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args, std::string utilityDirectory = status.GetMakefile().GetCurrentBinaryDirectory(); std::string exePath; - if (auto d = status.GetMakefile().GetDefinition("EXECUTABLE_OUTPUT_PATH")) { - exePath = d; + if (cmProp d = + status.GetMakefile().GetDefinition("EXECUTABLE_OUTPUT_PATH")) { + exePath = *d; } if (!exePath.empty()) { utilityDirectory = exePath; @@ -96,7 +98,7 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args, // Construct the cache entry for the executable's location. std::string utilityExecutable = utilityDirectory + "/" + cmakeCFGout + "/" + utilityName + - status.GetMakefile().GetDefinition("CMAKE_EXECUTABLE_SUFFIX"); + *status.GetMakefile().GetDefinition("CMAKE_EXECUTABLE_SUFFIX"); // make sure we remove any /./ in the name cmSystemTools::ReplaceString(utilityExecutable, "/./", "/"); diff --git a/Source/cmUtilitySourceCommand.h b/Source/cmUtilitySourceCommand.h index 934d539..8cf7e7f 100644 --- a/Source/cmUtilitySourceCommand.h +++ b/Source/cmUtilitySourceCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmUtilitySourceCommand_h -#define cmUtilitySourceCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmUtilitySourceCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmUtils.hxx b/Source/cmUtils.hxx index a7a3e81..733e72f 100644 --- a/Source/cmUtils.hxx +++ b/Source/cmUtils.hxx @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmUtils_hxx -#define cmUtils_hxx +#pragma once #include "cmsys/SystemTools.hxx" @@ -13,5 +12,3 @@ inline bool isCMakeVerbose() return (cmSystemTools::HasEnv("VERBOSE") && !cmSystemTools::HasEnv("CMAKE_NO_VERBOSE")); } - -#endif diff --git a/Source/cmUuid.h b/Source/cmUuid.h index 7de20dd..f5f724d 100644 --- a/Source/cmUuid.h +++ b/Source/cmUuid.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmUuid_h -#define cmUuid_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -41,5 +40,3 @@ private: bool IntFromHexDigit(char input, char& output) const; }; - -#endif diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index a926eee..04ea46d 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVSSetupHelper_h -#define cmVSSetupHelper_h +#pragma once #ifndef NOMINMAX # define NOMINMAX // Undefine min and max defined by windows.h @@ -136,5 +135,3 @@ private: std::string SpecifiedVSInstallLocation; }; - -#endif diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index 6b93c63..1fe03ab 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -4,6 +4,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -37,11 +38,11 @@ bool cmVariableRequiresCommand(std::vector<std::string> const& args, } } } - const char* reqVar = status.GetMakefile().GetDefinition(resultVariable); + cmProp reqVar = status.GetMakefile().GetDefinition(resultVariable); // if reqVar is unset, then set it to requirementsMet // if reqVar is set to true, but requirementsMet is false , then // set reqVar to false. - if (!reqVar || (!requirementsMet && status.GetMakefile().IsOn(reqVar))) { + if (!reqVar || (!requirementsMet && status.GetMakefile().IsOn(*reqVar))) { status.GetMakefile().AddDefinitionBool(resultVariable, requirementsMet); } diff --git a/Source/cmVariableRequiresCommand.h b/Source/cmVariableRequiresCommand.h index fb0520e..c6bfe8a 100644 --- a/Source/cmVariableRequiresCommand.h +++ b/Source/cmVariableRequiresCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVariableRequiresCommand_h -#define cmVariableRequiresCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -12,5 +11,3 @@ class cmExecutionStatus; bool cmVariableRequiresCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h index 6c418ed..349ce0e 100644 --- a/Source/cmVariableWatch.h +++ b/Source/cmVariableWatch.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVariableWatch_h -#define cmVariableWatch_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -81,5 +80,3 @@ protected: StringToVectorOfPairs WatchMap; }; - -#endif diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index ecae16d..750b0b5 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -10,6 +10,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVariableWatch.h" @@ -45,7 +46,7 @@ void cmVariableWatchCommandVariableAccessed(const std::string& variable, std::string stack = *mf->GetProperty("LISTFILE_STACK"); if (!data->Command.empty()) { cmListFileFunction newLFF; - const char* const currentListFile = + cmProp const currentListFile = mf->GetDefinition("CMAKE_CURRENT_LIST_FILE"); const auto fakeLineNo = std::numeric_limits<decltype(cmListFileArgument::Line)>::max(); @@ -53,7 +54,7 @@ void cmVariableWatchCommandVariableAccessed(const std::string& variable, { variable, cmListFileArgument::Quoted, fakeLineNo }, { accessString, cmListFileArgument::Quoted, fakeLineNo }, { newValue ? newValue : "", cmListFileArgument::Quoted, fakeLineNo }, - { currentListFile, cmListFileArgument::Quoted, fakeLineNo }, + { *currentListFile, cmListFileArgument::Quoted, fakeLineNo }, { stack, cmListFileArgument::Quoted, fakeLineNo } }; newLFF.Name = data->Command; diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h index 3f9f244..4477cb7 100644 --- a/Source/cmVariableWatchCommand.h +++ b/Source/cmVariableWatchCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVariableWatchCommand_h -#define cmVariableWatchCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -16,5 +15,3 @@ class cmExecutionStatus; */ bool cmVariableWatchCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmVersion.h b/Source/cmVersion.h index 932ef04..9072c9f 100644 --- a/Source/cmVersion.h +++ b/Source/cmVersion.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVersion_h -#define cmVersion_h +#pragma once #include <cm3p/kwiml/int.h> @@ -30,5 +29,3 @@ public: ((((major)*1000u) * CMake_VERSION_ENCODE__BASE) + \ (((minor) % 1000u) * CMake_VERSION_ENCODE__BASE) + \ (((patch) % CMake_VERSION_ENCODE__BASE))) - -#endif diff --git a/Source/cmVersionMacros.h b/Source/cmVersionMacros.h index e8ac4f8..f33f0df 100644 --- a/Source/cmVersionMacros.h +++ b/Source/cmVersionMacros.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVersionMacros_h -#define cmVersionMacros_h +#pragma once #include "cmVersionConfig.h" @@ -9,5 +8,3 @@ #if CMake_VERSION_PATCH_IS_RELEASE(CMake_VERSION_PATCH) # define CMake_VERSION_IS_RELEASE 1 #endif - -#endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index a8e424d..ae4a5be 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -232,15 +232,17 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator( , LocalGenerator( (cmLocalVisualStudio10Generator*)target->GetLocalGenerator()) { - this->Makefile->GetConfigurations(this->Configurations); + this->Configurations = + this->Makefile->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); this->NsightTegra = gg->IsNsightTegra(); + this->Android = gg->TargetsAndroid(); for (int i = 0; i < 4; ++i) { this->NsightTegraVersion[i] = 0; } sscanf(gg->GetNsightTegraVersion().c_str(), "%u.%u.%u.%u", &this->NsightTegraVersion[0], &this->NsightTegraVersion[1], &this->NsightTegraVersion[2], &this->NsightTegraVersion[3]); - this->MSTools = !this->NsightTegra; + this->MSTools = !this->NsightTegra && !this->Android; this->Managed = false; this->TargetCompileAsWinRT = false; this->IsMissingFiles = false; @@ -312,11 +314,6 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString( void cmVisualStudio10TargetGenerator::Generate() { - // do not generate external ms projects - if (this->GeneratorTarget->GetType() == cmStateEnums::INTERFACE_LIBRARY || - this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) { - return; - } const std::string ProjectFileExtension = computeProjectFileExtension(this->GeneratorTarget); if (ProjectFileExtension == ".vcxproj") { @@ -333,6 +330,13 @@ void cmVisualStudio10TargetGenerator::Generate() this->ProjectType = csproj; this->Managed = true; } + + if (this->Android && + this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE && + !this->GeneratorTarget->Target->IsAndroidGuiExecutable()) { + this->GlobalGenerator->AddAndroidExecutableWarning(this->Name); + } + // Tell the global generator the name of the project file this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", this->Name); @@ -427,8 +431,8 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Attribute("Label", "Globals"); e1.Element("ProjectGuid", "{" + this->GUID + "}"); - if (this->MSTools && - this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) { + if ((this->MSTools || this->Android) && + this->GeneratorTarget->IsInBuildSystem()) { this->WriteApplicationTypeSettings(e1); this->VerifyNecessaryFiles(); } @@ -469,7 +473,11 @@ void cmVisualStudio10TargetGenerator::Generate() cmProp vsGlobalKeyword = this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD"); if (!vsGlobalKeyword) { - e1.Element("Keyword", "Win32Proj"); + if (this->GlobalGenerator->TargetsAndroid()) { + e1.Element("Keyword", "Android"); + } else { + e1.Element("Keyword", "Win32Proj"); + } } else { e1.Element("Keyword", *vsGlobalKeyword); } @@ -503,7 +511,7 @@ void cmVisualStudio10TargetGenerator::Generate() p = this->GeneratorTarget->GetProperty( "DOTNET_TARGET_FRAMEWORK_VERSION"); } - const char* targetFrameworkVersion = p ? p->c_str() : nullptr; + const char* targetFrameworkVersion = cmToCStr(p); if (!targetFrameworkVersion && this->ProjectType == csproj && this->GlobalGenerator->TargetsWindowsCE() && this->GlobalGenerator->GetVersion() == @@ -583,20 +591,30 @@ void cmVisualStudio10TargetGenerator::Generate() case cmStateEnums::MODULE_LIBRARY: outputType = "Module"; break; - case cmStateEnums::EXECUTABLE: - if (this->GeneratorTarget->Target->GetPropertyAsBool( - "WIN32_EXECUTABLE")) { + case cmStateEnums::EXECUTABLE: { + auto const win32 = + this->GeneratorTarget->GetSafeProperty("WIN32_EXECUTABLE"); + if (win32.find("$<") != std::string::npos) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Target \"", this->GeneratorTarget->GetName(), + "\" has a generator expression in its WIN32_EXECUTABLE " + "property. This is not supported on managed executables.")); + return; + } + if (cmIsOn(win32)) { outputType = "WinExe"; } else { outputType = "Exe"; } - break; + } break; case cmStateEnums::UTILITY: + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::GLOBAL_TARGET: outputType = "Utility"; break; case cmStateEnums::UNKNOWN_LIBRARY: - case cmStateEnums::INTERFACE_LIBRARY: break; } e1.Element("OutputType", outputType); @@ -658,7 +676,7 @@ void cmVisualStudio10TargetGenerator::Generate() cmStrCat(this->DefaultArtifactDir, "\\nasm.props"); ConvertToWindowsSlash(propsLocal); this->Makefile->ConfigureFile(propsTemplate, propsLocal, false, true, - true); + true, true); Elem(e1, "Import").Attribute("Project", propsLocal); } } @@ -1134,14 +1152,17 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0) break; case cmStateEnums::EXECUTABLE: if (this->NsightTegra && - !this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) { + !this->GeneratorTarget->Target->IsAndroidGuiExecutable()) { // Android executables are .so too. configType = "DynamicLibrary"; + } else if (this->Android) { + configType = "DynamicLibrary"; } else { configType = "Application"; } break; case cmStateEnums::UTILITY: + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::GLOBAL_TARGET: if (this->NsightTegra) { // Tegra-Android platform does not understand "Utility". @@ -1151,7 +1172,6 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0) } break; case cmStateEnums::UNKNOWN_LIBRARY: - case cmStateEnums::INTERFACE_LIBRARY: break; } } @@ -1166,6 +1186,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0) } } else if (this->NsightTegra) { this->WriteNsightTegraConfigurationValues(e1, c); + } else if (this->Android) { + this->WriteAndroidConfigurationValues(e1, c); } } } @@ -1200,9 +1222,9 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( Elem& e1, std::string const& config) { cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; - const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG"); + cmProp mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG"); if (mfcFlag) { - std::string const mfcFlagValue = mfcFlag; + std::string const mfcFlagValue = *mfcFlag; std::string useOfMfcValue = "false"; if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) { @@ -1324,6 +1346,24 @@ void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues( } } +void cmVisualStudio10TargetGenerator::WriteAndroidConfigurationValues( + Elem& e1, std::string const&) +{ + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; + if (cmProp projectToolsetOverride = + this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) { + e1.Element("PlatformToolset", *projectToolsetOverride); + } else if (const char* toolset = gg->GetPlatformToolset()) { + e1.Element("PlatformToolset", toolset); + } + if (cmProp stlType = + this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) { + if (*stlType != "none") { + e1.Element("UseOfStl", *stlType); + } + } +} + void cmVisualStudio10TargetGenerator::WriteCustomCommands(Elem& e0) { this->CSharpCustomCommandNames.clear(); @@ -1941,7 +1981,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, } cmProp toolOverride = sf->GetProperty("VS_TOOL_OVERRIDE"); - if (toolOverride && !toolOverride->empty()) { + if (cmNonempty(toolOverride)) { tool = toolOverride->c_str(); } @@ -1950,12 +1990,12 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, if (this->GlobalGenerator->TargetsWindowsPhone() || this->GlobalGenerator->TargetsWindowsStore()) { cmProp content = sf->GetProperty("VS_DEPLOYMENT_CONTENT"); - if (content && !content->empty()) { + if (cmNonempty(content)) { toolHasSettings = true; deployContent = *content; cmProp location = sf->GetProperty("VS_DEPLOYMENT_LOCATION"); - if (location && !location->empty()) { + if (cmNonempty(location)) { deployLocation = *location; } } @@ -2117,7 +2157,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2, void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) { - if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) { + if (this->GeneratorTarget->GetType() == cmStateEnums::GLOBAL_TARGET) { return; } @@ -2258,7 +2298,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) e2.Attribute("UnityFilesDirectory", unityDir); } else { // Visual Studio versions prior to 2017 15.8 do not know about unity - // builds, thus we exclude the files alredy part of unity sources. + // builds, thus we exclude the files already part of unity sources. if (!si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")) { exclude_configs = si.Configs; } @@ -2559,42 +2599,42 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( e1.WritePlatformConfigTag("IntDir", cond, intermediateDir); - if (const char* sdkExecutableDirectories = this->Makefile->GetDefinition( + if (cmProp sdkExecutableDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES")) { e1.WritePlatformConfigTag("ExecutablePath", cond, - sdkExecutableDirectories); + *sdkExecutableDirectories); } - if (const char* sdkIncludeDirectories = this->Makefile->GetDefinition( + if (cmProp sdkIncludeDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_INCLUDE_DIRECTORIES")) { - e1.WritePlatformConfigTag("IncludePath", cond, sdkIncludeDirectories); + e1.WritePlatformConfigTag("IncludePath", cond, *sdkIncludeDirectories); } - if (const char* sdkReferenceDirectories = this->Makefile->GetDefinition( + if (cmProp sdkReferenceDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_REFERENCE_DIRECTORIES")) { e1.WritePlatformConfigTag("ReferencePath", cond, - sdkReferenceDirectories); + *sdkReferenceDirectories); } - if (const char* sdkLibraryDirectories = this->Makefile->GetDefinition( + if (cmProp sdkLibraryDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_LIBRARY_DIRECTORIES")) { - e1.WritePlatformConfigTag("LibraryPath", cond, sdkLibraryDirectories); + e1.WritePlatformConfigTag("LibraryPath", cond, *sdkLibraryDirectories); } - if (const char* sdkLibraryWDirectories = this->Makefile->GetDefinition( + if (cmProp sdkLibraryWDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES")) { e1.WritePlatformConfigTag("LibraryWPath", cond, - sdkLibraryWDirectories); + *sdkLibraryWDirectories); } - if (const char* sdkSourceDirectories = + if (cmProp sdkSourceDirectories = this->Makefile->GetDefinition("CMAKE_VS_SDK_SOURCE_DIRECTORIES")) { - e1.WritePlatformConfigTag("SourcePath", cond, sdkSourceDirectories); + e1.WritePlatformConfigTag("SourcePath", cond, *sdkSourceDirectories); } - if (const char* sdkExcludeDirectories = this->Makefile->GetDefinition( + if (cmProp sdkExcludeDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_EXCLUDE_DIRECTORIES")) { - e1.WritePlatformConfigTag("ExcludePath", cond, sdkExcludeDirectories); + e1.WritePlatformConfigTag("ExcludePath", cond, *sdkExcludeDirectories); } std::string name = @@ -2915,7 +2955,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( } } - if (this->MSTools) { + if (this->Android) { + e2.Element("ObjectFileName", "$(IntDir)%(filename).o"); + } else if (this->MSTools) { cmsys::RegularExpression clangToolset("v[0-9]+_clang_.*"); const char* toolset = this->GlobalGenerator->GetPlatformToolset(); if (toolset && clangToolset.find(toolset)) { @@ -3695,7 +3737,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( } if (this->MSTools) { - if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) { + if (this->GeneratorTarget->IsWin32Executable(config)) { if (this->GlobalGenerator->TargetsWindowsCE()) { linkOptions.AddFlag("SubSystem", "WindowsCE"); if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { @@ -3723,9 +3765,9 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( }; } - if (const char* stackVal = this->Makefile->GetDefinition( + if (cmProp stackVal = this->Makefile->GetDefinition( "CMAKE_" + linkLanguage + "_STACK_SIZE")) { - linkOptions.AddFlag("StackReserveSize", stackVal); + linkOptions.AddFlag("StackReserveSize", *stackVal); } linkOptions.AddFlag("GenerateDebugInformation", "false"); @@ -4021,8 +4063,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0) // output manifest flags <Manifest></Manifest> this->WriteManifestOptions(e1, c); if (this->NsightTegra && - this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE && - this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) { + this->GeneratorTarget->Target->IsAndroidGuiExecutable()) { this->WriteAntBuildOptions(e1, c); } } @@ -4108,7 +4149,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) Elem e1(e0, "ItemGroup"); e1.SetHasElements(); for (cmGeneratorTarget const* dt : depends) { - if (dt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (!dt->IsInBuildSystem()) { continue; } // skip fortran targets as they can not be processed by MSBuild @@ -4137,8 +4178,9 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) } // Don't reference targets that don't produce any output. - if (dt->GetManagedType(this->Configurations[0]) == - cmGeneratorTarget::ManagedType::Undefined) { + if (this->Configurations.empty() || + dt->GetManagedType(this->Configurations[0]) == + cmGeneratorTarget::ManagedType::Undefined) { e2.Element("ReferenceOutputAssembly", "false"); e2.Element("CopyToOutputDirectory", "Never"); } @@ -4354,6 +4396,7 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1) bool isAppContainer = false; bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone(); bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore(); + bool const isAndroid = this->GlobalGenerator->TargetsAndroid(); std::string const& rev = this->GlobalGenerator->GetApplicationTypeRevision(); if (isWindowsPhone || isWindowsStore) { e1.Element("ApplicationType", @@ -4391,13 +4434,19 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1) this->Name + "_$(Configuration)_$(Platform).xap"); } } + } else if (isAndroid) { + e1.Element("ApplicationType", "Android"); + e1.Element("ApplicationTypeRevision", + gg->GetAndroidApplicationTypeRevision()); } if (isAppContainer) { e1.Element("AppContainerApplication", "true"); - } else if (this->Platform == "ARM64") { - e1.Element("WindowsSDKDesktopARM64Support", "true"); - } else if (this->Platform == "ARM") { - e1.Element("WindowsSDKDesktopARMSupport", "true"); + } else if (!isAndroid) { + if (this->Platform == "ARM64") { + e1.Element("WindowsSDKDesktopARM64Support", "true"); + } else if (this->Platform == "ARM") { + e1.Element("WindowsSDKDesktopARMSupport", "true"); + } } std::string const& targetPlatformVersion = gg->GetWindowsTargetPlatformVersion(); diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 7c71de3..35dbba8 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVisualStudioTargetGenerator_h -#define cmVisualStudioTargetGenerator_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -70,6 +69,7 @@ private: void WriteExtraSource(Elem& e1, cmSourceFile const* sf); void WriteNsightTegraConfigurationValues(Elem& e1, std::string const& config); + void WriteAndroidConfigurationValues(Elem& e1, std::string const& config); void WriteSource(Elem& e2, cmSourceFile const* sf); void WriteExcludeFromBuild(Elem& e2, std::vector<size_t> const& exclude_configs); @@ -215,6 +215,7 @@ private: bool MSTools; bool Managed; bool NsightTegra; + bool Android; unsigned int NsightTegraVersion[4]; bool TargetCompileAsWinRT; std::set<std::string> IPOEnabledConfigurations; @@ -257,5 +258,3 @@ private: ConfigToSettings& toolSettings); std::string GetCMakeFilePath(const char* name) const; }; - -#endif diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h index 875a35b..85cc2b6 100644 --- a/Source/cmVisualStudio10ToolsetOptions.h +++ b/Source/cmVisualStudio10ToolsetOptions.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVisualStudio10ToolsetOptions_h -#define cmVisualStudio10ToolsetOptions_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -30,4 +29,3 @@ public: std::string GetToolsetName(std::string const& name, std::string const& toolset) const; }; -#endif diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index f9b50a7..b123019 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVisualStudioGeneratorOptions_h -#define cmVisualStudioGeneratorOptions_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -100,5 +99,3 @@ private: FlagValue TakeFlag(std::string const& key); }; - -#endif diff --git a/Source/cmVisualStudioSlnData.h b/Source/cmVisualStudioSlnData.h index 5ce7d74..b217bd8 100644 --- a/Source/cmVisualStudioSlnData.h +++ b/Source/cmVisualStudioSlnData.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVisualStudioSlnData_h -#define cmVisualStudioSlnData_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -50,5 +49,3 @@ private: using ProjectStringIndex = std::map<std::string, ProjectStorage::iterator>; ProjectStringIndex ProjectNameIndex; }; - -#endif diff --git a/Source/cmVisualStudioSlnParser.h b/Source/cmVisualStudioSlnParser.h index 4557cdb..1c33759 100644 --- a/Source/cmVisualStudioSlnParser.h +++ b/Source/cmVisualStudioSlnParser.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVisualStudioSlnParser_h -#define cmVisualStudioSlnParser_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -103,5 +102,3 @@ protected: bool ParseValue(const std::string& value, ParsedLine& parsedLine); }; - -#endif diff --git a/Source/cmVisualStudioWCEPlatformParser.h b/Source/cmVisualStudioWCEPlatformParser.h index 60a6611..eb4e978 100644 --- a/Source/cmVisualStudioWCEPlatformParser.h +++ b/Source/cmVisualStudioWCEPlatformParser.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmVisualStudioWCEPlatformParser_h -#define cmVisualStudioWCEPlatformParser_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -67,5 +66,3 @@ private: std::string VcInstallDir; std::string VsInstallDir; }; - -#endif diff --git a/Source/cmWhileCommand.h b/Source/cmWhileCommand.h index beca652..5b8f078 100644 --- a/Source/cmWhileCommand.h +++ b/Source/cmWhileCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWhileCommand_h -#define cmWhileCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -13,5 +12,3 @@ struct cmListFileArgument; /// \brief Starts a while loop bool cmWhileCommand(std::vector<cmListFileArgument> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmWorkerPool.h b/Source/cmWorkerPool.h index 9179922..0fb6707 100644 --- a/Source/cmWorkerPool.h +++ b/Source/cmWorkerPool.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWorkerPool_h -#define cmWorkerPool_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -221,5 +220,3 @@ private: unsigned int ThreadCount_ = 1; std::unique_ptr<cmWorkerPoolInternal> Int_; }; - -#endif diff --git a/Source/cmWorkingDirectory.h b/Source/cmWorkingDirectory.h index 4c7576d..c8adea9 100644 --- a/Source/cmWorkingDirectory.h +++ b/Source/cmWorkingDirectory.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWorkingDirectory_h -#define cmWorkingDirectory_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -43,5 +42,3 @@ private: std::string OldDir; int ResultCode; }; - -#endif diff --git a/Source/cmWriteFileCommand.h b/Source/cmWriteFileCommand.h index 3e0e043..0225e4f 100644 --- a/Source/cmWriteFileCommand.h +++ b/Source/cmWriteFileCommand.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmWriteFileCommand_h -#define cmWriteFileCommand_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -16,5 +15,3 @@ class cmExecutionStatus; */ bool cmWriteFileCommand(std::vector<std::string> const& args, cmExecutionStatus& status); - -#endif diff --git a/Source/cmXCode21Object.cxx b/Source/cmXCode21Object.cxx index 6b133a9..1cf9a95 100644 --- a/Source/cmXCode21Object.cxx +++ b/Source/cmXCode21Object.cxx @@ -16,7 +16,7 @@ cmXCode21Object::cmXCode21Object(PBXType ptype, Type type) void cmXCode21Object::PrintComment(std::ostream& out) { if (this->Comment.empty()) { - cmXCodeObject* n = this->GetObject("name"); + cmXCodeObject* n = this->GetAttribute("name"); if (n) { this->Comment = n->GetString(); cmSystemTools::ReplaceString(this->Comment, "\"", ""); diff --git a/Source/cmXCode21Object.h b/Source/cmXCode21Object.h index 76fad23..eb017447 100644 --- a/Source/cmXCode21Object.h +++ b/Source/cmXCode21Object.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmXCode21Object_h -#define cmXCode21Object_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -21,4 +20,3 @@ public: static void PrintList(std::vector<std::unique_ptr<cmXCodeObject>> const&, std::ostream& out); }; -#endif diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h index 24ecaa2..78d4727 100644 --- a/Source/cmXCodeObject.h +++ b/Source/cmXCodeObject.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmXCodeObject_h -#define cmXCodeObject_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -82,6 +81,10 @@ public: void SetObject(cmXCodeObject* value) { this->Object = value; } cmXCodeObject* GetObject() { return this->Object; } void AddObject(cmXCodeObject* value) { this->List.push_back(value); } + void PrependObject(cmXCodeObject* value) + { + this->List.insert(this->List.begin(), value); + } bool HasObject(cmXCodeObject* o) const { return cm::contains(this->List, o); @@ -107,7 +110,7 @@ public: void SetTarget(cmGeneratorTarget* t) { this->Target = t; } const std::string& GetComment() const { return this->Comment; } bool HasComment() const { return (!this->Comment.empty()); } - cmXCodeObject* GetObject(const char* name) const + cmXCodeObject* GetAttribute(const char* name) const { auto const i = this->ObjectAttributes.find(name); if (i != this->ObjectAttributes.end()) { @@ -167,4 +170,3 @@ protected: std::map<std::string, StringVec> DependTargets; std::map<std::string, cmXCodeObject*> ObjectAttributes; }; -#endif diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index f4c2f2d..55e941d 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -33,7 +33,7 @@ void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir, // Create shared scheme sub-directory tree // std::string xcodeSchemeDir = cmStrCat(xcProjDir, "/xcshareddata/xcschemes"); - cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str()); + cmSystemTools::MakeDirectory(xcodeSchemeDir); std::string xcodeSchemeFile = cmStrCat(xcodeSchemeDir, '/', this->TargetName, ".xcscheme"); @@ -324,8 +324,7 @@ bool cmXCodeScheme::WriteLaunchActionBooleanAttribute( bool defaultValue) { cmProp property = Target->GetTarget()->GetProperty(varName); - bool isOn = - (property == nullptr && defaultValue) || (property && cmIsOn(*property)); + bool isOn = (property == nullptr && defaultValue) || cmIsOn(property); if (isOn) { xout.Attribute(attrName.c_str(), "YES"); diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h index da40856..11f043e 100644 --- a/Source/cmXCodeScheme.h +++ b/Source/cmXCodeScheme.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmXCodeScheme_h -#define cmXCodeScheme_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -74,5 +73,3 @@ private: static bool IsExecutable(const cmXCodeObject* target); }; - -#endif diff --git a/Source/cmXMLParser.h b/Source/cmXMLParser.h index 1bc8d64..7e805d7 100644 --- a/Source/cmXMLParser.h +++ b/Source/cmXMLParser.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmXMLParser_h -#define cmXMLParser_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -107,5 +106,3 @@ protected: friend void cmXMLParserEndElement(void*, const char*); friend void cmXMLParserCharacterDataHandler(void*, const char*, int); }; - -#endif diff --git a/Source/cmXMLSafe.h b/Source/cmXMLSafe.h index 9aaf2d1..9b4c539 100644 --- a/Source/cmXMLSafe.h +++ b/Source/cmXMLSafe.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmXMLSafe_h -#define cmXMLSafe_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -33,5 +32,3 @@ private: bool DoQuotes; friend std::ostream& operator<<(std::ostream&, cmXMLSafe const&); }; - -#endif diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h index 00ea08c..a16c4c8 100644 --- a/Source/cmXMLWriter.h +++ b/Source/cmXMLWriter.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmXMLWiter_h -#define cmXMLWiter_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -196,5 +195,3 @@ public: private: cmXMLWriter& xmlwr; }; - -#endif diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx index b2cb9e6..1860211 100644 --- a/Source/cm_codecvt.hxx +++ b/Source/cm_codecvt.hxx @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cm_codecvt_hxx -#define cm_codecvt_hxx +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -62,5 +61,3 @@ private: #endif }; - -#endif diff --git a/Source/cm_get_date.h b/Source/cm_get_date.h index 38a690e..65722df 100644 --- a/Source/cm_get_date.h +++ b/Source/cm_get_date.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cm_get_date_h -#define cm_get_date_h +#pragma once #include <time.h> /* NOLINT(modernize-deprecated-headers) */ @@ -15,5 +14,3 @@ time_t cm_get_date(time_t now, const char* str); #ifdef __cplusplus } /* extern "C" */ #endif - -#endif diff --git a/Source/cm_sys_stat.h b/Source/cm_sys_stat.h index 9194286..c4e3d84 100644 --- a/Source/cm_sys_stat.h +++ b/Source/cm_sys_stat.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cm_sys_stat_h -#define cm_sys_stat_h +#pragma once #if defined(_MSC_VER) using mode_t = unsigned short; @@ -10,5 +9,3 @@ using mode_t = unsigned short; #include <sys/types.h> // include sys/stat.h after sys/types.h #include <sys/stat.h> // IWYU pragma: export - -#endif diff --git a/Source/cm_utf8.h b/Source/cm_utf8.h index 27dc559..fa9ed3a 100644 --- a/Source/cm_utf8.h +++ b/Source/cm_utf8.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cm_utf8_h -#define cm_utf8_h +#pragma once #ifdef __cplusplus extern "C" { @@ -20,5 +19,3 @@ int cm_utf8_is_valid(const char* s); #ifdef __cplusplus } /* extern "C" */ #endif - -#endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 162e807..bca938e 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -64,10 +64,6 @@ # include "cmVariableWatch.h" #endif -#if !defined(CMAKE_BOOTSTRAP) -# define CMAKE_USE_ECLIPSE -#endif - #if defined(__MINGW32__) && defined(CMAKE_BOOTSTRAP) # define CMAKE_BOOT_MINGW #endif @@ -97,20 +93,21 @@ #if defined(CMAKE_USE_WMAKE) # include "cmGlobalWatcomWMakeGenerator.h" #endif -#include "cmGlobalUnixMakefileGenerator3.h" #if !defined(CMAKE_BOOTSTRAP) # include "cmGlobalNinjaGenerator.h" +# include "cmGlobalUnixMakefileGenerator3.h" +#elif defined(CMAKE_BOOTSTRAP_MAKEFILES) +# include "cmGlobalUnixMakefileGenerator3.h" +#elif defined(CMAKE_BOOTSTRAP_NINJA) +# include "cmGlobalNinjaGenerator.h" #endif -#include "cmExtraCodeLiteGenerator.h" -#if !defined(CMAKE_BOOT_MINGW) +#if !defined(CMAKE_BOOTSTRAP) # include "cmExtraCodeBlocksGenerator.h" -#endif -#include "cmExtraKateGenerator.h" -#include "cmExtraSublimeTextGenerator.h" - -#ifdef CMAKE_USE_ECLIPSE +# include "cmExtraCodeLiteGenerator.h" # include "cmExtraEclipseCDT4Generator.h" +# include "cmExtraKateGenerator.h" +# include "cmExtraSublimeTextGenerator.h" #endif #if defined(__linux__) || defined(_WIN32) @@ -201,13 +198,14 @@ cmake::cmake(Role role, cmState::Mode mode) }; // The "c" extension MUST precede the "C" extension. - setupExts(this->SourceFileExtensions, + setupExts(this->CLikeSourceFileExtensions, { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "m", "M", "mm" }); setupExts(this->HeaderFileExtensions, { "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" }); setupExts(this->CudaFileExtensions, { "cu" }); setupExts(this->FortranFileExtensions, { "f", "F", "for", "f77", "f90", "f95", "f03" }); + setupExts(this->ISPCFileExtensions, { "ispc" }); } } @@ -780,8 +778,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) std::cout << "Warn about uninitialized values.\n"; this->SetWarnUninitialized(true); } else if (cmHasLiteralPrefix(arg, "--warn-unused-vars")) { - std::cout << "Finding unused variables.\n"; - this->SetWarnUnused(true); + // Option was removed. } else if (cmHasLiteralPrefix(arg, "--no-warn-unused-cli")) { std::cout << "Not searching for unused variables given on the " << "command line.\n"; @@ -1137,13 +1134,9 @@ void cmake::AddDefaultExtraGenerators() #if !defined(CMAKE_BOOTSTRAP) this->ExtraGenerators.push_back(cmExtraCodeBlocksGenerator::GetFactory()); this->ExtraGenerators.push_back(cmExtraCodeLiteGenerator::GetFactory()); - this->ExtraGenerators.push_back(cmExtraSublimeTextGenerator::GetFactory()); - this->ExtraGenerators.push_back(cmExtraKateGenerator::GetFactory()); - -# ifdef CMAKE_USE_ECLIPSE this->ExtraGenerators.push_back(cmExtraEclipseCDT4Generator::GetFactory()); -# endif - + this->ExtraGenerators.push_back(cmExtraKateGenerator::GetFactory()); + this->ExtraGenerators.push_back(cmExtraSublimeTextGenerator::GetFactory()); #endif } @@ -1383,7 +1376,7 @@ struct SaveCacheEntry int cmake::HandleDeleteCacheVariables(const std::string& var) { - std::vector<std::string> argsSplit = cmExpandedList(std::string(var), true); + std::vector<std::string> argsSplit = cmExpandedList(var, true); // erase the property to avoid infinite recursion this->State->SetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", ""); if (this->State->GetIsInTryCompile()) { @@ -1402,8 +1395,13 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) save.key = *i; warning << *i << "= "; i++; - save.value = *i; - warning << *i << "\n"; + if (i != argsSplit.end()) { + save.value = *i; + warning << *i << "\n"; + } else { + warning << "\n"; + i -= 1; + } cmProp existingValue = this->State->GetCacheEntryValue(save.key); if (existingValue) { save.type = this->State->GetCacheEntryType(save.key); @@ -1499,10 +1497,10 @@ int cmake::Configure() this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(*value)); value = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED"); - this->Messenger->SetDeprecatedWarningsAsErrors(value && cmIsOn(*value)); + this->Messenger->SetDeprecatedWarningsAsErrors(cmIsOn(value)); value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_WARNINGS"); - this->Messenger->SetSuppressDevWarnings(value && cmIsOn(*value)); + this->Messenger->SetSuppressDevWarnings(cmIsOn(value)); value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS"); this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(*value)); @@ -1757,6 +1755,9 @@ std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator() gen = cm::make_unique<cmGlobalNMakeMakefileGenerator>(this); } return std::unique_ptr<cmGlobalGenerator>(std::move(gen)); +#elif defined(CMAKE_BOOTSTRAP_NINJA) + return std::unique_ptr<cmGlobalGenerator>( + cm::make_unique<cmGlobalNinjaGenerator>(this)); #else return std::unique_ptr<cmGlobalGenerator>( cm::make_unique<cmGlobalUnixMakefileGenerator3>(this)); @@ -1970,6 +1971,19 @@ void cmake::AddGlobCacheEntry(bool recurse, bool listDirectories, backtrace); } +std::vector<std::string> cmake::GetAllExtensions() const +{ + std::vector<std::string> allExt = this->CLikeSourceFileExtensions.ordered; + allExt.insert(allExt.end(), this->HeaderFileExtensions.ordered.begin(), + this->HeaderFileExtensions.ordered.end()); + // cuda extensions are also in SourceFileExtensions so we ignore it here + allExt.insert(allExt.end(), this->FortranFileExtensions.ordered.begin(), + this->FortranFileExtensions.ordered.end()); + allExt.insert(allExt.end(), this->ISPCFileExtensions.ordered.begin(), + this->ISPCFileExtensions.ordered.end()); + return allExt; +} + std::string cmake::StripExtension(const std::string& file) const { auto dotpos = file.rfind('.'); @@ -1979,7 +1993,7 @@ std::string cmake::StripExtension(const std::string& file) const #else auto ext = cm::string_view(file).substr(dotpos + 1); #endif - if (this->IsSourceExtension(ext) || this->IsHeaderExtension(ext)) { + if (this->IsAKnownExtension(ext)) { return file.substr(0, dotpos); } } @@ -2022,13 +2036,17 @@ void cmake::AddDefaultGenerators() this->Generators.push_back(cmGlobalMSYSMakefileGenerator::NewFactory()); this->Generators.push_back(cmGlobalMinGWMakefileGenerator::NewFactory()); #endif - this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory()); #if !defined(CMAKE_BOOTSTRAP) # if defined(__linux__) || defined(_WIN32) this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory()); # endif + this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory()); this->Generators.push_back(cmGlobalNinjaGenerator::NewFactory()); this->Generators.push_back(cmGlobalNinjaMultiGenerator::NewFactory()); +#elif defined(CMAKE_BOOTSTRAP_NINJA) + this->Generators.push_back(cmGlobalNinjaGenerator::NewFactory()); +#elif defined(CMAKE_BOOTSTRAP_MAKEFILES) + this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory()); #endif #if defined(CMAKE_USE_WMAKE) this->Generators.push_back(cmGlobalWatcomWMakeGenerator::NewFactory()); @@ -2268,8 +2286,9 @@ int cmake::CheckBuildSystem() if (this->ClearBuildSystem) { // Get the generator used for this build system. - const char* genName = mf.GetDefinition("CMAKE_DEPENDS_GENERATOR"); - if (!genName || genName[0] == '\0') { + const char* genName = + cmToCStr(mf.GetDefinition("CMAKE_DEPENDS_GENERATOR")); + if (!cmNonempty(genName)) { genName = "Unix Makefiles"; } @@ -2743,9 +2762,7 @@ int cmake::Build(int jobs, const std::string& dir, } projName = *cachedProjectName; - cmProp cachedVerbose = - this->State->GetCacheEntryValue("CMAKE_VERBOSE_MAKEFILE"); - if (cachedVerbose && cmIsOn(*cachedVerbose)) { + if (cmIsOn(this->State->GetCacheEntryValue("CMAKE_VERBOSE_MAKEFILE"))) { verbose = true; } diff --git a/Source/cmake.h b/Source/cmake.h index 086ec87..44c35c2 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmake_h -#define cmake_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -264,44 +263,34 @@ public: this->GeneratorToolsetSet = true; } - const std::vector<std::string>& GetSourceExtensions() const + bool IsAKnownSourceExtension(cm::string_view ext) const { - return this->SourceFileExtensions.ordered; + return this->CLikeSourceFileExtensions.Test(ext) || + this->CudaFileExtensions.Test(ext) || + this->FortranFileExtensions.Test(ext) || + this->ISPCFileExtensions.Test(ext); } - bool IsSourceExtension(cm::string_view ext) const + bool IsACLikeSourceExtension(cm::string_view ext) const { - return this->SourceFileExtensions.Test(ext); + return this->CLikeSourceFileExtensions.Test(ext); } - const std::vector<std::string>& GetHeaderExtensions() const - { - return this->HeaderFileExtensions.ordered; - } - - bool IsHeaderExtension(cm::string_view ext) const - { - return this->HeaderFileExtensions.Test(ext); - } - - const std::vector<std::string>& GetCudaExtensions() const + bool IsAKnownExtension(cm::string_view ext) const { - return this->CudaFileExtensions.ordered; + return this->IsAKnownSourceExtension(ext) || this->IsAHeaderExtension(ext); } - bool IsCudaExtension(cm::string_view ext) const - { - return this->CudaFileExtensions.Test(ext); - } + std::vector<std::string> GetAllExtensions() const; - const std::vector<std::string>& GetFortranExtensions() const + const std::vector<std::string>& GetHeaderExtensions() const { - return this->FortranFileExtensions.ordered; + return this->HeaderFileExtensions.ordered; } - bool IsFortranExtension(cm::string_view ext) const + bool IsAHeaderExtension(cm::string_view ext) const { - return this->FortranFileExtensions.Test(ext); + return this->HeaderFileExtensions.Test(ext); } // Strips the extension (if present and known) from a filename @@ -461,8 +450,6 @@ public: bool GetWarnUninitialized() { return this->WarnUninitialized; } void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; } - bool GetWarnUnused() { return this->WarnUnused; } - void SetWarnUnused(bool b) { this->WarnUnused = b; } bool GetWarnUnusedCli() { return this->WarnUnusedCli; } void SetWarnUnusedCli(bool b) { this->WarnUnusedCli = b; } bool GetCheckSystemVars() { return this->CheckSystemVars; } @@ -616,7 +603,6 @@ private: TraceFormat TraceFormatVar = TRACE_HUMAN; cmGeneratedFileStream TraceFile; bool WarnUninitialized = false; - bool WarnUnused = false; bool WarnUnusedCli = true; bool CheckSystemVars = false; std::map<std::string, bool> UsedCliVariables; @@ -628,9 +614,10 @@ private: std::string CheckStampList; std::string VSSolutionFile; std::string EnvironmentGenerator; - FileExtensions SourceFileExtensions; + FileExtensions CLikeSourceFileExtensions; FileExtensions HeaderFileExtensions; FileExtensions CudaFileExtensions; + FileExtensions ISPCFileExtensions; FileExtensions FortranFileExtensions; bool ClearBuildSystem = false; bool DebugTryCompile = false; @@ -794,5 +781,3 @@ private: F(cuda_std_14) \ F(cuda_std_17) \ F(cuda_std_20) - -#endif diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index d662a9a..4600fc5 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -3,11 +3,13 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <algorithm> #include <cassert> #include <cctype> #include <climits> #include <cstring> #include <iostream> +#include <sstream> #include <string> #include <vector> @@ -69,7 +71,7 @@ const char* cmDocumentationOptions[][2] = { { "--open <dir>", "Open generated project in the associated application." }, { "-N", "View mode only." }, { "-P <file>", "Process script mode." }, - { "--find-package", "Run in pkg-config like mode." }, + { "--find-package", "Legacy pkg-config like mode. Do not use." }, { "--graphviz=[file]", "Generate graphviz of dependencies, see " "CMakeGraphVizOptions.cmake for more." }, @@ -91,7 +93,6 @@ const char* cmDocumentationOptions[][2] = { { "--trace-redirect=<file>", "Redirect trace output to a file instead of stderr." }, { "--warn-uninitialized", "Warn about uninitialized values." }, - { "--warn-unused-vars", "Warn about unused variables." }, { "--no-warn-unused-cli", "Don't warn about command line options." }, { "--check-system-vars", "Find problems with variable usage in system " @@ -519,6 +520,121 @@ int do_build(int ac, char const* const* av) #endif } +bool parse_default_directory_permissions(const std::string& permissions, + std::string& parsedPermissionsVar) +{ + std::vector<std::string> parsedPermissions; + enum Doing + { + DoingNone, + DoingOwner, + DoingGroup, + DoingWorld, + DoingOwnerAssignment, + DoingGroupAssignment, + DoingWorldAssignment, + }; + Doing doing = DoingNone; + + auto uniquePushBack = [&parsedPermissions](const std::string& e) { + if (std::find(parsedPermissions.begin(), parsedPermissions.end(), e) == + parsedPermissions.end()) { + parsedPermissions.push_back(e); + } + }; + + for (auto const& e : permissions) { + switch (doing) { + case DoingNone: + if (e == 'u') { + doing = DoingOwner; + } else if (e == 'g') { + doing = DoingGroup; + } else if (e == 'o') { + doing = DoingWorld; + } else { + return false; + } + break; + case DoingOwner: + if (e == '=') { + doing = DoingOwnerAssignment; + } else { + return false; + } + break; + case DoingGroup: + if (e == '=') { + doing = DoingGroupAssignment; + } else { + return false; + } + break; + case DoingWorld: + if (e == '=') { + doing = DoingWorldAssignment; + } else { + return false; + } + break; + case DoingOwnerAssignment: + if (e == 'r') { + uniquePushBack("OWNER_READ"); + } else if (e == 'w') { + uniquePushBack("OWNER_WRITE"); + } else if (e == 'x') { + uniquePushBack("OWNER_EXECUTE"); + } else if (e == ',') { + doing = DoingNone; + } else { + return false; + } + break; + case DoingGroupAssignment: + if (e == 'r') { + uniquePushBack("GROUP_READ"); + } else if (e == 'w') { + uniquePushBack("GROUP_WRITE"); + } else if (e == 'x') { + uniquePushBack("GROUP_EXECUTE"); + } else if (e == ',') { + doing = DoingNone; + } else { + return false; + } + break; + case DoingWorldAssignment: + if (e == 'r') { + uniquePushBack("WORLD_READ"); + } else if (e == 'w') { + uniquePushBack("WORLD_WRITE"); + } else if (e == 'x') { + uniquePushBack("WORLD_EXECUTE"); + } else if (e == ',') { + doing = DoingNone; + } else { + return false; + } + break; + } + } + if (doing != DoingOwnerAssignment && doing != DoingGroupAssignment && + doing != DoingWorldAssignment) { + return false; + } + + std::ostringstream oss; + for (auto i = 0u; i < parsedPermissions.size(); i++) { + if (i != 0) { + oss << ";"; + } + oss << parsedPermissions[i]; + } + + parsedPermissionsVar = oss.str(); + return true; +} + int do_install(int ac, char const* const* av) { #ifdef CMAKE_BOOTSTRAP @@ -529,6 +645,7 @@ int do_install(int ac, char const* const* av) std::string config; std::string component; + std::string defaultDirectoryPermissions; std::string prefix; std::string dir; bool strip = false; @@ -541,6 +658,7 @@ int do_install(int ac, char const* const* av) DoingConfig, DoingComponent, DoingPrefix, + DoingDefaultDirectoryPermissions, }; Doing doing = DoingDir; @@ -559,6 +677,8 @@ int do_install(int ac, char const* const* av) (strcmp(av[i], "-v") == 0)) { verbose = true; doing = DoingNone; + } else if (strcmp(av[i], "--default-directory-permissions") == 0) { + doing = DoingDefaultDirectoryPermissions; } else { switch (doing) { case DoingDir: @@ -577,6 +697,10 @@ int do_install(int ac, char const* const* av) prefix = av[i]; doing = DoingNone; break; + case DoingDefaultDirectoryPermissions: + defaultDirectoryPermissions = av[i]; + doing = DoingNone; + break; default: std::cerr << "Unknown argument " << av[i] << std::endl; dir.clear(); @@ -593,6 +717,8 @@ int do_install(int ac, char const* const* av) " <dir> = Project binary directory to install.\n" " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" " --component <comp> = Component-based install. Only install <comp>.\n" + " --default-directory-permissions <permission> \n" + " Default install permission. Use default permission <permission>.\n" " --prefix <prefix> = The installation prefix CMAKE_INSTALL_PREFIX.\n" " --strip = Performing install/strip.\n" " -v --verbose = Enable verbose output.\n" @@ -633,6 +759,18 @@ int do_install(int ac, char const* const* av) args.emplace_back("-DCMAKE_INSTALL_CONFIG_NAME=" + config); } + if (!defaultDirectoryPermissions.empty()) { + std::string parsedPermissionsVar; + if (!parse_default_directory_permissions(defaultDirectoryPermissions, + parsedPermissionsVar)) { + std::cerr << "--default-directory-permissions is in incorrect format" + << std::endl; + return 1; + } + args.emplace_back("-DCMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS=" + + parsedPermissionsVar); + } + args.emplace_back("-P"); args.emplace_back(dir + "/cmake_install.cmake"); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index de76d73..15d2fd1 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -126,6 +126,7 @@ void CMakeCommandUsage(const char* program) << " touch <file>... - touch a <file>.\n" << " touch_nocreate <file>... - touch a <file> but do not create it.\n" << " create_symlink old new - create a symbolic link new -> old\n" + << " create_hardlink old new - create a hard link new -> old\n" << " true - do nothing with an exit code of 0\n" << " false - do nothing with an exit code of 1\n" #if defined(_WIN32) && !defined(__CYGWIN__) @@ -582,12 +583,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) filesDiffer = cmsys::SystemTools::TextFilesDiffer(args[3], args[4]); } else { ::CMakeCommandUsage(args[0].c_str()); - return 1; + return 2; } if (filesDiffer) { - std::cerr << "Files \"" << args[args.size() - 2] << "\" to \"" - << args[args.size() - 1] << "\" are different.\n"; return 1; } return 0; @@ -602,8 +601,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) } cmsys::ifstream fin(args[3].c_str(), std::ios::in | std::ios::binary); if (!fin) { - std::cerr << "could not open object list file: " << args[3].c_str() - << "\n"; + std::cerr << "could not open object list file: " << args[3] << "\n"; return 1; } std::vector<std::string> files; @@ -626,13 +624,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) } FILE* fout = cmsys::SystemTools::Fopen(args[2], "w+"); if (!fout) { - std::cerr << "could not open output .def file: " << args[2].c_str() - << "\n"; + std::cerr << "could not open output .def file: " << args[2] << "\n"; return 1; } bindexplib deffile; if (args.size() >= 5) { - auto a = args[4]; + std::string const& a = args[4]; if (cmHasLiteralPrefix(a, "--nm=")) { deffile.SetNmPath(a.substr(5)); std::cerr << a.substr(5) << "\n"; @@ -640,7 +637,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) std::cerr << "unknown argument: " << a << "\n"; } } - for (auto const& file : files) { + for (std::string const& file : files) { std::string const& ext = cmSystemTools::GetFilenameLastExtension(file); if (cmSystemTools::LowerCase(ext) == ".def") { if (!deffile.AddDefinitionFile(file.c_str())) { @@ -1022,7 +1019,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) // Command to create a symbolic link. Fails on platforms not // supporting them. if (args[1] == "create_symlink" && args.size() == 4) { - const char* destinationFileName = args[3].c_str(); + std::string const& destinationFileName = args[3]; if ((cmSystemTools::FileExists(destinationFileName) || cmSystemTools::FileIsSymlink(destinationFileName)) && !cmSystemTools::RemoveFile(destinationFileName)) { @@ -1038,6 +1035,34 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 0; } + // Command to create a hard link. Fails on platforms not + // supporting them. + if (args[1] == "create_hardlink" && args.size() == 4) { + const char* SouceFileName = args[2].c_str(); + const char* destinationFileName = args[3].c_str(); + + if (!cmSystemTools::FileExists(SouceFileName)) { + std::cerr << "failed to create hard link because source path '" + << SouceFileName << "' does not exist \n"; + return 1; + } + + if ((cmSystemTools::FileExists(destinationFileName) || + cmSystemTools::FileIsSymlink(destinationFileName)) && + !cmSystemTools::RemoveFile(destinationFileName)) { + std::string emsg = cmSystemTools::GetLastSystemError(); + std::cerr << "failed to create hard link '" << destinationFileName + << "' because existing path cannot be removed: " << emsg + << "\n"; + return 1; + } + + if (!cmSystemTools::CreateLink(args[2], args[3])) { + return 1; + } + return 0; + } + // Command to do nothing with an exit code of 0. if (args[1] == "true") { return 0; @@ -1136,7 +1161,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return cmcmd::ExecuteLinkScript(args); } -#ifndef CMAKE_BOOTSTRAP +#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_NINJA) // Internal CMake ninja dependency scanning support. if (args[1] == "cmake_ninja_depends") { return cmcmd_cmake_ninja_depends(args.begin() + 2, args.end()); @@ -1379,15 +1404,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) #if defined(_WIN32) && !defined(__CYGWIN__) // Write registry value if (args[1] == "write_regv" && args.size() > 3) { - return cmSystemTools::WriteRegistryValue(args[2].c_str(), - args[3].c_str()) - ? 0 - : 1; + return cmSystemTools::WriteRegistryValue(args[2], args[3]) ? 0 : 1; } // Delete registry value if (args[1] == "delete_regv" && args.size() > 2) { - return cmSystemTools::DeleteRegistryValue(args[2].c_str()) ? 0 : 1; + return cmSystemTools::DeleteRegistryValue(args[2]) ? 0 : 1; } // Remove file @@ -1750,7 +1772,7 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args) // args[2] == source_file_path // args[3] == intermediate_file // args[4..n] == preprocess+args - // args[n+1] == -- + // args[n+1] == ++ // args[n+2...] == llvm-rc+args if (args.size() < 3) { std::cerr << "Invalid cmake_llvm_rc arguments"; @@ -1762,7 +1784,11 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args) std::vector<std::string> resource_compile; std::vector<std::string>* pArgTgt = &preprocess; for (std::string const& arg : cmMakeRange(args).advance(4)) { - if (arg == "--") { + // We use ++ as seperator between the preprocessing step definition and the + // rc compilation step becase we need to prepend a -- to seperate the + // source file properly from other options when using clang-cl for + // preprocessing. + if (arg == "++") { pArgTgt = &resource_compile; } else { if (arg.find("SOURCE_DIR") != std::string::npos) { diff --git a/Source/cmcmd.h b/Source/cmcmd.h index 5b6c813..605df23 100644 --- a/Source/cmcmd.h +++ b/Source/cmcmd.h @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmcmd_h -#define cmcmd_h +#pragma once #include "cmConfigure.h" // IWYU pragma: keep @@ -36,5 +35,3 @@ protected: static int RunLLVMRC(std::vector<std::string> const& args); static int VisualStudioLink(std::vector<std::string> const& args, int type); }; - -#endif diff --git a/Source/kwsys/CTestConfig.cmake b/Source/kwsys/CTestConfig.cmake index 33ea84c..12347b6 100644 --- a/Source/kwsys/CTestConfig.cmake +++ b/Source/kwsys/CTestConfig.cmake @@ -3,7 +3,9 @@ set(CTEST_PROJECT_NAME "KWSys") set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -set(CTEST_DROP_METHOD "http") +if (NOT CTEST_DROP_METHOD STREQUAL "https") + set(CTEST_DROP_METHOD "http") +endif () 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/Glob.cxx b/Source/kwsys/Glob.cxx index 5452f73..c6d4b19 100644 --- a/Source/kwsys/Glob.cxx +++ b/Source/kwsys/Glob.cxx @@ -27,7 +27,7 @@ #include <cstdio> #include <cstring> namespace KWSYS_NAMESPACE { -#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__) +#if defined(_WIN32) || defined(__APPLE__) // On Windows and Apple, no difference between lower and upper case # define KWSYS_GLOB_CASE_INDEPENDENT #endif diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in index b5a34d5..e8474e2 100644 --- a/Source/kwsys/Glob.hxx.in +++ b/Source/kwsys/Glob.hxx.in @@ -126,8 +126,8 @@ protected: bool RecurseListDirs; private: - Glob(const Glob&); // Not implemented. - void operator=(const Glob&); // Not implemented. + Glob(const Glob&) = delete; + void operator=(const Glob&) = delete; }; } // namespace @KWSYS_NAMESPACE@ diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index cc45529..e1e7721 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -2128,17 +2128,17 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig, #endif #ifdef SIGABRT case SIGABRT: - KWSYSPE_CASE(Other, "Child aborted"); + KWSYSPE_CASE(Other, "Subprocess aborted"); break; #endif #ifdef SIGKILL case SIGKILL: - KWSYSPE_CASE(Other, "Child killed"); + KWSYSPE_CASE(Other, "Subprocess killed"); break; #endif #ifdef SIGTERM case SIGTERM: - KWSYSPE_CASE(Other, "Child terminated"); + KWSYSPE_CASE(Other, "Subprocess terminated"); break; #endif #ifdef SIGHUP diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index ed1cdc0..9c34a56 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -863,7 +863,7 @@ void SystemInformation::RunMemoryCheck() // Hide implementation details in an anonymous namespace. namespace { // ***************************************************************************** -#if defined(__linux) || defined(__APPLE__) +#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) int LoadLines(FILE* file, std::vector<std::string>& lines) { // Load each line in the given file into a the vector. @@ -893,7 +893,7 @@ int LoadLines(FILE* file, std::vector<std::string>& lines) return nRead; } -# if defined(__linux) +# if defined(__linux) || defined(__CYGWIN__) // ***************************************************************************** int LoadLines(const char* fileName, std::vector<std::string>& lines) { @@ -926,7 +926,7 @@ int NameValue(std::vector<std::string> const& lines, std::string const& name, } #endif -#if defined(__linux) +#if defined(__linux) || defined(__CYGWIN__) // **************************************************************************** template <typename T> int GetFieldsFromFile(const char* fileName, const char** fieldNames, T* values) @@ -3393,7 +3393,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() pos = buffer.find("processor\t", pos + 1); } -#ifdef __linux +#if defined(__linux) || defined(__CYGWIN__) // Count sockets. std::set<int> PhysicalIDs; std::string idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id"); @@ -3414,8 +3414,8 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() this->NumberOfPhysicalCPU = NumberOfCoresPerSocket * (unsigned int)NumberOfSockets; -#else // __CYGWIN__ - // does not have "physical id" entries, neither "cpu cores" +#else + // For systems which do not have "physical id" entries, neither "cpu cores" // this has to be fixed for hyper-threading. std::string cpucount = this->ExtractValueFromCpuInfoFile(buffer, "cpu count"); @@ -3597,7 +3597,7 @@ long long SystemInformationImplementation::GetHostMemoryTotal() GlobalMemoryStatusEx(&statex); return statex.ullTotalPhys / 1024; # endif -#elif defined(__linux) +#elif defined(__linux) || defined(__CYGWIN__) long long memTotal = 0; int ierr = GetFieldFromFile("/proc/meminfo", "MemTotal:", memTotal); if (ierr) { @@ -3712,6 +3712,16 @@ long long SystemInformationImplementation::GetHostMemoryUsed() GlobalMemoryStatusEx(&statex); return (statex.ullTotalPhys - statex.ullAvailPhys) / 1024; # endif +#elif defined(__CYGWIN__) + const char* names[3] = { "MemTotal:", "MemFree:", nullptr }; + long long values[2] = { 0 }; + int ierr = GetFieldsFromFile("/proc/meminfo", names, values); + if (ierr) { + return ierr; + } + long long& memTotal = values[0]; + long long& memFree = values[1]; + return memTotal - memFree; #elif defined(__linux) // First try to use MemAvailable, but it only works on newer kernels const char* names2[3] = { "MemTotal:", "MemAvailable:", nullptr }; @@ -3773,7 +3783,7 @@ long long SystemInformationImplementation::GetProcMemoryUsed() return -2; } return pmc.WorkingSetSize / 1024; -#elif defined(__linux) +#elif defined(__linux) || defined(__CYGWIN__) long long memUsed = 0; int ierr = GetFieldFromFile("/proc/self/status", "VmRSS:", memUsed); if (ierr) { @@ -3850,7 +3860,8 @@ long long SystemInformationImplementation::GetProcessId() #if defined(_WIN32) return GetCurrentProcessId(); #elif defined(__linux) || defined(__APPLE__) || defined(__OpenBSD__) || \ - defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) + defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ + defined(__CYGWIN__) return getpid(); #else return -1; diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 25705ea..6144d9c 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -96,19 +96,12 @@ # if defined(_MSC_VER) && _MSC_VER >= 1800 # define KWSYS_WINDOWS_DEPRECATED_GetVersionEx # endif -#elif defined(__CYGWIN__) -# include <windows.h> -# undef _WIN32 #endif #if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H extern char** environ; #endif -#ifdef __CYGWIN__ -# include <sys/cygwin.h> -#endif - // getpwnam doesn't exist on Windows and Cray Xt3/Catamount // same for TIOCGWINSZ #if defined(_WIN32) || defined(__LIBCATAMOUNT__) || \ @@ -1290,15 +1283,7 @@ bool SystemTools::PathExists(const std::string& path) if (path.empty()) { return false; } -#if defined(__CYGWIN__) - // Convert path to native windows path if possible. - char winpath[MAX_PATH]; - if (SystemTools::PathCygwinToWin32(path.c_str(), winpath)) { - return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES); - } - struct stat st; - return lstat(path.c_str(), &st) == 0; -#elif defined(_WIN32) +#if defined(_WIN32) return (GetFileAttributesW(Encoding::ToWindowsExtendedPath(path).c_str()) != INVALID_FILE_ATTRIBUTES); #else @@ -1320,14 +1305,7 @@ bool SystemTools::FileExists(const std::string& filename) if (filename.empty()) { return false; } -#if defined(__CYGWIN__) - // Convert filename to native windows path if possible. - char winpath[MAX_PATH]; - if (SystemTools::PathCygwinToWin32(filename.c_str(), winpath)) { - return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES); - } - return access(filename.c_str(), R_OK) == 0; -#elif defined(_WIN32) +#if defined(_WIN32) DWORD attr = GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str()); if (attr == INVALID_FILE_ATTRIBUTES) { @@ -1433,27 +1411,9 @@ int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf) #endif } -#ifdef __CYGWIN__ -bool SystemTools::PathCygwinToWin32(const char* path, char* win32_path) -{ - auto itr = SystemToolsStatics->Cyg2Win32Map.find(path); - if (itr != SystemToolsStatics->Cyg2Win32Map.end()) { - strncpy(win32_path, itr->second.c_str(), MAX_PATH); - } else { - if (cygwin_conv_path(CCP_POSIX_TO_WIN_A, path, win32_path, MAX_PATH) != - 0) { - win32_path[0] = 0; - } - SystemToolsStatics->Cyg2Win32Map.insert( - SystemToolsStatic::StringMap::value_type(path, win32_path)); - } - return win32_path[0] != 0; -} -#endif - bool SystemTools::Touch(const std::string& filename, bool create) { - if (!SystemTools::PathExists(filename)) { + if (!SystemTools::FileExists(filename)) { if (create) { FILE* file = Fopen(filename, "a+b"); if (file) { diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 5dbb726..74dc176 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -331,15 +331,6 @@ public: static int Stat(const char* path, Stat_t* buf); static int Stat(const std::string& path, Stat_t* buf); -/** - * Converts Cygwin path to Win32 path. Uses dictionary container for - * caching and calls to cygwin_conv_to_win32_path from Cygwin dll - * for actual translation. Returns true on success, else false. - */ -#ifdef __CYGWIN__ - static bool PathCygwinToWin32(const char* path, char* win32_path); -#endif - /** * Return file length */ diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c index 0c658f5..eed770c 100644 --- a/Source/kwsys/testProcess.c +++ b/Source/kwsys/testProcess.c @@ -450,24 +450,25 @@ static int runChild2(kwsysProcess* kp, const char* cmd[], int state, printf("The process is still executing.\n"); break; case kwsysProcess_State_Expired: - printf("Child was killed when timeout expired.\n"); + printf("Subprocess was killed when timeout expired.\n"); break; case kwsysProcess_State_Exited: - printf("Child exited with value = %d\n", kwsysProcess_GetExitValue(kp)); + printf("Subprocess exited with value = %d\n", + kwsysProcess_GetExitValue(kp)); result = ((exception != kwsysProcess_GetExitException(kp)) || (value != kwsysProcess_GetExitValue(kp))); break; case kwsysProcess_State_Killed: - printf("Child was killed by parent.\n"); + printf("Subprocess was killed by parent.\n"); break; case kwsysProcess_State_Exception: - printf("Child terminated abnormally: %s\n", + printf("Subprocess terminated abnormally: %s\n", kwsysProcess_GetExceptionString(kp)); result = ((exception != kwsysProcess_GetExitException(kp)) || (value != kwsysProcess_GetExitValue(kp))); break; case kwsysProcess_State_Disowned: - printf("Child was disowned.\n"); + printf("Subprocess was disowned.\n"); break; case kwsysProcess_State_Error: printf("Error in administrating child process: [%s]\n", diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 1d34614..cfa420d 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -422,6 +422,28 @@ static bool CheckFileOperations() res = false; } +#if !defined(_WIN32) + std::string const testBadSymlink(testNewDir + "/badSymlink.txt"); + std::string const testBadSymlinkTgt(testNewDir + "/missing/symlinkTgt.txt"); + if (!kwsys::SystemTools::CreateSymlink(testBadSymlinkTgt, testBadSymlink)) { + std::cerr << "Problem with CreateSymlink for: " << testBadSymlink << " -> " + << testBadSymlinkTgt << std::endl; + res = false; + } + + if (!kwsys::SystemTools::Touch(testBadSymlink, false)) { + std::cerr << "Problem with Touch (no create) for: " << testBadSymlink + << std::endl; + res = false; + } +#endif + + if (!kwsys::SystemTools::Touch(testNewDir, false)) { + std::cerr << "Problem with Touch (no create) for: " << testNewDir + << std::endl; + res = false; + } + kwsys::SystemTools::Touch(testNewFile, true); if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) { std::cerr << "Problem with RemoveADirectory for: " << testNewDir |