diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-10-08 09:13:45 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-10-08 09:13:45 +0900 |
commit | fa10a4a91520c9add2283a053dd755a7e5db9f4b (patch) | |
tree | b4c33311cdf36a37e72e3c4bd013e59b42a815f6 /Source | |
parent | 4ca455f44f42bf3257fe1ce752ca7447e9568a27 (diff) | |
download | cmake-fa10a4a91520c9add2283a053dd755a7e5db9f4b.tar.gz cmake-fa10a4a91520c9add2283a053dd755a7e5db9f4b.tar.bz2 cmake-fa10a4a91520c9add2283a053dd755a7e5db9f4b.zip |
Imported Upstream version 3.14.1upstream/3.14.1
Diffstat (limited to 'Source')
548 files changed, 15047 insertions, 12369 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 8aff8f6b2..1c06052fd 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -31,6 +31,16 @@ else() set(CMAKE_USE_ELF_PARSER) endif() +if(NOT CMake_DEFAULT_RECURSION_LIMIT) + if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST}) + set(CMake_DEFAULT_RECURSION_LIMIT 100) + elseif(MINGW) + set(CMake_DEFAULT_RECURSION_LIMIT 400) + else() + set(CMake_DEFAULT_RECURSION_LIMIT 1000) + endif() +endif() + if(APPLE) set(CMAKE_USE_MACH_PARSER 1) endif() @@ -207,6 +217,14 @@ set(SRCS cmExtraKateGenerator.h cmExtraSublimeTextGenerator.cxx cmExtraSublimeTextGenerator.h + cmFileAPI.cxx + cmFileAPI.h + cmFileAPICache.cxx + cmFileAPICache.h + cmFileAPICodemodel.cxx + cmFileAPICodemodel.h + cmFileAPICMakeFiles.cxx + cmFileAPICMakeFiles.h cmFileLock.cxx cmFileLock.h cmFileLockPool.cxx @@ -260,6 +278,8 @@ set(SRCS cmInstallFilesGenerator.cxx cmInstallScriptGenerator.h cmInstallScriptGenerator.cxx + cmInstallSubdirectoryGenerator.h + cmInstallSubdirectoryGenerator.cxx cmInstallTargetGenerator.h cmInstallTargetGenerator.cxx cmInstallDirectoryGenerator.h @@ -288,6 +308,7 @@ set(SRCS cmMakefileExecutableTargetGenerator.cxx cmMakefileLibraryTargetGenerator.cxx cmMakefileUtilityTargetGenerator.cxx + cmMessageType.h cmMessenger.cxx cmMessenger.h cmMSVC60LinkLineComputer.cxx @@ -318,6 +339,8 @@ set(SRCS cmQtAutoGen.h cmQtAutoGenerator.cxx cmQtAutoGenerator.h + cmQtAutoGenGlobalInitializer.cxx + cmQtAutoGenGlobalInitializer.h cmQtAutoGenInitializer.cxx cmQtAutoGenInitializer.h cmQtAutoGeneratorMocUic.cxx @@ -371,6 +394,9 @@ set(SRCS cmXMLWriter.h cmake.cxx cmake.h + cm_string_view.cxx + cm_string_view.hxx + cm_static_string_view.hxx cmCommand.cxx cmCommand.h @@ -562,6 +588,8 @@ set(SRCS cmSiteNameCommand.h cmSourceGroupCommand.cxx cmSourceGroupCommand.h + cmString.cxx + cmString.hxx cmStringReplaceHelper.cxx cmStringCommand.cxx cmStringCommand.h @@ -679,10 +707,10 @@ if (WIN32) cmGlobalVisualStudio12Generator.cxx cmGlobalVisualStudio14Generator.h cmGlobalVisualStudio14Generator.cxx - cmGlobalVisualStudio15Generator.h - cmGlobalVisualStudio15Generator.cxx cmGlobalVisualStudioGenerator.cxx cmGlobalVisualStudioGenerator.h + cmGlobalVisualStudioVersionedGenerator.h + cmGlobalVisualStudioVersionedGenerator.cxx cmIDEFlagTable.h cmIDEOptions.cxx cmIDEOptions.h @@ -810,7 +838,6 @@ target_compile_definitions(CMakeLib PUBLIC ${CLANG_TIDY_DEFINITIONS}) # include_directories( "${CMake_SOURCE_DIR}/Source/CTest" - ${CMAKE_XMLRPC_INCLUDES} ${CMAKE_CURL_INCLUDES} ) # @@ -876,7 +903,7 @@ set(CTEST_SRCS cmCTest.cxx # Build CTestLib add_library(CTestLib ${CTEST_SRCS}) -target_link_libraries(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES} ${CMAKE_XMLRPC_LIBRARIES}) +target_link_libraries(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES}) # # CPack diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index fcd262572..0a264b915 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) -set(CMake_VERSION_MINOR 13) -set(CMake_VERSION_PATCH 5) +set(CMake_VERSION_MINOR 14) +set(CMake_VERSION_PATCH 1) #set(CMake_VERSION_RC 0) diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index 180c92eed..9102e3e20 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -21,9 +21,7 @@ cmCPackIFWGenerator::cmCPackIFWGenerator() this->Generator = this; } -cmCPackIFWGenerator::~cmCPackIFWGenerator() -{ -} +cmCPackIFWGenerator::~cmCPackIFWGenerator() = default; int cmCPackIFWGenerator::PackageFiles() { diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index 8f492afde..01e3ea4a7 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -16,9 +16,7 @@ #include <stddef.h> #include <utility> -cmCPackIFWInstaller::cmCPackIFWInstaller() -{ -} +cmCPackIFWInstaller::cmCPackIFWInstaller() = default; void cmCPackIFWInstaller::printSkippedOptionWarning( const std::string& optionName, const std::string& optionValue) @@ -288,8 +286,7 @@ protected: content = cmSystemTools::TrimWhitespace(content); std::string source = this->basePath + "/" + content; std::string destination = this->path + "/" + content; - if (!cmSystemTools::CopyFileIfDifferent(source.data(), - destination.data())) { + if (!cmSystemTools::CopyFileIfDifferent(source, destination)) { this->hasErrors = true; } } diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index 67e279c6b..a1a52b185 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -24,9 +24,7 @@ cmCPackIFWPackage::CompareStruct::CompareStruct() } //------------------------------------------------------- DependenceStruct --- -cmCPackIFWPackage::DependenceStruct::DependenceStruct() -{ -} +cmCPackIFWPackage::DependenceStruct::DependenceStruct() = default; cmCPackIFWPackage::DependenceStruct::DependenceStruct( const std::string& dependence) @@ -359,7 +357,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) if (this->IsSetToEmpty(option)) { this->DisplayName.clear(); } else if (const char* value = this->GetOption(option)) { - this->ExpandListArgument(value, this->DisplayName); + cmCPackIFWPackage::ExpandListArgument(value, this->DisplayName); } // Description @@ -367,7 +365,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) if (this->IsSetToEmpty(option)) { this->Description.clear(); } else if (const char* value = this->GetOption(option)) { - this->ExpandListArgument(value, this->Description); + cmCPackIFWPackage::ExpandListArgument(value, this->Description); } // Release date diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx index 987cad89e..8042167ed 100644 --- a/Source/CPack/IFW/cmCPackIFWRepository.cxx +++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx @@ -200,7 +200,7 @@ bool cmCPackIFWRepository::PatchUpdatesXml() fout.Close(); - return cmSystemTools::RenameFile(updatesPatchXml.data(), updatesXml.data()); + return cmSystemTools::RenameFile(updatesPatchXml, updatesXml); } void cmCPackIFWRepository::WriteRepositoryConfig(cmXMLWriter& xout) diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx index d3de02b47..4966d09f2 100644 --- a/Source/CPack/OSXScriptLauncher.cxx +++ b/Source/CPack/OSXScriptLauncher.cxx @@ -46,8 +46,7 @@ int main(int argc, char* argv[]) // get the file system path of the url as a cstring // in an encoding suitable for posix apis - if (CFURLGetFileSystemRepresentation(scriptFileURL, true, path, PATH_MAX) == - false) { + if (!CFURLGetFileSystemRepresentation(scriptFileURL, true, path, PATH_MAX)) { DebugError("CFURLGetFileSystemRepresentation failed"); return 1; } diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index 128a04de8..f8c76449b 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -28,20 +28,20 @@ public: ~cmCPackWIXGenerator(); protected: - virtual int InitializeInternal(); + int InitializeInternal() override; - virtual int PackageFiles(); + int PackageFiles() override; - virtual const char* GetOutputExtension() { return ".msi"; } + const char* GetOutputExtension() override { return ".msi"; } - virtual enum CPackSetDestdirSupport SupportsSetDestdir() const + enum CPackSetDestdirSupport SupportsSetDestdir() const override { return SETDESTDIR_UNSUPPORTED; } - virtual bool SupportsAbsoluteDestination() const { return false; } + bool SupportsAbsoluteDestination() const override { return false; } - virtual bool SupportsComponentInstallation() const { return true; } + bool SupportsComponentInstallation() const override { return true; } private: typedef std::map<std::string, std::string> id_map_t; diff --git a/Source/CPack/cmCPack7zGenerator.cxx b/Source/CPack/cmCPack7zGenerator.cxx index f0c41a2a1..741377012 100644 --- a/Source/CPack/cmCPack7zGenerator.cxx +++ b/Source/CPack/cmCPack7zGenerator.cxx @@ -10,6 +10,4 @@ cmCPack7zGenerator::cmCPack7zGenerator() { } -cmCPack7zGenerator::~cmCPack7zGenerator() -{ -} +cmCPack7zGenerator::~cmCPack7zGenerator() = default; diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index ee1070fe5..98fb29d14 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -10,6 +10,7 @@ #include "cmWorkingDirectory.h" #include <cstring> +#include <map> #include <ostream> #include <utility> #include <vector> @@ -21,9 +22,7 @@ cmCPackArchiveGenerator::cmCPackArchiveGenerator(cmArchiveWrite::Compress t, this->ArchiveFormat = format; } -cmCPackArchiveGenerator::~cmCPackArchiveGenerator() -{ -} +cmCPackArchiveGenerator::~cmCPackArchiveGenerator() = default; std::string cmCPackArchiveGenerator::GetArchiveComponentFileName( const std::string& component, bool isGroupName) @@ -111,13 +110,15 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( return 0; \ } \ cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat); \ - if (!(archive)) { \ - cmCPackLogger(cmCPackLog::LOG_ERROR, \ - "Problem to create archive <" \ - << (filename) << ">, ERROR = " << (archive).GetError() \ - << std::endl); \ - return 0; \ - } + do { \ + if (!(archive)) { \ + cmCPackLogger(cmCPackLog::LOG_ERROR, \ + "Problem to create archive <" \ + << (filename) << ">, ERROR = " << (archive).GetError() \ + << std::endl); \ + return 0; \ + } \ + } while (false) int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup) { diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx index f8fd108d3..3a476f44b 100644 --- a/Source/CPack/cmCPackBundleGenerator.cxx +++ b/Source/CPack/cmCPackBundleGenerator.cxx @@ -8,13 +8,9 @@ #include "cmCPackLog.h" #include "cmSystemTools.h" -cmCPackBundleGenerator::cmCPackBundleGenerator() -{ -} +cmCPackBundleGenerator::cmCPackBundleGenerator() = default; -cmCPackBundleGenerator::~cmCPackBundleGenerator() -{ -} +cmCPackBundleGenerator::~cmCPackBundleGenerator() = default; int cmCPackBundleGenerator::InitializeInternal() { diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index ea0ee5815..635de490a 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -23,17 +23,15 @@ namespace { class DebGenerator { public: - DebGenerator(cmCPackLog* logger, std::string const& outputName, - std::string const& workDir, std::string const& topLevelDir, - std::string const& temporaryDir, + DebGenerator(cmCPackLog* logger, std::string outputName, std::string workDir, + std::string topLevelDir, std::string temporaryDir, const char* debianCompressionType, const char* debianArchiveType, - std::map<std::string, std::string> const& controlValues, - bool genShLibs, std::string const& shLibsFilename, - bool genPostInst, std::string const& postInst, bool genPostRm, - std::string const& postRm, const char* controlExtra, - bool permissionStrctPolicy, - std::vector<std::string> const& packageFiles); + std::map<std::string, std::string> controlValues, + bool genShLibs, std::string shLibsFilename, bool genPostInst, + std::string postInst, bool genPostRm, std::string postRm, + const char* controlExtra, bool permissionStrctPolicy, + std::vector<std::string> packageFiles); bool generate() const; @@ -66,31 +64,29 @@ private: }; DebGenerator::DebGenerator( - cmCPackLog* logger, std::string const& outputName, - std::string const& workDir, std::string const& topLevelDir, - std::string const& temporaryDir, const char* debianCompressionType, - const char* debianArchiveType, - std::map<std::string, std::string> const& controlValues, bool genShLibs, - std::string const& shLibsFilename, bool genPostInst, - std::string const& postInst, bool genPostRm, std::string const& postRm, - const char* controlExtra, bool permissionStrictPolicy, - std::vector<std::string> const& packageFiles) + cmCPackLog* logger, std::string outputName, std::string workDir, + std::string topLevelDir, std::string temporaryDir, + const char* debianCompressionType, const char* debianArchiveType, + std::map<std::string, std::string> controlValues, bool genShLibs, + std::string shLibsFilename, bool genPostInst, std::string postInst, + bool genPostRm, std::string postRm, const char* controlExtra, + bool permissionStrictPolicy, std::vector<std::string> packageFiles) : Logger(logger) - , OutputName(outputName) - , WorkDir(workDir) - , TopLevelDir(topLevelDir) - , TemporaryDir(temporaryDir) - , DebianArchiveType(debianArchiveType ? debianArchiveType : "paxr") - , ControlValues(controlValues) + , OutputName(std::move(outputName)) + , WorkDir(std::move(workDir)) + , TopLevelDir(std::move(topLevelDir)) + , TemporaryDir(std::move(temporaryDir)) + , DebianArchiveType(debianArchiveType ? debianArchiveType : "gnutar") + , ControlValues(std::move(controlValues)) , GenShLibs(genShLibs) - , ShLibsFilename(shLibsFilename) + , ShLibsFilename(std::move(shLibsFilename)) , GenPostInst(genPostInst) - , PostInst(postInst) + , PostInst(std::move(postInst)) , GenPostRm(genPostRm) - , PostRm(postRm) + , PostRm(std::move(postRm)) , ControlExtra(controlExtra) , PermissionStrictPolicy(permissionStrictPolicy) - , PackageFiles(packageFiles) + , PackageFiles(std::move(packageFiles)) { if (!debianCompressionType) { debianCompressionType = "gzip"; @@ -436,13 +432,9 @@ bool DebGenerator::generateDeb() const } // end anonymous namespace -cmCPackDebGenerator::cmCPackDebGenerator() -{ -} +cmCPackDebGenerator::cmCPackDebGenerator() = default; -cmCPackDebGenerator::~cmCPackDebGenerator() -{ -} +cmCPackDebGenerator::~cmCPackDebGenerator() = default; int cmCPackDebGenerator::InitializeInternal() { diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 561652305..013ad8163 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -62,17 +62,15 @@ cmCPackDragNDropGenerator::cmCPackDragNDropGenerator() this->componentPackageMethod = ONE_PACKAGE; } -cmCPackDragNDropGenerator::~cmCPackDragNDropGenerator() -{ -} +cmCPackDragNDropGenerator::~cmCPackDragNDropGenerator() = default; int cmCPackDragNDropGenerator::InitializeInternal() { // Starting with Xcode 4.3, look in "/Applications/Xcode.app" first: // std::vector<std::string> paths; - paths.push_back("/Applications/Xcode.app/Contents/Developer/Tools"); - paths.push_back("/Developer/Tools"); + paths.emplace_back("/Applications/Xcode.app/Contents/Developer/Tools"); + paths.emplace_back("/Developer/Tools"); const std::string hdiutil_path = cmSystemTools::FindProgram("hdiutil", std::vector<std::string>(), false); @@ -212,8 +210,7 @@ int cmCPackDragNDropGenerator::PackageFiles() bool cmCPackDragNDropGenerator::CopyFile(std::ostringstream& source, std::ostringstream& target) { - if (!cmSystemTools::CopyFileIfDifferent(source.str().c_str(), - target.str().c_str())) { + if (!cmSystemTools::CopyFileIfDifferent(source.str(), target.str())) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error copying " << source.str() << " to " << target.str() << std::endl); @@ -533,7 +530,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, cmSystemTools::ExpandListArgument(cpack_dmg_languages, languages); } - cmGeneratedFileStream ofs(sla_r.c_str()); + cmGeneratedFileStream ofs(sla_r); ofs << "#include <CoreServices/CoreServices.r>\n\n"; if (oldStyle) { ofs << SLAHeader; diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx index 9f7b236a1..9dc985331 100644 --- a/Source/CPack/cmCPackExternalGenerator.cxx +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -13,6 +13,7 @@ #include "cmsys/FStream.hxx" +#include <map> #include <utility> #include <vector> @@ -67,7 +68,7 @@ int cmCPackExternalGenerator::PackageFiles() return 0; } - int res = this->MakefileMap->ReadListFile(packageScript); + bool res = this->MakefileMap->ReadListFile(packageScript); if (cmSystemTools::GetErrorOccuredFlag() || !res) { return 0; diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index 14334149e..fcf8af1f8 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -17,6 +17,7 @@ #include <pkg.h> #include <algorithm> +#include <utility> cmCPackFreeBSDGenerator::cmCPackFreeBSDGenerator() : cmCPackArchiveGenerator(cmArchiveWrite::CompressXZ, "paxr") @@ -30,9 +31,7 @@ int cmCPackFreeBSDGenerator::InitializeInternal() return this->Superclass::InitializeInternal(); } -cmCPackFreeBSDGenerator::~cmCPackFreeBSDGenerator() -{ -} +cmCPackFreeBSDGenerator::~cmCPackFreeBSDGenerator() = default; // This is a wrapper, for use only in stream-based output, // that will output a string in UCL escaped fashion (in particular, @@ -55,8 +54,7 @@ cmGeneratedFileStream& operator<<(cmGeneratedFileStream& s, const EscapeQuotes& v) { s << '"'; - for (std::string::size_type i = 0; i < v.value.length(); ++i) { - char c = v.value[i]; + for (char c : v.value) { switch (c) { case '\n': s << "\\n"; @@ -98,12 +96,12 @@ class ManifestKey public: std::string key; - ManifestKey(const std::string& k) - : key(k) + ManifestKey(std::string k) + : key(std::move(k)) { } - virtual ~ManifestKey() {} + virtual ~ManifestKey() = default; // Output the value associated with this key to the stream @p s. // Format is to be decided by subclasses. @@ -116,9 +114,9 @@ class ManifestKeyValue : public ManifestKey public: std::string value; - ManifestKeyValue(const std::string& k, const std::string& v) + ManifestKeyValue(const std::string& k, std::string v) : ManifestKey(k) - , value(v) + , value(std::move(v)) { } @@ -148,8 +146,8 @@ public: ManifestKeyListValue& operator<<(const std::vector<std::string>& v) { - for (VList::const_iterator it = v.begin(); it != v.end(); ++it) { - (*this) << (*it); + for (std::string const& e : v) { + (*this) << e; } return *this; } @@ -159,9 +157,9 @@ public: bool with_comma = false; s << '['; - for (VList::const_iterator it = value.begin(); it != value.end(); ++it) { + for (std::string const& elem : value) { s << (with_comma ? ',' : ' '); - s << EscapeQuotes(*it); + s << EscapeQuotes(elem); with_comma = true; } s << " ]"; @@ -182,8 +180,8 @@ public: void write_value(cmGeneratedFileStream& s) const override { s << "{\n"; - for (VList::const_iterator it = value.begin(); it != value.end(); ++it) { - s << " \"" << *it << "\": {\"origin\": \"" << *it << "\"},\n"; + for (std::string const& elem : value) { + s << " \"" << elem << "\": {\"origin\": \"" << elem << "\"},\n"; } s << '}'; } @@ -206,9 +204,8 @@ std::string cmCPackFreeBSDGenerator::var_lookup(const char* var_name) const char* pv = this->GetOption(var_name); if (!pv) { return std::string(); - } else { - return pv; } + return pv; } // Produce UCL in the given @p manifest file for the common @@ -234,7 +231,7 @@ void cmCPackFreeBSDGenerator::write_manifest_fields( cmSystemTools::ExpandListArgument( var_lookup("CPACK_FREEBSD_PACKAGE_LICENSE"), licenses); std::string licenselogic("single"); - if (licenses.size() < 1) { + if (licenses.empty()) { cmSystemTools::SetFatalErrorOccured(); } else if (licenses.size() > 1) { licenselogic = var_lookup("CPACK_FREEBSD_PACKAGE_LICENSE_LOGIC"); @@ -249,7 +246,7 @@ void cmCPackFreeBSDGenerator::write_manifest_fields( std::vector<std::string> deps; cmSystemTools::ExpandListArgument(var_lookup("CPACK_FREEBSD_PACKAGE_DEPS"), deps); - if (deps.size() > 0) { + if (!deps.empty()) { manifest << (ManifestKeyDepsValue("deps") << deps); } } @@ -259,13 +256,8 @@ void cmCPackFreeBSDGenerator::write_manifest_fields( static bool ignore_file(const std::string& filename) { struct stat statbuf; - - if (!((stat(filename.c_str(), &statbuf) >= 0) && - ((statbuf.st_mode & S_IFMT) == S_IFREG))) { - return true; - } - // May be other reasons to return false - return false; + return stat(filename.c_str(), &statbuf) < 0 || + (statbuf.st_mode & S_IFMT) != S_IFREG; } // Write the given list of @p files to the manifest stream @p s, @@ -277,13 +269,9 @@ void write_manifest_files(cmGeneratedFileStream& s, const std::string& toplevel, const std::vector<std::string>& files) { - const char* c_toplevel = toplevel.c_str(); - std::vector<std::string>::const_iterator it; - s << "\"files\": {\n"; - for (it = files.begin(); it != files.end(); ++it) { - s << " \"/" << cmSystemTools::RelativePath(c_toplevel, it->c_str()) - << "\": \"" + for (std::string const& file : files) { + s << " \"/" << cmSystemTools::RelativePath(toplevel, file) << "\": \"" << "<sha256>" << "\",\n"; } @@ -313,7 +301,7 @@ int cmCPackFreeBSDGenerator::PackageFiles() std::string manifestname = toplevel + "/+MANIFEST"; { - cmGeneratedFileStream manifest(manifestname.c_str()); + cmGeneratedFileStream manifest(manifestname); manifest << "{\n"; write_manifest_fields(manifest); write_manifest_files(manifest, toplevel, files); @@ -340,16 +328,15 @@ int cmCPackFreeBSDGenerator::PackageFiles() std::string output_dir = cmSystemTools::CollapseCombinedPath(toplevel, "../"); pkg_create_from_manifest(output_dir.c_str(), ::TXZ, toplevel.c_str(), - manifestname.c_str(), NULL); + manifestname.c_str(), nullptr); std::string broken_suffix = std::string("-") + var_lookup("CPACK_TOPLEVEL_TAG") + std::string(GetOutputExtension()); - for (std::vector<std::string>::iterator it = packageFileNames.begin(); - it != packageFileNames.end(); ++it) { - cmCPackLogger(cmCPackLog::LOG_DEBUG, "Packagefile " << *it << std::endl); - if (has_suffix(*it, broken_suffix)) { - it->replace(it->size() - broken_suffix.size(), std::string::npos, - GetOutputExtension()); + for (std::string& name : packageFileNames) { + cmCPackLogger(cmCPackLog::LOG_DEBUG, "Packagefile " << name << std::endl); + if (has_suffix(name, broken_suffix)) { + name.replace(name.size() - broken_suffix.size(), std::string::npos, + GetOutputExtension()); break; } } diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index acd665095..57c054590 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -18,6 +18,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmStateSnapshot.h" #include "cmVersion.h" #include "cmWorkingDirectory.h" @@ -42,12 +43,6 @@ cmCPackGenerator::~cmCPackGenerator() this->MakefileMap = nullptr; } -void cmCPackGeneratorProgress(const char* msg, float prog, void* ptr) -{ - cmCPackGenerator* self = static_cast<cmCPackGenerator*>(ptr); - self->DisplayVerboseOutput(msg, prog); -} - void cmCPackGenerator::DisplayVerboseOutput(const char* msg, float progress) { (void)progress; @@ -391,8 +386,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( std::move(inFileRelative)); } /* If it is not a symlink then do a plain copy */ - else if (!(cmSystemTools::CopyFileIfDifferent(inFile.c_str(), - filePath.c_str()) && + else if (!(cmSystemTools::CopyFileIfDifferent(inFile, filePath) && cmSystemTools::CopyFileTime(inFile.c_str(), filePath.c_str()))) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -497,7 +491,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript( tempInstallDirectory.c_str()); this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR", tempInstallDirectory.c_str()); - int res = this->MakefileMap->ReadListFile(installScript.c_str()); + bool res = this->MakefileMap->ReadListFile(installScript); if (cmSystemTools::GetErrorOccuredFlag() || !res) { return 0; } @@ -690,12 +684,14 @@ int cmCPackGenerator::InstallCMakeProject( "- Install component: " << component << std::endl); } - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::CPack); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); cm.AddCMakePaths(); - cm.SetProgressCallback(cmCPackGeneratorProgress, this); + cm.SetProgressCallback([this](const char* msg, float prog) { + this->DisplayVerboseOutput(msg, prog); + }); cm.SetTrace(this->Trace); cm.SetTraceExpand(this->TraceExpand); cmGlobalGenerator gg(&cm); @@ -850,7 +846,7 @@ int cmCPackGenerator::InstallCMakeProject( mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1"); } // do installation - int res = mf.ReadListFile(installFile.c_str()); + bool res = mf.ReadListFile(installFile); // 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 @@ -926,7 +922,7 @@ bool cmCPackGenerator::ReadListFile(const char* moduleName) { bool retval; std::string fullPath = this->MakefileMap->GetModulesFile(moduleName); - retval = this->MakefileMap->ReadListFile(fullPath.c_str()); + retval = this->MakefileMap->ReadListFile(fullPath); // include FATAL_ERROR and ERROR in the return status retval = retval && (!cmSystemTools::GetErrorOccuredFlag()); return retval; @@ -1035,7 +1031,8 @@ int cmCPackGenerator::DoPackage() * may update this during PackageFiles. * (either putting several names or updating the provided one) */ - packageFileNames.push_back(tempPackageFileName ? tempPackageFileName : ""); + packageFileNames.emplace_back(tempPackageFileName ? tempPackageFileName + : ""); toplevel = tempDirectory; { // scope that enables package generators to run internal scripts with // latest CMake policies enabled @@ -1075,8 +1072,7 @@ int cmCPackGenerator::DoPackage() << (tempPackageFileName ? tempPackageFileName : "(NULL)") << " to " << (packageFileName ? packageFileName : "(NULL)") << std::endl); - if (!cmSystemTools::CopyFileIfDifferent(tempPackageFileName, - packageFileName)) { + if (!cmSystemTools::CopyFileIfDifferent(pkgFileName, tmpPF)) { cmCPackLogger( cmCPackLog::LOG_ERROR, "Problem copying the package: " diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index f75a750fe..37ea66e76 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -30,9 +30,7 @@ cmCPackNSISGenerator::cmCPackNSISGenerator(bool nsis64) Nsis64 = nsis64; } -cmCPackNSISGenerator::~cmCPackNSISGenerator() -{ -} +cmCPackNSISGenerator::~cmCPackNSISGenerator() = default; int cmCPackNSISGenerator::PackageFiles() { @@ -223,7 +221,8 @@ int cmCPackNSISGenerator::PackageFiles() if (!group.second.Description.empty()) { groupDescriptions += " !insertmacro MUI_DESCRIPTION_TEXT ${" + group.first + "} \"" + - this->TranslateNewlines(group.second.Description) + "\"\n"; + cmCPackNSISGenerator::TranslateNewlines(group.second.Description) + + "\"\n"; } } @@ -253,7 +252,8 @@ int cmCPackNSISGenerator::PackageFiles() if (!comp.second.Description.empty()) { componentDescriptions += " !insertmacro MUI_DESCRIPTION_TEXT ${" + comp.first + "} \"" + - this->TranslateNewlines(comp.second.Description) + "\"\n"; + cmCPackNSISGenerator::TranslateNewlines(comp.second.Description) + + "\"\n"; } } @@ -608,7 +608,7 @@ bool cmCPackNSISGenerator::GetListOfSubdirectories( } } } - dirs.push_back(topdir); + dirs.emplace_back(topdir); return true; } diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx index dab72832c..486633c90 100644 --- a/Source/CPack/cmCPackOSXX11Generator.cxx +++ b/Source/CPack/cmCPackOSXX11Generator.cxx @@ -11,13 +11,9 @@ #include "cmSystemTools.h" #include "cm_sys_stat.h" -cmCPackOSXX11Generator::cmCPackOSXX11Generator() -{ -} +cmCPackOSXX11Generator::cmCPackOSXX11Generator() = default; -cmCPackOSXX11Generator::~cmCPackOSXX11Generator() -{ -} +cmCPackOSXX11Generator::~cmCPackOSXX11Generator() = default; int cmCPackOSXX11Generator::PackageFiles() { @@ -169,7 +165,7 @@ int cmCPackOSXX11Generator::PackageFiles() numTries--; } if (!res || retVal) { - cmGeneratedFileStream ofs(tmpFile.c_str()); + cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << dmgCmd.str() << std::endl << "# Output:" << std::endl << output << std::endl; diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index bdda38660..ae227aab1 100644 --- a/Source/CPack/cmCPackPKGGenerator.cxx +++ b/Source/CPack/cmCPackPKGGenerator.cxx @@ -15,9 +15,7 @@ cmCPackPKGGenerator::cmCPackPKGGenerator() this->componentPackageMethod = ONE_PACKAGE; } -cmCPackPKGGenerator::~cmCPackPKGGenerator() -{ -} +cmCPackPKGGenerator::~cmCPackPKGGenerator() = default; bool cmCPackPKGGenerator::SupportsComponentInstallation() const { @@ -225,7 +223,8 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component, xout.Content(this->GetPackageName(component)); } else { xout.Content("file:./"); - xout.Content(relativePackageLocation); + xout.Content(cmSystemTools::EncodeURL(relativePackageLocation, + /*escapeSlashes=*/false)); } xout.EndElement(); // pkg-ref } diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index 5b1a641a0..246178d8f 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -30,9 +30,7 @@ cmCPackPackageMakerGenerator::cmCPackPackageMakerGenerator() this->PackageCompatibilityVersion = getVersion(10, 4); } -cmCPackPackageMakerGenerator::~cmCPackPackageMakerGenerator() -{ -} +cmCPackPackageMakerGenerator::~cmCPackPackageMakerGenerator() = default; bool cmCPackPackageMakerGenerator::SupportsComponentInstallation() const { @@ -307,7 +305,7 @@ int cmCPackPackageMakerGenerator::PackageFiles() numTries--; } if (!res || retVal) { - cmGeneratedFileStream ofs(tmpFile.c_str()); + cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << dmgCmd.str() << std::endl << "# Output:" << std::endl << output << std::endl; @@ -340,16 +338,16 @@ int cmCPackPackageMakerGenerator::InitializeInternal() // If found, save result in the CPACK_INSTALLER_PROGRAM variable. std::vector<std::string> paths; - paths.push_back("/Applications/Xcode.app/Contents/Applications" - "/PackageMaker.app/Contents/MacOS"); - paths.push_back("/Applications/Utilities" - "/PackageMaker.app/Contents/MacOS"); - paths.push_back("/Applications" - "/PackageMaker.app/Contents/MacOS"); - paths.push_back("/Developer/Applications/Utilities" - "/PackageMaker.app/Contents/MacOS"); - paths.push_back("/Developer/Applications" - "/PackageMaker.app/Contents/MacOS"); + paths.emplace_back("/Applications/Xcode.app/Contents/Applications" + "/PackageMaker.app/Contents/MacOS"); + paths.emplace_back("/Applications/Utilities" + "/PackageMaker.app/Contents/MacOS"); + paths.emplace_back("/Applications" + "/PackageMaker.app/Contents/MacOS"); + paths.emplace_back("/Developer/Applications/Utilities" + "/PackageMaker.app/Contents/MacOS"); + paths.emplace_back("/Developer/Applications" + "/PackageMaker.app/Contents/MacOS"); std::string pkgPath; const char* inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM"); @@ -475,7 +473,7 @@ bool cmCPackPackageMakerGenerator::RunPackageMaker(const char* command, cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running package maker" << std::endl); if (!res || retVal) { - cmGeneratedFileStream ofs(tmpFile.c_str()); + cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << command << std::endl << "# Output:" << std::endl << output << std::endl; diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index 76b32753c..a556e0c52 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -17,9 +17,7 @@ cmCPackProductBuildGenerator::cmCPackProductBuildGenerator() this->componentPackageMethod = ONE_PACKAGE; } -cmCPackProductBuildGenerator::~cmCPackProductBuildGenerator() -{ -} +cmCPackProductBuildGenerator::~cmCPackProductBuildGenerator() = default; int cmCPackProductBuildGenerator::PackageFiles() { @@ -151,7 +149,7 @@ bool cmCPackProductBuildGenerator::RunProductBuild(const std::string& command) this->GeneratorVerbose, cmDuration::zero()); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running command" << std::endl); if (!res || retVal) { - cmGeneratedFileStream ofs(tmpFile.c_str()); + cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << command << std::endl << "# Output:" << std::endl << output << std::endl; diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index 5834829c6..33ab62bdf 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -14,13 +14,9 @@ #include "cmCPackLog.h" #include "cmSystemTools.h" -cmCPackRPMGenerator::cmCPackRPMGenerator() -{ -} +cmCPackRPMGenerator::cmCPackRPMGenerator() = default; -cmCPackRPMGenerator::~cmCPackRPMGenerator() -{ -} +cmCPackRPMGenerator::~cmCPackRPMGenerator() = default; int cmCPackRPMGenerator::InitializeInternal() { diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index ef0d1182c..aba15d239 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -6,19 +6,16 @@ #include <sstream> #include <stdio.h> #include <string> +#include <vector> #include "cmCPackGenerator.h" #include "cmCPackLog.h" #include "cmSystemTools.h" #include "cm_sys_stat.h" -cmCPackSTGZGenerator::cmCPackSTGZGenerator() -{ -} +cmCPackSTGZGenerator::cmCPackSTGZGenerator() = default; -cmCPackSTGZGenerator::~cmCPackSTGZGenerator() -{ -} +cmCPackSTGZGenerator::~cmCPackSTGZGenerator() = default; int cmCPackSTGZGenerator::InitializeInternal() { diff --git a/Source/CPack/cmCPackTGZGenerator.cxx b/Source/CPack/cmCPackTGZGenerator.cxx index eaf8186fe..6f4676ef9 100644 --- a/Source/CPack/cmCPackTGZGenerator.cxx +++ b/Source/CPack/cmCPackTGZGenerator.cxx @@ -10,6 +10,4 @@ cmCPackTGZGenerator::cmCPackTGZGenerator() { } -cmCPackTGZGenerator::~cmCPackTGZGenerator() -{ -} +cmCPackTGZGenerator::~cmCPackTGZGenerator() = default; diff --git a/Source/CPack/cmCPackTXZGenerator.cxx b/Source/CPack/cmCPackTXZGenerator.cxx index e55e903e9..ccbccde95 100644 --- a/Source/CPack/cmCPackTXZGenerator.cxx +++ b/Source/CPack/cmCPackTXZGenerator.cxx @@ -10,6 +10,4 @@ cmCPackTXZGenerator::cmCPackTXZGenerator() { } -cmCPackTXZGenerator::~cmCPackTXZGenerator() -{ -} +cmCPackTXZGenerator::~cmCPackTXZGenerator() = default; diff --git a/Source/CPack/cmCPackTarBZip2Generator.cxx b/Source/CPack/cmCPackTarBZip2Generator.cxx index c7a3dd429..85abeb1ca 100644 --- a/Source/CPack/cmCPackTarBZip2Generator.cxx +++ b/Source/CPack/cmCPackTarBZip2Generator.cxx @@ -10,6 +10,4 @@ cmCPackTarBZip2Generator::cmCPackTarBZip2Generator() { } -cmCPackTarBZip2Generator::~cmCPackTarBZip2Generator() -{ -} +cmCPackTarBZip2Generator::~cmCPackTarBZip2Generator() = default; diff --git a/Source/CPack/cmCPackTarCompressGenerator.cxx b/Source/CPack/cmCPackTarCompressGenerator.cxx index 0a7cd978c..55a6de53c 100644 --- a/Source/CPack/cmCPackTarCompressGenerator.cxx +++ b/Source/CPack/cmCPackTarCompressGenerator.cxx @@ -10,6 +10,4 @@ cmCPackTarCompressGenerator::cmCPackTarCompressGenerator() { } -cmCPackTarCompressGenerator::~cmCPackTarCompressGenerator() -{ -} +cmCPackTarCompressGenerator::~cmCPackTarCompressGenerator() = default; diff --git a/Source/CPack/cmCPackZIPGenerator.cxx b/Source/CPack/cmCPackZIPGenerator.cxx index 6b77c363d..f06494c44 100644 --- a/Source/CPack/cmCPackZIPGenerator.cxx +++ b/Source/CPack/cmCPackZIPGenerator.cxx @@ -10,6 +10,4 @@ cmCPackZIPGenerator::cmCPackZIPGenerator() { } -cmCPackZIPGenerator::~cmCPackZIPGenerator() -{ -} +cmCPackZIPGenerator::~cmCPackZIPGenerator() = default; diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 623cdcd75..0413422b2 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -21,8 +21,10 @@ #include "cmCPackLog.h" #include "cmDocumentation.h" #include "cmDocumentationEntry.h" +#include "cmDocumentationFormatter.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmake.h" @@ -88,12 +90,8 @@ int cpackDefinitionArgument(const char* argument, const char* cValue, return 1; } -static void cpackProgressCallback(const char* message, float progress, - void* clientdata) +static void cpackProgressCallback(const char* message, float /*unused*/) { - (void)progress; - (void)clientdata; - std::cout << "-- " << message << std::endl; } @@ -207,10 +205,10 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Read CPack config file: " << cpackConfigFile << std::endl); - cmake cminst(cmake::RoleScript); + cmake cminst(cmake::RoleScript, cmState::CPack); cminst.SetHomeDirectory(""); cminst.SetHomeOutputDirectory(""); - cminst.SetProgressCallback(cpackProgressCallback, nullptr); + cminst.SetProgressCallback(cpackProgressCallback); cminst.GetCurrentSnapshot().SetDefaultDefinitions(); cmGlobalGenerator cmgg(&cminst); cmMakefile globalMF(&cmgg, cminst.GetCurrentSnapshot()); @@ -254,7 +252,7 @@ int main(int argc, char const* const* argv) // paths, so FIND_XXX() commands can be used in scripts std::string systemFile = globalMF.GetModulesFile("CMakeDetermineSystem.cmake"); - if (!globalMF.ReadListFile(systemFile.c_str())) { + if (!globalMF.ReadListFile(systemFile)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Error reading CMakeDetermineSystem.cmake" << std::endl); return 1; @@ -262,7 +260,7 @@ int main(int argc, char const* const* argv) systemFile = globalMF.GetModulesFile("CMakeSystemSpecificInformation.cmake"); - if (!globalMF.ReadListFile(systemFile.c_str())) { + if (!globalMF.ReadListFile(systemFile)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Error reading CMakeSystemSpecificInformation.cmake" << std::endl); @@ -278,7 +276,7 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Read CPack configuration file: " << cpackConfigFile << std::endl); - if (!globalMF.ReadListFile(cpackConfigFile.c_str())) { + if (!globalMF.ReadListFile(cpackConfigFile)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Problem reading CPack config file: \"" << cpackConfigFile << "\"" << std::endl); @@ -368,8 +366,21 @@ int main(int argc, char const* const* argv) cpackGenerator->SetTraceExpand(traceExpand); } else { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "Cannot initialize CPack generator: " << gen - << std::endl); + "Could not create CPack generator: " << gen + << std::endl); + // Print out all the valid generators + cmDocumentation generatorDocs; + std::vector<cmDocumentationEntry> v; + for (auto const& g : generators.GetGeneratorsList()) { + cmDocumentationEntry e; + e.Name = g.first; + e.Brief = g.second; + v.push_back(std::move(e)); + } + generatorDocs.SetSection("Generators", v); + std::cerr << "\n"; + generatorDocs.PrintDocumentation(cmDocumentation::ListGenerators, + std::cerr); parsed = 0; } diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index 365f26774..b154caf30 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -77,9 +77,7 @@ cmCTestBZR::cmCTestBZR(cmCTest* ct, std::ostream& log) cmSystemTools::PutEnv("BZR_PROGRESS_BAR=none"); } -cmCTestBZR::~cmCTestBZR() -{ -} +cmCTestBZR::~cmCTestBZR() = default; class cmCTestBZR::InfoParser : public cmCTestVC::LineParser { diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 668a3871d..2fd4c7ab3 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -6,6 +6,7 @@ #include "cmCTestTestHandler.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" #include "cmake.h" @@ -108,27 +109,6 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, return 0; } -void CMakeMessageCallback(const char* m, const char* /*unused*/, - bool& /*unused*/, void* s) -{ - std::string* out = static_cast<std::string*>(s); - *out += m; - *out += "\n"; -} - -void CMakeProgressCallback(const char* msg, float /*unused*/, void* s) -{ - std::string* out = static_cast<std::string*>(s); - *out += msg; - *out += "\n"; -} - -void CMakeOutputCallback(const char* m, size_t len, void* s) -{ - std::string* out = static_cast<std::string*>(s); - out->append(m, len); -} - class cmCTestBuildAndTestCaptureRAII { cmake& CM; @@ -137,17 +117,27 @@ public: cmCTestBuildAndTestCaptureRAII(cmake& cm, std::string& s) : CM(cm) { - cmSystemTools::SetMessageCallback(CMakeMessageCallback, &s); - cmSystemTools::SetStdoutCallback(CMakeOutputCallback, &s); - cmSystemTools::SetStderrCallback(CMakeOutputCallback, &s); - this->CM.SetProgressCallback(CMakeProgressCallback, &s); + cmSystemTools::SetMessageCallback( + [&s](const char* msg, const char* /*unused*/) { + s += msg; + s += "\n"; + }); + + cmSystemTools::SetStdoutCallback([&s](std::string const& m) { s += m; }); + cmSystemTools::SetStderrCallback([&s](std::string const& m) { s += m; }); + + this->CM.SetProgressCallback([&s](const char* msg, float /*unused*/) { + s += msg; + s += "\n"; + }); } + ~cmCTestBuildAndTestCaptureRAII() { - this->CM.SetProgressCallback(nullptr, nullptr); - cmSystemTools::SetStderrCallback(nullptr, nullptr); - cmSystemTools::SetStdoutCallback(nullptr, nullptr); - cmSystemTools::SetMessageCallback(nullptr, nullptr); + this->CM.SetProgressCallback(nullptr); + cmSystemTools::SetStderrCallback(nullptr); + cmSystemTools::SetStdoutCallback(nullptr); + cmSystemTools::SetMessageCallback(nullptr); } }; @@ -163,7 +153,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) return 1; } - cmake cm(cmake::RoleProject); + cmake cm(cmake::RoleProject, cmState::Project); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); std::string cmakeOutString; @@ -231,7 +221,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) // do the build if (this->BuildTargets.empty()) { - this->BuildTargets.push_back(""); + this->BuildTargets.emplace_back(); } for (std::string const& tar : this->BuildTargets) { cmDuration remainingTime = std::chrono::seconds(0); diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index ce27da18a..32f7496a9 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -7,6 +7,7 @@ #include "cmCTestGenericHandler.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmake.h" @@ -53,10 +54,6 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() } else { const char* cmakeGeneratorName = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR"); - const char* cmakeProjectName = - (this->Values[ctb_PROJECT_NAME] && *this->Values[ctb_PROJECT_NAME]) - ? this->Values[ctb_PROJECT_NAME] - : this->Makefile->GetDefinition("CTEST_PROJECT_NAME"); // Build configuration is determined by: CONFIGURATION argument, // or CTEST_BUILD_CONFIGURATION script variable, or @@ -81,8 +78,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() ? this->Values[ctb_TARGET] : this->Makefile->GetDefinition("CTEST_BUILD_TARGET"); - if (cmakeGeneratorName && *cmakeGeneratorName && cmakeProjectName && - *cmakeProjectName) { + if (cmakeGeneratorName && *cmakeGeneratorName) { if (!cmakeBuildConfiguration) { cmakeBuildConfiguration = "Release"; } @@ -100,7 +96,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() std::string e = "could not create generator named \""; e += cmakeGeneratorName; e += "\""; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); cmSystemTools::SetFatalErrorOccured(); return nullptr; } @@ -132,14 +128,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() /* clang-format off */ ostr << "has no project to build. If this is a " "\"built with CMake\" project, verify that CTEST_CMAKE_GENERATOR " - "and CTEST_PROJECT_NAME are set." - "\n" - "CTEST_PROJECT_NAME is usually set in CTestConfig.cmake. Verify " - "that CTestConfig.cmake exists, or CTEST_PROJECT_NAME " - "is set in the script, or PROJECT_NAME is passed as an argument " - "to ctest_build." - "\n" - "Alternatively, set CTEST_BUILD_COMMAND to build the project " + "is set. Otherwise, set CTEST_BUILD_COMMAND to build the project " "with a custom command line."; /* clang-format on */ this->SetError(ostr.str()); diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index a8309d94a..d934c003c 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -341,30 +341,34 @@ int cmCTestBuildHandler::ProcessHandler() // warnings and warning exceptions. std::vector<std::string>::size_type cc; for (cc = 0; cmCTestErrorMatches[cc]; cc++) { - this->CustomErrorMatches.push_back(cmCTestErrorMatches[cc]); + this->CustomErrorMatches.emplace_back(cmCTestErrorMatches[cc]); } for (cc = 0; cmCTestErrorExceptions[cc]; cc++) { - this->CustomErrorExceptions.push_back(cmCTestErrorExceptions[cc]); + this->CustomErrorExceptions.emplace_back(cmCTestErrorExceptions[cc]); } for (cc = 0; cmCTestWarningMatches[cc]; cc++) { - this->CustomWarningMatches.push_back(cmCTestWarningMatches[cc]); + this->CustomWarningMatches.emplace_back(cmCTestWarningMatches[cc]); } for (cc = 0; cmCTestWarningExceptions[cc]; cc++) { - this->CustomWarningExceptions.push_back(cmCTestWarningExceptions[cc]); + this->CustomWarningExceptions.emplace_back(cmCTestWarningExceptions[cc]); } // Pre-compile regular expressions objects for all regular expressions #define cmCTestBuildHandlerPopulateRegexVector(strings, regexes) \ - regexes.clear(); \ - cmCTestOptionalLog(this->CTest, DEBUG, \ - this << "Add " #regexes << std::endl, this->Quiet); \ - for (std::string const& s : (strings)) { \ + do { \ + regexes.clear(); \ cmCTestOptionalLog(this->CTest, DEBUG, \ - "Add " #strings ": " << s << std::endl, this->Quiet); \ - (regexes).push_back(s.c_str()); \ - } + this << "Add " #regexes << std::endl, this->Quiet); \ + for (std::string const& s : (strings)) { \ + cmCTestOptionalLog(this->CTest, DEBUG, \ + "Add " #strings ": " << s << std::endl, \ + this->Quiet); \ + (regexes).emplace_back(s); \ + } \ + } while (false) + cmCTestBuildHandlerPopulateRegexVector(this->CustomErrorMatches, this->ErrorMatchRegex); cmCTestBuildHandlerPopulateRegexVector(this->CustomErrorExceptions, @@ -503,24 +507,20 @@ public: : FTC(ftc) { } - FragmentCompare() - : FTC(nullptr) - { - } + FragmentCompare() = default; bool operator()(std::string const& l, std::string const& r) const { // Order files by modification time. Use lexicographic order // among files with the same time. int result; - if (this->FTC->FileTimeCompare(l.c_str(), r.c_str(), &result) && - result != 0) { + if (this->FTC->FileTimeCompare(l, r, &result) && result != 0) { return result < 0; } return l < r; } private: - cmFileTimeComparison* FTC; + cmFileTimeComparison* FTC = nullptr; }; void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml) @@ -1033,7 +1033,7 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length, } } else { // Otherwise store pre-context for the next error - this->PreContext.push_back(line); + this->PreContext.emplace_back(line); if (this->PreContext.size() > this->MaxPreContext) { this->PreContext.erase(this->PreContext.begin(), this->PreContext.end() - diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx index 4fb3273bb..6e8f73f83 100644 --- a/Source/CTest/cmCTestCVS.cxx +++ b/Source/CTest/cmCTestCVS.cxx @@ -16,9 +16,7 @@ cmCTestCVS::cmCTestCVS(cmCTest* ct, std::ostream& log) { } -cmCTestCVS::~cmCTestCVS() -{ -} +cmCTestCVS::~cmCTestCVS() = default; class cmCTestCVS::UpdateParser : public cmCTestVC::LineParser { @@ -111,8 +109,8 @@ public: , Revisions(revs) , Section(SectionHeader) { - this->SetLog(&cvs->Log, prefix), - this->RegexRevision.compile("^revision +([^ ]*) *$"); + this->SetLog(&cvs->Log, prefix); + this->RegexRevision.compile("^revision +([^ ]*) *$"); this->RegexBranches.compile("^branches: .*$"); this->RegexPerson.compile("^date: +([^;]+); +author: +([^;]+);"); } diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx index 5967b7458..6b7601b6e 100644 --- a/Source/CTest/cmCTestConfigureHandler.cxx +++ b/Source/CTest/cmCTestConfigureHandler.cxx @@ -11,9 +11,7 @@ #include <ostream> #include <string> -cmCTestConfigureHandler::cmCTestConfigureHandler() -{ -} +cmCTestConfigureHandler::cmCTestConfigureHandler() = default; void cmCTestConfigureHandler::Initialize() { diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 1d9a5f7e0..225383ce0 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -15,7 +15,6 @@ #include "cmSystemTools.h" #include "cmWorkingDirectory.h" #include "cmXMLWriter.h" -#include "cmake.h" #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" @@ -56,13 +55,12 @@ public: void SetCommand(const char* command) { this->CommandLineStrings.clear(); - this->CommandLineStrings.push_back(command); - ; + this->CommandLineStrings.emplace_back(command); } void AddArgument(const char* arg) { if (arg) { - this->CommandLineStrings.push_back(arg); + this->CommandLineStrings.emplace_back(arg); } } void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; } @@ -113,9 +111,7 @@ private: cmDuration TimeOut; }; -cmCTestCoverageHandler::cmCTestCoverageHandler() -{ -} +cmCTestCoverageHandler::cmCTestCoverageHandler() = default; void cmCTestCoverageHandler::Initialize() { @@ -317,8 +313,7 @@ int cmCTestCoverageHandler::ProcessHandler() // setup the regex exclude stuff this->CustomCoverageExcludeRegex.clear(); for (std::string const& rex : this->CustomCoverageExclude) { - this->CustomCoverageExcludeRegex.push_back( - cmsys::RegularExpression(rex.c_str())); + this->CustomCoverageExcludeRegex.emplace_back(rex); } if (this->HandleBullseyeCoverage(&cont)) { @@ -1006,7 +1001,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( std::vector<std::string> basecovargs = cmSystemTools::ParseArguments(gcovExtraFlags.c_str()); basecovargs.insert(basecovargs.begin(), gcovCommand); - basecovargs.push_back("-o"); + basecovargs.emplace_back("-o"); // files is a list of *.da and *.gcda files with coverage data in them. // These are binary files that you give as input to gcov so that it will @@ -2228,7 +2223,7 @@ int cmCTestCoverageHandler::GetLabelId(std::string const& label) void cmCTestCoverageHandler::LoadLabels() { std::string fileList = this->CTest->GetBinaryDir(); - fileList += cmake::GetCMakeFilesDirectory(); + fileList += "/CMakeFiles"; fileList += "/TargetDirectories.txt"; cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " target directory list [" << fileList << "]\n", diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 71fcafb58..210abe55b 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -31,9 +31,7 @@ cmCTestGIT::cmCTestGIT(cmCTest* ct, std::ostream& log) this->CurrentGitVersion = 0; } -cmCTestGIT::~cmCTestGIT() -{ -} +cmCTestGIT::~cmCTestGIT() = default; class cmCTestGIT::OneLineParser : public cmCTestVC::LineParser { @@ -475,15 +473,8 @@ private: { std::string Name; std::string EMail; - unsigned long Time; - long TimeZone; - Person() - : Name() - , EMail() - , Time(0) - , TimeZone(0) - { - } + unsigned long Time = 0; + long TimeZone = 0; }; void ParsePerson(const char* str, Person& person) @@ -618,8 +609,8 @@ bool cmCTestGIT::LoadRevisions() git, "diff-tree", "--stdin", "--always", "-z", "-r", "--pretty=raw", "--encoding=utf-8", nullptr }; - this->Log << this->ComputeCommandLine(git_rev_list) << " | " - << this->ComputeCommandLine(git_diff_tree) << "\n"; + this->Log << cmCTestGIT::ComputeCommandLine(git_rev_list) << " | " + << cmCTestGIT::ComputeCommandLine(git_diff_tree) << "\n"; cmsysProcess* cp = cmsysProcess_New(); cmsysProcess_AddCommand(cp, git_rev_list); @@ -628,7 +619,7 @@ bool cmCTestGIT::LoadRevisions() CommitParser out(this, "dt-out> "); OutputLogger err(this->Log, "dt-err> "); - this->RunProcess(cp, &out, &err, cmProcessOutput::UTF8); + cmCTestGIT::RunProcess(cp, &out, &err, cmProcessOutput::UTF8); // Send one extra zero-byte to terminate the last record. out.Process("", 1); diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index dc1bba051..d3020b513 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -18,9 +18,7 @@ cmCTestGenericHandler::cmCTestGenericHandler() this->TestLoad = 0; } -cmCTestGenericHandler::~cmCTestGenericHandler() -{ -} +cmCTestGenericHandler::~cmCTestGenericHandler() = default; void cmCTestGenericHandler::SetOption(const std::string& op, const char* value) { diff --git a/Source/CTest/cmCTestGlobalVC.cxx b/Source/CTest/cmCTestGlobalVC.cxx index d2714d90b..a2d4d2c75 100644 --- a/Source/CTest/cmCTestGlobalVC.cxx +++ b/Source/CTest/cmCTestGlobalVC.cxx @@ -15,9 +15,7 @@ cmCTestGlobalVC::cmCTestGlobalVC(cmCTest* ct, std::ostream& log) this->PriorRev = this->Unknown; } -cmCTestGlobalVC::~cmCTestGlobalVC() -{ -} +cmCTestGlobalVC::~cmCTestGlobalVC() = default; const char* cmCTestGlobalVC::LocalPath(std::string const& path) { diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx index c3c5da460..6fb99d864 100644 --- a/Source/CTest/cmCTestHG.cxx +++ b/Source/CTest/cmCTestHG.cxx @@ -18,9 +18,7 @@ cmCTestHG::cmCTestHG(cmCTest* ct, std::ostream& log) this->PriorRev = this->Unknown; } -cmCTestHG::~cmCTestHG() -{ -} +cmCTestHG::~cmCTestHG() = default; class cmCTestHG::IdentifyParser : public cmCTestVC::LineParser { @@ -194,7 +192,8 @@ private: this->CData.clear(); if (name == "logentry") { this->Rev = Revision(); - if (const char* rev = this->FindAttribute(atts, "revision")) { + if (const char* rev = + cmCTestHG::LogParser::FindAttribute(atts, "revision")) { this->Rev.Rev = rev; } this->Changes.clear(); diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 667a8bad3..57a14efd1 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -5,9 +5,9 @@ #include "cmCTest.h" #include "cmCTestGenericHandler.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" -#include "cmake.h" #include <cstring> #include <sstream> @@ -206,18 +206,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, handler->PopulateCustomVectors(this->Makefile); if (this->Values[ct_SUBMIT_INDEX]) { - if (!this->CTest->GetDropSiteCDash() && - this->CTest->GetDartVersion() <= 1) { - cmCTestLog( - this->CTest, ERROR_MESSAGE, - "Dart before version 2.0 does not support collecting submissions." - << std::endl - << "Please upgrade the server to Dart 2 or higher, or do not use " - "SUBMIT_INDEX." - << std::endl); - } else { - handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX])); - } + handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX])); } cmWorkingDirectory workdir( this->CTest->GetCTestConfiguration("BuildDirectory")); @@ -300,7 +289,7 @@ bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg) if (this->Values[k]) { std::ostringstream e; e << "Called with more than one value for " << this->Arguments[k]; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); this->ArgumentDoing = ArgumentDoingError; return true; } diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 6cd1c09c6..5e66e056a 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -15,6 +15,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmProcessOutput.h" +#include "cmState.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -145,7 +146,7 @@ void cmCTestLaunch::HandleRealArg(const char* arg) return; } #endif - this->RealArgs.push_back(arg); + this->RealArgs.emplace_back(arg); } void cmCTestLaunch::ComputeFileNames() @@ -282,7 +283,7 @@ void cmCTestLaunch::LoadLabels() // Labels are listed in per-target files. std::string fname = this->OptionBuildDir; - fname += cmake::GetCMakeFilesDirectory(); + fname += "/CMakeFiles"; fname += "/"; fname += this->OptionTargetName; fname += ".dir/Labels.txt"; @@ -533,9 +534,9 @@ void cmCTestLaunch::LoadScrapeRules() // Common compiler warning formats. These are much simpler than the // full log-scraping expressions because we do not need to extract // file and line information. - this->RegexWarning.push_back("(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]"); - this->RegexWarning.push_back("(^|[ :])[Rr][Ee][Mm][Aa][Rr][Kk]"); - this->RegexWarning.push_back("(^|[ :])[Nn][Oo][Tt][Ee]"); + this->RegexWarning.emplace_back("(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]"); + this->RegexWarning.emplace_back("(^|[ :])[Rr][Ee][Mm][Aa][Rr][Kk]"); + this->RegexWarning.emplace_back("(^|[ :])[Nn][Oo][Tt][Ee]"); // Load custom match rules given to us by CTest. this->LoadScrapeRules("Warning", this->RegexWarning); @@ -610,7 +611,7 @@ int cmCTestLaunch::Main(int argc, const char* const argv[]) void cmCTestLaunch::LoadConfig() { - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::CTest); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -618,7 +619,7 @@ void cmCTestLaunch::LoadConfig() cmMakefile mf(&gg, cm.GetCurrentSnapshot()); std::string fname = this->LogDir; fname += "CTestLaunchConfig.cmake"; - if (cmSystemTools::FileExists(fname) && mf.ReadListFile(fname.c_str())) { + if (cmSystemTools::FileExists(fname) && mf.ReadListFile(fname)) { this->SourceDir = mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY"); cmSystemTools::ConvertToUnixSlashes(this->SourceDir); } diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 9c9532a08..8ba59d3f9 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -261,8 +261,8 @@ void cmCTestMemCheckHandler::InitializeResultsVectors() }; this->GlobalResults.clear(); for (int i = 0; cmCTestMemCheckResultStrings[i] != nullptr; ++i) { - this->ResultStrings.push_back(cmCTestMemCheckResultStrings[i]); - this->ResultStringsLong.push_back(cmCTestMemCheckResultLongStrings[i]); + this->ResultStrings.emplace_back(cmCTestMemCheckResultStrings[i]); + this->ResultStringsLong.emplace_back(cmCTestMemCheckResultLongStrings[i]); this->GlobalResults.push_back(0); } } @@ -528,11 +528,11 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() switch (this->MemoryTesterStyle) { case cmCTestMemCheckHandler::VALGRIND: { if (this->MemoryTesterOptions.empty()) { - this->MemoryTesterOptions.push_back("-q"); - this->MemoryTesterOptions.push_back("--tool=memcheck"); - this->MemoryTesterOptions.push_back("--leak-check=yes"); - this->MemoryTesterOptions.push_back("--show-reachable=yes"); - this->MemoryTesterOptions.push_back("--num-callers=50"); + this->MemoryTesterOptions.emplace_back("-q"); + this->MemoryTesterOptions.emplace_back("--tool=memcheck"); + this->MemoryTesterOptions.emplace_back("--leak-check=yes"); + this->MemoryTesterOptions.emplace_back("--show-reachable=yes"); + this->MemoryTesterOptions.emplace_back("--num-callers=50"); } if (!this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile") .empty()) { @@ -586,11 +586,11 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() std::string dpbdFile = this->CTest->GetBinaryDir() + "/Testing/Temporary/MemoryChecker.??.DPbd"; this->BoundsCheckerDPBDFile = dpbdFile; - this->MemoryTesterDynamicOptions.push_back("/B"); + this->MemoryTesterDynamicOptions.emplace_back("/B"); this->MemoryTesterDynamicOptions.push_back(std::move(dpbdFile)); - this->MemoryTesterDynamicOptions.push_back("/X"); + this->MemoryTesterDynamicOptions.emplace_back("/X"); this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile); - this->MemoryTesterOptions.push_back("/M"); + this->MemoryTesterOptions.emplace_back("/M"); break; } // these are almost the same but the env var used is different @@ -604,8 +604,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() // The MemoryTesterDynamicOptions is setup with the -E env // Then the MemoryTesterEnvironmentVariable gets the // TSAN_OPTIONS string with the log_path in it. - this->MemoryTesterDynamicOptions.push_back("-E"); - this->MemoryTesterDynamicOptions.push_back("env"); + this->MemoryTesterDynamicOptions.emplace_back("-E"); + this->MemoryTesterDynamicOptions.emplace_back("env"); std::string envVar; std::string extraOptions; std::string suppressionsOption; diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index f0260018e..756ac6cf6 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -6,9 +6,13 @@ #include "cmCTest.h" #include "cmCTestRunTest.h" #include "cmCTestTestHandler.h" +#include "cmDuration.h" +#include "cmListFileCache.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" #include "cm_uv.h" #include "cmUVSignalHackRAII.h" // IWYU pragma: keep @@ -20,13 +24,19 @@ #include <chrono> #include <cstring> #include <iomanip> +#include <iostream> #include <list> #include <math.h> #include <sstream> #include <stack> #include <stdlib.h> +#include <unordered_map> #include <utility> +namespace cmsys { +class RegularExpression; +} + class TestComparator { public: @@ -34,7 +44,6 @@ public: : Handler(handler) { } - ~TestComparator() {} // Sorts tests in descending order of cost bool operator()(int index1, int index2) const @@ -60,9 +69,7 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler() this->SerialTestRunning = false; } -cmCTestMultiProcessHandler::~cmCTestMultiProcessHandler() -{ -} +cmCTestMultiProcessHandler::~cmCTestMultiProcessHandler() = default; // Set the tests void cmCTestMultiProcessHandler::SetTests(TestMap& tests, @@ -528,7 +535,7 @@ void cmCTestMultiProcessHandler::UpdateCostData() fout << f << "\n"; } fout.close(); - cmSystemTools::RenameFile(tmpout.c_str(), fname.c_str()); + cmSystemTools::RenameFile(tmpout, fname); } void cmCTestMultiProcessHandler::ReadCostData() @@ -725,9 +732,335 @@ void cmCTestMultiProcessHandler::MarkFinished() cmSystemTools::RemoveFile(fname); } +static Json::Value DumpToJsonArray(const std::set<std::string>& values) +{ + Json::Value jsonArray = Json::arrayValue; + for (auto& it : values) { + jsonArray.append(it); + } + return jsonArray; +} + +static Json::Value DumpToJsonArray(const std::vector<std::string>& values) +{ + Json::Value jsonArray = Json::arrayValue; + for (auto& it : values) { + jsonArray.append(it); + } + return jsonArray; +} + +static Json::Value DumpRegExToJsonArray( + const std::vector<std::pair<cmsys::RegularExpression, std::string>>& values) +{ + Json::Value jsonArray = Json::arrayValue; + for (auto& it : values) { + jsonArray.append(it.second); + } + return jsonArray; +} + +static Json::Value DumpMeasurementToJsonArray( + const std::map<std::string, std::string>& values) +{ + Json::Value jsonArray = Json::arrayValue; + for (auto& it : values) { + Json::Value measurement = Json::objectValue; + measurement["measurement"] = it.first; + measurement["value"] = it.second; + jsonArray.append(measurement); + } + return jsonArray; +} + +static Json::Value DumpTimeoutAfterMatch( + cmCTestTestHandler::cmCTestTestProperties& testProperties) +{ + Json::Value timeoutAfterMatch = Json::objectValue; + timeoutAfterMatch["timeout"] = testProperties.AlternateTimeout.count(); + timeoutAfterMatch["regex"] = + DumpRegExToJsonArray(testProperties.TimeoutRegularExpressions); + return timeoutAfterMatch; +} + +static Json::Value DumpCTestProperty(std::string const& name, + Json::Value value) +{ + Json::Value property = Json::objectValue; + property["name"] = name; + property["value"] = std::move(value); + return property; +} + +static Json::Value DumpCTestProperties( + cmCTestTestHandler::cmCTestTestProperties& testProperties) +{ + Json::Value properties = Json::arrayValue; + if (!testProperties.AttachOnFail.empty()) { + properties.append(DumpCTestProperty( + "ATTACHED_FILES_ON_FAIL", DumpToJsonArray(testProperties.AttachOnFail))); + } + if (!testProperties.AttachedFiles.empty()) { + properties.append(DumpCTestProperty( + "ATTACHED_FILES", DumpToJsonArray(testProperties.AttachedFiles))); + } + if (testProperties.Cost != 0.0f) { + properties.append( + DumpCTestProperty("COST", static_cast<double>(testProperties.Cost))); + } + if (!testProperties.Depends.empty()) { + properties.append( + DumpCTestProperty("DEPENDS", DumpToJsonArray(testProperties.Depends))); + } + if (testProperties.Disabled) { + properties.append(DumpCTestProperty("DISABLED", testProperties.Disabled)); + } + if (!testProperties.Environment.empty()) { + properties.append(DumpCTestProperty( + "ENVIRONMENT", DumpToJsonArray(testProperties.Environment))); + } + if (!testProperties.ErrorRegularExpressions.empty()) { + properties.append(DumpCTestProperty( + "FAIL_REGULAR_EXPRESSION", + DumpRegExToJsonArray(testProperties.ErrorRegularExpressions))); + } + if (!testProperties.FixturesCleanup.empty()) { + properties.append(DumpCTestProperty( + "FIXTURES_CLEANUP", DumpToJsonArray(testProperties.FixturesCleanup))); + } + if (!testProperties.FixturesRequired.empty()) { + properties.append(DumpCTestProperty( + "FIXTURES_REQUIRED", DumpToJsonArray(testProperties.FixturesRequired))); + } + if (!testProperties.FixturesSetup.empty()) { + properties.append(DumpCTestProperty( + "FIXTURES_SETUP", DumpToJsonArray(testProperties.FixturesSetup))); + } + if (!testProperties.Labels.empty()) { + properties.append( + DumpCTestProperty("LABELS", DumpToJsonArray(testProperties.Labels))); + } + if (!testProperties.Measurements.empty()) { + properties.append(DumpCTestProperty( + "MEASUREMENT", DumpMeasurementToJsonArray(testProperties.Measurements))); + } + if (!testProperties.RequiredRegularExpressions.empty()) { + properties.append(DumpCTestProperty( + "PASS_REGULAR_EXPRESSION", + DumpRegExToJsonArray(testProperties.RequiredRegularExpressions))); + } + if (testProperties.WantAffinity) { + properties.append( + DumpCTestProperty("PROCESSOR_AFFINITY", testProperties.WantAffinity)); + } + if (testProperties.Processors != 1) { + properties.append( + DumpCTestProperty("PROCESSORS", testProperties.Processors)); + } + if (!testProperties.RequiredFiles.empty()) { + properties["REQUIRED_FILES"] = + DumpToJsonArray(testProperties.RequiredFiles); + } + if (!testProperties.LockedResources.empty()) { + properties.append(DumpCTestProperty( + "RESOURCE_LOCK", DumpToJsonArray(testProperties.LockedResources))); + } + if (testProperties.RunSerial) { + properties.append( + DumpCTestProperty("RUN_SERIAL", testProperties.RunSerial)); + } + if (testProperties.SkipReturnCode != -1) { + properties.append( + DumpCTestProperty("SKIP_RETURN_CODE", testProperties.SkipReturnCode)); + } + if (testProperties.ExplicitTimeout) { + properties.append( + DumpCTestProperty("TIMEOUT", testProperties.Timeout.count())); + } + if (!testProperties.TimeoutRegularExpressions.empty()) { + properties.append(DumpCTestProperty( + "TIMEOUT_AFTER_MATCH", DumpTimeoutAfterMatch(testProperties))); + } + if (testProperties.WillFail) { + properties.append(DumpCTestProperty("WILL_FAIL", testProperties.WillFail)); + } + if (!testProperties.Directory.empty()) { + properties.append( + DumpCTestProperty("WORKING_DIRECTORY", testProperties.Directory)); + } + return properties; +} + +class BacktraceData +{ + std::unordered_map<std::string, Json::ArrayIndex> CommandMap; + std::unordered_map<std::string, Json::ArrayIndex> FileMap; + std::unordered_map<cmListFileContext const*, Json::ArrayIndex> NodeMap; + Json::Value Commands = Json::arrayValue; + Json::Value Files = Json::arrayValue; + Json::Value Nodes = Json::arrayValue; + + Json::ArrayIndex AddCommand(std::string const& command) + { + auto i = this->CommandMap.find(command); + if (i == this->CommandMap.end()) { + i = this->CommandMap.emplace(command, this->Commands.size()).first; + this->Commands.append(command); + } + return i->second; + } + + Json::ArrayIndex AddFile(std::string const& file) + { + auto i = this->FileMap.find(file); + if (i == this->FileMap.end()) { + i = this->FileMap.emplace(file, this->Files.size()).first; + this->Files.append(file); + } + return i->second; + } + +public: + bool Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index); + Json::Value Dump(); +}; + +bool BacktraceData::Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index) +{ + if (bt.Empty()) { + return false; + } + cmListFileContext const* top = &bt.Top(); + auto found = this->NodeMap.find(top); + if (found != this->NodeMap.end()) { + index = found->second; + return true; + } + Json::Value entry = Json::objectValue; + entry["file"] = this->AddFile(top->FilePath); + if (top->Line) { + entry["line"] = static_cast<int>(top->Line); + } + if (!top->Name.empty()) { + entry["command"] = this->AddCommand(top->Name); + } + Json::ArrayIndex parent; + if (this->Add(bt.Pop(), parent)) { + entry["parent"] = parent; + } + index = this->NodeMap[top] = this->Nodes.size(); + this->Nodes.append(std::move(entry)); // NOLINT(*) + return true; +} + +Json::Value BacktraceData::Dump() +{ + Json::Value backtraceGraph; + this->CommandMap.clear(); + this->FileMap.clear(); + this->NodeMap.clear(); + backtraceGraph["commands"] = std::move(this->Commands); + backtraceGraph["files"] = std::move(this->Files); + backtraceGraph["nodes"] = std::move(this->Nodes); + return backtraceGraph; +} + +static void AddBacktrace(BacktraceData& backtraceGraph, Json::Value& object, + cmListFileBacktrace const& bt) +{ + Json::ArrayIndex backtrace; + if (backtraceGraph.Add(bt, backtrace)) { + object["backtrace"] = backtrace; + } +} + +static Json::Value DumpCTestInfo( + cmCTestRunTest& testRun, + cmCTestTestHandler::cmCTestTestProperties& testProperties, + BacktraceData& backtraceGraph) +{ + Json::Value testInfo = Json::objectValue; + // test name should always be present + testInfo["name"] = testProperties.Name; + std::string const& config = testRun.GetCTest()->GetConfigType(); + if (!config.empty()) { + testInfo["config"] = config; + } + std::string const& command = testRun.GetActualCommand(); + if (!command.empty()) { + std::vector<std::string> commandAndArgs; + commandAndArgs.push_back(command); + const std::vector<std::string>& args = testRun.GetArguments(); + if (!args.empty()) { + commandAndArgs.reserve(args.size() + 1); + commandAndArgs.insert(commandAndArgs.end(), args.begin(), args.end()); + } + testInfo["command"] = DumpToJsonArray(commandAndArgs); + } + Json::Value properties = DumpCTestProperties(testProperties); + if (!properties.empty()) { + testInfo["properties"] = properties; + } + if (!testProperties.Backtrace.Empty()) { + AddBacktrace(backtraceGraph, testInfo, testProperties.Backtrace); + } + return testInfo; +} + +static Json::Value DumpVersion(int major, int minor) +{ + Json::Value version = Json::objectValue; + version["major"] = major; + version["minor"] = minor; + return version; +} + +void cmCTestMultiProcessHandler::PrintOutputAsJson() +{ + this->TestHandler->SetMaxIndex(this->FindMaxIndex()); + + Json::Value result = Json::objectValue; + result["kind"] = "ctestInfo"; + result["version"] = DumpVersion(1, 0); + + BacktraceData backtraceGraph; + Json::Value tests = Json::arrayValue; + for (auto& it : this->Properties) { + cmCTestTestHandler::cmCTestTestProperties& p = *it.second; + + // Don't worry if this fails, we are only showing the test list, not + // running the tests + cmWorkingDirectory workdir(p.Directory); + cmCTestRunTest testRun(*this); + testRun.SetIndex(p.Index); + testRun.SetTestProperties(&p); + testRun.ComputeArguments(); + + // Skip tests not available in this configuration. + if (p.Args.size() >= 2 && p.Args[1] == "NOT_AVAILABLE") { + continue; + } + + Json::Value testInfo = DumpCTestInfo(testRun, p, backtraceGraph); + tests.append(testInfo); + } + result["backtraceGraph"] = backtraceGraph.Dump(); + result["tests"] = std::move(tests); + + Json::StreamWriterBuilder builder; + builder["indentation"] = " "; + std::unique_ptr<Json::StreamWriter> jout(builder.newStreamWriter()); + jout->write(result, &std::cout); +} + // For ShowOnly mode void cmCTestMultiProcessHandler::PrintTestList() { + if (this->CTest->GetOutputAsJson()) { + PrintOutputAsJson(); + return; + } + this->TestHandler->SetMaxIndex(this->FindMaxIndex()); int count = 0; diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 3927a8ab2..93bb880fe 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -51,6 +51,7 @@ public: void SetParallelLevel(size_t); void SetTestLoad(unsigned long load); virtual void RunTests(); + void PrintOutputAsJson(); void PrintTestList(); void PrintLabels(); diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index 511dbd2ec..435be97b6 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -19,9 +19,7 @@ cmCTestP4::cmCTestP4(cmCTest* ct, std::ostream& log) this->PriorRev = this->Unknown; } -cmCTestP4::~cmCTestP4() -{ -} +cmCTestP4::~cmCTestP4() = default; class cmCTestP4::IdentifyParser : public cmCTestVC::LineParser { @@ -307,20 +305,20 @@ void cmCTestP4::SetP4Options(std::vector<char const*>& CommandOptions) { if (P4Options.empty()) { const char* p4 = this->CommandLineTool.c_str(); - P4Options.push_back(p4); + P4Options.emplace_back(p4); // The CTEST_P4_CLIENT variable sets the P4 client used when issuing // Perforce commands, if it's different from the default one. std::string client = this->CTest->GetCTestConfiguration("P4Client"); if (!client.empty()) { - P4Options.push_back("-c"); + P4Options.emplace_back("-c"); P4Options.push_back(client); } // Set the message language to be English, in case the P4 admin // has localized them - P4Options.push_back("-L"); - P4Options.push_back("en"); + P4Options.emplace_back("-L"); + P4Options.emplace_back("en"); // The CTEST_P4_OPTIONS variable adds additional Perforce command line // options before the main command diff --git a/Source/CTest/cmCTestRunScriptCommand.cxx b/Source/CTest/cmCTestRunScriptCommand.cxx index 238284a3f..a7e47d35c 100644 --- a/Source/CTest/cmCTestRunScriptCommand.cxx +++ b/Source/CTest/cmCTestRunScriptCommand.cxx @@ -39,7 +39,8 @@ bool cmCTestRunScriptCommand::InitialPass(std::vector<std::string> const& args, ++i; } else { int ret; - cmCTestScriptHandler::RunScript(this->CTest, args[i].c_str(), !np, &ret); + cmCTestScriptHandler::RunScript(this->CTest, this->Makefile, + args[i].c_str(), !np, &ret); std::ostringstream str; str << ret; this->Makefile->AddDefinition(returnVariable, str.str().c_str()); diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 10dceca9b..918d5fa58 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -27,8 +27,6 @@ class cmCTestRunTest public: explicit cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler); - ~cmCTestRunTest() = default; - void SetNumberOfRuns(int n) { this->NumberOfRunsLeft = n; } void SetRunUntilFailOn() { this->RunUntilFail = true; } void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties* prop) @@ -78,6 +76,10 @@ public: cmCTest* GetCTest() const { return this->CTest; } + std::string& GetActualCommand() { return this->ActualCommand; } + + const std::vector<std::string>& GetArguments() { return this->Arguments; } + void FinalizeTest(); bool TimedOutForStopTime() const { return this->TimeoutIsForStopTime; } diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 58d9b3dcf..3bf66ca23 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -26,9 +26,7 @@ cmCTestSVN::cmCTestSVN(cmCTest* ct, std::ostream& log) this->PriorRev = this->Unknown; } -cmCTestSVN::~cmCTestSVN() -{ -} +cmCTestSVN::~cmCTestSVN() = default; void cmCTestSVN::CleanupImpl() { @@ -330,13 +328,15 @@ private: if (name == "logentry") { this->Rev = Revision(); this->Rev.SVNInfo = &SVNRepo; - if (const char* rev = this->FindAttribute(atts, "revision")) { + if (const char* rev = + cmCTestSVN::LogParser::FindAttribute(atts, "revision")) { this->Rev.Rev = rev; } this->Changes.clear(); } else if (name == "path") { this->CurChange = Change(); - if (const char* action = this->FindAttribute(atts, "action")) { + if (const char* action = + cmCTestSVN::LogParser::FindAttribute(atts, "action")) { this->CurChange.Action = action[0]; } } @@ -519,7 +519,7 @@ private: } else { local_path = path; } - this->SVN->Repositories.emplace_back(local_path.c_str()); + this->SVN->Repositories.emplace_back(local_path); } }; @@ -530,7 +530,7 @@ bool cmCTestSVN::LoadRepositories() } // Info for root repository - this->Repositories.emplace_back(""); + this->Repositories.emplace_back(); this->RootInfo = &(this->Repositories.back()); // Run "svn status" to get the list of external repositories diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h index a467ede28..5c8505d49 100644 --- a/Source/CTest/cmCTestSVN.h +++ b/Source/CTest/cmCTestSVN.h @@ -41,7 +41,7 @@ private: struct SVNInfo { - SVNInfo(const char* path) + SVNInfo(std::string const& path = std::string()) : LocalPath(path) { } diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index a87473d33..33b8b4a4c 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -53,8 +53,6 @@ struct cmListFileFunction; class cmCTestScriptFunctionBlocker : public cmFunctionBlocker { public: - cmCTestScriptFunctionBlocker() {} - ~cmCTestScriptFunctionBlocker() override {} bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus& /*status*/) override; // virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf); @@ -78,6 +76,7 @@ cmCTestScriptHandler::cmCTestScriptHandler() this->EmptyBinDir = false; this->EmptyBinDirOnce = false; this->Makefile = nullptr; + this->ParentMakefile = nullptr; this->CMake = nullptr; this->GlobalGenerator = nullptr; @@ -117,6 +116,7 @@ void cmCTestScriptHandler::Initialize() delete this->Makefile; this->Makefile = nullptr; + this->ParentMakefile = nullptr; delete this->GlobalGenerator; this->GlobalGenerator = nullptr; @@ -135,7 +135,7 @@ cmCTestScriptHandler::~cmCTestScriptHandler() void cmCTestScriptHandler::AddConfigurationScript(const char* script, bool pscope) { - this->ConfigurationScripts.push_back(script); + this->ConfigurationScripts.emplace_back(script); this->ScriptProcessScope.push_back(pscope); } @@ -263,15 +263,6 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) return retVal; } -static void ctestScriptProgressCallback(const char* m, float /*unused*/, - void* cd) -{ - cmCTest* ctest = static_cast<cmCTest*>(cd); - if (m && *m) { - cmCTestLog(ctest, HANDLER_OUTPUT, "-- " << m << std::endl); - } -} - void cmCTestScriptHandler::CreateCMake() { // create a cmake instance to read the configuration script @@ -280,7 +271,7 @@ void cmCTestScriptHandler::CreateCMake() delete this->GlobalGenerator; delete this->Makefile; } - this->CMake = new cmake(cmake::RoleScript); + this->CMake = new cmake(cmake::RoleScript, cmState::CTest); this->CMake->SetHomeDirectory(""); this->CMake->SetHomeOutputDirectory(""); this->CMake->GetCurrentSnapshot().SetDefaultDefinitions(); @@ -292,8 +283,16 @@ void cmCTestScriptHandler::CreateCMake() snapshot.GetDirectory().SetCurrentSource(cwd); snapshot.GetDirectory().SetCurrentBinary(cwd); this->Makefile = new cmMakefile(this->GlobalGenerator, snapshot); + if (this->ParentMakefile) { + this->Makefile->SetRecursionDepth( + this->ParentMakefile->GetRecursionDepth()); + } - this->CMake->SetProgressCallback(ctestScriptProgressCallback, this->CTest); + this->CMake->SetProgressCallback([this](const char* m, float /*unused*/) { + if (m && *m) { + cmCTestLog(this->CTest, HANDLER_OUTPUT, "-- " << m << std::endl); + } + }); this->AddCTestCommand("ctest_build", new cmCTestBuildCommand); this->AddCTestCommand("ctest_configure", new cmCTestConfigureCommand); @@ -373,7 +372,7 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) ctest scripting easier. */ std::string systemFile = this->Makefile->GetModulesFile("CTestScriptMode.cmake"); - if (!this->Makefile->ReadListFile(systemFile.c_str()) || + if (!this->Makefile->ReadListFile(systemFile) || cmSystemTools::GetErrorOccuredFlag()) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in read:" << systemFile << "\n"); @@ -388,7 +387,7 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) } // finally read in the script - if (!this->Makefile->ReadListFile(script.c_str()) || + if (!this->Makefile->ReadListFile(script) || cmSystemTools::GetErrorOccuredFlag()) { // Reset the error flag so that it can run more than // one script with an error when you use ctest_run_script. @@ -450,7 +449,7 @@ int cmCTestScriptHandler::ExtractVariables() updateVar, " specified without specifying CTEST_CVS_COMMAND."); return 12; } - this->ExtraUpdates.push_back(updateVal); + this->ExtraUpdates.emplace_back(updateVal); } } @@ -760,8 +759,8 @@ int cmCTestScriptHandler::RunConfigurationDashboard() // put the initial cache into the bin dir if (!this->InitialCache.empty()) { - if (!this->WriteInitialCache(this->BinaryDir.c_str(), - this->InitialCache.c_str())) { + if (!cmCTestScriptHandler::WriteInitialCache(this->BinaryDir.c_str(), + this->InitialCache.c_str())) { this->RestoreBackupDirectories(); return 9; } @@ -891,11 +890,13 @@ void cmCTestScriptHandler::RestoreBackupDirectories() } } -bool cmCTestScriptHandler::RunScript(cmCTest* ctest, const char* sname, - bool InProcess, int* returnValue) +bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf, + const char* sname, bool InProcess, + int* returnValue) { cmCTestScriptHandler* sh = new cmCTestScriptHandler(); sh->SetCTestInstance(ctest); + sh->ParentMakefile = mf; sh->AddConfigurationScript(sname, InProcess); int res = sh->ProcessHandler(); if (returnValue) { diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h index cf0762ec2..d93b5f8e7 100644 --- a/Source/CTest/cmCTestScriptHandler.h +++ b/Source/CTest/cmCTestScriptHandler.h @@ -72,8 +72,8 @@ public: /* * Run a script */ - static bool RunScript(cmCTest* ctest, const char* script, bool InProcess, - int* returnValue); + static bool RunScript(cmCTest* ctest, cmMakefile* mf, const char* script, + bool InProcess, int* returnValue); int RunCurrentScript(); /* @@ -166,6 +166,7 @@ private: std::chrono::steady_clock::time_point ScriptStartTime; cmMakefile* Makefile; + cmMakefile* ParentMakefile; cmGlobalGenerator* GlobalGenerator; cmake* CMake; }; diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx index 47006c10f..67ff2db05 100644 --- a/Source/CTest/cmCTestStartCommand.cxx +++ b/Source/CTest/cmCTestStartCommand.cxx @@ -146,7 +146,7 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, this->CTest->SetSuppressUpdatingCTestConfiguration(true); int model; if (smodel) { - model = this->CTest->GetTestModelFromString(smodel); + model = cmCTest::GetTestModelFromString(smodel); } else { model = cmCTest::UNKNOWN; } diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index 34adb4af3..00c061016 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -6,8 +6,8 @@ #include "cmCTestGenericHandler.h" #include "cmCTestSubmitHandler.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" #include <sstream> @@ -15,55 +15,28 @@ class cmExecutionStatus; cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() { - const char* ctestDropMethod = - this->Makefile->GetDefinition("CTEST_DROP_METHOD"); - const char* ctestDropSite = this->Makefile->GetDefinition("CTEST_DROP_SITE"); - const char* ctestDropLocation = - this->Makefile->GetDefinition("CTEST_DROP_LOCATION"); - const char* ctestTriggerSite = - this->Makefile->GetDefinition("CTEST_TRIGGER_SITE"); - bool ctestDropSiteCDash = this->Makefile->IsOn("CTEST_DROP_SITE_CDASH"); - const char* ctestProjectName = - this->Makefile->GetDefinition("CTEST_PROJECT_NAME"); - if (!ctestDropMethod) { - ctestDropMethod = "http"; - } + const char* submitURL = !this->SubmitURL.empty() + ? this->SubmitURL.c_str() + : this->Makefile->GetDefinition("CTEST_SUBMIT_URL"); - if (!ctestDropSite) { - // error: CDash requires CTEST_DROP_SITE definition - // in CTestConfig.cmake - } - if (!ctestDropLocation) { - // error: CDash requires CTEST_DROP_LOCATION definition - // in CTestConfig.cmake - } - this->CTest->SetCTestConfiguration("ProjectName", ctestProjectName, - this->Quiet); - this->CTest->SetCTestConfiguration("DropMethod", ctestDropMethod, - this->Quiet); - this->CTest->SetCTestConfiguration("DropSite", ctestDropSite, this->Quiet); - this->CTest->SetCTestConfiguration("DropLocation", ctestDropLocation, - this->Quiet); - - this->CTest->SetCTestConfiguration( - "IsCDash", ctestDropSiteCDash ? "TRUE" : "FALSE", this->Quiet); - - // Only propagate TriggerSite for non-CDash projects: - // - if (!ctestDropSiteCDash) { - this->CTest->SetCTestConfiguration("TriggerSite", ctestTriggerSite, - this->Quiet); + if (submitURL) { + this->CTest->SetCTestConfiguration("SubmitURL", submitURL, this->Quiet); + } else { + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "DropMethod", "CTEST_DROP_METHOD", this->Quiet); + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "DropSiteUser", "CTEST_DROP_SITE_USER", this->Quiet); + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "DropSitePassword", "CTEST_DROP_SITE_PASSWORD", + this->Quiet); + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "DropSite", "CTEST_DROP_SITE", this->Quiet); + this->CTest->SetCTestConfigurationFromCMakeVariable( + this->Makefile, "DropLocation", "CTEST_DROP_LOCATION", this->Quiet); } this->CTest->SetCTestConfigurationFromCMakeVariable( this->Makefile, "CurlOptions", "CTEST_CURL_OPTIONS", this->Quiet); - this->CTest->SetCTestConfigurationFromCMakeVariable( - this->Makefile, "DropSiteUser", "CTEST_DROP_SITE_USER", this->Quiet); - this->CTest->SetCTestConfigurationFromCMakeVariable( - this->Makefile, "DropSitePassword", "CTEST_DROP_SITE_PASSWORD", - this->Quiet); - this->CTest->SetCTestConfigurationFromCMakeVariable( - this->Makefile, "ScpCommand", "CTEST_SCP_COMMAND", this->Quiet); const char* notesFilesVariable = this->Makefile->GetDefinition("CTEST_NOTES_FILES"); @@ -203,6 +176,11 @@ bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg) return true; } + if (arg == "SUBMIT_URL") { + this->ArgumentDoing = ArgumentDoingSubmitURL; + return true; + } + if (arg == "INTERNAL_TEST_CHECKSUM") { this->InternalTest = true; return true; @@ -222,7 +200,7 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg) } else { std::ostringstream e; e << "Part name \"" << arg << "\" is invalid."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); this->ArgumentDoing = ArgumentDoingError; } return true; @@ -235,7 +213,7 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg) std::ostringstream e; e << "File \"" << arg << "\" does not exist. Cannot submit " << "a non-existent file."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); this->ArgumentDoing = ArgumentDoingError; } return true; @@ -268,6 +246,12 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg) return true; } + if (this->ArgumentDoing == ArgumentDoingSubmitURL) { + this->ArgumentDoing = ArgumentDoingNone; + this->SubmitURL = arg; + return true; + } + // Look for other arguments. return this->Superclass::CheckArgumentValue(arg); } diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h index c4b84ce9f..0caccd66d 100644 --- a/Source/CTest/cmCTestSubmitCommand.h +++ b/Source/CTest/cmCTestSubmitCommand.h @@ -71,6 +71,7 @@ protected: ArgumentDoingCDashUpload, ArgumentDoingCDashUploadType, ArgumentDoingHttpHeader, + ArgumentDoingSubmitURL, ArgumentDoingLast2 }; @@ -85,6 +86,7 @@ protected: std::string CDashUploadFile; std::string CDashUploadType; std::vector<std::string> HttpHeaders; + std::string SubmitURL; }; #endif diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index ecf309a80..87112da9e 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -5,13 +5,12 @@ #include "cm_curl.h" #include "cm_jsoncpp_reader.h" #include "cm_jsoncpp_value.h" -#include "cmsys/Process.h" #include <chrono> -#include <cstring> #include <sstream> #include <stdio.h> #include <stdlib.h> +#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestCurl.h" #include "cmCTestScriptHandler.h" @@ -19,20 +18,11 @@ #include "cmCurl.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" -#include "cmProcessOutput.h" #include "cmState.h" #include "cmSystemTools.h" -#include "cmThirdParty.h" -#include "cmWorkingDirectory.h" #include "cmXMLParser.h" #include "cmake.h" -#if defined(CTEST_USE_XMLRPC) -# include "cmVersion.h" -# include "cm_sys_stat.h" -# include "cm_xmlrpc.h" -#endif - #define SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT 120 typedef std::vector<char> cmCTestSubmitHandlerVectorOfChar; @@ -40,10 +30,6 @@ typedef std::vector<char> cmCTestSubmitHandlerVectorOfChar; class cmCTestSubmitHandler::ResponseParser : public cmXMLParser { public: - ResponseParser() { this->Status = STATUS_OK; } - ~ResponseParser() override {} - -public: enum StatusType { STATUS_OK, @@ -51,10 +37,11 @@ public: STATUS_ERROR }; - StatusType Status; + StatusType Status = STATUS_OK; std::string Filename; std::string MD5; std::string Message; + std::string BuildID; private: std::vector<char> CurrentValue; @@ -96,6 +83,8 @@ private: this->MD5 = this->GetCurrentValue(); } else if (name == "message") { this->Message = this->GetCurrentValue(); + } else if (name == "buildId") { + this->BuildID = this->GetCurrentValue(); } } }; @@ -126,8 +115,6 @@ static size_t cmCTestSubmitHandlerCurlDebugCallback(CURL* /*unused*/, } cmCTestSubmitHandler::cmCTestSubmitHandler() - : HTTPProxy() - , FTPProxy() { this->Initialize(); } @@ -139,170 +126,19 @@ void cmCTestSubmitHandler::Initialize() p = cmCTest::Part(p + 1)) { this->SubmitPart[p] = true; } - this->CDash = false; this->HasWarnings = false; this->HasErrors = false; this->Superclass::Initialize(); this->HTTPProxy.clear(); this->HTTPProxyType = 0; this->HTTPProxyAuth.clear(); - this->FTPProxy.clear(); - this->FTPProxyType = 0; this->LogFile = nullptr; this->Files.clear(); } -bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix, - const std::set<std::string>& files, - const std::string& remoteprefix, - const std::string& url) -{ - CURL* curl; - CURLcode res; - FILE* ftpfile; - char error_buffer[1024]; - - /* In windows, this will init the winsock stuff */ - ::curl_global_init(CURL_GLOBAL_ALL); - - for (std::string const& file : files) { - /* get a curl handle */ - curl = curl_easy_init(); - if (curl) { - // Using proxy - if (this->FTPProxyType > 0) { - curl_easy_setopt(curl, CURLOPT_PROXY, this->FTPProxy.c_str()); - switch (this->FTPProxyType) { - case 2: - curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); - break; - case 3: - curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); - break; - default: - curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); - } - } - - // enable uploading - ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1); - - // if there is little to no activity for too long stop submitting - ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1); - ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, - SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT); - - ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1); - - std::string local_file = file; - if (!cmSystemTools::FileExists(local_file)) { - local_file = localprefix + "/" + file; - } - std::string upload_as = - url + "/" + remoteprefix + cmSystemTools::GetFilenameName(file); - - if (!cmSystemTools::FileExists(local_file)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Cannot find file: " << local_file << std::endl); - ::curl_easy_cleanup(curl); - ::curl_global_cleanup(); - return false; - } - unsigned long filelen = cmSystemTools::FileLength(local_file); - - ftpfile = cmsys::SystemTools::Fopen(local_file, "rb"); - *this->LogFile << "\tUpload file: " << local_file << " to " << upload_as - << std::endl; - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - " Upload file: " << local_file << " to " - << upload_as << std::endl, - this->Quiet); - - ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); - - // specify target - ::curl_easy_setopt(curl, CURLOPT_URL, upload_as.c_str()); - - // now specify which file to upload - ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile); - - // and give the size of the upload (optional) - ::curl_easy_setopt(curl, CURLOPT_INFILESIZE, static_cast<long>(filelen)); - - // and give curl the buffer for errors - ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer); - - // specify handler for output - ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, - cmCTestSubmitHandlerWriteMemoryCallback); - ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, - cmCTestSubmitHandlerCurlDebugCallback); - - /* we pass our 'chunk' struct to the callback function */ - cmCTestSubmitHandlerVectorOfChar chunk; - cmCTestSubmitHandlerVectorOfChar chunkDebug; - ::curl_easy_setopt(curl, CURLOPT_FILE, &chunk); - ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &chunkDebug); - - // Now run off and do what you've been told! - res = ::curl_easy_perform(curl); - - if (!chunk.empty()) { - cmCTestOptionalLog(this->CTest, DEBUG, - "CURL output: [" - << cmCTestLogWrite(&*chunk.begin(), chunk.size()) - << "]" << std::endl, - this->Quiet); - } - if (!chunkDebug.empty()) { - cmCTestOptionalLog( - this->CTest, DEBUG, - "CURL debug output: [" - << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]" - << std::endl, - this->Quiet); - } - - fclose(ftpfile); - if (res) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Error when uploading file: " << local_file - << std::endl); - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Error message was: " << error_buffer << std::endl); - *this->LogFile << " Error when uploading file: " << local_file - << std::endl - << " Error message was: " << error_buffer << std::endl - << " Curl output was: "; - // avoid dereference of empty vector - if (!chunk.empty()) { - *this->LogFile << cmCTestLogWrite(&*chunk.begin(), chunk.size()); - cmCTestLog(this->CTest, ERROR_MESSAGE, - "CURL output: [" - << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]" - << std::endl); - } - *this->LogFile << std::endl; - ::curl_easy_cleanup(curl); - ::curl_global_cleanup(); - return false; - } - // always cleanup - ::curl_easy_cleanup(curl); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Uploaded: " + local_file << std::endl, - this->Quiet); - } - } - ::curl_global_cleanup(); - return true; -} - -// Uploading files is simpler -bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, - const std::set<std::string>& files, - const std::string& remoteprefix, - const std::string& url) +bool cmCTestSubmitHandler::SubmitUsingHTTP( + const std::string& localprefix, const std::vector<std::string>& files, + const std::string& remoteprefix, const std::string& url) { CURL* curl; CURLcode res; @@ -322,7 +158,6 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, /* In windows, this will init the winsock stuff */ ::curl_global_init(CURL_GLOBAL_ALL); - std::string dropMethod(this->CTest->GetCTestConfiguration("DropMethod")); std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions")); std::vector<std::string> args; cmSystemTools::ExpandListArgument(curlopt, args); @@ -405,26 +240,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, *this->LogFile << "\tUpload file: " << local_file << " to " << remote_file << std::endl; - std::string ofile; - for (char c : remote_file) { - char hexCh[4] = { 0, 0, 0, 0 }; - hexCh[0] = c; - switch (c) { - case '+': - case '?': - case '/': - case '\\': - case '&': - case ' ': - case '=': - case '%': - sprintf(hexCh, "%%%02X", static_cast<int>(c)); - ofile.append(hexCh); - break; - default: - ofile.append(hexCh); - } - } + std::string ofile = cmSystemTools::EncodeURL(remote_file); std::string upload_as = url + ((url.find('?') == std::string::npos) ? '?' : '&') + "FileName=" + ofile; @@ -465,6 +281,17 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, cmSystemTools::ComputeFileHash(local_file, cmCryptoHash::AlgoMD5); } + // Generate Done.xml right before it is submitted. + // The reason for this is two-fold: + // 1) It must be generated after some other part has been submitted + // so we have a buildId to refer to in its contents. + // 2) By generating Done.xml here its timestamp will be as late as + // possible. This gives us a more accurate record of how long the + // entire build took to complete. + if (file == "Done.xml") { + this->CTest->GenerateDoneFile(); + } + if (!cmSystemTools::FileExists(local_file)) { cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: " << local_file << std::endl); @@ -646,6 +473,7 @@ void cmCTestSubmitHandler::ParseResponse( " Submission failed: " << parser.Message << std::endl); return; } + this->CTest->SetBuildID(parser.BuildID); } output = cmSystemTools::UpperCase(output); if (output.find("WARNING") != std::string::npos) { @@ -662,392 +490,6 @@ void cmCTestSubmitHandler::ParseResponse( } } -bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::set<std::string>& files, - const std::string& remoteprefix, - const std::string& url) -{ - CURL* curl; - char error_buffer[1024]; - - /* In windows, this will init the winsock stuff */ - ::curl_global_init(CURL_GLOBAL_ALL); - - for (std::string const& file : files) { - /* get a curl handle */ - curl = curl_easy_init(); - if (curl) { - // Using proxy - if (this->HTTPProxyType > 0) { - curl_easy_setopt(curl, CURLOPT_PROXY, this->HTTPProxy.c_str()); - switch (this->HTTPProxyType) { - case 2: - curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); - break; - case 3: - curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); - break; - default: - curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); - if (!this->HTTPProxyAuth.empty()) { - curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, - this->HTTPProxyAuth.c_str()); - } - } - } - - ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); - - // and give curl the buffer for errors - ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer); - - // specify handler for output - ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, - cmCTestSubmitHandlerWriteMemoryCallback); - ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, - cmCTestSubmitHandlerCurlDebugCallback); - - /* we pass our 'chunk' struct to the callback function */ - cmCTestSubmitHandlerVectorOfChar chunk; - cmCTestSubmitHandlerVectorOfChar chunkDebug; - ::curl_easy_setopt(curl, CURLOPT_FILE, &chunk); - ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &chunkDebug); - - std::string rfile = remoteprefix + cmSystemTools::GetFilenameName(file); - std::string ofile; - for (char c : rfile) { - char hexCh[4] = { 0, 0, 0, 0 }; - hexCh[0] = c; - switch (c) { - case '+': - case '?': - case '/': - case '\\': - case '&': - case ' ': - case '=': - case '%': - sprintf(hexCh, "%%%02X", static_cast<int>(c)); - ofile.append(hexCh); - break; - default: - ofile.append(hexCh); - } - } - std::string turl = url + - ((url.find('?') == std::string::npos) ? '?' : '&') + - "xmlfile=" + ofile; - *this->LogFile << "Trigger url: " << turl << std::endl; - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - " Trigger url: " << turl << std::endl, this->Quiet); - curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); - curl_easy_setopt(curl, CURLOPT_URL, turl.c_str()); - if (curl_easy_perform(curl)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Error when triggering: " << turl << std::endl); - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Error message was: " << error_buffer << std::endl); - *this->LogFile << "\tTriggering failed with error: " << error_buffer - << std::endl - << " Error message was: " << error_buffer - << std::endl; - if (!chunk.empty()) { - *this->LogFile << " Curl output was: " - << cmCTestLogWrite(&*chunk.begin(), chunk.size()) - << std::endl; - cmCTestLog(this->CTest, ERROR_MESSAGE, - "CURL output: [" - << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]" - << std::endl); - } - ::curl_easy_cleanup(curl); - ::curl_global_cleanup(); - return false; - } - - if (!chunk.empty()) { - cmCTestOptionalLog(this->CTest, DEBUG, - "CURL output: [" - << cmCTestLogWrite(&*chunk.begin(), chunk.size()) - << "]" << std::endl, - this->Quiet); - } - if (!chunkDebug.empty()) { - cmCTestOptionalLog( - this->CTest, DEBUG, - "CURL debug output: [" - << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]" - << std::endl, - this->Quiet); - } - - // always cleanup - ::curl_easy_cleanup(curl); - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl, - this->Quiet); - } - } - ::curl_global_cleanup(); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Dart server triggered..." << std::endl, this->Quiet); - return true; -} - -bool cmCTestSubmitHandler::SubmitUsingSCP(const std::string& scp_command, - const std::string& localprefix, - const std::set<std::string>& files, - const std::string& remoteprefix, - const std::string& url) -{ - if (scp_command.empty() || localprefix.empty() || files.empty() || - remoteprefix.empty() || url.empty()) { - return false; - } - - std::vector<const char*> argv; - argv.push_back(scp_command.c_str()); // Scp command - argv.push_back(scp_command.c_str()); // Dummy string for file - argv.push_back(scp_command.c_str()); // Dummy string for remote url - argv.push_back(nullptr); - - cmsysProcess* cp = cmsysProcess_New(); - cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); - // cmsysProcess_SetTimeout(cp, timeout); - - int problems = 0; - - for (std::string const& file : files) { - int retVal; - - std::string lfname = localprefix; - cmSystemTools::ConvertToUnixSlashes(lfname); - lfname += "/" + file; - lfname = cmSystemTools::ConvertToOutputPath(lfname); - argv[1] = lfname.c_str(); - std::string rfname = url + "/" + remoteprefix + file; - argv[2] = rfname.c_str(); - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \"" - << argv[2] << "\"" << std::endl, - this->Quiet); - *this->LogFile << "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \"" - << argv[2] << "\"" << std::endl; - - cmsysProcess_SetCommand(cp, &*argv.begin()); - cmsysProcess_Execute(cp); - char* data; - int length; - cmProcessOutput processOutput; - std::string strdata; - - while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) { - processOutput.DecodeText(data, length, strdata); - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - cmCTestLogWrite(strdata.c_str(), strdata.size()), - this->Quiet); - } - processOutput.DecodeText(std::string(), strdata); - if (!strdata.empty()) { - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - cmCTestLogWrite(strdata.c_str(), strdata.size()), - this->Quiet); - } - - cmsysProcess_WaitForExit(cp, nullptr); - - int result = cmsysProcess_GetState(cp); - - if (result == cmsysProcess_State_Exited) { - retVal = cmsysProcess_GetExitValue(cp); - if (retVal != 0) { - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - "\tSCP returned: " << retVal << std::endl, - this->Quiet); - *this->LogFile << "\tSCP returned: " << retVal << std::endl; - problems++; - } - } else if (result == cmsysProcess_State_Exception) { - retVal = cmsysProcess_GetExitException(cp); - cmCTestLog(this->CTest, ERROR_MESSAGE, - "\tThere was an exception: " << retVal << std::endl); - *this->LogFile << "\tThere was an exception: " << retVal << std::endl; - problems++; - } else if (result == cmsysProcess_State_Expired) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "\tThere was a timeout" << std::endl); - *this->LogFile << "\tThere was a timeout" << std::endl; - problems++; - } else if (result == cmsysProcess_State_Error) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "\tError executing SCP: " << cmsysProcess_GetErrorString(cp) - << std::endl); - *this->LogFile << "\tError executing SCP: " - << cmsysProcess_GetErrorString(cp) << std::endl; - problems++; - } - } - cmsysProcess_Delete(cp); - return problems == 0; -} - -bool cmCTestSubmitHandler::SubmitUsingCP(const std::string& localprefix, - const std::set<std::string>& files, - const std::string& remoteprefix, - const std::string& destination) -{ - if (localprefix.empty() || files.empty() || remoteprefix.empty() || - destination.empty()) { - /* clang-format off */ - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Missing arguments for submit via cp:\n" - << "\tlocalprefix: " << localprefix << "\n" - << "\tNumber of files: " << files.size() << "\n" - << "\tremoteprefix: " << remoteprefix << "\n" - << "\tdestination: " << destination << std::endl); - /* clang-format on */ - return false; - } - - for (std::string const& file : files) { - std::string lfname = localprefix; - cmSystemTools::ConvertToUnixSlashes(lfname); - lfname += "/" + file; - std::string rfname = destination + "/" + remoteprefix + file; - cmSystemTools::CopyFileAlways(lfname, rfname); - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - " Copy file: " << lfname << " to " << rfname - << std::endl, - this->Quiet); - } - std::string tagDoneFile = destination + "/" + remoteprefix + "DONE"; - cmSystemTools::Touch(tagDoneFile, true); - return true; -} - -#if defined(CTEST_USE_XMLRPC) -bool cmCTestSubmitHandler::SubmitUsingXMLRPC( - const std::string& localprefix, const std::set<std::string>& files, - const std::string& remoteprefix, const std::string& url) -{ - xmlrpc_env env; - char ctestString[] = "CTest"; - std::string ctestVersionString = cmVersion::GetCMakeVersion(); - char* ctestVersion = const_cast<char*>(ctestVersionString.c_str()); - - std::string realURL = url + "/" + remoteprefix + "/Command/"; - - /* Start up our XML-RPC client library. */ - xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, ctestString, ctestVersion); - - /* Initialize our error-handling environment. */ - xmlrpc_env_init(&env); - - /* Call the famous server at UserLand. */ - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Submitting to: " << realURL << " (" << remoteprefix - << ")" << std::endl, - this->Quiet); - for (std::string const& file : files) { - xmlrpc_value* result; - - std::string local_file = file; - if (!cmSystemTools::FileExists(local_file)) { - local_file = localprefix + "/" + file; - } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Submit file: " << local_file << std::endl, - this->Quiet); - struct stat st; - if (::stat(local_file.c_str(), &st)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Cannot find file: " << local_file << std::endl); - return false; - } - - // off_t can be bigger than size_t. fread takes size_t. - // make sure the file is not too big. - if (static_cast<off_t>(static_cast<size_t>(st.st_size)) != - static_cast<off_t>(st.st_size)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " File too big: " << local_file << std::endl); - return false; - } - size_t fileSize = static_cast<size_t>(st.st_size); - FILE* fp = cmsys::SystemTools::Fopen(local_file, "rb"); - if (!fp) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Cannot open file: " << local_file << std::endl); - return false; - } - - unsigned char* fileBuffer = new unsigned char[fileSize]; - if (fread(fileBuffer, 1, fileSize, fp) != fileSize) { - delete[] fileBuffer; - fclose(fp); - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Cannot read file: " << local_file << std::endl); - return false; - } - fclose(fp); - - char remoteCommand[] = "Submit.put"; - char* pRealURL = const_cast<char*>(realURL.c_str()); - result = - xmlrpc_client_call(&env, pRealURL, remoteCommand, "(6)", fileBuffer, - static_cast<xmlrpc_int32>(fileSize)); - - delete[] fileBuffer; - - if (env.fault_occurred) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Submission problem: " << env.fault_string << " (" - << env.fault_code << ")" - << std::endl); - xmlrpc_env_clean(&env); - xmlrpc_client_cleanup(); - return false; - } - - /* Dispose of our result value. */ - xmlrpc_DECREF(result); - } - - /* Clean up our error-handling environment. */ - xmlrpc_env_clean(&env); - - /* Shutdown our XML-RPC client library. */ - xmlrpc_client_cleanup(); - return true; -} -#else -bool cmCTestSubmitHandler::SubmitUsingXMLRPC( - std::string const& /*unused*/, std::set<std::string> const& /*unused*/, - std::string const& /*unused*/, std::string const& /*unused*/) -{ - return false; -} -#endif - -void cmCTestSubmitHandler::ConstructCDashURL(std::string& dropMethod, - std::string& url) -{ - dropMethod = this->CTest->GetCTestConfiguration("DropMethod"); - url = dropMethod; - url += "://"; - if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) { - url += this->CTest->GetCTestConfiguration("DropSiteUser"); - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, - this->CTest->GetCTestConfiguration("DropSiteUser").c_str(), this->Quiet); - if (!this->CTest->GetCTestConfiguration("DropSitePassword").empty()) { - url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword"); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, ":******", this->Quiet); - } - url += "@"; - } - url += this->CTest->GetCTestConfiguration("DropSite") + - this->CTest->GetCTestConfiguration("DropLocation"); -} - int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, std::string const& typeString) { @@ -1068,12 +510,15 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, curl.SetCurlOptions(args); curl.SetTimeOutSeconds(SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT); curl.SetHttpHeaders(this->HttpHeaders); - std::string dropMethod; - std::string url; - this->ConstructCDashURL(dropMethod, url); - std::string::size_type pos = url.find("submit.php?"); - url = url.substr(0, pos + 10); - if (!(dropMethod == "http" || dropMethod == "https")) { + std::string url = this->CTest->GetSubmitURL(); + std::string fields; + std::string::size_type pos = url.find('?'); + if (pos != std::string::npos) { + fields = url.substr(pos + 1); + url = url.substr(0, pos); + } + if (!cmHasLiteralPrefix(url, "http://") && + !cmHasLiteralPrefix(url, "https://")) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Only http and https are supported for CDASH_UPLOAD\n"); return -1; @@ -1120,8 +565,6 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, const char* subproject = cm->GetState()->GetGlobalProperty("SubProject"); // TODO: Encode values for a URL instead of trusting caller. std::ostringstream str; - str << "project=" - << curl.Escape(this->CTest->GetCTestConfiguration("ProjectName")) << "&"; if (subproject) { str << "subproject=" << curl.Escape(subproject) << "&"; } @@ -1139,7 +582,10 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, << "endtime=" << timeNow << "&" << "datafilesmd5[0]=" << md5sum << "&" << "type=" << curl.Escape(typeString); - std::string fields = str.str(); + if (!fields.empty()) { + fields += '&'; + } + fields += str.str(); cmCTestOptionalLog(this->CTest, DEBUG, "fields: " << fields << "\nurl:" << url << "\nfile: " << file << "\n", @@ -1276,11 +722,6 @@ int cmCTestSubmitHandler::ProcessHandler() if (cdashUploadFile && cdashUploadType) { return this->HandleCDashUploadFile(cdashUploadFile, cdashUploadType); } - std::string iscdash = this->CTest->GetCTestConfiguration("IsCDash"); - // cdash does not need to trigger so just return true - if (!iscdash.empty()) { - this->CDash = true; - } const std::string& buildDirectory = this->CTest->GetCTestConfiguration("BuildDirectory"); @@ -1318,46 +759,21 @@ int cmCTestSubmitHandler::ProcessHandler() } } - if (getenv("FTP_PROXY")) { - this->FTPProxyType = 1; - this->FTPProxy = getenv("FTP_PROXY"); - if (getenv("FTP_PROXY_PORT")) { - this->FTPProxy += ":"; - this->FTPProxy += getenv("FTP_PROXY_PORT"); - } - if (getenv("FTP_PROXY_TYPE")) { - std::string type = getenv("FTP_PROXY_TYPE"); - // HTTP/SOCKS4/SOCKS5 - if (type == "HTTP") { - this->FTPProxyType = 1; - } else if (type == "SOCKS4") { - this->FTPProxyType = 2; - } else if (type == "SOCKS5") { - this->FTPProxyType = 3; - } - } - } - if (!this->HTTPProxy.empty()) { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Use HTTP Proxy: " << this->HTTPProxy << std::endl, this->Quiet); } - if (!this->FTPProxy.empty()) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Use FTP Proxy: " << this->FTPProxy << std::endl, - this->Quiet); - } cmGeneratedFileStream ofs; this->StartLogFile("Submit", ofs); - cmCTest::SetOfStrings files; + std::vector<std::string> files; std::string prefix = this->GetSubmitResultsPrefix(); if (!this->Files.empty()) { // Submit the explicitly selected files: // - files.insert(this->Files.begin(), this->Files.end()); + files.insert(files.end(), this->Files.begin(), this->Files.end()); } // Add to the list of files to submit from any selected, existing parts: @@ -1404,7 +820,21 @@ int cmCTestSubmitHandler::ProcessHandler() // Submit files from this part. std::vector<std::string> const& pfiles = this->CTest->GetSubmitFiles(p); - files.insert(pfiles.begin(), pfiles.end()); + files.insert(files.end(), pfiles.begin(), pfiles.end()); + } + + // Make sure files are unique, but preserve order. + { + // This endPos intermediate is needed to work around non-conformant C++11 + // standard libraries that have erase(iterator,iterator) instead of + // erase(const_iterator,const_iterator). + size_t endPos = cmRemoveDuplicates(files) - files.cbegin(); + files.erase(files.begin() + endPos, files.end()); + } + + // Submit Done.xml last + if (this->SubmitPart[cmCTest::PartDone]) { + files.emplace_back("Done.xml"); } if (ofs) { @@ -1415,10 +845,7 @@ int cmCTestSubmitHandler::ProcessHandler() cnt++; } } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - "Submit files (using " - << this->CTest->GetCTestConfiguration("DropMethod") - << ")" << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Submit files\n", this->Quiet); const char* specificTrack = this->CTest->GetSpecificTrack(); if (specificTrack) { @@ -1428,233 +855,32 @@ int cmCTestSubmitHandler::ProcessHandler() } this->SetLogFile(&ofs); - std::string dropMethod(this->CTest->GetCTestConfiguration("DropMethod")); - - if (dropMethod.empty() || dropMethod == "ftp") { - ofs << "Using drop method: FTP" << std::endl; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Using FTP submit method" << std::endl - << " Drop site: ftp://", - this->Quiet); - std::string url = "ftp://"; - url += cmCTest::MakeURLSafe( - this->CTest->GetCTestConfiguration("DropSiteUser")) + - ":" + - cmCTest::MakeURLSafe( - this->CTest->GetCTestConfiguration("DropSitePassword")) + - "@" + this->CTest->GetCTestConfiguration("DropSite") + - cmCTest::MakeURLSafe(this->CTest->GetCTestConfiguration("DropLocation")); - if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) { - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, - this->CTest->GetCTestConfiguration("DropSiteUser").c_str(), - this->Quiet); - if (!this->CTest->GetCTestConfiguration("DropSitePassword").empty()) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, ":******", - this->Quiet); - } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "@", this->Quiet); - } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - this->CTest->GetCTestConfiguration("DropSite") - << this->CTest->GetCTestConfiguration("DropLocation") - << std::endl, - this->Quiet); - if (!this->SubmitUsingFTP(buildDirectory + "/Testing/" + - this->CTest->GetCurrentTag(), - files, prefix, url)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Problems when submitting via FTP" << std::endl); - ofs << " Problems when submitting via FTP" << std::endl; - return -1; - } - if (!this->CDash) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Using HTTP trigger method" - << std::endl - << " Trigger site: " - << this->CTest->GetCTestConfiguration("TriggerSite") - << std::endl, - this->Quiet); - if (!this->TriggerUsingHTTP( - files, prefix, - this->CTest->GetCTestConfiguration("TriggerSite"))) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Problems when triggering via HTTP" << std::endl); - ofs << " Problems when triggering via HTTP" << std::endl; - return -1; - } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Submission successful" << std::endl, this->Quiet); - ofs << " Submission successful" << std::endl; - return 0; - } - } else if (dropMethod == "http" || dropMethod == "https") { - std::string url = dropMethod; - url += "://"; - ofs << "Using drop method: " << dropMethod << std::endl; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Using HTTP submit method" << std::endl - << " Drop site:" << url, - this->Quiet); - if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) { - url += this->CTest->GetCTestConfiguration("DropSiteUser"); - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, - this->CTest->GetCTestConfiguration("DropSiteUser").c_str(), - this->Quiet); - if (!this->CTest->GetCTestConfiguration("DropSitePassword").empty()) { - url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword"); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, ":******", - this->Quiet); - } - url += "@"; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "@", this->Quiet); - } - url += this->CTest->GetCTestConfiguration("DropSite") + - this->CTest->GetCTestConfiguration("DropLocation"); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - this->CTest->GetCTestConfiguration("DropSite") - << this->CTest->GetCTestConfiguration("DropLocation") - << std::endl, - this->Quiet); - if (!this->SubmitUsingHTTP(buildDirectory + "/Testing/" + - this->CTest->GetCurrentTag(), - files, prefix, url)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Problems when submitting via HTTP" << std::endl); - ofs << " Problems when submitting via HTTP" << std::endl; - return -1; - } - if (!this->CDash) { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Using HTTP trigger method" - << std::endl - << " Trigger site: " - << this->CTest->GetCTestConfiguration("TriggerSite") - << std::endl, - this->Quiet); - if (!this->TriggerUsingHTTP( - files, prefix, - this->CTest->GetCTestConfiguration("TriggerSite"))) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Problems when triggering via HTTP" << std::endl); - ofs << " Problems when triggering via HTTP" << std::endl; - return -1; - } - } - if (this->HasErrors) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, - " Errors occurred during " - "submission." - << std::endl); - ofs << " Errors occurred during submission. " << std::endl; - } else { - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Submission successful" - << (this->HasWarnings ? ", with warnings." : "") - << std::endl, - this->Quiet); - ofs << " Submission successful" - << (this->HasWarnings ? ", with warnings." : "") << std::endl; - } - - return 0; - } else if (dropMethod == "xmlrpc") { -#if defined(CTEST_USE_XMLRPC) - ofs << "Using drop method: XML-RPC" << std::endl; - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Using XML-RPC submit method" << std::endl, - this->Quiet); - std::string url = this->CTest->GetCTestConfiguration("DropSite"); - prefix = this->CTest->GetCTestConfiguration("DropLocation"); - if (!this->SubmitUsingXMLRPC(buildDirectory + "/Testing/" + - this->CTest->GetCurrentTag(), - files, prefix, url)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Problems when submitting via XML-RPC" << std::endl); - ofs << " Problems when submitting via XML-RPC" << std::endl; - return -1; - } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Submission successful" << std::endl, this->Quiet); - ofs << " Submission successful" << std::endl; - return 0; -#else + std::string url = this->CTest->GetSubmitURL(); + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " SubmitURL: " << url << '\n', this->Quiet); + if (!this->SubmitUsingHTTP(buildDirectory + "/Testing/" + + this->CTest->GetCurrentTag(), + files, prefix, url)) { cmCTestLog(this->CTest, ERROR_MESSAGE, - " Submission method \"xmlrpc\" not compiled into CTest!" - << std::endl); + " Problems when submitting via HTTP\n"); + ofs << " Problems when submitting via HTTP\n"; return -1; -#endif - } else if (dropMethod == "scp") { - std::string url; - if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) { - url += this->CTest->GetCTestConfiguration("DropSiteUser") + "@"; - } - url += this->CTest->GetCTestConfiguration("DropSite") + ":" + - this->CTest->GetCTestConfiguration("DropLocation"); - - // change to the build directory so that we can uses a relative path - // on windows since scp doesn't support "c:" a drive in the path - cmWorkingDirectory workdir(buildDirectory); - if (workdir.Failed()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Failed to change directory to " - << buildDirectory << " : " - << std::strerror(workdir.GetLastResult()) << std::endl); - ofs << " Failed to change directory to " << buildDirectory << " : " - << std::strerror(workdir.GetLastResult()) << std::endl; - return -1; - } - - if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"), - "Testing/" + this->CTest->GetCurrentTag(), files, - prefix, url)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Problems when submitting via SCP" << std::endl); - ofs << " Problems when submitting via SCP" << std::endl; - return -1; - } + } + if (this->HasErrors) { + cmCTestLog(this->CTest, HANDLER_OUTPUT, + " Errors occurred during submission.\n"); + ofs << " Errors occurred during submission.\n"; + } else { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Submission successful" << std::endl, this->Quiet); - ofs << " Submission successful" << std::endl; - return 0; - } else if (dropMethod == "cp") { - std::string location = this->CTest->GetCTestConfiguration("DropLocation"); - - // change to the build directory so that we can uses a relative path - // on windows since scp doesn't support "c:" a drive in the path - cmWorkingDirectory workdir(buildDirectory); - if (workdir.Failed()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Failed to change directory to " - << buildDirectory << " : " - << std::strerror(workdir.GetLastResult()) << std::endl); - ofs << " Failed to change directory to " << buildDirectory << " : " - << std::strerror(workdir.GetLastResult()) << std::endl; - return -1; - } - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - " Change directory: " << buildDirectory << std::endl, + " Submission successful" + << (this->HasWarnings ? ", with warnings." : "") + << std::endl, this->Quiet); - - if (!this->SubmitUsingCP("Testing/" + this->CTest->GetCurrentTag(), files, - prefix, location)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Problems when submitting via CP" << std::endl); - ofs << " Problems when submitting via cp" << std::endl; - return -1; - } - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Submission successful" << std::endl, this->Quiet); - ofs << " Submission successful" << std::endl; - return 0; + ofs << " Submission successful" + << (this->HasWarnings ? ", with warnings." : "") << std::endl; } - cmCTestLog(this->CTest, ERROR_MESSAGE, - " Unknown submission method: \"" << dropMethod << "\"" - << std::endl); - return -1; + return 0; } std::string cmCTestSubmitHandler::GetSubmitResultsPrefix() diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h index b4d0e7772..58f4f975d 100644 --- a/Source/CTest/cmCTestSubmitHandler.h +++ b/Source/CTest/cmCTestSubmitHandler.h @@ -48,38 +48,16 @@ public: this->HttpHeaders = v; } - void ConstructCDashURL(std::string& dropMethod, std::string& url); - private: void SetLogFile(std::ostream* ost) { this->LogFile = ost; } /** * Submit file using various ways */ - bool SubmitUsingFTP(const std::string& localprefix, - const std::set<std::string>& files, - const std::string& remoteprefix, const std::string& url); bool SubmitUsingHTTP(const std::string& localprefix, - const std::set<std::string>& files, + const std::vector<std::string>& files, const std::string& remoteprefix, const std::string& url); - bool SubmitUsingSCP(const std::string& scp_command, - const std::string& localprefix, - const std::set<std::string>& files, - const std::string& remoteprefix, const std::string& url); - - bool SubmitUsingCP(const std::string& localprefix, - const std::set<std::string>& files, - const std::string& remoteprefix, const std::string& url); - - bool TriggerUsingHTTP(const std::set<std::string>& files, - const std::string& remoteprefix, - const std::string& url); - - bool SubmitUsingXMLRPC(const std::string& localprefix, - const std::set<std::string>& files, - const std::string& remoteprefix, - const std::string& url); typedef std::vector<char> cmCTestSubmitHandlerVectorOfChar; @@ -92,11 +70,8 @@ private: std::string HTTPProxy; int HTTPProxyType; std::string HTTPProxyAuth; - std::string FTPProxy; - int FTPProxyType; std::ostream* LogFile; bool SubmitPart[cmCTest::PartCount]; - bool CDash; bool HasWarnings; bool HasErrors; cmCTest::SetOfStrings Files; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index c936910f8..cf2652afe 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -3,6 +3,7 @@ #include "cmCTestTestHandler.h" #include <algorithm> #include <chrono> +#include <cmath> #include <cmsys/Base64.h> #include <cmsys/Directory.hxx> #include <cmsys/RegularExpression.hxx> @@ -103,7 +104,7 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args, } fname += "/"; fname += testFilename; - readit = this->Makefile->ReadDependentFile(fname.c_str()); + readit = this->Makefile->ReadDependentFile(fname); } if (!readit) { std::string m = "Could not find include file: "; @@ -169,7 +170,7 @@ bool cmCTestAddSubdirectoryCommand::InitialPass( } fname += "/"; fname += testFilename; - readit = this->Makefile->ReadDependentFile(fname.c_str()); + readit = this->Makefile->ReadDependentFile(fname); } if (!readit) { std::string m = "Could not find include file: "; @@ -535,11 +536,20 @@ int cmCTestTestHandler::ProcessHandler() percent = 99; } + std::string passColorCode; + std::string failedColorCode; + if (failed.empty()) { + passColorCode = this->CTest->GetColorCode(cmCTest::Color::GREEN); + } else { + failedColorCode = this->CTest->GetColorCode(cmCTest::Color::RED); + } cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl - << static_cast<int>(percent + .5f) << "% tests passed, " - << failed.size() << " tests failed out of " << total - << std::endl); + << passColorCode << std::lround(percent) << "% tests passed" + << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR) + << ", " << failedColorCode << failed.size() << " tests failed" + << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR) + << " out of " << total << std::endl); if ((!this->CTest->GetLabelsForSubprojects().empty() && this->CTest->GetSubprojectSummary())) { this->PrintLabelOrSubprojectSummary(true); @@ -562,6 +572,8 @@ int cmCTestTestHandler::ProcessHandler() this->StartLogFile("TestsDisabled", ofs); const char* disabled_reason; + cmCTestLog(this->CTest, HANDLER_OUTPUT, + this->CTest->GetColorCode(cmCTest::Color::BLUE)); for (cmCTestTestResult const& dt : disabledTests) { ofs << dt.TestCount << ":" << dt.Name << std::endl; if (dt.CompletionStatus == "Disabled") { @@ -573,6 +585,8 @@ int cmCTestTestHandler::ProcessHandler() "\t" << std::setw(3) << dt.TestCount << " - " << dt.Name << " (" << disabled_reason << ")" << std::endl); } + cmCTestLog(this->CTest, HANDLER_OUTPUT, + this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)); } if (!failed.empty()) { @@ -587,10 +601,17 @@ int cmCTestTestHandler::ProcessHandler() !cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_RETURN_CODE=") && ft.CompletionStatus != "Disabled") { ofs << ft.TestCount << ":" << ft.Name << std::endl; - cmCTestLog(this->CTest, HANDLER_OUTPUT, - "\t" << std::setw(3) << ft.TestCount << " - " << ft.Name - << " (" << this->GetTestStatus(ft) << ")" - << std::endl); + auto testColor = cmCTest::Color::RED; + if (this->GetTestStatus(ft) == "Not Run") { + testColor = cmCTest::Color::YELLOW; + } + cmCTestLog( + this->CTest, HANDLER_OUTPUT, + "\t" << this->CTest->GetColorCode(testColor) << std::setw(3) + << ft.TestCount << " - " << ft.Name << " (" + << this->GetTestStatus(ft) << ")" + << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR) + << std::endl); } } } @@ -1503,7 +1524,7 @@ void cmCTestTestHandler::AddConfigurations( } tempPath = filepath + filename; attempted.push_back(tempPath); - attemptedConfigs.push_back(""); + attemptedConfigs.emplace_back(); if (!ctest->GetConfigType().empty()) { tempPath = filepath; @@ -1526,32 +1547,32 @@ void cmCTestTestHandler::AddConfigurations( tempPath += "Release/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("Release"); + attemptedConfigs.emplace_back("Release"); tempPath = filepath; tempPath += "Debug/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("Debug"); + attemptedConfigs.emplace_back("Debug"); tempPath = filepath; tempPath += "MinSizeRel/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("MinSizeRel"); + attemptedConfigs.emplace_back("MinSizeRel"); tempPath = filepath; tempPath += "RelWithDebInfo/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("RelWithDebInfo"); + attemptedConfigs.emplace_back("RelWithDebInfo"); tempPath = filepath; tempPath += "Deployment/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("Deployment"); + attemptedConfigs.emplace_back("Deployment"); tempPath = filepath; tempPath += "Development/"; tempPath += filename; attempted.push_back(tempPath); - attemptedConfigs.push_back("Deployment"); + attemptedConfigs.emplace_back("Deployment"); } } @@ -1655,7 +1676,7 @@ void cmCTestTestHandler::GetListOfTests() } cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Constructing a list of tests" << std::endl, this->Quiet); - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::CTest); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -1725,7 +1746,7 @@ void cmCTestTestHandler::UseExcludeRegExp() this->UseExcludeRegExpFirst = !this->UseIncludeRegExpFlag; } -const char* cmCTestTestHandler::GetTestStatus(cmCTestTestResult const& result) +std::string cmCTestTestHandler::GetTestStatus(cmCTestTestResult const& result) { static const char* statuses[] = { "Not Run", "Timeout", "SEGFAULT", "ILLEGAL", "INTERRUPT", "NUMERICAL", @@ -1737,7 +1758,7 @@ const char* cmCTestTestHandler::GetTestStatus(cmCTestTestResult const& result) return "No Status"; } if (status == cmCTestTestHandler::OTHER_FAULT) { - return result.ExceptionStatus.c_str(); + return result.ExceptionStatus; } return statuses[status]; } @@ -2126,6 +2147,32 @@ bool cmCTestTestHandler::SetTestsProperties( for (std::string const& t : tests) { for (cmCTestTestProperties& rt : this->TestList) { if (t == rt.Name) { + if (key == "_BACKTRACE_TRIPLES") { + std::vector<std::string> triples; + // allow empty args in the triples + cmSystemTools::ExpandListArgument(val, triples, true); + + // Ensure we have complete triples otherwise the data is corrupt. + if (triples.size() % 3 == 0) { + cmState state; + rt.Backtrace = cmListFileBacktrace(state.CreateBaseSnapshot()); + + // the first entry represents the top of the trace so we need to + // reconstruct the backtrace in reverse + for (size_t i = triples.size(); i >= 3; i -= 3) { + cmListFileContext fc; + fc.FilePath = triples[i - 3]; + long line = 0; + if (!cmSystemTools::StringToLong(triples[i - 2].c_str(), + &line)) { + line = 0; + } + fc.Line = line; + fc.Name = triples[i - 1]; + rt.Backtrace = rt.Backtrace.Push(fc); + } + } + } if (key == "WILL_FAIL") { rt.WillFail = cmSystemTools::IsOn(val); } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index d2694a114..0b557dbcb 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -7,6 +7,7 @@ #include "cmCTestGenericHandler.h" #include "cmDuration.h" +#include "cmListFileCache.h" #include "cmsys/RegularExpression.hxx" #include <chrono> @@ -141,6 +142,8 @@ public: std::set<std::string> FixturesCleanup; std::set<std::string> FixturesRequired; std::set<std::string> RequireSuccessDepends; + // Private test generator properties used to track backtraces + cmListFileBacktrace Backtrace; }; struct cmCTestTestResult @@ -274,7 +277,7 @@ private: */ std::string FindTheExecutable(const char* exe); - const char* GetTestStatus(cmCTestTestResult const&); + std::string GetTestStatus(cmCTestTestResult const&); void ExpandTestsToRunInformation(size_t numPossibleTests); void ExpandTestsToRunInformationForRerunFailed(); diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 57e40ce35..e3b7e9ef3 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -34,9 +34,7 @@ static const char* cmCTestUpdateHandlerUpdateToString(int type) return cmCTestUpdateHandlerUpdateStrings[type]; } -cmCTestUpdateHandler::cmCTestUpdateHandler() -{ -} +cmCTestUpdateHandler::cmCTestUpdateHandler() = default; void cmCTestUpdateHandler::Initialize() { diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx index ec78c1e87..2fe2cd347 100644 --- a/Source/CTest/cmCTestUploadCommand.cxx +++ b/Source/CTest/cmCTestUploadCommand.cxx @@ -9,8 +9,8 @@ #include "cmCTestGenericHandler.h" #include "cmCTestUploadHandler.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler() { @@ -58,7 +58,7 @@ bool cmCTestUploadCommand::CheckArgumentValue(std::string const& arg) std::ostringstream e; e << "File \"" << arg << "\" does not exist. Cannot submit " << "a non-existent file."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); this->ArgumentDoing = ArgumentDoingError; return false; } diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 21c888902..374e73ffb 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -24,9 +24,7 @@ cmCTestVC::cmCTestVC(cmCTest* ct, std::ostream& log) this->Unknown.Rev = "Unknown"; } -cmCTestVC::~cmCTestVC() -{ -} +cmCTestVC::~cmCTestVC() = default; void cmCTestVC::SetCommandLineTool(std::string const& tool) { @@ -79,13 +77,13 @@ bool cmCTestVC::RunChild(char const* const* cmd, OutputParser* out, OutputParser* err, const char* workDir, Encoding encoding) { - this->Log << this->ComputeCommandLine(cmd) << "\n"; + this->Log << cmCTestVC::ComputeCommandLine(cmd) << "\n"; cmsysProcess* cp = cmsysProcess_New(); cmsysProcess_SetCommand(cp, cmd); workDir = workDir ? workDir : this->SourceDirectory.c_str(); cmsysProcess_SetWorkingDirectory(cp, workDir); - this->RunProcess(cp, out, err, encoding); + cmCTestVC::RunProcess(cp, out, err, encoding); int result = cmsysProcess_GetExitValue(cp); cmsysProcess_Delete(cp); return result == 0; diff --git a/Source/CTest/cmParseBlanketJSCoverage.cxx b/Source/CTest/cmParseBlanketJSCoverage.cxx index 308e6f7a3..63d6a15d8 100644 --- a/Source/CTest/cmParseBlanketJSCoverage.cxx +++ b/Source/CTest/cmParseBlanketJSCoverage.cxx @@ -20,7 +20,7 @@ public: { } - virtual ~JSONParser() {} + virtual ~JSONParser() = default; std::string getValue(std::string const& line, int type) { diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx index 5bb64247b..848a034c9 100644 --- a/Source/CTest/cmParseCoberturaCoverage.cxx +++ b/Source/CTest/cmParseCoberturaCoverage.cxx @@ -13,19 +13,12 @@ class cmParseCoberturaCoverage::XMLParser : public cmXMLParser { public: XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont) - : CTest(ctest) + : FilePaths{ cont.SourceDir, cont.BinaryDir } + , CTest(ctest) , Coverage(cont) { - this->InSources = false; - this->InSource = false; - this->SkipThisClass = false; - this->FilePaths.push_back(this->Coverage.SourceDir); - this->FilePaths.push_back(this->Coverage.BinaryDir); - this->CurFileName.clear(); } - ~XMLParser() override {} - protected: void EndElement(const std::string& name) override { @@ -144,9 +137,9 @@ protected: } private: - bool InSources; - bool InSource; - bool SkipThisClass; + bool InSources = false; + bool InSource = false; + bool SkipThisClass = false; std::vector<std::string> FilePaths; typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector FileLinesType; diff --git a/Source/CTest/cmParseDelphiCoverage.cxx b/Source/CTest/cmParseDelphiCoverage.cxx index cc8197951..9eda6f8f3 100644 --- a/Source/CTest/cmParseDelphiCoverage.cxx +++ b/Source/CTest/cmParseDelphiCoverage.cxx @@ -20,7 +20,7 @@ public: { } - virtual ~HTMLParser() {} + virtual ~HTMLParser() = default; bool initializeDelphiFile( std::string const& filename, @@ -44,7 +44,7 @@ public: // Check that the begin is the first non-space string on the line if ((beginPos == line.find_first_not_of(' ')) && beginPos != std::string::npos) { - beginSet.push_back("begin"); + beginSet.emplace_back("begin"); coverageVector.push_back(-1); continue; } diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx index 83dde3f75..072275372 100644 --- a/Source/CTest/cmParseGTMCoverage.cxx +++ b/Source/CTest/cmParseGTMCoverage.cxx @@ -1,5 +1,6 @@ #include "cmParseGTMCoverage.h" +#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestCoverageHandler.h" #include "cmSystemTools.h" @@ -86,6 +87,10 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file) } // Find the full path to the file bool found = this->FindMumpsFile(routine, filepath); + if (!found && cmHasLiteralSuffix(routine, "%")) { + routine.erase(0, 1); + found = this->FindMumpsFile(routine, filepath); + } if (found) { int lineoffset = 0; if (this->FindFunctionInMumpsFile(filepath, function, lineoffset)) { @@ -192,8 +197,8 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line, done = true; } } else { - // all chars except ", (, and % get stored in the arg string - if (cur != '\"' && cur != '(' && cur != '%') { + // all chars except " and ( get stored in the arg string + if (cur != '\"' && cur != '(') { arg.append(1, line[pos]); } } diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx index 31e7cd4d4..b78142a81 100644 --- a/Source/CTest/cmParseJacocoCoverage.cxx +++ b/Source/CTest/cmParseJacocoCoverage.cxx @@ -18,13 +18,8 @@ public: : CTest(ctest) , Coverage(cont) { - this->FilePath.clear(); - this->PackagePath.clear(); - this->PackageName.clear(); } - ~XMLParser() override {} - protected: void EndElement(const std::string& /*name*/) override {} @@ -34,6 +29,7 @@ protected: this->PackageName = atts[1]; this->PackagePath.clear(); } else if (name == "sourcefile") { + this->FilePath.clear(); std::string fileName = atts[1]; if (this->PackagePath.empty()) { diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx index 18412ba35..4a81ee4f7 100644 --- a/Source/CTest/cmParseMumpsCoverage.cxx +++ b/Source/CTest/cmParseMumpsCoverage.cxx @@ -9,6 +9,7 @@ #include <map> #include <string> #include <utility> +#include <vector> cmParseMumpsCoverage::cmParseMumpsCoverage( cmCTestCoverageHandlerContainer& cont, cmCTest* ctest) @@ -17,9 +18,7 @@ cmParseMumpsCoverage::cmParseMumpsCoverage( { } -cmParseMumpsCoverage::~cmParseMumpsCoverage() -{ -} +cmParseMumpsCoverage::~cmParseMumpsCoverage() = default; bool cmParseMumpsCoverage::ReadCoverageFile(const char* file) { diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index c4cf046cf..70ef8dfcd 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -7,7 +7,6 @@ #include "cmCTestTestHandler.h" #include "cmsys/Process.h" -#include <algorithm> #include <fcntl.h> #include <iostream> #include <signal.h> @@ -15,6 +14,7 @@ #if !defined(_WIN32) # include <unistd.h> #endif +#include <utility> #define CM_PROCESS_BUF_SIZE 65536 @@ -69,9 +69,7 @@ cmProcess::cmProcess(cmCTestRunTest& runner) this->StartTime = std::chrono::steady_clock::time_point(); } -cmProcess::~cmProcess() -{ -} +cmProcess::~cmProcess() = default; void cmProcess::SetCommand(const char* command) { diff --git a/Source/Checks/cm_cxx14_check.cpp b/Source/Checks/cm_cxx14_check.cpp index 9369ba261..fff36c916 100644 --- a/Source/Checks/cm_cxx14_check.cpp +++ b/Source/Checks/cm_cxx14_check.cpp @@ -1,8 +1,15 @@ #include <cstdio> +#include <iterator> #include <memory> int main() { + int a[] = { 0, 1, 2 }; + auto ai = std::cbegin(a); + + int b[] = { 2, 1, 0 }; + auto bi = std::cend(b); + std::unique_ptr<int> u(new int(0)); - return *u; + return *u + *ai + *(bi - 1); } diff --git a/Source/Checks/cm_cxx17_check.cpp b/Source/Checks/cm_cxx17_check.cpp index 4e8918454..9ea52c456 100644 --- a/Source/Checks/cm_cxx17_check.cpp +++ b/Source/Checks/cm_cxx17_check.cpp @@ -1,9 +1,18 @@ #include <cstdio> +#include <iterator> #include <memory> #include <unordered_map> int main() { + int a[] = { 0, 1, 2 }; + auto ai = std::cbegin(a); + + int b[] = { 2, 1, 0 }; + auto bi = std::cend(b); + + auto ci = std::size(a); + std::unique_ptr<int> u(new int(0)); - return *u; + return *u + *ai + *(bi - 1) + (3 - static_cast<int>(ci)); } diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake index 1b57fd8e6..fb68ed78c 100644 --- a/Source/Checks/cm_cxx_features.cmake +++ b/Source/Checks/cm_cxx_features.cmake @@ -22,10 +22,12 @@ function(cm_check_cxx_feature name) # Filter out warnings caused by local configuration. string(REGEX REPLACE "[^\n]*warning:[^\n]*directory not found for option[^\n]*" "" check_output "${check_output}") string(REGEX REPLACE "[^\n]*warning:[^\n]*object file compiled with -mlong-branch which is no longer needed[^\n]*" "" check_output "${check_output}") + # Filter out other warnings unrelated to feature checks. + string(REGEX REPLACE "[^\n]*warning:[^\n]*sprintf\\(\\) is often misused, please use snprintf[^\n]*" "" check_output "${check_output}") # Filter out xcodebuild warnings. string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\] warning: [^\n]*" "" check_output "${check_output}") # If using the feature causes warnings, treat it as broken/unavailable. - if(check_output MATCHES "[Ww]arning") + if(check_output MATCHES "(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]") set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE) endif() if(CMake_HAVE_CXX_${FEATURE}) diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index a3e071716..f2982a62c 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -5,7 +5,8 @@ #include "cmCursesMainForm.h" #include "cmCursesStandardIncludes.h" #include "cmDocumentation.h" -#include "cmDocumentationEntry.h" +#include "cmDocumentationEntry.h" // IWYU pragma: keep +#include "cmState.h" #include "cmSystemTools.h" #include "cmake.h" @@ -64,13 +65,6 @@ void onsig(int /*unused*/) } } -void CMakeMessageHandler(const char* message, const char* title, - bool& /*unused*/, void* clientData) -{ - cmCursesForm* self = static_cast<cmCursesForm*>(clientData); - self->AddError(message, title); -} - int main(int argc, char const* const* argv) { cmsys::Encoding::CommandLineArguments encoding_args = @@ -83,19 +77,18 @@ int main(int argc, char const* const* argv) cmDocumentation doc; doc.addCMakeStandardDocSections(); if (doc.CheckOptions(argc, argv)) { - cmake hcm(cmake::RoleInternal); + cmake hcm(cmake::RoleInternal, cmState::Unknown); hcm.SetHomeDirectory(""); hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); - std::vector<cmDocumentationEntry> generators; - hcm.GetGeneratorDocumentation(generators); + auto generators = hcm.GetGeneratorsDocumentation(); doc.SetName("ccmake"); doc.SetSection("Name", cmDocumentationName); doc.SetSection("Usage", cmDocumentationUsage); if (argc == 1) { doc.AppendSection("Usage", cmDocumentationUsageNote); } - doc.SetSection("Generators", generators); + doc.AppendSection("Generators", generators); doc.PrependSection("Options", cmDocumentationOptions); return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1; } @@ -108,7 +101,7 @@ int main(int argc, char const* const* argv) if (strcmp(argv[j], "-debug") == 0) { debug = true; } else { - args.push_back(argv[j]); + args.emplace_back(argv[j]); } } @@ -156,7 +149,10 @@ int main(int argc, char const* const* argv) return 1; } - cmSystemTools::SetMessageCallback(CMakeMessageHandler, myform); + cmSystemTools::SetMessageCallback( + [myform](const char* message, const char* title) { + myform->AddError(message, title); + }); cmCursesForm::CurrentForm = myform; diff --git a/Source/CursesDialog/cmCursesBoolWidget.h b/Source/CursesDialog/cmCursesBoolWidget.h index cdb9478e1..8c9625635 100644 --- a/Source/CursesDialog/cmCursesBoolWidget.h +++ b/Source/CursesDialog/cmCursesBoolWidget.h @@ -12,11 +12,12 @@ class cmCursesMainForm; class cmCursesBoolWidget : public cmCursesWidget { - CM_DISABLE_COPY(cmCursesBoolWidget) - public: cmCursesBoolWidget(int width, int height, int left, int top); + cmCursesBoolWidget(cmCursesBoolWidget const&) = delete; + cmCursesBoolWidget& operator=(cmCursesBoolWidget const&) = delete; + // Description: // Handle user input. Called by the container of this widget // when this widget has focus. Returns true if the input was diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h index 54b2f1fd1..0a69d3a9b 100644 --- a/Source/CursesDialog/cmCursesCacheEntryComposite.h +++ b/Source/CursesDialog/cmCursesCacheEntryComposite.h @@ -13,14 +13,17 @@ class cmake; class cmCursesCacheEntryComposite { - CM_DISABLE_COPY(cmCursesCacheEntryComposite) - public: cmCursesCacheEntryComposite(const std::string& key, int labelwidth, int entrywidth); cmCursesCacheEntryComposite(const std::string& key, cmake* cm, bool isNew, int labelwidth, int entrywidth); ~cmCursesCacheEntryComposite(); + + cmCursesCacheEntryComposite(cmCursesCacheEntryComposite const&) = delete; + cmCursesCacheEntryComposite& operator=(cmCursesCacheEntryComposite const&) = + delete; + const char* GetValue(); friend class cmCursesMainForm; diff --git a/Source/CursesDialog/cmCursesDummyWidget.h b/Source/CursesDialog/cmCursesDummyWidget.h index c509ae773..07b7288ab 100644 --- a/Source/CursesDialog/cmCursesDummyWidget.h +++ b/Source/CursesDialog/cmCursesDummyWidget.h @@ -12,11 +12,12 @@ class cmCursesMainForm; class cmCursesDummyWidget : public cmCursesWidget { - CM_DISABLE_COPY(cmCursesDummyWidget) - public: cmCursesDummyWidget(int width, int height, int left, int top); + cmCursesDummyWidget(cmCursesDummyWidget const&) = delete; + cmCursesDummyWidget& operator=(cmCursesDummyWidget const&) = delete; + // Description: // Handle user input. Called by the container of this widget // when this widget has focus. Returns true if the input was diff --git a/Source/CursesDialog/cmCursesFilePathWidget.h b/Source/CursesDialog/cmCursesFilePathWidget.h index 0a304023e..3f71259d5 100644 --- a/Source/CursesDialog/cmCursesFilePathWidget.h +++ b/Source/CursesDialog/cmCursesFilePathWidget.h @@ -9,10 +9,11 @@ class cmCursesFilePathWidget : public cmCursesPathWidget { - CM_DISABLE_COPY(cmCursesFilePathWidget) - public: cmCursesFilePathWidget(int width, int height, int left, int top); + + 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 249b34936..ddb67deeb 100644 --- a/Source/CursesDialog/cmCursesForm.h +++ b/Source/CursesDialog/cmCursesForm.h @@ -11,12 +11,13 @@ class cmCursesForm { - CM_DISABLE_COPY(cmCursesForm) - public: cmCursesForm(); virtual ~cmCursesForm(); + cmCursesForm(cmCursesForm const&) = delete; + cmCursesForm& operator=(cmCursesForm const&) = delete; + // Description: // Handle user input. virtual void HandleInput() = 0; diff --git a/Source/CursesDialog/cmCursesLabelWidget.cxx b/Source/CursesDialog/cmCursesLabelWidget.cxx index 1dfd4ce47..83aea5a2c 100644 --- a/Source/CursesDialog/cmCursesLabelWidget.cxx +++ b/Source/CursesDialog/cmCursesLabelWidget.cxx @@ -14,9 +14,7 @@ cmCursesLabelWidget::cmCursesLabelWidget(int width, int height, int left, this->SetValue(name); } -cmCursesLabelWidget::~cmCursesLabelWidget() -{ -} +cmCursesLabelWidget::~cmCursesLabelWidget() = default; bool cmCursesLabelWidget::HandleInput(int& /*key*/, cmCursesMainForm* /*fm*/, WINDOW* /*w*/) diff --git a/Source/CursesDialog/cmCursesLabelWidget.h b/Source/CursesDialog/cmCursesLabelWidget.h index aab559b16..2ee9cfca8 100644 --- a/Source/CursesDialog/cmCursesLabelWidget.h +++ b/Source/CursesDialog/cmCursesLabelWidget.h @@ -14,13 +14,14 @@ class cmCursesMainForm; class cmCursesLabelWidget : public cmCursesWidget { - CM_DISABLE_COPY(cmCursesLabelWidget) - public: cmCursesLabelWidget(int width, int height, int left, int top, const std::string& name); ~cmCursesLabelWidget() override; + cmCursesLabelWidget(cmCursesLabelWidget const&) = delete; + cmCursesLabelWidget& operator=(cmCursesLabelWidget const&) = delete; + // Description: // Handle user input. Called by the container of this widget // when this widget has focus. Returns true if the input was diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h index 2bcc15a20..466b4e1b0 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.h +++ b/Source/CursesDialog/cmCursesLongMessageForm.h @@ -13,13 +13,14 @@ class cmCursesLongMessageForm : public cmCursesForm { - CM_DISABLE_COPY(cmCursesLongMessageForm) - public: cmCursesLongMessageForm(std::vector<std::string> const& messages, const char* title); ~cmCursesLongMessageForm() override; + cmCursesLongMessageForm(cmCursesLongMessageForm const&) = delete; + cmCursesLongMessageForm& operator=(cmCursesLongMessageForm const&) = delete; + // Description: // Handle user input. void HandleInput() override; diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 931797a46..8ca7802f1 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -20,15 +20,16 @@ #include <algorithm> #include <stdio.h> #include <string.h> +#include <utility> inline int ctrl(int z) { return (z & 037); } -cmCursesMainForm::cmCursesMainForm(std::vector<std::string> const& args, +cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args, int initWidth) - : Args(args) + : Args(std::move(args)) , InitialWidth(initWidth) { this->NumberOfPages = 0; @@ -37,11 +38,11 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> const& args, this->AdvancedMode = false; this->NumberOfVisibleEntries = 0; this->OkToGenerate = false; - this->HelpMessage.push_back( + this->HelpMessage.emplace_back( "Welcome to ccmake, curses based user interface for CMake."); - this->HelpMessage.push_back(""); - this->HelpMessage.push_back(s_ConstHelpMessage); - this->CMakeInstance = new cmake(cmake::RoleProject); + this->HelpMessage.emplace_back(); + this->HelpMessage.emplace_back(s_ConstHelpMessage); + this->CMakeInstance = new cmake(cmake::RoleProject, cmState::Project); this->CMakeInstance->SetCMakeEditCommand( cmSystemTools::GetCMakeCursesCommand()); @@ -505,12 +506,8 @@ void cmCursesMainForm::UpdateStatusBar(const char* message) pos_form_cursor(this->Form); } -void cmCursesMainForm::UpdateProgress(const char* msg, float prog, void* vp) +void cmCursesMainForm::UpdateProgress(const char* msg, float prog) { - cmCursesMainForm* cm = static_cast<cmCursesMainForm*>(vp); - if (!cm) { - return; - } char tmp[1024]; const char* cmsg = tmp; if (prog >= 0) { @@ -518,8 +515,8 @@ void cmCursesMainForm::UpdateProgress(const char* msg, float prog, void* vp) } else { cmsg = msg; } - cm->UpdateStatusBar(cmsg); - cm->PrintKeys(1); + this->UpdateStatusBar(cmsg); + this->PrintKeys(1); curses_move(1, 1); touchwin(stdscr); refresh(); @@ -535,8 +532,8 @@ int cmCursesMainForm::Configure(int noconfigure) this->PrintKeys(1); touchwin(stdscr); refresh(); - this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress, - this); + this->CMakeInstance->SetProgressCallback( + [this](const char* msg, float prog) { this->UpdateProgress(msg, prog); }); // always save the current gui values to disk this->FillCacheManagerFromUI(); @@ -559,7 +556,7 @@ int cmCursesMainForm::Configure(int noconfigure) } else { retVal = this->CMakeInstance->Configure(); } - this->CMakeInstance->SetProgressCallback(nullptr, nullptr); + this->CMakeInstance->SetProgressCallback(nullptr); keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ @@ -605,8 +602,8 @@ int cmCursesMainForm::Generate() this->PrintKeys(1); touchwin(stdscr); refresh(); - this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress, - this); + this->CMakeInstance->SetProgressCallback( + [this](const char* msg, float prog) { this->UpdateProgress(msg, prog); }); // Get rid of previous errors this->Errors = std::vector<std::string>(); @@ -614,7 +611,7 @@ int cmCursesMainForm::Generate() // run the generate process int retVal = this->CMakeInstance->Generate(); - this->CMakeInstance->SetProgressCallback(nullptr, nullptr); + this->CMakeInstance->SetProgressCallback(nullptr); keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ if (retVal != 0 || !this->Errors.empty()) { @@ -652,7 +649,7 @@ int cmCursesMainForm::Generate() void cmCursesMainForm::AddError(const char* message, const char* /*unused*/) { - this->Errors.push_back(message); + this->Errors.emplace_back(message); } void cmCursesMainForm::RemoveEntry(const char* value) diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h index 2c006cfb8..cc6482fd3 100644 --- a/Source/CursesDialog/cmCursesMainForm.h +++ b/Source/CursesDialog/cmCursesMainForm.h @@ -23,12 +23,13 @@ class cmake; */ class cmCursesMainForm : public cmCursesForm { - CM_DISABLE_COPY(cmCursesMainForm) - public: - cmCursesMainForm(std::vector<std::string> const& args, int initwidth); + cmCursesMainForm(std::vector<std::string> args, int initwidth); ~cmCursesMainForm() override; + cmCursesMainForm(cmCursesMainForm const&) = delete; + cmCursesMainForm& operator=(cmCursesMainForm const&) = delete; + /** * Set the widgets which represent the cache entries. */ @@ -101,8 +102,7 @@ public: /** * Progress callback */ - static void UpdateProgressOld(const char* msg, float prog, void*); - static void UpdateProgress(const char* msg, float prog, void*); + void UpdateProgress(const char* msg, float prog); protected: // Copy the cache values from the user interface to the actual diff --git a/Source/CursesDialog/cmCursesOptionsWidget.h b/Source/CursesDialog/cmCursesOptionsWidget.h index 3e50e2d4c..0128d6a42 100644 --- a/Source/CursesDialog/cmCursesOptionsWidget.h +++ b/Source/CursesDialog/cmCursesOptionsWidget.h @@ -15,11 +15,12 @@ class cmCursesMainForm; class cmCursesOptionsWidget : public cmCursesWidget { - CM_DISABLE_COPY(cmCursesOptionsWidget) - public: cmCursesOptionsWidget(int width, int height, int left, int top); + cmCursesOptionsWidget(cmCursesOptionsWidget const&) = delete; + cmCursesOptionsWidget& operator=(cmCursesOptionsWidget const&) = delete; + // Description: // Handle user input. Called by the container of this widget // when this widget has focus. Returns true if the input was diff --git a/Source/CursesDialog/cmCursesPathWidget.h b/Source/CursesDialog/cmCursesPathWidget.h index bfa0ea343..1eace03a6 100644 --- a/Source/CursesDialog/cmCursesPathWidget.h +++ b/Source/CursesDialog/cmCursesPathWidget.h @@ -14,11 +14,12 @@ class cmCursesMainForm; class cmCursesPathWidget : public cmCursesStringWidget { - CM_DISABLE_COPY(cmCursesPathWidget) - public: cmCursesPathWidget(int width, int height, int left, int top); + cmCursesPathWidget(cmCursesPathWidget const&) = delete; + cmCursesPathWidget& operator=(cmCursesPathWidget const&) = delete; + /** * This method is called when different keys are pressed. The * subclass can have a special implementation handler for this. diff --git a/Source/CursesDialog/cmCursesStringWidget.h b/Source/CursesDialog/cmCursesStringWidget.h index 90310f612..021515ba3 100644 --- a/Source/CursesDialog/cmCursesStringWidget.h +++ b/Source/CursesDialog/cmCursesStringWidget.h @@ -20,11 +20,12 @@ class cmCursesMainForm; class cmCursesStringWidget : public cmCursesWidget { - CM_DISABLE_COPY(cmCursesStringWidget) - public: cmCursesStringWidget(int width, int height, int left, int top); + cmCursesStringWidget(cmCursesStringWidget const&) = delete; + cmCursesStringWidget& operator=(cmCursesStringWidget const&) = delete; + /** * Handle user input. Called by the container of this widget * when this widget has focus. Returns true if the input was diff --git a/Source/CursesDialog/cmCursesWidget.h b/Source/CursesDialog/cmCursesWidget.h index a44c5e6b6..f761f6d8a 100644 --- a/Source/CursesDialog/cmCursesWidget.h +++ b/Source/CursesDialog/cmCursesWidget.h @@ -14,12 +14,13 @@ class cmCursesMainForm; class cmCursesWidget { - CM_DISABLE_COPY(cmCursesWidget) - public: cmCursesWidget(int width, int height, int left, int top); virtual ~cmCursesWidget(); + cmCursesWidget(cmCursesWidget const&) = delete; + cmCursesWidget& operator=(cmCursesWidget const&) = delete; + /** * Handle user input. Called by the container of this widget * when this widget has focus. Returns true if the input was diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx index 6b4fc85f2..58799123f 100644 --- a/Source/LexerParser/cmCommandArgumentLexer.cxx +++ b/Source/LexerParser/cmCommandArgumentLexer.cxx @@ -664,12 +664,14 @@ Modify cmCommandArgumentLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include "cmCommandArgumentParserHelper.h" /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmCommandArgumentParserTokens.h" @@ -2246,3 +2248,5 @@ void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes) BEGIN(ESCAPES); } } + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l index 5927b9ed3..010d54bf5 100644 --- a/Source/LexerParser/cmCommandArgumentLexer.in.l +++ b/Source/LexerParser/cmCommandArgumentLexer.in.l @@ -18,12 +18,14 @@ Modify cmCommandArgumentLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include "cmCommandArgumentParserHelper.h" /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmCommandArgumentParserTokens.h" @@ -145,3 +147,5 @@ void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes) BEGIN(ESCAPES); } } + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmDependsJavaLexer.cxx b/Source/LexerParser/cmDependsJavaLexer.cxx index 36cac61f9..d703e3c95 100644 --- a/Source/LexerParser/cmDependsJavaLexer.cxx +++ b/Source/LexerParser/cmDependsJavaLexer.cxx @@ -860,6 +860,8 @@ Modify cmDependsJavaLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include <iostream> #include "cmDependsJavaParserHelper.h" @@ -867,7 +869,7 @@ Modify cmDependsJavaLexer.cxx: /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmDependsJavaParserTokens.h" @@ -2811,3 +2813,7 @@ void yyfree (void * ptr , yyscan_t yyscanner) } #define YYTABLES_NAME "yytables" + +/*--------------------------------------------------------------------------*/ + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmDependsJavaLexer.in.l b/Source/LexerParser/cmDependsJavaLexer.in.l index 01a0fa302..3dd3c224a 100644 --- a/Source/LexerParser/cmDependsJavaLexer.in.l +++ b/Source/LexerParser/cmDependsJavaLexer.in.l @@ -18,6 +18,8 @@ Modify cmDependsJavaLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include <iostream> #include "cmDependsJavaParserHelper.h" @@ -25,7 +27,7 @@ Modify cmDependsJavaLexer.cxx: /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmDependsJavaParserTokens.h" @@ -173,3 +175,7 @@ null { PRIMITIVE; return jp_NULLLITERAL; } } %% + +/*--------------------------------------------------------------------------*/ + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx index 5400a10e7..e83afa9ea 100644 --- a/Source/LexerParser/cmDependsJavaParser.cxx +++ b/Source/LexerParser/cmDependsJavaParser.cxx @@ -107,7 +107,7 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); #define YYMAXDEPTH 1000000 -#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp); +#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp) #define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval) #define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str)) /* Disable some warnings in the generated code. */ diff --git a/Source/LexerParser/cmDependsJavaParser.y b/Source/LexerParser/cmDependsJavaParser.y index a4e9c5d17..d15cffc56 100644 --- a/Source/LexerParser/cmDependsJavaParser.y +++ b/Source/LexerParser/cmDependsJavaParser.y @@ -36,7 +36,7 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); #define YYMAXDEPTH 1000000 -#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp); +#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp) #define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval) #define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str)) /* Disable some warnings in the generated code. */ diff --git a/Source/LexerParser/cmExprLexer.cxx b/Source/LexerParser/cmExprLexer.cxx index cb246873e..72e59b689 100644 --- a/Source/LexerParser/cmExprLexer.cxx +++ b/Source/LexerParser/cmExprLexer.cxx @@ -664,12 +664,14 @@ Modify cmExprLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include "cmExprParserHelper.h" /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmExprParserTokens.h" @@ -2223,3 +2225,7 @@ void yyfree (void * ptr , yyscan_t yyscanner) } #define YYTABLES_NAME "yytables" + +/*--------------------------------------------------------------------------*/ + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmExprLexer.in.l b/Source/LexerParser/cmExprLexer.in.l index 2197c2ae5..f8a422431 100644 --- a/Source/LexerParser/cmExprLexer.in.l +++ b/Source/LexerParser/cmExprLexer.in.l @@ -18,12 +18,14 @@ Modify cmExprLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #include "cmExprParserHelper.h" /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = yyextra->LexInput(buf, max_size); } + do { result = yyextra->LexInput(buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmExprParserTokens.h" @@ -61,3 +63,7 @@ Modify cmExprLexer.cxx: . { yyextra->UnexpectedChar(yytext[0]); } %% + +/*--------------------------------------------------------------------------*/ + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmFortranLexer.cxx b/Source/LexerParser/cmFortranLexer.cxx index 82048df1d..bcda77c30 100644 --- a/Source/LexerParser/cmFortranLexer.cxx +++ b/Source/LexerParser/cmFortranLexer.cxx @@ -838,6 +838,8 @@ Modify cmFortranLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #undef YY_NO_UNPUT #define cmFortranLexer_cxx @@ -846,7 +848,7 @@ Modify cmFortranLexer.cxx: /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = cmFortranParser_Input(yyextra, buf, max_size); } + do { result = cmFortranParser_Input(yyextra, buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmFortranParserTokens.h" @@ -2610,3 +2612,5 @@ YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner) struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return YY_CURRENT_BUFFER; } + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmFortranLexer.in.l b/Source/LexerParser/cmFortranLexer.in.l index b7e837be0..3d38a7dad 100644 --- a/Source/LexerParser/cmFortranLexer.in.l +++ b/Source/LexerParser/cmFortranLexer.in.l @@ -27,6 +27,8 @@ Modify cmFortranLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + #undef YY_NO_UNPUT #define cmFortranLexer_cxx @@ -35,7 +37,7 @@ Modify cmFortranLexer.cxx: /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = cmFortranParser_Input(yyextra, buf, max_size); } + do { result = cmFortranParser_Input(yyextra, buf, max_size); } while (0) /* Include the set of tokens from the parser. */ #include "cmFortranParserTokens.h" @@ -183,3 +185,5 @@ YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner) struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return YY_CURRENT_BUFFER; } + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmListFileLexer.c b/Source/LexerParser/cmListFileLexer.c index eb373373f..15dcda04a 100644 --- a/Source/LexerParser/cmListFileLexer.c +++ b/Source/LexerParser/cmListFileLexer.c @@ -766,7 +766,7 @@ Modify cmListFileLexer.c: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifdef WIN32 +#ifdef _WIN32 #include "cmsys/Encoding.h" #endif @@ -805,7 +805,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer); /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } + do { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } while (0) /*--------------------------------------------------------------------------*/ diff --git a/Source/LexerParser/cmListFileLexer.in.l b/Source/LexerParser/cmListFileLexer.in.l index 23c7e4915..fdf14d2d3 100644 --- a/Source/LexerParser/cmListFileLexer.in.l +++ b/Source/LexerParser/cmListFileLexer.in.l @@ -18,7 +18,7 @@ Modify cmListFileLexer.c: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifdef WIN32 +#ifdef _WIN32 #include "cmsys/Encoding.h" #endif @@ -57,7 +57,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer); /* Replace the lexer input function. */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) \ - { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } + do { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } while (0) /*--------------------------------------------------------------------------*/ %} diff --git a/Source/QtDialog/AddCacheEntry.cxx b/Source/QtDialog/AddCacheEntry.cxx index 6284ac946..f5e0777bf 100644 --- a/Source/QtDialog/AddCacheEntry.cxx +++ b/Source/QtDialog/AddCacheEntry.cxx @@ -21,8 +21,8 @@ AddCacheEntry::AddCacheEntry(QWidget* p, const QStringList& varNames, , VarTypes(varTypes) { this->setupUi(this); - for (int i = 0; i < NumTypes; i++) { - this->Type->addItem(TypeStrings[i]); + for (auto const& elem : TypeStrings) { + this->Type->addItem(elem); } QWidget* cb = new QCheckBox(); QWidget* path = new QCMakePathEditor(); @@ -32,12 +32,12 @@ AddCacheEntry::AddCacheEntry(QWidget* p, const QStringList& varNames, this->StackedWidget->addWidget(path); this->StackedWidget->addWidget(filepath); this->StackedWidget->addWidget(string); - this->setTabOrder(this->Name, this->Type); - this->setTabOrder(this->Type, cb); - this->setTabOrder(cb, path); - this->setTabOrder(path, filepath); - this->setTabOrder(filepath, string); - this->setTabOrder(string, this->Description); + AddCacheEntry::setTabOrder(this->Name, this->Type); + AddCacheEntry::setTabOrder(this->Type, cb); + AddCacheEntry::setTabOrder(cb, path); + AddCacheEntry::setTabOrder(path, filepath); + AddCacheEntry::setTabOrder(filepath, string); + AddCacheEntry::setTabOrder(string, this->Description); QCompleter* completer = new QCompleter(this->VarNames, this); this->Name->setCompleter(completer); connect(completer, SIGNAL(activated(const QString&)), this, diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 330b74729..9ce032384 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -19,9 +19,20 @@ if (Qt5Widgets_FOUND) macro(qt4_add_resources) qt5_add_resources(${ARGN}) endmacro() + set(CMake_QT_LIBRARIES ${Qt5Widgets_LIBRARIES}) set(QT_QTMAIN_LIBRARY ${Qt5Core_QTMAIN_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() + endif() + # Remove this when the minimum version of Qt is 4.6. add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0) diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 7b980a01f..cd30ad547 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -30,7 +30,8 @@ static const char* cmDocumentationUsage[][2] = { { nullptr, " cmake-gui [options]\n" " cmake-gui [options] <path-to-source>\n" - " cmake-gui [options] <path-to-existing-build>" }, + " cmake-gui [options] <path-to-existing-build>\n" + " cmake-gui [options] -S <path-to-source> -B <path-to-build>\n" }, { nullptr, nullptr } }; @@ -64,13 +65,12 @@ int main(int argc, char** argv) doc.addCMakeStandardDocSections(); if (argc2 > 1 && doc.CheckOptions(argc2, argv2)) { // Construct and print requested documentation. - cmake hcm(cmake::RoleInternal); + cmake hcm(cmake::RoleInternal, cmState::Unknown); hcm.SetHomeDirectory(""); hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); - std::vector<cmDocumentationEntry> generators; - hcm.GetGeneratorDocumentation(generators); + auto generators = hcm.GetGeneratorsDocumentation(); doc.SetName("cmake"); doc.SetSection("Name", cmDocumentationName); doc.SetSection("Usage", cmDocumentationUsage); @@ -130,36 +130,66 @@ int main(int argc, char** argv) QTranslator translator; QString transfile = QString("cmake_%1").arg(QLocale::system().name()); translator.load(transfile, translationsDir.path()); - app.installTranslator(&translator); + QApplication::installTranslator(&translator); // app setup - app.setApplicationName("CMakeSetup"); - app.setOrganizationName("Kitware"); + QApplication::setApplicationName("CMakeSetup"); + QApplication::setOrganizationName("Kitware"); QIcon appIcon; appIcon.addFile(":/Icons/CMakeSetup32.png"); appIcon.addFile(":/Icons/CMakeSetup128.png"); - app.setWindowIcon(appIcon); + QApplication::setWindowIcon(appIcon); CMakeSetupDialog dialog; dialog.show(); - cmsys::CommandLineArguments arg; - arg.Initialize(argc2, argv2); + QStringList args = QApplication::arguments(); std::string binaryDirectory; std::string sourceDirectory; - typedef cmsys::CommandLineArguments argT; - arg.AddArgument("-B", argT::CONCAT_ARGUMENT, &binaryDirectory, - "Binary Directory"); - arg.AddArgument("-S", argT::CONCAT_ARGUMENT, &sourceDirectory, - "Source Directory"); - // do not complain about unknown options - arg.StoreUnusedArguments(true); - arg.Parse(); + for (int i = 1; i < args.size(); ++i) { + const QString& arg = args[i]; + if (arg.startsWith("-S")) { + QString path = arg.mid(2); + if (path.isEmpty()) { + ++i; + if (i >= args.size()) { + std::cerr << "No source directory specified for -S" << std::endl; + return 1; + } + path = args[i]; + if (path[0] == '-') { + std::cerr << "No source directory specified for -S" << std::endl; + return 1; + } + } + + sourceDirectory = + cmSystemTools::CollapseFullPath(path.toLocal8Bit().data()); + cmSystemTools::ConvertToUnixSlashes(sourceDirectory); + } else if (arg.startsWith("-B")) { + QString path = arg.mid(2); + if (path.isEmpty()) { + ++i; + if (i >= args.size()) { + std::cerr << "No build directory specified for -B" << std::endl; + return 1; + } + path = args[i]; + if (path[0] == '-') { + std::cerr << "No build directory specified for -B" << std::endl; + return 1; + } + } + + binaryDirectory = + cmSystemTools::CollapseFullPath(path.toLocal8Bit().data()); + cmSystemTools::ConvertToUnixSlashes(binaryDirectory); + } + } if (!sourceDirectory.empty() && !binaryDirectory.empty()) { dialog.setSourceDirectory(QString::fromLocal8Bit(sourceDirectory.c_str())); dialog.setBinaryDirectory(QString::fromLocal8Bit(binaryDirectory.c_str())); } else { - QStringList args = app.arguments(); if (args.count() == 2) { std::string filePath = cmSystemTools::CollapseFullPath(args[1].toLocal8Bit().data()); @@ -189,7 +219,7 @@ int main(int argc, char** argv) } } - return app.exec(); + return QApplication::exec(); } #if defined(Q_OS_MAC) @@ -216,12 +246,11 @@ static bool cmOSXInstall(std::string const& dir, std::string const& tool) if (symlink(tool.c_str(), link.c_str()) == 0) { std::cerr << "Linked: '" << link << "' -> '" << tool << "'\n"; return true; - } else { - int err = errno; - std::cerr << "Failed: '" << link << "' -> '" << tool - << "': " << strerror(err) << "\n"; - return false; } + int err = errno; + std::cerr << "Failed: '" << link << "' -> '" << tool + << "': " << strerror(err) << "\n"; + return false; } static int cmOSXInstall(std::string dir) { diff --git a/Source/QtDialog/CMakeSetup128.png b/Source/QtDialog/CMakeSetup128.png Binary files differindex 728ef0269..32984e104 100644 --- a/Source/QtDialog/CMakeSetup128.png +++ b/Source/QtDialog/CMakeSetup128.png diff --git a/Source/QtDialog/CMakeSetup32.png b/Source/QtDialog/CMakeSetup32.png Binary files differindex 1c36b31d0..78df82f15 100644 --- a/Source/QtDialog/CMakeSetup32.png +++ b/Source/QtDialog/CMakeSetup32.png diff --git a/Source/QtDialog/CMakeSetup64.png b/Source/QtDialog/CMakeSetup64.png Binary files differindex 44eb17173..5c2dbf552 100644 --- a/Source/QtDialog/CMakeSetup64.png +++ b/Source/QtDialog/CMakeSetup64.png diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 3761bd363..72cce9f50 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -21,6 +21,11 @@ #include <QToolButton> #include <QUrl> +#ifdef QT_WINEXTRAS +# include <QWinTaskbarButton> +# include <QWinTaskbarProgress> +#endif + #include "AddCacheEntry.h" #include "FirstConfigure.h" #include "QCMake.h" @@ -294,6 +299,12 @@ void CMakeSetupDialog::initialize() } else { this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text()); } + +#ifdef QT_WINEXTRAS + this->TaskbarButton = new QWinTaskbarButton(this); + this->TaskbarButton->setWindow(this->windowHandle()); + this->TaskbarButton->setOverlayIcon(QIcon(":/loading.png")); +#endif } CMakeSetupDialog::~CMakeSetupDialog() @@ -381,6 +392,10 @@ void CMakeSetupDialog::doConfigure() this->CacheValues->scrollToTop(); } this->ProgressBar->reset(); + +#ifdef QT_WINEXTRAS + this->TaskbarButton->progress()->reset(); +#endif } bool CMakeSetupDialog::doConfigureInternal() @@ -495,6 +510,9 @@ void CMakeSetupDialog::doGenerate() this->enterState(ReadyConfigure); this->ProgressBar->reset(); +#ifdef QT_WINEXTRAS + this->TaskbarButton->progress()->reset(); +#endif this->ConfigureNeeded = true; } @@ -674,6 +692,12 @@ void CMakeSetupDialog::showProgress(const QString& /*msg*/, float percent) { percent = (percent * ProgressFactor) + ProgressOffset; this->ProgressBar->setValue(qRound(percent * 100)); + +#ifdef QT_WINEXTRAS + QWinTaskbarProgress* progress = this->TaskbarButton->progress(); + progress->setVisible(true); + progress->setValue(qRound(percent * 100)); +#endif } void CMakeSetupDialog::error(const QString& msg) @@ -727,6 +751,7 @@ bool CMakeSetupDialog::setupFirstConfigure() if (dialog.exec() == QDialog::Accepted) { dialog.saveToSettings(); this->CMakeThread->cmakeInstance()->setGenerator(dialog.getGenerator()); + this->CMakeThread->cmakeInstance()->setPlatform(dialog.getPlatform()); this->CMakeThread->cmakeInstance()->setToolset(dialog.getToolset()); QCMakeCacheModel* m = this->CacheValues->cacheModel(); diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h index 1cce35c0b..39c1053cb 100644 --- a/Source/QtDialog/CMakeSetupDialog.h +++ b/Source/QtDialog/CMakeSetupDialog.h @@ -15,6 +15,10 @@ class CMakeCacheModel; class QProgressBar; class QToolButton; +#ifdef QT_WINEXTRAS +class QWinTaskbarButton; +#endif + /// Qt user interface for CMake class CMakeSetupDialog : public QMainWindow @@ -118,6 +122,10 @@ protected: QEventLoop LocalLoop; +#ifdef QT_WINEXTRAS + QWinTaskbarButton* TaskbarButton; +#endif + float ProgressOffset; float ProgressFactor; }; diff --git a/Source/QtDialog/Delete16.png b/Source/QtDialog/Delete16.png Binary files differindex 16989fee1..9d2f2b7ec 100644 --- a/Source/QtDialog/Delete16.png +++ b/Source/QtDialog/Delete16.png diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx index 88ce7cb8a..f28e1a821 100644 --- a/Source/QtDialog/FirstConfigure.cxx +++ b/Source/QtDialog/FirstConfigure.cxx @@ -16,8 +16,12 @@ StartCompilerSetup::StartCompilerSetup(QWidget* p) this->GeneratorOptions = new QComboBox(this); l->addWidget(this->GeneratorOptions); + // Add the generator platform + this->PlatformFrame = CreatePlatformWidgets(); + l->addWidget(PlatformFrame); + // Add the ability to specify toolset (-T parameter) - ToolsetFrame = CreateToolsetWidgets(); + this->ToolsetFrame = CreateToolsetWidgets(); l->addWidget(ToolsetFrame); l->addSpacing(6); @@ -45,7 +49,7 @@ StartCompilerSetup::StartCompilerSetup(QWidget* p) SLOT(onSelectionChanged(bool))); QObject::connect(this->CompilerSetupOptions[3], SIGNAL(toggled(bool)), this, SLOT(onSelectionChanged(bool))); - QObject::connect(GeneratorOptions, + QObject::connect(this->GeneratorOptions, SIGNAL(currentIndexChanged(QString const&)), this, SLOT(onGeneratorChanged(QString const&))); } @@ -65,10 +69,25 @@ QFrame* StartCompilerSetup::CreateToolsetWidgets() return frame; } -StartCompilerSetup::~StartCompilerSetup() +QFrame* StartCompilerSetup::CreatePlatformWidgets() { + QFrame* frame = new QFrame(this); + QVBoxLayout* l = new QVBoxLayout(frame); + l->setContentsMargins(0, 0, 0, 0); + + this->PlatformLabel = new QLabel(tr("Optional platform for generator")); + l->addWidget(this->PlatformLabel); + + this->PlatformOptions = new QComboBox(frame); + this->PlatformOptions->setEditable(true); + + l->addWidget(this->PlatformOptions); + + return frame; } +StartCompilerSetup::~StartCompilerSetup() = default; + void StartCompilerSetup::setGenerators( std::vector<cmake::GeneratorInfo> const& gens) { @@ -80,6 +99,26 @@ void StartCompilerSetup::setGenerators( for (it = gens.begin(); it != gens.end(); ++it) { generator_list.append(QString::fromLocal8Bit(it->name.c_str())); + if (it->supportsPlatform) { + this->GeneratorsSupportingPlatform.append( + QString::fromLocal8Bit(it->name.c_str())); + + this + ->GeneratorDefaultPlatform[QString::fromLocal8Bit(it->name.c_str())] = + QString::fromLocal8Bit(it->defaultPlatform.c_str()); + + std::vector<std::string>::const_iterator platformIt = + it->supportedPlatforms.cbegin(); + while (platformIt != it->supportedPlatforms.cend()) { + + this->GeneratorSupportedPlatforms.insert( + QString::fromLocal8Bit(it->name.c_str()), + QString::fromLocal8Bit((*platformIt).c_str())); + + platformIt++; + } + } + if (it->supportsToolset) { this->GeneratorsSupportingToolset.append( QString::fromLocal8Bit(it->name.c_str())); @@ -102,6 +141,11 @@ QString StartCompilerSetup::getGenerator() const return this->GeneratorOptions->currentText(); }; +QString StartCompilerSetup::getPlatform() const +{ + return this->PlatformOptions->currentText(); +}; + QString StartCompilerSetup::getToolset() const { return this->Toolset->text(); @@ -136,6 +180,31 @@ void StartCompilerSetup::onSelectionChanged(bool on) void StartCompilerSetup::onGeneratorChanged(QString const& name) { + // Display the generator platform for the generators supporting it + if (GeneratorsSupportingPlatform.contains(name)) { + + // Change the label title to include the default platform + std::string label = "Optional platform for generator"; + label += "(if empty, generator uses: "; + label += this->GeneratorDefaultPlatform[name].toStdString(); + label += ")"; + this->PlatformLabel->setText(tr(label.c_str())); + + // Regenerate the list of supported platform + this->PlatformOptions->clear(); + QStringList platform_list; + platform_list.append(""); + + QList<QString> platforms = this->GeneratorSupportedPlatforms.values(name); + platform_list.append(platforms); + + this->PlatformOptions->addItems(platform_list); + PlatformFrame->show(); + } else { + PlatformFrame->hide(); + } + + // Display the toolset box for the generators supporting it if (GeneratorsSupportingToolset.contains(name)) { ToolsetFrame->show(); } else { @@ -166,9 +235,7 @@ NativeCompilerSetup::NativeCompilerSetup(QWidget* p) this->setupUi(c); } -NativeCompilerSetup::~NativeCompilerSetup() -{ -} +NativeCompilerSetup::~NativeCompilerSetup() = default; QString NativeCompilerSetup::getCCompiler() const { @@ -230,9 +297,7 @@ CrossCompilerSetup::CrossCompilerSetup(QWidget* p) this->registerField("systemName*", this->systemName); } -CrossCompilerSetup::~CrossCompilerSetup() -{ -} +CrossCompilerSetup::~CrossCompilerSetup() = default; QString CrossCompilerSetup::getCCompiler() const { @@ -343,9 +408,7 @@ ToolchainCompilerSetup::ToolchainCompilerSetup(QWidget* p) l->addWidget(this->ToolchainFile); } -ToolchainCompilerSetup::~ToolchainCompilerSetup() -{ -} +ToolchainCompilerSetup::~ToolchainCompilerSetup() = default; QString ToolchainCompilerSetup::toolchainFile() const { @@ -375,9 +438,7 @@ FirstConfigure::FirstConfigure() this->setPage(ToolchainSetup, this->mToolchainCompilerSetupPage); } -FirstConfigure::~FirstConfigure() -{ -} +FirstConfigure::~FirstConfigure() = default; void FirstConfigure::setGenerators( std::vector<cmake::GeneratorInfo> const& gens) @@ -390,6 +451,11 @@ QString FirstConfigure::getGenerator() const return this->mStartCompilerSetupPage->getGenerator(); } +QString FirstConfigure::getPlatform() const +{ + return this->mStartCompilerSetupPage->getPlatform(); +} + QString FirstConfigure::getToolset() const { return this->mStartCompilerSetupPage->getToolset(); diff --git a/Source/QtDialog/FirstConfigure.h b/Source/QtDialog/FirstConfigure.h index abfa03fd8..d1db5bff6 100644 --- a/Source/QtDialog/FirstConfigure.h +++ b/Source/QtDialog/FirstConfigure.h @@ -35,6 +35,7 @@ public: void setCurrentGenerator(const QString& gen); QString getGenerator() const; QString getToolset() const; + QString getPlatform() const; bool defaultSetup() const; bool compilerSetup() const; @@ -56,10 +57,17 @@ protected: QFrame* ToolsetFrame; QLineEdit* Toolset; QLabel* ToolsetLabel; + QFrame* PlatformFrame; + QComboBox* PlatformOptions; + QLabel* PlatformLabel; QStringList GeneratorsSupportingToolset; + QStringList GeneratorsSupportingPlatform; + QMultiMap<QString, QString> GeneratorSupportedPlatforms; + QMap<QString, QString> GeneratorDefaultPlatform; private: QFrame* CreateToolsetWidgets(); + QFrame* CreatePlatformWidgets(); }; //! the page that gives basic options for native compilers @@ -159,6 +167,7 @@ public: void setGenerators(std::vector<cmake::GeneratorInfo> const& gens); QString getGenerator() const; + QString getPlatform() const; QString getToolset() const; bool defaultSetup() const; diff --git a/Source/QtDialog/Plus16.png b/Source/QtDialog/Plus16.png Binary files differindex 552f6f004..1c33bc763 100644 --- a/Source/QtDialog/Plus16.png +++ b/Source/QtDialog/Plus16.png diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 0133b88b3..a073c3064 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -23,19 +23,30 @@ QCMake::QCMake(QObject* p) cmSystemTools::DisableRunCommandOutput(); cmSystemTools::SetRunCommandHideConsole(true); - cmSystemTools::SetMessageCallback(QCMake::messageCallback, this); - cmSystemTools::SetStdoutCallback(QCMake::stdoutCallback, this); - cmSystemTools::SetStderrCallback(QCMake::stderrCallback, this); - this->CMakeInstance = new cmake(cmake::RoleProject); + cmSystemTools::SetMessageCallback( + [this](const char* msg, const char* title) { + this->messageCallback(msg, title); + }); + cmSystemTools::SetStdoutCallback( + [this](std::string const& msg) { this->stdoutCallback(msg); }); + cmSystemTools::SetStderrCallback( + [this](std::string const& msg) { this->stderrCallback(msg); }); + + this->CMakeInstance = new cmake(cmake::RoleProject, cmState::Project); this->CMakeInstance->SetCMakeEditCommand( cmSystemTools::GetCMakeGUICommand()); - this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this); + this->CMakeInstance->SetProgressCallback( + [this](const char* msg, float percent) { + this->progressCallback(msg, percent); + }); - cmSystemTools::SetInterruptCallback(QCMake::interruptCallback, this); + cmSystemTools::SetInterruptCallback( + [this] { return this->interruptCallback(); }); std::vector<cmake::GeneratorInfo> generators; - this->CMakeInstance->GetRegisteredGenerators(generators); + this->CMakeInstance->GetRegisteredGenerators( + generators, /*includeNamesWithPlatform=*/false); std::vector<cmake::GeneratorInfo>::const_iterator it; for (it = generators.begin(); it != generators.end(); ++it) { @@ -74,6 +85,7 @@ void QCMake::setBinaryDirectory(const QString& _dir) cmState* state = this->CMakeInstance->GetState(); this->setGenerator(QString()); this->setToolset(QString()); + this->setPlatform(QString()); if (!this->CMakeInstance->LoadCache( this->BinaryDirectory.toLocal8Bit().data())) { QDir testDir(this->BinaryDirectory); @@ -102,6 +114,12 @@ void QCMake::setBinaryDirectory(const QString& _dir) this->setGenerator(QString::fromLocal8Bit(curGen.c_str())); } + const char* platform = + state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); + if (platform) { + this->setPlatform(QString::fromLocal8Bit(platform)); + } + const char* toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); if (toolset) { this->setToolset(QString::fromLocal8Bit(toolset)); @@ -119,6 +137,14 @@ void QCMake::setGenerator(const QString& gen) } } +void QCMake::setPlatform(const QString& platform) +{ + if (this->Platform != platform) { + this->Platform = platform; + emit this->platformChanged(this->Platform); + } +} + void QCMake::setToolset(const QString& toolset) { if (this->Toolset != toolset) { @@ -140,7 +166,8 @@ void QCMake::configure() this->CMakeInstance->SetGlobalGenerator( this->CMakeInstance->CreateGlobalGenerator( this->Generator.toLocal8Bit().data())); - this->CMakeInstance->SetGeneratorPlatform(""); + this->CMakeInstance->SetGeneratorPlatform( + this->Platform.toLocal8Bit().data()); this->CMakeInstance->SetGeneratorToolset(this->Toolset.toLocal8Bit().data()); this->CMakeInstance->LoadCache(); this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode); @@ -313,46 +340,40 @@ void QCMake::interrupt() this->InterruptFlag.ref(); } -bool QCMake::interruptCallback(void* cd) +bool QCMake::interruptCallback() { - QCMake* self = reinterpret_cast<QCMake*>(cd); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) - return self->InterruptFlag; + return this->InterruptFlag; #else - return self->InterruptFlag.load(); + return this->InterruptFlag.load(); #endif } -void QCMake::progressCallback(const char* msg, float percent, void* cd) +void QCMake::progressCallback(const char* msg, float percent) { - QCMake* self = reinterpret_cast<QCMake*>(cd); if (percent >= 0) { - emit self->progressChanged(QString::fromLocal8Bit(msg), percent); + emit this->progressChanged(QString::fromLocal8Bit(msg), percent); } else { - emit self->outputMessage(QString::fromLocal8Bit(msg)); + emit this->outputMessage(QString::fromLocal8Bit(msg)); } QCoreApplication::processEvents(); } -void QCMake::messageCallback(const char* msg, const char* /*title*/, - bool& /*stop*/, void* cd) +void QCMake::messageCallback(const char* msg, const char* /*title*/) { - QCMake* self = reinterpret_cast<QCMake*>(cd); - emit self->errorMessage(QString::fromLocal8Bit(msg)); + emit this->errorMessage(QString::fromLocal8Bit(msg)); QCoreApplication::processEvents(); } -void QCMake::stdoutCallback(const char* msg, size_t len, void* cd) +void QCMake::stdoutCallback(std::string const& msg) { - QCMake* self = reinterpret_cast<QCMake*>(cd); - emit self->outputMessage(QString::fromLocal8Bit(msg, int(len))); + emit this->outputMessage(QString::fromStdString(msg)); QCoreApplication::processEvents(); } -void QCMake::stderrCallback(const char* msg, size_t len, void* cd) +void QCMake::stderrCallback(std::string const& msg) { - QCMake* self = reinterpret_cast<QCMake*>(cd); - emit self->outputMessage(QString::fromLocal8Bit(msg, int(len))); + emit this->outputMessage(QString::fromStdString(msg)); QCoreApplication::processEvents(); } diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h index 4b3920aaf..ef4d2a1a1 100644 --- a/Source/QtDialog/QCMake.h +++ b/Source/QtDialog/QCMake.h @@ -75,6 +75,8 @@ public slots: /// set the desired generator to use void setGenerator(const QString& generator); /// set the desired generator to use + void setPlatform(const QString& platform); + /// set the desired generator to use void setToolset(const QString& toolset); /// do the configure step void configure(); @@ -155,6 +157,8 @@ signals: void debugOutputChanged(bool); /// signal when the toolset changes void toolsetChanged(const QString& toolset); + /// signal when the platform changes + void platformChanged(const QString& platform); /// signal when open is done void openDone(bool successful); /// signal when open is done @@ -163,18 +167,19 @@ signals: protected: cmake* CMakeInstance; - static bool interruptCallback(void*); - static void progressCallback(const char* msg, float percent, void* cd); - static void messageCallback(const char* msg, const char* title, bool&, - void* cd); - static void stdoutCallback(const char* msg, size_t len, void* cd); - static void stderrCallback(const char* msg, size_t len, void* cd); + bool interruptCallback(); + void progressCallback(const char* msg, float percent); + void messageCallback(const char* msg, const char* title); + void stdoutCallback(std::string const& msg); + void stderrCallback(std::string const& msg); + bool WarnUninitializedMode; bool WarnUnusedMode; bool WarnUnusedAllMode; QString SourceDirectory; QString BinaryDirectory; QString Generator; + QString Platform; QString Toolset; std::vector<cmake::GeneratorInfo> AvailableGenerators; QString CMakeExecutable; diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx index 7d3aa57e6..78a271024 100644 --- a/Source/QtDialog/QCMakeCacheView.cxx +++ b/Source/QtDialog/QCMakeCacheView.cxx @@ -186,9 +186,7 @@ QCMakeCacheModel::QCMakeCacheModel(QObject* p) this->setHorizontalHeaderLabels(labels); } -QCMakeCacheModel::~QCMakeCacheModel() -{ -} +QCMakeCacheModel::~QCMakeCacheModel() = default; static uint qHash(const QCMakeProperty& p) { @@ -248,9 +246,9 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props) } } else if (this->View == GroupView) { QMap<QString, QCMakePropertyList> newPropsTree; - this->breakProperties(newProps, newPropsTree); + QCMakeCacheModel::breakProperties(newProps, newPropsTree); QMap<QString, QCMakePropertyList> newPropsTree2; - this->breakProperties(newProps2, newPropsTree2); + QCMakeCacheModel::breakProperties(newProps2, newPropsTree2); QStandardItem* root = this->invisibleRootItem(); diff --git a/Source/QtDialog/QCMakeWidgets.cxx b/Source/QtDialog/QCMakeWidgets.cxx index b544b8613..eab418fe7 100644 --- a/Source/QtDialog/QCMakeWidgets.cxx +++ b/Source/QtDialog/QCMakeWidgets.cxx @@ -7,10 +7,11 @@ #include <QFileInfo> #include <QResizeEvent> #include <QToolButton> +#include <utility> -QCMakeFileEditor::QCMakeFileEditor(QWidget* p, const QString& var) +QCMakeFileEditor::QCMakeFileEditor(QWidget* p, QString var) : QLineEdit(p) - , Variable(var) + , Variable(std::move(var)) { this->ToolButton = new QToolButton(this); this->ToolButton->setText("..."); diff --git a/Source/QtDialog/QCMakeWidgets.h b/Source/QtDialog/QCMakeWidgets.h index e63c19753..5d2368eab 100644 --- a/Source/QtDialog/QCMakeWidgets.h +++ b/Source/QtDialog/QCMakeWidgets.h @@ -18,7 +18,7 @@ class QCMakeFileEditor : public QLineEdit { Q_OBJECT public: - QCMakeFileEditor(QWidget* p, const QString& var); + QCMakeFileEditor(QWidget* p, QString var); protected slots: virtual void chooseFile() = 0; signals: diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 53f5593e4..a840f17c1 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -10,11 +10,11 @@ #include "cmCustomCommandLines.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSourceFile.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -361,7 +361,7 @@ bool cmAddCustomCommandCommand::InitialPass( } else { bool issueMessage = true; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0050)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0050) << "\n"; @@ -372,7 +372,7 @@ bool cmAddCustomCommandCommand::InitialPass( case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; break; } @@ -380,7 +380,7 @@ bool cmAddCustomCommandCommand::InitialPass( e << "The SOURCE signatures of add_custom_command are no longer " "supported."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index ddd9b7082..8240d3ef2 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -9,10 +9,10 @@ #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -183,19 +183,19 @@ bool cmAddCustomTargetCommand::InitialPass( if (commandLines.empty() && !byproducts.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "BYPRODUCTS may not be specified without any COMMAND"); return true; } if (commandLines.empty() && uses_terminal) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "USES_TERMINAL may not be specified without any COMMAND"); return true; } if (commandLines.empty() && command_expand_lists) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "COMMAND_EXPAND_LISTS may not be specified without any COMMAND"); return true; } diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx index a73b57e82..021bd2951 100644 --- a/Source/cmAddDependenciesCommand.cxx +++ b/Source/cmAddDependenciesCommand.cxx @@ -5,8 +5,8 @@ #include <sstream> #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -24,7 +24,7 @@ bool cmAddDependenciesCommand::InitialPass( std::ostringstream e; e << "Cannot add target-level dependencies to alias target \"" << target_name << "\".\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } if (cmTarget* target = this->Makefile->FindTargetToUse(target_name)) { std::vector<std::string>::const_iterator s = args.begin(); @@ -40,7 +40,7 @@ bool cmAddDependenciesCommand::InitialPass( << "by the add_executable, add_library, or add_custom_target commands. " << "If you want to add file-level dependencies see the DEPENDS option " << "of the add_custom_target and add_custom_command commands."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } return true; diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index fae806324..514933303 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -7,11 +7,11 @@ #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -259,7 +259,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, << (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE") << " option but the target platform does not support dynamic linking. " "Building a STATIC library instead. This may lead to problems."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); type = cmStateEnums::STATIC_LIBRARY; } @@ -275,7 +275,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation( &reason)) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The OBJECT library type may not be used for IMPORTED libraries" + reason + "."); return true; @@ -307,7 +307,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, // A non-imported target may not have UNKNOWN type. if (type == cmStateEnums::UNKNOWN_LIBRARY) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The UNKNOWN library type may be used only for IMPORTED libraries."); return true; } diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx index 75bd6fba4..75e5aa43f 100644 --- a/Source/cmAddSubDirectoryCommand.cxx +++ b/Source/cmAddSubDirectoryCommand.cxx @@ -20,7 +20,7 @@ bool cmAddSubDirectoryCommand::InitialPass( } // store the binpath - std::string const& srcArg = args[0]; + std::string const& srcArg = args.front(); std::string binArg; bool excludeFromAll = false; @@ -84,10 +84,10 @@ bool cmAddSubDirectoryCommand::InitialPass( const std::string& bin = this->Makefile->GetCurrentBinaryDirectory(); size_t srcLen = src.length(); size_t binLen = bin.length(); - if (srcLen > 0 && src[srcLen - 1] == '/') { + if (srcLen > 0 && src.back() == '/') { --srcLen; } - if (binLen > 0 && bin[binLen - 1] == '/') { + if (binLen > 0 && bin.back() == '/') { --binLen; } binPath = bin.substr(0, binLen) + srcPath.substr(srcLen); diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index bbd3e8ea4..d38b0d125 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -61,8 +61,8 @@ struct cmStrCmp : m_test(test) { } - cmStrCmp(const std::string& test) - : m_test(test) + cmStrCmp(std::string test) + : m_test(std::move(test)) { } @@ -336,6 +336,14 @@ std::reverse_iterator<Iter> cmMakeReverseIterator(Iter it) return std::reverse_iterator<Iter>(it); } +inline bool cmHasPrefix(std::string const& str, std::string const& prefix) +{ + if (str.size() < prefix.size()) { + return false; + } + return str.compare(0, prefix.size(), prefix) == 0; +} + inline bool cmHasSuffix(const std::string& str, const std::string& suffix) { if (str.size() < suffix.size()) { @@ -396,6 +404,12 @@ constexpr #endif +template <typename T> +int isize(const T& t) +{ + return static_cast<int>(cm::size(t)); +} + #if __cplusplus >= 201402L || defined(_MSVC_LANG) && _MSVC_LANG >= 201402L using std::cbegin; diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 60317818b..6e5109aa1 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -135,7 +135,7 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, return; } break; - }; + } #if !defined(_WIN32) || defined(__CYGWIN__) if (archive_read_disk_set_standard_lookup(this->Disk) != ARCHIVE_OK) { this->Error = "archive_read_disk_set_standard_lookup: "; @@ -178,7 +178,7 @@ bool cmArchiveWrite::Add(std::string path, size_t skip, const char* prefix, bool recursive) { if (this->Okay()) { - if (!path.empty() && path[path.size() - 1] == '/') { + if (!path.empty() && path.back() == '/') { path.erase(path.size() - 1); } this->AddPath(path.c_str(), skip, prefix, recursive); diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h index 6c678acbe..6ecdd630c 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -40,9 +40,6 @@ private: */ class cmArchiveWrite { - typedef void (cmArchiveWrite::*safe_bool)(); - void safe_bool_true() {} - public: /** Compression type. */ enum Compress @@ -73,10 +70,7 @@ public: bool recursive = true); /** Returns true if there has been no error. */ - operator safe_bool() const - { - return this->Okay() ? &cmArchiveWrite::safe_bool_true : nullptr; - } + explicit operator bool() const { return this->Okay(); } /** Returns true if there has been an error. */ bool operator!() const { return !this->Okay(); } diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index 1f9f5802a..106e7a79a 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -5,6 +5,7 @@ #include "cmsys/Directory.hxx" #include <algorithm> #include <stddef.h> +#include <utility> #include "cmAlgorithms.h" #include "cmMakefile.h" diff --git a/Source/cmBase32.cxx b/Source/cmBase32.cxx index 1dac212c2..80ada4766 100644 --- a/Source/cmBase32.cxx +++ b/Source/cmBase32.cxx @@ -34,13 +34,9 @@ void Base32Encode5(const unsigned char src[5], char dst[8]) // -- Class methods -cmBase32Encoder::cmBase32Encoder() -{ -} +cmBase32Encoder::cmBase32Encoder() = default; -cmBase32Encoder::~cmBase32Encoder() -{ -} +cmBase32Encoder::~cmBase32Encoder() = default; std::string cmBase32Encoder::encodeString(const unsigned char* input, size_t len, bool padding) diff --git a/Source/cmBreakCommand.cxx b/Source/cmBreakCommand.cxx index 3772c6fb6..d07898fd6 100644 --- a/Source/cmBreakCommand.cxx +++ b/Source/cmBreakCommand.cxx @@ -6,8 +6,8 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" -#include "cmake.h" // cmBreakCommand bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, @@ -16,7 +16,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, if (!this->Makefile->IsLoopBlock()) { bool issueMessage = true; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n"; @@ -27,7 +27,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; break; } @@ -35,7 +35,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, e << "A BREAK command was found outside of a proper " "FOREACH or WHILE loop scope."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -46,7 +46,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, if (!args.empty()) { bool issueMessage = true; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n"; @@ -57,14 +57,14 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; break; } if (issueMessage) { e << "The BREAK command does not accept any arguments."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index fd876004b..428a0b224 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -6,9 +6,9 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -84,7 +84,7 @@ bool cmBuildCommand::MainSignature(std::vector<std::string> const& args) if (!project_name.empty()) { this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, "Ignoring PROJECT_NAME option because it has no effect."); } diff --git a/Source/cmCLocaleEnvironmentScope.h b/Source/cmCLocaleEnvironmentScope.h index ec81cb9f2..93032c12e 100644 --- a/Source/cmCLocaleEnvironmentScope.h +++ b/Source/cmCLocaleEnvironmentScope.h @@ -10,12 +10,14 @@ class cmCLocaleEnvironmentScope { - CM_DISABLE_COPY(cmCLocaleEnvironmentScope) - public: cmCLocaleEnvironmentScope(); ~cmCLocaleEnvironmentScope(); + cmCLocaleEnvironmentScope(cmCLocaleEnvironmentScope const&) = delete; + cmCLocaleEnvironmentScope& operator=(cmCLocaleEnvironmentScope const&) = + delete; + private: std::string GetEnv(std::string const& key); void SetEnv(std::string const& key, std::string const& value); diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 882294264..54f08bbcd 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -10,7 +10,7 @@ #if defined(_WIN32) # include "cmAlgorithms.h" # include "cmGlobalGenerator.h" -# include "cmGlobalVisualStudio15Generator.h" +# include "cmGlobalVisualStudioVersionedGenerator.h" # include "cmSystemTools.h" # include "cmVSSetupHelper.h" # define HAVE_VS_SETUP_HELPER @@ -133,15 +133,31 @@ bool cmCMakeHostSystemInformationCommand::GetValue( // If generating for the VS 15 IDE, use the same instance. cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) { - cmGlobalVisualStudio15Generator* vs15gen = - static_cast<cmGlobalVisualStudio15Generator*>(gg); + cmGlobalVisualStudioVersionedGenerator* vs15gen = + static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); if (vs15gen->GetVSInstance(value)) { return true; } } // Otherwise, find a VS 15 instance ourselves. - cmVSSetupAPIHelper vsSetupAPIHelper; + cmVSSetupAPIHelper vsSetupAPIHelper(15); + if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { + cmSystemTools::ConvertToUnixSlashes(value); + } + } else if (key == "VS_16_DIR") { + // If generating for the VS 16 IDE, use the same instance. + cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 16 ")) { + cmGlobalVisualStudioVersionedGenerator* vs16gen = + static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); + if (vs16gen->GetVSInstance(value)) { + return true; + } + } + + // Otherwise, find a VS 16 instance ourselves. + cmVSSetupAPIHelper vsSetupAPIHelper(16); if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { cmSystemTools::ConvertToUnixSlashes(value); } diff --git a/Source/cmCMakeMinimumRequired.cxx b/Source/cmCMakeMinimumRequired.cxx index 2b51976b9..4218d810b 100644 --- a/Source/cmCMakeMinimumRequired.cxx +++ b/Source/cmCMakeMinimumRequired.cxx @@ -6,9 +6,9 @@ #include <stdio.h> #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmVersion.h" -#include "cmake.h" class cmExecutionStatus; @@ -96,7 +96,7 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args, e << "CMake " << version_min << " or higher is required. You are running version " << cmVersion::GetCMakeVersion(); - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -108,7 +108,7 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args, if (required_major < 2 || (required_major == 2 && required_minor < 4)) { this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0."); this->Makefile->SetPolicyVersion("2.4", version_max); } else { diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx index adf9ef80e..ac30e1a39 100644 --- a/Source/cmCMakePolicyCommand.cxx +++ b/Source/cmCMakePolicyCommand.cxx @@ -5,10 +5,10 @@ #include <sstream> #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" -#include "cmake.h" class cmExecutionStatus; @@ -46,6 +46,9 @@ bool cmCMakePolicyCommand::InitialPass(std::vector<std::string> const& args, if (args[0] == "VERSION") { return this->HandleVersionMode(args); } + if (args[0] == "GET_WARNING") { + return this->HandleGetWarningMode(args); + } std::ostringstream e; e << "given unknown first argument \"" << args[0] << "\""; @@ -143,7 +146,7 @@ bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args) << "The call to cmake_policy(GET " << id << " ...) at which this " << "error appears requests the policy, and this version of CMake " << "requires that the policy be set to NEW before it is checked."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } } @@ -181,3 +184,33 @@ bool cmCMakePolicyCommand::HandleVersionMode( this->Makefile->SetPolicyVersion(version_min, version_max); return true; } + +bool cmCMakePolicyCommand::HandleGetWarningMode( + std::vector<std::string> const& args) +{ + if (args.size() != 3) { + this->SetError( + "GET_WARNING must be given exactly 2 additional arguments."); + return false; + } + + // Get arguments. + std::string const& id = args[1]; + std::string const& var = args[2]; + + // Lookup the policy number. + cmPolicies::PolicyID pid; + if (!cmPolicies::GetPolicyID(id.c_str(), pid)) { + std::ostringstream e; + e << "GET_WARNING given policy \"" << id + << "\" which is not known to this version of CMake."; + this->SetError(e.str()); + return false; + } + + // Lookup the policy warning. + this->Makefile->AddDefinition(var, + cmPolicies::GetPolicyWarning(pid).c_str()); + + return true; +} diff --git a/Source/cmCMakePolicyCommand.h b/Source/cmCMakePolicyCommand.h index b18576c67..cca140617 100644 --- a/Source/cmCMakePolicyCommand.h +++ b/Source/cmCMakePolicyCommand.h @@ -37,6 +37,7 @@ private: bool HandleSetMode(std::vector<std::string> const& args); bool HandleGetMode(std::vector<std::string> const& args); bool HandleVersionMode(std::vector<std::string> const& args); + bool HandleGetWarningMode(std::vector<std::string> const& args); }; #endif diff --git a/Source/cmCPackPropertiesGenerator.h b/Source/cmCPackPropertiesGenerator.h index e580e044b..ad943c588 100644 --- a/Source/cmCPackPropertiesGenerator.h +++ b/Source/cmCPackPropertiesGenerator.h @@ -20,13 +20,15 @@ class cmLocalGenerator; */ class cmCPackPropertiesGenerator : public cmScriptGenerator { - CM_DISABLE_COPY(cmCPackPropertiesGenerator) - public: cmCPackPropertiesGenerator(cmLocalGenerator* lg, cmInstalledFile const& installedFile, std::vector<std::string> const& configurations); + cmCPackPropertiesGenerator(cmCPackPropertiesGenerator const&) = delete; + cmCPackPropertiesGenerator& operator=(cmCPackPropertiesGenerator const&) = + delete; + protected: void GenerateScriptForConfig(std::ostream& os, const std::string& config, Indent indent) override; diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 22ae34033..c0088ac5d 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -181,7 +181,7 @@ void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs, std::vector<std::string> srcs2; int i; for (i = 0; i < numSrcs; ++i) { - srcs2.push_back(srcs[i]); + srcs2.emplace_back(srcs[i]); } cmTarget* tg = mf->AddExecutable(exename, srcs2); if (win32) { @@ -347,7 +347,7 @@ static void addLinkLibrary(cmMakefile* mf, std::string const& target, std::ostringstream e; e << "Attempt to add link library \"" << lib << "\" to target \"" << target << "\" which is not built in this directory."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -362,7 +362,7 @@ static void addLinkLibrary(cmMakefile* mf, std::string const& target, << " may not be linked into another target. " << "One may link only to STATIC or SHARED libraries, or " << "to executables with the ENABLE_EXPORTS property set."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); } t->AddLinkLibrary(*mf, lib, llt); @@ -393,7 +393,7 @@ void CCONV cmAddLibrary(void* arg, const char* libname, int shared, std::vector<std::string> srcs2; int i; for (i = 0; i < numSrcs; ++i) { - srcs2.push_back(srcs[i]); + srcs2.emplace_back(srcs[i]); } mf->AddLibrary( libname, @@ -407,7 +407,7 @@ char CCONV* cmExpandVariablesInString(void* arg, const char* source, cmMakefile* mf = static_cast<cmMakefile*>(arg); std::string barf = source; std::string const& result = - mf->ExpandVariablesInString(barf, escapeQuotes, atOnly); + mf->ExpandVariablesInString(barf, escapeQuotes != 0, atOnly != 0); return strdup(result.c_str()); } @@ -419,8 +419,7 @@ int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs, lff.Name = name; for (int i = 0; i < numArgs; ++i) { // Assume all arguments are quoted. - lff.Arguments.push_back( - cmListFileArgument(args[i], cmListFileArgument::Quoted, 0)); + lff.Arguments.emplace_back(args[i], cmListFileArgument::Quoted, 0); } cmExecutionStatus status; return mf->ExecuteCommand(lff, status); @@ -436,7 +435,7 @@ void CCONV cmExpandSourceListArguments(void* arg, int numArgs, std::vector<std::string> result; int i; for (i = 0; i < numArgs; ++i) { - result.push_back(args[i]); + result.emplace_back(args[i]); } int resargc = static_cast<int>(result.size()); char** resargv = nullptr; @@ -475,11 +474,7 @@ int CCONV cmGetTotalArgumentSize(int argc, char** argv) // API for source files. struct cmCPluginAPISourceFile { - cmCPluginAPISourceFile() - : RealSourceFile(nullptr) - { - } - cmSourceFile* RealSourceFile; + cmSourceFile* RealSourceFile = nullptr; std::string SourceName; std::string SourceExtension; std::string FullPath; @@ -630,7 +625,7 @@ void CCONV cmSourceFileAddDepend(void* arg, const char* depend) if (cmSourceFile* rsf = sf->RealSourceFile) { rsf->AddDepend(depend); } else { - sf->Depends.push_back(depend); + sf->Depends.emplace_back(depend); } } @@ -650,10 +645,10 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir, std::vector<std::string> headerExts; int i; for (i = 0; i < numSourceExtensions; ++i) { - sourceExts.push_back(sourceExtensions[i]); + sourceExts.emplace_back(sourceExtensions[i]); } for (i = 0; i < numHeaderExtensions; ++i) { - headerExts.push_back(headerExtensions[i]); + headerExts.emplace_back(headerExtensions[i]); } // Save the original name given. @@ -724,7 +719,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir, ext != headerExts.end(); ++ext) { e << " ." << *ext; } - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); } void CCONV cmSourceFileSetName2(void* arg, const char* name, const char* dir, diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 908eea145..989c7ee45 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -278,6 +278,8 @@ cmCTest::cmCTest() this->ExtraVerbose = false; this->ProduceXML = false; this->ShowOnly = false; + this->OutputAsJson = false; + this->OutputAsJsonVersion = 1; this->RunConfigurationScript = false; this->UseHTTP10 = false; this->PrintLabels = false; @@ -292,9 +294,9 @@ cmCTest::cmCTest() this->OutputLogFile = nullptr; this->OutputLogFileLastTag = -1; this->SuppressUpdatingCTestConfiguration = false; - this->DartVersion = 1; - this->DropSiteCDash = false; + this->BuildID = ""; this->OutputTestOutputOnTestFailure = false; + this->OutputColorCode = cmCTest::ColoredOutputSupportedByConsole(); this->RepeatTests = 1; // default to run each test once this->RepeatUntilFail = false; @@ -320,6 +322,7 @@ cmCTest::cmCTest() this->Parts[PartNotes].SetName("Notes"); this->Parts[PartExtraFiles].SetName("ExtraFiles"); this->Parts[PartUpload].SetName("Upload"); + this->Parts[PartDone].SetName("Done"); // Fill the part name-to-id map. for (Part p = PartStart; p != PartCount; p = Part(p + 1)) { @@ -426,7 +429,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) } } - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::CTest); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -610,8 +613,7 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command) { std::string src_dir = this->GetCTestConfiguration("SourceDirectory"); std::string bld_dir = this->GetCTestConfiguration("BuildDirectory"); - this->DartVersion = 1; - this->DropSiteCDash = false; + this->BuildID = ""; for (Part p = PartStart; p != PartCount; p = Part(p + 1)) { this->Parts[p].SubmitFiles.clear(); } @@ -638,23 +640,13 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command) " Reading ctest configuration file: " << fname << std::endl, command->ShouldBeQuiet()); - bool readit = mf->ReadDependentFile(fname.c_str()); + bool readit = mf->ReadDependentFile(fname); if (!readit) { std::string m = "Could not find include file: "; m += fname; command->SetError(m); return false; } - } else { - cmCTestOptionalLog(this, WARNING, - "Cannot locate CTest configuration: in BuildDirectory: " - << bld_dir_fname << std::endl, - command->ShouldBeQuiet()); - cmCTestOptionalLog( - this, WARNING, - "Cannot locate CTest configuration: in SourceDirectory: " - << src_dir_fname << std::endl, - command->ShouldBeQuiet()); } this->SetCTestConfigurationFromCMakeVariable(mf, "NightlyStartTime", @@ -664,18 +656,6 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command) command->ShouldBeQuiet()); this->SetCTestConfigurationFromCMakeVariable( mf, "BuildName", "CTEST_BUILD_NAME", command->ShouldBeQuiet()); - const char* dartVersion = mf->GetDefinition("CTEST_DART_SERVER_VERSION"); - if (dartVersion) { - this->DartVersion = atoi(dartVersion); - if (this->DartVersion < 0) { - cmCTestLog(this, ERROR_MESSAGE, - "Invalid Dart server version: " - << dartVersion << ". Please specify the version number." - << std::endl); - return false; - } - } - this->DropSiteCDash = mf->IsOn("CTEST_DROP_SITE_CDASH"); if (!this->Initialize(bld_dir.c_str(), command)) { return false; @@ -724,7 +704,7 @@ bool cmCTest::UpdateCTestConfiguration() if (line.empty()) { continue; } - while (fin && (line[line.size() - 1] == '\\')) { + while (fin && (line.back() == '\\')) { line = line.substr(0, line.size() - 1); buffer[0] = 0; fin.getline(buffer, 1023); @@ -1196,12 +1176,12 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, if (strcmp(i, "--build-generator") == 0 && timeout != cmCTest::MaxDuration() && timeout > cmDuration::zero()) { - args.push_back("--test-timeout"); + args.emplace_back("--test-timeout"); std::ostringstream msg; msg << cmDurationTo<unsigned int>(timeout); args.push_back(msg.str()); } - args.push_back(i); + args.emplace_back(i); } } if (log) { @@ -1565,6 +1545,24 @@ int cmCTest::GenerateNotesFile(const char* cfiles) return this->GenerateNotesFile(files); } +int cmCTest::GenerateDoneFile() +{ + cmGeneratedFileStream ofs; + if (!this->OpenOutputFile(this->CurrentTag, "Done.xml", ofs)) { + cmCTestLog(this, ERROR_MESSAGE, "Cannot open done file" << std::endl); + return 1; + } + cmXMLWriter xml(ofs); + xml.StartDocument(); + xml.StartElement("Done"); + xml.Element("buildId", this->BuildID); + xml.Element("time", std::chrono::system_clock::now()); + xml.EndElement(); // Done + xml.EndDocument(); + + return 0; +} + std::string cmCTest::Base64GzipEncodeFile(std::string const& file) { std::string tarFile = file + "_temp.tar.gz"; @@ -1934,6 +1932,23 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, if (this->CheckArgument(arg, "-N", "--show-only")) { this->ShowOnly = true; } + if (cmSystemTools::StringStartsWith(arg.c_str(), "--show-only=")) { + this->ShowOnly = true; + + // Check if a specific format is requested. Defaults to human readable + // text. + std::string argWithFormat = "--show-only="; + std::string format = arg.substr(argWithFormat.length()); + if (format == "json-v1") { + // Force quiet mode so the only output is the json object model. + this->Quiet = true; + this->OutputAsJson = true; + this->OutputAsJsonVersion = 1; + } else if (format != "human") { + errormsg = "'--show-only=' given unknown value '" + format + "'"; + return false; + } + } if (this->CheckArgument(arg, "-O", "--output-log") && i < args.size() - 1) { i++; @@ -2054,7 +2069,18 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, return true; } -bool cmCTest::ProgressOutputSupportedByConsole() const +#if !defined(_WIN32) +bool cmCTest::ConsoleIsNotDumb() +{ + std::string term_env_variable; + if (cmSystemTools::GetEnv("TERM", term_env_variable)) { + return isatty(1) && term_env_variable != "dumb"; + } + return false; +} +#endif + +bool cmCTest::ProgressOutputSupportedByConsole() { #if defined(_WIN32) // On Windows we need a console buffer. @@ -2063,12 +2089,19 @@ bool cmCTest::ProgressOutputSupportedByConsole() const return GetConsoleScreenBufferInfo(console, &csbi); #else // On UNIX we need a non-dumb tty. - std::string term_env_variable; - if (cmSystemTools::GetEnv("TERM", term_env_variable)) { - return isatty(1) && term_env_variable != "dumb"; - } + return ConsoleIsNotDumb(); #endif +} + +bool cmCTest::ColoredOutputSupportedByConsole() +{ +#if defined(_WIN32) + // Not supported on Windows return false; +#else + // On UNIX we need a non-dumb tty. + return ConsoleIsNotDumb(); +#endif } // handle the -S -SR and -SP arguments @@ -2140,7 +2173,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) // handle the simple commandline arguments std::string errormsg; if (!this->HandleCommandLineArguments(i, args, errormsg)) { - cmSystemTools::Error(errormsg.c_str()); + cmSystemTools::Error(errormsg); return 1; } @@ -2439,8 +2472,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf) bool erroroc = cmSystemTools::GetErrorOccuredFlag(); cmSystemTools::ResetErrorOccuredFlag(); - if (!mf->ReadListFile(fname.c_str()) || - cmSystemTools::GetErrorOccuredFlag()) { + if (!mf->ReadListFile(fname) || cmSystemTools::GetErrorOccuredFlag()) { cmCTestLog(this, ERROR_MESSAGE, "Problem reading custom configuration: " << fname << std::endl); @@ -2459,15 +2491,13 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf) gl.RecurseOn(); gl.FindFiles(rexpr); std::vector<std::string>& files = gl.GetFiles(); - std::vector<std::string>::iterator fileIt; - for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) { + for (const std::string& file : files) { cmCTestLog(this, DEBUG, - "* Read custom CTest configuration file: " << *fileIt + "* Read custom CTest configuration file: " << file << std::endl); - if (!mf->ReadListFile(fileIt->c_str()) || - cmSystemTools::GetErrorOccuredFlag()) { + if (!mf->ReadListFile(file) || cmSystemTools::GetErrorOccuredFlag()) { cmCTestLog(this, ERROR_MESSAGE, - "Problem reading custom configuration: " << *fileIt + "Problem reading custom configuration: " << file << std::endl); } } @@ -2554,7 +2584,7 @@ std::string cmCTest::GetShortPathToFile(const char* cfname) cmSystemTools::ConvertToUnixSlashes(*res); path = "./" + *res; - if (path[path.size() - 1] == '/') { + if (path.back() == '/') { path = path.substr(0, path.size() - 1); } } @@ -2596,6 +2626,32 @@ void cmCTest::SetCTestConfiguration(const char* name, const char* value, this->CTestConfiguration[name] = value; } +std::string cmCTest::GetSubmitURL() +{ + std::string url = this->GetCTestConfiguration("SubmitURL"); + if (url.empty()) { + std::string method = this->GetCTestConfiguration("DropMethod"); + std::string user = this->GetCTestConfiguration("DropSiteUser"); + std::string password = this->GetCTestConfiguration("DropSitePassword"); + std::string site = this->GetCTestConfiguration("DropSite"); + std::string location = this->GetCTestConfiguration("DropLocation"); + + url = method.empty() ? "http" : method; + url += "://"; + if (!user.empty()) { + url += user; + if (!password.empty()) { + url += ':'; + url += password; + } + url += '@'; + } + url += site; + url += location; + } + return url; +} + std::string cmCTest::GetCurrentTag() { return this->CurrentTag; @@ -2616,6 +2672,16 @@ bool cmCTest::GetShowOnly() return this->ShowOnly; } +bool cmCTest::GetOutputAsJson() +{ + return this->OutputAsJson; +} + +int cmCTest::GetOutputAsJsonVersion() +{ + return this->OutputAsJsonVersion; +} + int cmCTest::GetMaxTestNameWidth() const { return this->MaxTestNameWidth; @@ -2650,7 +2716,7 @@ void cmCTest::SetSpecificTrack(const char* track) void cmCTest::AddSubmitFile(Part part, const char* name) { - this->Parts[part].SubmitFiles.push_back(name); + this->Parts[part].SubmitFiles.emplace_back(name); } void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr) @@ -2741,13 +2807,13 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args, if ((res == cmsysProcess_Pipe_STDOUT || res == cmsysProcess_Pipe_STDERR) && this->ExtraVerbose) { processOutput.DecodeText(data, length, strdata); - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } } if (this->ExtraVerbose) { processOutput.DecodeText(std::string(), strdata); if (!strdata.empty()) { - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } } @@ -2813,9 +2879,11 @@ static const char* cmCTestStringLogType[] = { "DEBUG", nullptr }; #define cmCTestLogOutputFileLine(stream) \ - if (this->ShowLineNumbers) { \ - (stream) << std::endl << file << ":" << line << " "; \ - } + do { \ + if (this->ShowLineNumbers) { \ + (stream) << std::endl << file << ":" << line << " "; \ + } \ + } while (false) void cmCTest::InitStreams() { @@ -2937,6 +3005,20 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg, } } +std::string cmCTest::GetColorCode(Color color) const +{ + if (this->OutputColorCode) { +#if defined(_WIN32) + // Not supported on Windows + static_cast<void>(color); +#else + return "\033[0;" + std::to_string(static_cast<int>(color)) + "m"; +#endif + } + + return ""; +} + cmDuration cmCTest::GetRemainingTimeAllowed() { if (!this->GetHandler("script")) { diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 345b538e7..92a02c316 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -50,27 +50,23 @@ public: PartNotes, PartExtraFiles, PartUpload, + PartDone, PartCount // Update names in constructor when adding a part }; /** Representation of one part. */ struct PartInfo { - PartInfo() - : Enabled(false) - { - } - void SetName(const std::string& name) { this->Name = name; } const std::string& GetName() const { return this->Name; } void Enable() { this->Enabled = true; } - operator bool() const { return this->Enabled; } + explicit operator bool() const { return this->Enabled; } std::vector<std::string> SubmitFiles; private: - bool Enabled; + bool Enabled = false; std::string Name; }; #ifdef CMAKE_BUILD_WITH_CMAKE @@ -178,6 +174,8 @@ public: bool suppress = false); void EmptyCTestConfiguration(); + std::string GetSubmitURL(); + /** * constructor and destructor */ @@ -217,6 +215,10 @@ public: /** Should we only show what we would do? */ bool GetShowOnly(); + bool GetOutputAsJson(); + + int GetOutputAsJsonVersion(); + bool ShouldUseHTTP10() { return this->UseHTTP10; } bool ShouldPrintLabels() { return this->PrintLabels; } @@ -373,6 +375,9 @@ public: /** Create XML file that contains all the notes specified */ int GenerateNotesFile(const VectorOfStrings& files); + /** Create XML file to indicate that build is complete */ + int GenerateDoneFile(); + /** Submit extra files to the server */ bool SubmitExtraFiles(const char* files); bool SubmitExtraFiles(const VectorOfStrings& files); @@ -401,9 +406,22 @@ public: void Log(int logType, const char* file, int line, const char* msg, bool suppress = false); - /** Get the version of dart server */ - int GetDartVersion() { return this->DartVersion; } - int GetDropSiteCDash() { return this->DropSiteCDash; } + /** Color values */ + enum class Color + { + CLEAR_COLOR = 0, + RED = 31, + GREEN = 32, + YELLOW = 33, + BLUE = 34 + }; + + /** Get color code characters for a specific color */ + std::string GetColorCode(Color color) const; + + /** The Build ID is assigned by CDash */ + void SetBuildID(const std::string& id) { this->BuildID = id; } + std::string GetBuildID() { return this->BuildID; } /** Add file to be submitted */ void AddSubmitFile(Part part, const char* name); @@ -493,6 +511,8 @@ private: t_TestingHandlers TestingHandlers; bool ShowOnly; + bool OutputAsJson; + int OutputAsJsonVersion; /** Map of configuration properties */ typedef std::map<std::string, std::string> CTestConfigurationMap; @@ -567,8 +587,16 @@ private: bool HandleCommandLineArguments(size_t& i, std::vector<std::string>& args, std::string& errormsg); +#if !defined(_WIN32) + /** returns true iff the console supports progress output */ + static bool ConsoleIsNotDumb(); +#endif + /** returns true iff the console supports progress output */ - bool ProgressOutputSupportedByConsole() const; + static bool ProgressOutputSupportedByConsole(); + + /** returns true iff the console supports colored output */ + static bool ColoredOutputSupportedByConsole(); /** handle the -S -SP and -SR arguments */ void HandleScriptArguments(size_t& i, std::vector<std::string>& args, @@ -604,8 +632,7 @@ private: bool ShowLineNumbers; bool Quiet; - int DartVersion; - bool DropSiteCDash; + std::string BuildID; std::vector<std::string> InitialCommandLineArguments; @@ -615,6 +642,7 @@ private: int OutputLogFileLastTag; bool OutputTestOutputOnTestFailure; + bool OutputColorCode; std::map<std::string, std::string> Definitions; }; diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index b391dc44b..2728f0f9a 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -11,11 +11,11 @@ #include <string> #include "cmGeneratedFileStream.h" +#include "cmMessageType.h" #include "cmMessenger.h" #include "cmState.h" #include "cmSystemTools.h" #include "cmVersion.h" -#include "cmake.h" cmCacheManager::cmCacheManager() { @@ -26,7 +26,7 @@ cmCacheManager::cmCacheManager() void cmCacheManager::CleanCMakeFiles(const std::string& path) { std::string glob = path; - glob += cmake::GetCMakeFilesDirectory(); + glob += "/CMakeFiles"; glob += "/*.cmake"; cmsys::Glob globIt; globIt.FindFiles(glob); @@ -122,7 +122,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, std::ostringstream error; error << "Parse error in cache file " << cacheFile; error << " on line " << lineno << ". Offending entry: " << realbuffer; - cmSystemTools::Error(error.str().c_str()); + cmSystemTools::Error(error.str()); } } this->CacheMajorVersion = 0; @@ -170,7 +170,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, << " where CMakeCache.txt was created. This may result " "in binaries being created in the wrong place. If you " "are not sure, reedit the CMakeCache.txt"; - cmSystemTools::Error(message.str().c_str()); + cmSystemTools::Error(message.str()); } } return true; @@ -188,7 +188,7 @@ bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey, } const char* end = entryKey.c_str() + entryKey.size(); - for (const char** p = this->PersistentProperties; *p; ++p) { + for (const char** p = cmCacheManager::PersistentProperties; *p; ++p) { std::string::size_type plen = strlen(*p) + 1; if (entryKey.size() > plen && *(end - plen) == '-' && strcmp(end - plen + 1, *p) == 0) { @@ -212,7 +212,7 @@ bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey, void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i, cmMessenger* messenger) { - for (const char** p = this->PersistentProperties; *p; ++p) { + for (const char** p = cmCacheManager::PersistentProperties; *p; ++p) { if (const char* value = i.GetProperty(*p)) { std::string helpstring = *p; helpstring += " property for variable: "; @@ -222,9 +222,9 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i, std::string key = i.GetName(); key += "-"; key += *p; - this->OutputKey(os, key); + cmCacheManager::OutputKey(os, key); os << ":INTERNAL="; - this->OutputValue(os, value); + cmCacheManager::OutputValue(os, value); os << "\n"; cmCacheManager::OutputNewlineTruncationWarning(os, key, value, messenger); @@ -319,9 +319,9 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) } else { cmCacheManager::OutputHelpString(fout, "Missing description"); } - this->OutputKey(fout, i.first); + cmCacheManager::OutputKey(fout, i.first); fout << ":" << cmState::CacheEntryTypeToString(t) << "="; - this->OutputValue(fout, ce.Value); + cmCacheManager::OutputValue(fout, ce.Value); fout << "\n"; cmCacheManager::OutputNewlineTruncationWarning(fout, i.first, ce.Value, messenger); @@ -346,11 +346,11 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) if (t == cmStateEnums::INTERNAL) { // Format is key:type=value if (const char* help = i.GetProperty("HELPSTRING")) { - this->OutputHelpString(fout, help); + cmCacheManager::OutputHelpString(fout, help); } - this->OutputKey(fout, i.GetName()); + cmCacheManager::OutputKey(fout, i.GetName()); fout << ":" << cmState::CacheEntryTypeToString(t) << "="; - this->OutputValue(fout, i.GetValue()); + cmCacheManager::OutputValue(fout, i.GetValue()); fout << "\n"; cmCacheManager::OutputNewlineTruncationWarning(fout, i.GetName(), i.GetValue(), messenger); @@ -359,7 +359,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) fout << "\n"; fout.Close(); std::string checkCacheFile = path; - checkCacheFile += cmake::GetCMakeFilesDirectory(); + checkCacheFile += "/CMakeFiles"; cmSystemTools::MakeDirectory(checkCacheFile); checkCacheFile += "/cmake.check_cache"; cmsys::ofstream checkCache(checkCacheFile.c_str()); @@ -383,7 +383,7 @@ bool cmCacheManager::DeleteCache(const std::string& path) cmSystemTools::RemoveFile(cacheFile); // now remove the files in the CMakeFiles directory // this cleans up language cache files - cmakeFiles += cmake::GetCMakeFilesDirectory(); + cmakeFiles += "/CMakeFiles"; if (cmSystemTools::FileIsDirectory(cmakeFiles)) { cmSystemTools::RemoveADirectory(cmakeFiles); } @@ -415,8 +415,7 @@ void cmCacheManager::OutputValueNoNewlines(std::ostream& fout, std::string const& value) { // if value has trailing space or tab, enclose it in single quotes - if (!value.empty() && - (value[value.size() - 1] == ' ' || value[value.size() - 1] == '\t')) { + if (!value.empty() && (value.back() == ' ' || value.back() == '\t')) { fout << '\'' << value << '\''; } else { fout << value; @@ -479,7 +478,7 @@ void cmCacheManager::OutputNewlineTruncationWarning(std::ostream& fout, std::string message = "Value of "; message += key; message += " contained a newline; truncating"; - messenger->IssueMessage(cmake::WARNING, message); + messenger->IssueMessage(MessageType::WARNING, message); } std::string comment = "WARNING: Value of "; diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index a269271b8..0c70ed27f 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -34,20 +34,14 @@ private: struct CacheEntry { std::string Value; - cmStateEnums::CacheEntryType Type; + cmStateEnums::CacheEntryType Type = cmStateEnums::UNINITIALIZED; cmPropertyMap Properties; std::vector<std::string> GetPropertyList() const; const char* GetProperty(const std::string&) const; void SetProperty(const std::string& property, const char* value); void AppendProperty(const std::string& property, const char* value, bool asString = false); - bool Initialized; - CacheEntry() - : Value("") - , Type(cmStateEnums::UNINITIALIZED) - , Initialized(false) - { - } + bool Initialized = false; }; public: diff --git a/Source/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx index ecfcfb965..ee5feee76 100644 --- a/Source/cmCallVisualStudioMacro.cxx +++ b/Source/cmCallVisualStudioMacro.cxx @@ -46,7 +46,7 @@ static bool LogErrorsAsMessages; << std::endl; \ _hresult_oss.flags(std::ios::dec); \ _hresult_oss << __FILE__ << "(" << __LINE__ << ")"; \ - cmSystemTools::Message(_hresult_oss.str().c_str()); \ + cmSystemTools::Message(_hresult_oss.str()); \ } \ } @@ -446,7 +446,7 @@ int cmCallVisualStudioMacro::CallMacro(const std::string& slnFile, if (err && LogErrorsAsMessages) { std::ostringstream oss; oss << "cmCallVisualStudioMacro::CallMacro failed, err = " << err; - cmSystemTools::Message(oss.str().c_str()); + cmSystemTools::Message(oss.str()); } return 0; diff --git a/Source/cmCommand.h b/Source/cmCommand.h index 2cc0b88ec..9ccd773f6 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -24,21 +24,19 @@ struct cmListFileArgument; */ class cmCommand { - CM_DISABLE_COPY(cmCommand) - public: /** * Construct the command. By default it has no makefile. */ - cmCommand() - : Makefile(nullptr) - { - } + cmCommand() = default; /** * Need virtual destructor to destroy real command type. */ - virtual ~cmCommand() {} + virtual ~cmCommand() = default; + + cmCommand(cmCommand const&) = delete; + cmCommand& operator=(cmCommand const&) = delete; /** * Specify the makefile. @@ -90,7 +88,7 @@ public: void SetError(const std::string& e); protected: - cmMakefile* Makefile; + cmMakefile* Makefile = nullptr; private: std::string Error; diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index 2b4ceaa3e..ca2996741 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -6,7 +6,6 @@ #include "cmMakefile.h" #include "cmState.h" #include "cmSystemTools.h" -#include "cmake.h" #include <iostream> #include <sstream> @@ -16,8 +15,6 @@ int cmCommandArgument_yyparse(yyscan_t yyscanner); // cmCommandArgumentParserHelper::cmCommandArgumentParserHelper() { - this->WarnUninitialized = false; - this->CheckSystemVars = false; this->FileLine = -1; this->FileName = nullptr; this->RemoveEmpty = true; @@ -95,23 +92,11 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) return this->AddString(ostr.str()); } const char* value = this->Makefile->GetDefinition(var); - if (!value && !this->RemoveEmpty) { - // check to see if we need to print a warning - // if strict mode is on and the variable has - // not been "cleared"/initialized with a set(foo ) call - if (this->WarnUninitialized && !this->Makefile->VariableInitialized(var)) { - if (this->CheckSystemVars || - (this->FileName && - (cmSystemTools::IsSubDirectory( - this->FileName, this->Makefile->GetHomeDirectory()) || - cmSystemTools::IsSubDirectory( - this->FileName, this->Makefile->GetHomeOutputDirectory())))) { - std::ostringstream msg; - msg << "uninitialized variable \'" << var << "\'"; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, msg.str()); - } + if (!value) { + this->Makefile->MaybeWarnUninitialized(var, this->FileName); + if (!this->RemoveEmpty) { + return nullptr; } - return nullptr; } if (this->EscapeQuotes && value) { return this->AddString(cmSystemTools::EscapeQuotes(value)); @@ -286,8 +271,6 @@ void cmCommandArgumentParserHelper::Error(const char* str) void cmCommandArgumentParserHelper::SetMakefile(const cmMakefile* mf) { this->Makefile = mf; - this->WarnUninitialized = mf->GetCMakeInstance()->GetWarnUninitialized(); - this->CheckSystemVars = mf->GetCMakeInstance()->GetCheckSystemVars(); } void cmCommandArgumentParserHelper::SetResult(const char* value) diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h index 098c00064..25e689224 100644 --- a/Source/cmCommandArgumentParserHelper.h +++ b/Source/cmCommandArgumentParserHelper.h @@ -12,8 +12,6 @@ class cmMakefile; class cmCommandArgumentParserHelper { - CM_DISABLE_COPY(cmCommandArgumentParserHelper) - public: struct ParserType { @@ -23,6 +21,10 @@ public: cmCommandArgumentParserHelper(); ~cmCommandArgumentParserHelper(); + cmCommandArgumentParserHelper(cmCommandArgumentParserHelper const&) = delete; + cmCommandArgumentParserHelper& operator=( + cmCommandArgumentParserHelper const&) = delete; + int ParseString(const char* str, int verb); // For the lexer: @@ -75,8 +77,6 @@ private: long FileLine; int CurrentLine; int Verbose; - bool WarnUninitialized; - bool CheckSystemVars; bool EscapeQuotes; bool NoEscapeMode; bool ReplaceAtSyntax; diff --git a/Source/cmCommandArgumentsHelper.h b/Source/cmCommandArgumentsHelper.h index c68e64c10..dc934bed6 100644 --- a/Source/cmCommandArgumentsHelper.h +++ b/Source/cmCommandArgumentsHelper.h @@ -39,7 +39,7 @@ class cmCommandArgument public: cmCommandArgument(cmCommandArgumentsHelper* args, const char* key, cmCommandArgumentGroup* group = nullptr); - virtual ~cmCommandArgument() {} + virtual ~cmCommandArgument() = default; /// this argument may follow after arg. 0 means it comes first. void Follows(const cmCommandArgument* arg); @@ -103,7 +103,6 @@ private: std::vector<std::string> Vector; unsigned int DataStart; const char* Ignore; - cmCAStringVector(); bool DoConsume(const std::string& arg, unsigned int index) override; void DoReset() override; }; @@ -125,7 +124,6 @@ private: unsigned int DataStart; bool DoConsume(const std::string& arg, unsigned int index) override; void DoReset() override; - cmCAString(); }; /** cmCAEnabler is to be used for options which are off by default and can be @@ -143,7 +141,6 @@ private: bool Enabled; bool DoConsume(const std::string& arg, unsigned int index) override; void DoReset() override; - cmCAEnabler(); }; /** cmCADisable is to be used for options which are on by default and can be @@ -161,7 +158,6 @@ private: bool Enabled; bool DoConsume(const std::string& arg, unsigned int index) override; void DoReset() override; - cmCADisabler(); }; /** Group of arguments, needed for ordering. E.g. WIN32, EXCLUDE_FROM_ALL and @@ -172,8 +168,6 @@ class cmCommandArgumentGroup friend class cmCommandArgument; public: - cmCommandArgumentGroup() {} - /// All members of this group may follow the given argument void Follows(const cmCommandArgument* arg); diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index a1df27107..66250f329 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -29,9 +29,7 @@ cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt) { } -cmCommonTargetGenerator::~cmCommonTargetGenerator() -{ -} +cmCommonTargetGenerator::~cmCommonTargetGenerator() = default; std::string const& cmCommonTargetGenerator::GetConfigName() const { @@ -198,7 +196,7 @@ std::string cmCommonTargetGenerator::GetManifests() manifests.reserve(manifest_srcs.size()); for (cmSourceFile const* manifest_src : manifest_srcs) { manifests.push_back(this->LocalCommonGenerator->ConvertToOutputFormat( - this->LocalCommonGenerator->ConvertToRelativePath( + this->LocalCommonGenerator->MaybeConvertToRelativePath( this->LocalCommonGenerator->GetWorkingDirectory(), manifest_src->GetFullPath()), cmOutputConverter::SHELL)); diff --git a/Source/cmComputeComponentGraph.cxx b/Source/cmComputeComponentGraph.cxx index a7dc1ca03..113463f63 100644 --- a/Source/cmComputeComponentGraph.cxx +++ b/Source/cmComputeComponentGraph.cxx @@ -18,9 +18,7 @@ cmComputeComponentGraph::cmComputeComponentGraph(Graph const& input) this->TransferEdges(); } -cmComputeComponentGraph::~cmComputeComponentGraph() -{ -} +cmComputeComponentGraph::~cmComputeComponentGraph() = default; void cmComputeComponentGraph::Tarjan() { @@ -125,8 +123,8 @@ void cmComputeComponentGraph::TransferEdges() if (i_component != j_component) { // We do not attempt to combine duplicate edges, but instead // store the inter-component edges with suitable multiplicity. - this->ComponentGraph[i_component].emplace_back(j_component, - ni.IsStrong()); + this->ComponentGraph[i_component].emplace_back( + j_component, ni.IsStrong(), ni.GetBacktrace()); } } } diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index aa17de6e4..4717cf6b5 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -6,6 +6,7 @@ #include "cmComputeComponentGraph.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" @@ -419,7 +420,8 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) // This shared library dependency must follow the item that listed // it. - this->EntryConstraintGraph[dep.DependerIndex].push_back(index); + this->EntryConstraintGraph[dep.DependerIndex].emplace_back( + index, true, cmListFileBacktrace()); // Target items may have their own dependencies. if (entry.Target) { @@ -522,7 +524,8 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, // The dependee must come after the depender. if (depender_index >= 0) { - this->EntryConstraintGraph[depender_index].push_back(dependee_index); + this->EntryConstraintGraph[depender_index].emplace_back( + dependee_index, false, cmListFileBacktrace()); } else { // This is a direct dependency of the target being linked. this->OriginalEntries.push_back(dependee_index); @@ -565,7 +568,7 @@ cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index, from = depender; } } - return from->ResolveLinkItem(name); + return from->ResolveLinkItem(name, cmListFileBacktrace()); } void cmComputeLinkDepends::InferDependencies() @@ -594,7 +597,10 @@ void cmComputeLinkDepends::InferDependencies() // Add the inferred dependencies to the graph. cmGraphEdgeList& edges = this->EntryConstraintGraph[depender_index]; - edges.insert(edges.end(), common.begin(), common.end()); + edges.reserve(edges.size() + common.size()); + for (auto const& c : common) { + edges.emplace_back(c, true, cmListFileBacktrace()); + } } } diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 66fb1e652..252f8748c 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -35,23 +35,9 @@ public: struct LinkEntry { std::string Item; - cmGeneratorTarget const* Target; - bool IsSharedDep; - bool IsFlag; - LinkEntry() - : Item() - , Target(nullptr) - , IsSharedDep(false) - , IsFlag(false) - { - } - LinkEntry(LinkEntry const& r) - : Item(r.Item) - , Target(r.Target) - , IsSharedDep(r.IsSharedDep) - , IsFlag(r.IsFlag) - { - } + cmGeneratorTarget const* Target = nullptr; + bool IsSharedDep = false; + bool IsFlag = false; }; typedef std::vector<LinkEntry> EntryVector; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 0e48ca86d..3d61665fd 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -8,6 +8,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOrderDirectories.h" #include "cmOutputConverter.h" #include "cmPolicies.h" @@ -30,7 +31,7 @@ Notes about linking on various platforms: ------------------------------------------------------------------------------ -Linux, FreeBSD, macOS, IRIX, Sun, Windows: +Linux, FreeBSD, macOS, Sun, Windows: Linking to libraries using the full path works fine. @@ -421,7 +422,8 @@ std::string cmComputeLinkInformation::GetRPathLinkString() const return ""; } - // Construct the linker runtime search path. + // Construct the linker runtime search path. These MUST NOT contain tokens + // such as $ORIGIN, see https://sourceware.org/bugzilla/show_bug.cgi?id=16936 return cmJoin(this->OrderDependentRPath->GetOrderedDirectories(), ":"); } @@ -521,7 +523,7 @@ bool cmComputeLinkInformation::Compute() "name." ; /* clang-format on */ - this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), + this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(), this->Target->GetBacktrace()); } @@ -882,12 +884,12 @@ void cmComputeLinkInformation::AddLinkExtension(const char* e, LinkType type) { if (e && *e) { if (type == LinkStatic) { - this->StaticLinkExtensions.push_back(e); + this->StaticLinkExtensions.emplace_back(e); } if (type == LinkShared) { - this->SharedLinkExtensions.push_back(e); + this->SharedLinkExtensions.emplace_back(e); } - this->LinkExtensions.push_back(e); + this->LinkExtensions.emplace_back(e); } } @@ -1235,7 +1237,7 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item) std::ostringstream e; e << "Could not parse framework path \"" << item << "\" " << "linked by target " << this->Target->GetName() << "."; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return; } @@ -1280,7 +1282,7 @@ void cmComputeLinkInformation::DropDirectoryItem(std::string const& item) << "\" requests linking to directory \"" << item << "\". " << "Targets may link only to libraries. " << "CMake is dropping the item."; - cmSystemTools::Message(e.str().c_str()); + cmSystemTools::Message(e.str()); } void cmComputeLinkInformation::ComputeFrameworkInfo() @@ -1381,7 +1383,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, << " " << item << "\n" << "which is a full-path but not a valid library file name."; /* clang-format on */ - this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), + this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(), this->Target->GetBacktrace()); } } @@ -1400,7 +1402,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, << " " << item << "\n" << "which is a full-path but not a valid library file name."; /* clang-format on */ - this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->CMakeInstance->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Target->GetBacktrace()); } break; } @@ -1423,7 +1425,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() "CMP0003-WARNING-GIVEN", "1"); std::ostringstream w; this->PrintLinkPolicyDiagnosis(w); - this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), + this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(), this->Target->GetBacktrace()); } case cmPolicies::OLD: @@ -1438,7 +1440,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() std::ostringstream e; e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0003) << "\n"; this->PrintLinkPolicyDiagnosis(e); - this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->CMakeInstance->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Target->GetBacktrace()); return false; } @@ -1702,6 +1704,14 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH") && this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH"); + // Select whether to use $ORIGIN in RPATHs for artifacts in the build tree. + std::string const& originToken = this->Makefile->GetSafeDefinition( + "CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN"); + std::string targetOutputDir = this->Target->GetDirectory(this->Config); + bool use_relative_build_rpath = + this->Target->GetPropertyAsBool("BUILD_RPATH_USE_ORIGIN") && + !originToken.empty() && !targetOutputDir.empty(); + // Construct the RPATH. std::set<std::string> emitted; if (use_install_rpath) { @@ -1711,6 +1721,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, if (use_build_rpath) { // Add directories explicitly specified by user if (const char* build_rpath = this->Target->GetProperty("BUILD_RPATH")) { + // This will not resolve entries to use $ORIGIN, the user is expected to + // do that if necessary. cmCLI_ExpandListUnique(build_rpath, runtimeDirs, emitted); } } @@ -1728,6 +1740,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); cmSystemTools::ConvertToUnixSlashes(rootPath); std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath(); + std::string const& topBinaryDir = + this->CMakeInstance->GetHomeOutputDirectory(); for (std::string const& ri : rdirs) { // Put this directory in the rpath if using build-tree rpath // support or if using the link path as an rpath. @@ -1741,6 +1755,18 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, d += "/"; d += suffix; cmSystemTools::ConvertToUnixSlashes(d); + } else if (use_relative_build_rpath) { + // If expansion of the $ORIGIN token is supported and permitted per + // policy, use relative paths in the RPATH. + if (cmSystemTools::ComparePath(d, topBinaryDir) || + cmSystemTools::IsSubDirectory(d, topBinaryDir)) { + d = cmSystemTools::RelativePath(targetOutputDir, d); + if (!d.empty()) { + d = originToken + "/" + d; + } else { + d = originToken; + } + } } if (emitted.insert(d).second) { runtimeDirs.push_back(std::move(d)); @@ -1749,8 +1775,6 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // Do not add any path inside the source or build tree. std::string const& topSourceDir = this->CMakeInstance->GetHomeDirectory(); - std::string const& topBinaryDir = - this->CMakeInstance->GetHomeOutputDirectory(); if (!cmSystemTools::ComparePath(ri, topSourceDir) && !cmSystemTools::ComparePath(ri, topBinaryDir) && !cmSystemTools::IsSubDirectory(ri, topSourceDir) && diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index e00d230a3..863639c6a 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -9,6 +9,7 @@ #include <iosfwd> #include <set> #include <string> +#include <utility> #include <vector> class cmGeneratorTarget; @@ -30,22 +31,16 @@ public: struct Item { - Item() - : Value() - , IsPath(true) - , Target(nullptr) - { - } - Item(std::string const& v, bool p, - cmGeneratorTarget const* target = nullptr) - : Value(v) + Item() = default; + Item(std::string v, bool p, cmGeneratorTarget const* target = nullptr) + : Value(std::move(v)) , IsPath(p) , Target(target) { } std::string Value; - bool IsPath; - cmGeneratorTarget const* Target; + bool IsPath = true; + cmGeneratorTarget const* Target = nullptr; }; typedef std::vector<Item> ItemVector; ItemVector const& GetItems() const; diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 268e74970..9b7b02f53 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -6,8 +6,10 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLinkItem.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSourceFile.h" #include "cmState.h" @@ -22,8 +24,6 @@ #include <stdio.h> #include <utility> -class cmListFileBacktrace; - /* This class is meant to analyze inter-target dependencies globally @@ -103,9 +103,7 @@ cmComputeTargetDepends::cmComputeTargetDepends(cmGlobalGenerator* gg) cm->GetState()->GetGlobalPropertyAsBool("GLOBAL_DEPENDS_NO_CYCLES"); } -cmComputeTargetDepends::~cmComputeTargetDepends() -{ -} +cmComputeTargetDepends::~cmComputeTargetDepends() = default; bool cmComputeTargetDepends::Compute() { @@ -152,6 +150,7 @@ void cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t, cmGeneratorTarget const* dep = this->Targets[ni]; cmTargetDependSet::iterator di = deps.insert(dep).first; di->SetType(ni.IsStrong()); + di->SetBacktrace(ni.GetBacktrace()); } } @@ -208,7 +207,8 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) for (cmSourceFile const* o : objectFiles) { std::string const& objLib = o->GetObjectLibrary(); if (!objLib.empty()) { - cmLinkItem const& objItem = depender->ResolveLinkItem(objLib); + cmLinkItem const& objItem = + depender->ResolveLinkItem(objLib, cmListFileBacktrace()); if (emitted.insert(objItem).second) { if (depender->GetType() != cmStateEnums::EXECUTABLE && depender->GetType() != cmStateEnums::STATIC_LIBRARY && @@ -216,7 +216,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) depender->GetType() != cmStateEnums::MODULE_LIBRARY && depender->GetType() != cmStateEnums::OBJECT_LIBRARY) { this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Only executables and libraries may reference target objects.", depender->GetBacktrace()); return; @@ -230,7 +230,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) cmLinkImplementation const* impl = depender->GetLinkImplementation(it); // A target should not depend on itself. - emitted.insert(cmLinkItem(depender)); + emitted.insert(cmLinkItem(depender, cmListFileBacktrace())); for (cmLinkImplItem const& lib : impl->Libraries) { // Don't emit the same library twice for this target. if (emitted.insert(lib).second) { @@ -246,7 +246,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) std::set<cmLinkItem> const& tutils = depender->GetUtilityItems(); std::set<cmLinkItem> emitted; // A target should not depend on itself. - emitted.insert(cmLinkItem(depender)); + emitted.insert(cmLinkItem(depender, cmListFileBacktrace())); for (cmLinkItem const& litem : tutils) { // Don't emit the same utility twice for this target. if (emitted.insert(litem).second) { @@ -258,7 +258,8 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) void cmComputeTargetDepends::AddInterfaceDepends( int depender_index, const cmGeneratorTarget* dependee, - const std::string& config, std::set<cmLinkItem>& emitted) + cmListFileBacktrace const& dependee_backtrace, const std::string& config, + std::set<cmLinkItem>& emitted) { cmGeneratorTarget const* depender = this->Targets[depender_index]; if (cmLinkInterface const* iface = @@ -266,8 +267,13 @@ void cmComputeTargetDepends::AddInterfaceDepends( for (cmLinkItem const& lib : iface->Libraries) { // Don't emit the same library twice for this target. if (emitted.insert(lib).second) { - this->AddTargetDepend(depender_index, lib, true); - this->AddInterfaceDepends(depender_index, lib, config, emitted); + // Inject the backtrace of the original link dependency whose + // link interface we are adding. This indicates the line of + // code in the project that caused this dependency to be added. + cmLinkItem libBT = lib; + libBT.Backtrace = dependee_backtrace; + this->AddTargetDepend(depender_index, libBT, true); + this->AddInterfaceDepends(depender_index, libBT, config, emitted); } } } @@ -289,8 +295,9 @@ void cmComputeTargetDepends::AddInterfaceDepends( if (dependee) { // A target should not depend on itself. - emitted.insert(cmLinkItem(depender)); - this->AddInterfaceDepends(depender_index, dependee, config, emitted); + emitted.insert(cmLinkItem(depender, cmListFileBacktrace())); + this->AddInterfaceDepends(depender_index, dependee, + dependee_name.Backtrace, config, emitted); } } @@ -306,7 +313,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, if (!dependee && !linking && (depender->GetType() != cmStateEnums::GLOBAL_TARGET)) { - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; bool issueMessage = false; std::ostringstream e; switch (depender->GetPolicyStatusCMP0046()) { @@ -319,7 +326,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: issueMessage = true; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (issueMessage) { cmake* cm = this->GlobalGenerator->GetCMakeInstance(); @@ -327,13 +334,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, e << "The dependency target \"" << dependee_name << "\" of target \"" << depender->GetName() << "\" does not exist."; - cmListFileBacktrace const* backtrace = - depender->GetUtilityBacktrace(dependee_name.AsStr()); - if (backtrace) { - cm->IssueMessage(messageType, e.str(), *backtrace); - } else { - cm->IssueMessage(messageType, e.str()); - } + cm->IssueMessage(messageType, e.str(), dependee_name.Backtrace); } } @@ -346,13 +347,14 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, } if (dependee) { - this->AddTargetDepend(depender_index, dependee, linking); + this->AddTargetDepend(depender_index, dependee, dependee_name.Backtrace, + linking); } } -void cmComputeTargetDepends::AddTargetDepend(int depender_index, - const cmGeneratorTarget* dependee, - bool linking) +void cmComputeTargetDepends::AddTargetDepend( + int depender_index, cmGeneratorTarget const* dependee, + cmListFileBacktrace const& dependee_backtrace, bool linking) { if (dependee->IsImported() || dependee->GetType() == cmStateEnums::INTERFACE_LIBRARY) { @@ -361,7 +363,8 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, std::set<cmLinkItem> const& utils = dependee->GetUtilityItems(); for (cmLinkItem const& i : utils) { if (cmGeneratorTarget const* transitive_dependee = i.Target) { - this->AddTargetDepend(depender_index, transitive_dependee, false); + this->AddTargetDepend(depender_index, transitive_dependee, i.Backtrace, + false); } } } else { @@ -373,7 +376,8 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, int dependee_index = tii->second; // Add this entry to the dependency graph. - this->InitialGraph[depender_index].emplace_back(dependee_index, !linking); + this->InitialGraph[depender_index].emplace_back(dependee_index, !linking, + dependee_backtrace); } } @@ -489,7 +493,7 @@ void cmComputeTargetDepends::ComplainAboutBadComponent( e << "At least one of these targets is not a STATIC_LIBRARY. " << "Cyclic dependencies are allowed only among static libraries."; } - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); } bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap, @@ -507,7 +511,7 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap, for (cmGraphEdge const& edge : el) { int j = edge; if (cmap[j] == c && edge.IsStrong()) { - this->FinalGraph[i].emplace_back(j, true); + this->FinalGraph[i].emplace_back(j, true, edge.GetBacktrace()); if (!this->IntraComponent(cmap, c, j, head, emitted, visited)) { return false; } @@ -516,7 +520,7 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap, // Prepend to a linear linked-list of intra-component edges. if (*head >= 0) { - this->FinalGraph[i].emplace_back(*head, false); + this->FinalGraph[i].emplace_back(*head, false, cmListFileBacktrace()); } else { this->ComponentTail[c] = i; } @@ -567,7 +571,7 @@ bool cmComputeTargetDepends::ComputeFinalDepends( int dependee_component = ni; int dependee_component_head = this->ComponentHead[dependee_component]; this->FinalGraph[depender_component_tail].emplace_back( - dependee_component_head, ni.IsStrong()); + dependee_component_head, ni.IsStrong(), ni.GetBacktrace()); } } return true; diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 3046e8af9..3840bd752 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmGraphAdjacencyList.h" +#include "cmListFileCache.h" #include <map> #include <set> @@ -47,6 +48,7 @@ private: void AddTargetDepend(int depender_index, cmLinkItem const& dependee_name, bool linking); void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee, + cmListFileBacktrace const& dependee_backtrace, bool linking); bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name, @@ -54,6 +56,7 @@ private: std::set<cmLinkItem>& emitted); void AddInterfaceDepends(int depender_index, cmGeneratorTarget const* dependee, + cmListFileBacktrace const& dependee_backtrace, const std::string& config, std::set<cmLinkItem>& emitted); cmGlobalGenerator* GlobalGenerator; diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 172ef9247..94ea529ea 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -8,11 +8,14 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <utility> #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmSystemTools.h" +#include "cmake.h" class cmCommand; class cmTest; @@ -51,11 +54,11 @@ static std::string const keyVERSION_LESS = "VERSION_LESS"; static std::string const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"; cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile, - const cmListFileContext& context, - const cmListFileBacktrace& bt) + cmListFileContext context, + cmListFileBacktrace bt) : Makefile(makefile) - , ExecutionContext(context) - , Backtrace(bt) + , ExecutionContext(std::move(context)) + , Backtrace(std::move(bt)) , Policy12Status(makefile.GetPolicyStatus(cmPolicies::CMP0012)) , Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054)) , Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057)) @@ -81,7 +84,7 @@ cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile, bool cmConditionEvaluator::IsTrue( const std::vector<cmExpandedCommandArgument>& args, std::string& errorString, - cmake::MessageType& status) + MessageType& status) { errorString.clear(); @@ -123,7 +126,7 @@ bool cmConditionEvaluator::IsTrue( // now at the end there should only be one argument left if (newArgs.size() != 1) { errorString = "Unknown arguments specified"; - status = cmake::FATAL_ERROR; + status = MessageType::FATAL_ERROR; return false; } @@ -155,7 +158,7 @@ const char* cmConditionEvaluator::GetDefinitionIfUnquoted( "Since the policy is not set the OLD behavior will be used."; this->Makefile.GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, e.str(), this->Backtrace); + MessageType::AUTHOR_WARNING, e.str(), this->Backtrace); } } @@ -199,7 +202,7 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword, "Since the policy is not set the OLD behavior will be used."; this->Makefile.GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, e.str(), this->Backtrace); + MessageType::AUTHOR_WARNING, e.str(), this->Backtrace); } } @@ -269,7 +272,7 @@ bool cmConditionEvaluator::GetBooleanValueOld( // returns the resulting boolean value bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( cmExpandedCommandArgument& newArg, std::string& errorString, - cmake::MessageType& status, bool oneArg) const + MessageType& status, bool oneArg) const { // Use the policy if it is set. if (this->Policy12Status == cmPolicies::NEW) { @@ -288,7 +291,7 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( errorString = "An argument named \"" + newArg.GetValue() + "\" appears in a conditional statement. " + cmPolicies::GetPolicyWarning(cmPolicies::CMP0012); - status = cmake::AUTHOR_WARNING; + status = MessageType::AUTHOR_WARNING; CM_FALLTHROUGH; case cmPolicies::OLD: return oldResult; @@ -297,7 +300,7 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( errorString = "An argument named \"" + newArg.GetValue() + "\" appears in a conditional statement. " + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0012); - status = cmake::FATAL_ERROR; + status = MessageType::FATAL_ERROR; } case cmPolicies::NEW: break; @@ -362,7 +365,7 @@ void cmConditionEvaluator::HandleBinaryOp(bool value, int& reducible, // level 0 processes parenthetical expressions bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status) + MessageType& status) { int reducible; do { @@ -386,7 +389,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, } if (depth) { errorString = "mismatched parenthesis in condition"; - status = cmake::FATAL_ERROR; + status = MessageType::FATAL_ERROR; return false; } // store the reduced args in this vector @@ -419,7 +422,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, //========================================================================= // level one handles most predicates except for NOT bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, - cmake::MessageType&) + MessageType&) { int reducible; do { @@ -485,7 +488,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, "when the policy is set to NEW. " "Since the policy is not set the OLD behavior will be used."; - this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } // is a variable defined if (this->IsKeyword(keyDEFINED, *arg) && argP1 != newArgs.end()) { @@ -495,6 +498,12 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, argP1->GetValue().operator[](argP1len - 1) == '}') { std::string env = argP1->GetValue().substr(4, argP1len - 5); bdef = cmSystemTools::HasEnv(env); + } else if (argP1len > 6 && + argP1->GetValue().substr(0, 6) == "CACHE{" && + argP1->GetValue().operator[](argP1len - 1) == '}') { + std::string cache = argP1->GetValue().substr(6, argP1len - 7); + bdef = + this->Makefile.GetState()->GetCacheEntryValue(cache) != nullptr; } else { bdef = this->Makefile.IsDefinitionSet(argP1->GetValue()); } @@ -510,7 +519,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, // level two handles most binary operations except for AND OR bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status) + MessageType& status) { int reducible; std::string def_buf; @@ -541,7 +550,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::ostringstream error; error << "Regular expression \"" << rex << "\" cannot compile"; errorString = error.str(); - status = cmake::FATAL_ERROR; + status = MessageType::FATAL_ERROR; return false; } if (regEntry.find(def)) { @@ -676,7 +685,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, "when the policy is set to NEW. " "Since the policy is not set the OLD behavior will be used."; - this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } } @@ -690,7 +699,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, // level 3 handles NOT bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status) + MessageType& status) { int reducible; do { @@ -716,7 +725,7 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, // level 4 handles AND OR bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status) + MessageType& status) { int reducible; bool lhs; diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index 50f4edc4f..59e1396f6 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -11,8 +11,8 @@ #include "cmExpandedCommandArgument.h" #include "cmListFileCache.h" +#include "cmMessageType.h" #include "cmPolicies.h" -#include "cmake.h" class cmMakefile; @@ -21,14 +21,14 @@ class cmConditionEvaluator public: typedef std::list<cmExpandedCommandArgument> cmArgumentList; - cmConditionEvaluator(cmMakefile& makefile, cmListFileContext const& context, - cmListFileBacktrace const& bt); + cmConditionEvaluator(cmMakefile& makefile, cmListFileContext context, + cmListFileBacktrace bt); // this is a shared function for both If and Else to determine if the // arguments were valid, and if so, was the response true. If there is // an error, the errorString will be set. bool IsTrue(const std::vector<cmExpandedCommandArgument>& args, - std::string& errorString, cmake::MessageType& status); + std::string& errorString, MessageType& status); private: // Filter the given variable definition based on policy CMP0054. @@ -48,7 +48,7 @@ private: bool GetBooleanValueWithAutoDereference(cmExpandedCommandArgument& newArg, std::string& errorString, - cmake::MessageType& status, + MessageType& status, bool oneArg = false) const; void IncrementArguments(cmArgumentList& newArgs, @@ -66,19 +66,18 @@ private: cmArgumentList::iterator& argP2); bool HandleLevel0(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status); + MessageType& status); - bool HandleLevel1(cmArgumentList& newArgs, std::string&, - cmake::MessageType&); + bool HandleLevel1(cmArgumentList& newArgs, std::string&, MessageType&); bool HandleLevel2(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status); + MessageType& status); bool HandleLevel3(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status); + MessageType& status); bool HandleLevel4(cmArgumentList& newArgs, std::string& errorString, - cmake::MessageType& status); + MessageType& status); cmMakefile& Makefile; cmListFileContext ExecutionContext; diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index c80439b13..19b1cd4e3 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -20,13 +20,10 @@ #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@" #define CM_FALLTHROUGH cmsys_FALLTHROUGH -#define CM_DISABLE_COPY(Class) \ - Class(Class const&) = delete; \ - Class& operator=(Class const&) = delete; - #endif diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx index 305262d2d..8224a0fe3 100644 --- a/Source/cmConfigureFileCommand.cxx +++ b/Source/cmConfigureFileCommand.cxx @@ -5,8 +5,8 @@ #include <sstream> #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -89,7 +89,7 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args, if (!unknown_args.empty()) { std::string msg = "configure_file called with unknown argument(s):\n"; msg += unknown_args; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); } if (!this->ConfigureFile()) { diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx index 50e193668..166426bfc 100644 --- a/Source/cmConnection.cxx +++ b/Source/cmConnection.cxx @@ -127,9 +127,7 @@ void cmEventBasedConnection::OnDisconnect(int onerror) } } -cmConnection::~cmConnection() -{ -} +cmConnection::~cmConnection() = default; bool cmConnection::OnConnectionShuttingDown() { diff --git a/Source/cmConnection.h b/Source/cmConnection.h index ce2d2dc2a..092b91302 100644 --- a/Source/cmConnection.h +++ b/Source/cmConnection.h @@ -60,10 +60,11 @@ public: class cmConnection { - CM_DISABLE_COPY(cmConnection) - public: - cmConnection() {} + cmConnection() = default; + + cmConnection(cmConnection const&) = delete; + cmConnection& operator=(cmConnection const&) = delete; virtual void WriteData(const std::string& data) = 0; diff --git a/Source/cmContinueCommand.cxx b/Source/cmContinueCommand.cxx index 2298a05c5..48f1f411b 100644 --- a/Source/cmContinueCommand.cxx +++ b/Source/cmContinueCommand.cxx @@ -4,15 +4,15 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" // cmContinueCommand bool cmContinueCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) { if (!this->Makefile->IsLoopBlock()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "A CONTINUE command was found outside of a " "proper FOREACH or WHILE loop scope."); cmSystemTools::SetFatalErrorOccured(); @@ -22,7 +22,7 @@ bool cmContinueCommand::InitialPass(std::vector<std::string> const& args, status.SetContinueInvoked(); if (!args.empty()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "The CONTINUE command does not accept any " "arguments."); cmSystemTools::SetFatalErrorOccured(); diff --git a/Source/cmConvertMSBuildXMLToJSON.py b/Source/cmConvertMSBuildXMLToJSON.py index 92569e744..02074ba65 100644 --- a/Source/cmConvertMSBuildXMLToJSON.py +++ b/Source/cmConvertMSBuildXMLToJSON.py @@ -96,7 +96,6 @@ def read_msbuild_json(path, values=[]): return values - def main(): """Script entrypoint.""" # Parse the arguments @@ -213,6 +212,14 @@ def __find_and_remove_value(list, compare): return found +def __normalize_switch(switch, separator): + new = switch + if switch.startswith("/") or switch.startswith("-"): + new = switch[1:] + if new and separator: + new = new + separator + return new + ########################################################################################### # private xml functions def __convert(root, tag, values, func): @@ -257,6 +264,8 @@ def __convert_bool(node): reverse_switch = __get_attribute(node, 'ReverseSwitch') if reverse_switch: + __with_argument(node, converted) + converted_reverse = copy.deepcopy(converted) converted_reverse['switch'] = reverse_switch @@ -303,7 +312,11 @@ def __convert_node(node, default_value='', default_flags=vsflags()): converted = {} converted['name'] = name - converted['switch'] = __get_attribute(node, 'Switch') + + switch = __get_attribute(node, 'Switch') + separator = __get_attribute(node, 'Separator') + converted['switch'] = __normalize_switch(switch, separator) + converted['comment'] = __get_attribute(node, 'DisplayName') converted['value'] = default_value @@ -435,7 +448,7 @@ def __write_json_file(path, values): with open(path, 'w') as f: json.dump(sorted_values, f, indent=2, separators=(',', ': ')) - + f.write("\n") ########################################################################################### # private list helpers diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 0b50121ae..3892011a5 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -13,6 +13,7 @@ #include "cmExportTryCompileFileGenerator.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmState.h" @@ -24,10 +25,18 @@ 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_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS"; static std::string const kCMAKE_LINK_SEARCH_END_STATIC = "CMAKE_LINK_SEARCH_END_STATIC"; @@ -48,6 +57,12 @@ static std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = "CMAKE_TRY_COMPILE_PLATFORM_VARIABLES"; static std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED"; +/* GHS Multi platform variables */ +static std::set<std::string> ghs_platform_vars{ + "GHS_TARGET_PLATFORM", "GHS_PRIMARY_TARGET", "GHS_TOOLSET_ROOT", + "GHS_OS_ROOT", "GHS_OS_DIR", "GHS_BSP_NAME" +}; + static void writeProperty(FILE* fout, std::string const& targetName, std::string const& prop, std::string const& value) { @@ -88,7 +103,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, targetType = cmStateEnums::STATIC_LIBRARY; } else { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, std::string("Invalid value '") + tt + "' for " "CMAKE_TRY_COMPILE_TARGET_TYPE. Only " @@ -108,6 +123,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::string targetName; std::vector<std::string> cmakeFlags(1, "CMAKE_FLAGS"); // fake argv[0] std::vector<std::string> compileDefs; + std::string cmakeInternal; std::string outputVariable; std::string copyFile; std::string copyFileError; @@ -121,6 +137,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::string cxxExtensions; std::string cudaExtensions; std::vector<std::string> targets; + std::vector<std::string> linkOptions; std::string libsToLink = " "; bool useOldLinkLibs = true; char targetNameBuf[64]; @@ -144,6 +161,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, DoingNone, DoingCMakeFlags, DoingCompileDefinitions, + DoingLinkOptions, DoingLinkLibraries, DoingOutputVariable, DoingCopyFile, @@ -157,7 +175,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, DoingCExtensions, DoingCxxExtensions, DoingCudaExtensions, - DoingSources + DoingSources, + DoingCMakeInternal }; Doing doing = useSources ? DoingSources : DoingNone; for (size_t i = 3; i < argv.size(); ++i) { @@ -165,6 +184,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, doing = DoingCMakeFlags; } else if (argv[i] == "COMPILE_DEFINITIONS") { doing = DoingCompileDefinitions; + } else if (argv[i] == "LINK_OPTIONS") { + doing = DoingLinkOptions; } else if (argv[i] == "LINK_LIBRARIES") { doing = DoingLinkLibraries; useOldLinkLibs = false; @@ -204,10 +225,14 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } else if (argv[i] == "CUDA_EXTENSIONS") { doing = DoingCudaExtensions; didCudaExtensions = true; + } else if (argv[i] == "__CMAKE_INTERNAL") { + doing = DoingCMakeInternal; } else if (doing == DoingCMakeFlags) { cmakeFlags.push_back(argv[i]); } else if (doing == DoingCompileDefinitions) { - compileDefs.push_back(argv[i]); + cmSystemTools::ExpandListArgument(argv[i], compileDefs); + } else if (doing == DoingLinkOptions) { + linkOptions.push_back(argv[i]); } else if (doing == DoingLinkLibraries) { libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" "; if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) { @@ -224,7 +249,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, CM_FALLTHROUGH; default: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Only libraries may be used as try_compile or try_run IMPORTED " "LINK_LIBRARIES. Got " + std::string(tgt->GetName()) + @@ -275,6 +300,9 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, doing = DoingNone; } else if (doing == DoingSources) { sources.push_back(argv[i]); + } else if (doing == DoingCMakeInternal) { + cmakeInternal = argv[i]; + doing = DoingNone; } else if (i == 3) { this->SrcFileSignature = false; projectName = argv[i].c_str(); @@ -283,93 +311,95 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } else { std::ostringstream m; m << "try_compile given unknown argument \"" << argv[i] << "\"."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m.str()); } } if (didCopyFile && copyFile.empty()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "COPY_FILE must be followed by a file path"); return -1; } if (didCopyFileError && copyFileError.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "COPY_FILE_ERROR must be followed by a variable name"); return -1; } if (didCopyFileError && !didCopyFile) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "COPY_FILE_ERROR may be used only with COPY_FILE"); + MessageType::FATAL_ERROR, + "COPY_FILE_ERROR may be used only with COPY_FILE"); return -1; } if (didOutputVariable && outputVariable.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "OUTPUT_VARIABLE must be followed by a variable name"); return -1; } if (useSources && sources.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "SOURCES must be followed by at least one source file"); return -1; } if (didCStandard && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "C_STANDARD allowed only in source file signature."); + MessageType::FATAL_ERROR, + "C_STANDARD allowed only in source file signature."); return -1; } if (didCxxStandard && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CXX_STANDARD allowed only in source file signature."); return -1; } if (didCudaStandard && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CUDA_STANDARD allowed only in source file signature."); return -1; } if (didCStandardRequired && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "C_STANDARD_REQUIRED allowed only in source file signature."); return -1; } if (didCxxStandardRequired && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CXX_STANDARD_REQUIRED allowed only in source file signature."); return -1; } if (didCudaStandardRequired && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CUDA_STANDARD_REQUIRED allowed only in source file signature."); return -1; } if (didCExtensions && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "C_EXTENSIONS allowed only in source file signature."); return -1; } if (didCxxExtensions && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CXX_EXTENSIONS allowed only in source file signature."); return -1; } if (didCudaExtensions && !this->SrcFileSignature) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CUDA_EXTENSIONS allowed only in source file signature."); return -1; } @@ -377,19 +407,19 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, // compute the binary dir when TRY_COMPILE is called with a src file // signature if (this->SrcFileSignature) { - this->BinaryDirectory += cmake::GetCMakeFilesDirectory(); + this->BinaryDirectory += "/CMakeFiles"; this->BinaryDirectory += "/CMakeTmp"; } else { // only valid for srcfile signatures if (!compileDefs.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE"); return -1; } if (!copyFile.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "COPY_FILE specified on a srcdir type TRY_COMPILE"); return -1; } @@ -402,7 +432,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::ostringstream e; e << "Attempt at a recursive or nested TRY_COMPILE in directory\n" << " " << this->BinaryDirectory << "\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return -1; } @@ -436,7 +466,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, gg->GetEnabledLanguages(langs); err << cmJoin(langs, " "); err << "\nSee project() command to enable other languages."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, err.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, err.str()); return -1; } } @@ -457,7 +487,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, << " " << outFileName << "\n" << cmSystemTools::GetLastSystemError(); /* clang-format on */ - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return -1; } @@ -485,6 +515,14 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } } fprintf(fout, "project(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str()); + if (cmakeInternal == "ABI") { + // This is the ABI detection step, also used for implicit includes. + // Erase any include_directories() calls from the toolchain file so + // that we do not see them as implicit. Our ABI detection source + // does not include any system headers anyway. + fprintf(fout, + "set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES \"\")\n"); + } fprintf(fout, "set(CMAKE_VERBOSE_MAKEFILE 1)\n"); for (std::string const& li : testLangs) { std::string langFlags = "CMAKE_" + li + "_FLAGS"; @@ -508,7 +546,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, "(e.g. CMAKE_C_FLAGS_DEBUG) in the test project." ; /* clang-format on */ - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } case cmPolicies::OLD: // OLD behavior is to do nothing. @@ -516,7 +554,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0066)); CM_FALLTHROUGH; case cmPolicies::NEW: { @@ -545,7 +583,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, "in the test project." ; /* clang-format on */ - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } case cmPolicies::OLD: // OLD behavior is to do nothing. @@ -553,7 +591,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0056)); CM_FALLTHROUGH; case cmPolicies::NEW: @@ -576,7 +614,9 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, fprintf(fout, "link_directories(${LINK_DIRECTORIES})\n"); // handle any compile flags we need to pass on if (!compileDefs.empty()) { - fprintf(fout, "add_definitions(%s)\n", cmJoin(compileDefs, " ").c_str()); + // Pass using bracket arguments to preserve content. + fprintf(fout, "add_definitions([==[%s]==])\n", + cmJoin(compileDefs, "]==] [==[").c_str()); } /* Use a random file name to avoid rapid creation and deletion @@ -592,7 +632,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, tcfg.SetConfig(tcConfig); if (!tcfg.GenerateImportFile()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "could not write export file."); fclose(fout); return -1; @@ -627,6 +667,16 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, vars.insert(varList.begin(), varList.end()); } + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0083) == + 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); + } + /* for the TRY_COMPILEs we want to be able to specify the architecture. So the user can set CMAKE_OSX_ARCHITECTURES to i386;ppc and then set CMAKE_TRY_COMPILE_OSX_ARCHITECTURES first to i386 and then to ppc to @@ -656,6 +706,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, ? "NEW" : "OLD"); + /* Set the appropriate policy information for PIE link flags */ + fprintf(fout, "cmake_policy(SET CMP0083 %s)\n", + this->Makefile->GetPolicyStatus(cmPolicies::CMP0083) == + cmPolicies::NEW + ? "NEW" + : "OLD"); + if (targetType == cmStateEnums::EXECUTABLE) { /* Put the executable at a known location (for COPY_FILE). */ fprintf(fout, "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n", @@ -703,7 +760,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0067)); case cmPolicies::NEW: // NEW behavior is to honor the language standard variables. @@ -765,7 +822,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, for (std::string const& vi : this->WarnCMP0067) { w << " " << vi << "\n"; } - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } if (testC) { @@ -807,6 +864,23 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } } + if (!linkOptions.empty()) { + std::vector<std::string> options; + options.reserve(linkOptions.size()); + for (const auto& option : linkOptions) { + options.emplace_back(cmOutputConverter::EscapeForCMake(option)); + } + + if (targetType == cmStateEnums::STATIC_LIBRARY) { + fprintf(fout, + "set_property(TARGET %s PROPERTY STATIC_LIBRARY_OPTIONS %s)\n", + targetName.c_str(), cmJoin(options, " ").c_str()); + } else { + fprintf(fout, "target_link_options(%s PRIVATE %s)\n", + targetName.c_str(), cmJoin(options, " ").c_str()); + } + } + if (useOldLinkLibs) { fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n", targetName.c_str()); @@ -818,6 +892,16 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, projectName = "CMAKE_TRY_COMPILE"; } + 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; + cmakeFlags.push_back(std::move(flag)); + } + } + } + bool erroroc = cmSystemTools::GetErrorOccuredFlag(); cmSystemTools::ResetErrorOccuredFlag(); std::string output; @@ -857,7 +941,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, emsg << this->FindErrorMessage.c_str(); } if (copyFileError.empty()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, emsg.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, emsg.str()); return -1; } copyFileErrorMessage = emsg.str(); @@ -954,12 +1038,12 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName, tmp += config; searchDirs.push_back(std::move(tmp)); } - searchDirs.push_back("/Debug"); + searchDirs.emplace_back("/Debug"); #if defined(__APPLE__) std::string app = "/Debug/" + targetName + ".app"; searchDirs.push_back(std::move(app)); #endif - searchDirs.push_back("/Development"); + searchDirs.emplace_back("/Development"); for (std::string const& sdir : searchDirs) { std::string command = this->BinaryDirectory; diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index 1f2a1b52c..b712f09da 100644 --- a/Source/cmCryptoHash.h +++ b/Source/cmCryptoHash.h @@ -15,8 +15,6 @@ */ class cmCryptoHash { - CM_DISABLE_COPY(cmCryptoHash) - public: enum Algo { @@ -35,6 +33,9 @@ public: cmCryptoHash(Algo algo); ~cmCryptoHash(); + cmCryptoHash(cmCryptoHash const&) = delete; + cmCryptoHash& operator=(cmCryptoHash const&) = delete; + /// @brief Returns a new hash generator of the requested type /// @arg algo Hash type name. Supported hash types are /// MD5, SHA1, SHA224, SHA256, SHA384, SHA512, diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx index 3360323f0..0004f666b 100644 --- a/Source/cmCurl.cxx +++ b/Source/cmCurl.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCurl.h" -#include "cmThirdParty.h" - #if !defined(CMAKE_USE_SYSTEM_CURL) && !defined(_WIN32) && \ !defined(__APPLE__) && !defined(CURL_CA_BUNDLE) && !defined(CURL_CA_PATH) # define CMAKE_FIND_CAFILE @@ -16,11 +14,13 @@ #endif #define check_curl_result(result, errstr) \ - if ((result) != CURLE_OK && (result) != CURLE_NOT_BUILT_IN) { \ - e += e.empty() ? "" : "\n"; \ - e += (errstr); \ - e += ::curl_easy_strerror(result); \ - } + do { \ + if ((result) != CURLE_OK && (result) != CURLE_NOT_BUILT_IN) { \ + e += e.empty() ? "" : "\n"; \ + e += (errstr); \ + e += ::curl_easy_strerror(result); \ + } \ + } while (false) std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile) { diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx index cfd260c23..242ceaab4 100644 --- a/Source/cmCustomCommand.cxx +++ b/Source/cmCustomCommand.cxx @@ -4,34 +4,22 @@ #include "cmMakefile.h" -cmCustomCommand::cmCustomCommand() - : Backtrace() -{ - this->HaveComment = false; - this->EscapeOldStyle = true; - this->EscapeAllowMakeVars = false; - this->UsesTerminal = false; - this->CommandExpandLists = false; -} +#include <utility> cmCustomCommand::cmCustomCommand(cmMakefile const* mf, - const std::vector<std::string>& outputs, - const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const cmCustomCommandLines& commandLines, + std::vector<std::string> outputs, + std::vector<std::string> byproducts, + std::vector<std::string> depends, + cmCustomCommandLines commandLines, const char* comment, const char* workingDirectory) - : Outputs(outputs) - , Byproducts(byproducts) - , Depends(depends) - , CommandLines(commandLines) - , Backtrace() + : Outputs(std::move(outputs)) + , Byproducts(std::move(byproducts)) + , Depends(std::move(depends)) + , CommandLines(std::move(commandLines)) , Comment(comment ? comment : "") , WorkingDirectory(workingDirectory ? workingDirectory : "") , HaveComment(comment != nullptr) - , EscapeAllowMakeVars(false) - , EscapeOldStyle(true) - , CommandExpandLists(false) { if (mf) { this->Backtrace = mf->GetBacktrace(); diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h index 9e82f2505..50f15a46f 100644 --- a/Source/cmCustomCommand.h +++ b/Source/cmCustomCommand.h @@ -22,16 +22,12 @@ class cmMakefile; class cmCustomCommand { public: - /** Default and copy constructors for STL containers. */ - cmCustomCommand(); - /** Main constructor specifies all information for the command. */ - cmCustomCommand(cmMakefile const* mf, - const std::vector<std::string>& outputs, - const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const cmCustomCommandLines& commandLines, - const char* comment, const char* workingDirectory); + cmCustomCommand(cmMakefile const* mf, std::vector<std::string> outputs, + std::vector<std::string> byproducts, + std::vector<std::string> depends, + cmCustomCommandLines commandLines, const char* comment, + const char* workingDirectory); /** Get the output file produced by the command. */ const std::vector<std::string>& GetOutputs() const; @@ -103,11 +99,11 @@ private: std::string Comment; std::string WorkingDirectory; std::string Depfile; - bool HaveComment; - bool EscapeAllowMakeVars; - bool EscapeOldStyle; - bool UsesTerminal; - bool CommandExpandLists; + bool HaveComment = false; + bool EscapeAllowMakeVars = false; + bool EscapeOldStyle = true; + bool UsesTerminal = false; + bool CommandExpandLists = false; }; #endif diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index d1c173670..6bf99468e 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -16,10 +16,10 @@ #include <utility> cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, - const std::string& config, + std::string config, cmLocalGenerator* lg) : CC(cc) - , Config(config) + , Config(std::move(config)) , LG(lg) , OldStyle(cc.GetEscapeOldStyle()) , MakeVars(cc.GetEscapeAllowMakeVars()) diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index b7e2a3924..9684cffa8 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -29,8 +29,8 @@ class cmCustomCommandGenerator const char* GetArgv0Location(unsigned int c) const; public: - cmCustomCommandGenerator(cmCustomCommand const& cc, - const std::string& config, cmLocalGenerator* lg); + cmCustomCommandGenerator(cmCustomCommand const& cc, std::string config, + cmLocalGenerator* lg); ~cmCustomCommandGenerator(); cmCustomCommand const& GetCC() const { return this->CC; } unsigned int GetNumberOfCommands() const; diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index 4ab5be6cc..6c252bee5 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -47,26 +47,19 @@ private: typedef std::string std_string; public: - Def() - : std_string() - , Exists(false) - , Used(false) - { - } + Def() = default; Def(const char* v) : std_string(v ? v : "") , Exists(v ? true : false) - , Used(false) { } Def(const std_string& v) : std_string(v) , Exists(true) - , Used(false) { } - bool Exists; - bool Used; + bool Exists = false; + bool Used = false; }; static Def NoDef; diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 6f1afd7bc..7d1d31624 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -13,12 +13,9 @@ #include <string.h> #include <utility> -cmDepends::cmDepends(cmLocalGenerator* lg, const char* targetDir) +cmDepends::cmDepends(cmLocalGenerator* lg, std::string targetDir) : LocalGenerator(lg) - , Verbose(false) - , FileComparison(nullptr) - , TargetDirectory(targetDir) - , MaxPath(16384) + , TargetDirectory(std::move(targetDir)) , Dependee(new char[MaxPath]) , Depender(new char[MaxPath]) { @@ -68,12 +65,13 @@ bool cmDepends::Finalize(std::ostream& /*unused*/, std::ostream& /*unused*/) return true; } -bool cmDepends::Check(const char* makeFile, const char* internalFile, +bool cmDepends::Check(const std::string& makeFile, + const std::string& internalFile, std::map<std::string, DependencyVector>& validDeps) { // Check whether dependencies must be regenerated. bool okay = true; - cmsys::ifstream fin(internalFile); + cmsys::ifstream fin(internalFile.c_str()); if (!(fin && this->CheckDependencies(fin, internalFile, validDeps))) { // Clear all dependencies so they will be regenerated. this->Clear(makeFile); @@ -84,13 +82,13 @@ bool cmDepends::Check(const char* makeFile, const char* internalFile, return okay; } -void cmDepends::Clear(const char* file) +void cmDepends::Clear(const std::string& file) { // Print verbose output. if (this->Verbose) { std::ostringstream msg; msg << "Clearing dependencies in \"" << file << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } // Write an empty dependency file. @@ -110,7 +108,7 @@ bool cmDepends::WriteDependencies(const std::set<std::string>& /*unused*/, } bool cmDepends::CheckDependencies( - std::istream& internalDepends, const char* internalDependsFileName, + std::istream& internalDepends, const std::string& internalDependsFileName, std::map<std::string, DependencyVector>& validDeps) { // Parse dependencies from the stream. If any dependee is missing @@ -158,8 +156,8 @@ bool cmDepends::CheckDependencies( // * if the depender does not exist, but the dependee is newer than the // depends file bool regenerate = false; - const char* dependee = this->Dependee + 1; - const char* depender = this->Depender; + const std::string dependee(this->Dependee + 1); + const std::string depender(this->Depender); if (currentDependencies != nullptr) { currentDependencies->push_back(dependee); } @@ -173,7 +171,7 @@ bool cmDepends::CheckDependencies( std::ostringstream msg; msg << "Dependee \"" << dependee << "\" does not exist for depender \"" << depender << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } } else { if (dependerExists) { @@ -190,7 +188,7 @@ bool cmDepends::CheckDependencies( std::ostringstream msg; msg << "Dependee \"" << dependee << "\" is newer than depender \"" << depender << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } } } else { @@ -209,7 +207,7 @@ bool cmDepends::CheckDependencies( msg << "Dependee \"" << dependee << "\" is newer than depends file \"" << internalDependsFileName << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } } } diff --git a/Source/cmDepends.h b/Source/cmDepends.h index 4b9e05a88..20c91ca57 100644 --- a/Source/cmDepends.h +++ b/Source/cmDepends.h @@ -24,12 +24,13 @@ class cmLocalGenerator; */ class cmDepends { - CM_DISABLE_COPY(cmDepends) - public: /** Instances need to know the build directory name and the relative path from the build directory to the target file. */ - cmDepends(cmLocalGenerator* lg = nullptr, const char* targetDir = ""); + cmDepends(cmLocalGenerator* lg = nullptr, std::string targetDir = ""); + + cmDepends(cmDepends const&) = delete; + cmDepends& operator=(cmDepends const&) = delete; /** Set the local generator for the directory in which we are scanning dependencies. This is not a full local generator; it @@ -41,7 +42,10 @@ public: void SetLanguage(const std::string& lang) { this->Language = lang; } /** Set the target build directory. */ - void SetTargetDirectory(const char* dir) { this->TargetDirectory = dir; } + void SetTargetDirectory(const std::string& dir) + { + this->TargetDirectory = dir; + } /** should this be verbose in its output */ void SetVerbose(bool verb) { this->Verbose = verb; } @@ -61,11 +65,11 @@ public: they must be generated Clear has already been called to wipe out the old dependencies. Dependencies which are still valid will be stored in validDeps. */ - bool Check(const char* makeFile, const char* internalFile, + bool Check(const std::string& makeFile, const std::string& internalFile, std::map<std::string, DependencyVector>& validDeps); /** Clear dependencies for the target file so they will be regenerated. */ - void Clear(const char* file); + void Clear(const std::string& file); /** Set the file comparison object */ void SetFileComparison(cmFileTimeComparison* fc) @@ -85,7 +89,7 @@ protected: // Return false if dependencies must be regenerated and true // otherwise. virtual bool CheckDependencies( - std::istream& internalDepends, const char* internalDependsFileName, + std::istream& internalDepends, const std::string& internalDependsFileName, std::map<std::string, DependencyVector>& validDeps); // Finalize the dependency information for the target. @@ -96,15 +100,15 @@ protected: cmLocalGenerator* LocalGenerator; // Flag for verbose output. - bool Verbose; - cmFileTimeComparison* FileComparison; + bool Verbose = false; + cmFileTimeComparison* FileComparison = nullptr; std::string Language; // The full path to the target's build directory. std::string TargetDirectory; - size_t MaxPath; + size_t MaxPath = 16384; char* Dependee; char* Depender; diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index f7dd33b37..b1630f9ae 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -19,13 +19,10 @@ #define INCLUDE_REGEX_COMPLAIN_MARKER "#IncludeRegexComplain: " #define INCLUDE_REGEX_TRANSFORM_MARKER "#IncludeRegexTransform: " -cmDependsC::cmDependsC() - : ValidDeps(nullptr) -{ -} +cmDependsC::cmDependsC() = default; cmDependsC::cmDependsC( - cmLocalGenerator* lg, const char* targetDir, const std::string& lang, + cmLocalGenerator* lg, const std::string& targetDir, const std::string& lang, const std::map<std::string, DependencyVector>* validDeps) : cmDepends(lg, targetDir) , ValidDeps(validDeps) @@ -54,8 +51,8 @@ cmDependsC::cmDependsC( } this->IncludeRegexLine.compile(INCLUDE_REGEX_LINE); - this->IncludeRegexScan.compile(scanRegex.c_str()); - this->IncludeRegexComplain.compile(complainRegex.c_str()); + this->IncludeRegexScan.compile(scanRegex); + this->IncludeRegexComplain.compile(complainRegex); this->IncludeRegexLineString = INCLUDE_REGEX_LINE_MARKER INCLUDE_REGEX_LINE; this->IncludeRegexScanString = INCLUDE_REGEX_SCAN_MARKER; this->IncludeRegexScanString += scanRegex; @@ -101,7 +98,8 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, // Compute a path to the object file to write to the internal depend file. // Any existing content of the internal depend file has already been // loaded in ValidDeps with this path as a key. - std::string obj_i = this->LocalGenerator->ConvertToRelativePath(binDir, obj); + std::string obj_i = + this->LocalGenerator->MaybeConvertToRelativePath(binDir, obj); if (this->ValidDeps != nullptr) { std::map<std::string, DependencyVector>::const_iterator tmpIt = @@ -213,7 +211,7 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, // Scan this file for new dependencies. Pass the directory // containing the file to handle double-quote includes. std::string dir = cmSystemTools::GetFilenamePath(fullName); - this->Scan(fin, dir.c_str(), fullName); + this->Scan(fin, dir, fullName); } else { // Skip file with encoding we do not implement. } @@ -235,7 +233,8 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, for (std::string const& dep : dependencies) { makeDepends << obj_m << ": " << cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->ConvertToRelativePath(binDir, dep)) + this->LocalGenerator->MaybeConvertToRelativePath(binDir, + dep)) << std::endl; internalDepends << " " << dep << std::endl; } @@ -269,8 +268,7 @@ void cmDependsC::ReadCacheFile() haveFileName = true; int newer = 0; cmFileTimeComparison comp; - bool res = comp.FileTimeCompare(this->CacheFileName.c_str(), - line.c_str(), &newer); + bool res = comp.FileTimeCompare(this->CacheFileName, line, &newer); if (res && newer == 1) // cache is newer than the parsed file { @@ -343,7 +341,7 @@ void cmDependsC::WriteCacheFile() const } } -void cmDependsC::Scan(std::istream& is, const char* directory, +void cmDependsC::Scan(std::istream& is, const std::string& directory, const std::string& fullName) { cmIncludeLines* newCacheEntry = new cmIncludeLines; @@ -419,7 +417,7 @@ void cmDependsC::SetupTransforms() sep = "|"; } xform += ")[ \t]*\\(([^),]*)\\)"; - this->IncludeRegexTransform.compile(xform.c_str()); + this->IncludeRegexTransform.compile(xform); // Build a string that encodes all transformation rules and will // change when rules are changed. @@ -461,11 +459,11 @@ void cmDependsC::TransformLine(std::string& line) // Construct the transformed line. std::string newline = this->IncludeRegexTransform.match(1); std::string arg = this->IncludeRegexTransform.match(4); - for (const char* c = tri->second.c_str(); *c; ++c) { - if (*c == '%') { + for (char c : tri->second) { + if (c == '%') { newline += arg; } else { - newline += *c; + newline += c; } } diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index 2f76f6275..eee5ae15c 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -22,19 +22,20 @@ class cmLocalGenerator; */ class cmDependsC : public cmDepends { - CM_DISABLE_COPY(cmDependsC) - public: /** Checking instances need to know the build directory name and the relative path from the build directory to the target file. */ cmDependsC(); - cmDependsC(cmLocalGenerator* lg, const char* targetDir, + cmDependsC(cmLocalGenerator* lg, const std::string& targetDir, const std::string& lang, const std::map<std::string, DependencyVector>* validDeps); /** Virtual destructor to cleanup subclasses properly. */ ~cmDependsC() override; + cmDependsC(cmDependsC const&) = delete; + cmDependsC& operator=(cmDependsC const&) = delete; + protected: // Implement writing/checking methods required by superclass. bool WriteDependencies(const std::set<std::string>& sources, @@ -42,7 +43,7 @@ protected: std::ostream& internalDepends) override; // Method to scan a single file. - void Scan(std::istream& is, const char* directory, + void Scan(std::istream& is, const std::string& directory, const std::string& fullName); // Regular expression to identify C preprocessor include directives. @@ -75,16 +76,12 @@ public: struct cmIncludeLines { - cmIncludeLines() - : Used(false) - { - } std::vector<UnscannedEntry> UnscannedEntries; - bool Used; + bool Used = false; }; protected: - const std::map<std::string, DependencyVector>* ValidDeps; + const std::map<std::string, DependencyVector>* ValidDeps = nullptr; std::set<std::string> Encountered; std::queue<UnscannedEntry> Unscanned; diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index a04cee790..3f036a9de 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -7,7 +7,6 @@ #include <iostream> #include <map> #include <stdlib.h> -#include <string.h> #include <utility> #include "cmAlgorithms.h" @@ -54,7 +53,8 @@ public: typedef std::map<std::string, cmFortranSourceInfo> ObjectInfoMap; ObjectInfoMap ObjectInfo; - cmFortranSourceInfo& CreateObjectInfo(const char* obj, const char* src) + cmFortranSourceInfo& CreateObjectInfo(const std::string& obj, + const std::string& src) { std::map<std::string, cmFortranSourceInfo>::iterator i = this->ObjectInfo.find(obj); @@ -68,10 +68,7 @@ public: } }; -cmDependsFortran::cmDependsFortran() - : Internal(nullptr) -{ -} +cmDependsFortran::cmDependsFortran() = default; cmDependsFortran::cmDependsFortran(cmLocalGenerator* lg) : cmDepends(lg) @@ -97,6 +94,10 @@ cmDependsFortran::cmDependsFortran(cmLocalGenerator* lg) } this->PPDefinitions.insert(def); } + + this->CompilerId = mf->GetSafeDefinition("CMAKE_Fortran_COMPILER_ID"); + this->SModSep = mf->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP"); + this->SModExt = mf->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT"); } cmDependsFortran::~cmDependsFortran() @@ -119,15 +120,19 @@ bool cmDependsFortran::WriteDependencies(const std::set<std::string>& sources, return false; } + cmFortranCompiler fc; + fc.Id = this->CompilerId; + fc.SModSep = this->SModSep; + fc.SModExt = this->SModExt; + bool okay = true; for (std::string const& src : sources) { // Get the information object for this source. - cmFortranSourceInfo& info = - this->Internal->CreateObjectInfo(obj.c_str(), src.c_str()); + cmFortranSourceInfo& info = this->Internal->CreateObjectInfo(obj, src); // Create the parser object. The constructor takes info by reference, // so we may look into the resulting objects later. - cmFortranParser parser(this->IncludePath, this->PPDefinitions, info); + cmFortranParser parser(fc, this->IncludePath, this->PPDefinitions, info); // Push on the starting file. cmFortranParser_FilePush(&parser, src.c_str()); @@ -154,7 +159,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, this->LocateModules(); // Get the directory in which stamp files will be stored. - const char* stamp_dir = this->TargetDirectory.c_str(); + const std::string& stamp_dir = this->TargetDirectory; // Get the directory in which module files will be created. cmMakefile* mf = this->LocalGenerator->GetMakefile(); @@ -168,9 +173,8 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, typedef cmDependsFortranInternals::ObjectInfoMap ObjectInfoMap; ObjectInfoMap const& objInfo = this->Internal->ObjectInfo; for (auto const& i : objInfo) { - if (!this->WriteDependenciesReal(i.first.c_str(), i.second, mod_dir, - stamp_dir, makeDepends, - internalDepends)) { + if (!this->WriteDependenciesReal(i.first, i.second, mod_dir, stamp_dir, + makeDepends, internalDepends)) { return false; } } @@ -257,22 +261,22 @@ void cmDependsFortran::LocateModules() std::string fname = targetDir + "/fortran.internal"; cmsys::ifstream fin(fname.c_str()); if (fin) { - this->MatchRemoteModules(fin, targetDir.c_str()); + this->MatchRemoteModules(fin, targetDir); } } } void cmDependsFortran::MatchLocalModules() { - const char* stampDir = this->TargetDirectory.c_str(); + std::string const& stampDir = this->TargetDirectory; std::set<std::string> const& provides = this->Internal->TargetProvides; for (std::string const& i : provides) { - this->ConsiderModule(i.c_str(), stampDir); + this->ConsiderModule(i, stampDir); } } void cmDependsFortran::MatchRemoteModules(std::istream& fin, - const char* stampDir) + const std::string& stampDir) { std::string line; bool doing_provides = false; @@ -301,7 +305,8 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin, } } -void cmDependsFortran::ConsiderModule(const char* name, const char* stampDir) +void cmDependsFortran::ConsiderModule(const std::string& name, + const std::string& stampDir) { // Locate each required module. typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap; @@ -318,17 +323,17 @@ void cmDependsFortran::ConsiderModule(const char* name, const char* stampDir) } } -bool cmDependsFortran::WriteDependenciesReal(const char* obj, +bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, cmFortranSourceInfo const& info, std::string const& mod_dir, - const char* stamp_dir, + std::string const& stamp_dir, std::ostream& makeDepends, std::ostream& internalDepends) { typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap; // Get the source file for this object. - const char* src = info.Source.c_str(); + std::string const& src = info.Source; // Write the include dependencies to the output stream. std::string binDir = this->LocalGenerator->GetBinaryDirectory(); @@ -503,8 +508,7 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args) cmFortranModuleAppendUpperLower(cmSystemTools::GetFilenameName(mod), mod_upper, mod_lower); if (cmSystemTools::FileExists(mod_upper, true)) { - if (cmDependsFortran::ModulesDiffer(mod_upper.c_str(), stamp.c_str(), - compilerId.c_str())) { + if (cmDependsFortran::ModulesDiffer(mod_upper, stamp, compilerId)) { if (!cmSystemTools::CopyFileAlways(mod_upper, stamp)) { std::cerr << "Error copying Fortran module from \"" << mod_upper << "\" to \"" << stamp << "\".\n"; @@ -514,8 +518,7 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args) return true; } if (cmSystemTools::FileExists(mod_lower, true)) { - if (cmDependsFortran::ModulesDiffer(mod_lower.c_str(), stamp.c_str(), - compilerId.c_str())) { + if (cmDependsFortran::ModulesDiffer(mod_lower, stamp, compilerId)) { if (!cmSystemTools::CopyFileAlways(mod_lower, stamp)) { std::cerr << "Error copying Fortran module from \"" << mod_lower << "\" to \"" << stamp << "\".\n"; @@ -582,9 +585,9 @@ static bool cmFortranStreamsDiffer(std::istream& ifs1, std::istream& ifs2) return true; } -bool cmDependsFortran::ModulesDiffer(const char* modFile, - const char* stampFile, - const char* compilerId) +bool cmDependsFortran::ModulesDiffer(const std::string& modFile, + const std::string& stampFile, + const std::string& compilerId) { /* gnu >= 4.9: @@ -618,16 +621,17 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, * source is compiled twice * -SunPro */ - if (strcmp(compilerId, "SunPro") == 0) { + if (compilerId == "SunPro") { return cmSystemTools::FilesDiffer(modFile, stampFile); } #if defined(_WIN32) || defined(__CYGWIN__) - cmsys::ifstream finModFile(modFile, std::ios::in | std::ios::binary); - cmsys::ifstream finStampFile(stampFile, std::ios::in | std::ios::binary); + cmsys::ifstream finModFile(modFile.c_str(), std::ios::in | std::ios::binary); + cmsys::ifstream finStampFile(stampFile.c_str(), + std::ios::in | std::ios::binary); #else - cmsys::ifstream finModFile(modFile); - cmsys::ifstream finStampFile(stampFile); + cmsys::ifstream finModFile(modFile.c_str()); + cmsys::ifstream finStampFile(stampFile.c_str()); #endif if (!finModFile || !finStampFile) { // At least one of the files does not exist. The modules differ. @@ -642,7 +646,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, * Eat the stream content until all recompile only related changes * are left behind. */ - if (strcmp(compilerId, "GNU") == 0) { + if (compilerId == "GNU") { // GNU Fortran 4.9 and later compress .mod files with gzip // but also do not include a date so we can fall through to // compare them without skipping any prefix. @@ -665,7 +669,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, return true; } } - } else if (strcmp(compilerId, "Intel") == 0) { + } else if (compilerId == "Intel") { const char seq[2] = { '\n', '\0' }; const int seqlen = 2; @@ -697,9 +701,9 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, std::string cmDependsFortran::MaybeConvertToRelativePath( std::string const& base, std::string const& path) { - if (!cmOutputConverter::ContainedInDirectory( - base, path, this->LocalGenerator->GetStateSnapshot().GetDirectory())) { + if (!this->LocalGenerator->GetStateSnapshot().GetDirectory().ContainsBoth( + base, path)) { return path; } - return cmOutputConverter::ForceToRelativePath(base, path); + return cmSystemTools::ForceToRelativePath(base, path); } diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index bee980471..04851152e 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -21,8 +21,6 @@ class cmLocalGenerator; */ class cmDependsFortran : public cmDepends { - CM_DISABLE_COPY(cmDependsFortran) - public: /** Checking instances need to know the build directory name and the relative path from the build directory to the target file. */ @@ -37,6 +35,9 @@ public: /** Virtual destructor to cleanup subclasses properly. */ ~cmDependsFortran() override; + cmDependsFortran(cmDependsFortran const&) = delete; + cmDependsFortran& operator=(cmDependsFortran const&) = delete; + /** Callback from build system after a .mod file has been generated by a Fortran90 compiler to copy the .mod file to the corresponding stamp file. */ @@ -44,8 +45,9 @@ public: /** Determine if a mod file and the corresponding mod.stamp file are representing different module information. */ - static bool ModulesDiffer(const char* modFile, const char* stampFile, - const char* compilerId); + static bool ModulesDiffer(const std::string& modFile, + const std::string& stampFile, + const std::string& compilerId); protected: // Finalize the dependency information for the target. @@ -55,8 +57,8 @@ protected: // Find all the modules required by the target. void LocateModules(); void MatchLocalModules(); - void MatchRemoteModules(std::istream& fin, const char* stampDir); - void ConsiderModule(const char* name, const char* stampDir); + void MatchRemoteModules(std::istream& fin, const std::string& stampDir); + void ConsiderModule(const std::string& name, const std::string& stampDir); bool FindModule(std::string const& name, std::string& module); // Implement writing/checking methods required by superclass. @@ -65,18 +67,24 @@ protected: std::ostream& internalDepends) override; // Actually write the dependencies to the streams. - bool WriteDependenciesReal(const char* obj, cmFortranSourceInfo const& info, - std::string const& mod_dir, const char* stamp_dir, + bool WriteDependenciesReal(std::string const& obj, + cmFortranSourceInfo const& info, + std::string const& mod_dir, + std::string const& stamp_dir, std::ostream& makeDepends, std::ostream& internalDepends); // The source file from which to start scanning. std::string SourceFile; + std::string CompilerId; + std::string SModSep; + std::string SModExt; + std::set<std::string> PPDefinitions; // Internal implementation details. - cmDependsFortranInternals* Internal; + cmDependsFortranInternals* Internal = nullptr; private: std::string MaybeConvertToRelativePath(std::string const& base, diff --git a/Source/cmDependsJava.cxx b/Source/cmDependsJava.cxx index 29938ba36..2485e15fd 100644 --- a/Source/cmDependsJava.cxx +++ b/Source/cmDependsJava.cxx @@ -4,13 +4,9 @@ #include "cmSystemTools.h" -cmDependsJava::cmDependsJava() -{ -} +cmDependsJava::cmDependsJava() = default; -cmDependsJava::~cmDependsJava() -{ -} +cmDependsJava::~cmDependsJava() = default; bool cmDependsJava::WriteDependencies(const std::set<std::string>& sources, const std::string& /*obj*/, @@ -27,7 +23,8 @@ bool cmDependsJava::WriteDependencies(const std::set<std::string>& sources, } bool cmDependsJava::CheckDependencies( - std::istream& /*internalDepends*/, const char* /*internalDependsFileName*/, + std::istream& /*internalDepends*/, + const std::string& /*internalDependsFileName*/, std::map<std::string, DependencyVector>& /*validDeps*/) { return true; diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h index d070840ad..109ef13d1 100644 --- a/Source/cmDependsJava.h +++ b/Source/cmDependsJava.h @@ -17,8 +17,6 @@ */ class cmDependsJava : public cmDepends { - CM_DISABLE_COPY(cmDependsJava) - public: /** Checking instances need to know the build directory name and the relative path from the build directory to the target file. */ @@ -27,13 +25,16 @@ public: /** Virtual destructor to cleanup subclasses properly. */ ~cmDependsJava() override; + cmDependsJava(cmDependsJava const&) = delete; + cmDependsJava& operator=(cmDependsJava const&) = delete; + protected: // Implement writing/checking methods required by superclass. bool WriteDependencies(const std::set<std::string>& sources, const std::string& file, std::ostream& makeDepends, std::ostream& internalDepends) override; bool CheckDependencies( - std::istream& internalDepends, const char* internalDependsFileName, + std::istream& internalDepends, const std::string& internalDependsFileName, std::map<std::string, DependencyVector>& validDeps) override; }; diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx index 02db11978..792db48a4 100644 --- a/Source/cmDependsJavaParserHelper.cxx +++ b/Source/cmDependsJavaParserHelper.cxx @@ -68,7 +68,7 @@ void cmDependsJavaParserHelper::AddClassFound(const char* sclass) return; } } - this->ClassesFound.push_back(sclass); + this->ClassesFound.emplace_back(sclass); } void cmDependsJavaParserHelper::AddPackagesImport(const char* sclass) @@ -78,7 +78,7 @@ void cmDependsJavaParserHelper::AddPackagesImport(const char* sclass) return; } } - this->PackagesImport.push_back(sclass); + this->PackagesImport.emplace_back(sclass); } void cmDependsJavaParserHelper::SafePrintMissing(const char* str, int line, diff --git a/Source/cmDisallowedCommand.cxx b/Source/cmDisallowedCommand.cxx index ce1965d30..418d98c9f 100644 --- a/Source/cmDisallowedCommand.cxx +++ b/Source/cmDisallowedCommand.cxx @@ -3,7 +3,7 @@ #include "cmDisallowedCommand.h" #include "cmMakefile.h" -#include "cmake.h" +#include "cmMessageType.h" class cmExecutionStatus; @@ -12,7 +12,7 @@ bool cmDisallowedCommand::InitialPass(std::vector<std::string> const& args, { switch (this->Makefile->GetPolicyStatus(this->Policy)) { case cmPolicies::WARN: - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(this->Policy)); break; case cmPolicies::OLD: @@ -20,7 +20,7 @@ bool cmDisallowedCommand::InitialPass(std::vector<std::string> const& args, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: - this->Makefile->IssueMessage(cmake::FATAL_ERROR, this->Message); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, this->Message); return true; } diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index 2dfba04a7..d4628fa7e 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDocumentation.h" -#include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmDocumentationSection.h" #include "cmRST.h" @@ -44,22 +43,24 @@ static const char* cmDocumentationStandardOptions[][2] = { { nullptr, nullptr } }; -static const char* cmDocumentationGeneratorsHeader[][2] = { +static const char* cmDocumentationCPackGeneratorsHeader[][2] = { { nullptr, "The following generators are available on this platform:" }, { nullptr, nullptr } }; +static const char* cmDocumentationCMakeGeneratorsHeader[][2] = { + { nullptr, + "The following generators are available on this platform (* marks " + "default):" }, + { nullptr, nullptr } +}; + cmDocumentation::cmDocumentation() { this->addCommonStandardDocSections(); this->ShowGenerators = true; } -cmDocumentation::~cmDocumentation() -{ - cmDeleteAll(this->AllSections); -} - bool cmDocumentation::PrintVersion(std::ostream& os) { /* clang-format off */ @@ -145,10 +146,12 @@ bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os) } #define GET_OPT_ARGUMENT(target) \ - if ((i + 1 < argc) && !this->IsOption(argv[i + 1])) { \ - (target) = argv[i + 1]; \ - i = i + 1; \ - }; + do { \ + if ((i + 1 < argc) && !this->IsOption(argv[i + 1])) { \ + (target) = argv[i + 1]; \ + i = i + 1; \ + }; \ + } while (false) void cmDocumentation::WarnFormFromFilename( cmDocumentation::RequestedHelpItem& request, bool& result) @@ -174,20 +177,16 @@ void cmDocumentation::WarnFormFromFilename( void cmDocumentation::addCommonStandardDocSections() { - cmDocumentationSection* sec; - - sec = new cmDocumentationSection("Options", "OPTIONS"); - sec->Append(cmDocumentationStandardOptions); - this->AllSections["Options"] = sec; + cmDocumentationSection sec{ "Options" }; + sec.Append(cmDocumentationStandardOptions); + this->AllSections.emplace("Options", std::move(sec)); } void cmDocumentation::addCMakeStandardDocSections() { - cmDocumentationSection* sec; - - sec = new cmDocumentationSection("Generators", "GENERATORS"); - sec->Append(cmDocumentationGeneratorsHeader); - this->AllSections["Generators"] = sec; + cmDocumentationSection sec{ "Generators" }; + sec.Append(cmDocumentationCMakeGeneratorsHeader); + this->AllSections.emplace("Generators", std::move(sec)); } void cmDocumentation::addCTestStandardDocSections() @@ -199,11 +198,9 @@ void cmDocumentation::addCTestStandardDocSections() void cmDocumentation::addCPackStandardDocSections() { - cmDocumentationSection* sec; - - sec = new cmDocumentationSection("Generators", "GENERATORS"); - sec->Append(cmDocumentationGeneratorsHeader); - this->AllSections["Generators"] = sec; + cmDocumentationSection sec{ "Generators" }; + sec.Append(cmDocumentationCPackGeneratorsHeader); + this->AllSections.emplace("Generators", std::move(sec)); } bool cmDocumentation::CheckOptions(int argc, const char* const* argv, @@ -364,91 +361,59 @@ void cmDocumentation::SetName(const std::string& name) } void cmDocumentation::SetSection(const char* name, - cmDocumentationSection* section) + cmDocumentationSection section) { - if (this->AllSections.find(name) != this->AllSections.end()) { - delete this->AllSections[name]; - } - this->AllSections[name] = section; + this->SectionAtName(name) = std::move(section); } void cmDocumentation::SetSection(const char* name, std::vector<cmDocumentationEntry>& docs) { - cmDocumentationSection* sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - sec->Append(docs); - this->SetSection(name, sec); + cmDocumentationSection sec{ name }; + sec.Append(docs); + this->SetSection(name, std::move(sec)); } void cmDocumentation::SetSection(const char* name, const char* docs[][2]) { - cmDocumentationSection* sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - sec->Append(docs); - this->SetSection(name, sec); + cmDocumentationSection sec{ name }; + sec.Append(docs); + this->SetSection(name, std::move(sec)); } void cmDocumentation::SetSections( - std::map<std::string, cmDocumentationSection*>& sections) + std::map<std::string, cmDocumentationSection> sections) { - for (auto const& s : sections) { - this->SetSection(s.first.c_str(), s.second); + for (auto& s : sections) { + this->SetSection(s.first.c_str(), std::move(s.second)); } } +cmDocumentationSection& cmDocumentation::SectionAtName(const char* name) +{ + return this->AllSections.emplace(name, cmDocumentationSection{ name }) + .first->second; +} void cmDocumentation::PrependSection(const char* name, const char* docs[][2]) { - cmDocumentationSection* sec = nullptr; - if (this->AllSections.find(name) == this->AllSections.end()) { - sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - this->SetSection(name, sec); - } else { - sec = this->AllSections[name]; - } - sec->Prepend(docs); + this->SectionAtName(name).Prepend(docs); } void cmDocumentation::PrependSection(const char* name, std::vector<cmDocumentationEntry>& docs) { - cmDocumentationSection* sec = nullptr; - if (this->AllSections.find(name) == this->AllSections.end()) { - sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - this->SetSection(name, sec); - } else { - sec = this->AllSections[name]; - } - sec->Prepend(docs); + this->SectionAtName(name).Prepend(docs); } void cmDocumentation::AppendSection(const char* name, const char* docs[][2]) { - cmDocumentationSection* sec = nullptr; - if (this->AllSections.find(name) == this->AllSections.end()) { - sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - this->SetSection(name, sec); - } else { - sec = this->AllSections[name]; - } - sec->Append(docs); + this->SectionAtName(name).Append(docs); } void cmDocumentation::AppendSection(const char* name, std::vector<cmDocumentationEntry>& docs) { - cmDocumentationSection* sec = nullptr; - if (this->AllSections.find(name) == this->AllSections.end()) { - sec = - new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); - this->SetSection(name, sec); - } else { - sec = this->AllSections[name]; - } - sec->Append(docs); + this->SectionAtName(name).Append(docs); } void cmDocumentation::AppendSection(const char* name, @@ -631,11 +596,10 @@ bool cmDocumentation::PrintHelpListPolicies(std::ostream& os) bool cmDocumentation::PrintHelpListGenerators(std::ostream& os) { - std::map<std::string, cmDocumentationSection*>::iterator si; - si = this->AllSections.find("Generators"); + const auto si = this->AllSections.find("Generators"); if (si != this->AllSections.end()) { this->Formatter.SetIndent(" "); - this->Formatter.PrintSection(os, *si->second); + this->Formatter.PrintSection(os, si->second); } return true; } @@ -661,29 +625,27 @@ bool cmDocumentation::PrintHelpListVariables(std::ostream& os) bool cmDocumentation::PrintUsage(std::ostream& os) { - std::map<std::string, cmDocumentationSection*>::iterator si; - si = this->AllSections.find("Usage"); + const auto si = this->AllSections.find("Usage"); if (si != this->AllSections.end()) { - this->Formatter.PrintSection(os, *si->second); + this->Formatter.PrintSection(os, si->second); } return true; } bool cmDocumentation::PrintHelp(std::ostream& os) { - std::map<std::string, cmDocumentationSection*>::iterator si; - si = this->AllSections.find("Usage"); + auto si = this->AllSections.find("Usage"); if (si != this->AllSections.end()) { - this->Formatter.PrintSection(os, *si->second); + this->Formatter.PrintSection(os, si->second); } si = this->AllSections.find("Options"); if (si != this->AllSections.end()) { - this->Formatter.PrintSection(os, *si->second); + this->Formatter.PrintSection(os, si->second); } if (this->ShowGenerators) { si = this->AllSections.find("Generators"); if (si != this->AllSections.end()) { - this->Formatter.PrintSection(os, *si->second); + this->Formatter.PrintSection(os, si->second); } } return true; diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index c80bed1cd..cf74b800d 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -6,13 +6,13 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmDocumentationFormatter.h" +#include "cmDocumentationSection.h" #include <iosfwd> #include <map> #include <string> #include <vector> -class cmDocumentationSection; struct cmDocumentationEntry; /** Class to generate documentation. */ @@ -21,8 +21,6 @@ class cmDocumentation : public cmDocumentationEnums public: cmDocumentation(); - ~cmDocumentation(); - /** * Check command line arguments for documentation options. Returns * true if documentation options are found, and false otherwise. @@ -52,11 +50,11 @@ public: /** Set a section of the documentation. Typical sections include Name, Usage, Description, Options */ - void SetSection(const char* sectionName, cmDocumentationSection* section); + void SetSection(const char* sectionName, cmDocumentationSection section); void SetSection(const char* sectionName, std::vector<cmDocumentationEntry>& docs); void SetSection(const char* sectionName, const char* docs[][2]); - void SetSections(std::map<std::string, cmDocumentationSection*>& sections); + void SetSections(std::map<std::string, cmDocumentationSection> sections); /** Add the documentation to the beginning/end of the section */ void PrependSection(const char* sectionName, const char* docs[][2]); @@ -110,17 +108,14 @@ private: bool ShowGenerators; std::string NameString; - std::map<std::string, cmDocumentationSection*> AllSections; + std::map<std::string, cmDocumentationSection> AllSections; + cmDocumentationSection& SectionAtName(const char* name); std::string CurrentArgument; struct RequestedHelpItem { - RequestedHelpItem() - : HelpType(None) - { - } - cmDocumentationEnums::Type HelpType; + cmDocumentationEnums::Type HelpType = None; std::string Filename; std::string Argument; }; diff --git a/Source/cmDocumentationEntry.h b/Source/cmDocumentationEntry.h index ea43b88c3..afbca5e4b 100644 --- a/Source/cmDocumentationEntry.h +++ b/Source/cmDocumentationEntry.h @@ -12,7 +12,8 @@ struct cmDocumentationEntry { std::string Name; std::string Brief; - cmDocumentationEntry() {} + char CustomNamePrefix = ' '; + cmDocumentationEntry() = default; cmDocumentationEntry(const char* doc[2]) { if (doc[0]) { diff --git a/Source/cmDocumentationFormatter.cxx b/Source/cmDocumentationFormatter.cxx index 2267ef94b..3e7f9897e 100644 --- a/Source/cmDocumentationFormatter.cxx +++ b/Source/cmDocumentationFormatter.cxx @@ -5,20 +5,15 @@ #include "cmDocumentationEntry.h" #include "cmDocumentationSection.h" +#include <iomanip> #include <ostream> #include <string.h> #include <string> #include <vector> -cmDocumentationFormatter::cmDocumentationFormatter() - : TextWidth(77) - , TextIndent("") -{ -} +cmDocumentationFormatter::cmDocumentationFormatter() = default; -cmDocumentationFormatter::~cmDocumentationFormatter() -{ -} +cmDocumentationFormatter::~cmDocumentationFormatter() = default; void cmDocumentationFormatter::PrintFormatted(std::ostream& os, const char* text) @@ -170,7 +165,7 @@ void cmDocumentationFormatter::PrintSection( const std::vector<cmDocumentationEntry>& entries = section.GetEntries(); for (cmDocumentationEntry const& entry : entries) { if (!entry.Name.empty()) { - os << " " << entry.Name; + os << std::setw(2) << std::left << entry.CustomNamePrefix << entry.Name; this->TextIndent = " "; int align = static_cast<int>(strlen(this->TextIndent)) - 4; for (int i = static_cast<int>(entry.Name.size()); i < align; ++i) { diff --git a/Source/cmDocumentationFormatter.h b/Source/cmDocumentationFormatter.h index 1f04250c9..17b63dacc 100644 --- a/Source/cmDocumentationFormatter.h +++ b/Source/cmDocumentationFormatter.h @@ -59,8 +59,8 @@ public: void SetIndent(const char* indent); private: - int TextWidth; - const char* TextIndent; + int TextWidth = 77; + const char* TextIndent = ""; }; #endif diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h index d9e8187f8..7031b525d 100644 --- a/Source/cmDocumentationSection.h +++ b/Source/cmDocumentationSection.h @@ -19,7 +19,7 @@ class cmDocumentationSection { public: /** Create a cmSection, with a special name for man-output mode. */ - cmDocumentationSection(const char* name, const char*) + explicit cmDocumentationSection(const char* name) : Name(name) { } diff --git a/Source/cmDynamicLoader.cxx b/Source/cmDynamicLoader.cxx index 7da6ff54b..0549cf916 100644 --- a/Source/cmDynamicLoader.cxx +++ b/Source/cmDynamicLoader.cxx @@ -24,9 +24,7 @@ private: cmDynamicLoaderCache* cmDynamicLoaderCache::Instance = nullptr; -cmDynamicLoaderCache::~cmDynamicLoaderCache() -{ -} +cmDynamicLoaderCache::~cmDynamicLoaderCache() = default; void cmDynamicLoaderCache::CacheFile(const char* path, cmsys::DynamicLoader::LibraryHandle p) diff --git a/Source/cmDynamicLoader.h b/Source/cmDynamicLoader.h index 61d3b468b..4b89388e2 100644 --- a/Source/cmDynamicLoader.h +++ b/Source/cmDynamicLoader.h @@ -14,8 +14,6 @@ class cmDynamicLoader { - CM_DISABLE_COPY(cmDynamicLoader) - public: // Description: // Load a dynamic library into the current process. @@ -28,8 +26,8 @@ public: static void FlushCache(); protected: - cmDynamicLoader() {} - ~cmDynamicLoader() {} + cmDynamicLoader() = default; + ~cmDynamicLoader() = default; }; #endif diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 0ccd68a97..27f91317f 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -684,7 +684,7 @@ cmELF::cmELF(const char* fname) std::unique_ptr<cmsys::ifstream> fin(new cmsys::ifstream(fname)); // Quit now if the file could not be opened. - if (!fin.get() || !*fin) { + if (!fin || !*fin) { this->ErrorMessage = "Error opening input file."; return; } diff --git a/Source/cmELF.h b/Source/cmELF.h index 9172f3803..c8a91e4ea 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -32,7 +32,7 @@ public: std::string const& GetErrorMessage() const { return this->ErrorMessage; } /** Boolean conversion. True if the ELF file is valid. */ - operator bool() const { return this->Valid(); } + explicit operator bool() const { return this->Valid(); } /** Enumeration of ELF file types. */ enum FileType diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index ea4cd4071..75a7786a4 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -217,11 +217,11 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, int p; cmProcessOutput processOutput(encoding); std::string strdata; - while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr), p)) { + while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) { if (p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR) { if (verbose) { processOutput.DecodeText(data, length, strdata); - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } output.append(data, length); } @@ -230,7 +230,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, if (verbose) { processOutput.DecodeText(std::string(), strdata); if (!strdata.empty()) { - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } } @@ -270,7 +270,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, } msg += "\n"; if (verbose) { - cmSystemTools::Stdout(msg.c_str()); + cmSystemTools::Stdout(msg); } output += msg; #else diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 679a64814..8c67cdb4e 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -54,7 +54,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, if (args[i] == "COMMAND") { doing_command = true; command_index = cmds.size(); - cmds.push_back(std::vector<const char*>()); + cmds.emplace_back(); } else if (args[i] == "OUTPUT_VARIABLE") { doing_command = false; if (++i < args.size()) { @@ -244,19 +244,19 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, int p; cmProcessOutput processOutput(encoding); std::string strdata; - while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr), p)) { + while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) { // Put the output in the right place. if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) { if (output_variable.empty()) { processOutput.DecodeText(data, length, strdata, 1); - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } else { cmExecuteProcessCommandAppend(tempOutput, data, length); } } else if (p == cmsysProcess_Pipe_STDERR && !error_quiet) { if (error_variable.empty()) { processOutput.DecodeText(data, length, strdata, 2); - cmSystemTools::Stderr(strdata.c_str(), strdata.size()); + cmSystemTools::Stderr(strdata); } else { cmExecuteProcessCommandAppend(tempError, data, length); } @@ -265,13 +265,13 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, if (!output_quiet && output_variable.empty()) { processOutput.DecodeText(std::string(), strdata, 1); if (!strdata.empty()) { - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } } if (!error_quiet && error_variable.empty()) { processOutput.DecodeText(std::string(), strdata, 2); if (!strdata.empty()) { - cmSystemTools::Stderr(strdata.c_str(), strdata.size()); + cmSystemTools::Stderr(strdata); } } @@ -327,15 +327,15 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, cmsysProcess_GetExitValueByIndex(cp, static_cast<int>(i)); char buf[16]; sprintf(buf, "%d", exitCode); - res.push_back(buf); + res.emplace_back(buf); } break; case kwsysProcess_StateByIndex_Exception: - res.push_back(cmsysProcess_GetExceptionStringByIndex( + res.emplace_back(cmsysProcess_GetExceptionStringByIndex( cp, static_cast<int>(i))); break; case kwsysProcess_StateByIndex_Error: default: - res.push_back("Error getting the child return code"); + res.emplace_back("Error getting the child return code"); break; } } diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h index ac5fe1d72..56199dd93 100644 --- a/Source/cmExecutionStatus.h +++ b/Source/cmExecutionStatus.h @@ -11,14 +11,6 @@ class cmExecutionStatus { public: - cmExecutionStatus() - : ReturnInvoked(false) - , BreakInvoked(false) - , ContinueInvoked(false) - , NestedError(false) - { - } - void Clear() { this->ReturnInvoked = false; @@ -40,10 +32,10 @@ public: bool GetNestedError() const { return this->NestedError; } private: - bool ReturnInvoked; - bool BreakInvoked; - bool ContinueInvoked; - bool NestedError; + bool ReturnInvoked = false; + bool BreakInvoked = false; + bool ContinueInvoked = false; + bool NestedError = false; }; #endif diff --git a/Source/cmExpandedCommandArgument.cxx b/Source/cmExpandedCommandArgument.cxx index 1c0a72175..43f648bc3 100644 --- a/Source/cmExpandedCommandArgument.cxx +++ b/Source/cmExpandedCommandArgument.cxx @@ -2,14 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExpandedCommandArgument.h" -cmExpandedCommandArgument::cmExpandedCommandArgument() - : Quoted(false) -{ -} +#include <utility> + +cmExpandedCommandArgument::cmExpandedCommandArgument() = default; -cmExpandedCommandArgument::cmExpandedCommandArgument(std::string const& value, +cmExpandedCommandArgument::cmExpandedCommandArgument(std::string value, bool quoted) - : Value(value) + : Value(std::move(value)) , Quoted(quoted) { } diff --git a/Source/cmExpandedCommandArgument.h b/Source/cmExpandedCommandArgument.h index 302e8dbd6..69d35debe 100644 --- a/Source/cmExpandedCommandArgument.h +++ b/Source/cmExpandedCommandArgument.h @@ -18,7 +18,7 @@ class cmExpandedCommandArgument { public: cmExpandedCommandArgument(); - cmExpandedCommandArgument(std::string const& value, bool quoted); + cmExpandedCommandArgument(std::string value, bool quoted); std::string const& GetValue() const; @@ -33,7 +33,7 @@ public: private: std::string Value; - bool Quoted; + bool Quoted = false; }; #endif diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index d12ad7fd1..ced27c91c 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -11,11 +11,11 @@ #include "cmGeneratorTarget.h" #include "cmLinkItem.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" cmExportBuildAndroidMKGenerator::cmExportBuildAndroidMKGenerator() { @@ -92,7 +92,7 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( } w << " set to OLD for target " << target->Target->GetName() << ". " << "The export will only work with CMP0022 set to NEW."; - target->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + target->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } if (!properties.empty()) { os << "LOCAL_CPP_FEATURES := rtti exceptions\n"; diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 024e64116..012355b41 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -9,6 +9,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -55,7 +56,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) std::ostringstream e; e << "given target \"" << te->GetName() << "\" more than once."; this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, e.str(), + MessageType::FATAL_ERROR, e.str(), this->LG->GetMakefile()->GetBacktrace()); return false; } @@ -110,7 +111,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) std::string errorMessage; if (!this->PopulateExportProperties(gte, properties, errorMessage)) { this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, errorMessage, + MessageType::FATAL_ERROR, errorMessage, this->LG->GetMakefile()->GetBacktrace()); return false; } @@ -328,7 +329,8 @@ void cmExportBuildFileGenerator::ComplainAboutMissingTarget( << "consider using the APPEND option with multiple separate calls."; this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, e.str(), this->LG->GetMakefile()->GetBacktrace()); + MessageType::FATAL_ERROR, e.str(), + this->LG->GetMakefile()->GetBacktrace()); } std::string cmExportBuildFileGenerator::InstallNameDir( diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index f965a2993..722831a7f 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -12,10 +12,10 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -25,9 +25,7 @@ class cmExecutionStatus; #endif cmExportCommand::cmExportCommand() - : cmCommand() - , ArgumentGroup() - , Targets(&Helper, "TARGETS") + : Targets(&Helper, "TARGETS") , Append(&Helper, "APPEND", &ArgumentGroup) , ExportSetName(&Helper, "EXPORT", &ArgumentGroup) , Namespace(&Helper, "NAMESPACE", &ArgumentGroup) @@ -281,7 +279,7 @@ void cmExportCommand::ReportRegistryError(std::string const& msg, e << "Windows reported:\n" << " " << cmsys::Encoding::ToNarrow(winmsg); } - this->Makefile->IssueMessage(cmake::WARNING, e.str()); + this->Makefile->IssueMessage(MessageType::WARNING, e.str()); } void cmExportCommand::StorePackageRegistryWin(std::string const& package, @@ -349,7 +347,7 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package, << " " << fname << "\n" << cmSystemTools::GetLastSystemError() << "\n"; /* clang-format on */ - this->Makefile->IssueMessage(cmake::WARNING, e.str()); + this->Makefile->IssueMessage(MessageType::WARNING, e.str()); } } } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index bddc3c4aa..c8f743acd 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -9,6 +9,7 @@ #include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmProperty.h" @@ -17,7 +18,6 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" -#include "cmake.h" #include "cmsys/FStream.hxx" #include <assert.h> @@ -79,11 +79,11 @@ bool cmExportFileGenerator::GenerateImportFile() ap->SetCopyIfDifferent(true); foutPtr = std::move(ap); } - if (!foutPtr.get() || !*foutPtr) { + if (!foutPtr || !*foutPtr) { std::string se = cmSystemTools::GetLastSystemError(); std::ostringstream e; e << "cannot write to file \"" << this->MainImportFile << "\": " << se; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return false; } std::ostream& os = *foutPtr; @@ -214,13 +214,13 @@ static bool checkInterfaceDirs(const std::string& prepro, if (genexPos == 0) { continue; } - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; std::ostringstream e; if (genexPos != std::string::npos) { if (prop == "INTERFACE_INCLUDE_DIRECTORIES") { switch (target->GetPolicyStatusCMP0041()) { case cmPolicies::WARN: - messageType = cmake::WARNING; + messageType = MessageType::WARNING; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0041) << "\n"; break; case cmPolicies::OLD: @@ -275,8 +275,8 @@ static bool checkInterfaceDirs(const std::string& prepro, << (inBinary ? "build" : "source") << " tree:\n \"" << (inBinary ? topBinaryDir : topSourceDir) << "\"" << std::endl; - target->GetLocalGenerator()->IssueMessage(cmake::AUTHOR_WARNING, - s.str()); + target->GetLocalGenerator()->IssueMessage( + MessageType::AUTHOR_WARNING, s.str()); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -390,7 +390,7 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( "depend on the configuration, policy values or the link interface " "are " "not supported. Consider using target_include_directories instead."; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -520,7 +520,7 @@ void getCompatibleInterfaceProperties(cmGeneratorTarget* target, e << "Exporting the target \"" << target->GetName() << "\" is not " "allowed since its linker language cannot be determined"; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -727,7 +727,8 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( this->ReplaceInstallPrefix(input); if (!errorString.empty()) { - target->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, errorString); + target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR, + errorString); } } @@ -780,7 +781,7 @@ void cmExportFileGenerator::SetImportLinkInterface( "but also has old-style LINK_INTERFACE_LIBRARIES properties " "populated, but it was exported without the " "EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties"; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 41c6538d1..747503e6d 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -42,7 +42,7 @@ class cmExportFileGenerator { public: cmExportFileGenerator(); - virtual ~cmExportFileGenerator() {} + virtual ~cmExportFileGenerator() = default; /** Set the full path to the export file to generate. */ void SetExportFile(const char* mainFile); diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index e44408773..f8bc0ab0b 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -4,6 +4,7 @@ #include "cmAlgorithms.h" #include "cmExportSet.h" +#include "cmExportSetMap.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -21,8 +22,6 @@ #include <sstream> #include <utility> -class cmExportSetMap; - cmExportInstallFileGenerator::cmExportInstallFileGenerator( cmInstallExportGenerator* iegen) : IEGen(iegen) @@ -55,7 +54,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) << "\" ...) " << "includes target \"" << te->Target->GetName() << "\" more than once in the export set."; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return false; } } @@ -113,7 +112,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) std::string errorMessage; if (!this->PopulateExportProperties(gt, properties, errorMessage)) { - cmSystemTools::Error(errorMessage.c_str()); + cmSystemTools::Error(errorMessage); return false; } @@ -295,7 +294,7 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig( std::string se = cmSystemTools::GetLastSystemError(); std::ostringstream e; e << "cannot write to file \"" << fileName << "\": " << se; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return false; } std::ostream& os = exportFileStream; @@ -397,8 +396,8 @@ void cmExportInstallFileGenerator::SetImportLocationProperty( prop += suffix; // Append the installed file name. - value += itgen->GetInstallFilename(target, config, - cmInstallTargetGenerator::NameImplib); + value += cmInstallTargetGenerator::GetInstallFilename( + target, config, cmInstallTargetGenerator::NameImplib); // Store the property. properties[prop] = value; @@ -426,12 +425,12 @@ void cmExportInstallFileGenerator::SetImportLocationProperty( // Append the installed file name. if (target->IsAppBundleOnApple()) { - value += itgen->GetInstallFilename(target, config); + value += cmInstallTargetGenerator::GetInstallFilename(target, config); value += ".app/Contents/MacOS/"; - value += itgen->GetInstallFilename(target, config); + value += cmInstallTargetGenerator::GetInstallFilename(target, config); } else { - value += itgen->GetInstallFilename(target, config, - cmInstallTargetGenerator::NameReal); + value += cmInstallTargetGenerator::GetInstallFilename( + target, config, cmInstallTargetGenerator::NameReal); } // Store the property. @@ -519,7 +518,7 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget( e << "that is not in this export set, but " << occurrences << " times in others."; } - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); } std::string cmExportInstallFileGenerator::InstallNameDir( diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h index 58ad617d4..0ef306f63 100644 --- a/Source/cmExportSet.h +++ b/Source/cmExportSet.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <string> +#include <utility> #include <vector> class cmInstallExportGenerator; @@ -17,8 +18,8 @@ class cmExportSet { public: /// Construct an empty export set named \a name - cmExportSet(const std::string& name) - : Name(name) + cmExportSet(std::string name) + : Name(std::move(name)) { } /// Destructor diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx index 8d3dad73e..80c78a38c 100644 --- a/Source/cmExprParserHelper.cxx +++ b/Source/cmExprParserHelper.cxx @@ -18,9 +18,7 @@ cmExprParserHelper::cmExprParserHelper() this->Result = 0; } -cmExprParserHelper::~cmExprParserHelper() -{ -} +cmExprParserHelper::~cmExprParserHelper() = default; int cmExprParserHelper::ParseString(const char* str, int verb) { diff --git a/Source/cmExternalMakefileProjectGenerator.cxx b/Source/cmExternalMakefileProjectGenerator.cxx index fecd8216e..ac548112a 100644 --- a/Source/cmExternalMakefileProjectGenerator.cxx +++ b/Source/cmExternalMakefileProjectGenerator.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExternalMakefileProjectGenerator.h" +#include <utility> + class cmMakefile; void cmExternalMakefileProjectGenerator::EnableLanguage( @@ -32,17 +34,14 @@ bool cmExternalMakefileProjectGenerator::Open( } cmExternalMakefileProjectGeneratorFactory:: - cmExternalMakefileProjectGeneratorFactory(const std::string& n, - const std::string& doc) - : Name(n) - , Documentation(doc) + cmExternalMakefileProjectGeneratorFactory(std::string n, std::string doc) + : Name(std::move(n)) + , Documentation(std::move(doc)) { } cmExternalMakefileProjectGeneratorFactory:: - ~cmExternalMakefileProjectGeneratorFactory() -{ -} + ~cmExternalMakefileProjectGeneratorFactory() = default; std::string cmExternalMakefileProjectGeneratorFactory::GetName() const { diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h index d48abca78..4438f2803 100644 --- a/Source/cmExternalMakefileProjectGenerator.h +++ b/Source/cmExternalMakefileProjectGenerator.h @@ -26,7 +26,7 @@ class cmMakefile; class cmExternalMakefileProjectGenerator { public: - virtual ~cmExternalMakefileProjectGenerator() {} + virtual ~cmExternalMakefileProjectGenerator() = default; virtual void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*, bool optional); @@ -70,8 +70,7 @@ protected: class cmExternalMakefileProjectGeneratorFactory { public: - cmExternalMakefileProjectGeneratorFactory(const std::string& n, - const std::string& doc); + cmExternalMakefileProjectGeneratorFactory(std::string n, std::string doc); virtual ~cmExternalMakefileProjectGeneratorFactory(); std::string GetName() const; diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 07a60de24..e408de384 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -32,10 +32,7 @@ Discussion: http://forums.codeblocks.org/index.php/topic,6789.0.html */ -cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator() - : cmExternalMakefileProjectGenerator() -{ -} +cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator() = default; cmExternalMakefileProjectGeneratorFactory* cmExtraCodeBlocksGenerator::GetFactory() @@ -365,7 +362,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // don't add source files from UTILITY target which have the // GENERATED property set: if (gt->GetType() == cmStateEnums::UTILITY && - s->GetPropertyAsBool("GENERATED")) { + s->GetIsGenerated()) { continue; } diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index 28106d19d..0773edcbd 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -21,9 +21,7 @@ #include <utility> cmExtraCodeLiteGenerator::cmExtraCodeLiteGenerator() - : cmExternalMakefileProjectGenerator() - , ConfigName("NoConfig") - , CpuCount(2) + : ConfigName("NoConfig") { } @@ -61,18 +59,17 @@ void cmExtraCodeLiteGenerator::Generate() // and extract the information for creating the worspace // root makefile for (auto const& it : projectMap) { - const cmMakefile* mf = it.second[0]->GetMakefile(); + cmLocalGenerator* lg = it.second[0]; + const cmMakefile* mf = lg->GetMakefile(); this->ConfigName = GetConfigurationName(mf); - if (it.second[0]->GetCurrentBinaryDirectory() == - it.second[0]->GetBinaryDirectory()) { - workspaceOutputDir = it.second[0]->GetCurrentBinaryDirectory(); - workspaceProjectName = it.second[0]->GetProjectName(); - workspaceSourcePath = it.second[0]->GetSourceDirectory(); + if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) { + workspaceOutputDir = lg->GetCurrentBinaryDirectory(); + workspaceProjectName = lg->GetProjectName(); + workspaceSourcePath = lg->GetSourceDirectory(); workspaceFileName = workspaceOutputDir + "/"; workspaceFileName += workspaceProjectName + ".workspace"; - this->WorkspacePath = it.second[0]->GetCurrentBinaryDirectory(); - ; + this->WorkspacePath = lg->GetCurrentBinaryDirectory(); break; } } @@ -226,7 +223,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles( for (cmSourceFile* s : sources) { // check whether it is a source or a include file // then put it accordingly into one of the two containers - switch (cmSystemTools::GetFileFormat(s->GetExtension().c_str())) { + switch (cmSystemTools::GetFileFormat(s->GetExtension())) { case cmSystemTools::C_FILE_FORMAT: case cmSystemTools::CXX_FILE_FORMAT: case cmSystemTools::CUDA_FILE_FORMAT: diff --git a/Source/cmExtraCodeLiteGenerator.h b/Source/cmExtraCodeLiteGenerator.h index 029054fdd..dea7ebc11 100644 --- a/Source/cmExtraCodeLiteGenerator.h +++ b/Source/cmExtraCodeLiteGenerator.h @@ -23,7 +23,7 @@ class cmExtraCodeLiteGenerator : public cmExternalMakefileProjectGenerator protected: std::string ConfigName; std::string WorkspacePath; - unsigned int CpuCount; + unsigned int CpuCount = 2; protected: std::string GetCodeLiteCompilerName(const cmMakefile* mf) const; diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 34f58adff..e05f74ba5 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -5,6 +5,7 @@ #include "cmsys/RegularExpression.hxx" #include <algorithm> #include <assert.h> +#include <map> #include <sstream> #include <stdio.h> #include <utility> @@ -15,6 +16,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" #include "cmState.h" @@ -41,7 +43,6 @@ void AppendDictionary(cmXMLWriter& xml, const char* key, T const& value) } cmExtraEclipseCDT4Generator::cmExtraEclipseCDT4Generator() - : cmExternalMakefileProjectGenerator() { this->SupportsVirtualFolders = true; this->GenerateLinkedResources = true; @@ -134,7 +135,7 @@ void cmExtraEclipseCDT4Generator::Generate() if (!this->GenerateSourceProject && (mf->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT"))) { mf->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT is set to TRUE, " "but this variable is not supported anymore since CMake 2.8.7.\n" "Enable CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT instead."); @@ -142,7 +143,7 @@ void cmExtraEclipseCDT4Generator::Generate() if (cmSystemTools::IsSubDirectory(this->HomeOutputDirectory, this->HomeDirectory)) { - mf->IssueMessage(cmake::WARNING, + mf->IssueMessage(MessageType::WARNING, "The build directory is a subdirectory " "of the source directory.\n" "This is not supported well by Eclipse. It is strongly " @@ -171,9 +172,9 @@ void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() // set up the project name: <project>-Source@<baseSourcePathName> cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; - std::string name = - this->GenerateProjectName(lg->GetProjectName(), "Source", - this->GetPathBasename(this->HomeDirectory)); + std::string name = cmExtraEclipseCDT4Generator::GenerateProjectName( + lg->GetProjectName(), "Source", + cmExtraEclipseCDT4Generator::GetPathBasename(this->HomeDirectory)); const std::string filename = this->HomeDirectory + "/.project"; cmGeneratedFileStream fout(filename); @@ -278,10 +279,11 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() xml.StartElement("projectDescription"); xml.Element("name", - this->GenerateProjectName( + cmExtraEclipseCDT4Generator::GenerateProjectName( lg->GetProjectName(), mf->GetSafeDefinition("CMAKE_BUILD_TYPE"), - this->GetPathBasename(this->HomeOutputDirectory))); + cmExtraEclipseCDT4Generator::GetPathBasename( + this->HomeOutputDirectory))); xml.Element("comment", ""); xml.Element("projects", ""); @@ -302,16 +304,17 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() // set the make command AppendDictionary(xml, "org.eclipse.cdt.make.core.enabledIncrementalBuild", "true"); - AppendDictionary( - xml, "org.eclipse.cdt.make.core.build.command", - this->GetEclipsePath(mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"))); + AppendDictionary(xml, "org.eclipse.cdt.make.core.build.command", + cmExtraEclipseCDT4Generator::GetEclipsePath( + mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"))); AppendDictionary(xml, "org.eclipse.cdt.make.core.contents", "org.eclipse.cdt.make.core.activeConfigSettings"); AppendDictionary(xml, "org.eclipse.cdt.make.core.build.target.inc", "all"); AppendDictionary(xml, "org.eclipse.cdt.make.core.build.arguments", mf->GetSafeDefinition("CMAKE_ECLIPSE_MAKE_ARGUMENTS")); - AppendDictionary(xml, "org.eclipse.cdt.make.core.buildLocation", - this->GetEclipsePath(this->HomeOutputDirectory)); + AppendDictionary( + xml, "org.eclipse.cdt.make.core.buildLocation", + cmExtraEclipseCDT4Generator::GetEclipsePath(this->HomeOutputDirectory)); AppendDictionary(xml, "org.eclipse.cdt.make.core.useDefaultBuildCmd", "false"); @@ -341,8 +344,9 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() "clean"); AppendDictionary(xml, "org.eclipse.cdt.make.core.fullBuildTarget", "all"); AppendDictionary(xml, "org.eclipse.cdt.make.core.buildArguments", ""); - AppendDictionary(xml, "org.eclipse.cdt.make.core.build.location", - this->GetEclipsePath(this->HomeOutputDirectory)); + AppendDictionary( + xml, "org.eclipse.cdt.make.core.build.location", + cmExtraEclipseCDT4Generator::GetEclipsePath(this->HomeOutputDirectory)); AppendDictionary(xml, "org.eclipse.cdt.make.core.autoBuildTarget", "all"); // set error parsers @@ -379,7 +383,6 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() xml.StartElement("natures"); xml.Element("nature", "org.eclipse.cdt.make.core.makeNature"); xml.Element("nature", "org.eclipse.cdt.make.core.ScannerConfigNature"); - ; for (std::string const& n : this->Natures) { xml.Element("nature", n); @@ -407,13 +410,15 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() std::string sourceLinkedResourceName = "[Source directory]"; std::string linkSourceDirectory = - this->GetEclipsePath(lg->GetCurrentSourceDirectory()); + cmExtraEclipseCDT4Generator::GetEclipsePath( + lg->GetCurrentSourceDirectory()); // .project dir can't be subdir of a linked resource dir if (!cmSystemTools::IsSubDirectory(this->HomeOutputDirectory, linkSourceDirectory)) { - this->AppendLinkedResource(xml, sourceLinkedResourceName, - this->GetEclipsePath(linkSourceDirectory), - LinkToFolder); + cmExtraEclipseCDT4Generator::AppendLinkedResource( + xml, sourceLinkedResourceName, + cmExtraEclipseCDT4Generator::GetEclipsePath(linkSourceDirectory), + LinkToFolder); this->SrcLinkedResources.push_back(std::move(sourceLinkedResourceName)); } } @@ -439,8 +444,8 @@ void cmExtraEclipseCDT4Generator::WriteGroups( std::replace(linkName3.begin(), linkName3.end(), '\\', '/'); - this->AppendLinkedResource(xml, linkName3, "virtual:/virtual", - VirtualFolder); + cmExtraEclipseCDT4Generator::AppendLinkedResource( + xml, linkName3, "virtual:/virtual", VirtualFolder); std::vector<cmSourceGroup> const& children = sg.GetGroupChildren(); if (!children.empty()) { this->WriteGroups(children, linkName, xml); @@ -453,8 +458,9 @@ void cmExtraEclipseCDT4Generator::WriteGroups( std::string linkName4 = linkName3; linkName4 += "/"; linkName4 += cmSystemTools::GetFilenameName(fullPath); - this->AppendLinkedResource(xml, linkName4, - this->GetEclipsePath(fullPath), LinkToFile); + cmExtraEclipseCDT4Generator::AppendLinkedResource( + xml, linkName4, + cmExtraEclipseCDT4Generator::GetEclipsePath(fullPath), LinkToFile); } } } @@ -463,7 +469,8 @@ void cmExtraEclipseCDT4Generator::WriteGroups( void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml) { std::string linkName = "[Targets]"; - this->AppendLinkedResource(xml, linkName, "virtual:/virtual", VirtualFolder); + cmExtraEclipseCDT4Generator::AppendLinkedResource( + xml, linkName, "virtual:/virtual", VirtualFolder); for (cmLocalGenerator* lg : this->GlobalGenerator->GetLocalGenerators()) { cmMakefile* makefile = lg->GetMakefile(); @@ -483,8 +490,8 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml) : "[lib] "); linkName2 += prefix; linkName2 += target->GetName(); - this->AppendLinkedResource(xml, linkName2, "virtual:/virtual", - VirtualFolder); + cmExtraEclipseCDT4Generator::AppendLinkedResource( + xml, linkName2, "virtual:/virtual", VirtualFolder); if (!this->GenerateLinkedResources) { break; // skip generating the linked resources to the source files } @@ -522,21 +529,23 @@ void cmExtraEclipseCDT4Generator::CreateLinksToSubprojects( // for each sub project create a linked resource to the source dir // - only if it is an out-of-source build - this->AppendLinkedResource(xml, "[Subprojects]", "virtual:/virtual", - VirtualFolder); + cmExtraEclipseCDT4Generator::AppendLinkedResource( + xml, "[Subprojects]", "virtual:/virtual", VirtualFolder); for (auto const& it : this->GlobalGenerator->GetProjectMap()) { std::string linkSourceDirectory = - this->GetEclipsePath(it.second[0]->GetCurrentSourceDirectory()); + cmExtraEclipseCDT4Generator::GetEclipsePath( + it.second[0]->GetCurrentSourceDirectory()); // a linked resource must not point to a parent directory of .project or // .project itself if ((baseDir != linkSourceDirectory) && !cmSystemTools::IsSubDirectory(baseDir, linkSourceDirectory)) { std::string linkName = "[Subprojects]/"; linkName += it.first; - this->AppendLinkedResource(xml, linkName, - this->GetEclipsePath(linkSourceDirectory), - LinkToFolder); + cmExtraEclipseCDT4Generator::AppendLinkedResource( + xml, linkName, + cmExtraEclipseCDT4Generator::GetEclipsePath(linkSourceDirectory), + LinkToFolder); // Don't add it to the srcLinkedResources, because listing multiple // directories confuses the Eclipse indexer (#13596). } @@ -705,7 +714,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const xml.Attribute("path", p); xml.EndElement(); - // exlude source directory from output search path + // exclude source directory from output search path // - only if not named the same as an output directory if (!cmSystemTools::FileIsDirectory( std::string(this->HomeOutputDirectory + "/" + p))) { @@ -836,6 +845,9 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const const std::vector<cmGeneratorTarget*>& targets = lgen->GetGeneratorTargets(); for (cmGeneratorTarget* target : targets) { + if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + continue; + } std::vector<std::string> includeDirs; std::string config = mf->GetSafeDefinition("CMAKE_BUILD_TYPE"); lgen->GetIncludeDirectories(includeDirs, target, "C", config); @@ -890,7 +902,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) { const std::vector<cmGeneratorTarget*>& targets = lgen->GetGeneratorTargets(); - std::string subdir = lgen->ConvertToRelativePath( + std::string subdir = lgen->MaybeConvertToRelativePath( this->HomeOutputDirectory, lgen->GetCurrentBinaryDirectory()); if (subdir == ".") { subdir.clear(); @@ -903,7 +915,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const // Only add the global targets from CMAKE_BINARY_DIR, // not from the subdirs if (subdir.empty()) { - this->AppendTarget(xml, targetName, make, makeArgs, subdir, ": "); + cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make, + makeArgs, subdir, ": "); } } break; case cmStateEnums::UTILITY: @@ -918,7 +931,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const break; } - this->AppendTarget(xml, targetName, make, makeArgs, subdir, ": "); + cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make, + makeArgs, subdir, ": "); break; case cmStateEnums::EXECUTABLE: case cmStateEnums::STATIC_LIBRARY: @@ -928,10 +942,12 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const const char* prefix = (target->GetType() == cmStateEnums::EXECUTABLE ? "[exe] " : "[lib] "); - this->AppendTarget(xml, targetName, make, makeArgs, subdir, prefix); + cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make, + makeArgs, subdir, prefix); std::string fastTarget = targetName; fastTarget += "/fast"; - this->AppendTarget(xml, fastTarget, make, makeArgs, subdir, prefix); + cmExtraEclipseCDT4Generator::AppendTarget(xml, fastTarget, make, + makeArgs, subdir, prefix); // Add Build and Clean targets in the virtual folder of targets: if (this->SupportsVirtualFolders) { @@ -942,8 +958,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const buildArgs += lgen->GetBinaryDirectory(); buildArgs += "\" "; buildArgs += makeArgs; - this->AppendTarget(xml, "Build", make, buildArgs, virtDir, "", - targetName.c_str()); + cmExtraEclipseCDT4Generator::AppendTarget( + xml, "Build", make, buildArgs, virtDir, "", targetName.c_str()); std::string cleanArgs = "-E chdir \""; cleanArgs += lgen->GetCurrentBinaryDirectory(); @@ -953,10 +969,13 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const cmGeneratorTarget* gt = target; cleanArgs += lgen->GetTargetDirectory(gt); cleanArgs += "/cmake_clean.cmake\""; - this->AppendTarget(xml, "Clean", cmSystemTools::GetCMakeCommand(), - cleanArgs, virtDir, "", ""); + cmExtraEclipseCDT4Generator::AppendTarget( + xml, "Clean", cmSystemTools::GetCMakeCommand(), cleanArgs, + virtDir, "", ""); } } break; + case cmStateEnums::INTERFACE_LIBRARY: + break; default: break; } @@ -964,10 +983,12 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const // insert the all and clean targets in every subdir if (!allTarget.empty()) { - this->AppendTarget(xml, allTarget, make, makeArgs, subdir, ": "); + cmExtraEclipseCDT4Generator::AppendTarget(xml, allTarget, make, makeArgs, + subdir, ": "); } if (!cleanTarget.empty()) { - this->AppendTarget(xml, cleanTarget, make, makeArgs, subdir, ": "); + cmExtraEclipseCDT4Generator::AppendTarget(xml, cleanTarget, make, + makeArgs, subdir, ": "); } // insert rules for compiling, preprocessing and assembling individual @@ -976,19 +997,20 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const lg->GetIndividualFileTargets(objectFileTargets); for (std::string const& f : objectFileTargets) { const char* prefix = "[obj] "; - if (f[f.length() - 1] == 's') { + if (f.back() == 's') { prefix = "[to asm] "; - } else if (f[f.length() - 1] == 'i') { + } else if (f.back() == 'i') { prefix = "[pre] "; } - this->AppendTarget(xml, f, make, makeArgs, subdir, prefix); + cmExtraEclipseCDT4Generator::AppendTarget(xml, f, make, makeArgs, subdir, + prefix); } } xml.EndElement(); // buildTargets xml.EndElement(); // storageModule - this->AppendStorageScanners(xml, *mf); + cmExtraEclipseCDT4Generator::AppendStorageScanners(xml, *mf); xml.EndElement(); // cconfiguration xml.EndElement(); // storageModule @@ -1035,8 +1057,7 @@ std::string cmExtraEclipseCDT4Generator::GetPathBasename( { std::string outputBasename = path; while (!outputBasename.empty() && - (outputBasename[outputBasename.size() - 1] == '/' || - outputBasename[outputBasename.size() - 1] == '\\')) { + (outputBasename.back() == '/' || outputBasename.back() == '\\')) { outputBasename.resize(outputBasename.size() - 1); } std::string::size_type loc = outputBasename.find_last_of("/\\"); diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index f5c4c93e4..23ba6b77f 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -16,10 +16,7 @@ #include <string.h> #include <vector> -cmExtraKateGenerator::cmExtraKateGenerator() - : cmExternalMakefileProjectGenerator() -{ -} +cmExtraKateGenerator::cmExtraKateGenerator() = default; cmExternalMakefileProjectGeneratorFactory* cmExtraKateGenerator::GetFactory() { @@ -259,7 +256,7 @@ std::string cmExtraKateGenerator::GenerateFilesString( const std::vector<cmSourceFile*>& sources = makefile->GetSourceFiles(); for (cmSourceFile* sf : sources) { - if (sf->GetPropertyAsBool("GENERATED")) { + if (sf->GetIsGenerated()) { continue; } @@ -294,8 +291,7 @@ std::string cmExtraKateGenerator::GetPathBasename( { std::string outputBasename = path; while (!outputBasename.empty() && - (outputBasename[outputBasename.size() - 1] == '/' || - outputBasename[outputBasename.size() - 1] == '\\')) { + (outputBasename.back() == '/' || outputBasename.back() == '\\')) { outputBasename.resize(outputBasename.size() - 1); } std::string::size_type loc = outputBasename.find_last_of("/\\"); diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index c4cca072b..739a177bb 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -14,6 +14,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -55,7 +56,6 @@ cmExtraSublimeTextGenerator::GetFactory() } cmExtraSublimeTextGenerator::cmExtraSublimeTextGenerator() - : cmExternalMakefileProjectGenerator() { this->ExcludeBuildFolder = false; } @@ -155,7 +155,7 @@ void cmExtraSublimeTextGenerator::CreateNewProjectFile( e << "Could not parse Env Vars specified in " "\"CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS\"" << ", corrupted string " << t; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); } } fout << "\n\t\t}"; @@ -384,13 +384,8 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines( cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, language); - // Add the export symbol definition for shared library objects. - if (const char* exportMacro = target->GetExportMacro()) { - lg->AppendDefines(defines, exportMacro); - } - // Add preprocessor definitions for this target and configuration. - lg->AddCompileDefinitions(defines, target, config, language); + lg->GetTargetDefines(target, config, language, defines); const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { lg->AppendDefines( diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index effb4460a..4b14d26d0 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -117,7 +117,7 @@ void cmFLTKWrapUICommand::FinalPass() msg += ". The problem was found while processing the source directory: "; msg += this->Makefile->GetCurrentSourceDirectory(); msg += ". This FLTK_WRAP_UI call will be ignored."; - cmSystemTools::Message(msg.c_str(), "Warning"); + cmSystemTools::Message(msg, "Warning"); return; } } diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx new file mode 100644 index 000000000..34b6b330d --- /dev/null +++ b/Source/cmFileAPI.cxx @@ -0,0 +1,800 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFileAPI.h" + +#include "cmAlgorithms.h" +#include "cmCryptoHash.h" +#include "cmFileAPICMakeFiles.h" +#include "cmFileAPICache.h" +#include "cmFileAPICodemodel.h" +#include "cmGlobalGenerator.h" +#include "cmSystemTools.h" +#include "cmTimestamp.h" +#include "cmake.h" +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" + +#include <algorithm> +#include <cassert> +#include <chrono> +#include <ctime> +#include <iomanip> +#include <sstream> +#include <utility> + +cmFileAPI::cmFileAPI(cmake* cm) + : CMakeInstance(cm) +{ + this->APIv1 = + this->CMakeInstance->GetHomeOutputDirectory() + "/.cmake/api/v1"; + + Json::CharReaderBuilder rbuilder; + rbuilder["collectComments"] = false; + rbuilder["failIfExtra"] = true; + rbuilder["rejectDupKeys"] = false; + rbuilder["strictRoot"] = true; + this->JsonReader = + std::unique_ptr<Json::CharReader>(rbuilder.newCharReader()); + + Json::StreamWriterBuilder wbuilder; + wbuilder["indentation"] = "\t"; + this->JsonWriter = + std::unique_ptr<Json::StreamWriter>(wbuilder.newStreamWriter()); +} + +void cmFileAPI::ReadQueries() +{ + std::string const query_dir = this->APIv1 + "/query"; + this->QueryExists = cmSystemTools::FileIsDirectory(query_dir); + if (!this->QueryExists) { + return; + } + + // Load queries at the top level. + std::vector<std::string> queries = cmFileAPI::LoadDir(query_dir); + + // Read the queries and save for later. + for (std::string& query : queries) { + if (cmHasLiteralPrefix(query, "client-")) { + this->ReadClient(query); + } else if (!cmFileAPI::ReadQuery(query, this->TopQuery.Known)) { + this->TopQuery.Unknown.push_back(std::move(query)); + } + } +} + +void cmFileAPI::WriteReplies() +{ + if (this->QueryExists) { + cmSystemTools::MakeDirectory(this->APIv1 + "/reply"); + this->WriteJsonFile(this->BuildReplyIndex(), "index", ComputeSuffixTime); + } + + this->RemoveOldReplyFiles(); +} + +std::vector<std::string> cmFileAPI::LoadDir(std::string const& dir) +{ + std::vector<std::string> files; + cmsys::Directory d; + d.Load(dir); + for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) { + std::string f = d.GetFile(i); + if (f != "." && f != "..") { + files.push_back(std::move(f)); + } + } + std::sort(files.begin(), files.end()); + return files; +} + +void cmFileAPI::RemoveOldReplyFiles() +{ + std::string const reply_dir = this->APIv1 + "/reply"; + std::vector<std::string> files = this->LoadDir(reply_dir); + for (std::string const& f : files) { + if (this->ReplyFiles.find(f) == this->ReplyFiles.end()) { + std::string file = reply_dir + "/" + f; + cmSystemTools::RemoveFile(file); + } + } +} + +bool cmFileAPI::ReadJsonFile(std::string const& file, Json::Value& value, + std::string& error) +{ + std::vector<char> content; + + cmsys::ifstream fin; + if (!cmSystemTools::FileIsDirectory(file)) { + fin.open(file.c_str(), std::ios::binary); + } + auto finEnd = fin.rdbuf()->pubseekoff(0, std::ios::end); + if (finEnd > 0) { + size_t finSize = finEnd; + try { + // Allocate a buffer to read the whole file. + content.resize(finSize); + + // Now read the file from the beginning. + fin.seekg(0, std::ios::beg); + fin.read(content.data(), finSize); + } catch (...) { + fin.setstate(std::ios::failbit); + } + } + fin.close(); + if (!fin) { + value = Json::Value(); + error = "failed to read from file"; + return false; + } + + // Parse our buffer as json. + if (!this->JsonReader->parse(content.data(), content.data() + content.size(), + &value, &error)) { + value = Json::Value(); + return false; + } + + return true; +} + +std::string cmFileAPI::WriteJsonFile( + Json::Value const& value, std::string const& prefix, + std::string (*computeSuffix)(std::string const&)) +{ + std::string fileName; + + // Write the json file with a temporary name. + std::string const& tmpFile = this->APIv1 + "/tmp.json"; + cmsys::ofstream ftmp(tmpFile.c_str()); + this->JsonWriter->write(value, &ftmp); + ftmp << "\n"; + ftmp.close(); + if (!ftmp) { + cmSystemTools::RemoveFile(tmpFile); + return fileName; + } + + // Compute the final name for the file. + fileName = prefix + "-" + computeSuffix(tmpFile) + ".json"; + + // Create the destination. + std::string file = this->APIv1 + "/reply"; + cmSystemTools::MakeDirectory(file); + file += "/"; + file += fileName; + + // If the final name already exists then assume it has proper content. + // Otherwise, atomically place the reply file at its final name + if (cmSystemTools::FileExists(file, true) || + !cmSystemTools::RenameFile(tmpFile, file)) { + cmSystemTools::RemoveFile(tmpFile); + } + + // Record this among files we have just written. + this->ReplyFiles.insert(fileName); + + return fileName; +} + +Json::Value cmFileAPI::MaybeJsonFile(Json::Value in, std::string const& prefix) +{ + Json::Value out; + if (in.isObject() || in.isArray()) { + out = Json::objectValue; + out["jsonFile"] = this->WriteJsonFile(in, prefix); + } else { + out = std::move(in); + } + return out; +} + +std::string cmFileAPI::ComputeSuffixHash(std::string const& file) +{ + cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256); + std::string hash = hasher.HashFile(file); + hash.resize(20, '0'); + return hash; +} + +std::string cmFileAPI::ComputeSuffixTime(std::string const&) +{ + std::chrono::milliseconds ms = + std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::system_clock::now().time_since_epoch()); + std::chrono::seconds s = + std::chrono::duration_cast<std::chrono::seconds>(ms); + + std::time_t ts = s.count(); + std::size_t tms = ms.count() % 1000; + + cmTimestamp cmts; + std::ostringstream ss; + ss << cmts.CreateTimestampFromTimeT(ts, "%Y-%m-%dT%H-%M-%S", true) << '-' + << std::setfill('0') << std::setw(4) << tms; + return ss.str(); +} + +bool cmFileAPI::ReadQuery(std::string const& query, + std::vector<Object>& objects) +{ + // Parse the "<kind>-" syntax. + std::string::size_type sep_pos = query.find('-'); + if (sep_pos == std::string::npos) { + return false; + } + std::string kindName = query.substr(0, sep_pos); + std::string verStr = query.substr(sep_pos + 1); + if (kindName == ObjectKindName(ObjectKind::CodeModel)) { + Object o; + o.Kind = ObjectKind::CodeModel; + if (verStr == "v2") { + o.Version = 2; + } else { + return false; + } + objects.push_back(o); + return true; + } + if (kindName == ObjectKindName(ObjectKind::Cache)) { + Object o; + o.Kind = ObjectKind::Cache; + if (verStr == "v2") { + o.Version = 2; + } else { + return false; + } + objects.push_back(o); + return true; + } + if (kindName == ObjectKindName(ObjectKind::CMakeFiles)) { + Object o; + o.Kind = ObjectKind::CMakeFiles; + if (verStr == "v1") { + o.Version = 1; + } else { + return false; + } + objects.push_back(o); + return true; + } + if (kindName == ObjectKindName(ObjectKind::InternalTest)) { + Object o; + o.Kind = ObjectKind::InternalTest; + if (verStr == "v1") { + o.Version = 1; + } else if (verStr == "v2") { + o.Version = 2; + } else { + return false; + } + objects.push_back(o); + return true; + } + return false; +} + +void cmFileAPI::ReadClient(std::string const& client) +{ + // Load queries for the client. + std::string clientDir = this->APIv1 + "/query/" + client; + std::vector<std::string> queries = this->LoadDir(clientDir); + + // Read the queries and save for later. + ClientQuery& clientQuery = this->ClientQueries[client]; + for (std::string& query : queries) { + if (query == "query.json") { + clientQuery.HaveQueryJson = true; + this->ReadClientQuery(client, clientQuery.QueryJson); + } else if (!this->ReadQuery(query, clientQuery.DirQuery.Known)) { + clientQuery.DirQuery.Unknown.push_back(std::move(query)); + } + } +} + +void cmFileAPI::ReadClientQuery(std::string const& client, ClientQueryJson& q) +{ + // Read the query.json file. + std::string queryFile = this->APIv1 + "/query/" + client + "/query.json"; + Json::Value query; + if (!this->ReadJsonFile(queryFile, query, q.Error)) { + return; + } + if (!query.isObject()) { + q.Error = "query root is not an object"; + return; + } + + Json::Value const& clientValue = query["client"]; + if (!clientValue.isNull()) { + q.ClientValue = clientValue; + } + q.RequestsValue = std::move(query["requests"]); + q.Requests = this->BuildClientRequests(q.RequestsValue); +} + +Json::Value cmFileAPI::BuildReplyIndex() +{ + Json::Value index(Json::objectValue); + + // Report information about this version of CMake. + index["cmake"] = this->BuildCMake(); + + // Reply to all queries that we loaded. + Json::Value& reply = index["reply"] = this->BuildReply(this->TopQuery); + for (auto const& client : this->ClientQueries) { + std::string const& clientName = client.first; + ClientQuery const& clientQuery = client.second; + reply[clientName] = this->BuildClientReply(clientQuery); + } + + // Move our index of generated objects into its field. + Json::Value& objects = index["objects"] = Json::arrayValue; + for (auto& entry : this->ReplyIndexObjects) { + objects.append(std::move(entry.second)); // NOLINT(*) + } + + return index; +} + +Json::Value cmFileAPI::BuildCMake() +{ + Json::Value cmake = Json::objectValue; + cmake["version"] = this->CMakeInstance->ReportVersionJson(); + Json::Value& cmake_paths = cmake["paths"] = Json::objectValue; + cmake_paths["cmake"] = cmSystemTools::GetCMakeCommand(); + cmake_paths["ctest"] = cmSystemTools::GetCTestCommand(); + cmake_paths["cpack"] = cmSystemTools::GetCPackCommand(); + cmake_paths["root"] = cmSystemTools::GetCMakeRoot(); + cmake["generator"] = this->CMakeInstance->GetGlobalGenerator()->GetJson(); + return cmake; +} + +Json::Value cmFileAPI::BuildReply(Query const& q) +{ + Json::Value reply = Json::objectValue; + for (Object const& o : q.Known) { + std::string const& name = ObjectName(o); + reply[name] = this->AddReplyIndexObject(o); + } + + for (std::string const& name : q.Unknown) { + reply[name] = cmFileAPI::BuildReplyError("unknown query file"); + } + return reply; +} + +Json::Value cmFileAPI::BuildReplyError(std::string const& error) +{ + Json::Value e = Json::objectValue; + e["error"] = error; + return e; +} + +Json::Value const& cmFileAPI::AddReplyIndexObject(Object const& o) +{ + Json::Value& indexEntry = this->ReplyIndexObjects[o]; + if (!indexEntry.isNull()) { + // The reply object has already been generated. + return indexEntry; + } + + // Generate this reply object. + Json::Value const& object = this->BuildObject(o); + assert(object.isObject()); + + // Populate this index entry. + indexEntry = Json::objectValue; + indexEntry["kind"] = object["kind"]; + indexEntry["version"] = object["version"]; + indexEntry["jsonFile"] = this->WriteJsonFile(object, ObjectName(o)); + return indexEntry; +} + +const char* cmFileAPI::ObjectKindName(ObjectKind kind) +{ + // Keep in sync with ObjectKind enum. + static const char* objectKindNames[] = { + "codemodel", // + "cache", // + "cmakeFiles", // + "__test" // + }; + return objectKindNames[size_t(kind)]; +} + +std::string cmFileAPI::ObjectName(Object const& o) +{ + std::string name = ObjectKindName(o.Kind); + name += "-v"; + name += std::to_string(o.Version); + return name; +} + +Json::Value cmFileAPI::BuildObject(Object const& object) +{ + Json::Value value; + + switch (object.Kind) { + case ObjectKind::CodeModel: + value = this->BuildCodeModel(object); + break; + case ObjectKind::Cache: + value = this->BuildCache(object); + break; + case ObjectKind::CMakeFiles: + value = this->BuildCMakeFiles(object); + break; + case ObjectKind::InternalTest: + value = this->BuildInternalTest(object); + break; + } + + return value; +} + +cmFileAPI::ClientRequests cmFileAPI::BuildClientRequests( + Json::Value const& requests) +{ + ClientRequests result; + if (requests.isNull()) { + result.Error = "'requests' member missing"; + return result; + } + if (!requests.isArray()) { + result.Error = "'requests' member is not an array"; + return result; + } + + result.reserve(requests.size()); + for (Json::Value const& request : requests) { + result.emplace_back(this->BuildClientRequest(request)); + } + + return result; +} + +cmFileAPI::ClientRequest cmFileAPI::BuildClientRequest( + Json::Value const& request) +{ + ClientRequest r; + + if (!request.isObject()) { + r.Error = "request is not an object"; + return r; + } + + Json::Value const& kind = request["kind"]; + if (kind.isNull()) { + r.Error = "'kind' member missing"; + return r; + } + if (!kind.isString()) { + r.Error = "'kind' member is not a string"; + return r; + } + std::string const& kindName = kind.asString(); + + if (kindName == this->ObjectKindName(ObjectKind::CodeModel)) { + r.Kind = ObjectKind::CodeModel; + } else if (kindName == this->ObjectKindName(ObjectKind::Cache)) { + r.Kind = ObjectKind::Cache; + } else if (kindName == this->ObjectKindName(ObjectKind::CMakeFiles)) { + r.Kind = ObjectKind::CMakeFiles; + } else if (kindName == this->ObjectKindName(ObjectKind::InternalTest)) { + r.Kind = ObjectKind::InternalTest; + } else { + r.Error = "unknown request kind '" + kindName + "'"; + return r; + } + + Json::Value const& version = request["version"]; + if (version.isNull()) { + r.Error = "'version' member missing"; + return r; + } + std::vector<RequestVersion> versions; + if (!cmFileAPI::ReadRequestVersions(version, versions, r.Error)) { + return r; + } + + switch (r.Kind) { + case ObjectKind::CodeModel: + this->BuildClientRequestCodeModel(r, versions); + break; + case ObjectKind::Cache: + this->BuildClientRequestCache(r, versions); + break; + case ObjectKind::CMakeFiles: + this->BuildClientRequestCMakeFiles(r, versions); + break; + case ObjectKind::InternalTest: + this->BuildClientRequestInternalTest(r, versions); + break; + } + + return r; +} + +Json::Value cmFileAPI::BuildClientReply(ClientQuery const& q) +{ + Json::Value reply = this->BuildReply(q.DirQuery); + + if (!q.HaveQueryJson) { + return reply; + } + + Json::Value& reply_query_json = reply["query.json"]; + ClientQueryJson const& qj = q.QueryJson; + + if (!qj.Error.empty()) { + reply_query_json = this->BuildReplyError(qj.Error); + return reply; + } + + if (!qj.ClientValue.isNull()) { + reply_query_json["client"] = qj.ClientValue; + } + + if (!qj.RequestsValue.isNull()) { + reply_query_json["requests"] = qj.RequestsValue; + } + + reply_query_json["responses"] = this->BuildClientReplyResponses(qj.Requests); + + return reply; +} + +Json::Value cmFileAPI::BuildClientReplyResponses( + ClientRequests const& requests) +{ + Json::Value responses; + + if (!requests.Error.empty()) { + responses = this->BuildReplyError(requests.Error); + return responses; + } + + responses = Json::arrayValue; + for (ClientRequest const& request : requests) { + responses.append(this->BuildClientReplyResponse(request)); + } + + return responses; +} + +Json::Value cmFileAPI::BuildClientReplyResponse(ClientRequest const& request) +{ + Json::Value response; + if (!request.Error.empty()) { + response = this->BuildReplyError(request.Error); + return response; + } + response = this->AddReplyIndexObject(request); + return response; +} + +bool cmFileAPI::ReadRequestVersions(Json::Value const& version, + std::vector<RequestVersion>& versions, + std::string& error) +{ + if (version.isArray()) { + for (Json::Value const& v : version) { + if (!ReadRequestVersion(v, /*inArray=*/true, versions, error)) { + return false; + } + } + } else { + if (!ReadRequestVersion(version, /*inArray=*/false, versions, error)) { + return false; + } + } + return true; +} + +bool cmFileAPI::ReadRequestVersion(Json::Value const& version, bool inArray, + std::vector<RequestVersion>& result, + std::string& error) +{ + if (version.isUInt()) { + RequestVersion v; + v.Major = version.asUInt(); + result.push_back(v); + return true; + } + + if (!version.isObject()) { + if (inArray) { + error = "'version' array entry is not a non-negative integer or object"; + } else { + error = + "'version' member is not a non-negative integer, object, or array"; + } + return false; + } + + Json::Value const& major = version["major"]; + if (major.isNull()) { + error = "'version' object 'major' member missing"; + return false; + } + if (!major.isUInt()) { + error = "'version' object 'major' member is not a non-negative integer"; + return false; + } + + RequestVersion v; + v.Major = major.asUInt(); + + Json::Value const& minor = version["minor"]; + if (minor.isUInt()) { + v.Minor = minor.asUInt(); + } else if (!minor.isNull()) { + error = "'version' object 'minor' member is not a non-negative integer"; + return false; + } + + result.push_back(v); + + return true; +} + +std::string cmFileAPI::NoSupportedVersion( + std::vector<RequestVersion> const& versions) +{ + std::ostringstream msg; + msg << "no supported version specified"; + if (!versions.empty()) { + msg << " among:"; + for (RequestVersion const& v : versions) { + msg << " " << v.Major << "." << v.Minor; + } + } + return msg.str(); +} + +// The "codemodel" object kind. + +static unsigned int const CodeModelV2Minor = 0; + +void cmFileAPI::BuildClientRequestCodeModel( + ClientRequest& r, std::vector<RequestVersion> const& versions) +{ + // Select a known version from those requested. + for (RequestVersion const& v : versions) { + if ((v.Major == 2 && v.Minor <= CodeModelV2Minor)) { + r.Version = v.Major; + break; + } + } + if (!r.Version) { + r.Error = NoSupportedVersion(versions); + } +} + +Json::Value cmFileAPI::BuildCodeModel(Object const& object) +{ + using namespace std::placeholders; + Json::Value codemodel = cmFileAPICodemodelDump(*this, object.Version); + codemodel["kind"] = this->ObjectKindName(object.Kind); + + Json::Value& version = codemodel["version"] = Json::objectValue; + if (object.Version == 2) { + version["major"] = 2; + version["minor"] = CodeModelV2Minor; + } else { + return codemodel; // should be unreachable + } + + return codemodel; +} + +// The "cache" object kind. + +static unsigned int const CacheV2Minor = 0; + +void cmFileAPI::BuildClientRequestCache( + ClientRequest& r, std::vector<RequestVersion> const& versions) +{ + // Select a known version from those requested. + for (RequestVersion const& v : versions) { + if ((v.Major == 2 && v.Minor <= CacheV2Minor)) { + r.Version = v.Major; + break; + } + } + if (!r.Version) { + r.Error = NoSupportedVersion(versions); + } +} + +Json::Value cmFileAPI::BuildCache(Object const& object) +{ + using namespace std::placeholders; + Json::Value cache = cmFileAPICacheDump(*this, object.Version); + cache["kind"] = this->ObjectKindName(object.Kind); + + Json::Value& version = cache["version"] = Json::objectValue; + if (object.Version == 2) { + version["major"] = 2; + version["minor"] = CacheV2Minor; + } else { + return cache; // should be unreachable + } + + return cache; +} + +// The "cmakeFiles" object kind. + +static unsigned int const CMakeFilesV1Minor = 0; + +void cmFileAPI::BuildClientRequestCMakeFiles( + ClientRequest& r, std::vector<RequestVersion> const& versions) +{ + // Select a known version from those requested. + for (RequestVersion const& v : versions) { + if ((v.Major == 1 && v.Minor <= CMakeFilesV1Minor)) { + r.Version = v.Major; + break; + } + } + if (!r.Version) { + r.Error = NoSupportedVersion(versions); + } +} + +Json::Value cmFileAPI::BuildCMakeFiles(Object const& object) +{ + using namespace std::placeholders; + Json::Value cmakeFiles = cmFileAPICMakeFilesDump(*this, object.Version); + cmakeFiles["kind"] = this->ObjectKindName(object.Kind); + + Json::Value& version = cmakeFiles["version"] = Json::objectValue; + if (object.Version == 1) { + version["major"] = 1; + version["minor"] = CMakeFilesV1Minor; + } else { + return cmakeFiles; // should be unreachable + } + + return cmakeFiles; +} + +// The "__test" object kind is for internal testing of CMake. + +static unsigned int const InternalTestV1Minor = 3; +static unsigned int const InternalTestV2Minor = 0; + +void cmFileAPI::BuildClientRequestInternalTest( + ClientRequest& r, std::vector<RequestVersion> const& versions) +{ + // Select a known version from those requested. + for (RequestVersion const& v : versions) { + if ((v.Major == 1 && v.Minor <= InternalTestV1Minor) || // + (v.Major == 2 && v.Minor <= InternalTestV2Minor)) { + r.Version = v.Major; + break; + } + } + if (!r.Version) { + r.Error = NoSupportedVersion(versions); + } +} + +Json::Value cmFileAPI::BuildInternalTest(Object const& object) +{ + Json::Value test = Json::objectValue; + test["kind"] = this->ObjectKindName(object.Kind); + Json::Value& version = test["version"] = Json::objectValue; + if (object.Version == 2) { + version["major"] = 2; + version["minor"] = InternalTestV2Minor; + } else { + version["major"] = 1; + version["minor"] = InternalTestV1Minor; + } + return test; +} diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h new file mode 100644 index 000000000..341b072f4 --- /dev/null +++ b/Source/cmFileAPI.h @@ -0,0 +1,204 @@ +/* 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 + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_jsoncpp_reader.h" +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" + +#include <map> +#include <memory> // IWYU pragma: keep +#include <string> +#include <unordered_set> +#include <vector> + +class cmake; + +class cmFileAPI +{ +public: + cmFileAPI(cmake* cm); + + /** Read fileapi queries from disk. */ + void ReadQueries(); + + /** Write fileapi replies to disk. */ + void WriteReplies(); + + /** Get the "cmake" instance with which this was constructed. */ + cmake* GetCMakeInstance() const { return this->CMakeInstance; } + + /** Convert a JSON object or array into an object with a single + "jsonFile" member specifying a file named with the given prefix + and holding the original object. Other JSON types are unchanged. */ + Json::Value MaybeJsonFile(Json::Value in, std::string const& prefix); + +private: + cmake* CMakeInstance; + + /** The api/v1 directory location. */ + std::string APIv1; + + /** The set of files we have just written to the reply directory. */ + std::unordered_set<std::string> ReplyFiles; + + static std::vector<std::string> LoadDir(std::string const& dir); + void RemoveOldReplyFiles(); + + // Keep in sync with ObjectKindName. + enum class ObjectKind + { + CodeModel, + Cache, + CMakeFiles, + InternalTest + }; + + /** Identify one object kind and major version. */ + struct Object + { + ObjectKind Kind; + unsigned long Version = 0; + friend bool operator<(Object const& l, Object const& r) + { + if (l.Kind != r.Kind) { + return l.Kind < r.Kind; + } + return l.Version < r.Version; + } + }; + + /** Represent content of a query directory. */ + struct Query + { + /** Known object kind-version pairs. */ + std::vector<Object> Known; + /** Unknown object kind names. */ + std::vector<std::string> Unknown; + }; + + /** Represent one request in a client 'query.json'. */ + struct ClientRequest : public Object + { + /** Empty if request is valid, else the error string. */ + std::string Error; + }; + + /** Represent the "requests" in a client 'query.json'. */ + struct ClientRequests : public std::vector<ClientRequest> + { + /** Empty if requests field is valid, else the error string. */ + std::string Error; + }; + + /** Represent the content of a client query.json file. */ + struct ClientQueryJson + { + /** The error string if parsing failed, else empty. */ + std::string Error; + + /** The 'query.json' object "client" member if it exists, else null. */ + Json::Value ClientValue; + + /** The 'query.json' object "requests" member if it exists, else null. */ + Json::Value RequestsValue; + + /** Requests extracted from 'query.json'. */ + ClientRequests Requests; + }; + + /** Represent content of a client query directory. */ + struct ClientQuery + { + /** The content of the client query directory except 'query.json'. */ + Query DirQuery; + + /** True if 'query.json' exists. */ + bool HaveQueryJson = false; + + /** The 'query.json' content. */ + ClientQueryJson QueryJson; + }; + + /** Whether the top-level query directory exists at all. */ + bool QueryExists = false; + + /** The content of the top-level query directory. */ + Query TopQuery; + + /** The content of each "client-$client" query directory. */ + std::map<std::string, ClientQuery> ClientQueries; + + /** Reply index object generated for object kind/version. + This populates the "objects" field of the reply index. */ + std::map<Object, Json::Value> ReplyIndexObjects; + + std::unique_ptr<Json::CharReader> JsonReader; + std::unique_ptr<Json::StreamWriter> JsonWriter; + + bool ReadJsonFile(std::string const& file, Json::Value& value, + std::string& error); + + std::string WriteJsonFile( + Json::Value const& value, std::string const& prefix, + std::string (*computeSuffix)(std::string const&) = ComputeSuffixHash); + static std::string ComputeSuffixHash(std::string const&); + static std::string ComputeSuffixTime(std::string const&); + + static bool ReadQuery(std::string const& query, + std::vector<Object>& objects); + void ReadClient(std::string const& client); + void ReadClientQuery(std::string const& client, ClientQueryJson& q); + + Json::Value BuildReplyIndex(); + Json::Value BuildCMake(); + Json::Value BuildReply(Query const& q); + static Json::Value BuildReplyError(std::string const& error); + Json::Value const& AddReplyIndexObject(Object const& o); + + static const char* ObjectKindName(ObjectKind kind); + static std::string ObjectName(Object const& o); + + Json::Value BuildObject(Object const& object); + + ClientRequests BuildClientRequests(Json::Value const& requests); + ClientRequest BuildClientRequest(Json::Value const& request); + Json::Value BuildClientReply(ClientQuery const& q); + Json::Value BuildClientReplyResponses(ClientRequests const& requests); + Json::Value BuildClientReplyResponse(ClientRequest const& request); + + struct RequestVersion + { + unsigned int Major = 0; + unsigned int Minor = 0; + }; + static bool ReadRequestVersions(Json::Value const& version, + std::vector<RequestVersion>& versions, + std::string& error); + static bool ReadRequestVersion(Json::Value const& version, bool inArray, + std::vector<RequestVersion>& result, + std::string& error); + static std::string NoSupportedVersion( + std::vector<RequestVersion> const& versions); + + void BuildClientRequestCodeModel( + ClientRequest& r, std::vector<RequestVersion> const& versions); + Json::Value BuildCodeModel(Object const& object); + + void BuildClientRequestCache(ClientRequest& r, + std::vector<RequestVersion> const& versions); + Json::Value BuildCache(Object const& object); + + void BuildClientRequestCMakeFiles( + ClientRequest& r, std::vector<RequestVersion> const& versions); + Json::Value BuildCMakeFiles(Object const& object); + + void BuildClientRequestInternalTest( + ClientRequest& r, std::vector<RequestVersion> const& versions); + Json::Value BuildInternalTest(Object const& object); +}; + +#endif diff --git a/Source/cmFileAPICMakeFiles.cxx b/Source/cmFileAPICMakeFiles.cxx new file mode 100644 index 000000000..5590bc2b3 --- /dev/null +++ b/Source/cmFileAPICMakeFiles.cxx @@ -0,0 +1,114 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFileAPICMakeFiles.h" + +#include "cmFileAPI.h" +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmSystemTools.h" +#include "cmake.h" + +#include "cm_jsoncpp_value.h" + +#include <string> +#include <vector> + +namespace { + +class CMakeFiles +{ + cmFileAPI& FileAPI; + unsigned long Version; + std::string CMakeModules; + std::string const& TopSource; + std::string const& TopBuild; + bool OutOfSource; + + Json::Value DumpPaths(); + Json::Value DumpInputs(); + Json::Value DumpInput(std::string const& file); + +public: + CMakeFiles(cmFileAPI& fileAPI, unsigned long version); + Json::Value Dump(); +}; + +CMakeFiles::CMakeFiles(cmFileAPI& fileAPI, unsigned long version) + : FileAPI(fileAPI) + , Version(version) + , CMakeModules(cmSystemTools::GetCMakeRoot() + "/Modules") + , TopSource(this->FileAPI.GetCMakeInstance()->GetHomeDirectory()) + , TopBuild(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory()) + , OutOfSource(TopBuild != TopSource) +{ + static_cast<void>(this->Version); +} + +Json::Value CMakeFiles::Dump() +{ + Json::Value cmakeFiles = Json::objectValue; + cmakeFiles["paths"] = this->DumpPaths(); + cmakeFiles["inputs"] = DumpInputs(); + return cmakeFiles; +} + +Json::Value CMakeFiles::DumpPaths() +{ + Json::Value paths = Json::objectValue; + paths["source"] = this->TopSource; + paths["build"] = this->TopBuild; + return paths; +} + +Json::Value CMakeFiles::DumpInputs() +{ + Json::Value inputs = Json::arrayValue; + + cmGlobalGenerator* gg = + this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); + for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) { + cmMakefile const* mf = lg->GetMakefile(); + for (std::string const& file : mf->GetListFiles()) { + inputs.append(this->DumpInput(file)); + } + } + + return inputs; +} + +Json::Value CMakeFiles::DumpInput(std::string const& file) +{ + Json::Value input = Json::objectValue; + + bool const isCMake = cmSystemTools::IsSubDirectory(file, this->CMakeModules); + if (isCMake) { + input["isCMake"] = true; + } + + if (!cmSystemTools::IsSubDirectory(file, this->TopSource) && + !cmSystemTools::IsSubDirectory(file, this->TopBuild)) { + input["isExternal"] = true; + } + + if (this->OutOfSource && + cmSystemTools::IsSubDirectory(file, this->TopBuild)) { + input["isGenerated"] = true; + } + + std::string path = file; + if (!isCMake && cmSystemTools::IsSubDirectory(path, this->TopSource)) { + // Use a relative path within the source directory. + path = cmSystemTools::RelativePath(this->TopSource, path); + } + input["path"] = path; + + return input; +} +} + +Json::Value cmFileAPICMakeFilesDump(cmFileAPI& fileAPI, unsigned long version) +{ + CMakeFiles cmakeFiles(fileAPI, version); + return cmakeFiles.Dump(); +} diff --git a/Source/cmFileAPICMakeFiles.h b/Source/cmFileAPICMakeFiles.h new file mode 100644 index 000000000..a851c32f4 --- /dev/null +++ b/Source/cmFileAPICMakeFiles.h @@ -0,0 +1,15 @@ +/* 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 + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_jsoncpp_value.h" + +class cmFileAPI; + +extern Json::Value cmFileAPICMakeFilesDump(cmFileAPI& fileAPI, + unsigned long version); + +#endif diff --git a/Source/cmFileAPICache.cxx b/Source/cmFileAPICache.cxx new file mode 100644 index 000000000..f96bc90e5 --- /dev/null +++ b/Source/cmFileAPICache.cxx @@ -0,0 +1,106 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFileAPICache.h" + +#include "cmFileAPI.h" +#include "cmState.h" +#include "cmake.h" + +#include "cm_jsoncpp_value.h" + +#include <algorithm> +#include <string> +#include <utility> +#include <vector> + +namespace { + +class Cache +{ + cmFileAPI& FileAPI; + unsigned long Version; + cmState* State; + + Json::Value DumpEntries(); + Json::Value DumpEntry(std::string const& name); + Json::Value DumpEntryProperties(std::string const& name); + Json::Value DumpEntryProperty(std::string const& name, + std::string const& prop); + +public: + Cache(cmFileAPI& fileAPI, unsigned long version); + Json::Value Dump(); +}; + +Cache::Cache(cmFileAPI& fileAPI, unsigned long version) + : FileAPI(fileAPI) + , Version(version) + , State(this->FileAPI.GetCMakeInstance()->GetState()) +{ + static_cast<void>(this->Version); +} + +Json::Value Cache::Dump() +{ + Json::Value cache = Json::objectValue; + cache["entries"] = DumpEntries(); + return cache; +} + +Json::Value Cache::DumpEntries() +{ + Json::Value entries = Json::arrayValue; + + std::vector<std::string> names = this->State->GetCacheEntryKeys(); + std::sort(names.begin(), names.end()); + + for (std::string const& name : names) { + entries.append(this->DumpEntry(name)); + } + + return entries; +} + +Json::Value Cache::DumpEntry(std::string const& name) +{ + Json::Value entry = Json::objectValue; + entry["name"] = name; + entry["type"] = + cmState::CacheEntryTypeToString(this->State->GetCacheEntryType(name)); + entry["value"] = this->State->GetCacheEntryValue(name); + + Json::Value properties = this->DumpEntryProperties(name); + if (!properties.empty()) { + entry["properties"] = std::move(properties); + } + + return entry; +} + +Json::Value Cache::DumpEntryProperties(std::string const& name) +{ + Json::Value properties = Json::arrayValue; + std::vector<std::string> props = + this->State->GetCacheEntryPropertyList(name); + std::sort(props.begin(), props.end()); + for (std::string const& prop : props) { + properties.append(this->DumpEntryProperty(name, prop)); + } + return properties; +} + +Json::Value Cache::DumpEntryProperty(std::string const& name, + std::string const& prop) +{ + Json::Value property = Json::objectValue; + property["name"] = prop; + property["value"] = this->State->GetCacheEntryProperty(name, prop); + return property; +} +} + +Json::Value cmFileAPICacheDump(cmFileAPI& fileAPI, unsigned long version) +{ + Cache cache(fileAPI, version); + return cache.Dump(); +} diff --git a/Source/cmFileAPICache.h b/Source/cmFileAPICache.h new file mode 100644 index 000000000..09d9e1ce9 --- /dev/null +++ b/Source/cmFileAPICache.h @@ -0,0 +1,15 @@ +/* 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 + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_jsoncpp_value.h" + +class cmFileAPI; + +extern Json::Value cmFileAPICacheDump(cmFileAPI& fileAPI, + unsigned long version); + +#endif diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx new file mode 100644 index 000000000..45e830318 --- /dev/null +++ b/Source/cmFileAPICodemodel.cxx @@ -0,0 +1,1247 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFileAPICodemodel.h" + +#include "cmCryptoHash.h" +#include "cmFileAPI.h" +#include "cmGeneratorExpression.h" +#include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" +#include "cmInstallGenerator.h" +#include "cmInstallSubdirectoryGenerator.h" +#include "cmInstallTargetGenerator.h" +#include "cmLinkLineComputer.h" +#include "cmListFileCache.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmSourceFile.h" +#include "cmSourceGroup.h" +#include "cmState.h" +#include "cmStateDirectory.h" +#include "cmStateSnapshot.h" +#include "cmStateTypes.h" +#include "cmSystemTools.h" +#include "cmTarget.h" +#include "cmTargetDepend.h" +#include "cmake.h" + +#include "cm_jsoncpp_value.h" + +#include <algorithm> +#include <cassert> +#include <map> +#include <set> +#include <string> +#include <unordered_map> +#include <utility> +#include <vector> + +namespace { + +class Codemodel +{ + cmFileAPI& FileAPI; + unsigned long Version; + + Json::Value DumpPaths(); + Json::Value DumpConfigurations(); + Json::Value DumpConfiguration(std::string const& config); + +public: + Codemodel(cmFileAPI& fileAPI, unsigned long version); + Json::Value Dump(); +}; + +class CodemodelConfig +{ + cmFileAPI& FileAPI; + unsigned long Version; + std::string const& Config; + std::string TopSource; + std::string TopBuild; + + struct Directory + { + cmStateSnapshot Snapshot; + cmLocalGenerator const* LocalGenerator = nullptr; + Json::Value TargetIndexes = Json::arrayValue; + Json::ArrayIndex ProjectIndex; + bool HasInstallRule = false; + }; + std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder> + DirectoryMap; + std::vector<Directory> Directories; + + struct Project + { + cmStateSnapshot Snapshot; + static const Json::ArrayIndex NoParentIndex = + static_cast<Json::ArrayIndex>(-1); + Json::ArrayIndex ParentIndex = NoParentIndex; + Json::Value ChildIndexes = Json::arrayValue; + Json::Value DirectoryIndexes = Json::arrayValue; + Json::Value TargetIndexes = Json::arrayValue; + }; + std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder> + ProjectMap; + std::vector<Project> Projects; + + void ProcessDirectories(); + + Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg); + Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s); + + Json::ArrayIndex AddProject(cmStateSnapshot s); + + Json::Value DumpTargets(); + Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti); + + Json::Value DumpDirectories(); + Json::Value DumpDirectory(Directory& d); + + Json::Value DumpProjects(); + Json::Value DumpProject(Project& p); + + Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s); + +public: + CodemodelConfig(cmFileAPI& fileAPI, unsigned long version, + std::string const& config); + Json::Value Dump(); +}; + +std::string RelativeIfUnder(std::string const& top, std::string const& in) +{ + std::string out; + if (in == top) { + out = "."; + } else if (cmSystemTools::IsSubDirectory(in, top)) { + out = in.substr(top.size() + 1); + } else { + out = in; + } + return out; +} + +std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild) +{ + cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256); + std::string path = RelativeIfUnder( + topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory()); + std::string hash = hasher.HashString(path); + hash.resize(20, '0'); + return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash; +} + +class BacktraceData +{ + std::string TopSource; + std::unordered_map<std::string, Json::ArrayIndex> CommandMap; + std::unordered_map<std::string, Json::ArrayIndex> FileMap; + std::unordered_map<cmListFileContext const*, Json::ArrayIndex> NodeMap; + Json::Value Commands = Json::arrayValue; + Json::Value Files = Json::arrayValue; + Json::Value Nodes = Json::arrayValue; + + Json::ArrayIndex AddCommand(std::string const& command) + { + auto i = this->CommandMap.find(command); + if (i == this->CommandMap.end()) { + auto cmdIndex = static_cast<Json::ArrayIndex>(this->Commands.size()); + i = this->CommandMap.emplace(command, cmdIndex).first; + this->Commands.append(command); + } + return i->second; + } + + Json::ArrayIndex AddFile(std::string const& file) + { + auto i = this->FileMap.find(file); + if (i == this->FileMap.end()) { + auto fileIndex = static_cast<Json::ArrayIndex>(this->Files.size()); + i = this->FileMap.emplace(file, fileIndex).first; + this->Files.append(RelativeIfUnder(this->TopSource, file)); + } + return i->second; + } + +public: + BacktraceData(std::string topSource); + bool Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index); + Json::Value Dump(); +}; + +BacktraceData::BacktraceData(std::string topSource) + : TopSource(std::move(topSource)) +{ +} + +bool BacktraceData::Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index) +{ + if (bt.Empty()) { + return false; + } + cmListFileContext const* top = &bt.Top(); + auto found = this->NodeMap.find(top); + if (found != this->NodeMap.end()) { + index = found->second; + return true; + } + Json::Value entry = Json::objectValue; + entry["file"] = this->AddFile(top->FilePath); + if (top->Line) { + entry["line"] = static_cast<int>(top->Line); + } + if (!top->Name.empty()) { + entry["command"] = this->AddCommand(top->Name); + } + Json::ArrayIndex parent; + if (this->Add(bt.Pop(), parent)) { + entry["parent"] = parent; + } + index = this->NodeMap[top] = this->Nodes.size(); + this->Nodes.append(std::move(entry)); // NOLINT(*) + return true; +} + +Json::Value BacktraceData::Dump() +{ + Json::Value backtraceGraph; + this->CommandMap.clear(); + this->FileMap.clear(); + this->NodeMap.clear(); + backtraceGraph["commands"] = std::move(this->Commands); + backtraceGraph["files"] = std::move(this->Files); + backtraceGraph["nodes"] = std::move(this->Nodes); + return backtraceGraph; +} + +struct CompileData +{ + struct IncludeEntry + { + BT<std::string> Path; + bool IsSystem = false; + IncludeEntry(BT<std::string> path, bool isSystem) + : Path(std::move(path)) + , IsSystem(isSystem) + { + } + }; + + void SetDefines(std::set<BT<std::string>> const& defines); + + std::string Language; + std::string Sysroot; + std::vector<BT<std::string>> Flags; + std::vector<BT<std::string>> Defines; + std::vector<IncludeEntry> Includes; +}; + +void CompileData::SetDefines(std::set<BT<std::string>> const& defines) +{ + this->Defines.reserve(defines.size()); + for (BT<std::string> const& d : defines) { + this->Defines.push_back(d); + } +} + +class Target +{ + cmGeneratorTarget* GT; + std::string const& Config; + std::string TopSource; + std::string TopBuild; + std::vector<cmSourceGroup> SourceGroupsLocal; + BacktraceData Backtraces; + + std::map<std::string, CompileData> CompileDataMap; + + std::unordered_map<cmSourceFile const*, Json::ArrayIndex> SourceMap; + Json::Value Sources = Json::arrayValue; + + struct SourceGroup + { + std::string Name; + Json::Value SourceIndexes = Json::arrayValue; + }; + std::unordered_map<cmSourceGroup const*, Json::ArrayIndex> SourceGroupsMap; + std::vector<SourceGroup> SourceGroups; + + struct CompileGroup + { + std::map<Json::Value, Json::ArrayIndex>::iterator Entry; + Json::Value SourceIndexes = Json::arrayValue; + }; + std::map<Json::Value, Json::ArrayIndex> CompileGroupMap; + std::vector<CompileGroup> CompileGroups; + + void ProcessLanguages(); + void ProcessLanguage(std::string const& lang); + + Json::ArrayIndex AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si); + CompileData BuildCompileData(cmSourceFile* sf); + Json::ArrayIndex AddSourceCompileGroup(cmSourceFile* sf, + Json::ArrayIndex si); + void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt); + Json::Value DumpPaths(); + Json::Value DumpCompileData(CompileData cd); + Json::Value DumpInclude(CompileData::IncludeEntry const& inc); + Json::Value DumpDefine(BT<std::string> const& def); + Json::Value DumpSources(); + Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk, + Json::ArrayIndex si); + Json::Value DumpSourceGroups(); + Json::Value DumpSourceGroup(SourceGroup& sg); + Json::Value DumpCompileGroups(); + Json::Value DumpCompileGroup(CompileGroup& cg); + Json::Value DumpSysroot(std::string const& path); + Json::Value DumpInstall(); + Json::Value DumpInstallPrefix(); + Json::Value DumpInstallDestinations(); + Json::Value DumpInstallDestination(cmInstallTargetGenerator* itGen); + Json::Value DumpArtifacts(); + Json::Value DumpLink(); + Json::Value DumpArchive(); + Json::Value DumpLinkCommandFragments(); + Json::Value DumpCommandFragments(std::vector<BT<std::string>> const& frags); + Json::Value DumpCommandFragment(BT<std::string> const& frag, + std::string const& role = std::string()); + Json::Value DumpDependencies(); + Json::Value DumpDependency(cmTargetDepend const& td); + Json::Value DumpFolder(); + +public: + Target(cmGeneratorTarget* gt, std::string const& config); + Json::Value Dump(); +}; + +Codemodel::Codemodel(cmFileAPI& fileAPI, unsigned long version) + : FileAPI(fileAPI) + , Version(version) +{ +} + +Json::Value Codemodel::Dump() +{ + Json::Value codemodel = Json::objectValue; + + codemodel["paths"] = this->DumpPaths(); + codemodel["configurations"] = this->DumpConfigurations(); + + return codemodel; +} + +Json::Value Codemodel::DumpPaths() +{ + Json::Value paths = Json::objectValue; + paths["source"] = this->FileAPI.GetCMakeInstance()->GetHomeDirectory(); + paths["build"] = this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory(); + return paths; +} + +Json::Value Codemodel::DumpConfigurations() +{ + std::vector<std::string> configs; + cmGlobalGenerator* gg = + this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); + auto makefiles = gg->GetMakefiles(); + if (!makefiles.empty()) { + makefiles[0]->GetConfigurations(configs); + if (configs.empty()) { + configs.emplace_back(); + } + } + Json::Value configurations = Json::arrayValue; + for (std::string const& config : configs) { + configurations.append(this->DumpConfiguration(config)); + } + return configurations; +} + +Json::Value Codemodel::DumpConfiguration(std::string const& config) +{ + CodemodelConfig configuration(this->FileAPI, this->Version, config); + return configuration.Dump(); +} + +CodemodelConfig::CodemodelConfig(cmFileAPI& fileAPI, unsigned long version, + std::string const& config) + : FileAPI(fileAPI) + , Version(version) + , Config(config) + , TopSource(this->FileAPI.GetCMakeInstance()->GetHomeDirectory()) + , TopBuild(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory()) +{ + static_cast<void>(this->Version); +} + +Json::Value CodemodelConfig::Dump() +{ + Json::Value configuration = Json::objectValue; + configuration["name"] = this->Config; + this->ProcessDirectories(); + configuration["targets"] = this->DumpTargets(); + configuration["directories"] = this->DumpDirectories(); + configuration["projects"] = this->DumpProjects(); + return configuration; +} + +void CodemodelConfig::ProcessDirectories() +{ + cmGlobalGenerator* gg = + this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); + std::vector<cmLocalGenerator*> const& localGens = gg->GetLocalGenerators(); + + // Add directories in forward order to process parents before children. + this->Directories.reserve(localGens.size()); + for (cmLocalGenerator* lg : localGens) { + auto directoryIndex = + static_cast<Json::ArrayIndex>(this->Directories.size()); + this->Directories.emplace_back(); + Directory& d = this->Directories[directoryIndex]; + d.Snapshot = lg->GetStateSnapshot().GetBuildsystemDirectory(); + d.LocalGenerator = lg; + this->DirectoryMap[d.Snapshot] = directoryIndex; + + d.ProjectIndex = this->AddProject(d.Snapshot); + this->Projects[d.ProjectIndex].DirectoryIndexes.append(directoryIndex); + } + + // Update directories in reverse order to process children before parents. + for (auto di = this->Directories.rbegin(); di != this->Directories.rend(); + ++di) { + Directory& d = *di; + + // Accumulate the presence of install rules on the way up. + for (auto gen : d.LocalGenerator->GetMakefile()->GetInstallGenerators()) { + if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(gen)) { + d.HasInstallRule = true; + break; + } + } + if (!d.HasInstallRule) { + for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) { + cmStateSnapshot childDir = child.GetBuildsystemDirectory(); + Json::ArrayIndex const childIndex = this->GetDirectoryIndex(childDir); + if (this->Directories[childIndex].HasInstallRule) { + d.HasInstallRule = true; + break; + } + } + } + } +} + +Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmLocalGenerator const* lg) +{ + return this->GetDirectoryIndex( + lg->GetStateSnapshot().GetBuildsystemDirectory()); +} + +Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmStateSnapshot s) +{ + auto i = this->DirectoryMap.find(s); + assert(i != this->DirectoryMap.end()); + return i->second; +} + +Json::ArrayIndex CodemodelConfig::AddProject(cmStateSnapshot s) +{ + cmStateSnapshot ps = s.GetBuildsystemDirectoryParent(); + if (ps.IsValid() && ps.GetProjectName() == s.GetProjectName()) { + // This directory is part of its parent directory project. + Json::ArrayIndex const parentDirIndex = this->GetDirectoryIndex(ps); + return this->Directories[parentDirIndex].ProjectIndex; + } + + // This directory starts a new project. + auto projectIndex = static_cast<Json::ArrayIndex>(this->Projects.size()); + this->Projects.emplace_back(); + Project& p = this->Projects[projectIndex]; + p.Snapshot = s; + this->ProjectMap[s] = projectIndex; + if (ps.IsValid()) { + Json::ArrayIndex const parentDirIndex = this->GetDirectoryIndex(ps); + p.ParentIndex = this->Directories[parentDirIndex].ProjectIndex; + this->Projects[p.ParentIndex].ChildIndexes.append(projectIndex); + } + return projectIndex; +} + +Json::Value CodemodelConfig::DumpTargets() +{ + Json::Value targets = Json::arrayValue; + + std::vector<cmGeneratorTarget*> targetList; + cmGlobalGenerator* gg = + this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); + for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) { + std::vector<cmGeneratorTarget*> const& list = lg->GetGeneratorTargets(); + targetList.insert(targetList.end(), list.begin(), list.end()); + } + std::sort(targetList.begin(), targetList.end(), + [](cmGeneratorTarget* l, cmGeneratorTarget* r) { + return l->GetName() < r->GetName(); + }); + + for (cmGeneratorTarget* gt : targetList) { + if (gt->GetType() == cmStateEnums::GLOBAL_TARGET || + gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + continue; + } + + targets.append(this->DumpTarget(gt, targets.size())); + } + + return targets; +} + +Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt, + Json::ArrayIndex ti) +{ + Target t(gt, this->Config); + std::string prefix = "target-" + gt->GetName(); + if (!this->Config.empty()) { + prefix += "-" + this->Config; + } + Json::Value target = this->FileAPI.MaybeJsonFile(t.Dump(), prefix); + target["name"] = gt->GetName(); + target["id"] = TargetId(gt, this->TopBuild); + + // Cross-reference directory containing target. + Json::ArrayIndex di = this->GetDirectoryIndex(gt->GetLocalGenerator()); + target["directoryIndex"] = di; + this->Directories[di].TargetIndexes.append(ti); + + // Cross-reference project containing target. + Json::ArrayIndex pi = this->Directories[di].ProjectIndex; + target["projectIndex"] = pi; + this->Projects[pi].TargetIndexes.append(ti); + + return target; +} + +Json::Value CodemodelConfig::DumpDirectories() +{ + Json::Value directories = Json::arrayValue; + for (Directory& d : this->Directories) { + directories.append(this->DumpDirectory(d)); + } + return directories; +} + +Json::Value CodemodelConfig::DumpDirectory(Directory& d) +{ + Json::Value directory = Json::objectValue; + + std::string sourceDir = d.Snapshot.GetDirectory().GetCurrentSource(); + directory["source"] = RelativeIfUnder(this->TopSource, sourceDir); + + std::string buildDir = d.Snapshot.GetDirectory().GetCurrentBinary(); + directory["build"] = RelativeIfUnder(this->TopBuild, buildDir); + + cmStateSnapshot parentDir = d.Snapshot.GetBuildsystemDirectoryParent(); + if (parentDir.IsValid()) { + directory["parentIndex"] = this->GetDirectoryIndex(parentDir); + } + + Json::Value childIndexes = Json::arrayValue; + for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) { + childIndexes.append( + this->GetDirectoryIndex(child.GetBuildsystemDirectory())); + } + if (!childIndexes.empty()) { + directory["childIndexes"] = std::move(childIndexes); + } + + directory["projectIndex"] = d.ProjectIndex; + + if (!d.TargetIndexes.empty()) { + directory["targetIndexes"] = std::move(d.TargetIndexes); + } + + Json::Value minimumCMakeVersion = this->DumpMinimumCMakeVersion(d.Snapshot); + if (!minimumCMakeVersion.isNull()) { + directory["minimumCMakeVersion"] = std::move(minimumCMakeVersion); + } + + if (d.HasInstallRule) { + directory["hasInstallRule"] = true; + } + + return directory; +} + +Json::Value CodemodelConfig::DumpProjects() +{ + Json::Value projects = Json::arrayValue; + for (Project& p : this->Projects) { + projects.append(this->DumpProject(p)); + } + return projects; +} + +Json::Value CodemodelConfig::DumpProject(Project& p) +{ + Json::Value project = Json::objectValue; + + project["name"] = p.Snapshot.GetProjectName(); + + if (p.ParentIndex != Project::NoParentIndex) { + project["parentIndex"] = p.ParentIndex; + } + + if (!p.ChildIndexes.empty()) { + project["childIndexes"] = std::move(p.ChildIndexes); + } + + project["directoryIndexes"] = std::move(p.DirectoryIndexes); + + if (!p.TargetIndexes.empty()) { + project["targetIndexes"] = std::move(p.TargetIndexes); + } + + return project; +} + +Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s) +{ + Json::Value minimumCMakeVersion; + if (std::string const* def = + s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { + minimumCMakeVersion = Json::objectValue; + minimumCMakeVersion["string"] = *def; + } + return minimumCMakeVersion; +} + +Target::Target(cmGeneratorTarget* gt, std::string const& config) + : GT(gt) + , Config(config) + , TopSource(gt->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory()) + , TopBuild( + gt->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory()) + , SourceGroupsLocal(this->GT->Makefile->GetSourceGroups()) + , Backtraces(this->TopSource) +{ +} + +Json::Value Target::Dump() +{ + Json::Value target = Json::objectValue; + + cmStateEnums::TargetType const type = this->GT->GetType(); + + target["name"] = this->GT->GetName(); + target["type"] = cmState::GetTargetTypeName(type); + target["id"] = TargetId(this->GT, this->TopBuild); + target["paths"] = this->DumpPaths(); + if (this->GT->Target->GetIsGeneratorProvided()) { + target["isGeneratorProvided"] = true; + } + + this->AddBacktrace(target, this->GT->GetBacktrace()); + + if (this->GT->Target->GetHaveInstallRule()) { + target["install"] = this->DumpInstall(); + } + + if (this->GT->HaveWellDefinedOutputFiles()) { + Json::Value artifacts = this->DumpArtifacts(); + if (!artifacts.empty()) { + target["artifacts"] = std::move(artifacts); + } + } + + if (type == cmStateEnums::EXECUTABLE || + type == cmStateEnums::SHARED_LIBRARY || + type == cmStateEnums::MODULE_LIBRARY) { + target["nameOnDisk"] = this->GT->GetFullName(this->Config); + target["link"] = this->DumpLink(); + } else if (type == cmStateEnums::STATIC_LIBRARY) { + target["nameOnDisk"] = this->GT->GetFullName(this->Config); + target["archive"] = this->DumpArchive(); + } + + Json::Value dependencies = this->DumpDependencies(); + if (!dependencies.empty()) { + target["dependencies"] = dependencies; + } + + { + this->ProcessLanguages(); + + target["sources"] = this->DumpSources(); + + Json::Value folder = this->DumpFolder(); + if (!folder.isNull()) { + target["folder"] = std::move(folder); + } + + Json::Value sourceGroups = this->DumpSourceGroups(); + if (!sourceGroups.empty()) { + target["sourceGroups"] = std::move(sourceGroups); + } + + Json::Value compileGroups = this->DumpCompileGroups(); + if (!compileGroups.empty()) { + target["compileGroups"] = std::move(compileGroups); + } + } + + target["backtraceGraph"] = this->Backtraces.Dump(); + + return target; +} + +void Target::ProcessLanguages() +{ + std::set<std::string> languages; + this->GT->GetLanguages(languages, this->Config); + for (std::string const& lang : languages) { + this->ProcessLanguage(lang); + } +} + +void Target::ProcessLanguage(std::string const& lang) +{ + CompileData& cd = this->CompileDataMap[lang]; + cd.Language = lang; + if (const char* sysrootCompile = + this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { + cd.Sysroot = sysrootCompile; + } else if (const char* sysroot = + this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) { + cd.Sysroot = sysroot; + } + cmLocalGenerator* lg = this->GT->GetLocalGenerator(); + { + // FIXME: Add flags from end section of ExpandRuleVariable, + // which may need to be factored out. + std::string flags; + lg->GetTargetCompileFlags(this->GT, this->Config, lang, flags); + cd.Flags.emplace_back(std::move(flags), cmListFileBacktrace()); + } + std::set<BT<std::string>> defines = + lg->GetTargetDefines(this->GT, this->Config, lang); + cd.SetDefines(defines); + std::vector<BT<std::string>> includePathList = + lg->GetIncludeDirectories(this->GT, lang, this->Config); + for (BT<std::string> const& i : includePathList) { + cd.Includes.emplace_back( + i, this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang)); + } +} + +Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si) +{ + std::unordered_map<cmSourceGroup const*, Json::ArrayIndex>::iterator i = + this->SourceGroupsMap.find(sg); + if (i == this->SourceGroupsMap.end()) { + auto sgIndex = static_cast<Json::ArrayIndex>(this->SourceGroups.size()); + i = this->SourceGroupsMap.emplace(sg, sgIndex).first; + SourceGroup g; + g.Name = sg->GetFullName(); + this->SourceGroups.push_back(std::move(g)); + } + this->SourceGroups[i->second].SourceIndexes.append(si); + return i->second; +} + +CompileData Target::BuildCompileData(cmSourceFile* sf) +{ + CompileData fd; + + fd.Language = sf->GetLanguage(); + if (fd.Language.empty()) { + return fd; + } + CompileData const& cd = this->CompileDataMap.at(fd.Language); + + fd.Sysroot = cd.Sysroot; + + cmLocalGenerator* lg = this->GT->GetLocalGenerator(); + cmGeneratorExpressionInterpreter genexInterpreter(lg, this->Config, this->GT, + fd.Language); + + fd.Flags = cd.Flags; + const std::string COMPILE_FLAGS("COMPILE_FLAGS"); + if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) { + std::string flags = genexInterpreter.Evaluate(cflags, COMPILE_FLAGS); + fd.Flags.emplace_back(std::move(flags), cmListFileBacktrace()); + } + const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); + if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) { + std::string flags; + lg->AppendCompileOptions( + flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS)); + fd.Flags.emplace_back(std::move(flags), cmListFileBacktrace()); + } + + // Add include directories from source file properties. + { + std::vector<std::string> includes; + const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); + if (const char* cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) { + const std::string& evaluatedIncludes = + genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES); + lg->AppendIncludeDirectories(includes, evaluatedIncludes, *sf); + + for (std::string const& include : includes) { + bool const isSystemInclude = this->GT->IsSystemIncludeDirectory( + include, this->Config, fd.Language); + fd.Includes.emplace_back(include, isSystemInclude); + } + } + } + fd.Includes.insert(fd.Includes.end(), cd.Includes.begin(), + cd.Includes.end()); + + const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); + std::set<std::string> fileDefines; + if (const char* defs = sf->GetProperty(COMPILE_DEFINITIONS)) { + lg->AppendDefines(fileDefines, + genexInterpreter.Evaluate(defs, COMPILE_DEFINITIONS)); + } + + const std::string defPropName = + "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(this->Config); + if (const char* config_defs = sf->GetProperty(defPropName)) { + lg->AppendDefines( + fileDefines, + genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS)); + } + + std::set<BT<std::string>> defines; + defines.insert(fileDefines.begin(), fileDefines.end()); + defines.insert(cd.Defines.begin(), cd.Defines.end()); + + fd.SetDefines(defines); + + return fd; +} + +Json::ArrayIndex Target::AddSourceCompileGroup(cmSourceFile* sf, + Json::ArrayIndex si) +{ + Json::Value compileDataJson = + this->DumpCompileData(this->BuildCompileData(sf)); + std::map<Json::Value, Json::ArrayIndex>::iterator i = + this->CompileGroupMap.find(compileDataJson); + if (i == this->CompileGroupMap.end()) { + Json::ArrayIndex cgIndex = + static_cast<Json::ArrayIndex>(this->CompileGroups.size()); + i = + this->CompileGroupMap.emplace(std::move(compileDataJson), cgIndex).first; + CompileGroup g; + g.Entry = i; + this->CompileGroups.push_back(std::move(g)); + } + this->CompileGroups[i->second].SourceIndexes.append(si); + return i->second; +} + +void Target::AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt) +{ + Json::ArrayIndex backtrace; + if (this->Backtraces.Add(bt, backtrace)) { + object["backtrace"] = backtrace; + } +} + +Json::Value Target::DumpPaths() +{ + Json::Value paths = Json::objectValue; + cmLocalGenerator* lg = this->GT->GetLocalGenerator(); + + std::string const& sourceDir = lg->GetCurrentSourceDirectory(); + paths["source"] = RelativeIfUnder(this->TopSource, sourceDir); + + std::string const& buildDir = lg->GetCurrentBinaryDirectory(); + paths["build"] = RelativeIfUnder(this->TopBuild, buildDir); + + return paths; +} + +Json::Value Target::DumpSources() +{ + Json::Value sources = Json::arrayValue; + cmGeneratorTarget::KindedSources const& kinded = + this->GT->GetKindedSources(this->Config); + for (cmGeneratorTarget::SourceAndKind const& sk : kinded.Sources) { + sources.append(this->DumpSource(sk, sources.size())); + } + return sources; +} + +Json::Value Target::DumpSource(cmGeneratorTarget::SourceAndKind const& sk, + Json::ArrayIndex si) +{ + Json::Value source = Json::objectValue; + + std::string const path = sk.Source.Value->GetFullPath(); + source["path"] = RelativeIfUnder(this->TopSource, path); + if (sk.Source.Value->GetIsGenerated()) { + source["isGenerated"] = true; + } + this->AddBacktrace(source, sk.Source.Backtrace); + + if (cmSourceGroup* sg = + this->GT->Makefile->FindSourceGroup(path, this->SourceGroupsLocal)) { + source["sourceGroupIndex"] = this->AddSourceGroup(sg, si); + } + + switch (sk.Kind) { + case cmGeneratorTarget::SourceKindObjectSource: { + source["compileGroupIndex"] = + this->AddSourceCompileGroup(sk.Source.Value, si); + } break; + case cmGeneratorTarget::SourceKindAppManifest: + case cmGeneratorTarget::SourceKindCertificate: + case cmGeneratorTarget::SourceKindCustomCommand: + case cmGeneratorTarget::SourceKindExternalObject: + case cmGeneratorTarget::SourceKindExtra: + case cmGeneratorTarget::SourceKindHeader: + case cmGeneratorTarget::SourceKindIDL: + case cmGeneratorTarget::SourceKindManifest: + case cmGeneratorTarget::SourceKindModuleDefinition: + case cmGeneratorTarget::SourceKindResx: + case cmGeneratorTarget::SourceKindXaml: + break; + } + + return source; +} + +Json::Value Target::DumpCompileData(CompileData cd) +{ + Json::Value result = Json::objectValue; + + if (!cd.Language.empty()) { + result["language"] = cd.Language; + } + if (!cd.Sysroot.empty()) { + result["sysroot"] = this->DumpSysroot(cd.Sysroot); + } + if (!cd.Flags.empty()) { + result["compileCommandFragments"] = this->DumpCommandFragments(cd.Flags); + } + if (!cd.Includes.empty()) { + Json::Value includes = Json::arrayValue; + for (auto const& i : cd.Includes) { + includes.append(this->DumpInclude(i)); + } + result["includes"] = includes; + } + if (!cd.Defines.empty()) { + Json::Value defines = Json::arrayValue; + for (BT<std::string> const& d : cd.Defines) { + defines.append(this->DumpDefine(d)); + } + result["defines"] = std::move(defines); + } + + return result; +} + +Json::Value Target::DumpInclude(CompileData::IncludeEntry const& inc) +{ + Json::Value include = Json::objectValue; + include["path"] = inc.Path.Value; + if (inc.IsSystem) { + include["isSystem"] = true; + } + this->AddBacktrace(include, inc.Path.Backtrace); + return include; +} + +Json::Value Target::DumpDefine(BT<std::string> const& def) +{ + Json::Value define = Json::objectValue; + define["define"] = def.Value; + this->AddBacktrace(define, def.Backtrace); + return define; +} + +Json::Value Target::DumpSourceGroups() +{ + Json::Value sourceGroups = Json::arrayValue; + for (auto& sg : this->SourceGroups) { + sourceGroups.append(this->DumpSourceGroup(sg)); + } + return sourceGroups; +} + +Json::Value Target::DumpSourceGroup(SourceGroup& sg) +{ + Json::Value group = Json::objectValue; + group["name"] = sg.Name; + group["sourceIndexes"] = std::move(sg.SourceIndexes); + return group; +} + +Json::Value Target::DumpCompileGroups() +{ + Json::Value compileGroups = Json::arrayValue; + for (auto& cg : this->CompileGroups) { + compileGroups.append(this->DumpCompileGroup(cg)); + } + return compileGroups; +} + +Json::Value Target::DumpCompileGroup(CompileGroup& cg) +{ + Json::Value group = cg.Entry->first; + group["sourceIndexes"] = std::move(cg.SourceIndexes); + return group; +} + +Json::Value Target::DumpSysroot(std::string const& path) +{ + Json::Value sysroot = Json::objectValue; + sysroot["path"] = path; + return sysroot; +} + +Json::Value Target::DumpInstall() +{ + Json::Value install = Json::objectValue; + install["prefix"] = this->DumpInstallPrefix(); + install["destinations"] = this->DumpInstallDestinations(); + return install; +} + +Json::Value Target::DumpInstallPrefix() +{ + Json::Value prefix = Json::objectValue; + std::string p = + this->GT->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); + cmSystemTools::ConvertToUnixSlashes(p); + prefix["path"] = p; + return prefix; +} + +Json::Value Target::DumpInstallDestinations() +{ + Json::Value destinations = Json::arrayValue; + auto installGens = this->GT->Makefile->GetInstallGenerators(); + for (auto iGen : installGens) { + auto itGen = dynamic_cast<cmInstallTargetGenerator*>(iGen); + if (itGen != nullptr && itGen->GetTarget() == this->GT) { + destinations.append(this->DumpInstallDestination(itGen)); + } + } + return destinations; +} + +Json::Value Target::DumpInstallDestination(cmInstallTargetGenerator* itGen) +{ + Json::Value destination = Json::objectValue; + destination["path"] = itGen->GetDestination(this->Config); + this->AddBacktrace(destination, itGen->GetBacktrace()); + return destination; +} + +Json::Value Target::DumpArtifacts() +{ + Json::Value artifacts = Json::arrayValue; + + // Object libraries have only object files as artifacts. + if (this->GT->GetType() == cmStateEnums::OBJECT_LIBRARY) { + if (!this->GT->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) { + return artifacts; + } + std::vector<cmSourceFile const*> objectSources; + this->GT->GetObjectSources(objectSources, this->Config); + std::string const obj_dir = this->GT->GetObjectDirectory(this->Config); + for (cmSourceFile const* sf : objectSources) { + const std::string& obj = this->GT->GetObjectName(sf); + Json::Value artifact = Json::objectValue; + artifact["path"] = RelativeIfUnder(this->TopBuild, obj_dir + obj); + artifacts.append(std::move(artifact)); // NOLINT(*) + } + return artifacts; + } + + // Other target types always have a "main" artifact. + { + Json::Value artifact = Json::objectValue; + artifact["path"] = + RelativeIfUnder(this->TopBuild, + this->GT->GetFullPath( + this->Config, cmStateEnums::RuntimeBinaryArtifact)); + artifacts.append(std::move(artifact)); // NOLINT(*) + } + + // Add Windows-specific artifacts produced by the linker. + if (this->GT->IsDLLPlatform() && + this->GT->GetType() != cmStateEnums::STATIC_LIBRARY) { + if (this->GT->GetType() == cmStateEnums::SHARED_LIBRARY || + this->GT->IsExecutableWithExports()) { + Json::Value artifact = Json::objectValue; + artifact["path"] = + RelativeIfUnder(this->TopBuild, + this->GT->GetFullPath( + this->Config, cmStateEnums::ImportLibraryArtifact)); + artifacts.append(std::move(artifact)); // NOLINT(*) + } + cmGeneratorTarget::OutputInfo const* output = + this->GT->GetOutputInfo(this->Config); + if (output && !output->PdbDir.empty()) { + Json::Value artifact = Json::objectValue; + artifact["path"] = RelativeIfUnder(this->TopBuild, + output->PdbDir + '/' + + this->GT->GetPDBName(this->Config)); + artifacts.append(std::move(artifact)); // NOLINT(*) + } + } + return artifacts; +} + +Json::Value Target::DumpLink() +{ + Json::Value link = Json::objectValue; + std::string lang = this->GT->GetLinkerLanguage(this->Config); + link["language"] = lang; + { + Json::Value commandFragments = this->DumpLinkCommandFragments(); + if (!commandFragments.empty()) { + link["commandFragments"] = std::move(commandFragments); + } + } + if (const char* sysrootLink = + this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) { + link["sysroot"] = this->DumpSysroot(sysrootLink); + } else if (const char* sysroot = + this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) { + link["sysroot"] = this->DumpSysroot(sysroot); + } + if (this->GT->IsIPOEnabled(lang, this->Config)) { + link["lto"] = true; + } + return link; +} + +Json::Value Target::DumpArchive() +{ + Json::Value archive = Json::objectValue; + { + // The "link" fragments not relevant to static libraries are empty. + Json::Value commandFragments = this->DumpLinkCommandFragments(); + if (!commandFragments.empty()) { + archive["commandFragments"] = std::move(commandFragments); + } + } + std::string lang = this->GT->GetLinkerLanguage(this->Config); + if (this->GT->IsIPOEnabled(lang, this->Config)) { + archive["lto"] = true; + } + return archive; +} + +Json::Value Target::DumpLinkCommandFragments() +{ + Json::Value linkFragments = Json::arrayValue; + + std::string linkLanguageFlags; + std::string linkFlags; + std::string frameworkPath; + std::string linkPath; + std::string linkLibs; + cmLocalGenerator* lg = this->GT->GetLocalGenerator(); + cmLinkLineComputer linkLineComputer(lg, + lg->GetStateSnapshot().GetDirectory()); + lg->GetTargetFlags(&linkLineComputer, this->Config, linkLibs, + linkLanguageFlags, linkFlags, frameworkPath, linkPath, + this->GT); + linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags); + linkFlags = cmSystemTools::TrimWhitespace(linkFlags); + frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath); + linkPath = cmSystemTools::TrimWhitespace(linkPath); + linkLibs = cmSystemTools::TrimWhitespace(linkLibs); + + if (!linkLanguageFlags.empty()) { + linkFragments.append( + this->DumpCommandFragment(std::move(linkLanguageFlags), "flags")); + } + + if (!linkFlags.empty()) { + linkFragments.append( + this->DumpCommandFragment(std::move(linkFlags), "flags")); + } + + if (!frameworkPath.empty()) { + linkFragments.append( + this->DumpCommandFragment(std::move(frameworkPath), "frameworkPath")); + } + + if (!linkPath.empty()) { + linkFragments.append( + this->DumpCommandFragment(std::move(linkPath), "libraryPath")); + } + + if (!linkLibs.empty()) { + linkFragments.append( + this->DumpCommandFragment(std::move(linkLibs), "libraries")); + } + + return linkFragments; +} + +Json::Value Target::DumpCommandFragments( + std::vector<BT<std::string>> const& frags) +{ + Json::Value commandFragments = Json::arrayValue; + for (BT<std::string> const& f : frags) { + commandFragments.append(this->DumpCommandFragment(f)); + } + return commandFragments; +} + +Json::Value Target::DumpCommandFragment(BT<std::string> const& frag, + std::string const& role) +{ + Json::Value fragment = Json::objectValue; + fragment["fragment"] = frag.Value; + if (!role.empty()) { + fragment["role"] = role; + } + this->AddBacktrace(fragment, frag.Backtrace); + return fragment; +} + +Json::Value Target::DumpDependencies() +{ + Json::Value dependencies = Json::arrayValue; + cmGlobalGenerator* gg = this->GT->GetGlobalGenerator(); + for (cmTargetDepend const& td : gg->GetTargetDirectDepends(this->GT)) { + dependencies.append(this->DumpDependency(td)); + } + return dependencies; +} + +Json::Value Target::DumpDependency(cmTargetDepend const& td) +{ + Json::Value dependency = Json::objectValue; + dependency["id"] = TargetId(td, this->TopBuild); + this->AddBacktrace(dependency, td.GetBacktrace()); + return dependency; +} + +Json::Value Target::DumpFolder() +{ + Json::Value folder; + if (const char* f = this->GT->GetProperty("FOLDER")) { + folder = Json::objectValue; + folder["name"] = f; + } + return folder; +} +} + +Json::Value cmFileAPICodemodelDump(cmFileAPI& fileAPI, unsigned long version) +{ + Codemodel codemodel(fileAPI, version); + return codemodel.Dump(); +} diff --git a/Source/cmFileAPICodemodel.h b/Source/cmFileAPICodemodel.h new file mode 100644 index 000000000..ffbd92863 --- /dev/null +++ b/Source/cmFileAPICodemodel.h @@ -0,0 +1,15 @@ +/* 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 + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_jsoncpp_value.h" + +class cmFileAPI; + +extern Json::Value cmFileAPICodemodelDump(cmFileAPI& fileAPI, + unsigned long version); + +#endif diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 5d34b7114..0f911c170 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -10,12 +10,14 @@ #include <algorithm> #include <assert.h> +#include <cmath> #include <ctype.h> #include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <utility> #include <vector> #include "cmAlgorithms.h" @@ -30,6 +32,7 @@ #include "cmInstallType.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSystemTools.h" #include "cmTimestamp.h" @@ -176,6 +179,15 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args, if (subCommand == "LOCK") { return this->HandleLockCommand(args); } + if (subCommand == "SIZE") { + return this->HandleSizeCommand(args); + } + if (subCommand == "READ_SYMLINK") { + return this->HandleReadSymlinkCommand(args); + } + if (subCommand == "CREATE_LINK") { + return this->HandleCreateLinkCommand(args); + } std::string e = "does not recognize sub-command " + subCommand; this->SetError(e); @@ -213,7 +225,7 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args, // Set permissions to writable if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) { #if defined(_MSC_VER) || defined(__MINGW32__) - writable = mode & S_IWRITE; + writable = (mode & S_IWRITE) != 0; mode_t newMode = mode | S_IWRITE; #else writable = mode & S_IWUSR; @@ -549,7 +561,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) if (hex_conversion_enabled) { // TODO: should work without temp file, but just on a memory buffer std::string binaryFileName = this->Makefile->GetCurrentBinaryDirectory(); - binaryFileName += cmake::GetCMakeFilesDirectory(); + binaryFileName += "/CMakeFiles"; binaryFileName += "/FileCommandStringsBinaryFile"; if (cmHexFileConverter::TryConvert(fileName.c_str(), binaryFileName.c_str())) { @@ -826,13 +838,13 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, // Generated build system depends on glob results if (!configureDepends && warnConfigureLate) { this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, "CONFIGURE_DEPENDS flag was given after a glob expression was " "already evaluated."); } if (workingMode != cmake::NORMAL_MODE) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "CONFIGURE_DEPENDS is invalid for script and find package modes."); return false; } @@ -863,12 +875,12 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, for (cmsys::Glob::Message const& globMessage : globMessages) { if (globMessage.type == cmsys::Glob::cyclicRecursion) { this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, "Cyclic recursion detected while globbing for '" + *i + "':\n" + globMessage.content); } else { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Error has occurred while globbing for '" + *i + "' - " + globMessage.content); shouldExit = true; @@ -917,7 +929,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, // symlinks without being explicitly asked to: warn the author. if (warnFollowedSymlinks) { this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0009)); } break; @@ -1067,7 +1079,7 @@ struct cmFileCopier , Doing(DoingNone) { } - virtual ~cmFileCopier() {} + virtual ~cmFileCopier() = default; bool Run(std::vector<std::string> const& args); @@ -1088,13 +1100,8 @@ protected: // Properties set by pattern and regex match rules. struct MatchProperties { - bool Exclude; - mode_t Permissions; - MatchProperties() - : Exclude(false) - , Permissions(0) - { - } + bool Exclude = false; + mode_t Permissions = 0; }; struct MatchRule { @@ -2453,7 +2460,7 @@ bool cmFileCommand::HandleRename(std::vector<std::string> const& args) newname += "/" + args[2]; } - if (!cmSystemTools::RenameFile(oldname.c_str(), newname.c_str())) { + if (!cmSystemTools::RenameFile(oldname, newname)) { std::string err = cmSystemTools::GetLastSystemError(); std::ostringstream e; /* clang-format off */ @@ -2525,7 +2532,7 @@ bool cmFileCommand::HandleCMakePathCommand( // remove double quotes in the path std::string& s = *j; - if (s.size() > 1 && s[0] == '\"' && s[s.size() - 1] == '\"') { + if (s.size() > 1 && s.front() == '\"' && s.back() == '\"') { s = s.substr(1, s.size() - 2); } } @@ -2602,10 +2609,10 @@ public: bool UpdatePercentage(double value, double total, std::string& status) { - int OldPercentage = this->CurrentPercentage; + long OldPercentage = this->CurrentPercentage; if (total > 0.0) { - this->CurrentPercentage = static_cast<int>(value / total * 100.0 + 0.5); + this->CurrentPercentage = std::lround(value / total * 100.0); if (this->CurrentPercentage > 100) { // Avoid extra progress reports for unexpected data beyond total. this->CurrentPercentage = 100; @@ -2627,7 +2634,7 @@ public: cmFileCommand* GetFileCommand() { return this->FileCommand; } private: - int CurrentPercentage; + long CurrentPercentage; cmFileCommand* FileCommand; std::string Text; }; @@ -2695,12 +2702,14 @@ private: #endif #define check_curl_result(result, errstr) \ - if (result != CURLE_OK) { \ - std::string e(errstr); \ - e += ::curl_easy_strerror(result); \ - this->SetError(e); \ - return false; \ - } + do { \ + if (result != CURLE_OK) { \ + std::string e(errstr); \ + e += ::curl_easy_strerror(result); \ + this->SetError(e); \ + return false; \ + } \ + } while (false) bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) { @@ -2824,7 +2833,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) std::string algo = i->substr(0, pos); expectedHash = cmSystemTools::LowerCase(i->substr(pos + 1)); hash = std::unique_ptr<cmCryptoHash>(cmCryptoHash::New(algo.c_str())); - if (!hash.get()) { + if (!hash) { std::string err = "DOWNLOAD EXPECTED_HASH given unknown ALGO: "; err += algo; this->SetError(err); @@ -2849,7 +2858,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) // Do not return error for compatibility reason. std::string err = "Unexpected argument: "; err += *i; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, err); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, err); } ++i; } @@ -3161,7 +3170,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) // Do not return error for compatibility reason. std::string err = "Unexpected argument: "; err += *i; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, err); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, err); } ++i; @@ -3415,7 +3424,8 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) // Parse arguments if (args.size() < 2) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "sub-command LOCK requires at least two arguments."); + MessageType::FATAL_ERROR, + "sub-command LOCK requires at least two arguments."); return false; } @@ -3429,7 +3439,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) ++i; const char* merr = "expected FUNCTION, FILE or PROCESS after GUARD"; if (i >= args.size()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, merr); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, merr); return false; } if (args[i] == "FUNCTION") { @@ -3441,7 +3451,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) } else { std::ostringstream e; e << merr << ", but got:\n \"" << args[i] << "\"."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -3449,14 +3459,15 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) ++i; if (i >= args.size()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "expected variable name after RESULT_VARIABLE"); + MessageType::FATAL_ERROR, + "expected variable name after RESULT_VARIABLE"); return false; } resultVariable = args[i]; } else if (args[i] == "TIMEOUT") { ++i; if (i >= args.size()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "expected timeout value after TIMEOUT"); return false; } @@ -3465,7 +3476,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) scanned < 0) { std::ostringstream e; e << "TIMEOUT value \"" << args[i] << "\" is not an unsigned integer."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } timeout = static_cast<unsigned long>(scanned); @@ -3473,7 +3484,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) std::ostringstream e; e << "expected DIRECTORY, RELEASE, GUARD, RESULT_VARIABLE or TIMEOUT\n"; e << "but got: \"" << args[i] << "\"."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } } @@ -3495,7 +3506,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) std::ostringstream e; e << "directory\n \"" << parentDir << "\"\ncreation failed "; e << "(check permissions)."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -3503,7 +3514,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) if (!file) { std::ostringstream e; e << "file\n \"" << path << "\"\ncreation failed (check permissions)."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -3538,7 +3549,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) if (resultVariable.empty() && !fileLockResult.IsOk()) { std::ostringstream e; e << "error locking file\n \"" << path << "\"\n" << result << "."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -3597,3 +3608,174 @@ bool cmFileCommand::HandleTimestampCommand( return true; } + +bool cmFileCommand::HandleSizeCommand(std::vector<std::string> const& args) +{ + if (args.size() != 3) { + std::ostringstream e; + e << args[0] << " requires a file name and output variable"; + this->SetError(e.str()); + return false; + } + + unsigned int argsIndex = 1; + + const std::string& filename = args[argsIndex++]; + + const std::string& outputVariable = args[argsIndex++]; + + if (!cmSystemTools::FileExists(filename, true)) { + std::ostringstream e; + e << "SIZE requested of path that is not readable:\n " << filename; + this->SetError(e.str()); + return false; + } + + this->Makefile->AddDefinition( + outputVariable, + std::to_string(cmSystemTools::FileLength(filename)).c_str()); + + return true; +} + +bool cmFileCommand::HandleReadSymlinkCommand( + std::vector<std::string> const& args) +{ + if (args.size() != 3) { + std::ostringstream e; + e << args[0] << " requires a file name and output variable"; + this->SetError(e.str()); + return false; + } + + const std::string& filename = args[1]; + const std::string& outputVariable = args[2]; + + std::string result; + if (!cmSystemTools::ReadSymlink(filename, result)) { + std::ostringstream e; + e << "READ_SYMLINK requested of path that is not a symlink:\n " + << filename; + this->SetError(e.str()); + return false; + } + + this->Makefile->AddDefinition(outputVariable, result.c_str()); + + return true; +} + +bool cmFileCommand::HandleCreateLinkCommand( + std::vector<std::string> const& args) +{ + if (args.size() < 3) { + this->SetError("CREATE_LINK must be called with at least two additional " + "arguments"); + return false; + } + + cmCommandArgumentsHelper argHelper; + cmCommandArgumentGroup group; + + cmCAString linkArg(&argHelper, "CREATE_LINK"); + cmCAString fileArg(&argHelper, nullptr); + cmCAString newFileArg(&argHelper, nullptr); + + cmCAString resultArg(&argHelper, "RESULT", &group); + cmCAEnabler copyOnErrorArg(&argHelper, "COPY_ON_ERROR", &group); + cmCAEnabler symbolicArg(&argHelper, "SYMBOLIC", &group); + + linkArg.Follows(nullptr); + fileArg.Follows(&linkArg); + newFileArg.Follows(&fileArg); + group.Follows(&newFileArg); + + std::vector<std::string> unconsumedArgs; + argHelper.Parse(&args, &unconsumedArgs); + + if (!unconsumedArgs.empty()) { + this->SetError("unknown argument: \"" + unconsumedArgs.front() + '\"'); + return false; + } + + std::string fileName = fileArg.GetString(); + std::string newFileName = newFileArg.GetString(); + + // Output variable for storing the result. + const std::string& resultVar = resultArg.GetString(); + + // The system error message generated in the operation. + std::string result; + + // Check if the paths are distinct. + if (fileName == newFileName) { + result = "CREATE_LINK cannot use same file and newfile"; + if (!resultVar.empty()) { + this->Makefile->AddDefinition(resultVar, result.c_str()); + return true; + } + this->SetError(result); + return false; + } + + // Hard link requires original file to exist. + if (!symbolicArg.IsEnabled() && !cmSystemTools::FileExists(fileName)) { + result = "Cannot hard link \'" + fileName + "\' as it does not exist."; + if (!resultVar.empty()) { + this->Makefile->AddDefinition(resultVar, result.c_str()); + return true; + } + this->SetError(result); + return false; + } + + // Check if the new file already exists and remove it. + if ((cmSystemTools::FileExists(newFileName) || + cmSystemTools::FileIsSymlink(newFileName)) && + !cmSystemTools::RemoveFile(newFileName)) { + std::ostringstream e; + e << "Failed to create link '" << newFileName + << "' because existing path cannot be removed: " + << cmSystemTools::GetLastSystemError() << "\n"; + + if (!resultVar.empty()) { + this->Makefile->AddDefinition(resultVar, e.str().c_str()); + return true; + } + this->SetError(e.str()); + return false; + } + + // Whether the operation completed successfully. + bool completed = false; + + // Check if the command requires a symbolic link. + if (symbolicArg.IsEnabled()) { + completed = cmSystemTools::CreateSymlink(fileName, newFileName, &result); + } else { + completed = cmSystemTools::CreateLink(fileName, newFileName, &result); + } + + // Check if copy-on-error is enabled in the arguments. + if (!completed && copyOnErrorArg.IsEnabled()) { + completed = cmSystemTools::cmCopyFile(fileName, newFileName); + if (!completed) { + result = "Copy failed: " + cmSystemTools::GetLastSystemError(); + } + } + + // Check if the operation was successful. + if (completed) { + result = "0"; + } else if (resultVar.empty()) { + // The operation failed and the result is not reported in a variable. + this->SetError(result); + return false; + } + + if (!resultVar.empty()) { + this->Makefile->AddDefinition(resultVar, result.c_str()); + } + + return true; +} diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 719dca29e..12c511514 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -59,6 +59,9 @@ protected: bool HandleTimestampCommand(std::vector<std::string> const& args); bool HandleGenerateCommand(std::vector<std::string> const& args); bool HandleLockCommand(std::vector<std::string> const& args); + bool HandleSizeCommand(std::vector<std::string> const& args); + bool HandleReadSymlinkCommand(std::vector<std::string> const& args); + bool HandleCreateLinkCommand(std::vector<std::string> const& args); private: void AddEvaluationFile(const std::string& inputName, diff --git a/Source/cmFileLock.h b/Source/cmFileLock.h index 6c9a7b86f..2130d65db 100644 --- a/Source/cmFileLock.h +++ b/Source/cmFileLock.h @@ -21,12 +21,13 @@ class cmFileLockResult; */ class cmFileLock { - CM_DISABLE_COPY(cmFileLock) - public: cmFileLock(); ~cmFileLock(); + cmFileLock(cmFileLock const&) = delete; + cmFileLock& operator=(cmFileLock const&) = delete; + /** * @brief Lock the file. * @param timeoutSec Lock timeout. If -1 try until success or fatal error. @@ -51,14 +52,13 @@ private: cmFileLockResult LockWithTimeout(unsigned long timeoutSec); #if defined(_WIN32) - typedef HANDLE FileId; + HANDLE File = INVALID_HANDLE_VALUE; BOOL LockFile(DWORD flags); #else - typedef int FileId; + int File = -1; int LockFile(int cmd, int type); #endif - FileId File; std::string Filename; }; diff --git a/Source/cmFileLockPool.cxx b/Source/cmFileLockPool.cxx index 5dc9243a1..d700a79c3 100644 --- a/Source/cmFileLockPool.cxx +++ b/Source/cmFileLockPool.cxx @@ -8,9 +8,7 @@ #include "cmFileLock.h" #include "cmFileLockResult.h" -cmFileLockPool::cmFileLockPool() -{ -} +cmFileLockPool::cmFileLockPool() = default; cmFileLockPool::~cmFileLockPool() { @@ -111,9 +109,7 @@ bool cmFileLockPool::IsAlreadyLocked(const std::string& filename) const return this->ProcessScope.IsAlreadyLocked(filename); } -cmFileLockPool::ScopePool::ScopePool() -{ -} +cmFileLockPool::ScopePool::ScopePool() = default; cmFileLockPool::ScopePool::~ScopePool() { diff --git a/Source/cmFileLockPool.h b/Source/cmFileLockPool.h index 0197354c3..41203baac 100644 --- a/Source/cmFileLockPool.h +++ b/Source/cmFileLockPool.h @@ -13,12 +13,13 @@ class cmFileLockResult; class cmFileLockPool { - CM_DISABLE_COPY(cmFileLockPool) - public: cmFileLockPool(); ~cmFileLockPool(); + cmFileLockPool(cmFileLockPool const&) = delete; + cmFileLockPool& operator=(cmFileLockPool const&) = delete; + //@{ /** * @brief Function scope control. @@ -58,12 +59,13 @@ private: class ScopePool { - CM_DISABLE_COPY(ScopePool) - public: ScopePool(); ~ScopePool(); + ScopePool(ScopePool const&) = delete; + ScopePool& operator=(ScopePool const&) = delete; + cmFileLockResult Lock(const std::string& filename, unsigned long timeoutSec); cmFileLockResult Release(const std::string& filename); diff --git a/Source/cmFileLockUnix.cxx b/Source/cmFileLockUnix.cxx index 7353b01fc..1bf5013ad 100644 --- a/Source/cmFileLockUnix.cxx +++ b/Source/cmFileLockUnix.cxx @@ -8,10 +8,7 @@ #include <stdio.h> // SEEK_SET #include <unistd.h> -cmFileLock::cmFileLock() - : File(-1) -{ -} +cmFileLock::cmFileLock() = default; cmFileLockResult cmFileLock::Release() { diff --git a/Source/cmFileLockWin32.cxx b/Source/cmFileLockWin32.cxx index 51ac24993..a61d360ab 100644 --- a/Source/cmFileLockWin32.cxx +++ b/Source/cmFileLockWin32.cxx @@ -6,7 +6,6 @@ #include <windows.h> // CreateFileW cmFileLock::cmFileLock() - : File(INVALID_HANDLE_VALUE) { } diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx index b36ac7805..56ee739b0 100644 --- a/Source/cmFileMonitor.cxx +++ b/Source/cmFileMonitor.cxx @@ -19,7 +19,6 @@ void on_fs_close(uv_handle_t* handle); class cmIBaseWatcher { public: - cmIBaseWatcher() = default; virtual ~cmIBaseWatcher() = default; virtual void Trigger(const std::string& pathSegment, int events, @@ -150,11 +149,6 @@ public: p->AddChildWatcher(ps, this); } - ~cmRealDirectoryWatcher() override - { - // Handle is freed via uv_handle_close callback! - } - void StartWatching() final { if (!this->Handle) { diff --git a/Source/cmFileMonitor.h b/Source/cmFileMonitor.h index 632e7514f..7ffc9294e 100644 --- a/Source/cmFileMonitor.h +++ b/Source/cmFileMonitor.h @@ -14,12 +14,14 @@ class cmRootWatcher; class cmFileMonitor { - CM_DISABLE_COPY(cmFileMonitor) public: cmFileMonitor(uv_loop_t* l); ~cmFileMonitor(); + cmFileMonitor(cmFileMonitor const&) = delete; + cmFileMonitor& operator=(cmFileMonitor const&) = delete; + using Callback = std::function<void(const std::string&, int, int)>; void MonitorPaths(const std::vector<std::string>& paths, Callback const& cb); void StopMonitoring(); diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx index f84360e7f..2cffa7c5b 100644 --- a/Source/cmFilePathChecksum.cxx +++ b/Source/cmFilePathChecksum.cxx @@ -9,9 +9,7 @@ #include <vector> -cmFilePathChecksum::cmFilePathChecksum() -{ -} +cmFilePathChecksum::cmFilePathChecksum() = default; cmFilePathChecksum::cmFilePathChecksum(std::string const& currentSrcDir, std::string const& currentBinDir, diff --git a/Source/cmFileTimeComparison.cxx b/Source/cmFileTimeComparison.cxx index 8f6993d1e..8b3911e4b 100644 --- a/Source/cmFileTimeComparison.cxx +++ b/Source/cmFileTimeComparison.cxx @@ -21,9 +21,10 @@ class cmFileTimeComparisonInternal { public: // Internal comparison method. - inline bool FileTimeCompare(const char* f1, const char* f2, int* result); + inline bool FileTimeCompare(const std::string& f1, const std::string& f2, + int* result); - bool FileTimesDiffer(const char* f1, const char* f2); + bool FileTimesDiffer(const std::string& f1, const std::string& f2); private: typedef std::unordered_map<std::string, cmFileTimeComparison_Type> @@ -31,14 +32,14 @@ private: FileStatsMap Files; // Internal methods to lookup and compare modification times. - inline bool Stat(const char* fname, cmFileTimeComparison_Type* st); + inline bool Stat(const std::string& fname, cmFileTimeComparison_Type* st); inline int Compare(cmFileTimeComparison_Type* st1, cmFileTimeComparison_Type* st2); inline bool TimesDiffer(cmFileTimeComparison_Type* st1, cmFileTimeComparison_Type* st2); }; -bool cmFileTimeComparisonInternal::Stat(const char* fname, +bool cmFileTimeComparisonInternal::Stat(const std::string& fname, cmFileTimeComparison_Type* st) { // Use the stored time if available. @@ -51,7 +52,7 @@ bool cmFileTimeComparisonInternal::Stat(const char* fname, #if !defined(_WIN32) || defined(__CYGWIN__) // POSIX version. Use the stat function. - int res = ::stat(fname, st); + int res = ::stat(fname.c_str(), st); if (res != 0) { return false; } @@ -83,13 +84,14 @@ cmFileTimeComparison::~cmFileTimeComparison() delete this->Internals; } -bool cmFileTimeComparison::FileTimeCompare(const char* f1, const char* f2, - int* result) +bool cmFileTimeComparison::FileTimeCompare(const std::string& f1, + const std::string& f2, int* result) { return this->Internals->FileTimeCompare(f1, f2, result); } -bool cmFileTimeComparison::FileTimesDiffer(const char* f1, const char* f2) +bool cmFileTimeComparison::FileTimesDiffer(const std::string& f1, + const std::string& f2) { return this->Internals->FileTimesDiffer(f1, f2); } @@ -199,8 +201,9 @@ bool cmFileTimeComparisonInternal::TimesDiffer(cmFileTimeComparison_Type* s1, #endif } -bool cmFileTimeComparisonInternal::FileTimeCompare(const char* f1, - const char* f2, int* result) +bool cmFileTimeComparisonInternal::FileTimeCompare(const std::string& f1, + const std::string& f2, + int* result) { // Get the modification time for each file. cmFileTimeComparison_Type s1; @@ -215,8 +218,8 @@ bool cmFileTimeComparisonInternal::FileTimeCompare(const char* f1, return false; } -bool cmFileTimeComparisonInternal::FileTimesDiffer(const char* f1, - const char* f2) +bool cmFileTimeComparisonInternal::FileTimesDiffer(const std::string& f1, + const std::string& f2) { // Get the modification time for each file. cmFileTimeComparison_Type s1; diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h index 114989b51..5f74e3499 100644 --- a/Source/cmFileTimeComparison.h +++ b/Source/cmFileTimeComparison.h @@ -5,6 +5,8 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <string> + class cmFileTimeComparisonInternal; /** \class cmFileTimeComparison @@ -24,13 +26,14 @@ public: * When true is returned, result has -1, 0, +1 for * f1 older, same, or newer than f2. */ - bool FileTimeCompare(const char* f1, const char* f2, int* result); + bool FileTimeCompare(const std::string& f1, const std::string& f2, + int* result); /** * Compare file modification times. Return true unless both files * exist and have modification times less than 1 second apart. */ - bool FileTimesDiffer(const char* f1, const char* f2); + bool FileTimesDiffer(const std::string& f1, const std::string& f2); protected: cmFileTimeComparisonInternal* Internals; diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 865595b79..425546a83 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -129,13 +129,13 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) this->VariableDocumentation += "the (unknown) library be found"; } else if (this->Names.size() == 1) { this->VariableDocumentation += - "the " + this->Names[0] + " library be found"; + "the " + this->Names.front() + " library be found"; } else { this->VariableDocumentation += "one of the "; this->VariableDocumentation += cmJoin(cmMakeRange(this->Names).retreat(1), ", "); this->VariableDocumentation += - " or " + this->Names[this->Names.size() - 1] + " libraries be found"; + " or " + this->Names.back() + " libraries be found"; } } diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index fbaacfcf5..78be64e09 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -48,9 +48,7 @@ cmFindCommon::cmFindCommon() this->InitializeSearchPathGroups(); } -cmFindCommon::~cmFindCommon() -{ -} +cmFindCommon::~cmFindCommon() = default; void cmFindCommon::InitializeSearchPathGroups() { @@ -178,13 +176,13 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) cmSystemTools::ExpandListArgument(rootPath, roots); } if (sysrootCompile) { - roots.push_back(sysrootCompile); + roots.emplace_back(sysrootCompile); } if (sysrootLink) { - roots.push_back(sysrootLink); + roots.emplace_back(sysrootLink); } if (sysroot) { - roots.push_back(sysroot); + roots.emplace_back(sysroot); } for (std::string& r : roots) { cmSystemTools::ConvertToUnixSlashes(r); @@ -293,13 +291,13 @@ void cmFindCommon::AddPathSuffix(std::string const& arg) if (suffix.empty()) { return; } - if (suffix[0] == '/') { + if (suffix.front() == '/') { suffix = suffix.substr(1); } if (suffix.empty()) { return; } - if (suffix[suffix.size() - 1] == '/') { + if (suffix.back() == '/') { suffix = suffix.substr(0, suffix.size() - 1); } if (suffix.empty()) { diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 1e1ab147f..73d602de7 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -7,6 +7,7 @@ #include <set> #include <stdio.h> #include <string.h> +#include <utility> #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -198,13 +199,9 @@ struct cmFindLibraryHelper // Current names under consideration. struct Name { - bool TryRaw; + bool TryRaw = false; std::string Raw; cmsys::RegularExpression Regex; - Name() - : TryRaw(false) - { - } }; std::vector<Name> Names; diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 96de6adce..c2e0712ff 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -21,12 +21,12 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSearchPath.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmVersion.h" -#include "cmake.h" #if defined(__HAIKU__) # include <FindDirectory.h> @@ -95,6 +95,7 @@ cmFindPackageCommand::cmFindPackageCommand() this->UseLib32Paths = false; this->UseLib64Paths = false; this->UseLibx32Paths = false; + this->UseRealPath = false; this->PolicyScope = true; this->VersionMajor = 0; this->VersionMinor = 0; @@ -111,6 +112,8 @@ cmFindPackageCommand::cmFindPackageCommand() this->SortOrder = None; this->SortDirection = Asc; this->AppendSearchPathGroups(); + + this->DeprecatedFindModules["Qt"] = cmPolicies::CMP0084; } void cmFindPackageCommand::AppendSearchPathGroups() @@ -193,6 +196,11 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, this->NoSystemRegistry = true; } + // Check whether we should resolve symlinks when finding packages + if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS")) { + this->UseRealPath = true; + } + // Check if Sorting should be enabled if (const char* so = this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) { @@ -382,7 +390,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, if (this->Version.empty() && this->VersionExact) { this->VersionExact = false; this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, "Ignoring EXACT since no version is requested."); + MessageType::AUTHOR_WARNING, + "Ignoring EXACT since no version is requested."); } if (this->Version.empty() || components.empty()) { @@ -471,7 +480,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0074)); break; case cmPolicies::NEW: { @@ -534,7 +543,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, } aw << "\n" "(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this warning.)"; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, aw.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str()); } // No find module. Assume the project has a CMake config file. Use @@ -653,15 +662,38 @@ bool cmFindPackageCommand::FindModule(bool& found) std::string module = "Find"; module += this->Name; module += ".cmake"; - std::string mfile = this->Makefile->GetModulesFile(module.c_str()); + bool system = false; + std::string mfile = this->Makefile->GetModulesFile(module, system); if (!mfile.empty()) { + if (system) { + auto it = this->DeprecatedFindModules.find(this->Name); + if (it != this->DeprecatedFindModules.end()) { + cmPolicies::PolicyStatus status = + this->Makefile->GetPolicyStatus(it->second); + switch (status) { + case cmPolicies::WARN: { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(it->second) << "\n"; + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + CM_FALLTHROUGH; + } + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + return true; + } + } + } + // Load the module we found, and set "<name>_FIND_MODULE" to true // while inside it. found = true; std::string var = this->Name; var += "_FIND_MODULE"; this->Makefile->AddDefinition(var, "1"); - bool result = this->ReadListFile(mfile.c_str(), DoPolicyScope); + bool result = this->ReadListFile(mfile, DoPolicyScope); this->Makefile->RemoveDefinition(var); return result; } @@ -711,7 +743,8 @@ bool cmFindPackageCommand::HandlePackageMode() // Sanity check. if (fileFound && this->FileFound.empty()) { this->Makefile->IssueMessage( - cmake::INTERNAL_ERROR, "fileFound is true but FileFound is empty!"); + MessageType::INTERNAL_ERROR, + "fileFound is true but FileFound is empty!"); fileFound = false; } } @@ -743,7 +776,7 @@ bool cmFindPackageCommand::HandlePackageMode() this->StoreVersionFound(); // Parse the configuration file. - if (this->ReadListFile(this->FileFound.c_str(), DoPolicyScope)) { + if (this->ReadListFile(this->FileFound, DoPolicyScope)) { // The package has been found. found = true; @@ -862,14 +895,15 @@ bool cmFindPackageCommand::HandlePackageMode() } } - this->Makefile->IssueMessage( - this->Required ? cmake::FATAL_ERROR : cmake::WARNING, e.str()); + this->Makefile->IssueMessage(this->Required ? MessageType::FATAL_ERROR + : MessageType::WARNING, + e.str()); if (this->Required) { cmSystemTools::SetFatalErrorOccured(); } if (!aw.str().empty()) { - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, aw.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str()); } } // output result if in config mode but not in quiet mode @@ -1002,7 +1036,8 @@ bool cmFindPackageCommand::FindAppBundleConfig() return false; } -bool cmFindPackageCommand::ReadListFile(const char* f, PolicyScopeRule psr) +bool cmFindPackageCommand::ReadListFile(const std::string& f, + PolicyScopeRule psr) { const bool noPolicyScope = !this->PolicyScope || psr == NoPolicyScope; if (this->Makefile->ReadDependentFile(f, noPolicyScope)) { @@ -1429,7 +1464,7 @@ void cmFindPackageCommand::FillPrefixesUserHints() bool cmFindPackageCommand::SearchDirectory(std::string const& dir) { - assert(!dir.empty() && dir[dir.size() - 1] == '/'); + assert(!dir.empty() && dir.back() == '/'); // Check each path suffix on this directory. for (std::string const& s : this->SearchPathSuffixes) { @@ -1447,7 +1482,7 @@ bool cmFindPackageCommand::SearchDirectory(std::string const& dir) bool cmFindPackageCommand::CheckDirectory(std::string const& dir) { - assert(!dir.empty() && dir[dir.size() - 1] == '/'); + assert(!dir.empty() && dir.back() == '/'); // Look for the file in this directory. std::string d = dir.substr(0, dir.size() - 1); @@ -1474,6 +1509,10 @@ bool cmFindPackageCommand::FindConfigFile(std::string const& dir, fprintf(stderr, "Checking file [%s]\n", file.c_str()); } if (cmSystemTools::FileExists(file, true) && this->CheckVersion(file)) { + // Allow resolving symlinks when the config file is found through a link + if (this->UseRealPath) { + file = cmSystemTools::GetRealPath(file); + } return true; } } @@ -1552,7 +1591,7 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file, // Load the version check file. Pass NoPolicyScope because we do // our own policy push/pop independent of CMP0011. bool suitable = false; - if (this->ReadListFile(version_file.c_str(), NoPolicyScope)) { + if (this->ReadListFile(version_file, NoPolicyScope)) { // Check the output variables. bool okay = this->Makefile->IsOn("PACKAGE_VERSION_EXACT"); bool unsuitable = this->Makefile->IsOn("PACKAGE_VERSION_UNSUITABLE"); @@ -1633,7 +1672,7 @@ void cmFindPackageCommand::StoreVersionFound() class cmFileListGeneratorBase { public: - virtual ~cmFileListGeneratorBase() {} + virtual ~cmFileListGeneratorBase() = default; protected: bool Consider(std::string const& fullPath, cmFileList& listing); @@ -1650,12 +1689,7 @@ private: class cmFileList { public: - cmFileList() - : First() - , Last(nullptr) - { - } - virtual ~cmFileList() {} + virtual ~cmFileList() = default; cmFileList& operator/(cmFileListGeneratorBase const& rhs) { if (this->Last) { @@ -1678,15 +1712,14 @@ private: virtual bool Visit(std::string const& fullPath) = 0; friend class cmFileListGeneratorBase; std::unique_ptr<cmFileListGeneratorBase> First; - cmFileListGeneratorBase* Last; + cmFileListGeneratorBase* Last = nullptr; }; class cmFindPackageFileList : public cmFileList { public: cmFindPackageFileList(cmFindPackageCommand* fpc, bool use_suffixes = true) - : cmFileList() - , FPC(fpc) + : FPC(fpc) , UseSuffixes(use_suffixes) { } @@ -1727,14 +1760,12 @@ bool cmFileListGeneratorBase::Consider(std::string const& fullPath, class cmFileListGeneratorFixed : public cmFileListGeneratorBase { public: - cmFileListGeneratorFixed(std::string const& str) - : cmFileListGeneratorBase() - , String(str) + cmFileListGeneratorFixed(std::string str) + : String(std::move(str)) { } cmFileListGeneratorFixed(cmFileListGeneratorFixed const& r) - : cmFileListGeneratorBase() - , String(r.String) + : String(r.String) { } @@ -1757,13 +1788,11 @@ class cmFileListGeneratorEnumerate : public cmFileListGeneratorBase { public: cmFileListGeneratorEnumerate(std::vector<std::string> const& v) - : cmFileListGeneratorBase() - , Vector(v) + : Vector(v) { } cmFileListGeneratorEnumerate(cmFileListGeneratorEnumerate const& r) - : cmFileListGeneratorBase() - , Vector(r.Vector) + : Vector(r.Vector) { } @@ -1792,14 +1821,12 @@ public: cmFileListGeneratorProject(std::vector<std::string> const& names, cmFindPackageCommand::SortOrderType so, cmFindPackageCommand::SortDirectionType sd) - : cmFileListGeneratorBase() - , Names(names) + : Names(names) { this->SetSort(so, sd); } cmFileListGeneratorProject(cmFileListGeneratorProject const& r) - : cmFileListGeneratorBase() - , Names(r.Names) + : Names(r.Names) { this->SetSort(r.SortOrder, r.SortDirection); } @@ -1831,7 +1858,7 @@ private: } for (std::string const& n : this->Names) { if (cmsysString_strncasecmp(fname, n.c_str(), n.length()) == 0) { - matches.push_back(fname); + matches.emplace_back(fname); } } } @@ -1863,14 +1890,12 @@ class cmFileListGeneratorMacProject : public cmFileListGeneratorBase public: cmFileListGeneratorMacProject(std::vector<std::string> const& names, const char* ext) - : cmFileListGeneratorBase() - , Names(names) + : Names(names) , Extension(ext) { } cmFileListGeneratorMacProject(cmFileListGeneratorMacProject const& r) - : cmFileListGeneratorBase() - , Names(r.Names) + : Names(r.Names) , Extension(r.Extension) { } @@ -1892,7 +1917,7 @@ private: for (std::string name : this->Names) { name += this->Extension; if (cmsysString_strcasecmp(fname, name.c_str()) == 0) { - matches.push_back(fname); + matches.emplace_back(fname); } } } @@ -1915,15 +1940,13 @@ private: class cmFileListGeneratorCaseInsensitive : public cmFileListGeneratorBase { public: - cmFileListGeneratorCaseInsensitive(std::string const& str) - : cmFileListGeneratorBase() - , String(str) + cmFileListGeneratorCaseInsensitive(std::string str) + : String(std::move(str)) { } cmFileListGeneratorCaseInsensitive( cmFileListGeneratorCaseInsensitive const& r) - : cmFileListGeneratorBase() - , String(r.String) + : String(r.String) { } @@ -1959,14 +1982,12 @@ private: class cmFileListGeneratorGlob : public cmFileListGeneratorBase { public: - cmFileListGeneratorGlob(std::string const& str) - : cmFileListGeneratorBase() - , Pattern(str) + cmFileListGeneratorGlob(std::string str) + : Pattern(std::move(str)) { } cmFileListGeneratorGlob(cmFileListGeneratorGlob const& r) - : cmFileListGeneratorBase() - , Pattern(r.Pattern) + : Pattern(r.Pattern) { } @@ -2001,7 +2022,7 @@ private: bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) { - assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/'); + assert(!prefix_in.empty() && prefix_in.back() == '/'); if (this->DebugMode) { fprintf(stderr, "Checking prefix [%s]\n", prefix_in.c_str()); } @@ -2059,16 +2080,16 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) common.push_back("lib/" + this->LibraryArchitecture); } if (this->UseLib32Paths) { - common.push_back("lib32"); + common.emplace_back("lib32"); } if (this->UseLib64Paths) { - common.push_back("lib64"); + common.emplace_back("lib64"); } if (this->UseLibx32Paths) { - common.push_back("libx32"); + common.emplace_back("libx32"); } - common.push_back("lib"); - common.push_back("share"); + common.emplace_back("lib"); + common.emplace_back("share"); // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/ { @@ -2157,7 +2178,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in) { - assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/'); + assert(!prefix_in.empty() && prefix_in.back() == '/'); if (this->DebugMode) { fprintf(stderr, "Checking framework prefix [%s]\n", prefix_in.c_str()); } @@ -2218,7 +2239,7 @@ bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in) bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in) { - assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/'); + assert(!prefix_in.empty() && prefix_in.back() == '/'); if (this->DebugMode) { fprintf(stderr, "Checking bundle prefix [%s]\n", prefix_in.c_str()); } diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 48f17ef11..a11d25304 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -4,6 +4,7 @@ #define cmFindPackageCommand_h #include "cmConfigure.h" // IWYU pragma: keep +#include "cmPolicies.h" #include "cm_kwiml.h" #include <cstddef> @@ -109,7 +110,7 @@ private: NoPolicyScope, DoPolicyScope }; - bool ReadListFile(const char* f, PolicyScopeRule psr); + bool ReadListFile(const std::string& f, PolicyScopeRule psr); void StoreVersionFound(); void ComputePrefixes(); @@ -148,6 +149,8 @@ private: }; std::map<std::string, OriginalDef> OriginalDefs; + std::map<std::string, cmPolicies::PolicyID> DeprecatedFindModules; + std::string Name; std::string Variable; std::string Version; @@ -175,6 +178,7 @@ private: bool UseLib32Paths; bool UseLib64Paths; bool UseLibx32Paths; + bool UseRealPath; bool PolicyScope; std::string LibraryArchitecture; std::vector<std::string> Names; diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index db340772f..782f746ef 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -77,7 +77,7 @@ struct cmFindProgramHelper this->TestNameExt = name; this->TestNameExt += ext; this->TestPath = - cmSystemTools::CollapseCombinedPath(path, this->TestNameExt); + cmSystemTools::CollapseFullPath(this->TestNameExt, path); if (cmSystemTools::FileExists(this->TestPath, true)) { this->BestPath = this->TestPath; diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 9ff967c50..e359deff9 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -10,8 +10,8 @@ #include "cmAlgorithms.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf) : Makefile(mf) @@ -38,7 +38,7 @@ bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, // Remove the function blocker for this scope or bail. std::unique_ptr<cmFunctionBlocker> fb( mf.RemoveFunctionBlocker(this, lff)); - if (!fb.get()) { + if (!fb) { return false; } @@ -164,7 +164,7 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args, break; } sprintf(buffer, "%d", cc); - range.push_back(buffer); + range.emplace_back(buffer); if (cc == stop) { break; } @@ -210,7 +210,7 @@ bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args) std::ostringstream e; e << "Unknown argument:\n" << " " << args[i] << "\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return true; } } diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h index 132b3e684..076234035 100644 --- a/Source/cmFortranParser.h +++ b/Source/cmFortranParser.h @@ -8,6 +8,7 @@ # include <set> # include <string> +# include <utility> # include <vector> #endif @@ -114,10 +115,10 @@ int cmFortran_yyparse(yyscan_t); // Define parser object internal structure. struct cmFortranFile { - cmFortranFile(FILE* file, YY_BUFFER_STATE buffer, const std::string& dir) + cmFortranFile(FILE* file, YY_BUFFER_STATE buffer, std::string dir) : File(file) , Buffer(buffer) - , Directory(dir) + , Directory(std::move(dir)) , LastCharWasNewline(false) { } @@ -127,16 +128,29 @@ struct cmFortranFile bool LastCharWasNewline; }; +struct cmFortranCompiler +{ + std::string Id; + std::string SModSep; + std::string SModExt; +}; + struct cmFortranParser_s { - cmFortranParser_s(std::vector<std::string> const& includes, - std::set<std::string> const& defines, - cmFortranSourceInfo& info); + cmFortranParser_s(cmFortranCompiler fc, std::vector<std::string> includes, + std::set<std::string> defines, cmFortranSourceInfo& info); ~cmFortranParser_s(); bool FindIncludeFile(const char* dir, const char* includeName, std::string& fileName); + std::string ModName(std::string const& mod_name) const; + std::string SModName(std::string const& mod_name, + std::string const& sub_name) const; + + // What compiler. + cmFortranCompiler Compiler; + // The include file search path. std::vector<std::string> IncludePath; diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx index 01cbb7843..18e3c107d 100644 --- a/Source/cmFortranParserImpl.cxx +++ b/Source/cmFortranParserImpl.cxx @@ -8,6 +8,7 @@ #include <stack> #include <stdio.h> #include <string> +#include <utility> #include <vector> bool cmFortranParser_s::FindIncludeFile(const char* dir, @@ -42,11 +43,13 @@ bool cmFortranParser_s::FindIncludeFile(const char* dir, return false; } -cmFortranParser_s::cmFortranParser_s(std::vector<std::string> const& includes, - std::set<std::string> const& defines, +cmFortranParser_s::cmFortranParser_s(cmFortranCompiler fc, + std::vector<std::string> includes, + std::set<std::string> defines, cmFortranSourceInfo& info) - : IncludePath(includes) - , PPDefinitions(defines) + : Compiler(std::move(fc)) + , IncludePath(std::move(includes)) + , PPDefinitions(std::move(defines)) , Info(info) { this->InInterface = false; @@ -68,6 +71,17 @@ cmFortranParser_s::~cmFortranParser_s() cmFortran_yylex_destroy(this->Scanner); } +std::string cmFortranParser_s::ModName(std::string const& mod_name) const +{ + return mod_name + ".mod"; +} + +std::string cmFortranParser_s::SModName(std::string const& mod_name, + std::string const& sub_name) const +{ + return mod_name + this->Compiler.SModSep + sub_name + this->Compiler.SModExt; +} + bool cmFortranParser_FilePush(cmFortranParser* parser, const char* fname) { // Open the new file and push it onto the stack. Save the old @@ -177,7 +191,7 @@ void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name) // syntax: "use module_name" // requires: "module_name.mod" std::string const& mod_name = cmSystemTools::LowerCase(module_name); - parser->Info.Requires.insert(mod_name + ".mod"); + parser->Info.Requires.insert(parser->ModName(mod_name)); } void cmFortranParser_RuleLineDirective(cmFortranParser* parser, @@ -241,7 +255,7 @@ void cmFortranParser_RuleModule(cmFortranParser* parser, // syntax: "module module_name" // provides: "module_name.mod" std::string const& mod_name = cmSystemTools::LowerCase(module_name); - parser->Info.Provides.insert(mod_name + ".mod"); + parser->Info.Provides.insert(parser->ModName(mod_name)); } } @@ -264,8 +278,8 @@ void cmFortranParser_RuleSubmodule(cmFortranParser* parser, std::string const& mod_name = cmSystemTools::LowerCase(module_name); std::string const& sub_name = cmSystemTools::LowerCase(submodule_name); - parser->Info.Requires.insert(mod_name + ".mod"); - parser->Info.Provides.insert(mod_name + "@" + sub_name + ".smod"); + parser->Info.Requires.insert(parser->ModName(mod_name)); + parser->Info.Provides.insert(parser->SModName(mod_name, sub_name)); } void cmFortranParser_RuleSubmoduleNested(cmFortranParser* parser, @@ -285,8 +299,8 @@ void cmFortranParser_RuleSubmoduleNested(cmFortranParser* parser, std::string const& sub_name = cmSystemTools::LowerCase(submodule_name); std::string const& nest_name = cmSystemTools::LowerCase(nested_submodule_name); - parser->Info.Requires.insert(mod_name + "@" + sub_name + ".smod"); - parser->Info.Provides.insert(mod_name + "@" + nest_name + ".smod"); + parser->Info.Requires.insert(parser->SModName(mod_name, sub_name)); + parser->Info.Provides.insert(parser->SModName(mod_name, nest_name)); } void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* macro) diff --git a/Source/cmFunctionBlocker.h b/Source/cmFunctionBlocker.h index b3450b3f2..cd6b05db4 100644 --- a/Source/cmFunctionBlocker.h +++ b/Source/cmFunctionBlocker.h @@ -26,7 +26,7 @@ public: return false; } - virtual ~cmFunctionBlocker() {} + virtual ~cmFunctionBlocker() = default; /** Set/Get the context in which this blocker is created. */ void SetStartingContext(cmListFileContext const& lfc) diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index 67c9e9a5d..264a3385c 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -14,11 +14,6 @@ class cmFunctionHelperCommand : public cmCommand { public: - cmFunctionHelperCommand() {} - - ///! clean up any memory allocated by the function - ~cmFunctionHelperCommand() override {} - /** * This is a virtual constructor for the command. */ diff --git a/Source/cmFunctionCommand.h b/Source/cmFunctionCommand.h index 3352b9235..8b37df032 100644 --- a/Source/cmFunctionCommand.h +++ b/Source/cmFunctionCommand.h @@ -18,15 +18,13 @@ class cmMakefile; class cmFunctionFunctionBlocker : public cmFunctionBlocker { public: - cmFunctionFunctionBlocker() { this->Depth = 0; } - ~cmFunctionFunctionBlocker() override {} bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf, cmExecutionStatus&) override; bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override; std::vector<std::string> Args; std::vector<cmListFileFunction> Functions; - int Depth; + int Depth = 0; }; /// Starts function() ... endfunction() block diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 186ec8c9e..4fe15874d 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -12,8 +12,6 @@ #endif cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding) - : cmGeneratedFileStreamBase() - , Stream() { #ifdef CMAKE_BUILD_WITH_CMAKE if (encoding != codecvt::None) { @@ -104,23 +102,9 @@ void cmGeneratedFileStream::SetCompressionExtraExtension(bool ext) this->CompressExtraExtension = ext; } -cmGeneratedFileStreamBase::cmGeneratedFileStreamBase() - : Name() - , TempName() - , CopyIfDifferent(false) - , Okay(false) - , Compress(false) - , CompressExtraExtension(true) -{ -} +cmGeneratedFileStreamBase::cmGeneratedFileStreamBase() = default; cmGeneratedFileStreamBase::cmGeneratedFileStreamBase(std::string const& name) - : Name() - , TempName() - , CopyIfDifferent(false) - , Okay(false) - , Compress(false) - , CompressExtraExtension(true) { this->Open(name); } @@ -224,7 +208,7 @@ int cmGeneratedFileStreamBase::CompressFile(std::string const&, int cmGeneratedFileStreamBase::RenameFile(std::string const& oldname, std::string const& newname) { - return cmSystemTools::RenameFile(oldname.c_str(), newname.c_str()); + return cmSystemTools::RenameFile(oldname, newname); } void cmGeneratedFileStream::SetName(const std::string& fname) diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h index dacd16692..5b1eb5153 100644 --- a/Source/cmGeneratedFileStream.h +++ b/Source/cmGeneratedFileStream.h @@ -45,16 +45,16 @@ protected: std::string TempName; // Whether to do a copy-if-different. - bool CopyIfDifferent; + bool CopyIfDifferent = false; // Whether the real file stream was valid when it was closed. - bool Okay; + bool Okay = false; // Whether the destination file is compressed - bool Compress; + bool Compress = false; // Whether the destination file is compressed - bool CompressExtraExtension; + bool CompressExtraExtension = true; }; /** \class cmGeneratedFileStream @@ -97,6 +97,8 @@ public: */ ~cmGeneratedFileStream() override; + cmGeneratedFileStream(cmGeneratedFileStream const&) = delete; + /** * Open an output file by name. This should be used only with a * non-open stream. It automatically generates a name for the @@ -134,9 +136,6 @@ public: * the output file to be changed during the use of cmGeneratedFileStream. */ void SetName(const std::string& fname); - -private: - cmGeneratedFileStream(cmGeneratedFileStream const&); // not implemented }; #endif diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 2727d9ae4..175a26d2e 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -15,9 +15,8 @@ #include "cmGeneratorExpressionParser.h" #include "cmSystemTools.h" -cmGeneratorExpression::cmGeneratorExpression( - const cmListFileBacktrace& backtrace) - : Backtrace(backtrace) +cmGeneratorExpression::cmGeneratorExpression(cmListFileBacktrace backtrace) + : Backtrace(std::move(backtrace)) { } @@ -34,9 +33,7 @@ std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse( return this->Parse(std::string(input ? input : "")); } -cmGeneratorExpression::~cmGeneratorExpression() -{ -} +cmGeneratorExpression::~cmGeneratorExpression() = default; const std::string& cmCompiledGeneratorExpression::Evaluate( cmLocalGenerator* lg, const std::string& config, bool quiet, @@ -71,16 +68,11 @@ const std::string& cmCompiledGeneratorExpression::EvaluateWithContext( this->Output.clear(); - std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it = - this->Evaluators.begin(); - const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end = - this->Evaluators.end(); - - for (; it != end; ++it) { - this->Output += (*it)->Evaluate(&context, dagChecker); + for (const cmGeneratorExpressionEvaluator* it : this->Evaluators) { + this->Output += it->Evaluate(&context, dagChecker); - this->SeenTargetProperties.insert(context.SeenTargetProperties.begin(), - context.SeenTargetProperties.end()); + this->SeenTargetProperties.insert(context.SeenTargetProperties.cbegin(), + context.SeenTargetProperties.cend()); if (context.HadError) { this->Output.clear(); break; @@ -101,9 +93,9 @@ const std::string& cmCompiledGeneratorExpression::EvaluateWithContext( } cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( - cmListFileBacktrace const& backtrace, const std::string& input) - : Backtrace(backtrace) - , Input(input) + cmListFileBacktrace backtrace, std::string input) + : Backtrace(std::move(backtrace)) + , Input(std::move(input)) , HadContextSensitiveCondition(false) , HadHeadSensitiveCondition(false) , EvaluateForBuildsystem(false) diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 9c05f60c8..fd36c4bcb 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -11,6 +11,7 @@ #include <memory> // IWYU pragma: keep #include <set> #include <string> +#include <utility> #include <vector> class cmCompiledGeneratorExpression; @@ -31,14 +32,14 @@ struct cmGeneratorExpressionEvaluator; */ class cmGeneratorExpression { - CM_DISABLE_COPY(cmGeneratorExpression) - public: /** Construct. */ - cmGeneratorExpression( - cmListFileBacktrace const& backtrace = cmListFileBacktrace()); + cmGeneratorExpression(cmListFileBacktrace backtrace = cmListFileBacktrace()); ~cmGeneratorExpression(); + cmGeneratorExpression(cmGeneratorExpression const&) = delete; + cmGeneratorExpression& operator=(cmGeneratorExpression const&) = delete; + std::unique_ptr<cmCompiledGeneratorExpression> Parse( std::string const& input); std::unique_ptr<cmCompiledGeneratorExpression> Parse(const char* input); @@ -78,9 +79,13 @@ private: class cmCompiledGeneratorExpression { - CM_DISABLE_COPY(cmCompiledGeneratorExpression) - public: + ~cmCompiledGeneratorExpression(); + + cmCompiledGeneratorExpression(cmCompiledGeneratorExpression const&) = delete; + cmCompiledGeneratorExpression& operator=( + cmCompiledGeneratorExpression const&) = delete; + const std::string& Evaluate( cmLocalGenerator* lg, const std::string& config, bool quiet = false, cmGeneratorTarget const* headTarget = nullptr, @@ -109,8 +114,6 @@ public: return this->AllTargetsSeen; } - ~cmCompiledGeneratorExpression(); - std::string const& GetInput() const { return this->Input; } cmListFileBacktrace GetBacktrace() const { return this->Backtrace; } @@ -140,8 +143,8 @@ private: cmGeneratorExpressionContext& context, cmGeneratorExpressionDAGChecker* dagChecker) const; - cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace, - const std::string& input); + cmCompiledGeneratorExpression(cmListFileBacktrace backtrace, + std::string input); friend class cmGeneratorExpression; @@ -165,20 +168,23 @@ private: class cmGeneratorExpressionInterpreter { - CM_DISABLE_COPY(cmGeneratorExpressionInterpreter) - public: cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator, - std::string const& config, + std::string config, cmGeneratorTarget const* headTarget, - std::string const& lang = std::string()) + std::string lang = std::string()) : LocalGenerator(localGenerator) - , Config(config) + , Config(std::move(config)) , HeadTarget(headTarget) - , Language(lang) + , Language(std::move(lang)) { } + cmGeneratorExpressionInterpreter(cmGeneratorExpressionInterpreter const&) = + delete; + cmGeneratorExpressionInterpreter& operator=( + cmGeneratorExpressionInterpreter const&) = delete; + const std::string& Evaluate(const char* expression, const std::string& property); const std::string& Evaluate(const std::string& expression, diff --git a/Source/cmGeneratorExpressionContext.cxx b/Source/cmGeneratorExpressionContext.cxx index a6dde5d39..6d973310c 100644 --- a/Source/cmGeneratorExpressionContext.cxx +++ b/Source/cmGeneratorExpressionContext.cxx @@ -2,15 +2,17 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGeneratorExpressionContext.h" +#include <utility> + cmGeneratorExpressionContext::cmGeneratorExpressionContext( - cmLocalGenerator* lg, std::string const& config, bool quiet, + cmLocalGenerator* lg, std::string config, bool quiet, cmGeneratorTarget const* headTarget, const cmGeneratorTarget* currentTarget, - bool evaluateForBuildsystem, cmListFileBacktrace const& backtrace, - std::string const& language) - : Backtrace(backtrace) + bool evaluateForBuildsystem, cmListFileBacktrace backtrace, + std::string language) + : Backtrace(std::move(backtrace)) , LG(lg) - , Config(config) - , Language(language) + , Config(std::move(config)) + , Language(std::move(language)) , HeadTarget(headTarget) , CurrentTarget(currentTarget) , Quiet(quiet) diff --git a/Source/cmGeneratorExpressionContext.h b/Source/cmGeneratorExpressionContext.h index 5b0123ec8..6e076bf54 100644 --- a/Source/cmGeneratorExpressionContext.h +++ b/Source/cmGeneratorExpressionContext.h @@ -14,12 +14,12 @@ class cmLocalGenerator; struct cmGeneratorExpressionContext { - cmGeneratorExpressionContext(cmLocalGenerator* lg, std::string const& config, + cmGeneratorExpressionContext(cmLocalGenerator* lg, std::string config, bool quiet, const cmGeneratorTarget* headTarget, cmGeneratorTarget const* currentTarget, bool evaluateForBuildsystem, - cmListFileBacktrace const& backtrace, - std::string const& language); + cmListFileBacktrace backtrace, + std::string language); cmListFileBacktrace Backtrace; std::set<cmGeneratorTarget*> DependTargets; diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 8d57441c3..728f2a4fd 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -7,6 +7,7 @@ #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" +#include "cmMessageType.h" #include "cmake.h" #include <sstream> @@ -14,26 +15,26 @@ #include <utility> cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( - const cmListFileBacktrace& backtrace, cmGeneratorTarget const* target, - const std::string& property, const GeneratorExpressionContent* content, + cmListFileBacktrace backtrace, cmGeneratorTarget const* target, + std::string property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent) : Parent(parent) , Target(target) - , Property(property) + , Property(std::move(property)) , Content(content) - , Backtrace(backtrace) + , Backtrace(std::move(backtrace)) , TransitivePropertiesOnly(false) { Initialize(); } cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( - cmGeneratorTarget const* target, const std::string& property, + cmGeneratorTarget const* target, std::string property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent) : Parent(parent) , Target(target) - , Property(property) + , Property(std::move(property)) , Content(content) , Backtrace() , TransitivePropertiesOnly(false) @@ -55,7 +56,7 @@ void cmGeneratorExpressionDAGChecker::Initialize() if (CheckResult == DAG && (CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD( - TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(clang-tidy) + TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(*) #undef TEST_TRANSITIVE_PROPERTY_METHOD { std::map<cmGeneratorTarget const*, std::set<std::string>>::const_iterator @@ -99,8 +100,8 @@ void cmGeneratorExpressionDAGChecker::ReportError( << " " << expr << "\n" << "Self reference on target \"" << context->HeadTarget->GetName() << "\".\n"; - context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - parent->Backtrace); + context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), parent->Backtrace); return; } @@ -111,8 +112,8 @@ void cmGeneratorExpressionDAGChecker::ReportError( << " " << expr << "\n" << "Dependency loop found."; /* clang-format on */ - context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - context->Backtrace); + context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), context->Backtrace); } int loopStep = 1; @@ -122,8 +123,8 @@ void cmGeneratorExpressionDAGChecker::ReportError( << " " << (parent->Content ? parent->Content->GetOriginalExpression() : expr) << "\n"; - context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - parent->Backtrace); + context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), parent->Backtrace); parent = parent->Parent; ++loopStep; } @@ -156,6 +157,12 @@ bool cmGeneratorExpressionDAGChecker::GetTransitivePropertiesOnly() bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression() { + return this->Property.find("TARGET_GENEX_EVAL:") == 0 || + this->Property.find("GENEX_EVAL:", 0) == 0; +} + +bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression() +{ const cmGeneratorExpressionDAGChecker* top = this; const cmGeneratorExpressionDAGChecker* parent = this->Parent; while (parent) { @@ -163,7 +170,7 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression() parent = parent->Parent; } - return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL"; + return top->Property == "INTERFACE_POSITION_INDEPENDENT_CODE"; } bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries( diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index a5134c315..e1fba5e5c 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -42,13 +42,13 @@ class cmGeneratorTarget; struct cmGeneratorExpressionDAGChecker { - cmGeneratorExpressionDAGChecker(const cmListFileBacktrace& backtrace, + cmGeneratorExpressionDAGChecker(cmListFileBacktrace backtrace, cmGeneratorTarget const* target, - const std::string& property, + std::string property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent); cmGeneratorExpressionDAGChecker(cmGeneratorTarget const* target, - const std::string& property, + std::string property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent); @@ -66,6 +66,7 @@ struct cmGeneratorExpressionDAGChecker const std::string& expr); bool EvaluatingGenexExpression(); + bool EvaluatingPICExpression(); bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr); #define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const; diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index e7a55e054..326cb0e55 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -12,17 +12,17 @@ #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmSourceFileLocationKind.h" #include "cmSystemTools.h" -#include "cmake.h" cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile( - const std::string& input, + std::string input, std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070) - : Input(input) + : Input(std::move(input)) , OutputFileExpr(std::move(outputFileExpr)) , Condition(std::move(condition)) , InputIsContent(inputIsContent) @@ -48,7 +48,7 @@ void cmGeneratorExpressionEvaluationFile::Generate( << "\" did " "not evaluate to valid content. Got \"" << condResult << "\"."; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } } @@ -77,7 +77,7 @@ void cmGeneratorExpressionEvaluationFile::Generate( "This is generally caused by the content evaluating the " "configuration type, language, or location of object files:\n " << outputFileName; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -137,7 +137,7 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg) if (!fin) { std::ostringstream e; e << "Evaluation file \"" << inputFileName << "\" cannot be read."; - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); + lg->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -204,7 +204,7 @@ std::string cmGeneratorExpressionEvaluationFile::FixRelativePath( "undefined behavior will be used." ; /* clang-format on */ - lg->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + lg->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } CM_FALLTHROUGH; case cmPolicies::OLD: diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h index 2a790697f..89a239057 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.h +++ b/Source/cmGeneratorExpressionEvaluationFile.h @@ -20,7 +20,7 @@ class cmGeneratorExpressionEvaluationFile { public: cmGeneratorExpressionEvaluationFile( - const std::string& input, + std::string input, std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070); diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index 056179950..453015262 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -16,8 +16,13 @@ struct cmGeneratorExpressionNode; struct cmGeneratorExpressionEvaluator { - cmGeneratorExpressionEvaluator() {} - virtual ~cmGeneratorExpressionEvaluator() {} + cmGeneratorExpressionEvaluator() = default; + virtual ~cmGeneratorExpressionEvaluator() = default; + + cmGeneratorExpressionEvaluator(cmGeneratorExpressionEvaluator const&) = + delete; + cmGeneratorExpressionEvaluator& operator=( + cmGeneratorExpressionEvaluator const&) = delete; enum Type { @@ -29,9 +34,6 @@ struct cmGeneratorExpressionEvaluator virtual std::string Evaluate(cmGeneratorExpressionContext* context, cmGeneratorExpressionDAGChecker*) const = 0; - -private: - CM_DISABLE_COPY(cmGeneratorExpressionEvaluator) }; struct TextContent : public cmGeneratorExpressionEvaluator diff --git a/Source/cmGeneratorExpressionLexer.cxx b/Source/cmGeneratorExpressionLexer.cxx index e37f165a8..a7f090ac7 100644 --- a/Source/cmGeneratorExpressionLexer.cxx +++ b/Source/cmGeneratorExpressionLexer.cxx @@ -2,11 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGeneratorExpressionLexer.h" -cmGeneratorExpressionLexer::cmGeneratorExpressionLexer() - : SawBeginExpression(false) - , SawGeneratorExpression(false) -{ -} +cmGeneratorExpressionLexer::cmGeneratorExpressionLexer() = default; static void InsertText(const char* upto, const char* c, std::vector<cmGeneratorExpressionToken>& result) @@ -22,8 +18,8 @@ std::vector<cmGeneratorExpressionToken> cmGeneratorExpressionLexer::Tokenize( std::vector<cmGeneratorExpressionToken> result; if (input.find('$') == std::string::npos) { - result.push_back(cmGeneratorExpressionToken( - cmGeneratorExpressionToken::Text, input.c_str(), input.size())); + result.emplace_back(cmGeneratorExpressionToken::Text, input.c_str(), + input.size()); return result; } diff --git a/Source/cmGeneratorExpressionLexer.h b/Source/cmGeneratorExpressionLexer.h index e53f0b547..bf2430818 100644 --- a/Source/cmGeneratorExpressionLexer.h +++ b/Source/cmGeneratorExpressionLexer.h @@ -46,8 +46,8 @@ public: } private: - bool SawBeginExpression; - bool SawGeneratorExpression; + bool SawBeginExpression = false; + bool SawGeneratorExpression = false; }; #endif diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index f901215e3..70c80c90d 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -12,6 +12,7 @@ #include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmStateTypes.h" @@ -55,7 +56,7 @@ std::string cmGeneratorExpressionNode::EvaluateDependentExpression( static const struct ZeroNode : public cmGeneratorExpressionNode { - ZeroNode() {} + ZeroNode() {} // NOLINT(modernize-use-equals-default) bool GeneratesContent() const override { return false; } @@ -73,7 +74,7 @@ static const struct ZeroNode : public cmGeneratorExpressionNode static const struct OneNode : public cmGeneratorExpressionNode { - OneNode() {} + OneNode() {} // NOLINT(modernize-use-equals-default) bool AcceptsArbitraryContentParameter() const override { return true; } @@ -94,7 +95,7 @@ static const struct ZeroNode installInterfaceNode; #define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \ static const struct OP##Node : public cmGeneratorExpressionNode \ { \ - OP##Node() {} \ + OP##Node() {} /* NOLINT(modernize-use-equals-default) */ \ virtual int NumExpectedParameters() const { return OneOrMoreParameters; } \ \ std::string Evaluate(const std::vector<std::string>& parameters, \ @@ -126,7 +127,7 @@ BOOLEAN_OP_NODE(orNode, OR, 0, 1) static const struct NotNode : public cmGeneratorExpressionNode { - NotNode() {} + NotNode() {} // NOLINT(modernize-use-equals-default) std::string Evaluate( const std::vector<std::string>& parameters, @@ -146,7 +147,7 @@ static const struct NotNode : public cmGeneratorExpressionNode static const struct BoolNode : public cmGeneratorExpressionNode { - BoolNode() {} + BoolNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 1; } @@ -162,7 +163,7 @@ static const struct BoolNode : public cmGeneratorExpressionNode static const struct IfNode : public cmGeneratorExpressionNode { - IfNode() {} + IfNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 3; } @@ -183,7 +184,7 @@ static const struct IfNode : public cmGeneratorExpressionNode static const struct StrEqualNode : public cmGeneratorExpressionNode { - StrEqualNode() {} + StrEqualNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 2; } @@ -199,7 +200,7 @@ static const struct StrEqualNode : public cmGeneratorExpressionNode static const struct EqualNode : public cmGeneratorExpressionNode { - EqualNode() {} + EqualNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 2; } @@ -277,20 +278,45 @@ static const struct EqualNode : public cmGeneratorExpressionNode static const struct InListNode : public cmGeneratorExpressionNode { - InListNode() {} + InListNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 2; } std::string Evaluate( const std::vector<std::string>& parameters, - cmGeneratorExpressionContext* /*context*/, + cmGeneratorExpressionContext* context, const GeneratorExpressionContent* /*content*/, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - std::vector<std::string> values; - cmSystemTools::ExpandListArgument(parameters[1], values); - if (values.empty()) { - return "0"; + std::vector<std::string> values, checkValues; + bool check = false; + switch (context->LG->GetPolicyStatus(cmPolicies::CMP0085)) { + case cmPolicies::WARN: + if (parameters.front().empty()) { + check = true; + cmSystemTools::ExpandListArgument(parameters[1], checkValues, true); + } + CM_FALLTHROUGH; + case cmPolicies::OLD: + cmSystemTools::ExpandListArgument(parameters[1], values); + if (check && values != checkValues) { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0085) + << "\nSearch Item:\n \"" << parameters.front() + << "\"\nList:\n \"" << parameters[1] << "\"\n"; + context->LG->GetCMakeInstance()->IssueMessage( + MessageType ::AUTHOR_WARNING, e.str(), context->Backtrace); + return "0"; + } + if (values.empty()) { + return "0"; + } + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + cmSystemTools::ExpandListArgument(parameters[1], values, true); + break; } return std::find(values.cbegin(), values.cend(), parameters.front()) == @@ -302,7 +328,7 @@ static const struct InListNode : public cmGeneratorExpressionNode static const struct TargetExistsNode : public cmGeneratorExpressionNode { - TargetExistsNode() {} + TargetExistsNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 1; } @@ -333,7 +359,7 @@ static const struct TargetExistsNode : public cmGeneratorExpressionNode static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode { - TargetNameIfExistsNode() {} + TargetNameIfExistsNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 1; } @@ -367,7 +393,7 @@ static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode struct GenexEvaluator : public cmGeneratorExpressionNode { - GenexEvaluator() {} + GenexEvaluator() {} // NOLINT(modernize-use-equals-default) protected: std::string EvaluateExpression( @@ -378,8 +404,8 @@ protected: { if (context->HeadTarget) { cmGeneratorExpressionDAGChecker dagChecker( - context->Backtrace, context->HeadTarget, genexOperator, content, - dagCheckerParent); + context->Backtrace, context->HeadTarget, + genexOperator + ":" + expression, content, dagCheckerParent); switch (dagChecker.Check()) { case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: { @@ -404,7 +430,7 @@ protected: static const struct TargetGenexEvalNode : public GenexEvaluator { - TargetGenexEvalNode() {} + TargetGenexEvalNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 2; } @@ -450,7 +476,7 @@ static const struct TargetGenexEvalNode : public GenexEvaluator static const struct GenexEvalNode : public GenexEvaluator { - GenexEvalNode() {} + GenexEvalNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 1; } @@ -474,7 +500,7 @@ static const struct GenexEvalNode : public GenexEvaluator static const struct LowerCaseNode : public cmGeneratorExpressionNode { - LowerCaseNode() {} + LowerCaseNode() {} // NOLINT(modernize-use-equals-default) bool AcceptsArbitraryContentParameter() const override { return true; } @@ -490,7 +516,7 @@ static const struct LowerCaseNode : public cmGeneratorExpressionNode static const struct UpperCaseNode : public cmGeneratorExpressionNode { - UpperCaseNode() {} + UpperCaseNode() {} // NOLINT(modernize-use-equals-default) bool AcceptsArbitraryContentParameter() const override { return true; } @@ -506,7 +532,7 @@ static const struct UpperCaseNode : public cmGeneratorExpressionNode static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode { - MakeCIdentifierNode() {} + MakeCIdentifierNode() {} // NOLINT(modernize-use-equals-default) bool AcceptsArbitraryContentParameter() const override { return true; } @@ -522,7 +548,7 @@ static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode static const struct Angle_RNode : public cmGeneratorExpressionNode { - Angle_RNode() {} + Angle_RNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 0; } @@ -538,7 +564,7 @@ static const struct Angle_RNode : public cmGeneratorExpressionNode static const struct CommaNode : public cmGeneratorExpressionNode { - CommaNode() {} + CommaNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 0; } @@ -554,7 +580,7 @@ static const struct CommaNode : public cmGeneratorExpressionNode static const struct SemicolonNode : public cmGeneratorExpressionNode { - SemicolonNode() {} + SemicolonNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 0; } @@ -570,7 +596,7 @@ static const struct SemicolonNode : public cmGeneratorExpressionNode struct CompilerIdNode : public cmGeneratorExpressionNode { - CompilerIdNode() {} + CompilerIdNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return OneOrZeroParameters; } @@ -607,7 +633,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044); context->LG->GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, e.str(), context->Backtrace); + MessageType::AUTHOR_WARNING, e.str(), context->Backtrace); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -624,7 +650,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode static const struct CCompilerIdNode : public CompilerIdNode { - CCompilerIdNode() {} + CCompilerIdNode() {} // NOLINT(modernize-use-equals-default) std::string Evaluate( const std::vector<std::string>& parameters, @@ -646,7 +672,7 @@ static const struct CCompilerIdNode : public CompilerIdNode static const struct CXXCompilerIdNode : public CompilerIdNode { - CXXCompilerIdNode() {} + CXXCompilerIdNode() {} // NOLINT(modernize-use-equals-default) std::string Evaluate( const std::vector<std::string>& parameters, @@ -666,9 +692,31 @@ static const struct CXXCompilerIdNode : public CompilerIdNode } } cxxCompilerIdNode; +static const struct FortranCompilerIdNode : public CompilerIdNode +{ + FortranCompilerIdNode() {} // NOLINT(modernize-use-equals-default) + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!context->HeadTarget) { + reportError( + context, content->GetOriginalExpression(), + "$<Fortran_COMPILER_ID> may only be used with binary targets. It may " + "not be used with add_custom_command or add_custom_target."); + return std::string(); + } + return this->EvaluateWithLanguage(parameters, context, content, dagChecker, + "Fortran"); + } +} fortranCompilerIdNode; + struct CompilerVersionNode : public cmGeneratorExpressionNode { - CompilerVersionNode() {} + CompilerVersionNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return OneOrZeroParameters; } @@ -705,7 +753,7 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode static const struct CCompilerVersionNode : public CompilerVersionNode { - CCompilerVersionNode() {} + CCompilerVersionNode() {} // NOLINT(modernize-use-equals-default) std::string Evaluate( const std::vector<std::string>& parameters, @@ -727,7 +775,7 @@ static const struct CCompilerVersionNode : public CompilerVersionNode static const struct CxxCompilerVersionNode : public CompilerVersionNode { - CxxCompilerVersionNode() {} + CxxCompilerVersionNode() {} // NOLINT(modernize-use-equals-default) std::string Evaluate( const std::vector<std::string>& parameters, @@ -747,9 +795,31 @@ static const struct CxxCompilerVersionNode : public CompilerVersionNode } } cxxCompilerVersionNode; +static const struct FortranCompilerVersionNode : public CompilerVersionNode +{ + FortranCompilerVersionNode() {} // NOLINT(modernize-use-equals-default) + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!context->HeadTarget) { + reportError( + context, content->GetOriginalExpression(), + "$<Fortran_COMPILER_VERSION> may only be used with binary targets. " + "It may not be used with add_custom_command or add_custom_target."); + return std::string(); + } + return this->EvaluateWithLanguage(parameters, context, content, dagChecker, + "Fortran"); + } +} fortranCompilerVersionNode; + struct PlatformIdNode : public cmGeneratorExpressionNode { - PlatformIdNode() {} + PlatformIdNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return OneOrZeroParameters; } @@ -778,7 +848,7 @@ struct PlatformIdNode : public cmGeneratorExpressionNode static const struct VersionGreaterNode : public cmGeneratorExpressionNode { - VersionGreaterNode() {} + VersionGreaterNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 2; } @@ -798,7 +868,7 @@ static const struct VersionGreaterNode : public cmGeneratorExpressionNode static const struct VersionGreaterEqNode : public cmGeneratorExpressionNode { - VersionGreaterEqNode() {} + VersionGreaterEqNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 2; } @@ -818,7 +888,7 @@ static const struct VersionGreaterEqNode : public cmGeneratorExpressionNode static const struct VersionLessNode : public cmGeneratorExpressionNode { - VersionLessNode() {} + VersionLessNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 2; } @@ -838,7 +908,7 @@ static const struct VersionLessNode : public cmGeneratorExpressionNode static const struct VersionLessEqNode : public cmGeneratorExpressionNode { - VersionLessEqNode() {} + VersionLessEqNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 2; } @@ -858,7 +928,7 @@ static const struct VersionLessEqNode : public cmGeneratorExpressionNode static const struct VersionEqualNode : public cmGeneratorExpressionNode { - VersionEqualNode() {} + VersionEqualNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 2; } @@ -878,7 +948,7 @@ static const struct VersionEqualNode : public cmGeneratorExpressionNode static const struct LinkOnlyNode : public cmGeneratorExpressionNode { - LinkOnlyNode() {} + LinkOnlyNode() {} // NOLINT(modernize-use-equals-default) std::string Evaluate( const std::vector<std::string>& parameters, @@ -900,7 +970,7 @@ static const struct LinkOnlyNode : public cmGeneratorExpressionNode static const struct ConfigurationNode : public cmGeneratorExpressionNode { - ConfigurationNode() {} + ConfigurationNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 0; } @@ -917,7 +987,7 @@ static const struct ConfigurationNode : public cmGeneratorExpressionNode static const struct ConfigurationTestNode : public cmGeneratorExpressionNode { - ConfigurationTestNode() {} + ConfigurationTestNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return OneOrZeroParameters; } @@ -976,7 +1046,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode static const struct JoinNode : public cmGeneratorExpressionNode { - JoinNode() {} + JoinNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 2; } @@ -996,7 +1066,7 @@ static const struct JoinNode : public cmGeneratorExpressionNode static const struct CompileLanguageNode : public cmGeneratorExpressionNode { - CompileLanguageNode() {} + CompileLanguageNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return OneOrZeroParameters; } @@ -1076,7 +1146,7 @@ std::string getLinkedTargetsContent( static const struct TargetPropertyNode : public cmGeneratorExpressionNode { - TargetPropertyNode() {} + TargetPropertyNode() {} // NOLINT(modernize-use-equals-default) // This node handles errors on parameter count itself. int NumExpectedParameters() const override { return OneOrMoreParameters; } @@ -1225,13 +1295,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode const char* prop = target->GetProperty(propertyName); if (dagCheckerParent) { - if (dagCheckerParent->EvaluatingGenexExpression()) { + if (dagCheckerParent->EvaluatingGenexExpression() || + dagCheckerParent->EvaluatingPICExpression()) { // No check required. } else if (dagCheckerParent->EvaluatingLinkLibraries()) { #define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \ (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) || if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME( - TRANSITIVE_PROPERTY_COMPARE) false) { // NOLINT(clang-tidy) + TRANSITIVE_PROPERTY_COMPARE) false) { // NOLINT(*) reportError( context, content->GetOriginalExpression(), "$<TARGET_PROPERTY:...> expression in link libraries " @@ -1371,7 +1442,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode static const struct TargetNameNode : public cmGeneratorExpressionNode { - TargetNameNode() {} + TargetNameNode() {} // NOLINT(modernize-use-equals-default) bool GeneratesContent() const override { return true; } @@ -1393,7 +1464,7 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode static const struct TargetObjectsNode : public cmGeneratorExpressionNode { - TargetObjectsNode() {} + TargetObjectsNode() {} // NOLINT(modernize-use-equals-default) std::string Evaluate( const std::vector<std::string>& parameters, @@ -1475,7 +1546,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode static const struct CompileFeaturesNode : public cmGeneratorExpressionNode { - CompileFeaturesNode() {} + CompileFeaturesNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return OneOrMoreParameters; } @@ -1600,7 +1671,7 @@ cmPolicies::PolicyID policyForString(const char* policy_id) static const struct TargetPolicyNode : public cmGeneratorExpressionNode { - TargetPolicyNode() {} + TargetPolicyNode() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 1; } @@ -1628,7 +1699,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode switch (statusForTarget(context->HeadTarget, policy)) { case cmPolicies::WARN: lg->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(policyForString(policy))); CM_FALLTHROUGH; case cmPolicies::REQUIRED_IF_USED: @@ -1661,7 +1732,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode static const struct InstallPrefixNode : public cmGeneratorExpressionNode { - InstallPrefixNode() {} + InstallPrefixNode() {} // NOLINT(modernize-use-equals-default) bool GeneratesContent() const override { return true; } int NumExpectedParameters() const override { return 0; } @@ -1882,7 +1953,7 @@ struct TargetFilesystemArtifactResultGetter<ArtifactPathTag> template <typename ArtifactT, typename ComponentT> struct TargetFilesystemArtifact : public cmGeneratorExpressionNode { - TargetFilesystemArtifact() {} + TargetFilesystemArtifact() {} // NOLINT(modernize-use-equals-default) int NumExpectedParameters() const override { return 1; } @@ -1938,7 +2009,9 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode template <typename ArtifactT> struct TargetFilesystemArtifactNodeGroup { - TargetFilesystemArtifactNodeGroup() {} + TargetFilesystemArtifactNodeGroup() // NOLINT(modernize-use-equals-default) + { + } TargetFilesystemArtifact<ArtifactT, ArtifactPathTag> File; TargetFilesystemArtifact<ArtifactT, ArtifactNameTag> FileName; @@ -1966,7 +2039,7 @@ static const TargetFilesystemArtifact<ArtifactBundleContentDirTag, static const struct ShellPathNode : public cmGeneratorExpressionNode { - ShellPathNode() {} + ShellPathNode() {} // NOLINT(modernize-use-equals-default) std::string Evaluate( const std::vector<std::string>& parameters, @@ -1997,6 +2070,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( nodeMap["NOT"] = ¬Node; nodeMap["C_COMPILER_ID"] = &cCompilerIdNode; nodeMap["CXX_COMPILER_ID"] = &cxxCompilerIdNode; + nodeMap["Fortran_COMPILER_ID"] = &fortranCompilerIdNode; nodeMap["VERSION_GREATER"] = &versionGreaterNode; nodeMap["VERSION_GREATER_EQUAL"] = &versionGreaterEqNode; nodeMap["VERSION_LESS"] = &versionLessNode; @@ -2004,6 +2078,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( nodeMap["VERSION_EQUAL"] = &versionEqualNode; nodeMap["C_COMPILER_VERSION"] = &cCompilerVersionNode; nodeMap["CXX_COMPILER_VERSION"] = &cxxCompilerVersionNode; + nodeMap["Fortran_COMPILER_VERSION"] = &fortranCompilerVersionNode; nodeMap["PLATFORM_ID"] = &platformIdNode; nodeMap["COMPILE_FEATURES"] = &compileFeaturesNode; nodeMap["CONFIGURATION"] = &configurationNode; @@ -2070,6 +2145,6 @@ void reportError(cmGeneratorExpressionContext* context, << " " << expr << "\n" << result; /* clang-format on */ - context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - context->Backtrace); + context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), context->Backtrace); } diff --git a/Source/cmGeneratorExpressionNode.h b/Source/cmGeneratorExpressionNode.h index ece1c113c..3dbfc6e5e 100644 --- a/Source/cmGeneratorExpressionNode.h +++ b/Source/cmGeneratorExpressionNode.h @@ -22,7 +22,7 @@ struct cmGeneratorExpressionNode OneOrMoreParameters = -1, OneOrZeroParameters = -2 }; - virtual ~cmGeneratorExpressionNode() {} + virtual ~cmGeneratorExpressionNode() = default; virtual bool GeneratesContent() const { return true; } diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx index 489970ce3..949a86d81 100644 --- a/Source/cmGeneratorExpressionParser.cxx +++ b/Source/cmGeneratorExpressionParser.cxx @@ -9,8 +9,8 @@ #include <utility> cmGeneratorExpressionParser::cmGeneratorExpressionParser( - const std::vector<cmGeneratorExpressionToken>& tokens) - : Tokens(tokens) + std::vector<cmGeneratorExpressionToken> tokens) + : Tokens(std::move(tokens)) , NestingLevel(0) { } diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h index 633381c8a..e663496da 100644 --- a/Source/cmGeneratorExpressionParser.h +++ b/Source/cmGeneratorExpressionParser.h @@ -13,8 +13,7 @@ struct cmGeneratorExpressionEvaluator; struct cmGeneratorExpressionParser { - cmGeneratorExpressionParser( - const std::vector<cmGeneratorExpressionToken>& tokens); + cmGeneratorExpressionParser(std::vector<cmGeneratorExpressionToken> tokens); void Parse(std::vector<cmGeneratorExpressionEvaluator*>& result); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 5c294f8c4..25349d42e 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -14,6 +14,7 @@ #include <stdlib.h> #include <string.h> #include <unordered_set> +#include <utility> #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" @@ -25,6 +26,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPropertyMap.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" @@ -201,7 +203,7 @@ std::string cmGeneratorTarget::GetExportName() const std::ostringstream e; e << "EXPORT_NAME property \"" << exportName << "\" for \"" << this->GetName() << "\": is not valid."; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return ""; } return exportName; @@ -318,7 +320,7 @@ std::string cmGeneratorTarget::GetOutputName( props.push_back(configUpper + "_OUTPUT_NAME"); } // OUTPUT_NAME - props.push_back("OUTPUT_NAME"); + props.emplace_back("OUTPUT_NAME"); std::string outName; for (std::string const& p : props) { @@ -340,7 +342,7 @@ std::string cmGeneratorTarget::GetOutputName( // An empty map entry indicates we have been called recursively // from the above block. this->LocalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Target '" + this->GetName() + "' OUTPUT_NAME depends on itself.", this->GetBacktrace()); } @@ -354,20 +356,22 @@ void cmGeneratorTarget::ClearSourcesCache() this->Objects.clear(); } -void cmGeneratorTarget::AddSourceCommon(const std::string& src) +void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(lfbt); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src); cge->SetEvaluateForBuildsystem(true); - this->SourceEntries.push_back(new TargetPropertyEntry(std::move(cge))); + this->SourceEntries.insert(before ? this->SourceEntries.begin() + : this->SourceEntries.end(), + new TargetPropertyEntry(std::move(cge))); this->ClearSourcesCache(); } -void cmGeneratorTarget::AddSource(const std::string& src) +void cmGeneratorTarget::AddSource(const std::string& src, bool before) { - this->Target->AddSource(src); - this->AddSourceCommon(src); + this->Target->AddSource(src, before); + this->AddSourceCommon(src, before); } void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs) @@ -386,12 +390,10 @@ void cmGeneratorTarget::AddIncludeDirectory(const std::string& src, cmGeneratorExpression ge(lfbt); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src); cge->SetEvaluateForBuildsystem(true); - // Insert before begin/end - std::vector<TargetPropertyEntry*>::iterator pos = before - ? this->IncludeDirectoriesEntries.begin() - : this->IncludeDirectoriesEntries.end(); this->IncludeDirectoriesEntries.insert( - pos, new TargetPropertyEntry(std::move(cge))); + before ? this->IncludeDirectoriesEntries.begin() + : this->IncludeDirectoriesEntries.end(), + new TargetPropertyEntry(std::move(cge))); } std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends( @@ -435,14 +437,14 @@ static void handleSystemIncludesDep( /* clang-format off */ #define IMPLEMENT_VISIT(KIND) \ - { \ + do { \ KindedSources const& kinded = this->GetKindedSources(config); \ for (SourceAndKind const& s : kinded.Sources) { \ if (s.Kind == KIND) { \ - data.push_back(s.Source); \ + data.push_back(s.Source.Value); \ } \ } \ - } + } while (false) /* clang-format on */ void cmGeneratorTarget::GetObjectSources( @@ -495,6 +497,25 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature, return this->LocalGenerator->GetFeature(feature, config); } +const char* cmGeneratorTarget::GetLinkPIEProperty( + const std::string& config) const +{ + static std::string PICValue; + + PICValue = this->GetLinkInterfaceDependentStringAsBoolProperty( + "POSITION_INDEPENDENT_CODE", config); + + if (PICValue == "(unset)") { + // POSITION_INDEPENDENT_CODE is not set + return nullptr; + } + + auto status = this->GetPolicyStatusCMP0083(); + return (status != cmPolicies::WARN && status != cmPolicies::OLD) + ? PICValue.c_str() + : nullptr; +} + bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, std::string const& config) const { @@ -529,7 +550,7 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target " << "'" << this->GetName() << "'."; this->LocalGenerator->GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace()); + MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace()); this->PolicyReportedCMP0069 = true; } @@ -560,7 +581,7 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, this->PolicyReportedCMP0069 = true; this->LocalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, message, this->GetBacktrace()); + MessageType::FATAL_ERROR, message, this->GetBacktrace()); return false; } @@ -674,13 +695,13 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const { if (!this->UtilityItemsDone) { this->UtilityItemsDone = true; - std::set<std::string> const& utilities = this->GetUtilities(); - for (std::string const& i : utilities) { + std::set<BT<std::string>> const& utilities = this->GetUtilities(); + for (BT<std::string> const& i : utilities) { if (cmGeneratorTarget* gt = - this->LocalGenerator->FindGeneratorTargetToUse(i)) { - this->UtilityItems.insert(cmLinkItem(gt)); + this->LocalGenerator->FindGeneratorTargetToUse(i.Value)) { + this->UtilityItems.insert(cmLinkItem(gt, i.Backtrace)); } else { - this->UtilityItems.insert(cmLinkItem(i)); + this->UtilityItems.insert(cmLinkItem(i.Value, i.Backtrace)); } } } @@ -865,7 +886,8 @@ static void AddObjectEntries( static bool processSources( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<std::string>& srcs, std::unordered_set<std::string>& uniqueSrcs, + std::vector<BT<std::string>>& srcs, + std::unordered_set<std::string>& uniqueSrcs, cmGeneratorExpressionDAGChecker* dagChecker, std::string const& config, bool debugSources) { @@ -893,7 +915,7 @@ static bool processSources( if (fullPath.empty()) { if (!e.empty()) { cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, e, tgt->GetBacktrace()); + cm->IssueMessage(MessageType::FATAL_ERROR, e, tgt->GetBacktrace()); } return contextDependent; } @@ -908,7 +930,8 @@ static bool processSources( err << "Found relative path while evaluating sources of \"" << tgt->GetName() << "\":\n \"" << src << "\"\n"; } - tgt->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, err.str()); + tgt->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR, + err.str()); return contextDependent; } src = fullPath; @@ -916,7 +939,7 @@ static bool processSources( std::string usedSources; for (std::string const& src : entrySources) { if (uniqueSrcs.insert(src).second) { - srcs.push_back(src); + srcs.emplace_back(src, entry->ge->GetBacktrace()); if (debugSources) { usedSources += " * " + src + "\n"; } @@ -924,7 +947,7 @@ static bool processSources( } if (!usedSources.empty()) { tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::LOG, + MessageType::LOG, std::string("Used sources for target ") + tgt->GetName() + ":\n" + usedSources, entry->ge->GetBacktrace()); @@ -933,9 +956,10 @@ static bool processSources( return contextDependent; } -void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files, - const std::string& config) const +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()) { @@ -951,13 +975,13 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files, cmSystemTools::ExpandListArgument(entry, items); for (std::string const& item : items) { if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") && - item[item.size() - 1] == '>') { + item.back() == '>') { continue; } - files.push_back(item); + files.emplace_back(item); } } - return; + return files; } std::vector<std::string> debugProperties; @@ -1009,11 +1033,23 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files, cmDeleteAll(linkInterfaceSourcesEntries); cmDeleteAll(linkObjectsEntries); + return files; } void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files, const std::string& config) const { + std::vector<BT<cmSourceFile*>> tmp = this->GetSourceFiles(config); + files.reserve(tmp.size()); + for (BT<cmSourceFile*>& v : tmp) { + files.push_back(v.Value); + } +} + +std::vector<BT<cmSourceFile*>> cmGeneratorTarget::GetSourceFiles( + std::string const& config) const +{ + std::vector<BT<cmSourceFile*>> files; if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) { // Since we are still configuring not all sources may exist yet, // so we need to avoid full source classification because that @@ -1021,16 +1057,15 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files, // Since this is only for compatibility with old policies that // projects should not depend on anymore, just compute the files // without memoizing them. - std::vector<std::string> srcs; - this->GetSourceFiles(srcs, config); + std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config); std::set<cmSourceFile*> emitted; - for (std::string const& s : srcs) { - cmSourceFile* sf = this->Makefile->GetOrCreateSource(s); + for (BT<std::string> const& s : srcs) { + cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value); if (emitted.insert(sf).second) { - files.push_back(sf); + files.emplace_back(sf, s.Backtrace); } } - return; + return files; } KindedSources const& kinded = this->GetKindedSources(config); @@ -1038,18 +1073,33 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files, for (SourceAndKind const& si : kinded.Sources) { files.push_back(si.Source); } + return files; } void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries( std::vector<cmSourceFile*>& files, const std::string& config) const { + std::vector<BT<cmSourceFile*>> tmp = + this->GetSourceFilesWithoutObjectLibraries(config); + files.reserve(tmp.size()); + for (BT<cmSourceFile*>& v : tmp) { + files.push_back(v.Value); + } +} + +std::vector<BT<cmSourceFile*>> +cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries( + std::string const& config) const +{ + std::vector<BT<cmSourceFile*>> files; KindedSources const& kinded = this->GetKindedSources(config); files.reserve(kinded.Sources.size()); for (SourceAndKind const& si : kinded.Sources) { - if (si.Source->GetObjectLibrary().empty()) { + if (si.Source.Value->GetObjectLibrary().empty()) { files.push_back(si.Source); } } + return files; } cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources( @@ -1071,7 +1121,7 @@ cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources( << "\" use a generator expression that depends on the " "SOURCES themselves."; this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + MessageType::FATAL_ERROR, e.str(), this->GetBacktrace()); static KindedSources empty; return empty; } @@ -1089,16 +1139,15 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, std::string const& config) const { // Get the source file paths by string. - std::vector<std::string> srcs; - this->GetSourceFiles(srcs, config); + std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config); cmsys::RegularExpression header_regex(CM_HEADER_REGEX); std::vector<cmSourceFile*> badObjLib; std::set<cmSourceFile*> emitted; - for (std::string const& s : srcs) { + for (BT<std::string> const& s : srcs) { // Create each source at most once. - cmSourceFile* sf = this->Makefile->GetOrCreateSource(s); + cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value); if (!emitted.insert(sf).second) { continue; } @@ -1161,7 +1210,7 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, } // Save this classified source file in the result vector. - files.Sources.push_back({ sf, kind }); + files.Sources.push_back({ BT<cmSourceFile*>(sf, s.Backtrace), kind }); } if (!badObjLib.empty()) { @@ -1173,7 +1222,7 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, e << "but may contain only sources that compile, header files, and " "other files that would not affect linking of a normal library."; this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + MessageType::FATAL_ERROR, e.str(), this->GetBacktrace()); } } @@ -1197,14 +1246,14 @@ void cmGeneratorTarget::ComputeAllConfigSources() const KindedSources const& sources = this->GetKindedSources(configs[ci]); for (SourceAndKind const& src : sources.Sources) { std::map<cmSourceFile const*, size_t>::iterator mi = - index.find(src.Source); + index.find(src.Source.Value); if (mi == index.end()) { AllConfigSource acs; - acs.Source = src.Source; + acs.Source = src.Source.Value; acs.Kind = src.Kind; this->AllConfigSources.push_back(std::move(acs)); std::map<cmSourceFile const*, size_t>::value_type entry( - src.Source, this->AllConfigSources.size() - 1); + src.Source.Value, this->AllConfigSources.size() - 1); mi = index.insert(entry).first; } this->AllConfigSources[mi->second].Configs.push_back(ci); @@ -1331,7 +1380,7 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall( /* clang-format on */ cmake* cm = this->LocalGenerator->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace()); + cm->IssueMessage(MessageType::FATAL_ERROR, w.str(), this->GetBacktrace()); } return have_rpath; @@ -1462,7 +1511,7 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir( w << " less than 10.5 or because CMake's platform configuration is"; w << " corrupt."; cmake* cm = this->LocalGenerator->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace()); + cm->IssueMessage(MessageType::FATAL_ERROR, w.str(), this->GetBacktrace()); } return true; @@ -1710,17 +1759,11 @@ cmListFileBacktrace cmGeneratorTarget::GetBacktrace() const return this->Target->GetBacktrace(); } -const std::set<std::string>& cmGeneratorTarget::GetUtilities() const +const std::set<BT<std::string>>& cmGeneratorTarget::GetUtilities() const { return this->Target->GetUtilities(); } -const cmListFileBacktrace* cmGeneratorTarget::GetUtilityBacktrace( - const std::string& u) const -{ - return this->Target->GetUtilityBacktrace(u); -} - bool cmGeneratorTarget::HaveWellDefinedOutputFiles() const { return this->GetType() == cmStateEnums::STATIC_LIBRARY || @@ -1730,7 +1773,7 @@ bool cmGeneratorTarget::HaveWellDefinedOutputFiles() const this->GetType() == cmStateEnums::EXECUTABLE; } -const char* cmGeneratorTarget::GetExportMacro() const +const std::string* cmGeneratorTarget::GetExportMacro() const { // Define the symbol for targets that export symbols. if (this->GetType() == cmStateEnums::SHARED_LIBRARY || @@ -1743,7 +1786,7 @@ const char* cmGeneratorTarget::GetExportMacro() const in += "_EXPORTS"; this->ExportMacro = cmSystemTools::MakeCidentifier(in); } - return this->ExportMacro.c_str(); + return &this->ExportMacro; } return nullptr; } @@ -1752,10 +1795,10 @@ class cmTargetCollectLinkLanguages { public: cmTargetCollectLinkLanguages(cmGeneratorTarget const* target, - const std::string& config, + std::string config, std::unordered_set<std::string>& languages, cmGeneratorTarget const* head) - : Config(config) + : Config(std::move(config)) , Languages(languages) , HeadTarget(head) , Target(target) @@ -1768,13 +1811,13 @@ public: if (!item.Target) { if (item.AsStr().find("::") != std::string::npos) { bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; std::ostringstream e; switch (this->Target->GetLocalGenerator()->GetPolicyStatus( cmPolicies::CMP0028)) { case cmPolicies::WARN: { e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n"; - messageType = cmake::AUTHOR_WARNING; + messageType = MessageType::AUTHOR_WARNING; } break; case cmPolicies::OLD: noMessage = true; @@ -1877,7 +1920,7 @@ public: } e << "Set the LINKER_LANGUAGE property for this target."; cmake* cm = this->Target->GetLocalGenerator()->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, e.str(), + cm->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Target->GetBacktrace()); } return *this->Preferred.begin(); @@ -2002,7 +2045,7 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo( msg += this->GetName(); msg += " which has type "; msg += cmState::GetTargetTypeName(this->GetType()); - this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); return nullptr; } @@ -2188,7 +2231,7 @@ cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target) << "\"\ndepends on the sources of a target it is used in. This " "is a dependency loop and is not allowed."; this->GeneratorTarget->LocalGenerator->IssueMessage( - cmake::FATAL_ERROR, e.str()); + MessageType::FATAL_ERROR, e.str()); return; } if (emitted.insert(sf).second && @@ -2480,7 +2523,7 @@ std::string cmGeneratorTarget::GetCreateRuleVariable( static void processIncludeDirectories( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<std::string>& includes, + std::vector<BT<std::string>>& includes, std::unordered_set<std::string>& uniqueIncludes, cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, bool debugIncludes, const std::string& language) @@ -2500,14 +2543,14 @@ static void processIncludeDirectories( for (std::string& entryInclude : entryIncludes) { if (fromImported && !cmSystemTools::FileExists(entryInclude)) { std::ostringstream e; - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; if (checkCMP0027) { switch (tgt->GetPolicyStatusCMP0027()) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n"; CM_FALLTHROUGH; case cmPolicies::OLD: - messageType = cmake::AUTHOR_WARNING; + messageType = MessageType::AUTHOR_WARNING; break; case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: @@ -2533,7 +2576,7 @@ static void processIncludeDirectories( if (!cmSystemTools::FileIsFullPath(entryInclude)) { std::ostringstream e; bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; if (!targetName.empty()) { /* clang-format off */ e << "Target \"" << targetName << "\" contains relative " @@ -2544,7 +2587,7 @@ static void processIncludeDirectories( switch (tgt->GetPolicyStatusCMP0021()) { case cmPolicies::WARN: { e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0021) << "\n"; - messageType = cmake::AUTHOR_WARNING; + messageType = MessageType::AUTHOR_WARNING; } break; case cmPolicies::OLD: noMessage = true; @@ -2560,7 +2603,7 @@ static void processIncludeDirectories( } if (!noMessage) { tgt->GetLocalGenerator()->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return; } } @@ -2572,7 +2615,7 @@ static void processIncludeDirectories( std::string inc = entryInclude; if (uniqueIncludes.insert(inc).second) { - includes.push_back(inc); + includes.emplace_back(inc, entry->ge->GetBacktrace()); if (debugIncludes) { usedIncludes += " * " + inc + "\n"; } @@ -2580,7 +2623,7 @@ static void processIncludeDirectories( } if (!usedIncludes.empty()) { tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::LOG, + MessageType::LOG, std::string("Used includes for target ") + tgt->GetName() + ":\n" + usedIncludes, entry->ge->GetBacktrace()); @@ -2588,10 +2631,10 @@ static void processIncludeDirectories( } } -std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories( +std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( const std::string& config, const std::string& lang) const { - std::vector<std::string> includes; + std::vector<BT<std::string>> includes; std::unordered_set<std::string> uniqueIncludes; cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES", @@ -2661,7 +2704,7 @@ enum class OptionsParse static void processOptionsInternal( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<std::string>& options, + std::vector<BT<std::string>>& options, std::unordered_set<std::string>& uniqueOptions, cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, bool debugOptions, const char* logName, std::string const& language, @@ -2678,9 +2721,13 @@ static void processOptionsInternal( if (uniqueOptions.insert(opt).second) { if (parse == OptionsParse::Shell && cmHasLiteralPrefix(opt, "SHELL:")) { - cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, options); + std::vector<std::string> tmp; + cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp); + for (std::string& o : tmp) { + options.emplace_back(std::move(o), entry->ge->GetBacktrace()); + } } else { - options.push_back(opt); + options.emplace_back(opt, entry->ge->GetBacktrace()); } if (debugOptions) { usedOptions += " * " + opt + "\n"; @@ -2689,7 +2736,7 @@ static void processOptionsInternal( } if (!usedOptions.empty()) { tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::LOG, + MessageType::LOG, std::string("Used ") + logName + std::string(" for target ") + tgt->GetName() + ":\n" + usedOptions, entry->ge->GetBacktrace()); @@ -2700,7 +2747,7 @@ static void processOptionsInternal( static void processCompileOptions( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<std::string>& options, + std::vector<BT<std::string>>& options, std::unordered_set<std::string>& uniqueOptions, cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, bool debugOptions, std::string const& language) @@ -2714,6 +2761,17 @@ void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const { + std::vector<BT<std::string>> tmp = this->GetCompileOptions(config, language); + result.reserve(tmp.size()); + for (BT<std::string>& v : tmp) { + result.emplace_back(std::move(v.Value)); + } +} + +std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions( + std::string const& config, std::string const& language) const +{ + std::vector<BT<std::string>> result; std::unordered_set<std::string> uniqueOptions; cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr, @@ -2749,12 +2807,13 @@ void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result, language); cmDeleteAll(linkInterfaceCompileOptionsEntries); + return result; } static void processCompileFeatures( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<std::string>& options, + std::vector<BT<std::string>>& options, std::unordered_set<std::string>& uniqueOptions, cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, bool debugOptions) @@ -2767,6 +2826,17 @@ static void processCompileFeatures( void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result, const std::string& config) const { + std::vector<BT<std::string>> tmp = this->GetCompileFeatures(config); + result.reserve(tmp.size()); + for (BT<std::string>& v : tmp) { + result.emplace_back(std::move(v.Value)); + } +} + +std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures( + std::string const& config) const +{ + std::vector<BT<std::string>> result; std::unordered_set<std::string> uniqueFeatures; cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr, @@ -2799,12 +2869,13 @@ void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result, uniqueFeatures, &dagChecker, config, debugFeatures); cmDeleteAll(linkInterfaceCompileFeaturesEntries); + return result; } static void processCompileDefinitions( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<std::string>& options, + std::vector<BT<std::string>>& options, std::unordered_set<std::string>& uniqueOptions, cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, bool debugOptions, std::string const& language) @@ -2815,9 +2886,21 @@ static void processCompileDefinitions( } void cmGeneratorTarget::GetCompileDefinitions( - std::vector<std::string>& list, const std::string& config, + std::vector<std::string>& result, const std::string& config, const std::string& language) const { + std::vector<BT<std::string>> tmp = + this->GetCompileDefinitions(config, language); + result.reserve(tmp.size()); + for (BT<std::string>& v : tmp) { + result.emplace_back(std::move(v.Value)); + } +} + +std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( + std::string const& config, std::string const& language) const +{ + std::vector<BT<std::string>> list; std::unordered_set<std::string> uniqueOptions; cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS", @@ -2855,7 +2938,8 @@ void cmGeneratorTarget::GetCompileDefinitions( case cmPolicies::WARN: { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043); - this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, + e.str()); CM_FALLTHROUGH; } case cmPolicies::OLD: { @@ -2878,13 +2962,14 @@ void cmGeneratorTarget::GetCompileDefinitions( language); cmDeleteAll(linkInterfaceCompileDefinitionsEntries); + return list; } namespace { void processLinkOptions( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<std::string>& options, + std::vector<BT<std::string>>& options, std::unordered_set<std::string>& uniqueOptions, cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, bool debugOptions, std::string const& language) @@ -2899,6 +2984,17 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const { + std::vector<BT<std::string>> tmp = this->GetLinkOptions(config, language); + result.reserve(tmp.size()); + for (BT<std::string>& v : tmp) { + result.emplace_back(std::move(v.Value)); + } +} + +std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( + std::string const& config, std::string const& language) const +{ + std::vector<BT<std::string>> result; std::unordered_set<std::string> uniqueOptions; cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr, @@ -2952,21 +3048,24 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result, const std::string SHELL{ "SHELL:" }; const std::string LINKER_SHELL = LINKER + SHELL; - std::vector<std::string>::iterator entry; + std::vector<BT<std::string>>::iterator entry; while ((entry = std::find_if(result.begin(), result.end(), - [&LINKER](const std::string& item) -> bool { - return item.compare(0, LINKER.length(), - LINKER) == 0; + [&LINKER](BT<std::string> const& item) -> bool { + return item.Value.compare(0, LINKER.length(), + LINKER) == 0; })) != result.end()) { + std::string value = std::move(entry->Value); + cmListFileBacktrace bt = std::move(entry->Backtrace); + entry = result.erase(entry); + std::vector<std::string> linkerOptions; - if (entry->compare(0, LINKER_SHELL.length(), LINKER_SHELL) == 0) { + if (value.compare(0, LINKER_SHELL.length(), LINKER_SHELL) == 0) { cmSystemTools::ParseUnixCommandLine( - entry->c_str() + LINKER_SHELL.length(), linkerOptions); + value.c_str() + LINKER_SHELL.length(), linkerOptions); } else { linkerOptions = - cmSystemTools::tokenize(entry->substr(LINKER.length()), ","); + cmSystemTools::tokenize(value.substr(LINKER.length()), ","); } - entry = result.erase(entry); if (linkerOptions.empty() || (linkerOptions.size() == 1 && linkerOptions.front().empty())) { @@ -2979,59 +3078,67 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result, return item.find(SHELL) != std::string::npos; }) != linkerOptions.end()) { this->LocalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "'SHELL:' prefix is not supported as part of 'LINKER:' arguments.", this->GetBacktrace()); - return; + return result; } + std::vector<BT<std::string>> options; if (wrapperFlag.empty()) { // nothing specified, insert elements as is - result.insert(entry, linkerOptions.begin(), linkerOptions.end()); + options.reserve(linkerOptions.size()); + for (std::string& o : linkerOptions) { + options.emplace_back(std::move(o), bt); + } } else { - std::vector<std::string> options; - if (!wrapperSep.empty()) { if (concatFlagAndArgs) { // insert flag elements except last one - options.insert(options.end(), wrapperFlag.begin(), - wrapperFlag.end() - 1); + for (auto i = wrapperFlag.begin(); i != wrapperFlag.end() - 1; ++i) { + options.emplace_back(*i, bt); + } // concatenate last flag element and all LINKER list values // in one option - options.push_back(wrapperFlag.back() + - cmJoin(linkerOptions, wrapperSep)); + options.emplace_back( + wrapperFlag.back() + cmJoin(linkerOptions, wrapperSep), bt); } else { - options.insert(options.end(), wrapperFlag.begin(), - wrapperFlag.end()); + for (std::string const& i : wrapperFlag) { + options.emplace_back(i, bt); + } // concatenate all LINKER list values in one option - options.push_back(cmJoin(linkerOptions, wrapperSep)); + options.emplace_back(cmJoin(linkerOptions, wrapperSep), bt); } } else { // prefix each element of LINKER list with wrapper if (concatFlagAndArgs) { - std::transform( - linkerOptions.begin(), linkerOptions.end(), linkerOptions.begin(), - [&wrapperFlag](const std::string& value) -> std::string { - return wrapperFlag.back() + value; - }); + std::transform(linkerOptions.begin(), linkerOptions.end(), + linkerOptions.begin(), + [&wrapperFlag](std::string const& o) -> std::string { + return wrapperFlag.back() + o; + }); } - for (const auto& value : linkerOptions) { - options.insert(options.end(), wrapperFlag.begin(), - concatFlagAndArgs ? wrapperFlag.end() - 1 - : wrapperFlag.end()); - options.push_back(value); + for (std::string& o : linkerOptions) { + for (auto i = wrapperFlag.begin(), + e = concatFlagAndArgs ? wrapperFlag.end() - 1 + : wrapperFlag.end(); + i != e; ++i) { + options.emplace_back(*i, bt); + } + options.emplace_back(std::move(o), bt); } } - result.insert(entry, options.begin(), options.end()); } + result.insert(entry, options.begin(), options.end()); } + return result; } namespace { void processStaticLibraryLinkOptions( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<std::string>& options, + std::vector<BT<std::string>>& options, std::unordered_set<std::string>& uniqueOptions, cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, std::string const& language) @@ -3046,6 +3153,18 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions( std::vector<std::string>& result, const std::string& config, const std::string& language) const { + std::vector<BT<std::string>> tmp = + this->GetStaticLibraryLinkOptions(config, language); + result.reserve(tmp.size()); + for (BT<std::string>& v : tmp) { + result.emplace_back(std::move(v.Value)); + } +} + +std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions( + std::string const& config, std::string const& language) const +{ + std::vector<BT<std::string>> result; std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries; std::unordered_set<std::string> uniqueOptions; @@ -3066,13 +3185,14 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions( &dagChecker, config, language); cmDeleteAll(entries); + return result; } namespace { void processLinkDirectories( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<std::string>& directories, + std::vector<BT<std::string>>& directories, std::unordered_set<std::string>& uniqueDirectories, cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, bool debugDirectories, std::string const& language) @@ -3092,7 +3212,7 @@ void processLinkDirectories( if (!cmSystemTools::FileIsFullPath(entryDirectory)) { std::ostringstream e; bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; if (!targetName.empty()) { /* clang-format off */ e << "Target \"" << targetName << "\" contains relative " @@ -3103,7 +3223,7 @@ void processLinkDirectories( switch (tgt->GetPolicyStatusCMP0081()) { case cmPolicies::WARN: { e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0081) << "\n"; - messageType = cmake::AUTHOR_WARNING; + messageType = MessageType::AUTHOR_WARNING; } break; case cmPolicies::OLD: noMessage = true; @@ -3120,7 +3240,7 @@ void processLinkDirectories( } if (!noMessage) { tgt->GetLocalGenerator()->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return; } } @@ -3130,7 +3250,7 @@ void processLinkDirectories( // in case projects set the LINK_DIRECTORIES property directly. cmSystemTools::ConvertToUnixSlashes(entryDirectory); if (uniqueDirectories.insert(entryDirectory).second) { - directories.push_back(entryDirectory); + directories.emplace_back(entryDirectory); if (debugDirectories) { usedDirectories += " * " + entryDirectory + "\n"; } @@ -3138,7 +3258,7 @@ void processLinkDirectories( } if (!usedDirectories.empty()) { tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::LOG, + MessageType::LOG, std::string("Used link directories for target ") + tgt->GetName() + ":\n" + usedDirectories, entry->ge->GetBacktrace()); @@ -3151,6 +3271,18 @@ void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result, const std::string& config, const std::string& language) const { + std::vector<BT<std::string>> tmp = + this->GetLinkDirectories(config, language); + result.reserve(tmp.size()); + for (BT<std::string>& v : tmp) { + result.emplace_back(std::move(v.Value)); + } +} + +std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories( + std::string const& config, std::string const& language) const +{ + std::vector<BT<std::string>> result; std::unordered_set<std::string> uniqueDirectories; cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr, @@ -3186,13 +3318,14 @@ void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result, debugDirectories, language); cmDeleteAll(linkInterfaceLinkDirectoriesEntries); + return result; } namespace { void processLinkDepends( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<std::string>& options, + std::vector<BT<std::string>>& options, std::unordered_set<std::string>& uniqueOptions, cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, std::string const& language) @@ -3207,6 +3340,17 @@ void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result, const std::string& config, const std::string& language) const { + std::vector<BT<std::string>> tmp = this->GetLinkDepends(config, language); + result.reserve(tmp.size()); + for (BT<std::string>& v : tmp) { + result.emplace_back(std::move(v.Value)); + } +} + +std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends( + std::string const& config, std::string const& language) const +{ + std::vector<BT<std::string>> result; std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries; std::unordered_set<std::string> uniqueOptions; cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr, @@ -3228,6 +3372,7 @@ void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result, &dagChecker, config, language); cmDeleteAll(linkDependsEntries); + return result; } void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const @@ -3293,10 +3438,9 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const { - std::vector<std::string> features; - this->GetCompileFeatures(features, config); - for (std::string const& f : features) { - if (!this->Makefile->AddRequiredTargetFeature(this->Target, f)) { + std::vector<BT<std::string>> features = this->GetCompileFeatures(config); + for (BT<std::string> const& f : features) { + if (!this->Makefile->AddRequiredTargetFeature(this->Target, f.Value)) { return false; } } @@ -3360,7 +3504,7 @@ std::string cmGeneratorTarget::NormalGetRealName( if (this->IsImported()) { std::string msg = "NormalGetRealName called on imported target: "; msg += this->GetName(); - this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); } if (this->GetType() == cmStateEnums::EXECUTABLE) { @@ -3394,7 +3538,7 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName, if (this->IsImported()) { std::string msg = "GetLibraryNames called on imported target: "; msg += this->GetName(); - this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); return; } @@ -3471,7 +3615,7 @@ void cmGeneratorTarget::GetExecutableNames(std::string& name, if (this->IsImported()) { std::string msg = "GetExecutableNames called on imported target: "; msg += this->GetName(); - this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); } // This versioning is supported only for executables and then only @@ -3684,7 +3828,7 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const } // PDB_NAME - props.push_back("PDB_NAME"); + props.emplace_back("PDB_NAME"); for (std::string const& p : props) { if (const char* outName = this->GetProperty(p)) { @@ -3704,6 +3848,13 @@ std::string cmGeneratorTarget::GetObjectDirectory( // find and replace $(PROJECT_NAME) xcode placeholder const std::string projectName = this->LocalGenerator->GetProjectName(); cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName); + // Replace Xcode's placeholder for the object file directory since + // installation and export scripts need to know the real directory. + // Xcode has build-time settings (e.g. for sanitizers) that affect this, + // but we use the default here. Users that want to enable sanitizers + // will do so at the cost of object library installation and export. + cmSystemTools::ReplaceString(obj_dir, "$(OBJECT_FILE_DIR_normal:base)", + "Objects-normal"); #endif return obj_dir; } @@ -3972,7 +4123,8 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender, "This is not allowed. Only user-defined properties may appear " "listed in the " << propName << " property."; - depender->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str()); + depender->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR, + e.str()); return; } if (emitted.insert(p).second) { @@ -4112,10 +4264,33 @@ void cmGeneratorTarget::CheckPropertyCompatibility( "in a boolean interpretation, a numeric minimum, a numeric maximum " "or a " "string interpretation, but not a mixture."; - this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str()); } } +template <typename PropertyType> +std::string valueAsString(PropertyType); +template <> +std::string valueAsString<bool>(bool value) +{ + return value ? "TRUE" : "FALSE"; +} +template <> +std::string valueAsString<const char*>(const char* value) +{ + return value ? value : "(unset)"; +} +template <> +std::string valueAsString<std::string>(std::string value) +{ + return value; +} +template <> +std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/) +{ + return "(unset)"; +} + std::string compatibilityType(CompatibleType t) { switch (t) { @@ -4147,34 +4322,49 @@ std::string compatibilityAgree(CompatibleType t, bool dominant) } template <typename PropertyType> -PropertyType getTypedProperty(cmGeneratorTarget const* tgt, - const std::string& prop); +PropertyType getTypedProperty( + cmGeneratorTarget const* tgt, const std::string& prop, + cmGeneratorExpressionInterpreter* genexInterpreter = nullptr); template <> bool getTypedProperty<bool>(cmGeneratorTarget const* tgt, - const std::string& prop) + const std::string& prop, + cmGeneratorExpressionInterpreter* genexInterpreter) { - return tgt->GetPropertyAsBool(prop); -} + if (genexInterpreter == nullptr) { + return tgt->GetPropertyAsBool(prop); + } -template <> -const char* getTypedProperty<const char*>(cmGeneratorTarget const* tgt, - const std::string& prop) -{ - return tgt->GetProperty(prop); + const char* value = tgt->GetProperty(prop); + return cmSystemTools::IsOn(genexInterpreter->Evaluate(value, prop)); } -template <typename PropertyType> -std::string valueAsString(PropertyType); template <> -std::string valueAsString<bool>(bool value) +const char* getTypedProperty<const char*>( + cmGeneratorTarget const* tgt, const std::string& prop, + cmGeneratorExpressionInterpreter* genexInterpreter) { - return value ? "TRUE" : "FALSE"; + const char* value = tgt->GetProperty(prop); + + if (genexInterpreter == nullptr) { + return value; + } + + return genexInterpreter->Evaluate(value, prop).c_str(); } + template <> -std::string valueAsString<const char*>(const char* value) +std::string getTypedProperty<std::string>( + cmGeneratorTarget const* tgt, const std::string& prop, + cmGeneratorExpressionInterpreter* genexInterpreter) { - return value ? value : "(unset)"; + const char* value = tgt->GetProperty(prop); + + if (genexInterpreter == nullptr) { + return valueAsString(value); + } + + return genexInterpreter->Evaluate(value, prop); } template <typename PropertyType> @@ -4189,6 +4379,11 @@ const char* impliedValue<const char*>(const char* /*unused*/) { return ""; } +template <> +std::string impliedValue<std::string>(std::string /*unused*/) // NOLINT(*) +{ + return std::string(); +} template <typename PropertyType> std::pair<bool, PropertyType> consistentProperty(PropertyType lhs, @@ -4209,6 +4404,13 @@ std::pair<bool, const char*> consistentStringProperty(const char* lhs, return std::make_pair(b, b ? lhs : nullptr); } +std::pair<bool, std::string> consistentStringProperty(const std::string& lhs, + const std::string& rhs) +{ + const bool b = lhs == rhs; + return std::make_pair(b, b ? lhs : valueAsString(nullptr)); +} + std::pair<bool, const char*> consistentNumberProperty(const char* lhs, const char* rhs, CompatibleType t) @@ -4251,9 +4453,10 @@ std::pair<bool, const char*> consistentProperty(const char* lhs, const char* const null_ptr = nullptr; switch (t) { - case BoolType: - assert(false && "consistentProperty for strings called with BoolType"); - return std::pair<bool, const char*>(false, null_ptr); + case BoolType: { + bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs); + return std::make_pair(same, same ? lhs : nullptr); + } case StringType: return consistentStringProperty(lhs, rhs); case NumberMinType: @@ -4264,6 +4467,40 @@ std::pair<bool, const char*> consistentProperty(const char* lhs, return std::pair<bool, const char*>(false, null_ptr); } +std::pair<bool, std::string> consistentProperty(const std::string& lhs, + const std::string& rhs, + CompatibleType t) +{ + const std::string null_ptr = valueAsString(nullptr); + + if (lhs == null_ptr && rhs == null_ptr) { + return std::make_pair(true, lhs); + } + if (lhs == null_ptr) { + return std::make_pair(true, rhs); + } + if (rhs == null_ptr) { + return std::make_pair(true, lhs); + } + + switch (t) { + case BoolType: { + bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs); + return std::make_pair(same, same ? lhs : null_ptr); + } + case StringType: + return consistentStringProperty(lhs, rhs); + case NumberMinType: + case NumberMaxType: { + auto value = consistentNumberProperty(lhs.c_str(), rhs.c_str(), t); + return std::make_pair( + value.first, value.first ? std::string(value.second) : null_ptr); + } + } + assert(false && "Unreachable!"); + return std::pair<bool, std::string>(false, null_ptr); +} + template <typename PropertyType> PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, const std::string& p, @@ -4273,6 +4510,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, PropertyType* /*unused*/) { PropertyType propContent = getTypedProperty<PropertyType>(tgt, p); + std::vector<std::string> headPropKeys = tgt->GetPropertyKeys(); const bool explicitlySet = std::find(headPropKeys.begin(), headPropKeys.end(), p) != @@ -4302,6 +4540,11 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, } std::string interfaceProperty = "INTERFACE_" + p; + std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter( + p == "POSITION_INDEPENDENT_CODE" ? new cmGeneratorExpressionInterpreter( + tgt->GetLocalGenerator(), config, tgt) + : nullptr); + for (cmGeneratorTarget const* theTarget : deps) { // An error should be reported if one dependency // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other @@ -4313,8 +4556,8 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, const bool ifaceIsSet = std::find(propKeys.begin(), propKeys.end(), interfaceProperty) != propKeys.end(); - PropertyType ifacePropContent = - getTypedProperty<PropertyType>(theTarget, interfaceProperty); + PropertyType ifacePropContent = getTypedProperty<PropertyType>( + theTarget, interfaceProperty, genexInterpreter.get()); std::string reportEntry; if (ifaceIsSet) { @@ -4340,7 +4583,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, << " property requirement\nof " "dependency \"" << theTarget->GetName() << "\".\n"; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); break; } propContent = consistent.second; @@ -4365,7 +4608,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, "already. The INTERFACE_" << p << " property on\ndependency \"" << theTarget->GetName() << "\" is in conflict.\n"; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); break; } propContent = consistent.second; @@ -4385,7 +4628,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, e << "The INTERFACE_" << p << " property of \"" << theTarget->GetName() << "\" does\nnot agree with the value of " << p << " already determined\nfor \"" << tgt->GetName() << "\".\n"; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); break; } propContent = consistent.second; @@ -4412,6 +4655,13 @@ bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty( BoolType, nullptr); } +std::string cmGeneratorTarget::GetLinkInterfaceDependentStringAsBoolProperty( + const std::string& p, const std::string& config) const +{ + return checkInterfacePropertyCompatibility<std::string>( + this, p, config, "FALSE", BoolType, nullptr); +} + const char* cmGeneratorTarget::GetLinkInterfaceDependentStringProperty( const std::string& p, const std::string& config) const { @@ -4614,10 +4864,12 @@ void cmGeneratorTarget::ReportPropertyOrigin( areport += result; areport += "\"):\n" + report; - this->LocalGenerator->GetCMakeInstance()->IssueMessage(cmake::LOG, areport); + this->LocalGenerator->GetCMakeInstance()->IssueMessage(MessageType::LOG, + areport); } void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, + cmListFileBacktrace const& bt, std::vector<cmLinkItem>& items) const { for (std::string const& n : names) { @@ -4625,7 +4877,7 @@ void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, if (name == this->GetName() || name.empty()) { continue; } - items.push_back(this->ResolveLinkItem(name)); + items.push_back(this->ResolveLinkItem(name, bt)); } } @@ -4647,7 +4899,7 @@ void cmGeneratorTarget::ExpandLinkItems( false, headTarget, this, &dagChecker), libs); - this->LookupLinkItems(libs, items); + this->LookupLinkItems(libs, cge->GetBacktrace(), items); hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); } @@ -4842,7 +5094,7 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo( msg += this->GetName(); msg += " which has type "; msg += cmState::GetTargetTypeName(this->GetType()); - this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); return nullptr; } @@ -4873,7 +5125,7 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo( // An empty map entry indicates we have been called recursively // from the above block. this->LocalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Target '" + this->GetName() + "' OUTPUT_DIRECTORY depends on itself.", this->GetBacktrace()); return nullptr; @@ -5093,7 +5345,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( linkIfaceProp << ":\n" " " << explicitLibraries << "\n"; /* clang-format on */ - this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); this->PolicyWarnedCMP0022 = true; } } @@ -5162,7 +5414,8 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( "Link implementation:\n" " " << oldLibraries << "\n"; /* clang-format on */ - this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, + w.str()); this->PolicyWarnedCMP0022 = true; } } @@ -5200,7 +5453,7 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( iface.HadHeadSensitiveCondition); std::vector<std::string> deps; cmSystemTools::ExpandListArgument(info->SharedDeps, deps); - this->LookupLinkItems(deps, iface.SharedDeps); + this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps); } return &iface; @@ -5470,7 +5723,7 @@ bool cmGeneratorTarget::GetConfigCommonSourceFiles( "Config \"" << *it << "\":\n" " " << thisConfigFiles << "\n"; /* clang-format on */ - this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } } @@ -5490,8 +5743,7 @@ void cmGeneratorTarget::GetObjectLibrariesCMP0026( std::vector<std::string> files; cmSystemTools::ExpandListArgument(entry, files); for (std::string const& li : files) { - if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && - li[li.size() - 1] == '>') { + if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && li.back() == '>') { std::string objLibName = li.substr(17, li.size() - 18); if (cmGeneratorExpression::Find(objLibName) != std::string::npos) { @@ -5529,7 +5781,8 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0004) << "\n" << "Target \"" << this->GetName() << "\" links to item \"" << item << "\" which has leading or trailing whitespace."; - cm->IssueMessage(cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace()); + cm->IssueMessage(MessageType::AUTHOR_WARNING, w.str(), + this->GetBacktrace()); } case cmPolicies::OLD: break; @@ -5538,7 +5791,8 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const e << "Target \"" << this->GetName() << "\" links to item \"" << item << "\" which has leading or trailing whitespace. " << "This is now an error according to policy CMP0004."; - cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + cm->IssueMessage(MessageType::FATAL_ERROR, e.str(), + this->GetBacktrace()); } break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: { @@ -5546,7 +5800,8 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0004) << "\n" << "Target \"" << this->GetName() << "\" links to item \"" << item << "\" which has leading or trailing whitespace."; - cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + cm->IssueMessage(MessageType::FATAL_ERROR, e.str(), + this->GetBacktrace()); } break; } } @@ -5710,12 +5965,12 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( if (name == this->GetName() || name.empty()) { if (name == this->GetName()) { bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; + MessageType messageType = MessageType::FATAL_ERROR; std::ostringstream e; switch (this->GetPolicyStatusCMP0038()) { case cmPolicies::WARN: { e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0038) << "\n"; - messageType = cmake::AUTHOR_WARNING; + messageType = MessageType::AUTHOR_WARNING; } break; case cmPolicies::OLD: noMessage = true; @@ -5730,7 +5985,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( e << "Target \"" << this->GetName() << "\" links to itself."; this->LocalGenerator->GetCMakeInstance()->IssueMessage( messageType, e.str(), this->GetBacktrace()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return; } } @@ -5739,7 +5994,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - impl.Libraries.emplace_back(this->ResolveLinkItem(name), *btIt, + impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt), evaluated != *le); } @@ -5767,7 +6022,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( continue; } // Support OLD behavior for CMP0003. - impl.WrongConfigLibraries.push_back(this->ResolveLinkItem(name)); + impl.WrongConfigLibraries.push_back( + this->ResolveLinkItem(name, cmListFileBacktrace())); } } } @@ -5814,12 +6070,13 @@ cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( return resolved; } -cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const +cmLinkItem cmGeneratorTarget::ResolveLinkItem( + std::string const& name, cmListFileBacktrace const& bt) const { TargetOrString resolved = this->ResolveTargetReference(name); if (!resolved.Target) { - return cmLinkItem(resolved.String); + return cmLinkItem(resolved.String, bt); } // Skip targets that will not really be linked. This is probably a @@ -5827,10 +6084,10 @@ cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const // within the project. if (resolved.Target->GetType() == cmStateEnums::EXECUTABLE && !resolved.Target->IsExecutableWithExports()) { - return cmLinkItem(resolved.Target->GetName()); + return cmLinkItem(resolved.Target->GetName(), bt); } - return cmLinkItem(resolved.Target); + return cmLinkItem(resolved.Target, bt); } std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const @@ -5880,7 +6137,7 @@ bool cmGeneratorTarget::HasImportLibrary(std::string const& config) const std::string cmGeneratorTarget::GetSupportDirectory() const { std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory(); - dir += cmake::GetCMakeFilesDirectory(); + dir += "/CMakeFiles"; dir += "/"; dir += this->GetName(); #if defined(__VMS) diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 5ed8e5ace..59d38afd7 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -27,12 +27,13 @@ class cmTarget; class cmGeneratorTarget { - CM_DISABLE_COPY(cmGeneratorTarget) - public: cmGeneratorTarget(cmTarget*, cmLocalGenerator* lg); ~cmGeneratorTarget(); + cmGeneratorTarget(cmGeneratorTarget const&) = delete; + cmGeneratorTarget& operator=(cmGeneratorTarget const&) = delete; + cmLocalGenerator* GetLocalGenerator() const; cmGlobalGenerator* GetGlobalGenerator() const; @@ -75,8 +76,8 @@ public: bool GetPropertyAsBool(const std::string& prop) const; void GetSourceFiles(std::vector<cmSourceFile*>& files, const std::string& config) const; - void GetSourceFilesWithoutObjectLibraries(std::vector<cmSourceFile*>& files, - const std::string& config) const; + std::vector<BT<cmSourceFile*>> GetSourceFiles( + std::string const& config) const; /** Source file kinds (classifications). Generators use this to decide how to treat a source file. */ @@ -99,7 +100,7 @@ public: /** A source file paired with a kind (classification). */ struct SourceAndKind { - cmSourceFile* Source; + BT<cmSourceFile*> Source; SourceKind Kind; }; @@ -110,11 +111,7 @@ public: std::set<std::string> ExpectedResxHeaders; std::set<std::string> ExpectedXamlHeaders; std::set<std::string> ExpectedXamlSources; - bool Initialized; - KindedSources() - : Initialized(false) - { - } + bool Initialized = false; }; /** Get all sources needed for a configuration with kinds assigned. */ @@ -173,6 +170,8 @@ public: const char* GetFeature(const std::string& feature, const std::string& config) const; + const char* GetLinkPIEProperty(const std::string& config) const; + bool IsIPOEnabled(std::string const& lang, std::string const& config) const; bool IsLinkInterfaceDependentBoolProperty(const std::string& p, @@ -273,8 +272,7 @@ public: cmListFileBacktrace GetBacktrace() const; - std::set<std::string> const& GetUtilities() const; - cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const; + std::set<BT<std::string>> const& GetUtilities() const; bool LinkLanguagePropagatesToDependents() const { @@ -283,7 +281,7 @@ public: /** Get the macro to define when building sources in this target. If no macro should be defined null is returned. */ - const char* GetExportMacro() const; + const std::string* GetExportMacro() const; /** Get the soname of the target. Allowed only for a shared library. */ std::string GetSOName(const std::string& config) const; @@ -362,7 +360,8 @@ public: }; TargetOrString ResolveTargetReference(std::string const& name) const; - cmLinkItem ResolveLinkItem(std::string const& name) const; + cmLinkItem ResolveLinkItem(std::string const& name, + cmListFileBacktrace const& bt) const; // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change @@ -408,34 +407,49 @@ public: std::string const& config) const; /** Get the include directories for this target. */ - std::vector<std::string> GetIncludeDirectories( + std::vector<BT<std::string>> GetIncludeDirectories( const std::string& config, const std::string& lang) const; void GetCompileOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const; + std::vector<BT<std::string>> GetCompileOptions( + std::string const& config, std::string const& language) const; void GetCompileFeatures(std::vector<std::string>& features, const std::string& config) const; + std::vector<BT<std::string>> GetCompileFeatures( + std::string const& config) const; void GetCompileDefinitions(std::vector<std::string>& result, const std::string& config, const std::string& language) const; + std::vector<BT<std::string>> GetCompileDefinitions( + std::string const& config, std::string const& language) const; void GetLinkOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const; + std::vector<BT<std::string>> GetLinkOptions( + std::string const& config, std::string const& language) const; + void GetStaticLibraryLinkOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const; + std::vector<BT<std::string>> GetStaticLibraryLinkOptions( + std::string const& config, std::string const& language) const; void GetLinkDirectories(std::vector<std::string>& result, const std::string& config, const std::string& language) const; + std::vector<BT<std::string>> GetLinkDirectories( + std::string const& config, std::string const& language) const; void GetLinkDepends(std::vector<std::string>& result, const std::string& config, const std::string& language) const; + std::vector<BT<std::string>> GetLinkDepends( + std::string const& config, std::string const& language) const; bool IsSystemIncludeDirectory(const std::string& dir, const std::string& config, @@ -522,7 +536,7 @@ public: */ void ClearSourcesCache(); - void AddSource(const std::string& src); + void AddSource(const std::string& src, bool before = false); void AddTracedSources(std::vector<std::string> const& srcs); /** @@ -548,13 +562,8 @@ public: }; struct SourceFileFlags { - SourceFileFlags() - : Type(SourceFileTypeNormal) - , MacFolder(nullptr) - { - } - SourceFileType Type; - const char* MacFolder; // location inside Mac content folders + SourceFileType Type = SourceFileTypeNormal; + const char* MacFolder = nullptr; // location inside Mac content folders }; void GetAutoUicOptions(std::vector<std::string>& result, const std::string& config) const; @@ -684,7 +693,7 @@ public: const char* GetSourcesProperty() const; private: - void AddSourceCommon(const std::string& src); + void AddSourceCommon(const std::string& src, bool before = false); std::string CreateFortranModuleDirectory( std::string const& working_dir) const; @@ -740,11 +749,7 @@ private: struct CompatibleInterfaces : public CompatibleInterfacesBase { - CompatibleInterfaces() - : Done(false) - { - } - bool Done; + bool Done = false; }; mutable std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap; @@ -757,11 +762,7 @@ private: struct LinkImplClosure : public std::vector<cmGeneratorTarget const*> { - LinkImplClosure() - : Done(false) - { - } - bool Done; + bool Done = false; }; mutable std::map<std::string, LinkImplClosure> LinkImplClosureMap; @@ -774,18 +775,15 @@ private: cmHeadToLinkInterfaceMap& GetHeadToLinkInterfaceUsageRequirementsMap( std::string const& config) const; + std::string GetLinkInterfaceDependentStringAsBoolProperty( + const std::string& p, const std::string& config) const; + // Cache import information from properties for each configuration. struct ImportInfo { - ImportInfo() - : NoSOName(false) - , Managed(Native) - , Multiplicity(0) - { - } - bool NoSOName; - ManagedType Managed; - unsigned int Multiplicity; + bool NoSOName = false; + ManagedType Managed = Native; + unsigned int Multiplicity = 0; std::string Location; std::string SOName; std::string ImportLibrary; @@ -834,10 +832,15 @@ private: std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const; void LookupLinkItems(std::vector<std::string> const& names, + cmListFileBacktrace const& bt, std::vector<cmLinkItem>& items) const; - void GetSourceFiles(std::vector<std::string>& files, - const std::string& config) const; + std::vector<BT<std::string>> GetSourceFilePaths( + std::string const& config) const; + std::vector<BT<cmSourceFile*>> GetSourceFilesWithoutObjectLibraries( + std::string const& config) const; + void GetSourceFilesWithoutObjectLibraries(std::vector<cmSourceFile*>& files, + const std::string& config) const; struct HeadToLinkImplementationMap : public std::map<cmGeneratorTarget const*, cmOptionalLinkImplementation> diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index 0d4d6534c..a92eb7186 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -4,9 +4,9 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -76,7 +76,7 @@ bool cmGetDirectoryPropertyCommand::InitialPass( switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0059)) { case cmPolicies::WARN: this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0059)); CM_FALLTHROUGH; case cmPolicies::OLD: diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index 1b358aba8..163b4c8ab 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -19,8 +19,8 @@ bool cmGetFilenameComponentCommand::InitialPass( // Check and see if the value has been stored in the cache // already, if so use that value - if (args.size() >= 4 && args[args.size() - 1] == "CACHE") { - const char* cacheValue = this->Makefile->GetDefinition(args[0]); + if (args.size() >= 4 && args.back() == "CACHE") { + const char* cacheValue = this->Makefile->GetDefinition(args.front()); if (cacheValue && !cmSystemTools::IsNOTFOUND(cacheValue)) { return true; } @@ -88,6 +88,10 @@ bool cmGetFilenameComponentCommand::InitialPass( result = cmSystemTools::GetFilenameExtension(filename); } else if (args[2] == "NAME_WE") { result = cmSystemTools::GetFilenameWithoutExtension(filename); + } else if (args[2] == "LAST_EXT") { + result = cmSystemTools::GetFilenameLastExtension(filename); + } else if (args[2] == "NAME_WLE") { + result = cmSystemTools::GetFilenameWithoutLastExtension(filename); } else if (args[2] == "ABSOLUTE" || args[2] == "REALPATH") { // If the path given is relative, evaluate it relative to the // current source directory unless the user passes a different @@ -113,20 +117,20 @@ bool cmGetFilenameComponentCommand::InitialPass( return false; } - if (args.size() >= 4 && args[args.size() - 1] == "CACHE") { + if (args.size() >= 4 && args.back() == "CACHE") { if (!programArgs.empty() && !storeArgs.empty()) { this->Makefile->AddCacheDefinition( storeArgs, programArgs.c_str(), "", args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING); } this->Makefile->AddCacheDefinition( - args[0], result.c_str(), "", + args.front(), result.c_str(), "", args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING); } else { if (!programArgs.empty() && !storeArgs.empty()) { this->Makefile->AddDefinition(storeArgs, programArgs.c_str()); } - this->Makefile->AddDefinition(args[0], result.c_str()); + this->Makefile->AddDefinition(args.front(), result.c_str()); } return true; diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 1d812bd28..039f43922 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -8,6 +8,7 @@ #include "cmInstalledFile.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmProperty.h" #include "cmPropertyDefinition.h" @@ -230,7 +231,7 @@ bool cmGetPropertyCommand::HandleDirectoryMode() if (this->PropertyName == "DEFINITIONS") { switch (mf->GetPolicyStatus(cmPolicies::CMP0059)) { case cmPolicies::WARN: - mf->IssueMessage(cmake::AUTHOR_WARNING, + mf->IssueMessage(MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0059)); CM_FALLTHROUGH; case cmPolicies::OLD: diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index ec485aa3e..fc0e9c693 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -6,10 +6,10 @@ #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmTarget.h" #include "cmTargetPropertyComputer.h" -#include "cmake.h" class cmExecutionStatus; class cmMessenger; @@ -52,7 +52,7 @@ bool cmGetTargetPropertyCommand::InitialPass( } else { bool issueMessage = false; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0045)) { case cmPolicies::WARN: issueMessage = true; @@ -63,13 +63,13 @@ bool cmGetTargetPropertyCommand::InitialPass( case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: issueMessage = true; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (issueMessage) { e << "get_target_property() called with non-existent target \"" << targetName << "\"."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } diff --git a/Source/cmGhsMultiGpj.cxx b/Source/cmGhsMultiGpj.cxx index f58cfc1e5..c1f0742f2 100644 --- a/Source/cmGhsMultiGpj.cxx +++ b/Source/cmGhsMultiGpj.cxx @@ -4,31 +4,34 @@ #include "cmGeneratedFileStream.h" -void GhsMultiGpj::WriteGpjTag(Types const gpjType, - cmGeneratedFileStream* const filestream) +static const char* GHS_TAG[] = { "[INTEGRITY Application]", + "[Library]", + "[Project]", + "[Program]", + "[Reference]", + "[Subproject]" }; + +const char* GhsMultiGpj::GetGpjTag(Types const gpjType) { char const* tag; switch (gpjType) { case INTERGRITY_APPLICATION: - tag = "INTEGRITY Application"; - break; case LIBRARY: - tag = "Library"; - break; case PROJECT: - tag = "Project"; - break; case PROGRAM: - tag = "Program"; - break; case REFERENCE: - tag = "Reference"; - break; case SUBPROJECT: - tag = "Subproject"; + tag = GHS_TAG[gpjType]; break; default: tag = ""; } - *filestream << "[" << tag << "]" << std::endl; + return tag; +} + +void GhsMultiGpj::WriteGpjTag(Types const gpjType, std::ostream& fout) +{ + char const* tag; + tag = GhsMultiGpj::GetGpjTag(gpjType); + fout << tag << std::endl; } diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h index b1eead101..6d59225da 100644 --- a/Source/cmGhsMultiGpj.h +++ b/Source/cmGhsMultiGpj.h @@ -4,6 +4,7 @@ #define cmGhsMultiGpj_h #include "cmConfigure.h" // IWYU pragma: keep +#include <iosfwd> class cmGeneratedFileStream; @@ -20,8 +21,9 @@ public: SUBPROJECT }; - static void WriteGpjTag(Types const gpjType, - cmGeneratedFileStream* filestream); + static void WriteGpjTag(Types const gpjType, std::ostream& fout); + + static const char* GetGpjTag(Types const gpjType); }; #endif // ! cmGhsMultiGpjType_h diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 847230a82..5fe350c10 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGhsMultiTargetGenerator.h" +#include "cmComputeLinkInformation.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGhsMultiGenerator.h" @@ -9,177 +10,128 @@ #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" #include "cmSourceFile.h" +#include "cmSourceGroup.h" #include "cmTarget.h" -#include <assert.h> - -std::string const cmGhsMultiTargetGenerator::DDOption("-dynamic"); cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target) : GeneratorTarget(target) , LocalGenerator( static_cast<cmLocalGhsMultiGenerator*>(target->GetLocalGenerator())) , Makefile(target->Target->GetMakefile()) - , TargetGroup(DetermineIfTargetGroup(target)) - , DynamicDownload(false) -{ - this->RelBuildFilePath = this->GetRelBuildFilePath(target); - - this->RelOutputFileName = this->RelBuildFilePath + target->GetName() + ".a"; - - this->RelBuildFileName = this->RelBuildFilePath; - this->RelBuildFileName += this->GetBuildFileName(target); - - std::string absPathToRoot = this->GetAbsPathToRoot(target); - absPathToRoot = this->AddSlashIfNeededToPath(absPathToRoot); - this->AbsBuildFilePath = absPathToRoot + this->RelBuildFilePath; - this->AbsBuildFileName = absPathToRoot + this->RelBuildFileName; - this->AbsOutputFileName = absPathToRoot + this->RelOutputFileName; -} - -cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator() + , Name(target->GetName()) { - cmDeleteAll(this->FolderBuildStreams); -} - -std::string cmGhsMultiTargetGenerator::GetRelBuildFilePath( - const cmGeneratorTarget* target) -{ - std::string output = target->GetEffectiveFolderName(); - cmSystemTools::ConvertToUnixSlashes(output); - if (!output.empty()) { - output += "/"; + // Store the configuration name that is being used + if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { + // Use the build type given by the user. + this->ConfigName = config; + } else { + // No configuration type given. + this->ConfigName.clear(); } - output += target->GetName() + "/"; - return output; -} - -std::string cmGhsMultiTargetGenerator::GetAbsPathToRoot( - const cmGeneratorTarget* target) -{ - return target->GetLocalGenerator()->GetBinaryDirectory(); } -std::string cmGhsMultiTargetGenerator::GetAbsBuildFilePath( - const cmGeneratorTarget* target) -{ - std::string output; - output = cmGhsMultiTargetGenerator::GetAbsPathToRoot(target); - output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output); - output += cmGhsMultiTargetGenerator::GetRelBuildFilePath(target); - return output; -} - -std::string cmGhsMultiTargetGenerator::GetRelBuildFileName( - const cmGeneratorTarget* target) -{ - std::string output; - output = cmGhsMultiTargetGenerator::GetRelBuildFilePath(target); - output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output); - output += cmGhsMultiTargetGenerator::GetBuildFileName(target); - return output; -} - -std::string cmGhsMultiTargetGenerator::GetBuildFileName( - const cmGeneratorTarget* target) -{ - std::string output; - output = target->GetName(); - output += cmGlobalGhsMultiGenerator::FILE_EXTENSION; - return output; -} - -std::string cmGhsMultiTargetGenerator::AddSlashIfNeededToPath( - std::string const& input) +cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator() { - std::string output(input); - if (!cmHasLiteralSuffix(output, "/")) { - output += "/"; - } - return output; } void cmGhsMultiTargetGenerator::Generate() { - std::vector<cmSourceFile*> objectSources = this->GetSources(); - if (!objectSources.empty() && this->IncludeThisTarget()) { - if (!cmSystemTools::FileExists(this->AbsBuildFilePath.c_str())) { - cmSystemTools::MakeDirectory(this->AbsBuildFilePath.c_str()); + // Determine type of target for this project + switch (this->GeneratorTarget->GetType()) { + case cmStateEnums::EXECUTABLE: { + // Get the name of the executable to generate. + std::string targetName; + std::string targetNameImport; + std::string targetNamePDB; + this->GeneratorTarget->GetExecutableNames( + targetName, this->TargetNameReal, targetNameImport, targetNamePDB, + this->ConfigName); + if (cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()) { + this->TagType = GhsMultiGpj::INTERGRITY_APPLICATION; + } else { + this->TagType = GhsMultiGpj::PROGRAM; + } + break; + } + case cmStateEnums::STATIC_LIBRARY: { + std::string targetName; + std::string targetNameSO; + std::string targetNameImport; + std::string targetNamePDB; + this->GeneratorTarget->GetLibraryNames( + targetName, targetNameSO, this->TargetNameReal, targetNameImport, + targetNamePDB, this->ConfigName); + this->TagType = GhsMultiGpj::LIBRARY; + break; + } + case cmStateEnums::SHARED_LIBRARY: { + std::string msg = "add_library(<name> SHARED ...) not supported: "; + msg += this->Name; + cmSystemTools::Message(msg); + return; } - cmGlobalGhsMultiGenerator::Open(std::string(""), this->AbsBuildFileName, - &this->FolderBuildStreams); - cmGlobalGhsMultiGenerator::OpenBuildFileStream( - this->GetFolderBuildStreams()); - std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - if (0 == config.length()) { - config = "RELEASE"; + case cmStateEnums::OBJECT_LIBRARY: { + std::string targetName; + std::string targetNameSO; + std::string targetNameImport; + std::string targetNamePDB; + this->GeneratorTarget->GetLibraryNames( + targetName, targetNameSO, this->TargetNameReal, targetNameImport, + targetNamePDB, this->ConfigName); + this->TagType = GhsMultiGpj::SUBPROJECT; + break; } - const std::string language( - this->GeneratorTarget->GetLinkerLanguage(config)); - config = cmSystemTools::UpperCase(config); - this->DynamicDownload = this->DetermineIfDynamicDownload(config, language); - if (this->DynamicDownload) { - *this->GetFolderBuildStreams() - << "#component integrity_dynamic_download" << std::endl; + case cmStateEnums::MODULE_LIBRARY: { + std::string msg = "add_library(<name> MODULE ...) not supported: "; + msg += this->Name; + cmSystemTools::Message(msg); + return; } - GhsMultiGpj::WriteGpjTag(this->GetGpjTag(), this->GetFolderBuildStreams()); - cmGlobalGhsMultiGenerator::WriteDisclaimer(this->GetFolderBuildStreams()); - - bool const notKernel = this->IsNotKernel(config, language); - this->WriteTypeSpecifics(config, notKernel); - this->SetCompilerFlags(config, language, notKernel); - this->WriteCompilerFlags(config, language); - this->WriteCompilerDefinitions(config, language); - this->WriteIncludes(config, language); - if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - this->WriteTargetLinkLibraries(config, language); + case cmStateEnums::UTILITY: { + std::string msg = "add_custom_target(<name> ...) not supported: "; + msg += this->Name; + cmSystemTools::Message(msg); + return; } - this->WriteCustomCommands(); + default: + return; + } - std::map<const cmSourceFile*, std::string> objectNames = - cmGhsMultiTargetGenerator::GetObjectNames( - &objectSources, this->LocalGenerator, this->GeneratorTarget); + // Tell the global generator the name of the project file + this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", + this->Name.c_str()); + this->GeneratorTarget->Target->SetProperty( + "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType)); - this->WriteSources(objectSources, objectNames); - } + this->GenerateTarget(); } -bool cmGhsMultiTargetGenerator::IncludeThisTarget() +void cmGhsMultiTargetGenerator::GenerateTarget() { - bool output = true; - char const* excludeFromAll = - this->GeneratorTarget->GetProperty("EXCLUDE_FROM_ALL"); - if (NULL != excludeFromAll && '1' == excludeFromAll[0] && - '\0' == excludeFromAll[1]) { - output = false; - } - return output; -} + // Open the filestream in copy-if-different mode. + std::string fname = this->LocalGenerator->GetCurrentBinaryDirectory(); + fname += "/"; + fname += this->Name; + fname += cmGlobalGhsMultiGenerator::FILE_EXTENSION; + cmGeneratedFileStream fout(fname.c_str()); + fout.SetCopyIfDifferent(true); -std::vector<cmSourceFile*> cmGhsMultiTargetGenerator::GetSources() const -{ - std::vector<cmSourceFile*> output; - std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - this->GeneratorTarget->GetSourceFiles(output, config); - return output; -} + this->GetGlobalGenerator()->WriteFileHeader(fout); + GhsMultiGpj::WriteGpjTag(this->TagType, fout); -GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag() const -{ - return cmGhsMultiTargetGenerator::GetGpjTag(this->GeneratorTarget); -} + const std::string language( + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName)); -GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag( - const cmGeneratorTarget* target) -{ - GhsMultiGpj::Types output; - if (cmGhsMultiTargetGenerator::DetermineIfTargetGroup(target)) { - output = GhsMultiGpj::INTERGRITY_APPLICATION; - } else if (target->GetType() == cmStateEnums::STATIC_LIBRARY) { - output = GhsMultiGpj::LIBRARY; - } else { - output = GhsMultiGpj::PROGRAM; - } - return output; + this->WriteTargetSpecifics(fout, this->ConfigName); + this->SetCompilerFlags(this->ConfigName, language); + this->WriteCompilerFlags(fout, this->ConfigName, language); + this->WriteCompilerDefinitions(fout, this->ConfigName, language); + this->WriteIncludes(fout, this->ConfigName, language); + this->WriteTargetLinkLine(fout, this->ConfigName); + this->WriteCustomCommands(fout); + this->WriteSources(fout); + this->WriteReferences(fout); + fout.Close(); } cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator() @@ -189,41 +141,28 @@ cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator() this->LocalGenerator->GetGlobalGenerator()); } -void cmGhsMultiTargetGenerator::WriteTypeSpecifics(const std::string& config, - bool const notKernel) +void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout, + const std::string& config) { - std::string outputDir(this->GetOutputDirectory(config)); - std::string outputFilename(this->GetOutputFilename(config)); - - if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) { - std::string const static_library_suffix = - this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"); - *this->GetFolderBuildStreams() - << " -o \"" << outputDir << outputFilename << static_library_suffix - << "\"" << std::endl; - } else if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - if (notKernel && !this->IsTargetGroup()) { - *this->GetFolderBuildStreams() << " -relprog" << std::endl; - } - if (this->IsTargetGroup()) { - *this->GetFolderBuildStreams() - << " -o \"" << outputDir << outputFilename << ".elf\"" << std::endl; - *this->GetFolderBuildStreams() - << " :extraOutputFile=\"" << outputDir << outputFilename - << ".elf.ael\"" << std::endl; - } else { - std::string const executable_suffix = - this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX"); - *this->GetFolderBuildStreams() - << " -o \"" << outputDir << outputFilename << executable_suffix - << "\"" << std::endl; - } + std::string outpath; + std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory(); + + if (this->TagType != GhsMultiGpj::SUBPROJECT) { + // set target binary file destination + outpath = this->GeneratorTarget->GetDirectory(config); + outpath = + this->LocalGenerator->MaybeConvertToRelativePath(rootpath, outpath); + fout << " :binDirRelative=\"" << outpath << "\"" << std::endl; + fout << " -o \"" << this->TargetNameReal << "\"" << std::endl; } + + // set target object file destination + outpath = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + fout << " :outputDirRelative=\"" << outpath << "\"" << std::endl; } void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, - const std::string& language, - bool const notKernel) + const std::string& language) { std::map<std::string, std::string>::iterator i = this->FlagsByLanguage.find(language); @@ -231,14 +170,9 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, std::string flags; const char* lang = language.c_str(); - if (notKernel) { - this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, - lang, config); - } else { - this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, - lang + std::string("_GHS_KERNEL"), - config); - } + this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, lang, + config); + this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, lang, config); this->LocalGenerator->AddVisibilityPresetFlags( @@ -267,14 +201,9 @@ std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language, if (i == this->DefinesByLanguage.end()) { std::set<std::string> defines; const char* lang = language.c_str(); - // Add the export symbol definition for shared library objects. - if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) { - this->LocalGenerator->AppendDefines(defines, exportMacro); - } - // Add preprocessor definitions for this target and configuration. - this->LocalGenerator->AddCompileDefinitions(defines, this->GeneratorTarget, - config, language); + this->LocalGenerator->GetTargetDefines(this->GeneratorTarget, config, + language, defines); std::string definesString; this->LocalGenerator->JoinDefines(defines, definesString, lang); @@ -286,21 +215,25 @@ std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language, return i->second; } -void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::string const&, +void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::ostream& fout, + std::string const&, const std::string& language) { std::map<std::string, std::string>::iterator flagsByLangI = this->FlagsByLanguage.find(language); if (flagsByLangI != this->FlagsByLanguage.end()) { if (!flagsByLangI->second.empty()) { - *this->GetFolderBuildStreams() - << " " << flagsByLangI->second << std::endl; + std::vector<std::string> ghsCompFlags = + cmSystemTools::ParseArguments(flagsByLangI->second.c_str()); + for (auto& f : ghsCompFlags) { + fout << " " << f << std::endl; + } } } } void cmGhsMultiTargetGenerator::WriteCompilerDefinitions( - const std::string& config, const std::string& language) + std::ostream& fout, const std::string& config, const std::string& language) { std::vector<std::string> compileDefinitions; this->GeneratorTarget->GetCompileDefinitions(compileDefinitions, config, @@ -308,11 +241,12 @@ void cmGhsMultiTargetGenerator::WriteCompilerDefinitions( for (std::vector<std::string>::const_iterator cdI = compileDefinitions.begin(); cdI != compileDefinitions.end(); ++cdI) { - *this->GetFolderBuildStreams() << " -D" << (*cdI) << std::endl; + fout << " -D" << (*cdI) << std::endl; } } -void cmGhsMultiTargetGenerator::WriteIncludes(const std::string& config, +void cmGhsMultiTargetGenerator::WriteIncludes(std::ostream& fout, + const std::string& config, const std::string& language) { std::vector<std::string> includes; @@ -321,80 +255,73 @@ void cmGhsMultiTargetGenerator::WriteIncludes(const std::string& config, for (std::vector<std::string>::const_iterator includes_i = includes.begin(); includes_i != includes.end(); ++includes_i) { - *this->GetFolderBuildStreams() - << " -I\"" << *includes_i << "\"" << std::endl; + fout << " -I\"" << *includes_i << "\"" << std::endl; } } -void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries( - std::string const& config, std::string const& language) +void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, + std::string const& config) { - // library directories - cmTargetDependSet tds = - this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget); - for (cmTargetDependSet::iterator tdsI = tds.begin(); tdsI != tds.end(); - ++tdsI) { - const cmGeneratorTarget* tg = *tdsI; - *this->GetFolderBuildStreams() - << " -L\"" << GetAbsBuildFilePath(tg) << "\"" << std::endl; + if (this->TagType == GhsMultiGpj::INTERGRITY_APPLICATION) { + return; } - // library targets - cmTarget::LinkLibraryVectorType llv = - this->GeneratorTarget->Target->GetOriginalLinkLibraries(); - for (cmTarget::LinkLibraryVectorType::const_iterator llvI = llv.begin(); - llvI != llv.end(); ++llvI) { - std::string libName = llvI->first; - // if it is a user defined target get the full path to the lib - cmTarget* tg(GetGlobalGenerator()->FindTarget(libName)); - if (NULL != tg) { - libName = tg->GetName() + ".a"; - } - *this->GetFolderBuildStreams() - << " -l\"" << libName << "\"" << std::endl; + + std::string linkLibraries; + std::string flags; + std::string linkFlags; + std::string frameworkPath; + std::string linkPath; + + std::unique_ptr<cmLinkLineComputer> linkLineComputer( + this->GetGlobalGenerator()->CreateLinkLineComputer( + this->LocalGenerator, + this->LocalGenerator->GetStateSnapshot().GetDirectory())); + + this->LocalGenerator->GetTargetFlags( + linkLineComputer.get(), config, linkLibraries, flags, linkFlags, + frameworkPath, linkPath, this->GeneratorTarget); + + // write out link options + std::vector<std::string> lopts = + cmSystemTools::ParseArguments(linkFlags.c_str()); + for (auto& l : lopts) { + fout << " " << l << std::endl; } - if (!this->TargetGroup) { - std::string linkLibraries; - std::string flags; - std::string linkFlags; - std::string frameworkPath; - std::string linkPath; - std::string createRule = - this->GeneratorTarget->GetCreateRuleVariable(language, config); - bool useWatcomQuote = - this->Makefile->IsOn(createRule + "_USE_WATCOM_QUOTE"); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( - this->GetGlobalGenerator()->CreateLinkLineComputer( - this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); - linkLineComputer->SetUseWatcomQuote(useWatcomQuote); - - this->LocalGenerator->GetTargetFlags( - linkLineComputer.get(), config, linkLibraries, flags, linkFlags, - frameworkPath, linkPath, this->GeneratorTarget); - linkFlags = cmSystemTools::TrimWhitespace(linkFlags); - - if (!linkPath.empty()) { - linkPath = " " + linkPath.substr(0U, linkPath.size() - 1U); - *this->GetFolderBuildStreams() << linkPath; - } + // write out link search paths + // must be quoted for paths that contain spaces + std::vector<std::string> lpath = + cmSystemTools::ParseArguments(linkPath.c_str()); + for (auto& l : lpath) { + fout << " -L\"" << l << "\"" << std::endl; + } + + // write out link libs + // must be quoted for filepaths that contains spaces + std::string cbd = this->LocalGenerator->GetCurrentBinaryDirectory(); - if (!linkFlags.empty()) { - *this->GetFolderBuildStreams() << " " << linkFlags << std::endl; + std::vector<std::string> llibs = + cmSystemTools::ParseArguments(linkLibraries.c_str()); + for (auto& l : llibs) { + if (l.compare(0, 2, "-l") == 0) { + fout << " \"" << l << "\"" << std::endl; + } else { + std::string rl = cmSystemTools::CollapseCombinedPath(cbd, l); + fout << " -l\"" << rl << "\"" << std::endl; } } } -void cmGhsMultiTargetGenerator::WriteCustomCommands() +void cmGhsMultiTargetGenerator::WriteCustomCommands(std::ostream& fout) { - WriteCustomCommandsHelper(this->GeneratorTarget->GetPreBuildCommands(), + WriteCustomCommandsHelper(fout, this->GeneratorTarget->GetPreBuildCommands(), cmTarget::PRE_BUILD); - WriteCustomCommandsHelper(this->GeneratorTarget->GetPostBuildCommands(), - cmTarget::POST_BUILD); + WriteCustomCommandsHelper( + fout, this->GeneratorTarget->GetPostBuildCommands(), cmTarget::POST_BUILD); } void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( - std::vector<cmCustomCommand> const& commandsSet, + std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet, cmTarget::CustomCommandType const commandType) { for (std::vector<cmCustomCommand>::const_iterator commandsSetI = @@ -405,10 +332,10 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( commandI != commands.end(); ++commandI) { switch (commandType) { case cmTarget::PRE_BUILD: - *this->GetFolderBuildStreams() << " :preexecShellSafe="; + fout << " :preexecShellSafe="; break; case cmTarget::POST_BUILD: - *this->GetFolderBuildStreams() << " :postexecShellSafe="; + fout << " :postexecShellSafe="; break; default: assert("Only pre and post are supported"); @@ -419,243 +346,237 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( std::string subCommandE = this->LocalGenerator->EscapeForShell(*commandLineI, true); if (!command.empty()) { - *this->GetFolderBuildStreams() - << (command.begin() == commandLineI ? "'" : " "); + fout << (command.begin() == commandLineI ? "'" : " "); // Need to double escape backslashes cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\"); } - *this->GetFolderBuildStreams() << subCommandE; + fout << subCommandE; } if (!command.empty()) { - *this->GetFolderBuildStreams() << "'" << std::endl; + fout << "'" << std::endl; } } } } -std::map<const cmSourceFile*, std::string> -cmGhsMultiTargetGenerator::GetObjectNames( - std::vector<cmSourceFile*>* const objectSources, - cmLocalGhsMultiGenerator* const localGhsMultiGenerator, - cmGeneratorTarget* const generatorTarget) +void cmGhsMultiTargetGenerator::WriteSourceProperty(std::ostream& fout, + const cmSourceFile* sf, + std::string propName, + std::string propFlag) { - std::map<std::string, std::vector<cmSourceFile*>> filenameToSource; - std::map<cmSourceFile*, std::string> sourceToFilename; - for (std::vector<cmSourceFile*>::const_iterator sf = objectSources->begin(); - sf != objectSources->end(); ++sf) { - const std::string filename = - cmSystemTools::GetFilenameName((*sf)->GetFullPath()); - const std::string lower_filename = cmSystemTools::LowerCase(filename); - filenameToSource[lower_filename].push_back(*sf); - sourceToFilename[*sf] = lower_filename; - } - - std::vector<cmSourceFile*> duplicateSources; - for (std::map<std::string, std::vector<cmSourceFile*>>::const_iterator - msvSourceI = filenameToSource.begin(); - msvSourceI != filenameToSource.end(); ++msvSourceI) { - if (msvSourceI->second.size() > 1) { - duplicateSources.insert(duplicateSources.end(), - msvSourceI->second.begin(), - msvSourceI->second.end()); + const char* prop = sf->GetProperty(propName); + if (prop) { + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(prop, list); + for (auto& p : list) { + fout << " " << propFlag << p << std::endl; } } - - std::map<const cmSourceFile*, std::string> objectNamesCorrected; - - for (std::vector<cmSourceFile*>::const_iterator sf = - duplicateSources.begin(); - sf != duplicateSources.end(); ++sf) { - std::string const longestObjectDirectory( - cmGhsMultiTargetGenerator::ComputeLongestObjectDirectory( - localGhsMultiGenerator, generatorTarget, *sf)); - std::string objFilenameName = - localGhsMultiGenerator->GetObjectFileNameWithoutTarget( - **sf, longestObjectDirectory); - cmsys::SystemTools::ReplaceString(objFilenameName, "/", "_"); - objectNamesCorrected[*sf] = objFilenameName; - } - - return objectNamesCorrected; } -void cmGhsMultiTargetGenerator::WriteSources( - std::vector<cmSourceFile*> const& objectSources, - std::map<const cmSourceFile*, std::string> const& objectNames) +void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) { - for (std::vector<cmSourceFile*>::const_iterator si = objectSources.begin(); - si != objectSources.end(); ++si) { - std::vector<cmSourceGroup> sourceGroups(this->Makefile->GetSourceGroups()); - std::string const& sourceFullPath = (*si)->GetFullPath(); - cmSourceGroup* sourceGroup = - this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups); - std::string sgPath = sourceGroup->GetFullName(); - cmSystemTools::ConvertToUnixSlashes(sgPath); - cmGlobalGhsMultiGenerator::AddFilesUpToPath( - this->GetFolderBuildStreams(), &this->FolderBuildStreams, - this->LocalGenerator->GetBinaryDirectory().c_str(), sgPath, - GhsMultiGpj::SUBPROJECT, this->RelBuildFilePath); - - std::string fullSourcePath((*si)->GetFullPath()); - if ((*si)->GetExtension() == "int" || (*si)->GetExtension() == "bsp") { - *this->FolderBuildStreams[sgPath] << fullSourcePath << std::endl; - } else { - // WORKAROUND: GHS MULTI needs the path to use backslashes without quotes - // to open files in search as of version 6.1.6 - cmsys::SystemTools::ReplaceString(fullSourcePath, "/", "\\"); - *this->FolderBuildStreams[sgPath] << fullSourcePath << std::endl; - } + /* vector of all sources for this target */ + std::vector<cmSourceFile*> sources; + this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName); - if ("ld" != (*si)->GetExtension() && "int" != (*si)->GetExtension() && - "bsp" != (*si)->GetExtension()) { - this->WriteObjectLangOverride(this->FolderBuildStreams[sgPath], (*si)); - if (objectNames.end() != objectNames.find(*si)) { - *this->FolderBuildStreams[sgPath] - << " -o \"" << objectNames.find(*si)->second << "\"" << std::endl; - } + /* vector of all groups defined for this target + * -- but the vector is not expanded with sub groups or in any useful order + */ + std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); - this->WriteObjectDir(this->FolderBuildStreams[sgPath], - this->AbsBuildFilePath + sgPath); - } + /* for each source file assign it to its group */ + std::map<std::string, std::vector<cmSourceFile*>> groupFiles; + std::set<std::string> groupNames; + for (auto& sf : sources) { + cmSourceGroup* sourceGroup = + this->Makefile->FindSourceGroup(sf->GetFullPath(), sourceGroups); + std::string gn = sourceGroup->GetFullName(); + groupFiles[gn].push_back(sf); + groupNames.insert(gn); } -} -void cmGhsMultiTargetGenerator::WriteObjectLangOverride( - cmGeneratedFileStream* fileStream, cmSourceFile* sourceFile) -{ - const char* rawLangProp = sourceFile->GetProperty("LANGUAGE"); - if (NULL != rawLangProp) { - std::string sourceLangProp(rawLangProp); - std::string extension(sourceFile->GetExtension()); - if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) { - *fileStream << " -dotciscxx" << std::endl; + /* list of known groups and the order they are displayed in a project file */ + const std::vector<std::string> standardGroups = { + "Header Files", "Source Files", "CMake Rules", + "Object Files", "Object Libraries", "Resources" + }; + + /* list of groups in the order they are displayed in a project file*/ + std::vector<std::string> groupFilesList(groupFiles.size()); + + /* put the groups in the order they should be listed + * - standard groups first, and then everything else + * in the order used by std::map. + */ + int i = 0; + for (const std::string& gn : standardGroups) { + auto n = groupNames.find(gn); + if (n != groupNames.end()) { + groupFilesList[i] = *n; + i += 1; + groupNames.erase(gn); } } -} -void cmGhsMultiTargetGenerator::WriteObjectDir( - cmGeneratedFileStream* fileStream, std::string const& dir) -{ - std::string workingDir(dir); - cmSystemTools::ConvertToUnixSlashes(workingDir); - if (!workingDir.empty()) { - workingDir += "/"; + { /* catch-all group - is last item */ + std::string gn = ""; + auto n = groupNames.find(gn); + if (n != groupNames.end()) { + groupFilesList.back() = *n; + groupNames.erase(gn); + } } - workingDir += "Objs"; - *fileStream << " -object_dir=\"" << workingDir << "\"" << std::endl; -} -std::string cmGhsMultiTargetGenerator::GetOutputDirectory( - const std::string& config) const -{ - std::string outputDir(AbsBuildFilePath); - - const char* runtimeOutputProp = - this->GeneratorTarget->GetProperty("RUNTIME_OUTPUT_DIRECTORY"); - if (NULL != runtimeOutputProp) { - outputDir = runtimeOutputProp; + for (auto& n : groupNames) { + groupFilesList[i] = n; + i += 1; } - std::string configCapped(cmSystemTools::UpperCase(config)); - const char* runtimeOutputSProp = this->GeneratorTarget->GetProperty( - "RUNTIME_OUTPUT_DIRECTORY_" + configCapped); - if (NULL != runtimeOutputSProp) { - outputDir = runtimeOutputSProp; + /* sort the files within each group */ + for (auto& n : groupFilesList) { + std::sort(groupFiles[n].begin(), groupFiles[n].end(), + [](cmSourceFile* l, cmSourceFile* r) { + return l->GetFullPath() < r->GetFullPath(); + }); } - cmSystemTools::ConvertToUnixSlashes(outputDir); - if (!outputDir.empty()) { - outputDir += "/"; - } + /* list of open project files */ + std::vector<cmGeneratedFileStream*> gfiles; + + /* write files into the proper project file + * -- groups go into main project file + * unless FOLDER property or variable is set. + */ + for (auto& sg : groupFilesList) { + std::ostream* fout; + bool useProjectFile = + cmSystemTools::IsOn( + this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE")) || + cmSystemTools::IsOn( + this->Makefile->GetDefinition("CMAKE_GHS_NO_SOURCE_GROUP_FILE")); + if (useProjectFile || sg.empty()) { + fout = &fout_proj; + } else { + // Open the filestream in copy-if-different mode. + std::string gname = sg; + cmsys::SystemTools::ReplaceString(gname, "\\", "_"); + std::string lpath = + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + lpath += "/"; + lpath += gname; + lpath += cmGlobalGhsMultiGenerator::FILE_EXTENSION; + std::string fpath = this->LocalGenerator->GetCurrentBinaryDirectory(); + fpath += "/"; + fpath += lpath; + cmGeneratedFileStream* f = new cmGeneratedFileStream(fpath.c_str()); + f->SetCopyIfDifferent(true); + gfiles.push_back(f); + fout = f; + this->GetGlobalGenerator()->WriteFileHeader(*f); + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::SUBPROJECT, *f); + fout_proj << lpath << " "; + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::SUBPROJECT, fout_proj); + } - return outputDir; -} + if (useProjectFile) { + if (sg.empty()) { + *fout << "{comment} Others" << std::endl; + } else { + *fout << "{comment} " << sg << std::endl; + } + } -std::string cmGhsMultiTargetGenerator::GetOutputFilename( - const std::string& config) const -{ - std::string outputFilename(this->GeneratorTarget->GetName()); + /* output rule for each source file */ + for (const cmSourceFile* si : groupFiles[sg]) { - const char* outputNameProp = - this->GeneratorTarget->GetProperty("OUTPUT_NAME"); - if (NULL != outputNameProp) { - outputFilename = outputNameProp; - } + // Convert filename to native system + // WORKAROUND: GHS MULTI 6.1.4 and 6.1.6 are known to need backslash on + // windows when opening some files from the search window. + std::string fname(si->GetFullPath()); + cmSystemTools::ConvertToOutputSlashes(fname); + *fout << fname << std::endl; + + if ("ld" != si->GetExtension() && "int" != si->GetExtension() && + "bsp" != si->GetExtension()) { + this->WriteObjectLangOverride(*fout, si); + } + + this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I"); + this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D"); + this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", ""); - std::string configCapped(cmSystemTools::UpperCase(config)); - const char* outputNameSProp = - this->GeneratorTarget->GetProperty(configCapped + "_OUTPUT_NAME"); - if (NULL != outputNameSProp) { - outputFilename = outputNameSProp; + /* to avoid clutter in the gui only print out the objectName if it has + * been renamed */ + std::string objectName = this->GeneratorTarget->GetObjectName(si); + if (!objectName.empty() && + this->GeneratorTarget->HasExplicitObjectName(si)) { + *fout << " -o " << objectName << std::endl; + } + } } - return outputFilename; + for (cmGeneratedFileStream* f : gfiles) { + f->Close(); + } } -std::string cmGhsMultiTargetGenerator::ComputeLongestObjectDirectory( - cmLocalGhsMultiGenerator const* localGhsMultiGenerator, - cmGeneratorTarget* const generatorTarget, cmSourceFile* const sourceFile) +void cmGhsMultiTargetGenerator::WriteObjectLangOverride( + std::ostream& fout, const cmSourceFile* sourceFile) { - std::string dir_max; - dir_max += - localGhsMultiGenerator->GetMakefile()->GetCurrentBinaryDirectory(); - dir_max += "/"; - dir_max += generatorTarget->Target->GetName(); - dir_max += "/"; - std::vector<cmSourceGroup> sourceGroups( - localGhsMultiGenerator->GetMakefile()->GetSourceGroups()); - std::string const& sourceFullPath = sourceFile->GetFullPath(); - cmSourceGroup* sourceGroup = - localGhsMultiGenerator->GetMakefile()->FindSourceGroup(sourceFullPath, - sourceGroups); - std::string const& sgPath = sourceGroup->GetFullName(); - dir_max += sgPath; - dir_max += "/Objs/libs/"; - dir_max += generatorTarget->Target->GetName(); - dir_max += "/"; - return dir_max; + const char* rawLangProp = sourceFile->GetProperty("LANGUAGE"); + if (NULL != rawLangProp) { + std::string sourceLangProp(rawLangProp); + std::string extension(sourceFile->GetExtension()); + if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) { + fout << " -dotciscxx" << std::endl; + } + } } -bool cmGhsMultiTargetGenerator::IsNotKernel(std::string const& config, - const std::string& language) +void cmGhsMultiTargetGenerator::WriteReferences(std::ostream& fout) { - bool output; - std::vector<std::string> options; - this->GeneratorTarget->GetCompileOptions(options, config, language); - output = - options.end() == std::find(options.begin(), options.end(), "-kernel"); - return output; -} + // This only applies to INTEGRITY Applications + if (this->TagType != GhsMultiGpj::INTERGRITY_APPLICATION) { + return; + } -bool cmGhsMultiTargetGenerator::DetermineIfTargetGroup( - const cmGeneratorTarget* target) -{ - bool output = false; - std::vector<cmSourceFile*> sources; - std::string config = - target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); - target->GetSourceFiles(sources, config); - for (std::vector<cmSourceFile*>::const_iterator sources_i = sources.begin(); - sources.end() != sources_i; ++sources_i) { - if ("int" == (*sources_i)->GetExtension()) { - output = true; - } + // Get the targets that this one depends upon + cmTargetDependSet unordered = + this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget); + cmGlobalGhsMultiGenerator::OrderedTargetDependSet ordered(unordered, + this->Name); + for (auto& t : ordered) { + std::string tname = t->GetName(); + std::string tpath = t->LocalGenerator->GetCurrentBinaryDirectory(); + std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory(); + std::string outpath = + this->LocalGenerator->MaybeConvertToRelativePath(rootpath, tpath) + "/" + + tname + "REF" + cmGlobalGhsMultiGenerator::FILE_EXTENSION; + + fout << outpath; + fout << " "; + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::REFERENCE, fout); + + // Tell the global generator that a refernce project needs to be created + t->Target->SetProperty("GHS_REFERENCE_PROJECT", "ON"); } - return output; } -bool cmGhsMultiTargetGenerator::DetermineIfDynamicDownload( - std::string const& config, const std::string& language) +bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp(void) { - std::vector<std::string> options; - bool output = false; - this->GeneratorTarget->GetCompileOptions(options, config, language); - for (std::vector<std::string>::const_iterator options_i = options.begin(); - options_i != options.end(); ++options_i) { - std::string option = *options_i; - if (this->DDOption == option) { - output = true; + const char* p = this->GeneratorTarget->GetProperty("ghs_integrity_app"); + if (p) { + return cmSystemTools::IsOn( + this->GeneratorTarget->GetProperty("ghs_integrity_app")); + } else { + std::vector<cmSourceFile*> sources; + this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName); + for (auto& sf : sources) { + if ("int" == sf->GetExtension()) { + return true; + } } + return false; } - return output; } diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h index 2cdf68e11..a241cc6bd 100644 --- a/Source/cmGhsMultiTargetGenerator.h +++ b/Source/cmGhsMultiTargetGenerator.h @@ -24,97 +24,49 @@ public: virtual void Generate(); - bool IncludeThisTarget(); - std::vector<cmSourceFile*> GetSources() const; - GhsMultiGpj::Types GetGpjTag() const; - static GhsMultiGpj::Types GetGpjTag(const cmGeneratorTarget* target); - const char* GetAbsBuildFilePath() const - { - return this->AbsBuildFilePath.c_str(); - } - const char* GetRelBuildFileName() const - { - return this->RelBuildFileName.c_str(); - } - const char* GetAbsBuildFileName() const - { - return this->AbsBuildFileName.c_str(); - } - const char* GetAbsOutputFileName() const - { - return this->AbsOutputFileName.c_str(); - } - - static std::string GetRelBuildFilePath(const cmGeneratorTarget* target); - static std::string GetAbsPathToRoot(const cmGeneratorTarget* target); - static std::string GetAbsBuildFilePath(const cmGeneratorTarget* target); - static std::string GetRelBuildFileName(const cmGeneratorTarget* target); - static std::string GetBuildFileName(const cmGeneratorTarget* target); - static std::string AddSlashIfNeededToPath(std::string const& input); - private: cmGlobalGhsMultiGenerator* GetGlobalGenerator() const; - cmGeneratedFileStream* GetFolderBuildStreams() - { - return this->FolderBuildStreams[""]; - }; - bool IsTargetGroup() const { return this->TargetGroup; } - - void WriteTypeSpecifics(const std::string& config, bool notKernel); - void WriteCompilerFlags(const std::string& config, + + void GenerateTarget(); + + void WriteTargetSpecifics(std::ostream& fout, const std::string& config); + + void WriteCompilerFlags(std::ostream& fout, const std::string& config, const std::string& language); - void WriteCompilerDefinitions(const std::string& config, + void WriteCompilerDefinitions(std::ostream& fout, const std::string& config, const std::string& language); - void SetCompilerFlags(std::string const& config, const std::string& language, - bool const notKernel); + void SetCompilerFlags(std::string const& config, + const std::string& language); + std::string GetDefines(const std::string& langugae, std::string const& config); - void WriteIncludes(const std::string& config, const std::string& language); - void WriteTargetLinkLibraries(std::string const& config, - std::string const& language); - void WriteCustomCommands(); + void WriteIncludes(std::ostream& fout, const std::string& config, + const std::string& language); + void WriteTargetLinkLine(std::ostream& fout, std::string const& config); + void WriteCustomCommands(std::ostream& fout); void WriteCustomCommandsHelper( - std::vector<cmCustomCommand> const& commandsSet, + std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet, cmTarget::CustomCommandType commandType); - void WriteSources( - std::vector<cmSourceFile*> const& objectSources, - std::map<const cmSourceFile*, std::string> const& objectNames); - static std::map<const cmSourceFile*, std::string> GetObjectNames( - std::vector<cmSourceFile*>* objectSources, - cmLocalGhsMultiGenerator* localGhsMultiGenerator, - cmGeneratorTarget* generatorTarget); - static void WriteObjectLangOverride(cmGeneratedFileStream* fileStream, - cmSourceFile* sourceFile); - static void WriteObjectDir(cmGeneratedFileStream* fileStream, - std::string const& dir); - std::string GetOutputDirectory(const std::string& config) const; - std::string GetOutputFilename(const std::string& config) const; - static std::string ComputeLongestObjectDirectory( - cmLocalGhsMultiGenerator const* localGhsMultiGenerator, - cmGeneratorTarget* generatorTarget, cmSourceFile* const sourceFile); - - bool IsNotKernel(std::string const& config, const std::string& language); - static bool DetermineIfTargetGroup(const cmGeneratorTarget* target); - bool DetermineIfDynamicDownload(std::string const& config, - const std::string& language); + void WriteSources(std::ostream& fout_proj); + void WriteSourceProperty(std::ostream& fout, const cmSourceFile* sf, + std::string propName, std::string propFlag); + void WriteReferences(std::ostream& fout); + static void WriteObjectLangOverride(std::ostream& fout, + const cmSourceFile* sourceFile); + bool DetermineIfIntegrityApp(void); cmGeneratorTarget* GeneratorTarget; cmLocalGhsMultiGenerator* LocalGenerator; cmMakefile* Makefile; - std::string AbsBuildFilePath; - std::string RelBuildFilePath; - std::string AbsBuildFileName; - std::string RelBuildFileName; - std::string RelOutputFileName; - std::string AbsOutputFileName; - std::map<std::string, cmGeneratedFileStream*> FolderBuildStreams; - bool TargetGroup; - bool DynamicDownload; - static std::string const DDOption; std::map<std::string, std::string> FlagsByLanguage; std::map<std::string, std::string> DefinesByLanguage; + + std::string TargetNameReal; + GhsMultiGpj::Types TagType; + std::string const Name; + std::string ConfigName; /* CMAKE_BUILD_TYPE */ }; #endif // ! cmGhsMultiTargetGenerator_h diff --git a/Source/cmGlobVerificationManager.cxx b/Source/cmGlobVerificationManager.cxx index e8959f2a0..5fd890eab 100644 --- a/Source/cmGlobVerificationManager.cxx +++ b/Source/cmGlobVerificationManager.cxx @@ -9,7 +9,6 @@ #include "cmListFileCache.h" #include "cmSystemTools.h" #include "cmVersion.h" -#include "cmake.h" bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path) { @@ -18,7 +17,7 @@ bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path) } std::string scriptFile = path; - scriptFile += cmake::GetCMakeFilesDirectory(); + scriptFile += "/CMakeFiles"; std::string stampFile = scriptFile; cmSystemTools::MakeDirectory(scriptFile); scriptFile += "/VerifyGlobs.cmake"; @@ -165,7 +164,7 @@ void cmGlobVerificationManager::AddCacheEntry( message << "\n " << std::get<0>(bt); std::get<1>(bt).PrintTitle(message); } - cmSystemTools::Error(message.str().c_str()); + cmSystemTools::Error(message.str()); } else { value.Backtraces.emplace_back(variable, backtrace); } diff --git a/Source/cmGlobVerificationManager.h b/Source/cmGlobVerificationManager.h index cf04c97c7..f7146bec0 100644 --- a/Source/cmGlobVerificationManager.h +++ b/Source/cmGlobVerificationManager.h @@ -21,9 +21,6 @@ */ class cmGlobVerificationManager { -public: - cmGlobVerificationManager() {} - protected: ///! Save verification script for given makefile. ///! Saves to output <path>/<CMakeFilesDirectory>/VerifyGlobs.cmake @@ -55,13 +52,13 @@ private: const bool FollowSymlinks; const std::string Relative; const std::string Expression; - CacheEntryKey(const bool rec, const bool l, const bool s, - const std::string& rel, const std::string& e) + CacheEntryKey(const bool rec, const bool l, const bool s, std::string rel, + std::string e) : Recurse(rec) , ListDirectories(l) , FollowSymlinks(s) - , Relative(rel) - , Expression(e) + , Relative(std::move(rel)) + , Expression(std::move(e)) { } bool operator<(const CacheEntryKey& r) const; @@ -70,13 +67,9 @@ private: struct CacheEntryValue { - bool Initialized; + bool Initialized = false; std::vector<std::string> Files; std::vector<std::pair<std::string, cmListFileBacktrace>> Backtraces; - CacheEntryValue() - : Initialized(false) - { - } }; typedef std::map<CacheEntryKey, CacheEntryValue> CacheEntryMap; diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index 23891031b..c2eb583a9 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -5,6 +5,7 @@ #include "cmDocumentationEntry.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmake.h" @@ -53,7 +54,7 @@ void cmGlobalBorlandMakefileGenerator::GetDocumentation( } void cmGlobalBorlandMakefileGenerator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, const std::string& targetName, const std::string& config, bool fast, int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions) diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h index 27de6cc6c..ca04b7b73 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.h +++ b/Source/cmGlobalBorlandMakefileGenerator.h @@ -46,7 +46,7 @@ public: bool AllowDeleteOnError() const override { return false; } protected: - void GenerateBuildCommand(std::vector<std::string>& makeCommand, + void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index 3b7de4b9c..bf992b48b 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -9,6 +9,4 @@ cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm) { } -cmGlobalCommonGenerator::~cmGlobalCommonGenerator() -{ -} +cmGlobalCommonGenerator::~cmGlobalCommonGenerator() = default; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 5f7ff0bb9..386a3f716 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -32,10 +32,8 @@ #include "cmLocalGenerator.h" #include "cmMSVC60LinkLineComputer.h" #include "cmMakefile.h" -#include "cmOutputConverter.h" +#include "cmMessageType.h" #include "cmPolicies.h" -#include "cmQtAutoGen.h" -#include "cmQtAutoGenInitializer.h" #include "cmSourceFile.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -46,6 +44,7 @@ #if defined(CMAKE_BUILD_WITH_CMAKE) # include "cmCryptoHash.h" +# include "cmQtAutoGenGlobalInitializer.h" # include "cm_jsoncpp_value.h" # include "cm_jsoncpp_writer.h" #endif @@ -98,6 +97,8 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm) this->ConfigureDoneCMP0026AndCMP0024 = false; this->FirstTimeProgress = 0.0f; + this->RecursionDepth = 0; + cm->GetState()->SetIsGeneratorMultiConfig(false); cm->GetState()->SetMinGWMake(false); cm->GetState()->SetMSYSShell(false); @@ -113,6 +114,15 @@ cmGlobalGenerator::~cmGlobalGenerator() delete this->ExtraGenerator; } +#if defined(CMAKE_BUILD_WITH_CMAKE) +Json::Value cmGlobalGenerator::GetJson() const +{ + Json::Value generator = Json::objectValue; + generator["name"] = this->GetName(); + return generator; +} +#endif + bool cmGlobalGenerator::SetGeneratorInstance(std::string const& i, cmMakefile* mf) { @@ -129,7 +139,7 @@ bool cmGlobalGenerator::SetGeneratorInstance(std::string const& i, " " << i << "\n" "was specified."; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -149,7 +159,7 @@ bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p, " " << p << "\n" "was specified."; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -168,7 +178,7 @@ bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, " " << ts << "\n" "was specified."; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -293,7 +303,8 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const for (cmGeneratorTarget* target : targets) { if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET || target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY || - target->GetType() == cmStateEnums::TargetType::UTILITY) { + target->GetType() == cmStateEnums::TargetType::UTILITY || + cmSystemTools::IsOn(target->GetProperty("ghs_integrity_app"))) { continue; } @@ -311,8 +322,8 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const if (srcs.empty()) { std::ostringstream e; e << "No SOURCES given to target: " << target->GetName(); - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - target->GetBacktrace()); + this->GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, e.str(), target->GetBacktrace()); failed = true; } } @@ -343,10 +354,9 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) } if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { - std::string setMakeProgram = - mf->GetModulesFile(this->FindMakeProgramFile.c_str()); + std::string setMakeProgram = mf->GetModulesFile(this->FindMakeProgramFile); if (!setMakeProgram.empty()) { - mf->ReadListFile(setMakeProgram.c_str()); + mf->ReadListFile(setMakeProgram); } } if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") || @@ -355,7 +365,7 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) err << "CMake was unable to find a build program corresponding to \"" << this->GetName() << "\". CMAKE_MAKE_PROGRAM is not set. You " << "probably need to select a different build tool."; - cmSystemTools::Error(err.str().c_str()); + cmSystemTools::Error(err.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -446,7 +456,7 @@ void cmGlobalGenerator::EnableLanguage( e << "Language '" << li << "' is currently being enabled. " "Recursive call not allowed."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return; } @@ -454,16 +464,15 @@ void cmGlobalGenerator::EnableLanguage( if (this->TryCompileOuterMakefile) { // In a try-compile we can only enable languages provided by caller. - for (std::string const& li : languages) { - if (li == "NONE") { + for (std::string const& lang : languages) { + if (lang == "NONE") { this->SetLanguageEnabled("NONE", mf); } else { - const char* lang = li.c_str(); if (this->LanguagesReady.find(lang) == this->LanguagesReady.end()) { std::ostringstream e; e << "The test project needs language " << lang << " which is not enabled."; - this->TryCompileOuterMakefile->IssueMessage(cmake::FATAL_ERROR, + this->TryCompileOuterMakefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return; @@ -476,7 +485,7 @@ void cmGlobalGenerator::EnableLanguage( mf->AddDefinition("RUN_CONFIGURE", true); std::string rootBin = this->CMakeInstance->GetHomeOutputDirectory(); - rootBin += cmake::GetCMakeFilesDirectory(); + rootBin += "/CMakeFiles"; // If the configuration files path has been set, // then we are in a try compile and need to copy the enable language @@ -513,7 +522,7 @@ void cmGlobalGenerator::EnableLanguage( if (readCMakeSystem) { fpath += "/CMakeSystem.cmake"; if (cmSystemTools::FileExists(fpath)) { - mf->ReadListFile(fpath.c_str()); + mf->ReadListFile(fpath); } } // Load the CMakeDetermineSystem.cmake file and find out @@ -542,12 +551,12 @@ void cmGlobalGenerator::EnableLanguage( #endif // Read the DetermineSystem file std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake"); - mf->ReadListFile(systemFile.c_str()); + mf->ReadListFile(systemFile); // load the CMakeSystem.cmake from the binary directory // this file is configured by the CMakeDetermineSystem.cmake file fpath = rootBin; fpath += "/CMakeSystem.cmake"; - mf->ReadListFile(fpath.c_str()); + mf->ReadListFile(fpath); } if (readCMakeSystem) { @@ -558,11 +567,6 @@ void cmGlobalGenerator::EnableLanguage( return; } - // Find the native build tool for this generator. - if (!this->FindMakeProgram(mf)) { - return; - } - // Tell the generator about the target system. std::string system = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME"); if (!this->SetSystemName(system, mf)) { @@ -583,6 +587,11 @@ 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 @@ -594,7 +603,7 @@ void cmGlobalGenerator::EnableLanguage( // **** Load the system specific initialization if not yet loaded if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INITIALIZE_LOADED")) { fpath = mf->GetModulesFile("CMakeSystemSpecificInitialize.cmake"); - if (!mf->ReadListFile(fpath.c_str())) { + if (!mf->ReadListFile(fpath)) { cmSystemTools::Error("Could not find cmake module file: " "CMakeSystemSpecificInitialize.cmake"); } @@ -606,10 +615,9 @@ void cmGlobalGenerator::EnableLanguage( // load the CMakeDetermine(LANG)Compiler.cmake file to find // the compiler - for (std::string const& l : languages) { - const char* lang = l.c_str(); + for (std::string const& lang : languages) { needSetLanguageEnabledMaps[lang] = false; - if (l == "NONE") { + if (lang == "NONE") { this->SetLanguageEnabled("NONE", mf); continue; } @@ -626,7 +634,7 @@ void cmGlobalGenerator::EnableLanguage( // version of CMake then try to load the configured file first // to avoid duplicate compiler tests. if (cmSystemTools::FileExists(fpath)) { - if (!mf->ReadListFile(fpath.c_str())) { + if (!mf->ReadListFile(fpath)) { cmSystemTools::Error("Could not find cmake module file: ", fpath.c_str()); } @@ -651,9 +659,8 @@ void cmGlobalGenerator::EnableLanguage( std::string determineCompiler = "CMakeDetermine"; determineCompiler += lang; determineCompiler += "Compiler.cmake"; - std::string determineFile = - mf->GetModulesFile(determineCompiler.c_str()); - if (!mf->ReadListFile(determineFile.c_str())) { + std::string determineFile = mf->GetModulesFile(determineCompiler); + if (!mf->ReadListFile(determineFile)) { cmSystemTools::Error("Could not find cmake module file: ", determineCompiler.c_str()); } @@ -687,7 +694,7 @@ void cmGlobalGenerator::EnableLanguage( fpath += "/CMake"; fpath += lang; fpath += "Compiler.cmake"; - if (!mf->ReadListFile(fpath.c_str())) { + if (!mf->ReadListFile(fpath)) { cmSystemTools::Error("Could not find cmake module file: ", fpath.c_str()); } @@ -704,16 +711,15 @@ void cmGlobalGenerator::EnableLanguage( // **** Load the system specific information if not yet loaded if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED")) { fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake"); - if (!mf->ReadListFile(fpath.c_str())) { + if (!mf->ReadListFile(fpath)) { cmSystemTools::Error("Could not find cmake module file: " "CMakeSystemSpecificInformation.cmake"); } } // loop over languages again loading CMake(LANG)Information.cmake // - for (std::string const& l : languages) { - const char* lang = l.c_str(); - if (l == "NONE") { + for (std::string const& lang : languages) { + if (lang == "NONE") { this->SetLanguageEnabled("NONE", mf); continue; } @@ -734,7 +740,7 @@ void cmGlobalGenerator::EnableLanguage( "No " << compilerName << " could be found.\n" ; /* clang-format on */ - } else if (strcmp(lang, "RC") != 0 && strcmp(lang, "ASM_MASM") != 0) { + } else if ((lang != "RC") && (lang != "ASM_MASM")) { if (!cmSystemTools::FileIsFullPath(compilerFile)) { /* clang-format off */ noCompiler << @@ -767,7 +773,7 @@ void cmGlobalGenerator::EnableLanguage( if (!this->CMakeInstance->GetIsInTryCompile()) { this->PrintCompilerAdvice(noCompiler, lang, mf->GetDefinition(compilerEnv)); - mf->IssueMessage(cmake::FATAL_ERROR, noCompiler.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, noCompiler.str()); fatalError = true; } } @@ -780,11 +786,11 @@ void cmGlobalGenerator::EnableLanguage( fpath = "CMake"; fpath += lang; fpath += "Information.cmake"; - std::string informationFile = mf->GetModulesFile(fpath.c_str()); + std::string informationFile = mf->GetModulesFile(fpath); if (informationFile.empty()) { cmSystemTools::Error("Could not find cmake module file: ", fpath.c_str()); - } else if (!mf->ReadListFile(informationFile.c_str())) { + } else if (!mf->ReadListFile(informationFile)) { cmSystemTools::Error("Could not process cmake module file: ", informationFile.c_str()); } @@ -804,8 +810,8 @@ void cmGlobalGenerator::EnableLanguage( std::string testLang = "CMakeTest"; testLang += lang; testLang += "Compiler.cmake"; - std::string ifpath = mf->GetModulesFile(testLang.c_str()); - if (!mf->ReadListFile(ifpath.c_str())) { + std::string ifpath = mf->GetModulesFile(testLang); + if (!mf->ReadListFile(ifpath)) { cmSystemTools::Error("Could not find cmake module file: ", testLang.c_str()); } @@ -843,7 +849,7 @@ void cmGlobalGenerator::EnableLanguage( projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME"); projectCompatibility += "Compatibility.cmake"; if (cmSystemTools::FileExists(projectCompatibility)) { - mf->ReadListFile(projectCompatibility.c_str()); + mf->ReadListFile(projectCompatibility); } // Inform any extra generator of the new language. if (this->ExtraGenerator) { @@ -895,7 +901,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( " compiler id \"AppleClang\" to \"Clang\" for compatibility." ; /* clang-format on */ - mf->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } CM_FALLTHROUGH; case cmPolicies::OLD: @@ -905,7 +911,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: mf->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0025)); case cmPolicies::NEW: // NEW behavior is to keep AppleClang. @@ -925,7 +931,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( " compiler id \"QCC\" to \"GNU\" for compatibility." ; /* clang-format on */ - mf->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } CM_FALLTHROUGH; case cmPolicies::OLD: @@ -940,7 +946,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: mf->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0047)); CM_FALLTHROUGH; case cmPolicies::NEW: @@ -1053,7 +1059,7 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l, if (preference < 0) { std::string msg = linkerPrefVar; msg += " is negative, adjusting it to 0"; - cmSystemTools::Message(msg.c_str(), "Warning"); + cmSystemTools::Message(msg, "Warning"); preference = 0; } @@ -1161,6 +1167,7 @@ void cmGlobalGenerator::Configure() this->CMakeInstance->GetHomeOutputDirectory()); cmMakefile* dirMf = new cmMakefile(this, snapshot); + dirMf->SetRecursionDepth(this->RecursionDepth); this->Makefiles.push_back(dirMf); this->IndexMakefile(dirMf); @@ -1205,7 +1212,7 @@ void cmGlobalGenerator::Configure() const char* logs[] = { "CMakeOutput.log", "CMakeError.log", nullptr }; for (const char** log = logs; *log; ++log) { std::string f = this->CMakeInstance->GetHomeOutputDirectory(); - f += this->CMakeInstance->GetCMakeFilesDirectory(); + f += "/CMakeFiles"; f += "/"; f += *log; if (cmSystemTools::FileExists(f)) { @@ -1277,7 +1284,7 @@ bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const << "duplicate custom targets. " << "Consider using a Makefiles generator or fix the project to not " << "use duplicate target names."; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return false; } @@ -1402,13 +1409,13 @@ void cmGlobalGenerator::Generate() if (!this->GenerateCPackPropertiesFile()) { this->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, "Could not write CPack properties file."); + MessageType::FATAL_ERROR, "Could not write CPack properties file."); } for (auto& buildExpSet : this->BuildExportSets) { if (!buildExpSet.second->GenerateImportFile()) { if (!cmSystemTools::GetErrorOccuredFlag()) { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, "Could not write export file."); } return; @@ -1431,7 +1438,8 @@ void cmGlobalGenerator::Generate() for (std::string const& t : this->CMP0042WarnTargets) { w << " " << t << "\n"; } - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + w.str()); } if (!this->CMP0068WarnTargets.empty()) { @@ -1447,7 +1455,8 @@ void cmGlobalGenerator::Generate() for (std::string const& t : this->CMP0068WarnTargets) { w << " " << t << "\n"; } - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + w.str()); } this->CMakeInstance->UpdateProgress("Generating done", -1); @@ -1469,89 +1478,11 @@ bool cmGlobalGenerator::ComputeTargetDepends() bool cmGlobalGenerator::QtAutoGen() { #ifdef CMAKE_BUILD_WITH_CMAKE - std::vector<std::unique_ptr<cmQtAutoGenInitializer>> autogenInits; - - for (cmLocalGenerator* localGen : this->LocalGenerators) { - const std::vector<cmGeneratorTarget*>& targets = - localGen->GetGeneratorTargets(); - // Find targets that require AUTOGEN processing - for (cmGeneratorTarget* target : targets) { - if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { - continue; - } - if (target->GetType() != cmStateEnums::EXECUTABLE && - target->GetType() != cmStateEnums::STATIC_LIBRARY && - target->GetType() != cmStateEnums::SHARED_LIBRARY && - target->GetType() != cmStateEnums::MODULE_LIBRARY && - target->GetType() != cmStateEnums::OBJECT_LIBRARY) { - continue; - } - if (target->IsImported()) { - continue; - } - - const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC"); - const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC"); - const bool rccEnabled = target->GetPropertyAsBool("AUTORCC"); - if (!mocEnabled && !uicEnabled && !rccEnabled) { - continue; - } - - auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target); - // don't do anything if there is no Qt4 or Qt5Core (which contains moc) - if (qtVersion.Major != 4 && qtVersion.Major != 5) { - std::string msg = "AUTOGEN: No valid Qt version found for target "; - msg += target->GetName(); - msg += ". "; - { - std::vector<std::string> lst; - if (mocEnabled) { - lst.emplace_back("AUTOMOC"); - } - if (uicEnabled) { - lst.emplace_back("AUTOUIC"); - } - if (rccEnabled) { - lst.emplace_back("AUTORCC"); - } - msg += cmJoin(lst, ", "); - } - msg += " disabled. "; - msg += "Consider adding:\n"; - if (uicEnabled) { - msg += " find_package(Qt5 COMPONENTS Widgets)\n"; - } else { - msg += " find_package(Qt5 COMPONENTS Core)\n"; - } - msg += "to your CMakeLists.txt file."; - target->Makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); - continue; - } - - autogenInits.emplace_back(cm::make_unique<cmQtAutoGenInitializer>( - target, mocEnabled, uicEnabled, rccEnabled, qtVersion)); - } - } - - if (!autogenInits.empty()) { - // Initialize custom targets - for (auto& autoGen : autogenInits) { - if (!autoGen->InitCustomTargets()) { - return false; - } - } - - // Setup custom targets - for (auto& autoGen : autogenInits) { - if (!autoGen->SetupCustomTargets()) { - return false; - } - autoGen.reset(nullptr); - } - } -#endif - + cmQtAutoGenGlobalInitializer initializer(this->LocalGenerators); + return initializer.generate(); +#else return true; +#endif } cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer( @@ -1822,14 +1753,13 @@ int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir, } void cmGlobalGenerator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& /*unused*/, + GeneratedMakeCommand& makeCommand, const std::string& /*unused*/, const std::string& /*unused*/, const std::string& /*unused*/, const std::string& /*unused*/, const std::string& /*unused*/, bool /*unused*/, int /*unused*/, bool /*unused*/, std::vector<std::string> const& /*unused*/) { - makeCommand.push_back( - "cmGlobalGenerator::GenerateBuildCommand not implemented"); + makeCommand.add("cmGlobalGenerator::GenerateBuildCommand not implemented"); } void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/, @@ -1873,31 +1803,29 @@ int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/, std::string outputBuffer; std::string* outputPtr = &outputBuffer; - std::vector<std::string> makeCommand; + GeneratedMakeCommand makeCommand; this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName, bindir, target, config, fast, jobs, verbose, nativeOptions); - // Workaround to convince VCExpress.exe to produce output. + // Workaround to convince some commands to produce output. if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH && - !makeCommand.empty() && - cmSystemTools::LowerCase( - cmSystemTools::GetFilenameName(makeCommand[0])) == "vcexpress.exe") { + makeCommand.RequiresOutputForward) { outputflag = cmSystemTools::OUTPUT_FORWARD; } // should we do a clean first? if (clean) { - std::vector<std::string> cleanCommand; + GeneratedMakeCommand cleanCommand; this->GenerateBuildCommand(cleanCommand, makeCommandCSTR, projectName, bindir, "clean", config, fast, jobs, verbose); output += "\nRun Clean Command:"; - output += cmSystemTools::PrintSingleCommand(cleanCommand); + output += cleanCommand.printable(); output += "\n"; - if (!cmSystemTools::RunSingleCommand(cleanCommand, outputPtr, outputPtr, - &retVal, nullptr, outputflag, - timeout)) { + if (!cmSystemTools::RunSingleCommand(cleanCommand.PrimaryCommand, + outputPtr, outputPtr, &retVal, + nullptr, outputflag, timeout)) { cmSystemTools::SetRunCommandHideConsole(hideconsole); cmSystemTools::Error("Generator: execution of make clean failed."); output += *outputPtr; @@ -1909,13 +1837,13 @@ int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/, } // now build - std::string makeCommandStr = cmSystemTools::PrintSingleCommand(makeCommand); - output += "\nRun Build Command:"; + std::string makeCommandStr = makeCommand.printable(); + output += "\nRun Build Command(s):"; output += makeCommandStr; output += "\n"; - if (!cmSystemTools::RunSingleCommand(makeCommand, outputPtr, outputPtr, - &retVal, nullptr, outputflag, + if (!cmSystemTools::RunSingleCommand(makeCommand.PrimaryCommand, outputPtr, + outputPtr, &retVal, nullptr, outputflag, timeout)) { cmSystemTools::SetRunCommandHideConsole(hideconsole); cmSystemTools::Error( @@ -2067,7 +1995,7 @@ void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen) this->ConfiguredFilesPath = gen->ConfiguredFilesPath; } else { this->ConfiguredFilesPath = gen->CMakeInstance->GetHomeOutputDirectory(); - this->ConfiguredFilesPath += cmake::GetCMakeFilesDirectory(); + this->ConfiguredFilesPath += "/CMakeFiles"; } } @@ -2101,17 +2029,10 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root, return this->IsExcluded(rootSnp, snp); } -bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root, - cmGeneratorTarget* target) const +bool cmGlobalGenerator::IsExcluded(cmGeneratorTarget* target) const { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY || - target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { - // This target is excluded from its directory. - return true; - } - // This target is included in its directory. Check whether the - // directory is excluded. - return this->IsExcluded(root, target->GetLocalGenerator()); + return target->GetType() == cmStateEnums::INTERFACE_LIBRARY || + target->GetPropertyAsBool("EXCLUDE_FROM_ALL"); } void cmGlobalGenerator::GetEnabledLanguages( @@ -2290,7 +2211,7 @@ bool cmGlobalGenerator::NameResolvesToFramework( inline std::string removeQuotes(const std::string& s) { - if (s[0] == '\"' && s[s.size() - 1] == '\"') { + if (s.front() == '\"' && s.back() == '\"') { return s.substr(1, s.size() - 2); } return s; @@ -2303,7 +2224,7 @@ bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName, if (!tgt) { return true; } - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; std::ostringstream e; bool issueMessage = false; switch (tgt->GetPolicyStatusCMP0037()) { @@ -2317,18 +2238,18 @@ bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: issueMessage = true; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; break; } if (issueMessage) { e << "The target name \"" << targetName << "\" is reserved " << reason << "."; - if (messageType == cmake::AUTHOR_WARNING) { + if (messageType == MessageType::AUTHOR_WARNING) { e << " It may result in undefined behavior."; } this->GetCMakeInstance()->IssueMessage(messageType, e.str(), tgt->GetBacktrace()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -2380,12 +2301,12 @@ void cmGlobalGenerator::AddGlobalTarget_Package( singleLine.push_back("./CPackConfig.cmake"); gti.CommandLines.push_back(std::move(singleLine)); if (this->GetPreinstallTargetName()) { - gti.Depends.push_back(this->GetPreinstallTargetName()); + gti.Depends.emplace_back(this->GetPreinstallTargetName()); } else { const char* noPackageAll = mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY"); if (!noPackageAll || cmSystemTools::IsOff(noPackageAll)) { - gti.Depends.push_back(this->GetAllTargetName()); + gti.Depends.emplace_back(this->GetAllTargetName()); } } targets.push_back(std::move(gti)); @@ -2523,7 +2444,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( bool skipInstallRules = mf->IsOn("CMAKE_SKIP_INSTALL_RULES"); if (this->InstallTargetEnabled && skipInstallRules) { this->CMakeInstance->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "CMAKE_SKIP_INSTALL_RULES was enabled even though " "installation rules have been specified", mf->GetBacktrace()); @@ -2550,12 +2471,12 @@ void cmGlobalGenerator::AddGlobalTarget_Install( gti.UsesTerminal = true; cmCustomCommandLine singleLine; if (this->GetPreinstallTargetName()) { - gti.Depends.push_back(this->GetPreinstallTargetName()); + gti.Depends.emplace_back(this->GetPreinstallTargetName()); } else { const char* noall = mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); if (!noall || cmSystemTools::IsOff(noall)) { - gti.Depends.push_back(this->GetAllTargetName()); + gti.Depends.emplace_back(this->GetAllTargetName()); } } if (mf->GetDefinition("CMake_BINARY_DIR") && @@ -2685,8 +2606,7 @@ std::string cmGlobalGenerator::GenerateRuleFile( ruleFile += ".rule"; const char* dir = this->GetCMakeCFGIntDir(); if (dir && dir[0] == '$') { - cmSystemTools::ReplaceString(ruleFile, dir, - cmake::GetCMakeFilesDirectory()); + cmSystemTools::ReplaceString(ruleFile, dir, "/CMakeFiles"); } return ruleFile; } @@ -2870,8 +2790,9 @@ void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs, } // Shorten the output name (in expected use case). - cmOutputConverter converter(this->GetMakefiles()[0]->GetStateSnapshot()); - std::string fname = converter.ConvertToRelativePath( + cmStateDirectory cmDir = + this->GetMakefiles()[0]->GetStateSnapshot().GetDirectory(); + std::string fname = cmDir.ConvertToRelPathIfNotContained( this->GetMakefiles()[0]->GetState()->GetBinaryDirectory(), outputs[0]); // Associate the hash with this output. @@ -2887,7 +2808,7 @@ void cmGlobalGenerator::CheckRuleHashes() #if defined(CMAKE_BUILD_WITH_CMAKE) std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory(); std::string pfile = home; - pfile += this->GetCMakeInstance()->GetCMakeFilesDirectory(); + pfile += "/CMakeFiles"; pfile += "/CMakeRuleHashes.txt"; this->CheckRuleHashes(pfile, home); this->WriteRuleHashes(pfile); @@ -2927,7 +2848,7 @@ void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile, if (strncmp(line.c_str(), rhi->second.Data, 32) != 0) { // The rule has changed. Delete the output so it will be // built again. - fname = cmSystemTools::CollapseFullPath(fname, home.c_str()); + fname = cmSystemTools::CollapseFullPath(fname, home); cmSystemTools::RemoveFile(fname); } } else { @@ -2937,7 +2858,7 @@ void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile, // Instead, we keep the rule hash as long as the file exists so // that if the feature is turned back on and the rule has // changed the file is still rebuilt. - std::string fpath = cmSystemTools::CollapseFullPath(fname, home.c_str()); + std::string fpath = cmSystemTools::CollapseFullPath(fname, home); if (cmSystemTools::FileExists(fpath)) { RuleHash hash; memcpy(hash.Data, line.c_str(), 32); @@ -2966,7 +2887,7 @@ void cmGlobalGenerator::WriteSummary() { // Record all target directories in a central location. std::string fname = this->CMakeInstance->GetHomeOutputDirectory(); - fname += cmake::GetCMakeFilesDirectory(); + fname += "/CMakeFiles"; fname += "/TargetDirectories.txt"; cmGeneratedFileStream fout(fname); @@ -3093,11 +3014,23 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) std::string cmGlobalGenerator::EscapeJSON(const std::string& s) { std::string result; + result.reserve(s.size()); for (char i : s) { - if (i == '"' || i == '\\') { - result += '\\'; + switch (i) { + case '"': + case '\\': + result += '\\'; + result += i; + break; + case '\n': + result += "\\n"; + break; + case '\t': + result += "\\t"; + break; + default: + result += i; } - result += i; } return result; } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 1ea2d2445..ac013268c 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -24,6 +24,7 @@ #if defined(CMAKE_BUILD_WITH_CMAKE) # include "cmFileLockPool.h" +# include "cm_jsoncpp_value.h" #endif #define CMAKE_DIRECTORY_ID_SEP "::@" @@ -40,6 +41,54 @@ class cmSourceFile; class cmStateDirectory; class cmake; +namespace detail { +inline void AppendStrs(std::vector<std::string>&) +{ +} +template <typename T, typename... Ts> +inline void AppendStrs(std::vector<std::string>& command, T&& s, Ts&&... ts) +{ + command.emplace_back(std::forward<T>(s)); + AppendStrs(command, std::forward<Ts>(ts)...); +} + +struct GeneratedMakeCommand +{ + // Add each argument as a separate element to the vector + template <typename... T> + void add(T&&... args) + { + // iterate the args and append each one + AppendStrs(PrimaryCommand, std::forward<T>(args)...); + } + + // Add each value in the iterators as a separate element to the vector + void add(std::vector<std::string>::const_iterator start, + std::vector<std::string>::const_iterator end) + { + PrimaryCommand.insert(PrimaryCommand.end(), start, end); + } + + std::string printable() const + { + std::size_t size = PrimaryCommand.size(); + for (auto&& i : PrimaryCommand) { + size += i.size(); + } + std::string buffer; + buffer.reserve(size); + for (auto&& i : PrimaryCommand) { + buffer.append(i); + buffer.append(1, ' '); + } + return buffer; + } + + std::vector<std::string> PrimaryCommand; + bool RequiresOutputForward = false; +}; +} + /** \class cmGlobalGenerator * \brief Responsible for overseeing the generation process for the entire tree * @@ -70,6 +119,11 @@ public: return codecvt::None; } +#if defined(CMAKE_BUILD_WITH_CMAKE) + /** Get a JSON object describing the generator. */ + virtual Json::Value GetJson() const; +#endif + /** Tell the generator about the target system. */ virtual bool SetSystemName(std::string const&, cmMakefile*) { return true; } @@ -176,8 +230,12 @@ public: virtual bool Open(const std::string& bindir, const std::string& projectName, bool dryRun); + struct GeneratedMakeCommand final : public detail::GeneratedMakeCommand + { + }; + virtual void GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, const std::string& targetName, const std::string& config, bool fast, int jobs, bool verbose, @@ -426,6 +484,8 @@ public: std::string MakeSilentFlag; + int RecursionDepth; + protected: typedef std::vector<cmLocalGenerator*> GeneratorVector; // for a project collect all its targets by following depend @@ -462,7 +522,7 @@ 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(cmGeneratorTarget* target) const; virtual void InitializeProgressMarks() {} struct GlobalTargetInfo @@ -472,11 +532,7 @@ protected: cmCustomCommandLines CommandLines; std::vector<std::string> Depends; std::string WorkingDir; - bool UsesTerminal; - GlobalTargetInfo() - : UsesTerminal(false) - { - } + bool UsesTerminal = false; }; void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets); @@ -602,13 +658,9 @@ private: // Cache directory content and target files to be built. struct DirectoryContent { - long LastDiskTime; + long LastDiskTime = -1; std::set<std::string> All; std::set<std::string> Generated; - DirectoryContent() - : LastDiskTime(-1) - { - } }; std::map<std::string, DirectoryContent> DirectoryContentMap; diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h index 4e3e7705b..bb5f74cca 100644 --- a/Source/cmGlobalGeneratorFactory.h +++ b/Source/cmGlobalGeneratorFactory.h @@ -20,7 +20,7 @@ struct cmDocumentationEntry; class cmGlobalGeneratorFactory { public: - virtual ~cmGlobalGeneratorFactory() {} + virtual ~cmGlobalGeneratorFactory() = default; /** Create a GlobalGenerator */ virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& n, @@ -30,13 +30,20 @@ public: virtual void GetDocumentation(cmDocumentationEntry& entry) const = 0; /** Get the names of the current registered generators */ - virtual void GetGenerators(std::vector<std::string>& names) const = 0; + virtual std::vector<std::string> GetGeneratorNames() const = 0; + virtual std::vector<std::string> GetGeneratorNamesWithPlatform() const = 0; /** Determine whether or not this generator supports toolsets */ virtual bool SupportsToolset() const = 0; /** Determine whether or not this generator supports platforms */ virtual bool SupportsPlatform() const = 0; + + /** 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. */ + virtual std::string GetDefaultPlatformName() const = 0; }; template <class T> @@ -60,9 +67,15 @@ public: } /** Get the names of the current registered generators */ - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(T::GetActualName()); + return names; + } + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + return std::vector<std::string>(); } /** Determine whether or not this generator supports toolsets */ @@ -70,6 +83,15 @@ public: /** Determine whether or not this generator supports platforms */ bool SupportsPlatform() const override { return T::SupportsPlatform(); } + + /** Get the list of supported platforms name for this generator */ + std::vector<std::string> GetKnownPlatforms() const override + { + // default is no platform supported + return std::vector<std::string>(); + } + + std::string GetDefaultPlatformName() const override { return std::string(); } }; #endif diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index a9742c531..45fa0529f 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -11,7 +11,9 @@ #include "cmGhsMultiTargetGenerator.h" #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmVersion.h" +#include "cmake.h" const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj"; const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild.exe"; @@ -19,13 +21,12 @@ const char* cmGlobalGhsMultiGenerator::DEFAULT_TOOLSET_ROOT = "C:/ghs"; cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm) : cmGlobalGenerator(cm) - , OSDirRelative(false) { + cm->GetState()->SetGhsMultiIDE(true); } cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator() { - cmDeleteAll(TargetFolderBuildStreams); } cmLocalGenerator* cmGlobalGhsMultiGenerator::CreateLocalGenerator( @@ -41,46 +42,59 @@ void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry) "Generates Green Hills MULTI files (experimental, work-in-progress)."; } +void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory( + cmGeneratorTarget* gt) const +{ + // Compute full path to object file directory for this target. + std::string dir; + dir += gt->LocalGenerator->GetCurrentBinaryDirectory(); + dir += "/"; + dir += gt->LocalGenerator->GetTargetDirectory(gt); + dir += "/"; + gt->ObjectDirectory = dir; +} + bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, cmMakefile* mf) { - std::string tsp; /* toolset path */ - std::string tsn = ts; /* toolset name */ + std::string tsp; /* toolset path */ - GetToolset(mf, tsp, tsn); + this->GetToolset(mf, tsp, ts); /* no toolset was found */ - if (tsn.empty()) { + if (tsp.empty()) { return false; } else if (ts.empty()) { std::string message; message = "Green Hills MULTI: -T <toolset> not specified; defaulting to \""; - message += tsn; + message += tsp; message += "\""; - cmSystemTools::Message(message.c_str()); + cmSystemTools::Message(message); - /* store the toolset for later use + /* store the full toolset for later use * -- already done if -T<toolset> was specified */ - mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsn.c_str(), - "Name of generator toolset.", + mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsp.c_str(), + "Location of generator toolset.", cmStateEnums::INTERNAL); } /* set the build tool to use */ + std::string gbuild(tsp + ((tsp.back() == '/') ? "" : "/") + + DEFAULT_BUILD_PROGRAM); const char* prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM"); - std::string gbuild(tsp + "/" + tsn + "/" + DEFAULT_BUILD_PROGRAM); /* check if the toolset changed from last generate */ if (prevTool != NULL && (gbuild != prevTool)) { - std::string message = "generator toolset: "; + std::string message = "toolset build tool: "; message += gbuild; - message += "\nDoes not match the toolset used previously: "; + message += "\nDoes not match the previously used build tool: "; message += prevTool; message += "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."; - cmSystemTools::Error(message.c_str()); + cmSystemTools::Error(message); + return false; } else { /* store the toolset that is being used for this build */ mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(), @@ -88,25 +102,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, true); } - mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsn.c_str()); - - // FIXME: compiler detection not implemented - // gbuild uses the primaryTarget setting in the top-level project - // file to determine which compiler to use. Because compiler - // detection is not implemented these variables must be - // set to skip past these tests. However cmake will verify that - // the executable pointed to by CMAKE_<LANG>_COMPILER exists. - // To pass this additional check gbuild is used as a place holder for the - // actual compiler. - mf->AddDefinition("CMAKE_C_COMPILER", gbuild.c_str()); - mf->AddDefinition("CMAKE_C_COMPILER_ID_RUN", "TRUE"); - mf->AddDefinition("CMAKE_C_COMPILER_ID", "GHS"); - mf->AddDefinition("CMAKE_C_COMPILER_FORCED", "TRUE"); - - mf->AddDefinition("CMAKE_CXX_COMPILER", gbuild.c_str()); - mf->AddDefinition("CMAKE_CXX_COMPILER_ID_RUN", "TRUE"); - mf->AddDefinition("CMAKE_CXX_COMPILER_ID", "GHS"); - mf->AddDefinition("CMAKE_CXX_COMPILER_FORCED", "TRUE"); + mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsp.c_str()); return true; } @@ -129,6 +125,8 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM"); if (tgtPlatform == nullptr) { + cmSystemTools::Message("Green Hills MULTI: GHS_TARGET_PLATFORM not " + "specified; defaulting to \"integrity\""); tgtPlatform = "integrity"; } @@ -159,11 +157,11 @@ bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* /*mf*/) } void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd, - std::string& ts) + const std::string& ts) { const char* ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT"); - if (!ghsRoot) { + if (!ghsRoot || ghsRoot[0] == '\0') { ghsRoot = DEFAULT_TOOLSET_ROOT; } tsd = ghsRoot; @@ -172,156 +170,250 @@ void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd, std::vector<std::string> output; // Use latest? version + if (tsd.back() != '/') { + tsd += "/"; + } cmSystemTools::Glob(tsd, "comp_[^;]+", output); if (output.empty()) { - cmSystemTools::Error("GHS toolset not found in ", tsd.c_str()); - ts = ""; + std::string msg = + "No GHS toolsets found in GHS_TOOLSET_ROOT \"" + tsd + "\"."; + cmSystemTools::Error(msg); + tsd = ""; } else { - ts = output.back(); + tsd += output.back(); } } else { - std::string tryPath = tsd + std::string("/") + ts; + std::string tryPath; + /* CollapseCombinedPath will check if ts is an absolute path */ + tryPath = cmSystemTools::CollapseCombinedPath(tsd, ts); if (!cmSystemTools::FileExists(tryPath)) { - cmSystemTools::Error("GHS toolset \"", ts.c_str(), "\" not found in ", - tsd.c_str()); - ts = ""; + std::string msg = "GHS toolset \"" + tryPath + "\" not found."; + cmSystemTools::Error(msg); + tsd = ""; + } else { + tsd = tryPath; } } } -void cmGlobalGhsMultiGenerator::OpenBuildFileStream( - std::string const& filepath, cmGeneratedFileStream** filestream) +void cmGlobalGhsMultiGenerator::WriteFileHeader(std::ostream& fout) { - // Get a stream where to generate things. - if (NULL == *filestream) { - *filestream = new cmGeneratedFileStream(filepath.c_str()); - if (NULL != *filestream) { - OpenBuildFileStream(*filestream); - } - } + fout << "#!gbuild" << std::endl; + fout << "#" << std::endl + << "# CMAKE generated file: DO NOT EDIT!" << std::endl + << "# Generated by \"" << this->GetActualName() << "\"" + << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "." + << cmVersion::GetMinorVersion() << std::endl + << "#" << std::endl + << std::endl; } -void cmGlobalGhsMultiGenerator::OpenBuildFileStream( - cmGeneratedFileStream* filestream) +void cmGlobalGhsMultiGenerator::WriteTopLevelProject( + std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators) { - *filestream << "#!gbuild" << std::endl; -} + WriteFileHeader(fout); -void cmGlobalGhsMultiGenerator::OpenBuildFileStream() -{ - // Compute GHS MULTI's build file path. - std::string buildFilePath = - this->GetCMakeInstance()->GetHomeOutputDirectory(); - buildFilePath += "/"; - buildFilePath += "default"; - buildFilePath += FILE_EXTENSION; - - this->Open(std::string(""), buildFilePath, &this->TargetFolderBuildStreams); - OpenBuildFileStream(GetBuildFileStream()); - - char const* osDir = - this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR"); - if (NULL == osDir) { - osDir = ""; - cmSystemTools::Error("GHS_OS_DIR cache variable must be set"); - } else { - this->GetCMakeInstance()->MarkCliAsUsed("GHS_OS_DIR"); - } - std::string fOSDir(this->trimQuotes(osDir)); - std::replace(fOSDir.begin(), fOSDir.end(), '\\', '/'); - if (!fOSDir.empty() && ('c' == fOSDir[0] || 'C' == fOSDir[0])) { - this->OSDirRelative = false; - } else { - this->OSDirRelative = true; + this->WriteMacros(fout); + this->WriteHighLevelDirectives(fout); + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fout); + + fout << "# Top Level Project File" << std::endl; + + // Specify BSP option if supplied by user + // -- not all platforms require this entry in the project file + // integrity platforms require this field; use default if needed + std::string platform; + if (const char* p = + this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM")) { + platform = p; } std::string bspName; - char const* bspCache = - this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME"); - if (bspCache) { + if (char const* bspCache = + this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME")) { bspName = bspCache; this->GetCMakeInstance()->MarkCliAsUsed("GHS_BSP_NAME"); + } else { + bspName = "IGNORE"; } - if (bspName.empty() || bspName.compare("IGNORE") == 0) { + + if (platform.find("integrity") != std::string::npos && + cmSystemTools::IsOff(bspName.c_str())) { const char* a = this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM"); bspName = "sim"; bspName += (a ? a : ""); } - this->WriteMacros(); - this->WriteHighLevelDirectives(); + if (!cmSystemTools::IsOff(bspName.c_str())) { + fout << " -bsp " << bspName << std::endl; + } + + // Specify OS DIR if supplied by user + // -- not all platforms require this entry in the project file + std::string osDir; + std::string osDirOption; + if (char const* osDirCache = + this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR")) { + osDir = osDirCache; + } + + if (char const* osDirOptionCache = + this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR_OPTION")) { + osDirOption = osDirOptionCache; + } - GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, this->GetBuildFileStream()); - this->WriteDisclaimer(this->GetBuildFileStream()); - *this->GetBuildFileStream() << "# Top Level Project File" << std::endl; - *this->GetBuildFileStream() << " -bsp " << bspName << std::endl; + if (!cmSystemTools::IsOff(osDir.c_str()) || + platform.find("integrity") != std::string::npos) { + std::replace(osDir.begin(), osDir.end(), '\\', '/'); + fout << " " << osDirOption << "\"" << osDir << "\"" << std::endl; + } - this->WriteCompilerOptions(fOSDir); + WriteSubProjects(fout, root, generators); } -void cmGlobalGhsMultiGenerator::CloseBuildFileStream( - cmGeneratedFileStream** filestream) +void cmGlobalGhsMultiGenerator::WriteSubProjects( + std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators) { - if (filestream) { - delete *filestream; - *filestream = NULL; - } else { - cmSystemTools::Error("Build file stream was not open."); + // Collect all targets under this root generator and the transitive + // closure of their dependencies. + TargetDependSet projectTargets; + TargetDependSet originalTargets; + this->GetTargetSets(projectTargets, originalTargets, root, generators); + OrderedTargetDependSet orderedProjectTargets(projectTargets, ""); + + // write out all the sub-projects + std::string rootBinaryDir = root->GetCurrentBinaryDirectory(); + for (cmGeneratorTarget const* target : orderedProjectTargets) { + if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + continue; + } + + const char* projName = target->GetProperty("GENERATOR_FILE_NAME"); + const char* projType = target->GetProperty("GENERATOR_FILE_NAME_EXT"); + if (projName && projType) { + cmLocalGenerator* lg = target->GetLocalGenerator(); + std::string dir = lg->GetCurrentBinaryDirectory(); + dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir.c_str()); + if (dir == ".") { + dir.clear(); + } else { + if (dir.back() != '/') { + dir += "/"; + } + } + + if (cmSystemTools::IsOn(target->GetProperty("EXCLUDE_FROM_ALL"))) { + fout << "{comment} "; + } + std::string projFile = dir + projName + FILE_EXTENSION; + fout << projFile; + fout << " " << projType << std::endl; + + if (cmSystemTools::IsOn(target->GetProperty("GHS_REFERENCE_PROJECT"))) { + // create reference project + std::string fname = dir; + fname += target->GetName(); + fname += "REF"; + fname += FILE_EXTENSION; + + cmGeneratedFileStream fref(fname.c_str()); + fref.SetCopyIfDifferent(true); + + this->WriteFileHeader(fref); + GhsMultiGpj::WriteGpjTag(GhsMultiGpj::REFERENCE, fref); + fref << " :reference=" << projFile << std::endl; + + fref.Close(); + } + } } } void cmGlobalGhsMultiGenerator::Generate() { + // first do the superclass method this->cmGlobalGenerator::Generate(); - if (!this->LocalGenerators.empty()) { - this->OpenBuildFileStream(); + // output top-level projects + for (auto& it : this->ProjectMap) { + this->OutputTopLevelProject(it.second[0], it.second); + } +} - // Build all the folder build files - for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { - cmLocalGhsMultiGenerator* lg = - static_cast<cmLocalGhsMultiGenerator*>(this->LocalGenerators[i]); - const std::vector<cmGeneratorTarget*>& tgts = lg->GetGeneratorTargets(); - this->UpdateBuildFiles(tgts); - } +void cmGlobalGhsMultiGenerator::OutputTopLevelProject( + cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) +{ + if (generators.empty()) { + return; } - cmDeleteAll(TargetFolderBuildStreams); - this->TargetFolderBuildStreams.clear(); + /* Name top-level projects as filename.top.gpj to avoid name clashes + * with target projects. This avoid the issue where the project has + * the same name as the executable target. + */ + std::string fname = root->GetCurrentBinaryDirectory(); + fname += "/"; + fname += root->GetProjectName(); + fname += ".top"; + fname += FILE_EXTENSION; + + cmGeneratedFileStream fout(fname.c_str()); + fout.SetCopyIfDifferent(true); + + this->WriteTopLevelProject(fout, root, generators); + + fout.Close(); } void cmGlobalGhsMultiGenerator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, - const std::string& /*projectName*/, const std::string& /*projectDir*/, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, + const std::string& projectName, const std::string& projectDir, const std::string& targetName, const std::string& /*config*/, bool /*fast*/, int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions) { const char* gbuild = this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); - makeCommand.push_back( - this->SelectMakeProgram(makeProgram, (std::string)gbuild)); + makeCommand.add(this->SelectMakeProgram(makeProgram, (std::string)gbuild)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - makeCommand.push_back("-parallel"); + makeCommand.add("-parallel"); if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.push_back(std::to_string(jobs)); + makeCommand.add(std::to_string(jobs)); } } - makeCommand.insert(makeCommand.end(), makeOptions.begin(), - makeOptions.end()); + makeCommand.add(makeOptions.begin(), makeOptions.end()); + + /* determine which top-project file to use */ + std::string proj = projectName + ".top" + FILE_EXTENSION; + std::vector<std::string> files; + cmSystemTools::Glob(projectDir, ".*\\.top\\.gpj", files); + if (!files.empty()) { + auto p = std::find(files.begin(), files.end(), proj); + if (p == files.end()) { + proj = files.at(0); + } + } + + makeCommand.add("-top", proj); if (!targetName.empty()) { if (targetName == "clean") { - makeCommand.push_back("-clean"); + makeCommand.add("-clean"); } else { - makeCommand.push_back(targetName); + if (targetName.compare(targetName.size() - 4, 4, ".gpj") == 0) { + makeCommand.add(targetName); + } else { + makeCommand.add(targetName + ".gpj"); + } } } } -void cmGlobalGhsMultiGenerator::WriteMacros() +void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout) { char const* ghsGpjMacros = this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS"); @@ -331,12 +423,12 @@ void cmGlobalGhsMultiGenerator::WriteMacros() for (std::vector<std::string>::const_iterator expandedListI = expandedList.begin(); expandedListI != expandedList.end(); ++expandedListI) { - *this->GetBuildFileStream() << "macro " << *expandedListI << std::endl; + fout << "macro " << *expandedListI << std::endl; } } } -void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives() +void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(std::ostream& fout) { /* set primary target */ std::string tgt; @@ -356,183 +448,46 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives() tgt += ".tgt"; } - *this->GetBuildFileStream() << "primaryTarget=" << tgt << std::endl; + fout << "primaryTarget=" << tgt << std::endl; char const* const customization = this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION"); if (NULL != customization && strlen(customization) > 0) { - *this->GetBuildFileStream() - << "customization=" << trimQuotes(customization) << std::endl; + fout << "customization=" << trimQuotes(customization) << std::endl; this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION"); } } -void cmGlobalGhsMultiGenerator::WriteCompilerOptions(std::string const& fOSDir) -{ - *this->GetBuildFileStream() - << " -os_dir=\"" << fOSDir << "\"" << std::endl; -} - -void cmGlobalGhsMultiGenerator::WriteDisclaimer(std::ostream* os) -{ - (*os) << "#" << std::endl - << "# CMAKE generated file: DO NOT EDIT!" << std::endl - << "# Generated by \"" << GetActualName() << "\"" - << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "." - << cmVersion::GetMinorVersion() << std::endl - << "#" << std::endl; -} - -void cmGlobalGhsMultiGenerator::AddFilesUpToPath( - cmGeneratedFileStream* mainBuildFile, - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - char const* homeOutputDirectory, std::string const& path, - GhsMultiGpj::Types projType, std::string const& relPath) +std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const& str) { - std::string workingPath(path); - cmSystemTools::ConvertToUnixSlashes(workingPath); - std::vector<std::string> splitPath = cmSystemTools::SplitString(workingPath); - std::string workingRelPath(relPath); - cmSystemTools::ConvertToUnixSlashes(workingRelPath); - if (!workingRelPath.empty()) { - workingRelPath += "/"; - } - std::string pathUpTo; - for (std::vector<std::string>::const_iterator splitPathI = splitPath.begin(); - splitPath.end() != splitPathI; ++splitPathI) { - pathUpTo += *splitPathI; - if (targetFolderBuildStreams->end() == - targetFolderBuildStreams->find(pathUpTo)) { - AddFilesUpToPathNewBuildFile( - mainBuildFile, targetFolderBuildStreams, homeOutputDirectory, pathUpTo, - splitPath.begin() == splitPathI, workingRelPath, projType); + std::string result; + result.reserve(str.size()); + for (const char* ch = str.c_str(); *ch != '\0'; ++ch) { + if (*ch != '"') { + result += *ch; } - AddFilesUpToPathAppendNextFile(targetFolderBuildStreams, pathUpTo, - splitPathI, splitPath.end(), projType); - pathUpTo += "/"; - } -} - -void cmGlobalGhsMultiGenerator::Open( - std::string const& mapKeyName, std::string const& fileName, - std::map<std::string, cmGeneratedFileStream*>* fileMap) -{ - if (fileMap->end() == fileMap->find(fileName)) { - cmGeneratedFileStream* temp(new cmGeneratedFileStream); - temp->open(fileName.c_str()); - (*fileMap)[mapKeyName] = temp; - } -} - -void cmGlobalGhsMultiGenerator::AddFilesUpToPathNewBuildFile( - cmGeneratedFileStream* mainBuildFile, - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - char const* homeOutputDirectory, std::string const& pathUpTo, - bool const isFirst, std::string const& relPath, - GhsMultiGpj::Types const projType) -{ - // create folders up to file path - std::string absPath = std::string(homeOutputDirectory) + "/" + relPath; - std::string newPath = absPath + pathUpTo; - if (!cmSystemTools::FileExists(newPath.c_str())) { - cmSystemTools::MakeDirectory(newPath.c_str()); - } - - // Write out to filename for first time - std::string relFilename(GetFileNameFromPath(pathUpTo)); - std::string absFilename = absPath + relFilename; - Open(pathUpTo, absFilename, targetFolderBuildStreams); - OpenBuildFileStream((*targetFolderBuildStreams)[pathUpTo]); - GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]); - WriteDisclaimer((*targetFolderBuildStreams)[pathUpTo]); - - // Add to main build file - if (isFirst) { - *mainBuildFile << relFilename << " "; - GhsMultiGpj::WriteGpjTag(projType, mainBuildFile); - } -} - -void cmGlobalGhsMultiGenerator::AddFilesUpToPathAppendNextFile( - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - std::string const& pathUpTo, - std::vector<std::string>::const_iterator splitPathI, - std::vector<std::string>::const_iterator end, - GhsMultiGpj::Types const projType) -{ - std::vector<std::string>::const_iterator splitPathNextI = splitPathI + 1; - if (end != splitPathNextI && - targetFolderBuildStreams->end() == - targetFolderBuildStreams->find(pathUpTo + "/" + *splitPathNextI)) { - std::string nextFilename(*splitPathNextI); - nextFilename = GetFileNameFromPath(nextFilename); - *(*targetFolderBuildStreams)[pathUpTo] << nextFilename << " "; - GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]); } + return result; } -std::string cmGlobalGhsMultiGenerator::GetFileNameFromPath( - std::string const& path) +bool cmGlobalGhsMultiGenerator::TargetCompare::operator()( + cmGeneratorTarget const* l, cmGeneratorTarget const* r) const { - std::string output(path); - if (!path.empty()) { - cmSystemTools::ConvertToUnixSlashes(output); - std::vector<std::string> splitPath = cmSystemTools::SplitString(output); - output += "/" + splitPath.back() + FILE_EXTENSION; + // Make sure a given named target is ordered first, + // e.g. to set ALL_BUILD as the default active project. + // When the empty string is named this is a no-op. + if (r->GetName() == this->First) { + return false; } - return output; -} - -void cmGlobalGhsMultiGenerator::UpdateBuildFiles( - const std::vector<cmGeneratorTarget*>& tgts) -{ - for (std::vector<cmGeneratorTarget*>::const_iterator tgtsI = tgts.begin(); - tgtsI != tgts.end(); ++tgtsI) { - const cmGeneratorTarget* tgt = *tgtsI; - if (IsTgtForBuild(tgt)) { - std::string folderName = tgt->GetEffectiveFolderName(); - if (this->TargetFolderBuildStreams.end() == - this->TargetFolderBuildStreams.find(folderName)) { - this->AddFilesUpToPath( - GetBuildFileStream(), &this->TargetFolderBuildStreams, - this->GetCMakeInstance()->GetHomeOutputDirectory().c_str(), - folderName, GhsMultiGpj::PROJECT); - } - std::vector<std::string> splitPath = cmSystemTools::SplitString( - cmGhsMultiTargetGenerator::GetRelBuildFileName(tgt)); - std::string foldNameRelBuildFile(*(splitPath.end() - 2) + "/" + - splitPath.back()); - *this->TargetFolderBuildStreams[folderName] << foldNameRelBuildFile - << " "; - GhsMultiGpj::WriteGpjTag(cmGhsMultiTargetGenerator::GetGpjTag(tgt), - this->TargetFolderBuildStreams[folderName]); - } + if (l->GetName() == this->First) { + return true; } + return l->GetName() < r->GetName(); } -bool cmGlobalGhsMultiGenerator::IsTgtForBuild(const cmGeneratorTarget* tgt) +cmGlobalGhsMultiGenerator::OrderedTargetDependSet::OrderedTargetDependSet( + TargetDependSet const& targets, std::string const& first) + : derived(TargetCompare(first)) { - const std::string config = - tgt->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); - std::vector<cmSourceFile*> tgtSources; - tgt->GetSourceFiles(tgtSources, config); - bool tgtInBuild = true; - char const* excludeFromAll = tgt->GetProperty("EXCLUDE_FROM_ALL"); - if (NULL != excludeFromAll && '1' == excludeFromAll[0] && - '\0' == excludeFromAll[1]) { - tgtInBuild = false; - } - return !tgtSources.empty() && tgtInBuild; -} - -std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const& str) -{ - std::string result; - result.reserve(str.size()); - for (const char* ch = str.c_str(); *ch != '\0'; ++ch) { - if (*ch != '"') { - result += *ch; - } - } - return result; + this->insert(targets.begin(), targets.end()); } diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index 13c511302..bc2b199a0 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -13,7 +13,7 @@ class cmGeneratedFileStream; class cmGlobalGhsMultiGenerator : public cmGlobalGenerator { public: - /// The default name of GHS MULTI's build file. Typically: monolith.gpj. + // The default filename extension of GHS MULTI's build files. static const char* FILE_EXTENSION; cmGlobalGhsMultiGenerator(cmake* cm); @@ -25,13 +25,13 @@ public: } ///! create the correct local generator - virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf); + cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; /// @return the name of this generator. static std::string GetActualName() { return "Green Hills MULTI"; } ///! Get the name for this generator - virtual std::string GetName() const { return this->GetActualName(); } + std::string GetName() const override { return this->GetActualName(); } /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation() static void GetDocumentation(cmDocumentationEntry& entry); @@ -49,83 +49,85 @@ public: static bool SupportsPlatform() { return true; } // Toolset / Platform Support - virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); - virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf); + bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; + bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; /** * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ - virtual void EnableLanguage(std::vector<std::string> const& languages, - cmMakefile*, bool optional); + void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*, + bool optional) override; /* * Determine what program to use for building the project. */ bool FindMakeProgram(cmMakefile* mf) override; - cmGeneratedFileStream* GetBuildFileStream() - { - return this->TargetFolderBuildStreams[""]; - } + void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; - static void OpenBuildFileStream(std::string const& filepath, - cmGeneratedFileStream** filestream); - static void OpenBuildFileStream(cmGeneratedFileStream* filestream); - static void CloseBuildFileStream(cmGeneratedFileStream** filestream); - /// Write the common disclaimer text at the top of each build file. - static void WriteDisclaimer(std::ostream* os); - std::vector<std::string> GetLibDirs() { return this->LibDirs; } - - static void AddFilesUpToPath( - cmGeneratedFileStream* mainBuildFile, - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - char const* homeOutputDirectory, std::string const& path, - GhsMultiGpj::Types projType, std::string const& relPath = ""); - static void Open(std::string const& mapKeyName, std::string const& fileName, - std::map<std::string, cmGeneratedFileStream*>* fileMap); - - static std::string trimQuotes(std::string const& str); - inline bool IsOSDirRelative() { return this->OSDirRelative; } + // Write the common disclaimer text at the top of each build file. + void WriteFileHeader(std::ostream& fout); + + // Target dependency sorting + class TargetSet : public std::set<cmGeneratorTarget const*> + { + }; + class TargetCompare + { + std::string First; + + public: + TargetCompare(std::string const& first) + : First(first) + { + } + bool operator()(cmGeneratorTarget const* l, + cmGeneratorTarget const* r) const; + }; + class OrderedTargetDependSet; protected: - virtual void Generate(); - virtual void GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& projectDir, - const std::string& targetName, const std::string& config, bool fast, - int jobs, bool verbose, - std::vector<std::string> const& makeOptions = std::vector<std::string>()); + void Generate() override; + void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, + const std::string& makeProgram, + const std::string& projectName, + const std::string& projectDir, + const std::string& targetName, + const std::string& config, bool fast, int jobs, + bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; private: - void GetToolset(cmMakefile* mf, std::string& tsd, std::string& ts); - void OpenBuildFileStream(); - - void WriteMacros(); - void WriteHighLevelDirectives(); - void WriteCompilerOptions(std::string const& fOSDir); - - static void AddFilesUpToPathNewBuildFile( - cmGeneratedFileStream* mainBuildFile, - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - char const* homeOutputDirectory, std::string const& pathUpTo, bool isFirst, - std::string const& relPath, GhsMultiGpj::Types projType); - static void AddFilesUpToPathAppendNextFile( - std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, - std::string const& pathUpTo, - std::vector<std::string>::const_iterator splitPathI, - std::vector<std::string>::const_iterator end, GhsMultiGpj::Types projType); - static std::string GetFileNameFromPath(std::string const& path); - void UpdateBuildFiles(const std::vector<cmGeneratorTarget*>& tgts); - bool IsTgtForBuild(const cmGeneratorTarget* tgt); - - std::vector<cmGeneratedFileStream*> TargetSubProjects; - std::map<std::string, cmGeneratedFileStream*> TargetFolderBuildStreams; - - std::vector<std::string> LibDirs; - - bool OSDirRelative; + void GetToolset(cmMakefile* mf, std::string& tsd, const std::string& ts); + + /* top-level project */ + void OutputTopLevelProject(cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators); + void WriteTopLevelProject(std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators); + void WriteMacros(std::ostream& fout); + void WriteHighLevelDirectives(std::ostream& fout); + void WriteSubProjects(std::ostream& fout, cmLocalGenerator* root, + std::vector<cmLocalGenerator*>& generators); + + std::string trimQuotes(std::string const& str); + static const char* DEFAULT_BUILD_PROGRAM; static const char* DEFAULT_TOOLSET_ROOT; }; +class cmGlobalGhsMultiGenerator::OrderedTargetDependSet + : public std::multiset<cmTargetDepend, + cmGlobalGhsMultiGenerator::TargetCompare> +{ + typedef std::multiset<cmTargetDepend, + cmGlobalGhsMultiGenerator::TargetCompare> + derived; + +public: + typedef cmGlobalGenerator::TargetDependSet TargetDependSet; + OrderedTargetDependSet(TargetDependSet const&, std::string const& first); +}; + #endif diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx index 0f41ea148..2b7f48695 100644 --- a/Source/cmGlobalJOMMakefileGenerator.cxx +++ b/Source/cmGlobalJOMMakefileGenerator.cxx @@ -6,6 +6,7 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmState.h" +#include "cmake.h" cmGlobalJOMMakefileGenerator::cmGlobalJOMMakefileGenerator(cmake* cm) : cmGlobalUnixMakefileGenerator3(cm) @@ -54,7 +55,7 @@ void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice( } void cmGlobalJOMMakefileGenerator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, const std::string& targetName, const std::string& config, bool fast, int jobs, bool verbose, std::vector<std::string> const& makeOptions) diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index bcf46d031..aa8b5fbb0 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -40,7 +40,7 @@ public: bool optional) override; protected: - void GenerateBuildCommand(std::vector<std::string>& makeCommand, + void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx index 3f223824a..3c2455662 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.cxx +++ b/Source/cmGlobalMSYSMakefileGenerator.cxx @@ -7,6 +7,7 @@ #include "cmDocumentationEntry.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmake.h" diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx index 3c3a5d1dc..c6d46e936 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.cxx +++ b/Source/cmGlobalMinGWMakefileGenerator.cxx @@ -6,6 +6,7 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmState.h" +#include "cmake.h" cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator(cmake* cm) : cmGlobalUnixMakefileGenerator3(cm) diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index eb66bd12b..ffe95f905 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -6,6 +6,7 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmState.h" +#include "cmake.h" cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm) : cmGlobalUnixMakefileGenerator3(cm) @@ -54,7 +55,7 @@ void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice( } void cmGlobalNMakeMakefileGenerator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, const std::string& targetName, const std::string& config, bool fast, int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions) diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index 62dea6ebc..06c48e22b 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -45,7 +45,7 @@ public: bool optional) override; protected: - void GenerateBuildCommand(std::vector<std::string>& makeCommand, + void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index f51340377..920f6393c 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -19,9 +19,11 @@ #include "cmGeneratedFileStream.h" #include "cmGeneratorExpressionEvaluationFile.h" #include "cmGeneratorTarget.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmNinjaLinkLineComputer.h" #include "cmOutputConverter.h" #include "cmState.h" @@ -111,7 +113,7 @@ std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit) std::string cmGlobalNinjaGenerator::EncodePath(const std::string& path) { - std::string result = path; // NOLINT(clang-tidy) + std::string result = path; #ifdef _WIN32 if (this->IsGCCOnWindows()) std::replace(result.begin(), result.end(), '\\', '/'); @@ -253,7 +255,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( bool restat, const cmNinjaDeps& outputs, const cmNinjaDeps& deps, const cmNinjaDeps& orderOnly) { - std::string cmd = command; // NOLINT(clang-tidy) + std::string cmd = command; // NOLINT(*) #ifdef _WIN32 if (cmd.empty()) // TODO Shouldn't an empty command be handled by ninja? @@ -446,14 +448,13 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm) , BuildFileStream(nullptr) , RulesFileStream(nullptr) , CompileCommandsStream(nullptr) - , Rules() - , AllDependencies() , UsingGCCOnWindows(false) , ComputingUnknownDependencies(false) , PolicyCMP0058(cmPolicies::WARN) , NinjaSupportsConsolePool(false) , NinjaSupportsImplicitOuts(false) , NinjaSupportsManifestRestat(false) + , NinjaSupportsMultilineDepfile(false) , NinjaSupportsDyndeps(0) { #ifdef _WIN32 @@ -502,8 +503,9 @@ void cmGlobalNinjaGenerator::Generate() std::ostringstream msg; msg << "The detected version of Ninja (" << this->NinjaVersion; msg << ") is less than the version of Ninja required by CMake ("; - msg << this->RequiredNinjaVersion() << ")."; - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, msg.str()); + msg << cmGlobalNinjaGenerator::RequiredNinjaVersion() << ")."; + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + msg.str()); return; } this->OpenBuildFileStream(); @@ -549,13 +551,13 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) this->NinjaCommand = ninjaCommand; std::vector<std::string> command; command.push_back(this->NinjaCommand); - command.push_back("--version"); + command.emplace_back("--version"); std::string version; std::string error; if (!cmSystemTools::RunSingleCommand(command, &version, &error, nullptr, nullptr, cmSystemTools::OUTPUT_NONE)) { - mf->IssueMessage(cmake::FATAL_ERROR, + mf->IssueMessage(MessageType::FATAL_ERROR, "Running\n '" + cmJoin(command, "' '") + "'\n" "failed with:\n " + @@ -576,10 +578,13 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() RequiredNinjaVersionForConsolePool().c_str()); this->NinjaSupportsImplicitOuts = !cmSystemTools::VersionCompare( cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - this->RequiredNinjaVersionForImplicitOuts().c_str()); + cmGlobalNinjaGenerator::RequiredNinjaVersionForImplicitOuts().c_str()); this->NinjaSupportsManifestRestat = !cmSystemTools::VersionCompare( cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), RequiredNinjaVersionForManifestRestat().c_str()); + this->NinjaSupportsMultilineDepfile = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForMultilineDepfile().c_str()); { // Our ninja branch adds ".dyndep-#" to its version number, // where '#' is a feature-specific version number. Extract it. @@ -635,7 +640,7 @@ bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const ; /* clang-format on */ } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -672,31 +677,28 @@ void cmGlobalNinjaGenerator::EnableLanguage( // Called by: // cmGlobalGenerator::Build() void cmGlobalNinjaGenerator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& /*projectName*/, const std::string& /*projectDir*/, const std::string& targetName, const std::string& /*config*/, bool /*fast*/, int jobs, bool verbose, std::vector<std::string> const& makeOptions) { - makeCommand.push_back(this->SelectMakeProgram(makeProgram)); + makeCommand.add(this->SelectMakeProgram(makeProgram)); if (verbose) { - makeCommand.push_back("-v"); + makeCommand.add("-v"); } if ((jobs != cmake::NO_BUILD_PARALLEL_LEVEL) && (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL)) { - makeCommand.push_back("-j"); - makeCommand.push_back(std::to_string(jobs)); + makeCommand.add("-j", std::to_string(jobs)); } - makeCommand.insert(makeCommand.end(), makeOptions.begin(), - makeOptions.end()); + makeCommand.add(makeOptions.begin(), makeOptions.end()); if (!targetName.empty()) { if (targetName == "clean") { - makeCommand.push_back("-t"); - makeCommand.push_back("clean"); + makeCommand.add("-t", "clean"); } else { - makeCommand.push_back(targetName); + makeCommand.add(targetName); } } } @@ -837,7 +839,7 @@ static void EnsureTrailingSlash(std::string& path) if (path.empty()) { return; } - std::string::value_type last = path[path.size() - 1]; + std::string::value_type last = path.back(); #ifdef _WIN32 if (last != '\\') { path += '\\'; @@ -860,7 +862,7 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath( cmLocalNinjaGenerator* ng = static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]); std::string const& bin_dir = ng->GetState()->GetBinaryDirectory(); - std::string convPath = ng->ConvertToRelativePath(bin_dir, path); + std::string convPath = ng->MaybeConvertToRelativePath(bin_dir, path); convPath = this->NinjaOutputPath(convPath); #ifdef _WIN32 std::replace(convPath.begin(), convPath.end(), '/', '\\'); @@ -1008,10 +1010,11 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { // These depend only on other CMake-provided targets, e.g. "all". - std::set<std::string> const& utils = target->GetUtilities(); - for (std::string const& util : utils) { + std::set<BT<std::string>> const& utils = target->GetUtilities(); + for (BT<std::string> const& util : utils) { std::string d = - target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + util; + target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + + util.Value; outputs.push_back(this->ConvertToNinjaPath(d)); } } else { @@ -1300,7 +1303,8 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) "options to the custom commands that produce these files." ; /* clang-format on */ - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + w.str()); } } @@ -1423,10 +1427,13 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) << "is less than the version of Ninja required by CMake for adding " "restat dependencies to the build.ninja manifest regeneration " "target:\n" - << " " << this->RequiredNinjaVersionForManifestRestat() << "\n"; + << " " + << cmGlobalNinjaGenerator::RequiredNinjaVersionForManifestRestat() + << "\n"; msg << "Any pre-check scripts, such as those generated for file(GLOB " "CONFIGURE_DEPENDS), will not be run by Ninja."; - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, msg.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + msg.str()); } std::sort(implicitDeps.begin(), implicitDeps.end()); @@ -1475,6 +1482,11 @@ bool cmGlobalNinjaGenerator::SupportsManifestRestat() const return this->NinjaSupportsManifestRestat; } +bool cmGlobalNinjaGenerator::SupportsMultilineDepfile() const +{ + return this->NinjaSupportsMultilineDepfile; +} + void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) { WriteRule(*this->RulesFileStream, "CLEAN", ninjaCmd() + " -t clean", @@ -1667,6 +1679,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg, return 1; } + cmFortranCompiler fc; std::vector<std::string> includes; { Json::Value tdio; @@ -1688,11 +1701,20 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg, includes.push_back(tdi_include_dir.asString()); } } + + Json::Value const& tdi_compiler_id = tdi["compiler-id"]; + fc.Id = tdi_compiler_id.asString(); + + Json::Value const& tdi_submodule_sep = tdi["submodule-sep"]; + fc.SModSep = tdi_submodule_sep.asString(); + + Json::Value const& tdi_submodule_ext = tdi["submodule-ext"]; + fc.SModExt = tdi_submodule_ext.asString(); } cmFortranSourceInfo info; std::set<std::string> defines; - cmFortranParser parser(includes, defines, info); + cmFortranParser parser(fc, includes, defines, info); if (!cmFortranParser_FilePush(&parser, arg_pp.c_str())) { cmSystemTools::Error("-E cmake_ninja_depends failed to open ", arg_pp.c_str()); @@ -1933,12 +1955,12 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, } } - cmake cm(cmake::RoleInternal); + cmake cm(cmake::RoleInternal, cmState::Unknown); cm.SetHomeDirectory(dir_top_src); cm.SetHomeOutputDirectory(dir_top_bld); std::unique_ptr<cmGlobalNinjaGenerator> ggd( static_cast<cmGlobalNinjaGenerator*>(cm.CreateGlobalGenerator("Ninja"))); - if (!ggd.get() || + if (!ggd || !ggd->WriteDyndepFile(dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis, module_dir, linked_target_dirs)) { diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 00fa348c0..c619e672f 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -183,8 +183,6 @@ public: return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); } - ~cmGlobalNinjaGenerator() override {} - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; std::string GetName() const override @@ -202,7 +200,7 @@ public: void EnableLanguage(std::vector<std::string> const& languages, cmMakefile* mf, bool optional) override; - void GenerateBuildCommand(std::vector<std::string>& makeCommand, + void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, @@ -331,9 +329,9 @@ public: return LocalGenerators; } - bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) + bool IsExcluded(cmGeneratorTarget* target) { - return cmGlobalGenerator::IsExcluded(root, target); + return cmGlobalGenerator::IsExcluded(target); } int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; } @@ -347,9 +345,14 @@ public: static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; } static std::string RequiredNinjaVersionForImplicitOuts() { return "1.7"; } static std::string RequiredNinjaVersionForManifestRestat() { return "1.8"; } + static std::string RequiredNinjaVersionForMultilineDepfile() + { + return "1.9"; + } bool SupportsConsolePool() const; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; + bool SupportsMultilineDepfile() const; std::string NinjaOutputPath(std::string const& path) const; bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); } @@ -463,6 +466,7 @@ private: bool NinjaSupportsConsolePool; bool NinjaSupportsImplicitOuts; bool NinjaSupportsManifestRestat; + bool NinjaSupportsMultilineDepfile; unsigned long NinjaSupportsDyndeps; private: diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index db7235366..dac6ea606 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -7,6 +7,7 @@ #include <sstream> #include <utility> +#include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -145,7 +146,7 @@ void cmGlobalUnixMakefileGenerator3::Generate() for (cmLocalGenerator* lg : this->LocalGenerators) { std::string markFileName = lg->GetCurrentBinaryDirectory(); markFileName += "/"; - markFileName += cmake::GetCMakeFilesDirectory(); + markFileName += "/CMakeFiles"; markFileName += "/progress.marks"; cmGeneratedFileStream markFile(markFileName); markFile << this->CountProgressMarksInAll(lg) << "\n"; @@ -195,7 +196,7 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() // see if the build system must be regenerated. std::string makefileName = this->GetCMakeInstance()->GetHomeOutputDirectory(); - makefileName += cmake::GetCMakeFilesDirectory(); + makefileName += "/CMakeFiles"; makefileName += "/Makefile2"; cmGeneratedFileStream makefileStream(makefileName, false, this->GetMakefileEncoding()); @@ -215,7 +216,7 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() // Just depend on the all target to drive the build. std::vector<std::string> depends; std::vector<std::string> no_commands; - depends.push_back("all"); + depends.emplace_back("all"); // Write the rule. lg->WriteMakeRule(makefileStream, @@ -267,7 +268,7 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() // see if the build system must be regenerated. std::string cmakefileName = this->GetCMakeInstance()->GetHomeOutputDirectory(); - cmakefileName += cmake::GetCMakeFilesDirectory(); + cmakefileName += "/CMakeFiles"; cmakefileName += "/Makefile.cmake"; cmGeneratedFileStream cmakefileStream(cmakefileName); if (!cmakefileStream) { @@ -324,23 +325,26 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() << "set(CMAKE_MAKEFILE_DEPENDS\n" << " \"CMakeCache.txt\"\n"; for (std::string const& f : lfiles) { - cmakefileStream << " \"" << lg->ConvertToRelativePath(currentBinDir, f) + cmakefileStream << " \"" + << lg->MaybeConvertToRelativePath(currentBinDir, f) << "\"\n"; } cmakefileStream << " )\n\n"; // Build the path to the cache check file. std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory(); - check += cmake::GetCMakeFilesDirectory(); + check += "/CMakeFiles"; check += "/cmake.check_cache"; // Set the corresponding makefile in the cmake file. cmakefileStream << "# The corresponding makefile is:\n" << "set(CMAKE_MAKEFILE_OUTPUTS\n" << " \"" - << lg->ConvertToRelativePath(currentBinDir, makefileName) + << lg->MaybeConvertToRelativePath(currentBinDir, + makefileName) << "\"\n" - << " \"" << lg->ConvertToRelativePath(currentBinDir, check) + << " \"" + << lg->MaybeConvertToRelativePath(currentBinDir, check) << "\"\n"; cmakefileStream << " )\n\n"; @@ -353,7 +357,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() const std::vector<std::string>& outfiles = lg->GetMakefile()->GetOutputFiles(); for (std::string const& outfile : outfiles) { - cmakefileStream << " \"" << lg->ConvertToRelativePath(binDir, outfile) + cmakefileStream << " \"" + << lg->MaybeConvertToRelativePath(binDir, outfile) << "\"\n"; } @@ -362,9 +367,10 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() for (cmLocalGenerator* localGen : this->LocalGenerators) { lg = static_cast<cmLocalUnixMakefileGenerator3*>(localGen); tmpStr = lg->GetCurrentBinaryDirectory(); - tmpStr += cmake::GetCMakeFilesDirectory(); + tmpStr += "/CMakeFiles"; tmpStr += "/CMakeDirectoryInformation.cmake"; - cmakefileStream << " \"" << lg->ConvertToRelativePath(binDir, tmpStr) + cmakefileStream << " \"" + << lg->MaybeConvertToRelativePath(binDir, tmpStr) << "\"\n"; } cmakefileStream << " )\n\n"; @@ -473,7 +479,7 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2( // Begin the directory-level rules section. std::string dir = - cmSystemTools::ConvertToOutputPath(lg->ConvertToRelativePath( + cmSystemTools::ConvertToOutputPath(lg->MaybeConvertToRelativePath( lg->GetBinaryDirectory(), lg->GetCurrentBinaryDirectory())); lg->WriteDivider(ruleFileStream); ruleFileStream << "# Directory level rules for directory " << dir << "\n\n"; @@ -489,11 +495,12 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2( } void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& /*projectName*/, const std::string& /*projectDir*/, const std::string& targetName, const std::string& /*config*/, bool fast, - int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions) + int jobs, bool verbose, std::vector<std::string> const& makeOptions) { + std::unique_ptr<cmMakefile> mfu; cmMakefile* mf; if (!this->Makefiles.empty()) { mf = this->Makefiles[0]; @@ -504,33 +511,37 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( snapshot.GetDirectory().SetCurrentBinary( this->CMakeInstance->GetHomeOutputDirectory()); snapshot.SetDefaultDefinitions(); - mf = new cmMakefile(this, snapshot); + mfu = cm::make_unique<cmMakefile>(this, snapshot); + mf = mfu.get(); } - makeCommand.push_back(this->SelectMakeProgram(makeProgram)); + // Make it possible to set verbosity also from command line + if (verbose) { + makeCommand.add(cmSystemTools::GetCMakeCommand()); + makeCommand.add("-E"); + makeCommand.add("env"); + makeCommand.add("VERBOSE=1"); + } + makeCommand.add(this->SelectMakeProgram(makeProgram)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - makeCommand.push_back("-j"); + makeCommand.add("-j"); if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.push_back(std::to_string(jobs)); + makeCommand.add(std::to_string(jobs)); } } - makeCommand.insert(makeCommand.end(), makeOptions.begin(), - makeOptions.end()); + makeCommand.add(makeOptions.begin(), makeOptions.end()); if (!targetName.empty()) { std::string tname = targetName; if (fast) { tname += "/fast"; } - cmOutputConverter conv(mf->GetStateSnapshot()); tname = - conv.ConvertToRelativePath(mf->GetState()->GetBinaryDirectory(), tname); + mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained( + mf->GetState()->GetBinaryDirectory(), tname); cmSystemTools::ConvertToOutputSlashes(tname); - makeCommand.push_back(std::move(tname)); - } - if (this->Makefiles.empty()) { - delete mf; + makeCommand.add(std::move(tname)); } } @@ -542,7 +553,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); if (regenerate) { - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } // write the target convenience rules @@ -572,12 +583,12 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( // Write the rule. commands.clear(); - std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash(); + std::string tmp = "CMakeFiles/"; tmp += "Makefile2"; - commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), name)); + commands.push_back(lg->GetRecursiveMakeCall(tmp, name)); depends.clear(); if (regenerate) { - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name, depends, commands, true); @@ -594,7 +605,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( localName = name; localName += "/fast"; commands.push_back( - lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName)); + lg->GetRecursiveMakeCall(makefileName, makeTargetName)); lg->WriteMakeRule(ruleFileStream, "fast build rule for target.", localName, depends, commands, true); @@ -608,7 +619,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( depends.clear(); commands.clear(); commands.push_back( - lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName)); + lg->GetRecursiveMakeCall(makefileName, makeTargetName)); lg->WriteMakeRule(ruleFileStream, "Manual pre-install relink rule for target.", localName, depends, commands, true); @@ -631,7 +642,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); if (regenerate) { - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } // for each target Generate the rule files for each target. @@ -659,12 +670,12 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( makeTargetName = localName; makeTargetName += "/depend"; commands.push_back( - lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName)); + lg->GetRecursiveMakeCall(makefileName, makeTargetName)); makeTargetName = localName; makeTargetName += "/build"; commands.push_back( - lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName)); + lg->GetRecursiveMakeCall(makefileName, makeTargetName)); // Write the rule. localName += "/all"; @@ -672,7 +683,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( cmLocalUnixMakefileGenerator3::EchoProgress progress; progress.Dir = lg->GetBinaryDirectory(); - progress.Dir += cmake::GetCMakeFilesDirectory(); + progress.Dir += "/CMakeFiles"; { std::ostringstream progressArg; const char* sep = ""; @@ -702,7 +713,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( localName, depends, commands, true); // add the all/all dependency - if (!this->IsExcluded(this->LocalGenerators[0], gtarget)) { + if (!this->IsExcluded(gtarget)) { depends.clear(); depends.push_back(localName); commands.clear(); @@ -726,9 +737,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( progCmd << " " << this->CountProgressMarksInTarget(gtarget, emitted); commands.push_back(progCmd.str()); } - std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash(); + std::string tmp = "CMakeFiles/"; tmp += "Makefile2"; - commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), localName)); + commands.push_back(lg->GetRecursiveMakeCall(tmp, localName)); { std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0 @@ -740,7 +751,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( } depends.clear(); if (regenerate) { - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } localName = lg->GetRelativeTargetDirectory(gtarget); localName += "/rule"; @@ -761,13 +772,12 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( localName += "/preinstall"; depends.clear(); commands.clear(); - commands.push_back( - lg->GetRecursiveMakeCall(makefileName.c_str(), localName)); + commands.push_back(lg->GetRecursiveMakeCall(makefileName, localName)); lg->WriteMakeRule(ruleFileStream, "Pre-install relink rule for target.", localName, depends, commands, true); - if (!this->IsExcluded(this->LocalGenerators[0], gtarget)) { + if (!this->IsExcluded(gtarget)) { depends.clear(); depends.push_back(localName); commands.clear(); @@ -783,7 +793,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( depends.clear(); commands.clear(); commands.push_back( - lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName)); + lg->GetRecursiveMakeCall(makefileName, makeTargetName)); lg->WriteMakeRule(ruleFileStream, "clean rule for target.", makeTargetName, depends, commands, true); commands.clear(); diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index a2ad09516..8a80acc05 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -127,7 +127,7 @@ public: std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; } // change the build command for speed - void GenerateBuildCommand(std::vector<std::string>& makeCommand, + void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, @@ -217,11 +217,7 @@ protected: // Store per-target progress counters. struct TargetProgress { - TargetProgress() - : NumberOfActions(0) - { - } - unsigned long NumberOfActions; + unsigned long NumberOfActions = 0; std::string VariableFile; std::vector<unsigned long> Marks; void WriteProgressVariables(unsigned long total, unsigned long& current); diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 82fcaadde..d8b2e892c 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -7,20 +7,13 @@ #include "cmGeneratorTarget.h" #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" -#include "cmVS10CLFlagTable.h" -#include "cmVS10CSharpFlagTable.h" -#include "cmVS10CudaFlagTable.h" -#include "cmVS10CudaHostFlagTable.h" -#include "cmVS10LibFlagTable.h" -#include "cmVS10LinkFlagTable.h" -#include "cmVS10MASMFlagTable.h" -#include "cmVS10NASMFlagTable.h" -#include "cmVS10RCFlagTable.h" #include "cmVersion.h" #include "cmVisualStudioSlnData.h" #include "cmVisualStudioSlnParser.h" #include "cmXMLWriter.h" +#include "cm_jsoncpp_reader.h" #include "cmake.h" #include "cmsys/FStream.hxx" @@ -30,6 +23,7 @@ #include <algorithm> static const char vs10generatorName[] = "Visual Studio 10 2010"; +static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles; // Map generator name without year to name with year. static const char* cmVS10GenName(const std::string& name, std::string& genName) @@ -80,15 +74,34 @@ public: "Optional [arch] can be \"Win64\" or \"IA64\"."; } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(vs10generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; names.push_back(vs10generatorName + std::string(" IA64")); names.push_back(vs10generatorName + std::string(" Win64")); + return names; } bool SupportsToolset() const override { return true; } bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("Itanium"); + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } }; cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory() @@ -97,8 +110,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory() } cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( - cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio8Generator(cm, name, platformName) + cmake* cm, const std::string& name, + std::string const& platformInGeneratorName) + : cmGlobalVisualStudio8Generator(cm, name, platformInGeneratorName) { std::string vc10Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( @@ -120,15 +134,16 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( this->DefaultPlatformToolset = "v100"; } } - this->DefaultClFlagTable = cmVS10CLFlagTable; - this->DefaultCSharpFlagTable = cmVS10CSharpFlagTable; - this->DefaultLibFlagTable = cmVS10LibFlagTable; - this->DefaultLinkFlagTable = cmVS10LinkFlagTable; - this->DefaultCudaFlagTable = cmVS10CudaFlagTable; - this->DefaultCudaHostFlagTable = cmVS10CudaHostFlagTable; - this->DefaultMasmFlagTable = cmVS10MASMFlagTable; - this->DefaultNasmFlagTable = cmVS10NASMFlagTable; - this->DefaultRcFlagTable = cmVS10RCFlagTable; + this->DefaultCLFlagTableName = "v10"; + this->DefaultCSharpFlagTableName = "v10"; + this->DefaultLibFlagTableName = "v10"; + this->DefaultLinkFlagTableName = "v10"; + this->DefaultCudaFlagTableName = "v10"; + this->DefaultCudaHostFlagTableName = "v10"; + this->DefaultMasmFlagTableName = "v10"; + this->DefaultNasmFlagTableName = "v10"; + this->DefaultRCFlagTableName = "v10"; + this->Version = VS10; this->PlatformToolsetNeedsDebugEnum = false; } @@ -184,7 +199,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( std::ostringstream e; e << this->GetName() << " Windows CE version '" << this->SystemVersion << "' requires CMAKE_GENERATOR_TOOLSET to be set."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -257,7 +272,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( "contains an invalid version specification." ; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); // Clear the configured tool-set this->GeneratorToolsetVersion.clear(); @@ -284,7 +299,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( " " << toolsetPath; ; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); // Clear the configured tool-set this->GeneratorToolsetVersion.clear(); @@ -338,7 +353,7 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( "that contains a field after the first ',' with no '='." ; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } std::string const key = fi->substr(0, pos); @@ -354,7 +369,7 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( "that contains duplicate field key '" << key << "'." ; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } if (!this->ProcessGeneratorToolsetField(key, value)) { @@ -368,7 +383,7 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( "that contains invalid field '" << *fi << "'." ; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } } @@ -412,16 +427,16 @@ bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) return false; } } else if (this->SystemName == "Android") { - if (this->DefaultPlatformName != "Win32") { + if (this->PlatformInGeneratorName) { std::ostringstream e; e << "CMAKE_SYSTEM_NAME is 'Android' but CMAKE_GENERATOR " << "specifies a platform too: '" << this->GetName() << "'"; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } std::string v = this->GetInstalledNsightTegraVersion(); if (v.empty()) { - mf->IssueMessage(cmake::FATAL_ERROR, + mf->IssueMessage(MessageType::FATAL_ERROR, "CMAKE_SYSTEM_NAME is 'Android' but " "'NVIDIA Nsight Tegra Visual Studio Edition' " "is not installed."); @@ -443,11 +458,11 @@ bool cmGlobalVisualStudio10Generator::InitializeWindows(cmMakefile*) bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile* mf) { - if (this->DefaultPlatformName != "Win32") { + if (this->PlatformInGeneratorName) { std::ostringstream e; e << "CMAKE_SYSTEM_NAME is 'WindowsCE' but CMAKE_GENERATOR " << "specifies a platform too: '" << this->GetName() << "'"; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -460,7 +475,7 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsPhone(cmMakefile* mf) { std::ostringstream e; e << this->GetName() << " does not support Windows Phone."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -468,7 +483,7 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsStore(cmMakefile* mf) { std::ostringstream e; e << this->GetName() << " does not support Windows Store."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -494,16 +509,6 @@ std::string cmGlobalVisualStudio10Generator::SelectWindowsCEToolset() const return ""; } -void cmGlobalVisualStudio10Generator::WriteSLNHeader(std::ostream& fout) -{ - fout << "Microsoft Visual Studio Solution File, Format Version 11.00\n"; - if (this->ExpressEdition) { - fout << "# Visual C++ Express 2010\n"; - } else { - fout << "# Visual Studio 2010\n"; - } -} - ///! Create a local generator appropriate to this Global Generator cmLocalGenerator* cmGlobalVisualStudio10Generator::CreateLocalGenerator( cmMakefile* mf) @@ -539,7 +544,7 @@ void cmGlobalVisualStudio10Generator::Generate() "To avoid this problem CMake must use a full path for this file " "which then triggers the VS 10 property dialog bug."; /* clang-format on */ - lg->IssueMessage(cmake::WARNING, e.str().c_str()); + lg->IssueMessage(MessageType::WARNING, e.str().c_str()); } } @@ -602,10 +607,26 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetVersionString() const const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const { + std::string const& hostArch = + this->GetPlatformToolsetHostArchitectureString(); + if (hostArch.empty()) { + return nullptr; + } + return hostArch.c_str(); +} + +std::string const& +cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitectureString() + const +{ if (!this->GeneratorToolsetHostArchitecture.empty()) { - return this->GeneratorToolsetHostArchitecture.c_str(); + return this->GeneratorToolsetHostArchitecture; } - return nullptr; + if (!this->DefaultPlatformToolsetHostArchitecture.empty()) { + return this->DefaultPlatformToolsetHostArchitecture; + } + static std::string const empty; + return empty; } const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCuda() const @@ -701,7 +722,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) wd = this->ConfiguredFilesPath; } else { wd = this->GetCMakeInstance()->GetHomeOutputDirectory(); - wd += cmake::GetCMakeFilesDirectory(); + wd += "/CMakeFiles"; } wd += "/"; wd += cmVersion::GetCMakeVersion(); @@ -722,7 +743,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) // Prepare the work directory. if (!cmSystemTools::MakeDirectory(wd)) { std::string e = "Failed to make directory:\n " + wd; - mf->IssueMessage(cmake::FATAL_ERROR, e.c_str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.c_str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -781,10 +802,9 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) } cmXMLElement(eprj, "Import") .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); - if (!this->GeneratorToolsetHostArchitecture.empty()) { + if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) { cmXMLElement epg(eprj, "PropertyGroup"); - cmXMLElement(epg, "PreferredToolArchitecture") - .Content(this->GeneratorToolsetHostArchitecture); + cmXMLElement(epg, "PreferredToolArchitecture").Content(hostArch); } { cmXMLElement epg(eprj, "PropertyGroup"); @@ -844,7 +864,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) if (ret != 0) { e << "Exit code: " << ret << "\n"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -859,7 +879,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) } void cmGlobalVisualStudio10Generator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, const std::string& targetName, const std::string& config, bool fast, int jobs, bool verbose, std::vector<std::string> const& makeOptions) @@ -874,6 +894,10 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand( bool useDevEnv = (makeProgramLower.find("devenv") != std::string::npos || makeProgramLower.find("vcexpress") != std::string::npos); + // Workaround to convince VCExpress.exe to produce output. + makeCommand.RequiresOutputForward = + (makeProgramLower.find("vcexpress") != std::string::npos); + // MSBuild is preferred (and required for VS Express), but if the .sln has // an Intel Fortran .vfproj then we have to use devenv. Parse it to find out. cmSlnData slnData; @@ -907,7 +931,7 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand( return; } - makeCommand.push_back(makeProgramSelected); + makeCommand.add(makeProgramSelected); std::string realTarget = targetName; // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug /target:ALL_BUILD @@ -916,8 +940,8 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand( realTarget = "ALL_BUILD"; } if (realTarget == "clean") { - makeCommand.push_back(std::string(projectName) + ".sln"); - makeCommand.push_back("/t:Clean"); + makeCommand.add(std::string(projectName) + ".sln"); + makeCommand.add("/t:Clean"); } else { std::string targetProject(realTarget); targetProject += ".vcxproj"; @@ -929,7 +953,7 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand( cmSystemTools::ConvertToUnixSlashes(targetProject); } } - makeCommand.push_back(targetProject); + makeCommand.add(std::move(targetProject)); } std::string configArg = "/p:Configuration="; if (!config.empty()) { @@ -937,23 +961,26 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand( } else { configArg += "Debug"; } - makeCommand.push_back(configArg); - makeCommand.push_back("/p:Platform=" + this->GetPlatformName()); - makeCommand.push_back(std::string("/p:VisualStudioVersion=") + - this->GetIDEVersion()); + makeCommand.add(configArg); + makeCommand.add(std::string("/p:Platform=") + this->GetPlatformName()); + makeCommand.add(std::string("/p:VisualStudioVersion=") + + this->GetIDEVersion()); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.push_back("/m"); + makeCommand.add("/m"); } else { - makeCommand.push_back(std::string("/m:") + std::to_string(jobs)); + makeCommand.add(std::string("/m:") + std::to_string(jobs)); } // Having msbuild.exe and cl.exe using multiple jobs is discouraged - makeCommand.push_back("/p:CL_MPCount=1"); + makeCommand.add("/p:CL_MPCount=1"); } - makeCommand.insert(makeCommand.end(), makeOptions.begin(), - makeOptions.end()); + // Respect the verbosity: 'n' normal will show build commands + // 'm' minimal only the build step's title + makeCommand.add(std::string("/v:") + ((verbose) ? "n" : "m")); + + makeCommand.add(makeOptions.begin(), makeOptions.end()); } bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf) @@ -988,7 +1015,7 @@ bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf) << "Install the Microsoft Windows SDK v7.1 to get 64-bit tools:\n" << " http://msdn.microsoft.com/en-us/windows/bb980924.aspx"; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -1000,7 +1027,7 @@ std::string cmGlobalVisualStudio10Generator::GenerateRuleFile( // The VS 10 generator needs to create the .rule files on disk. // Hide them away under the CMakeFiles directory. std::string ruleDir = this->GetCMakeInstance()->GetHomeOutputDirectory(); - ruleDir += cmake::GetCMakeFilesDirectory(); + ruleDir += "/CMakeFiles"; ruleDir += "/"; ruleDir += cmSystemTools::ComputeStringMD5( cmSystemTools::GetFilenamePath(output).c_str()); @@ -1030,6 +1057,29 @@ std::string cmGlobalVisualStudio10Generator::Encoding() return "utf-8"; } +const char* cmGlobalVisualStudio10Generator::GetToolsVersion() const +{ + switch (this->Version) { + case cmGlobalVisualStudioGenerator::VS9: + case cmGlobalVisualStudioGenerator::VS10: + case cmGlobalVisualStudioGenerator::VS11: + return "4.0"; + + // in Visual Studio 2013 they detached the MSBuild tools version + // from the .Net Framework version and instead made it have it's own + // version number + case cmGlobalVisualStudioGenerator::VS12: + return "12.0"; + case cmGlobalVisualStudioGenerator::VS14: + return "14.0"; + case cmGlobalVisualStudioGenerator::VS15: + return "15.0"; + case cmGlobalVisualStudioGenerator::VS16: + return "16.0"; + } + return ""; +} + bool cmGlobalVisualStudio10Generator::IsNsightTegra() const { return !this->NsightTegraVersion.empty(); @@ -1050,67 +1100,218 @@ std::string cmGlobalVisualStudio10Generator::GetInstalledNsightTegraVersion() return version; } +static std::string cmLoadFlagTableString(Json::Value entry, const char* field) +{ + if (entry.isMember(field)) { + auto string = entry[field]; + if (string.isConvertibleTo(Json::ValueType::stringValue)) { + return string.asString(); + } + } + return ""; +} + +static unsigned int cmLoadFlagTableSpecial(Json::Value entry, + const char* field) +{ + unsigned int value = 0; + if (entry.isMember(field)) { + auto specials = entry[field]; + if (specials.isArray()) { + for (auto const& special : specials) { + std::string s = special.asString(); + if (s == "UserValue") { + value |= cmIDEFlagTable::UserValue; + } else if (s == "UserIgnored") { + value |= cmIDEFlagTable::UserIgnored; + } else if (s == "UserRequired") { + value |= cmIDEFlagTable::UserRequired; + } else if (s == "Continue") { + value |= cmIDEFlagTable::Continue; + } else if (s == "SemicolonAppendable") { + value |= cmIDEFlagTable::SemicolonAppendable; + } else if (s == "UserFollowing") { + value |= cmIDEFlagTable::UserFollowing; + } else if (s == "CaseInsensitive") { + value |= cmIDEFlagTable::CaseInsensitive; + } else if (s == "SpaceAppendable") { + value |= cmIDEFlagTable::SpaceAppendable; + } else if (s == "CommaAppendable") { + value |= cmIDEFlagTable::CommaAppendable; + } + } + } + } + return value; +} + +static cmIDEFlagTable const* cmLoadFlagTableJson( + std::string const& flagJsonPath) +{ + cmIDEFlagTable* ret = nullptr; + auto savedFlagIterator = loadedFlagJsonFiles.find(flagJsonPath); + if (savedFlagIterator != loadedFlagJsonFiles.end()) { + ret = savedFlagIterator->second.data(); + } else { + Json::Reader reader; + cmsys::ifstream stream; + + stream.open(flagJsonPath.c_str(), std::ios_base::in); + if (stream) { + Json::Value flags; + if (reader.parse(stream, flags, false) && flags.isArray()) { + std::vector<cmIDEFlagTable> flagTable; + for (auto const& flag : flags) { + cmIDEFlagTable flagEntry; + flagEntry.IDEName = cmLoadFlagTableString(flag, "name"); + flagEntry.commandFlag = cmLoadFlagTableString(flag, "switch"); + flagEntry.comment = cmLoadFlagTableString(flag, "comment"); + flagEntry.value = cmLoadFlagTableString(flag, "value"); + flagEntry.special = cmLoadFlagTableSpecial(flag, "flags"); + flagTable.push_back(flagEntry); + } + cmIDEFlagTable endFlag{ "", "", "", "", 0 }; + flagTable.push_back(endFlag); + + loadedFlagJsonFiles[flagJsonPath] = flagTable; + ret = loadedFlagJsonFiles[flagJsonPath].data(); + } + } + } + return ret; +} + +static std::string cmGetFlagTableName(std::string const& toolsetName, + std::string const& table) +{ + return cmSystemTools::GetCMakeRoot() + "/Templates/MSBuild/FlagTables/" + + toolsetName + "_" + table + ".json"; +} + +cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( + std::string const& optionsName, std::string const& toolsetName, + std::string const& defaultName, std::string const& table) const +{ + cmIDEFlagTable const* ret = nullptr; + + std::string filename; + if (!optionsName.empty()) { + filename = cmGetFlagTableName(optionsName, table); + ret = cmLoadFlagTableJson(filename); + } else { + filename = cmGetFlagTableName(toolsetName, table); + if (cmSystemTools::FileExists(filename)) { + ret = cmLoadFlagTableJson(filename); + } else { + filename = cmGetFlagTableName(defaultName, table); + ret = cmLoadFlagTableJson(filename); + } + } + + if (!ret) { + cmMakefile* mf = this->GetCurrentMakefile(); + + std::ostringstream e; + /* clang-format off */ + e << "JSON flag table \"" << filename << + "\" could not be loaded.\n"; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str()); + } + return ret; +} + cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const { - cmIDEFlagTable const* table = this->ToolsetOptions.GetClFlagTable( + std::string optionsName = this->ToolsetOptions.GetClFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - - return (table != nullptr) ? table : this->DefaultClFlagTable; + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultCLFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "CL"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() const { - cmIDEFlagTable const* table = this->ToolsetOptions.GetCSharpFlagTable( + std::string optionsName = this->ToolsetOptions.GetCSharpFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - - return (table != nullptr) ? table : this->DefaultCSharpFlagTable; + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultCSharpFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "CSharp"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const { - cmIDEFlagTable const* table = this->ToolsetOptions.GetRcFlagTable( + std::string optionsName = this->ToolsetOptions.GetRcFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - - return (table != nullptr) ? table : this->DefaultRcFlagTable; + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultRCFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "RC"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const { - cmIDEFlagTable const* table = this->ToolsetOptions.GetLibFlagTable( + std::string optionsName = this->ToolsetOptions.GetLibFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - - return (table != nullptr) ? table : this->DefaultLibFlagTable; + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultLibFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "LIB"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const { - cmIDEFlagTable const* table = this->ToolsetOptions.GetLinkFlagTable( + std::string optionsName = this->ToolsetOptions.GetLinkFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - - return (table != nullptr) ? table : this->DefaultLinkFlagTable; + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultLinkFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "Link"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const { - return this->DefaultCudaFlagTable; + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultCudaFlagTableName); + return LoadFlagTable("", toolsetName, defaultName, "Cuda"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() const { - return this->DefaultCudaHostFlagTable; + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultCudaHostFlagTableName); + return LoadFlagTable("", toolsetName, defaultName, "CudaHost"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { - cmIDEFlagTable const* table = this->ToolsetOptions.GetMasmFlagTable( + std::string optionsName = this->ToolsetOptions.GetMasmFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - - return (table != nullptr) ? table : this->DefaultMasmFlagTable; + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultMasmFlagTableName); + return LoadFlagTable(optionsName, toolsetName, defaultName, "MASM"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const { - return this->DefaultNasmFlagTable; + std::string toolsetName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->GetPlatformToolsetString()); + std::string defaultName = this->ToolsetOptions.GetToolsetName( + this->GetPlatformName(), this->DefaultNasmFlagTableName); + return LoadFlagTable("", toolsetName, defaultName, "NASM"); } diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 63e690343..3ef7abfd0 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -14,8 +14,6 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator { public: - cmGlobalVisualStudio10Generator(cmake* cm, const std::string& name, - const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; @@ -24,7 +22,7 @@ public: bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; - void GenerateBuildCommand(std::vector<std::string>& makeCommand, + void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, @@ -43,7 +41,6 @@ public: */ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*, bool optional) override; - void WriteSLNHeader(std::ostream& fout) override; bool IsCudaEnabled() const { return this->CudaEnabled; } @@ -61,6 +58,7 @@ public: /** The toolset host architecture name (e.g. x64 for 64-bit host tools). */ const char* GetPlatformToolsetHostArchitecture() const; + std::string const& GetPlatformToolsetHostArchitectureString() const; /** The cuda toolset version. */ const char* GetPlatformToolsetCuda() const; @@ -86,7 +84,7 @@ public: } /** Return true if building for WindowsCE */ - bool TargetsWindowsCE() const { return this->SystemIsWindowsCE; } + bool TargetsWindowsCE() const override { return this->SystemIsWindowsCE; } /** Return true if building for WindowsPhone */ bool TargetsWindowsPhone() const { return this->SystemIsWindowsPhone; } @@ -104,7 +102,7 @@ public: std::string const& sfRel); std::string Encoding() override; - virtual const char* GetToolsVersion() { return "4.0"; } + const char* GetToolsVersion() const; virtual bool IsDefaultToolset(const std::string& version) const; virtual std::string GetAuxiliaryToolset() const; @@ -126,6 +124,9 @@ public: cmIDEFlagTable const* GetNasmFlagTable() const; protected: + cmGlobalVisualStudio10Generator(cmake* cm, const std::string& name, + std::string const& platformInGeneratorName); + void Generate() override; virtual bool InitializeSystem(cmMakefile* mf); virtual bool InitializeWindows(cmMakefile* mf); @@ -140,34 +141,40 @@ protected: virtual bool SelectWindowsPhoneToolset(std::string& toolset) const; virtual bool SelectWindowsStoreToolset(std::string& toolset) const; - const char* GetIDEVersion() override { return "10.0"; } - std::string const& GetMSBuildCommand(); + cmIDEFlagTable const* LoadFlagTable(std::string const& optionsName, + std::string const& toolsetName, + std::string const& defaultName, + std::string const& table) const; + std::string GeneratorToolset; std::string GeneratorToolsetVersion; std::string GeneratorToolsetHostArchitecture; std::string GeneratorToolsetCuda; std::string DefaultPlatformToolset; + std::string DefaultPlatformToolsetHostArchitecture; std::string WindowsTargetPlatformVersion; std::string SystemName; std::string SystemVersion; std::string NsightTegraVersion; - cmIDEFlagTable const* DefaultClFlagTable; - cmIDEFlagTable const* DefaultCSharpFlagTable; - cmIDEFlagTable const* DefaultLibFlagTable; - cmIDEFlagTable const* DefaultLinkFlagTable; - cmIDEFlagTable const* DefaultCudaFlagTable; - cmIDEFlagTable const* DefaultCudaHostFlagTable; - cmIDEFlagTable const* DefaultMasmFlagTable; - cmIDEFlagTable const* DefaultNasmFlagTable; - cmIDEFlagTable const* DefaultRcFlagTable; + std::string DefaultCLFlagTableName; + std::string DefaultCSharpFlagTableName; + std::string DefaultLibFlagTableName; + std::string DefaultLinkFlagTableName; + std::string DefaultCudaFlagTableName; + std::string DefaultCudaHostFlagTableName; + std::string DefaultMasmFlagTableName; + std::string DefaultNasmFlagTableName; + std::string DefaultRCFlagTableName; bool SystemIsWindowsCE; bool SystemIsWindowsPhone; bool SystemIsWindowsStore; private: class Factory; + friend class Factory; + struct LongestSourcePath { LongestSourcePath() diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index f1d5a8c64..4eb78ba9c 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -6,12 +6,6 @@ #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" -#include "cmVS11CLFlagTable.h" -#include "cmVS11CSharpFlagTable.h" -#include "cmVS11LibFlagTable.h" -#include "cmVS11LinkFlagTable.h" -#include "cmVS11MASMFlagTable.h" -#include "cmVS11RCFlagTable.h" static const char vs11generatorName[] = "Visual Studio 11 2012"; @@ -75,9 +69,16 @@ public: "Optional [arch] can be \"Win64\" or \"ARM\"."; } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(vs11generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; names.push_back(vs11generatorName + std::string(" ARM")); names.push_back(vs11generatorName + std::string(" Win64")); @@ -86,10 +87,30 @@ public: for (std::string const& i : installedSDKs) { names.push_back(std::string(vs11generatorName) + " " + i); } + + return names; } bool SupportsToolset() const override { return true; } bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + + std::set<std::string> installedSDKs = + cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs(); + for (std::string const& i : installedSDKs) { + platforms.emplace_back(i); + } + + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } }; cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory() @@ -98,8 +119,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory() } cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator( - cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio10Generator(cm, name, platformName) + cmake* cm, const std::string& name, + std::string const& platformInGeneratorName) + : cmGlobalVisualStudio10Generator(cm, name, platformInGeneratorName) { std::string vc11Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( @@ -107,12 +129,12 @@ cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator( "ProductDir", vc11Express, cmSystemTools::KeyWOW64_32); this->DefaultPlatformToolset = "v110"; - this->DefaultClFlagTable = cmVS11CLFlagTable; - this->DefaultCSharpFlagTable = cmVS11CSharpFlagTable; - this->DefaultLibFlagTable = cmVS11LibFlagTable; - this->DefaultLinkFlagTable = cmVS11LinkFlagTable; - this->DefaultMasmFlagTable = cmVS11MASMFlagTable; - this->DefaultRcFlagTable = cmVS11RCFlagTable; + this->DefaultCLFlagTableName = "v11"; + this->DefaultCSharpFlagTableName = "v11"; + this->DefaultLibFlagTableName = "v11"; + this->DefaultLinkFlagTableName = "v11"; + this->DefaultMasmFlagTableName = "v11"; + this->DefaultRCFlagTableName = "v11"; this->Version = VS11; } @@ -138,7 +160,7 @@ bool cmGlobalVisualStudio11Generator::InitializeWindowsPhone(cmMakefile* mf) << "Desktop SDK as well as the Windows Phone '" << this->SystemVersion << "' SDK. Please make sure that you have both installed"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } return true; @@ -156,7 +178,7 @@ bool cmGlobalVisualStudio11Generator::InitializeWindowsStore(cmMakefile* mf) << "Desktop SDK as well as the Windows Store '" << this->SystemVersion << "' SDK. Please make sure that you have both installed"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } return true; @@ -194,17 +216,7 @@ bool cmGlobalVisualStudio11Generator::SelectWindowsStoreToolset( toolset); } -void cmGlobalVisualStudio11Generator::WriteSLNHeader(std::ostream& fout) -{ - fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; - if (this->ExpressEdition) { - fout << "# Visual Studio Express 2012 for Windows Desktop\n"; - } else { - fout << "# Visual Studio 2012\n"; - } -} - -bool cmGlobalVisualStudio11Generator::UseFolderProperty() +bool cmGlobalVisualStudio11Generator::UseFolderProperty() const { // Intentionally skip up to the top-level class implementation. // Folders are not supported by the Express editions in VS10 and earlier, diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index 40f02fb12..8b4c8b739 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -20,15 +20,14 @@ class cmake; class cmGlobalVisualStudio11Generator : public cmGlobalVisualStudio10Generator { public: - cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name, - const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; - void WriteSLNHeader(std::ostream& fout) override; - protected: + cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name, + std::string const& platformInGeneratorName); + bool InitializeWindowsPhone(cmMakefile* mf) override; bool InitializeWindowsStore(cmMakefile* mf) override; bool SelectWindowsPhoneToolset(std::string& toolset) const override; @@ -43,8 +42,7 @@ protected: bool IsWindowsPhoneToolsetInstalled() const; bool IsWindowsStoreToolsetInstalled() const; - const char* GetIDEVersion() override { return "11.0"; } - bool UseFolderProperty(); + bool UseFolderProperty() const override; static std::set<std::string> GetInstalledWindowsCESDKs(); /** Return true if the configuration needs to be deployed */ diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index e05ae70dc..d9702c9ee 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -6,12 +6,6 @@ #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" -#include "cmVS12CLFlagTable.h" -#include "cmVS12CSharpFlagTable.h" -#include "cmVS12LibFlagTable.h" -#include "cmVS12LinkFlagTable.h" -#include "cmVS12MASMFlagTable.h" -#include "cmVS12RCFlagTable.h" static const char vs12generatorName[] = "Visual Studio 12 2013"; @@ -64,15 +58,34 @@ public: "Optional [arch] can be \"Win64\" or \"ARM\"."; } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(vs12generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; names.push_back(vs12generatorName + std::string(" ARM")); names.push_back(vs12generatorName + std::string(" Win64")); + return names; } bool SupportsToolset() const override { return true; } bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } }; cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory() @@ -81,8 +94,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory() } cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator( - cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio11Generator(cm, name, platformName) + cmake* cm, const std::string& name, + std::string const& platformInGeneratorName) + : cmGlobalVisualStudio11Generator(cm, name, platformInGeneratorName) { std::string vc12Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( @@ -90,12 +104,12 @@ cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator( "ProductDir", vc12Express, cmSystemTools::KeyWOW64_32); this->DefaultPlatformToolset = "v120"; - this->DefaultClFlagTable = cmVS12CLFlagTable; - this->DefaultCSharpFlagTable = cmVS12CSharpFlagTable; - this->DefaultLibFlagTable = cmVS12LibFlagTable; - this->DefaultLinkFlagTable = cmVS12LinkFlagTable; - this->DefaultMasmFlagTable = cmVS12MASMFlagTable; - this->DefaultRcFlagTable = cmVS12RCFlagTable; + this->DefaultCLFlagTableName = "v12"; + this->DefaultCSharpFlagTableName = "v12"; + this->DefaultLibFlagTableName = "v12"; + this->DefaultLinkFlagTableName = "v12"; + this->DefaultMasmFlagTableName = "v12"; + this->DefaultRCFlagTableName = "v12"; this->Version = VS12; } @@ -112,8 +126,8 @@ bool cmGlobalVisualStudio12Generator::MatchesGeneratorName( bool cmGlobalVisualStudio12Generator::ProcessGeneratorToolsetField( std::string const& key, std::string const& value) { - if (key == "host" && value == "x64") { - this->GeneratorToolsetHostArchitecture = "x64"; + if (key == "host" && (value == "x64" || value == "x86")) { + this->GeneratorToolsetHostArchitecture = value; return true; } return this->cmGlobalVisualStudio11Generator::ProcessGeneratorToolsetField( @@ -134,7 +148,7 @@ bool cmGlobalVisualStudio12Generator::InitializeWindowsPhone(cmMakefile* mf) << "Desktop SDK as well as the Windows Phone '" << this->SystemVersion << "' SDK. Please make sure that you have both installed"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } return true; @@ -154,7 +168,7 @@ bool cmGlobalVisualStudio12Generator::InitializeWindowsStore(cmMakefile* mf) << "Desktop SDK as well as the Windows Store '" << this->SystemVersion << "' SDK. Please make sure that you have both installed"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } return true; @@ -192,16 +206,6 @@ bool cmGlobalVisualStudio12Generator::SelectWindowsStoreToolset( toolset); } -void cmGlobalVisualStudio12Generator::WriteSLNHeader(std::ostream& fout) -{ - fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; - if (this->ExpressEdition) { - fout << "# Visual Studio Express 2013 for Windows Desktop\n"; - } else { - fout << "# Visual Studio 2013\n"; - } -} - bool cmGlobalVisualStudio12Generator::IsWindowsDesktopToolsetInstalled() const { const char desktop81Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index 9d6554a34..53b709157 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -18,20 +18,14 @@ class cmake; class cmGlobalVisualStudio12Generator : public cmGlobalVisualStudio11Generator { public: - cmGlobalVisualStudio12Generator(cmake* cm, const std::string& name, - const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; - void WriteSLNHeader(std::ostream& fout) override; - - // in Visual Studio 2013 they detached the MSBuild tools version - // from the .Net Framework version and instead made it have it's own - // version number - const char* GetToolsVersion() override { return "12.0"; } - protected: + cmGlobalVisualStudio12Generator(cmake* cm, const std::string& name, + std::string const& platformInGeneratorName); + bool ProcessGeneratorToolsetField(std::string const& key, std::string const& value) override; @@ -48,9 +42,9 @@ protected: // of the toolset is installed bool IsWindowsPhoneToolsetInstalled() const; bool IsWindowsStoreToolsetInstalled() const; - const char* GetIDEVersion() override { return "12.0"; } private: class Factory; + friend class Factory; }; #endif diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 92ee2e074..20258678a 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -6,12 +6,6 @@ #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" -#include "cmVS140CLFlagTable.h" -#include "cmVS140CSharpFlagTable.h" -#include "cmVS140LinkFlagTable.h" -#include "cmVS14LibFlagTable.h" -#include "cmVS14MASMFlagTable.h" -#include "cmVS14RCFlagTable.h" static const char vs14generatorName[] = "Visual Studio 14 2015"; @@ -64,15 +58,34 @@ public: "Optional [arch] can be \"Win64\" or \"ARM\"."; } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(vs14generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; names.push_back(vs14generatorName + std::string(" ARM")); names.push_back(vs14generatorName + std::string(" Win64")); + return names; } bool SupportsToolset() const override { return true; } bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } }; cmGlobalGeneratorFactory* cmGlobalVisualStudio14Generator::NewFactory() @@ -81,8 +94,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio14Generator::NewFactory() } cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator( - cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio12Generator(cm, name, platformName) + cmake* cm, const std::string& name, + std::string const& platformInGeneratorName) + : cmGlobalVisualStudio12Generator(cm, name, platformInGeneratorName) { std::string vc14Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( @@ -90,12 +104,12 @@ cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator( "ProductDir", vc14Express, cmSystemTools::KeyWOW64_32); this->DefaultPlatformToolset = "v140"; - this->DefaultClFlagTable = cmVS140CLFlagTable; - this->DefaultCSharpFlagTable = cmVS140CSharpFlagTable; - this->DefaultLibFlagTable = cmVS14LibFlagTable; - this->DefaultLinkFlagTable = cmVS140LinkFlagTable; - this->DefaultMasmFlagTable = cmVS14MASMFlagTable; - this->DefaultRcFlagTable = cmVS14RCFlagTable; + this->DefaultCLFlagTableName = "v140"; + this->DefaultCSharpFlagTableName = "v140"; + this->DefaultLibFlagTableName = "v14"; + this->DefaultLinkFlagTableName = "v140"; + this->DefaultMasmFlagTableName = "v14"; + this->DefaultRCFlagTableName = "v14"; this->Version = VS14; } @@ -131,7 +145,7 @@ bool cmGlobalVisualStudio14Generator::InitializeWindowsStore(cmMakefile* mf) << "Desktop SDK as well as the Windows Store '" << this->SystemVersion << "' SDK. Please make sure that you have both installed"; } - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { @@ -144,14 +158,22 @@ bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf, bool required) { // Find the default version of the Windows 10 SDK. - this->WindowsTargetPlatformVersion = this->GetWindows10SDKVersion(); - if (required && this->WindowsTargetPlatformVersion.empty()) { + std::string const version = this->GetWindows10SDKVersion(); + if (required && version.empty()) { std::ostringstream e; e << "Could not find an appropriate version of the Windows 10 SDK" << " installed on this machine"; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } + this->SetWindowsTargetPlatformVersion(version, mf); + return true; +} + +void cmGlobalVisualStudio14Generator::SetWindowsTargetPlatformVersion( + std::string const& version, cmMakefile* mf) +{ + this->WindowsTargetPlatformVersion = version; if (!cmSystemTools::VersionCompareEqual(this->WindowsTargetPlatformVersion, this->SystemVersion)) { std::ostringstream e; @@ -161,7 +183,6 @@ bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf, } mf->AddDefinition("CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION", this->WindowsTargetPlatformVersion.c_str()); - return true; } bool cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset( @@ -180,17 +201,6 @@ bool cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset( toolset); } -void cmGlobalVisualStudio14Generator::WriteSLNHeader(std::ostream& fout) -{ - // Visual Studio 14 writes .sln format 12.00 - fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; - if (this->ExpressEdition) { - fout << "# Visual Studio Express 14 for Windows Desktop\n"; - } else { - fout << "# Visual Studio 14\n"; - } -} - bool cmGlobalVisualStudio14Generator::IsWindowsDesktopToolsetInstalled() const { const char desktop10Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 9f5bb4e66..6e12d3e2c 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -18,17 +18,14 @@ class cmake; class cmGlobalVisualStudio14Generator : public cmGlobalVisualStudio12Generator { public: - cmGlobalVisualStudio14Generator(cmake* cm, const std::string& name, - const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; - void WriteSLNHeader(std::ostream& fout) override; - - const char* GetToolsVersion() override { return "14.0"; } - protected: + cmGlobalVisualStudio14Generator(cmake* cm, const std::string& name, + std::string const& platformInGeneratorName); + bool InitializeWindows(cmMakefile* mf) override; bool InitializeWindowsStore(cmMakefile* mf) override; bool SelectWindowsStoreToolset(std::string& toolset) const override; @@ -41,9 +38,11 @@ protected: // version of the toolset. virtual std::string GetWindows10SDKMaxVersion() const; - const char* GetIDEVersion() override { return "14.0"; } virtual bool SelectWindows10SDK(cmMakefile* mf, bool required); + void SetWindowsTargetPlatformVersion(std::string const& version, + cmMakefile* mf); + // Used to verify that the Desktop toolset for the current generator is // installed on the machine. bool IsWindowsDesktopToolsetInstalled() const override; @@ -52,5 +51,6 @@ protected: private: class Factory; + friend class Factory; }; #endif diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx deleted file mode 100644 index 23fd2d5b4..000000000 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ /dev/null @@ -1,298 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmGlobalVisualStudio15Generator.h" - -#include "cmAlgorithms.h" -#include "cmDocumentationEntry.h" -#include "cmLocalVisualStudio10Generator.h" -#include "cmMakefile.h" -#include "cmVS141CLFlagTable.h" -#include "cmVS141CSharpFlagTable.h" -#include "cmVS141LinkFlagTable.h" -#include "cmVSSetupHelper.h" - -static const char vs15generatorName[] = "Visual Studio 15 2017"; - -// Map generator name without year to name with year. -static const char* cmVS15GenName(const std::string& name, std::string& genName) -{ - if (strncmp(name.c_str(), vs15generatorName, - sizeof(vs15generatorName) - 6) != 0) { - return 0; - } - const char* p = name.c_str() + sizeof(vs15generatorName) - 6; - if (cmHasLiteralPrefix(p, " 2017")) { - p += 5; - } - genName = std::string(vs15generatorName) + p; - return p; -} - -class cmGlobalVisualStudio15Generator::Factory - : public cmGlobalGeneratorFactory -{ -public: - virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const - { - std::string genName; - const char* p = cmVS15GenName(name, genName); - if (!p) { - return 0; - } - if (!*p) { - return new cmGlobalVisualStudio15Generator(cm, genName, ""); - } - if (*p++ != ' ') { - return 0; - } - if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio15Generator(cm, genName, "x64"); - } - if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio15Generator(cm, genName, "ARM"); - } - return 0; - } - - virtual void GetDocumentation(cmDocumentationEntry& entry) const - { - entry.Name = std::string(vs15generatorName) + " [arch]"; - entry.Brief = "Generates Visual Studio 2017 project files. " - "Optional [arch] can be \"Win64\" or \"ARM\"."; - } - - virtual void GetGenerators(std::vector<std::string>& names) const - { - names.push_back(vs15generatorName); - names.push_back(vs15generatorName + std::string(" ARM")); - names.push_back(vs15generatorName + std::string(" Win64")); - } - - bool SupportsToolset() const override { return true; } - bool SupportsPlatform() const override { return true; } -}; - -cmGlobalGeneratorFactory* cmGlobalVisualStudio15Generator::NewFactory() -{ - return new Factory; -} - -cmGlobalVisualStudio15Generator::cmGlobalVisualStudio15Generator( - cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio14Generator(cm, name, platformName) -{ - this->ExpressEdition = false; - this->DefaultPlatformToolset = "v141"; - this->DefaultClFlagTable = cmVS141CLFlagTable; - this->DefaultCSharpFlagTable = cmVS141CSharpFlagTable; - this->DefaultLinkFlagTable = cmVS141LinkFlagTable; - this->Version = VS15; -} - -bool cmGlobalVisualStudio15Generator::MatchesGeneratorName( - const std::string& name) const -{ - std::string genName; - if (cmVS15GenName(name, genName)) { - return genName == this->GetName(); - } - return false; -} - -void cmGlobalVisualStudio15Generator::WriteSLNHeader(std::ostream& fout) -{ - // Visual Studio 15 writes .sln format 12.00 - fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; - if (this->ExpressEdition) { - fout << "# Visual Studio Express 15 for Windows Desktop\n"; - } else { - fout << "# Visual Studio 15\n"; - } -} - -bool cmGlobalVisualStudio15Generator::SetGeneratorInstance( - std::string const& i, cmMakefile* mf) -{ - if (!i.empty()) { - if (!this->vsSetupAPIHelper.SetVSInstance(i)) { - std::ostringstream e; - /* clang-format off */ - e << - "Generator\n" - " " << this->GetName() << "\n" - "could not find specified instance of Visual Studio:\n" - " " << i; - /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } - } - - std::string vsInstance; - if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { - std::ostringstream e; - /* clang-format off */ - e << - "Generator\n" - " " << this->GetName() << "\n" - "could not find any instance of Visual Studio.\n"; - /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } - - // Save the selected instance persistently. - std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); - if (vsInstance != genInstance) { - this->CMakeInstance->AddCacheEntry( - "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(), - "Generator instance identifier.", cmStateEnums::INTERNAL); - } - - return true; -} - -bool cmGlobalVisualStudio15Generator::GetVSInstance(std::string& dir) const -{ - return vsSetupAPIHelper.GetVSInstanceInfo(dir); -} - -bool cmGlobalVisualStudio15Generator::IsDefaultToolset( - const std::string& version) const -{ - if (version.empty()) { - return true; - } - - std::string vcToolsetVersion; - if (this->vsSetupAPIHelper.GetVCToolsetVersion(vcToolsetVersion)) { - - cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9]+"); - if (regex.find(version) && regex.find(vcToolsetVersion)) { - const auto majorMinorEnd = vcToolsetVersion.find('.', 3); - const auto majorMinor = vcToolsetVersion.substr(0, majorMinorEnd); - return version == majorMinor; - } - } - - return false; -} - -std::string cmGlobalVisualStudio15Generator::GetAuxiliaryToolset() const -{ - const char* version = this->GetPlatformToolsetVersion(); - if (version) { - std::string instancePath; - GetVSInstance(instancePath); - std::stringstream path; - path << instancePath; - path << "/VC/Auxiliary/Build/"; - path << version; - path << "/Microsoft.VCToolsVersion." << version << ".props"; - - std::string toolsetPath = path.str(); - cmSystemTools::ConvertToUnixSlashes(toolsetPath); - return toolsetPath; - } - return {}; -} - -bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf) -{ - // If the Win 8.1 SDK is installed then we can select a SDK matching - // the target Windows version. - if (this->IsWin81SDKInstalled()) { - return cmGlobalVisualStudio14Generator::InitializeWindows(mf); - } - // Otherwise we must choose a Win 10 SDK even if we are not targeting - // Windows 10. - return this->SelectWindows10SDK(mf, false); -} - -bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset( - std::string& toolset) const -{ - if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { - if (this->IsWindowsStoreToolsetInstalled() && - this->IsWindowsDesktopToolsetInstalled()) { - toolset = "v141"; // VS 15 uses v141 toolset - return true; - } else { - return false; - } - } - return this->cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset( - toolset); -} - -bool cmGlobalVisualStudio15Generator::IsWindowsDesktopToolsetInstalled() const -{ - return vsSetupAPIHelper.IsVS2017Installed(); -} - -bool cmGlobalVisualStudio15Generator::IsWindowsStoreToolsetInstalled() const -{ - return vsSetupAPIHelper.IsWin10SDKInstalled(); -} - -bool cmGlobalVisualStudio15Generator::IsWin81SDKInstalled() const -{ - // Does the VS installer tool know about one? - if (vsSetupAPIHelper.IsWin81SDKInstalled()) { - return true; - } - - // Does the registry know about one (e.g. from VS 2015)? - std::string win81Root; - if (cmSystemTools::ReadRegistryValue( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" - "Windows Kits\\Installed Roots;KitsRoot81", - win81Root, cmSystemTools::KeyWOW64_32) || - cmSystemTools::ReadRegistryValue( - "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" - "Windows Kits\\Installed Roots;KitsRoot81", - win81Root, cmSystemTools::KeyWOW64_32)) { - return cmSystemTools::FileExists(win81Root + "/um/windows.h", true); - } - return false; -} - -std::string cmGlobalVisualStudio15Generator::GetWindows10SDKMaxVersion() const -{ - return std::string(); -} - -std::string cmGlobalVisualStudio15Generator::FindMSBuildCommand() -{ - std::string msbuild; - - // Ask Visual Studio Installer tool. - std::string vs; - if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { - msbuild = vs + "/MSBuild/15.0/Bin/MSBuild.exe"; - if (cmSystemTools::FileExists(msbuild)) { - return msbuild; - } - } - - msbuild = "MSBuild.exe"; - return msbuild; -} - -std::string cmGlobalVisualStudio15Generator::FindDevEnvCommand() -{ - std::string devenv; - - // Ask Visual Studio Installer tool. - std::string vs; - if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { - devenv = vs + "/Common7/IDE/devenv.com"; - if (cmSystemTools::FileExists(devenv)) { - return devenv; - } - } - - devenv = "devenv.com"; - return devenv; -} diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index ba12fac96..8e67fad89 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -6,7 +6,7 @@ #include "cmGeneratorTarget.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" -#include "cmake.h" +#include "cmMessageType.h" cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator( cmake* cm, const std::string& platformName) @@ -149,7 +149,7 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends( m += target->GetName(); m += " depends on unknown target: "; m += name; - cmSystemTools::Error(m.c_str()); + cmSystemTools::Error(m); } fout << "\t\t{" << guid << "} = {" << guid << "}\n"; } @@ -159,7 +159,7 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends( // executables to the libraries it uses are also done here void cmGlobalVisualStudio71Generator::WriteExternalProject( std::ostream& fout, const std::string& name, const char* location, - const char* typeGuid, const std::set<std::string>& depends) + const char* typeGuid, const std::set<BT<std::string>>& depends) { fout << "Project(\"{" << (typeGuid ? typeGuid : this->ExternalProjectType(location)) @@ -171,9 +171,10 @@ void cmGlobalVisualStudio71Generator::WriteExternalProject( // project instead of in the global section if (!depends.empty()) { fout << "\tProjectSection(ProjectDependencies) = postProject\n"; - for (std::string const& it : depends) { - if (!it.empty()) { - fout << "\t\t{" << this->GetGUID(it) << "} = {" << this->GetGUID(it) + for (BT<std::string> const& it : depends) { + std::string const& dep = it.Value; + if (!dep.empty()) { + fout << "\t\t{" << this->GetGUID(dep) << "} = {" << this->GetGUID(dep) << "}\n"; } } @@ -216,9 +217,3 @@ void cmGlobalVisualStudio71Generator::WriteProjectConfigurations( } } } - -// output standard header for dsw file -void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout) -{ - fout << "Microsoft Visual Studio Solution File, Format Version 8.00\n"; -} diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index 054c3421d..85755af60 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -33,11 +33,10 @@ protected: const std::string& platformMapping = "") override; void WriteExternalProject(std::ostream& fout, const std::string& name, const char* path, const char* typeGuid, - const std::set<std::string>& depends) override; - void WriteSLNHeader(std::ostream& fout) override; + const std::set<BT<std::string>>& depends) override; // Folders are not supported by VS 7.1. - virtual bool UseFolderProperty() { return false; } + bool UseFolderProperty() const override { return false; } std::string ProjectConfigurationSectionName; }; diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 21121f2bb..d457f60d1 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -6,6 +6,7 @@ #include "cmGeneratorTarget.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmUuid.h" #include "cmake.h" @@ -37,23 +38,17 @@ static cmVS7FlagTable cmVS7ExtraFlagTable[] = { // and have EHa passed on the command line by leaving out the table // entry. - { 0, 0, 0, 0, 0 } + { "", "", "", "", 0 } }; cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator( - cmake* cm, const std::string& platformName) - : cmGlobalVisualStudioGenerator(cm) + cmake* cm, std::string const& platformInGeneratorName) + : cmGlobalVisualStudioGenerator(cm, platformInGeneratorName) { this->IntelProjectVersion = 0; this->DevEnvCommandInitialized = false; this->MasmEnabled = false; this->NasmEnabled = false; - - if (platformName.empty()) { - this->DefaultPlatformName = "Win32"; - } else { - this->DefaultPlatformName = platformName; - } this->ExtraFlagTable = cmVS7ExtraFlagTable; } @@ -196,7 +191,7 @@ const char* cmGlobalVisualStudio7Generator::ExternalProjectType( return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"; } void cmGlobalVisualStudio7Generator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& /*projectDir*/, const std::string& targetName, const std::string& config, bool /*fast*/, int /*jobs*/, bool /*verbose*/, std::vector<std::string> const& makeOptions) @@ -214,35 +209,25 @@ void cmGlobalVisualStudio7Generator::GenerateBuildCommand( makeProgramSelected = this->GetDevEnvCommand(); } - makeCommand.push_back(makeProgramSelected); + // Workaround to convince VCExpress.exe to produce output. + makeCommand.RequiresOutputForward = + (makeProgramLower.find("vcexpress") != std::string::npos); - makeCommand.push_back(std::string(projectName) + ".sln"); + makeCommand.add(makeProgramSelected); + + makeCommand.add(std::string(projectName) + ".sln"); std::string realTarget = targetName; bool clean = false; if (realTarget == "clean") { clean = true; realTarget = "ALL_BUILD"; } - if (clean) { - makeCommand.push_back("/clean"); - } else { - makeCommand.push_back("/build"); - } - - if (!config.empty()) { - makeCommand.push_back(config); - } else { - makeCommand.push_back("Debug"); - } - makeCommand.push_back("/project"); - if (!realTarget.empty()) { - makeCommand.push_back(realTarget); - } else { - makeCommand.push_back("ALL_BUILD"); - } - makeCommand.insert(makeCommand.end(), makeOptions.begin(), - makeOptions.end()); + makeCommand.add((clean ? "/clean" : "/build")); + makeCommand.add((config.empty() ? "Debug" : config)); + makeCommand.add("/project"); + makeCommand.add((realTarget.empty() ? "ALL_BUILD" : realTarget)); + makeCommand.add(makeOptions.begin(), makeOptions.end()); } ///! Create a local generator appropriate to this Global Generator @@ -254,13 +239,14 @@ cmLocalGenerator* cmGlobalVisualStudio7Generator::CreateLocalGenerator( return lg; } -std::string const& cmGlobalVisualStudio7Generator::GetPlatformName() const +#if defined(CMAKE_BUILD_WITH_CMAKE) +Json::Value cmGlobalVisualStudio7Generator::GetJson() const { - if (!this->GeneratorPlatform.empty()) { - return this->GeneratorPlatform; - } - return this->DefaultPlatformName; + Json::Value generator = this->cmGlobalVisualStudioGenerator::GetJson(); + generator["platform"] = this->GetPlatformName(); + return generator; } +#endif bool cmGlobalVisualStudio7Generator::SetSystemName(std::string const& s, cmMakefile* mf) @@ -270,18 +256,6 @@ bool cmGlobalVisualStudio7Generator::SetSystemName(std::string const& s, return this->cmGlobalVisualStudioGenerator::SetSystemName(s, mf); } -bool cmGlobalVisualStudio7Generator::SetGeneratorPlatform(std::string const& p, - cmMakefile* mf) -{ - if (this->GetPlatformName() == "x64") { - mf->AddDefinition("CMAKE_FORCE_WIN64", "TRUE"); - } else if (this->GetPlatformName() == "Itanium") { - mf->AddDefinition("CMAKE_FORCE_IA64", "TRUE"); - } - mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName().c_str()); - return this->cmGlobalVisualStudioGenerator::SetGeneratorPlatform(p, mf); -} - void cmGlobalVisualStudio7Generator::Generate() { // first do the superclass method @@ -383,7 +357,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( if (vcprojName) { cmLocalGenerator* lg = target->GetLocalGenerator(); std::string dir = lg->GetCurrentBinaryDirectory(); - dir = root->ConvertToRelativePath(rootBinaryDir, dir.c_str()); + dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir.c_str()); if (dir == ".") { dir.clear(); // msbuild cannot handle ".\" prefix } diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 0c9dd889b..3f1c1732d 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -18,19 +18,16 @@ struct cmIDEFlagTable; class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator { public: - cmGlobalVisualStudio7Generator(cmake* cm, - const std::string& platformName = ""); ~cmGlobalVisualStudio7Generator(); - ///! Get the name for the platform. - std::string const& GetPlatformName() const; - ///! Create a local generator appropriate to this Global Generator cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; - bool SetSystemName(std::string const& s, cmMakefile* mf) override; +#if defined(CMAKE_BUILD_WITH_CMAKE) + Json::Value GetJson() const override; +#endif - bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; + bool SetSystemName(std::string const& s, cmMakefile* mf) override; /** * Utilized by the generator factory to determine if this generator @@ -55,7 +52,7 @@ public: * Try running cmake and building a file. This is used for dynamically * loaded commands, not as part of the usual build process. */ - void GenerateBuildCommand(std::vector<std::string>& makeCommand, + void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, @@ -106,8 +103,10 @@ public: cmIDEFlagTable const* ExtraFlagTable; protected: + cmGlobalVisualStudio7Generator(cmake* cm, + std::string const& platformInGeneratorName); + void Generate() override; - virtual const char* GetIDEVersion() = 0; std::string const& GetDevEnvCommand(); virtual std::string FindDevEnvCommand(); @@ -131,7 +130,6 @@ protected: virtual void WriteSLNGlobalSections(std::ostream& fout, cmLocalGenerator* root); virtual void WriteSLNFooter(std::ostream& fout); - virtual void WriteSLNHeader(std::ostream& fout) = 0; std::string WriteUtilityDepend(const cmGeneratorTarget* target) override; virtual void WriteTargetsToSolution( @@ -145,7 +143,7 @@ protected: virtual void WriteExternalProject( std::ostream& fout, const std::string& name, const char* path, - const char* typeGuid, const std::set<std::string>& dependencies) = 0; + const char* typeGuid, const std::set<BT<std::string>>& dependencies) = 0; std::string ConvertToSolutionPath(const char* path); @@ -164,8 +162,6 @@ protected: // Set during OutputSLNFile with the name of the current project. // There is one SLN file per project. std::string CurrentProject; - std::string GeneratorPlatform; - std::string DefaultPlatformName; bool MasmEnabled; bool NasmEnabled; diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index ba138c22e..f6db018ea 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -7,13 +7,15 @@ #include "cmGeneratorTarget.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmVisualStudioWCEPlatformParser.h" #include "cmake.h" cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator( - cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio71Generator(cm, platformName) + cmake* cm, const std::string& name, + std::string const& platformInGeneratorName) + : cmGlobalVisualStudio71Generator(cm, platformInGeneratorName) { this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms"; this->Name = name; @@ -60,7 +62,7 @@ void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf) bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p, cmMakefile* mf) { - if (this->DefaultPlatformName == "Win32") { + if (!this->PlatformInGeneratorName) { this->GeneratorPlatform = p; return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf); } else { @@ -78,7 +80,7 @@ void cmGlobalVisualStudio8Generator::Configure() this->cmGlobalVisualStudio7Generator::Configure(); } -bool cmGlobalVisualStudio8Generator::UseFolderProperty() +bool cmGlobalVisualStudio8Generator::UseFolderProperty() const { return IsExpressEdition() ? false : cmGlobalGenerator::UseFolderProperty(); } @@ -115,7 +117,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // Create a list of all stamp files for this project. std::vector<std::string> stamps; - std::string stampList = cmake::GetCMakeFilesDirectoryPostSlash(); + std::string stampList = "CMakeFiles/"; stampList += cmGlobalVisualStudio8Generator::GetGenerateStampList(); { std::string stampListFile = @@ -127,7 +129,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() for (cmLocalGenerator const* gi : generators) { stampFile = gi->GetMakefile()->GetCurrentBinaryDirectory(); stampFile += "/"; - stampFile += cmake::GetCMakeFilesDirectoryPostSlash(); + stampFile += "CMakeFiles/"; stampFile += "generate.stamp"; fout << stampFile << "\n"; stamps.push_back(stampFile); @@ -315,9 +317,9 @@ bool cmGlobalVisualStudio8Generator::NeedLinkLibraryDependencies( cmGeneratorTarget* target) { // Look for utility dependencies that magically link. - for (std::string const& ui : target->GetUtilities()) { + for (BT<std::string> const& ui : target->GetUtilities()) { if (cmGeneratorTarget* depTarget = - target->GetLocalGenerator()->FindGeneratorTargetToUse(ui)) { + target->GetLocalGenerator()->FindGeneratorTargetToUse(ui.Value)) { if (depTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY && depTarget->GetProperty("EXTERNAL_MSPROJECT")) { // This utility dependency names an external .vcproj target. @@ -362,7 +364,7 @@ static cmVS7FlagTable cmVS8ExtraFlagTable[] = { { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "wchar_t is not a built-in type", "false", 0 }, - { 0, 0, 0, 0, 0 } + { "", "", "", "", 0 } }; cmIDEFlagTable const* cmGlobalVisualStudio8Generator::GetExtraFlagTableVS8() { diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index 6f64b9c66..8719bf3bb 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -13,9 +13,6 @@ class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator { public: - cmGlobalVisualStudio8Generator(cmake* cm, const std::string& name, - const std::string& platformName); - ///! Get the name for the generator. std::string GetName() const override { return this->Name; } @@ -44,12 +41,11 @@ public: return !this->WindowsCEVersion.empty(); } - /** Is the installed VS an Express edition? */ - bool IsExpressEdition() const { return this->ExpressEdition; } - protected: + cmGlobalVisualStudio8Generator(cmake* cm, const std::string& name, + std::string const& platformInGeneratorName); + void AddExtraIDETargets() override; - const char* GetIDEVersion() override { return "8.0"; } std::string FindDevEnvCommand() override; @@ -73,10 +69,9 @@ protected: const char* path, const cmGeneratorTarget* t) override; - bool UseFolderProperty(); + bool UseFolderProperty() const override; std::string Name; std::string WindowsCEVersion; - bool ExpressEdition; }; #endif diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index 7ac3a6f09..6e61d2681 100644 --- a/Source/cmGlobalVisualStudio9Generator.cxx +++ b/Source/cmGlobalVisualStudio9Generator.cxx @@ -5,8 +5,8 @@ #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmVisualStudioWCEPlatformParser.h" -#include "cmake.h" static const char vs9generatorName[] = "Visual Studio 9 2008"; @@ -59,9 +59,16 @@ public: "Optional [arch] can be \"Win64\" or \"IA64\"."; } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(vs9generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; names.push_back(vs9generatorName + std::string(" Win64")); names.push_back(vs9generatorName + std::string(" IA64")); cmVisualStudioWCEPlatformParser parser; @@ -71,10 +78,29 @@ public: for (std::string const& i : availablePlatforms) { names.push_back("Visual Studio 9 2008 " + i); } + return names; } bool SupportsToolset() const override { return false; } bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("Itanium"); + cmVisualStudioWCEPlatformParser parser; + parser.ParseVersion("9.0"); + const std::vector<std::string>& availablePlatforms = + parser.GetAvailablePlatforms(); + for (std::string const& i : availablePlatforms) { + platforms.emplace_back(i); + } + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } }; cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory() @@ -83,8 +109,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory() } cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator( - cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio8Generator(cm, name, platformName) + cmake* cm, const std::string& name, + std::string const& platformInGeneratorName) + : cmGlobalVisualStudio8Generator(cm, name, platformInGeneratorName) { this->Version = VS9; std::string vc9Express; @@ -94,12 +121,6 @@ cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator( vc9Express, cmSystemTools::KeyWOW64_32); } -void cmGlobalVisualStudio9Generator::WriteSLNHeader(std::ostream& fout) -{ - fout << "Microsoft Visual Studio Solution File, Format Version 10.00\n"; - fout << "# Visual Studio 2008\n"; -} - std::string cmGlobalVisualStudio9Generator::GetUserMacrosDirectory() { std::string base; diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h index 2aa6a91ee..7bebfd65f 100644 --- a/Source/cmGlobalVisualStudio9Generator.h +++ b/Source/cmGlobalVisualStudio9Generator.h @@ -13,17 +13,9 @@ class cmGlobalVisualStudio9Generator : public cmGlobalVisualStudio8Generator { public: - cmGlobalVisualStudio9Generator(cmake* cm, const std::string& name, - const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); /** - * Try to determine system information such as shared library - * extension, pthreads, byte order etc. - */ - void WriteSLNHeader(std::ostream& fout) override; - - /** * Where does this version of Visual Studio look for macros for the * current user? Returns the empty string if this version of Visual * Studio does not implement support for VB macros. @@ -37,7 +29,8 @@ public: std::string GetUserMacrosRegKeyBase() override; protected: - const char* GetIDEVersion() override { return "9.0"; } + cmGlobalVisualStudio9Generator(cmake* cm, const std::string& name, + std::string const& platformInGeneratorName); private: class Factory; diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index da3daf86b..639dc226d 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -19,13 +19,22 @@ #include "cmSourceFile.h" #include "cmState.h" #include "cmTarget.h" +#include "cmake.h" -cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm) +cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator( + cmake* cm, std::string const& platformInGeneratorName) : cmGlobalGenerator(cm) { cm->GetState()->SetIsGeneratorMultiConfig(true); cm->GetState()->SetWindowsShell(true); cm->GetState()->SetWindowsVSIDE(true); + + if (platformInGeneratorName.empty()) { + this->DefaultPlatformName = "Win32"; + } else { + this->DefaultPlatformName = platformInGeneratorName; + this->PlatformInGeneratorName = true; + } } cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator() @@ -43,6 +52,108 @@ void cmGlobalVisualStudioGenerator::SetVersion(VSVersion v) this->Version = v; } +bool cmGlobalVisualStudioGenerator::SetGeneratorPlatform(std::string const& p, + cmMakefile* mf) +{ + if (this->GetPlatformName() == "x64") { + mf->AddDefinition("CMAKE_FORCE_WIN64", "TRUE"); + } else if (this->GetPlatformName() == "Itanium") { + mf->AddDefinition("CMAKE_FORCE_IA64", "TRUE"); + } + mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName().c_str()); + return this->cmGlobalGenerator::SetGeneratorPlatform(p, mf); +} + +std::string const& cmGlobalVisualStudioGenerator::GetPlatformName() const +{ + if (!this->GeneratorPlatform.empty()) { + return this->GeneratorPlatform; + } + return this->DefaultPlatformName; +} + +const char* cmGlobalVisualStudioGenerator::GetIDEVersion() const +{ + switch (this->Version) { + case cmGlobalVisualStudioGenerator::VS9: + return "9.0"; + case cmGlobalVisualStudioGenerator::VS10: + return "10.0"; + case cmGlobalVisualStudioGenerator::VS11: + return "11.0"; + case cmGlobalVisualStudioGenerator::VS12: + return "12.0"; + case cmGlobalVisualStudioGenerator::VS14: + return "14.0"; + case cmGlobalVisualStudioGenerator::VS15: + return "15.0"; + case cmGlobalVisualStudioGenerator::VS16: + return "16.0"; + } + return ""; +} + +void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout) +{ + switch (this->Version) { + case cmGlobalVisualStudioGenerator::VS9: + fout << "Microsoft Visual Studio Solution File, Format Version 10.00\n"; + fout << "# Visual Studio 2008\n"; + break; + case cmGlobalVisualStudioGenerator::VS10: + fout << "Microsoft Visual Studio Solution File, Format Version 11.00\n"; + if (this->ExpressEdition) { + fout << "# Visual C++ Express 2010\n"; + } else { + fout << "# Visual Studio 2010\n"; + } + break; + case cmGlobalVisualStudioGenerator::VS11: + fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; + if (this->ExpressEdition) { + fout << "# Visual Studio Express 2012 for Windows Desktop\n"; + } else { + fout << "# Visual Studio 2012\n"; + } + break; + case cmGlobalVisualStudioGenerator::VS12: + fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; + if (this->ExpressEdition) { + fout << "# Visual Studio Express 2013 for Windows Desktop\n"; + } else { + fout << "# Visual Studio 2013\n"; + } + break; + case cmGlobalVisualStudioGenerator::VS14: + // Visual Studio 14 writes .sln format 12.00 + fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; + if (this->ExpressEdition) { + fout << "# Visual Studio Express 14 for Windows Desktop\n"; + } else { + fout << "# Visual Studio 14\n"; + } + break; + case cmGlobalVisualStudioGenerator::VS15: + // Visual Studio 15 writes .sln format 12.00 + fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; + if (this->ExpressEdition) { + fout << "# Visual Studio Express 15 for Windows Desktop\n"; + } else { + fout << "# Visual Studio 15\n"; + } + break; + case cmGlobalVisualStudioGenerator::VS16: + // Visual Studio 16 writes .sln format 12.00 + fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; + if (this->ExpressEdition) { + fout << "# Visual Studio Express 16 for Windows Desktop\n"; + } else { + fout << "# Visual Studio 16\n"; + } + break; + } +} + std::string cmGlobalVisualStudioGenerator::GetRegistryBase() { return cmGlobalVisualStudioGenerator::GetRegistryBase(this->GetIDEVersion()); @@ -90,7 +201,7 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets() tgt->IsImported()) { continue; } - if (!this->IsExcluded(gen[0], tgt)) { + if (!this->IsExcluded(tgt)) { allBuild->AddUtility(tgt->GetName()); } } @@ -151,13 +262,12 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros() // purposes but newer versions distributed with CMake will replace // older versions in user directories. int res; - if (!cmSystemTools::FileTimeCompare(src.c_str(), dst.c_str(), &res) || - res > 0) { - if (!cmSystemTools::CopyFileAlways(src.c_str(), dst.c_str())) { + if (!cmSystemTools::FileTimeCompare(src, dst, &res) || res > 0) { + if (!cmSystemTools::CopyFileAlways(src, dst)) { std::ostringstream oss; oss << "Could not copy from: " << src << std::endl; oss << " to: " << dst << std::endl; - cmSystemTools::Message(oss.str().c_str(), "Warning"); + cmSystemTools::Message(oss.str(), "Warning"); } } @@ -413,7 +523,7 @@ std::string cmGlobalVisualStudioGenerator::GetStartupProjectName( return startup; } else { root->GetMakefile()->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, "Directory property VS_STARTUP_PROJECT specifies target " "'" + startup + "' that does not exist. Ignoring."); @@ -672,7 +782,7 @@ void RegisterVisualStudioMacros(const std::string& macrosFile, << "CMake needs to register Visual Studio macros when its macros" << " file is updated or when it detects that its current macros file" << " is no longer registered with Visual Studio." << std::endl; - cmSystemTools::Message(oss.str().c_str(), "Warning"); + cmSystemTools::Message(oss.str(), "Warning"); // Count them again now that the warning is over. In the case of a GUI // warning, the user may have gone to close Visual Studio and then come @@ -703,7 +813,6 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly( cmGeneratorTarget const* gt) { // check to see if this is a fortran build - std::set<std::string> languages; { // Issue diagnostic if the source files depend on the config. std::vector<cmSourceFile*> sources; @@ -711,27 +820,25 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly( return false; } } + // If there's only one source language, Fortran has to be used // in order for the sources to compile. - // Note: Via linker propagation, LINKER_LANGUAGE could become CXX in - // this situation and mismatch from the actual language of the linker. + std::set<std::string> languages; gt->GetLanguages(languages, ""); - if (languages.size() == 1) { - if (*languages.begin() == "Fortran") { - return true; - } + // Consider an explicit linker language property, but *not* the + // computed linker language that may depend on linked targets. + // This allows the project to control the language choice in + // a target with none of its own sources, e.g. when also using + // object libraries. + const char* linkLang = gt->GetProperty("LINKER_LANGUAGE"); + if (linkLang && *linkLang) { + languages.insert(linkLang); } - // In the case of mixed object files or sources mixed with objects, - // decide the language based on the value of LINKER_LANGUAGE. - // This will not make it possible to mix source files of different - // languages, but object libraries will be linked together in the - // same fashion as other generators do. - if (gt->GetLinkerLanguage("") == "Fortran") { - return true; - } + // Intel Fortran .vfproj files do support the resource compiler. + languages.erase("RC"); - return false; + return languages.size() == 1 && *languages.begin() == "Fortran"; } bool cmGlobalVisualStudioGenerator::TargetCompare::operator()( diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 07bc9a393..039191c6c 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -38,15 +38,26 @@ public: VS12 = 120, /* VS13 = 130 was skipped */ VS14 = 140, - VS15 = 150 + VS15 = 150, + VS16 = 160 }; - cmGlobalVisualStudioGenerator(cmake* cm); virtual ~cmGlobalVisualStudioGenerator(); VSVersion GetVersion() const; void SetVersion(VSVersion v); + /** Is the installed VS an Express edition? */ + bool IsExpressEdition() const { return this->ExpressEdition; } + + bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; + + /** + * Get the name of the target platform (architecture) for which we generate. + * The names are as defined by VS, e.g. "Win32", "x64", "Itanium", "ARM". + */ + std::string const& GetPlatformName() const; + /** * Configure CMake's Visual Studio macros file into the user's Visual * Studio macros directory. @@ -118,7 +129,7 @@ public: std::string ExpandCFGIntDir(const std::string& str, const std::string& config) const override; - void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; + void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; std::string GetStartupProjectName(cmLocalGenerator const* root) const; @@ -130,6 +141,9 @@ public: bool dryRun) override; protected: + cmGlobalVisualStudioGenerator(cmake* cm, + std::string const& platformInGeneratorName); + void AddExtraIDETargets() override; // Does this VS version link targets to each other if there are @@ -137,7 +151,9 @@ protected: // below 8. virtual bool VSLinksDependencies() const { return true; } - virtual const char* GetIDEVersion() = 0; + const char* GetIDEVersion() const; + + void WriteSLNHeader(std::ostream& fout); bool ComputeTargetDepends() override; class VSDependSet : public std::set<std::string> @@ -159,11 +175,16 @@ protected: protected: VSVersion Version; + bool ExpressEdition; + + std::string GeneratorPlatform; + std::string DefaultPlatformName; + bool PlatformInGeneratorName = false; private: virtual std::string GetVSMakeProgram() = 0; void PrintCompilerAdvice(std::ostream&, std::string const&, - const char*) const + const char*) const override { } diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx new file mode 100644 index 000000000..f52abd0dc --- /dev/null +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -0,0 +1,515 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmGlobalVisualStudioVersionedGenerator.h" + +#include "cmAlgorithms.h" +#include "cmDocumentationEntry.h" +#include "cmLocalVisualStudio10Generator.h" +#include "cmMakefile.h" +#include "cmVSSetupHelper.h" +#include "cmake.h" + +#if defined(_M_ARM64) +# define HOST_PLATFORM_NAME "ARM64" +# define HOST_TOOLS_ARCH "" +#elif defined(_M_ARM) +# define HOST_PLATFORM_NAME "ARM" +# define HOST_TOOLS_ARCH "" +#elif defined(_M_IA64) +# define HOST_PLATFORM_NAME "Itanium" +# define HOST_TOOLS_ARCH "" +#elif defined(_WIN64) +# define HOST_PLATFORM_NAME "x64" +# define HOST_TOOLS_ARCH "x64" +#else +static bool VSIsWow64() +{ + BOOL isWow64 = false; + return IsWow64Process(GetCurrentProcess(), &isWow64) && isWow64; +} +#endif + +static std::string VSHostPlatformName() +{ +#ifdef HOST_PLATFORM_NAME + return HOST_PLATFORM_NAME; +#else + if (VSIsWow64()) { + return "x64"; + } else { + return "Win32"; + } +#endif +} + +static std::string VSHostArchitecture() +{ +#ifdef HOST_TOOLS_ARCH + return HOST_TOOLS_ARCH; +#else + if (VSIsWow64()) { + return "x64"; + } else { + return "x86"; + } +#endif +} + +static unsigned int VSVersionToMajor( + cmGlobalVisualStudioGenerator::VSVersion v) +{ + switch (v) { + case cmGlobalVisualStudioGenerator::VS9: + return 9; + case cmGlobalVisualStudioGenerator::VS10: + return 10; + case cmGlobalVisualStudioGenerator::VS11: + return 11; + case cmGlobalVisualStudioGenerator::VS12: + return 12; + case cmGlobalVisualStudioGenerator::VS14: + return 14; + case cmGlobalVisualStudioGenerator::VS15: + return 15; + case cmGlobalVisualStudioGenerator::VS16: + return 16; + } + return 0; +} + +static const char* VSVersionToToolset( + cmGlobalVisualStudioGenerator::VSVersion v) +{ + switch (v) { + case cmGlobalVisualStudioGenerator::VS9: + return "v90"; + case cmGlobalVisualStudioGenerator::VS10: + return "v100"; + case cmGlobalVisualStudioGenerator::VS11: + return "v110"; + case cmGlobalVisualStudioGenerator::VS12: + return "v120"; + case cmGlobalVisualStudioGenerator::VS14: + return "v140"; + case cmGlobalVisualStudioGenerator::VS15: + return "v141"; + case cmGlobalVisualStudioGenerator::VS16: + return "v142"; + } + return ""; +} + +static const char vs15generatorName[] = "Visual Studio 15 2017"; + +// Map generator name without year to name with year. +static const char* cmVS15GenName(const std::string& name, std::string& genName) +{ + if (strncmp(name.c_str(), vs15generatorName, + sizeof(vs15generatorName) - 6) != 0) { + return 0; + } + const char* p = name.c_str() + sizeof(vs15generatorName) - 6; + if (cmHasLiteralPrefix(p, " 2017")) { + p += 5; + } + genName = std::string(vs15generatorName) + p; + return p; +} + +class cmGlobalVisualStudioVersionedGenerator::Factory15 + : public cmGlobalGeneratorFactory +{ +public: + cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, + cmake* cm) const override + { + std::string genName; + const char* p = cmVS15GenName(name, genName); + if (!p) { + return 0; + } + if (!*p) { + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, ""); + } + if (*p++ != ' ') { + return 0; + } + if (strcmp(p, "Win64") == 0) { + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "x64"); + } + if (strcmp(p, "ARM") == 0) { + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "ARM"); + } + return 0; + } + + void GetDocumentation(cmDocumentationEntry& entry) const override + { + entry.Name = std::string(vs15generatorName) + " [arch]"; + entry.Brief = "Generates Visual Studio 2017 project files. " + "Optional [arch] can be \"Win64\" or \"ARM\"."; + } + + std::vector<std::string> GetGeneratorNames() const override + { + std::vector<std::string> names; + names.push_back(vs15generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + std::vector<std::string> names; + names.push_back(vs15generatorName + std::string(" ARM")); + names.push_back(vs15generatorName + std::string(" Win64")); + return names; + } + + bool SupportsToolset() const override { return true; } + bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + platforms.emplace_back("ARM64"); + return platforms; + } + + std::string GetDefaultPlatformName() const override { return "Win32"; } +}; + +cmGlobalGeneratorFactory* +cmGlobalVisualStudioVersionedGenerator::NewFactory15() +{ + return new Factory15; +} + +static const char vs16generatorName[] = "Visual Studio 16 2019"; + +// Map generator name without year to name with year. +static const char* cmVS16GenName(const std::string& name, std::string& genName) +{ + if (strncmp(name.c_str(), vs16generatorName, + sizeof(vs16generatorName) - 6) != 0) { + return 0; + } + const char* p = name.c_str() + sizeof(vs16generatorName) - 6; + if (cmHasLiteralPrefix(p, " 2019")) { + p += 5; + } + genName = std::string(vs16generatorName) + p; + return p; +} + +class cmGlobalVisualStudioVersionedGenerator::Factory16 + : public cmGlobalGeneratorFactory +{ +public: + virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, + cmake* cm) const + { + std::string genName; + const char* p = cmVS16GenName(name, genName); + if (!p) { + return 0; + } + if (!*p) { + return new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS16, cm, genName, ""); + } + return 0; + } + + virtual void GetDocumentation(cmDocumentationEntry& entry) const + { + entry.Name = std::string(vs16generatorName); + entry.Brief = "Generates Visual Studio 2019 project files. " + "Use -A option to specify architecture."; + } + + std::vector<std::string> GetGeneratorNames() const override + { + std::vector<std::string> names; + names.push_back(vs16generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + return std::vector<std::string>(); + } + + bool SupportsToolset() const override { return true; } + bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + platforms.emplace_back("ARM64"); + return platforms; + } + + std::string GetDefaultPlatformName() const override + { + return VSHostPlatformName(); + } +}; + +cmGlobalGeneratorFactory* +cmGlobalVisualStudioVersionedGenerator::NewFactory16() +{ + return new Factory16; +} + +cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator( + VSVersion version, cmake* cm, const std::string& name, + std::string const& platformInGeneratorName) + : cmGlobalVisualStudio14Generator(cm, name, platformInGeneratorName) + , vsSetupAPIHelper(VSVersionToMajor(version)) +{ + this->Version = version; + this->ExpressEdition = false; + this->DefaultPlatformToolset = VSVersionToToolset(this->Version); + this->DefaultCLFlagTableName = VSVersionToToolset(this->Version); + this->DefaultCSharpFlagTableName = VSVersionToToolset(this->Version); + this->DefaultLinkFlagTableName = VSVersionToToolset(this->Version); + if (this->Version >= cmGlobalVisualStudioGenerator::VS16) { + this->DefaultPlatformName = VSHostPlatformName(); + this->DefaultPlatformToolsetHostArchitecture = VSHostArchitecture(); + } +} + +bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( + const std::string& name) const +{ + std::string genName; + switch (this->Version) { + case cmGlobalVisualStudioGenerator::VS9: + case cmGlobalVisualStudioGenerator::VS10: + case cmGlobalVisualStudioGenerator::VS11: + case cmGlobalVisualStudioGenerator::VS12: + case cmGlobalVisualStudioGenerator::VS14: + break; + case cmGlobalVisualStudioGenerator::VS15: + if (cmVS15GenName(name, genName)) { + return genName == this->GetName(); + } + break; + case cmGlobalVisualStudioGenerator::VS16: + if (cmVS16GenName(name, genName)) { + return genName == this->GetName(); + } + break; + } + return false; +} + +bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( + std::string const& i, cmMakefile* mf) +{ + if (!i.empty()) { + if (!this->vsSetupAPIHelper.SetVSInstance(i)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "could not find specified instance of Visual Studio:\n" + " " << i; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + } + + std::string vsInstance; + if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "could not find any instance of Visual Studio.\n"; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return false; + } + + // Save the selected instance persistently. + std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); + if (vsInstance != genInstance) { + this->CMakeInstance->AddCacheEntry( + "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(), + "Generator instance identifier.", cmStateEnums::INTERNAL); + } + + return true; +} + +bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance( + std::string& dir) const +{ + return vsSetupAPIHelper.GetVSInstanceInfo(dir); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsDefaultToolset( + const std::string& version) const +{ + if (version.empty()) { + return true; + } + + std::string vcToolsetVersion; + if (this->vsSetupAPIHelper.GetVCToolsetVersion(vcToolsetVersion)) { + + cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9]+"); + if (regex.find(version) && regex.find(vcToolsetVersion)) { + const auto majorMinorEnd = vcToolsetVersion.find('.', 3); + const auto majorMinor = vcToolsetVersion.substr(0, majorMinorEnd); + return version == majorMinor; + } + } + + return false; +} + +std::string cmGlobalVisualStudioVersionedGenerator::GetAuxiliaryToolset() const +{ + const char* version = this->GetPlatformToolsetVersion(); + if (version) { + std::string instancePath; + GetVSInstance(instancePath); + std::stringstream path; + path << instancePath; + path << "/VC/Auxiliary/Build/"; + path << version; + path << "/Microsoft.VCToolsVersion." << version << ".props"; + + std::string toolsetPath = path.str(); + cmSystemTools::ConvertToUnixSlashes(toolsetPath); + return toolsetPath; + } + return {}; +} + +bool cmGlobalVisualStudioVersionedGenerator::InitializeWindows(cmMakefile* mf) +{ + // If the Win 8.1 SDK is installed then we can select a SDK matching + // the target Windows version. + if (this->IsWin81SDKInstalled()) { + // VS 2019 does not default to 8.1 so specify it explicitly when needed. + if (this->Version >= cmGlobalVisualStudioGenerator::VS16 && + !cmSystemTools::VersionCompareGreater(this->SystemVersion, "8.1")) { + this->SetWindowsTargetPlatformVersion("8.1", mf); + return true; + } + return cmGlobalVisualStudio14Generator::InitializeWindows(mf); + } + // Otherwise we must choose a Win 10 SDK even if we are not targeting + // Windows 10. + return this->SelectWindows10SDK(mf, false); +} + +bool cmGlobalVisualStudioVersionedGenerator::SelectWindowsStoreToolset( + std::string& toolset) const +{ + if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) { + if (this->IsWindowsStoreToolsetInstalled() && + this->IsWindowsDesktopToolsetInstalled()) { + toolset = VSVersionToToolset(this->Version); + return true; + } else { + return false; + } + } + return this->cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset( + toolset); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsWindowsDesktopToolsetInstalled() + const +{ + return vsSetupAPIHelper.IsVSInstalled(); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsWindowsStoreToolsetInstalled() + const +{ + return vsSetupAPIHelper.IsWin10SDKInstalled(); +} + +bool cmGlobalVisualStudioVersionedGenerator::IsWin81SDKInstalled() const +{ + // Does the VS installer tool know about one? + if (vsSetupAPIHelper.IsWin81SDKInstalled()) { + return true; + } + + // Does the registry know about one (e.g. from VS 2015)? + std::string win81Root; + if (cmSystemTools::ReadRegistryValue( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot81", + win81Root, cmSystemTools::KeyWOW64_32) || + cmSystemTools::ReadRegistryValue( + "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot81", + win81Root, cmSystemTools::KeyWOW64_32)) { + return cmSystemTools::FileExists(win81Root + "/include/um/windows.h", + true); + } + return false; +} + +std::string cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersion() + const +{ + return std::string(); +} + +std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand() +{ + std::string msbuild; + + // Ask Visual Studio Installer tool. + std::string vs; + if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + msbuild = vs + "/MSBuild/Current/Bin/MSBuild.exe"; + if (cmSystemTools::FileExists(msbuild)) { + return msbuild; + } + msbuild = vs + "/MSBuild/15.0/Bin/MSBuild.exe"; + if (cmSystemTools::FileExists(msbuild)) { + return msbuild; + } + } + + msbuild = "MSBuild.exe"; + return msbuild; +} + +std::string cmGlobalVisualStudioVersionedGenerator::FindDevEnvCommand() +{ + std::string devenv; + + // Ask Visual Studio Installer tool. + std::string vs; + if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + devenv = vs + "/Common7/IDE/devenv.com"; + if (cmSystemTools::FileExists(devenv)) { + return devenv; + } + } + + devenv = "devenv.com"; + return devenv; +} diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index 8ab63f141..466816ba8 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -1,7 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmGlobalVisualStudio15Generator_h -#define cmGlobalVisualStudio15Generator_h +#ifndef cmGlobalVisualStudioVersionedGenerator_h +#define cmGlobalVisualStudioVersionedGenerator_h #include "cmConfigure.h" // IWYU pragma: keep @@ -14,20 +14,16 @@ class cmGlobalGeneratorFactory; class cmake; -/** \class cmGlobalVisualStudio15Generator */ -class cmGlobalVisualStudio15Generator : public cmGlobalVisualStudio14Generator +/** \class cmGlobalVisualStudioVersionedGenerator */ +class cmGlobalVisualStudioVersionedGenerator + : public cmGlobalVisualStudio14Generator { public: - cmGlobalVisualStudio15Generator(cmake* cm, const std::string& name, - const std::string& platformName); - static cmGlobalGeneratorFactory* NewFactory(); + static cmGlobalGeneratorFactory* NewFactory15(); + static cmGlobalGeneratorFactory* NewFactory16(); bool MatchesGeneratorName(const std::string& name) const override; - void WriteSLNHeader(std::ostream& fout) override; - - const char* GetToolsVersion() override { return "15.0"; } - bool SetGeneratorInstance(std::string const& i, cmMakefile* mf) override; bool GetVSInstance(std::string& dir) const; @@ -36,11 +32,13 @@ public: std::string GetAuxiliaryToolset() const override; protected: + cmGlobalVisualStudioVersionedGenerator( + VSVersion version, cmake* cm, const std::string& name, + std::string const& platformInGeneratorName); + bool InitializeWindows(cmMakefile* mf) override; bool SelectWindowsStoreToolset(std::string& toolset) const override; - const char* GetIDEVersion() override { return "15.0"; } - // Used to verify that the Desktop toolset for the current generator is // installed on the machine. bool IsWindowsDesktopToolsetInstalled() const override; @@ -58,7 +56,10 @@ protected: std::string FindDevEnvCommand() override; private: - class Factory; + class Factory15; + friend class Factory15; + class Factory16; + friend class Factory16; mutable cmVSSetupAPIHelper vsSetupAPIHelper; }; #endif diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx index 558ef1585..c02c4711a 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.cxx +++ b/Source/cmGlobalWatcomWMakeGenerator.cxx @@ -51,7 +51,7 @@ void cmGlobalWatcomWMakeGenerator::GetDocumentation( } void cmGlobalWatcomWMakeGenerator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, const std::string& targetName, const std::string& config, bool fast, int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions) diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h index 0d10d58f4..6680b193f 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.h +++ b/Source/cmGlobalWatcomWMakeGenerator.h @@ -50,7 +50,7 @@ public: bool AllowDeleteOnError() const override { return false; } protected: - void GenerateBuildCommand(std::vector<std::string>& makeCommand, + void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index e353a3770..51c001e75 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -21,6 +21,7 @@ #include "cmLocalGenerator.h" #include "cmLocalXCodeGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" @@ -132,13 +133,27 @@ public: cmGlobalXCodeGenerator::GetDocumentation(entry); } - void GetGenerators(std::vector<std::string>& names) const override + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(cmGlobalXCodeGenerator::GetActualName()); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + return std::vector<std::string>(); } bool SupportsToolset() const override { return true; } bool SupportsPlatform() const override { return false; } + + std::vector<std::string> GetKnownPlatforms() const override + { + return std::vector<std::string>(); + } + + std::string GetDefaultPlatformName() const override { return std::string(); } }; cmGlobalXCodeGenerator::cmGlobalXCodeGenerator( @@ -176,12 +191,14 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( std::string versionFile; { std::string out; - std::string::size_type pos = 0; - if (cmSystemTools::RunSingleCommand("xcode-select --print-path", &out, - nullptr, nullptr, nullptr, - cmSystemTools::OUTPUT_NONE) && - (pos = out.find(".app/"), pos != std::string::npos)) { - versionFile = out.substr(0, pos + 5) + "Contents/version.plist"; + bool commandResult = cmSystemTools::RunSingleCommand( + "xcode-select --print-path", &out, nullptr, nullptr, nullptr, + cmSystemTools::OUTPUT_NONE); + if (commandResult) { + std::string::size_type pos = out.find(".app/"); + if (pos != std::string::npos) { + versionFile = out.substr(0, pos + 5) + "Contents/version.plist"; + } } } if (!versionFile.empty() && cmSystemTools::FileExists(versionFile.c_str())) { @@ -201,7 +218,7 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( unsigned int version_number = 10 * v[0] + v[1]; if (version_number < 30) { - cm->IssueMessage(cmake::FATAL_ERROR, + cm->IssueMessage(MessageType::FATAL_ERROR, "Xcode " + version_string + " not supported."); return nullptr; } @@ -263,7 +280,7 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, " " << ts << "\n" "that was specified."; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } this->GeneratorToolset = ts; @@ -322,20 +339,22 @@ bool cmGlobalXCodeGenerator::Open(const std::string& bindir, } void cmGlobalXCodeGenerator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, + GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& /*projectDir*/, const std::string& targetName, const std::string& config, bool /*fast*/, int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions) { // now build the test - makeCommand.push_back( + makeCommand.add( this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand())); - makeCommand.push_back("-project"); - std::string projectArg = projectName; - projectArg += ".xcode"; - projectArg += "proj"; - makeCommand.push_back(projectArg); + if (!projectName.empty()) { + makeCommand.add("-project"); + std::string projectArg = projectName; + projectArg += ".xcode"; + projectArg += "proj"; + makeCommand.add(projectArg); + } bool clean = false; std::string realTarget = targetName; @@ -343,29 +362,22 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand( clean = true; realTarget = "ALL_BUILD"; } - if (clean) { - makeCommand.push_back("clean"); - } else { - makeCommand.push_back("build"); - } - makeCommand.push_back("-target"); - if (!realTarget.empty()) { - makeCommand.push_back(realTarget); - } else { - makeCommand.push_back("ALL_BUILD"); - } - makeCommand.push_back("-configuration"); - makeCommand.push_back(!config.empty() ? config : "Debug"); + + makeCommand.add((clean ? "clean" : "build")); + makeCommand.add("-target", (realTarget.empty() ? "ALL_BUILD" : realTarget)); + makeCommand.add("-configuration", (config.empty() ? "Debug" : config)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - makeCommand.push_back("-jobs"); + makeCommand.add("-jobs"); if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.push_back(std::to_string(jobs)); + makeCommand.add(std::to_string(jobs)); } } - makeCommand.insert(makeCommand.end(), makeOptions.begin(), - makeOptions.end()); + if (this->XcodeVersion >= 70) { + makeCommand.add("-hideShellScriptEnvironment"); + } + makeCommand.add(makeOptions.begin(), makeOptions.end()); } ///! Create a local generator appropriate to this Global Generator @@ -473,6 +485,7 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget( } #define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK" +#define OBJECT_LIBRARY_ARTIFACT_DIR std::string() void cmGlobalXCodeGenerator::AddExtraTargets( cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens) @@ -497,6 +510,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets( makeHelper.push_back(dir); makeHelper.push_back("-f"); makeHelper.push_back(this->CurrentXCodeHackMakefile); + makeHelper.push_back("OBJDIR=$(OBJDIR)"); makeHelper.push_back(""); // placeholder, see below // Add ZERO_CHECK @@ -521,10 +535,6 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // now make the allbuild depend on all the non-utility targets // in the project for (auto& gen : gens) { - if (this->IsExcluded(root, gen)) { - continue; - } - for (auto target : gen->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { continue; @@ -546,7 +556,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets( target->GetType() == cmStateEnums::STATIC_LIBRARY || target->GetType() == cmStateEnums::SHARED_LIBRARY || target->GetType() == cmStateEnums::MODULE_LIBRARY))) { - makeHelper[makeHelper.size() - 1] = // fill placeholder + makeHelper.back() = // fill placeholder this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)"); cmCustomCommandLines commandLines; commandLines.push_back(makeHelper); @@ -557,8 +567,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets( false, "", false, cmMakefile::AcceptObjectLibraryCommands); } - if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY && - !target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { + if (!this->IsExcluded(target)) { allbuild->AddUtility(target->GetName()); } } @@ -589,8 +598,7 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( this->CurrentReRunCMakeMakefile += "/CMakeScripts"; cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile.c_str()); this->CurrentReRunCMakeMakefile += "/ReRunCMake.make"; - cmGeneratedFileStream makefileStream( - this->CurrentReRunCMakeMakefile.c_str()); + cmGeneratedFileStream makefileStream(this->CurrentReRunCMakeMakefile); makefileStream.SetCopyIfDifferent(true); makefileStream << "# Generated by CMake, DO NOT EDIT\n\n"; @@ -607,7 +615,7 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( std::string checkCache = root->GetBinaryDirectory(); checkCache += "/"; - checkCache += cmake::GetCMakeFilesDirectoryPostSlash(); + checkCache += "CMakeFiles/"; checkCache += "cmake.check_cache"; if (cm->DoWriteGlobVerifyTarget()) { @@ -746,8 +754,6 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath( class XCodeGeneratorExpressionInterpreter : public cmGeneratorExpressionInterpreter { - CM_DISABLE_COPY(XCodeGeneratorExpressionInterpreter) - public: XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile, cmLocalGenerator* localGenerator, @@ -759,6 +765,11 @@ public: { } + XCodeGeneratorExpressionInterpreter( + XCodeGeneratorExpressionInterpreter const&) = delete; + XCodeGeneratorExpressionInterpreter& operator=( + XCodeGeneratorExpressionInterpreter const&) = delete; + using cmGeneratorExpressionInterpreter::Evaluate; const std::string& Evaluate(const char* expression, @@ -775,7 +786,7 @@ public: "specified for source:\n" " " << this->SourceFile->GetFullPath() << "\n"; /* clang-format on */ - this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str()); } return processed; @@ -1051,7 +1062,7 @@ void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen) this->CurrentConfigurationTypes.clear(); this->CurrentMakefile->GetConfigurations(this->CurrentConfigurationTypes); if (this->CurrentConfigurationTypes.empty()) { - this->CurrentConfigurationTypes.push_back(""); + this->CurrentConfigurationTypes.emplace_back(); } } @@ -1397,14 +1408,14 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt) // language. cmMakefile* mf = gtgt->Target->GetMakefile(); std::string fname = gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory(); - fname += cmake::GetCMakeFilesDirectory(); + fname += "/CMakeFiles"; fname += "/"; fname += gtgt->GetName(); fname += "-CMakeForceLinker"; fname += "."; fname += cmSystemTools::LowerCase(llang); { - cmGeneratedFileStream fout(fname.c_str()); + cmGeneratedFileStream fout(fname); fout << "\n"; } if (cmSourceFile* sf = mf->GetOrCreateSource(fname)) { @@ -1655,6 +1666,7 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase( makecmd += cdir; makecmd += " -f "; makecmd += this->ConvertToRelativeForMake((makefile + "$CONFIGURATION")); + makecmd += " OBJDIR=$(basename \"$OBJECT_FILE_DIR_normal\")"; makecmd += " all"; buildphase->AddAttribute("shellScript", this->CreateString(makecmd)); buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0")); @@ -1666,7 +1678,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( { std::string makefileName = makefileBasename; makefileName += configName; - cmGeneratedFileStream makefileStream(makefileName.c_str()); + cmGeneratedFileStream makefileStream(makefileName); if (!makefileStream) { return; } @@ -1755,6 +1767,26 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( } } +void cmGlobalXCodeGenerator::AddPositionIndependentLinkAttribute( + cmGeneratorTarget* target, cmXCodeObject* buildSettings, + const std::string& configName) +{ + // For now, only EXECUTABLE is concerned + if (target->GetType() != cmStateEnums::EXECUTABLE) { + return; + } + + const char* PICValue = target->GetLinkPIEProperty(configName); + if (PICValue == nullptr) { + // POSITION_INDEPENDENT_CODE is not set + return; + } + + buildSettings->AddAttribute( + "LD_NO_PIE", + this->CreateString(cmSystemTools::IsOn(PICValue) ? "NO" : "YES")); +} + void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, cmXCodeObject* buildSettings, const std::string& configName) @@ -1806,6 +1838,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue)); } + // Handle PIE linker configuration + this->AddPositionIndependentLinkAttribute(gtgt, buildSettings, configName); + // Add define flags this->CurrentLocalGenerator->AppendFlags( defFlags, this->CurrentMakefile->GetDefineFlags()); @@ -1814,9 +1849,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, BuildObjectListOrString ppDefs(this, true); this->AppendDefines( ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\""); - if (const char* exportMacro = gtgt->GetExportMacro()) { + if (const std::string* exportMacro = gtgt->GetExportMacro()) { // Add the export symbol definition for shared library objects. - this->AppendDefines(ppDefs, exportMacro); + this->AppendDefines(ppDefs, exportMacro->c_str()); } std::vector<std::string> targetDefines; if (!langForPreprocessor.empty()) { @@ -1939,8 +1974,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, pnbase = gtgt->GetName(); pnsuffix = ".a"; - std::string pncdir = - this->GetObjectsNormalDirectory(this->CurrentProject, configName, gtgt); + std::string pncdir = this->GetObjectsDirectory( + this->CurrentProject, configName, gtgt, OBJECT_LIBRARY_ARTIFACT_DIR); buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", this->CreateString(pncdir)); } @@ -2219,6 +2254,22 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, debugStr = "NO"; } + // extract C++ stdlib + for (auto const& language : languages) { + if (language != "CXX") { + continue; + } + std::string& flags = cflags[language]; + + auto stdlib = + this->ExtractFlagRegex("(^| )(-stdlib=[^ ]+)( |$)", 2, flags); + if (stdlib.size() > 8) { + const auto cxxLibrary = stdlib.substr(8); + buildSettings->AddAttribute("CLANG_CXX_LIBRARY", + this->CreateString(cxxLibrary)); + } + } + buildSettings->AddAttribute("COMBINE_HIDPI_IMAGES", this->CreateString("YES")); buildSettings->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS", @@ -2425,7 +2476,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( this->AddXCodeProjBuildRule(gtgt, sources); for (auto sourceFile : sources) { - if (!sourceFile->GetPropertyAsBool("GENERATED")) { + if (!sourceFile->GetIsGenerated()) { this->CreateXCodeFileReference(sourceFile, gtgt); } } @@ -2841,8 +2892,7 @@ bool cmGlobalXCodeGenerator::CreateGroups( } // Add the file to the list of sources. std::string const& source = sf->GetFullPath(); - cmSourceGroup* sourceGroup = - mf->FindSourceGroup(source.c_str(), sourceGroups); + cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups); cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup); std::string key = GetGroupMapKeyFromPath(gtgt, source); this->GroupMap[key] = pbxgroup; @@ -2855,8 +2905,7 @@ bool cmGlobalXCodeGenerator::CreateGroups( listfile += "/CMakeLists.txt"; cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(listfile); std::string const& source = sf->GetFullPath(); - cmSourceGroup* sourceGroup = - mf->FindSourceGroup(source.c_str(), sourceGroups); + cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups); cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup); std::string key = GetGroupMapKeyFromPath(gtgt, source); this->GroupMap[key] = pbxgroup; @@ -3109,6 +3158,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( if (const char* vers = this->CurrentMakefile->GetDefinition( "CMAKE_Swift_LANGUAGE_VERSION")) { swiftVersion = vers; + } else if (this->XcodeVersion >= 102) { + swiftVersion = "4.0"; } else if (this->XcodeVersion >= 83) { swiftVersion = "3.0"; } else { @@ -3172,9 +3223,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( return true; } -std::string cmGlobalXCodeGenerator::GetObjectsNormalDirectory( +std::string cmGlobalXCodeGenerator::GetObjectsDirectory( const std::string& projName, const std::string& configName, - const cmGeneratorTarget* t) const + const cmGeneratorTarget* t, const std::string& variant) const { std::string dir = t->GetLocalGenerator()->GetCurrentBinaryDirectory(); dir += "/"; @@ -3183,8 +3234,8 @@ std::string cmGlobalXCodeGenerator::GetObjectsNormalDirectory( dir += configName; dir += "/"; dir += t->GetName(); - dir += ".build/Objects-normal/"; - + dir += ".build/"; + dir += variant; return dir; } @@ -3228,7 +3279,7 @@ void cmGlobalXCodeGenerator::ComputeObjectDirArch(cmMakefile* mf) void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::vector<cmXCodeObject*>& targets) { - cmGeneratedFileStream makefileStream(this->CurrentXCodeHackMakefile.c_str()); + cmGeneratedFileStream makefileStream(this->CurrentXCodeHackMakefile); if (!makefileStream) { cmSystemTools::Error("Could not create", this->CurrentXCodeHackMakefile.c_str()); @@ -3311,8 +3362,9 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( for (auto objLib : objlibs) { const std::string objLibName = objLib->GetName(); - std::string d = this->GetObjectsNormalDirectory(this->CurrentProject, - configName, objLib); + std::string d = + this->GetObjectsDirectory(this->CurrentProject, configName, objLib, + OBJECT_LIBRARY_ARTIFACT_DIR); d += "lib"; d += objLibName; d += ".a"; @@ -3329,8 +3381,8 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( // if building for more than one architecture // then remove those executables as well if (this->Architectures.size() > 1) { - std::string universal = this->GetObjectsNormalDirectory( - this->CurrentProject, configName, gt); + std::string universal = this->GetObjectsDirectory( + this->CurrentProject, configName, gt, "$(OBJDIR)/"); for (const auto& architecture : this->Architectures) { std::string universalFile = universal; universalFile += architecture; @@ -3369,7 +3421,7 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( xcodeDir += ".xcodeproj"; cmSystemTools::MakeDirectory(xcodeDir.c_str()); std::string xcodeProjFile = xcodeDir + "/project.pbxproj"; - cmGeneratedFileStream fout(xcodeProjFile.c_str()); + cmGeneratedFileStream fout(xcodeProjFile); fout.SetCopyIfDifferent(true); if (!fout) { return; @@ -3446,7 +3498,7 @@ void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings( std::string workspaceSettingsFile = xcodeSharedDataDir; workspaceSettingsFile += "/WorkspaceSettings.xcsettings"; - cmGeneratedFileStream fout(workspaceSettingsFile.c_str()); + cmGeneratedFileStream fout(workspaceSettingsFile); fout.SetCopyIfDifferent(true); if (!fout) { return; @@ -3543,13 +3595,13 @@ std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p) { // We force conversion because Xcode breakpoints do not work unless // they are in a file named relative to the source tree. - return cmOutputConverter::ForceToRelativePath( + return cmSystemTools::ForceToRelativePath( cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p); } std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p) { - return this->CurrentLocalGenerator->ConvertToRelativePath( + return this->CurrentLocalGenerator->MaybeConvertToRelativePath( cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p); } @@ -3684,7 +3736,7 @@ std::string cmGlobalXCodeGenerator::ComputeInfoPListLocation( cmGeneratorTarget* target) { std::string plist = target->GetLocalGenerator()->GetCurrentBinaryDirectory(); - plist += cmake::GetCMakeFilesDirectory(); + plist += "/CMakeFiles"; plist += "/"; plist += target->GetName(); plist += ".dir/Info.plist"; @@ -3734,8 +3786,8 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { std::string configName = this->GetCMakeCFGIntDir(); - std::string dir = - this->GetObjectsNormalDirectory("$(PROJECT_NAME)", configName, gt); + std::string dir = this->GetObjectsDirectory( + "$(PROJECT_NAME)", configName, gt, "$(OBJECT_FILE_DIR_normal:base)/"); dir += this->ObjectDirArch; dir += "/"; gt->ObjectDirectory = dir; diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 62f70302a..e1e412dca 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -66,7 +66,7 @@ public: * Try running cmake and building a file. This is used for dynalically * loaded commands, not as part of the usual build process. */ - void GenerateBuildCommand(std::vector<std::string>& makeCommand, + void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, @@ -171,6 +171,9 @@ private: const std::string& configName); cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt); void AddDependAndLinkInformation(cmXCodeObject* target); + void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target, + cmXCodeObject* buildSettings, + const std::string& configName); void CreateBuildSettings(cmGeneratorTarget* gtgt, cmXCodeObject* buildSettings, const std::string& buildType); @@ -261,9 +264,10 @@ private: { } - std::string GetObjectsNormalDirectory(const std::string& projName, - const std::string& configName, - const cmGeneratorTarget* t) const; + std::string GetObjectsDirectory(const std::string& projName, + const std::string& configName, + const cmGeneratorTarget* t, + const std::string& variant) const; static std::string GetDeploymentPlatform(const cmMakefile* mf); diff --git a/Source/cmGraphAdjacencyList.h b/Source/cmGraphAdjacencyList.h index 6a0a79912..5ca9269ed 100644 --- a/Source/cmGraphAdjacencyList.h +++ b/Source/cmGraphAdjacencyList.h @@ -5,6 +5,9 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cmListFileCache.h" + +#include <utility> #include <vector> /** @@ -15,18 +18,22 @@ class cmGraphEdge { public: - cmGraphEdge(int n = 0, bool s = true) + cmGraphEdge(int n, bool s, cmListFileBacktrace bt) : Dest(n) , Strong(s) + , Backtrace(std::move(bt)) { } operator int() const { return this->Dest; } bool IsStrong() const { return this->Strong; } + cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; } + private: int Dest; bool Strong; + cmListFileBacktrace Backtrace; }; struct cmGraphEdgeList : public std::vector<cmGraphEdge> { diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index fcdf03fc9..4b6027995 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -13,6 +13,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -68,7 +69,7 @@ const char* getShapeForTarget(const cmGeneratorTarget* target) } std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget( - cmTarget* Target) + cmTarget* Target, const cmGlobalGenerator* globalGenerator) { char sep = ';'; std::map<std::string, LinkLibraryScopeType> tokens; @@ -95,6 +96,13 @@ std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget( } std::string element = interfaceLinkLibraries.substr(start, end - start); + if (globalGenerator->IsAlias(element)) { + const auto tgt = globalGenerator->FindTarget(element); + if (tgt) { + element = tgt->GetName(); + } + } + if (std::string::npos == element.find("$<LINK_ONLY:", 0)) { // we assume first, that this library is an interface library. // if we find it again in the linklibraries property, we promote it to an @@ -116,6 +124,12 @@ std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget( } std::string element = linkLibraries.substr(start, end - start); + if (globalGenerator->IsAlias(element)) { + const auto tgt = globalGenerator->FindTarget(element); + if (tgt) { + element = tgt->GetName(); + } + } if (tokens.find(element) == tokens.end()) { // this library is not found in interfaceLinkLibraries but in @@ -137,13 +151,13 @@ std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget( } } -cmGraphVizWriter::cmGraphVizWriter( - const std::vector<cmLocalGenerator*>& localGenerators) +cmGraphVizWriter::cmGraphVizWriter(const cmGlobalGenerator* globalGenerator) : GraphType("digraph") , GraphName("GG") , GraphHeader("node [\n fontsize = \"12\"\n];") , GraphNodePrefix("node") - , LocalGenerators(localGenerators) + , GlobalGenerator(globalGenerator) + , LocalGenerators(globalGenerator->GetLocalGenerators()) , GenerateForExecutables(true) , GenerateForStaticLibs(true) , GenerateForSharedLibs(true) @@ -159,7 +173,7 @@ cmGraphVizWriter::cmGraphVizWriter( void cmGraphVizWriter::ReadSettings(const char* settingsFileName, const char* fallbackSettingsFileName) { - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::Unknown); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -185,12 +199,12 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName, std::cout << "Reading GraphViz options file: " << inFileName << std::endl; #define __set_if_set(var, cmakeDefinition) \ - { \ + do { \ const char* value = mf.GetDefinition(cmakeDefinition); \ if (value) { \ (var) = value; \ } \ - } + } while (false) __set_if_set(this->GraphType, "GRAPHVIZ_GRAPH_TYPE"); __set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME"); @@ -198,12 +212,12 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName, __set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX"); #define __set_bool_if_set(var, cmakeDefinition) \ - { \ + do { \ const char* value = mf.GetDefinition(cmakeDefinition); \ if (value) { \ (var) = mf.IsOn(cmakeDefinition); \ } \ - } + } while (false) __set_bool_if_set(this->GenerateForExecutables, "GRAPHVIZ_EXECUTABLES"); __set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS"); @@ -374,7 +388,8 @@ void cmGraphVizWriter::WriteConnections( std::string myNodeName = this->TargetNamesNodes.find(targetName)->second; std::map<std::string, LinkLibraryScopeType> ll = - getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target); + getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target, + GlobalGenerator); for (auto const& llit : ll) { const char* libName = llit.first.c_str(); @@ -439,7 +454,7 @@ void cmGraphVizWriter::WriteDependerConnections( // Now we have a target, check whether it links against targetName. // If so, draw a connection, and then continue with dependers on that one. std::map<std::string, LinkLibraryScopeType> ll = - getScopedLinkLibrariesFromTarget(tptr.second->Target); + getScopedLinkLibrariesFromTarget(tptr.second->Target, GlobalGenerator); for (auto const& llit : ll) { if (llit.first == targetName) { @@ -540,6 +555,13 @@ int cmGraphVizWriter::CollectAllExternalLibs(int cnt) continue; } + if (GlobalGenerator->IsAlias(libName)) { + const auto tgt = GlobalGenerator->FindTarget(libName); + if (tgt) { + libName = tgt->GetName().c_str(); + } + } + std::map<std::string, const cmGeneratorTarget*>::const_iterator tarIt = this->TargetPtrs.find(libName); if (tarIt == this->TargetPtrs.end()) { diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h index ac20da963..ed242f0ab 100644 --- a/Source/cmGraphVizWriter.h +++ b/Source/cmGraphVizWriter.h @@ -16,13 +16,14 @@ class cmGeneratedFileStream; class cmGeneratorTarget; class cmLocalGenerator; +class cmGlobalGenerator; /** This class implements writing files for graphviz (dot) for graphs * representing the dependencies between the targets in the project. */ class cmGraphVizWriter { public: - cmGraphVizWriter(const std::vector<cmLocalGenerator*>& localGenerators); + cmGraphVizWriter(const cmGlobalGenerator* globalGenerator); void ReadSettings(const char* settingsFileName, const char* fallbackSettingsFileName); @@ -69,6 +70,7 @@ protected: std::vector<cmsys::RegularExpression> TargetsToIgnoreRegex; + const cmGlobalGenerator* GlobalGenerator; const std::vector<cmLocalGenerator*>& LocalGenerators; std::map<std::string, const cmGeneratorTarget*> TargetPtrs; diff --git a/Source/cmIDEFlagTable.h b/Source/cmIDEFlagTable.h index 152e293eb..ff93432cb 100644 --- a/Source/cmIDEFlagTable.h +++ b/Source/cmIDEFlagTable.h @@ -3,13 +3,15 @@ #ifndef cmIDEFlagTable_h #define cmIDEFlagTable_h +#include <string> + // This is a table mapping XML tag IDE names to command line options struct cmIDEFlagTable { - const char* IDEName; // name used in the IDE xml file - const char* commandFlag; // command line flag - const char* comment; // comment - const char* value; // string value + std::string IDEName; // name used in the IDE xml file + std::string commandFlag; // command line flag + std::string comment; // comment + std::string value; // string value unsigned int special; // flags for special handling requests enum { @@ -27,6 +29,9 @@ struct cmIDEFlagTable SpaceAppendable = (1 << 7), // a flag that if specified multiple times // should have its value appended to the // old value with spaces + CommaAppendable = (1 << 8), // a flag that if specified multiple times + // should have its value appended to the + // old value with commas (e.g. C# /nowarn UserValueIgnored = UserValue | UserIgnored, UserValueRequired = UserValue | UserRequired diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index f996788d7..ea67d45fa 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -97,24 +97,24 @@ bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table, { const char* pf = flag.c_str() + 1; // Look for an entry in the flag table matching this flag. - for (cmIDEFlagTable const* entry = table; entry->IDEName; ++entry) { + for (cmIDEFlagTable const* entry = table; !entry->IDEName.empty(); ++entry) { bool entry_found = false; if (entry->special & cmIDEFlagTable::UserValue) { // This flag table entry accepts a user-specified value. If // the entry specifies UserRequired we must match only if a // non-empty value is given. - int n = static_cast<int>(strlen(entry->commandFlag)); - if ((strncmp(pf, entry->commandFlag, n) == 0 || + int n = static_cast<int>(entry->commandFlag.length()); + if ((strncmp(pf, entry->commandFlag.c_str(), n) == 0 || (entry->special & cmIDEFlagTable::CaseInsensitive && - cmsysString_strncasecmp(pf, entry->commandFlag, n))) && + cmsysString_strncasecmp(pf, entry->commandFlag.c_str(), n))) && (!(entry->special & cmIDEFlagTable::UserRequired) || static_cast<int>(strlen(pf)) > n)) { this->FlagMapUpdate(entry, std::string(pf + n)); entry_found = true; } - } else if (strcmp(pf, entry->commandFlag) == 0 || + } else if (strcmp(pf, entry->commandFlag.c_str()) == 0 || (entry->special & cmIDEFlagTable::CaseInsensitive && - cmsysString_strcasecmp(pf, entry->commandFlag) == 0)) { + cmsysString_strcasecmp(pf, entry->commandFlag.c_str()) == 0)) { if (entry->special & cmIDEFlagTable::UserFollowing) { // This flag expects a value in the following argument. this->DoingFollowing = entry; @@ -148,6 +148,8 @@ void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry, this->FlagMap[entry->IDEName].push_back(new_value); } else if (entry->special & cmIDEFlagTable::SpaceAppendable) { this->FlagMap[entry->IDEName].append_with_space(new_value); + } else if (entry->special & cmIDEFlagTable::CommaAppendable) { + this->FlagMap[entry->IDEName].append_with_comma(new_value); } else { // Use the user-specified value. this->FlagMap[entry->IDEName] = new_value; diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h index a4e575780..4a430732f 100644 --- a/Source/cmIDEOptions.h +++ b/Source/cmIDEOptions.h @@ -65,12 +65,22 @@ protected: this->derived::operator=(r); return *this; } + FlagValue& append_with_comma(std::string const& r) + { + return append_with_separator(r, ','); + } FlagValue& append_with_space(std::string const& r) { + return append_with_separator(r, ' '); + } + + private: + FlagValue& append_with_separator(std::string const& r, char separator) + { this->resize(1); std::string& l = this->operator[](0); if (!l.empty()) { - l += " "; + l += separator; } l += r; return *this; diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index ae4041d8e..d1f8f58e2 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -6,6 +6,7 @@ #include "cmExecutionStatus.h" #include "cmExpandedCommandArgument.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmSystemTools.h" #include "cmake.h" @@ -39,7 +40,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, // Remove the function blocker for this scope or bail. std::unique_ptr<cmFunctionBlocker> fb( mf.RemoveFunctionBlocker(this, lff)); - if (!fb.get()) { + if (!fb) { return false; } @@ -60,7 +61,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, if (this->ElseSeen) { cmListFileBacktrace bt = mf.GetBacktrace(func); mf.GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "A duplicate ELSE command was found inside an IF block.", bt); cmSystemTools::SetFatalErrorOccured(); return true; @@ -79,7 +80,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, if (this->ElseSeen) { cmListFileBacktrace bt = mf.GetBacktrace(func); mf.GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "An ELSEIF command was found after an ELSE command.", bt); cmSystemTools::SetFatalErrorOccured(); return true; @@ -98,7 +99,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, std::vector<cmExpandedCommandArgument> expandedArguments; mf.ExpandArguments(func.Arguments, expandedArguments); - cmake::MessageType messType; + MessageType messType; cmListFileContext conditionContext = cmListFileContext::FromCommandContext( @@ -115,7 +116,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, err += errorString; cmListFileBacktrace bt = mf.GetBacktrace(func); mf.GetCMakeInstance()->IssueMessage(messType, err, bt); - if (messType == cmake::FATAL_ERROR) { + if (messType == MessageType::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); return true; } @@ -181,7 +182,7 @@ bool cmIfCommand::InvokeInitialPass( std::vector<cmExpandedCommandArgument> expandedArguments; this->Makefile->ExpandArguments(args, expandedArguments); - cmake::MessageType status; + MessageType status; cmConditionEvaluator conditionEvaluator( *(this->Makefile), this->Makefile->GetExecutionContext(), @@ -193,8 +194,8 @@ bool cmIfCommand::InvokeInitialPass( if (!errorString.empty()) { std::string err = "if " + cmIfCommandError(expandedArguments); err += errorString; - if (status == cmake::FATAL_ERROR) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, err); + if (status == MessageType::FATAL_ERROR) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, err); cmSystemTools::SetFatalErrorOccured(); return true; } diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h index e3d30ddbd..d34ed02c8 100644 --- a/Source/cmIfCommand.h +++ b/Source/cmIfCommand.h @@ -19,13 +19,6 @@ class cmMakefile; class cmIfFunctionBlocker : public cmFunctionBlocker { public: - cmIfFunctionBlocker() - { - this->HasRun = false; - this->ElseSeen = false; - this->ScopeDepth = 0; - } - ~cmIfFunctionBlocker() override {} bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus&) override; bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override; @@ -33,9 +26,9 @@ public: std::vector<cmListFileArgument> Args; std::vector<cmListFileFunction> Functions; bool IsBlocking; - bool HasRun; - bool ElseSeen; - unsigned int ScopeDepth; + bool HasRun = false; + bool ElseSeen = false; + unsigned int ScopeDepth = 0; }; /// Starts an if block diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx index f86257826..0d608bb9d 100644 --- a/Source/cmIncludeCommand.cxx +++ b/Source/cmIncludeCommand.cxx @@ -6,9 +6,9 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -58,7 +58,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, } if (fname.empty()) { - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, "include() given empty file name (ignored)."); return true; } @@ -67,7 +67,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, // Not a path. Maybe module. std::string module = fname; module += ".cmake"; - std::string mfile = this->Makefile->GetModulesFile(module.c_str()); + std::string mfile = this->Makefile->GetModulesFile(module); if (!mfile.empty()) { fname = mfile; } @@ -80,7 +80,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, if (gg->IsExportedTargetsFile(fname_abs)) { const char* modal = nullptr; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0024)) { case cmPolicies::WARN: @@ -92,7 +92,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: modal = "may"; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (modal) { e << "The file\n " << fname_abs @@ -103,7 +103,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, "include() command. Use ALIAS targets instead to refer to targets " "by alternative names.\n"; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -120,8 +120,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, return true; } - bool readit = - this->Makefile->ReadDependentFile(listFile.c_str(), noPolicyScope); + bool readit = this->Makefile->ReadDependentFile(listFile, noPolicyScope); // add the location of the included file if a result variable was given if (!resultVarName.empty()) { diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index caec67db7..549a263e3 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -4,6 +4,7 @@ #include <algorithm> #include <set> +#include <utility> #include "cmGeneratorExpression.h" #include "cmMakefile.h" diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx index c9217d374..93134adb6 100644 --- a/Source/cmIncludeExternalMSProjectCommand.cxx +++ b/Source/cmIncludeExternalMSProjectCommand.cxx @@ -8,6 +8,7 @@ # include "cmStateTypes.h" # include "cmSystemTools.h" # include "cmTarget.h" +# include "cmake.h" #endif class cmExecutionStatus; @@ -84,10 +85,12 @@ bool cmIncludeExternalMSProjectCommand::InitialPass( // Create a target instance for this utility. cmTarget* target = this->Makefile->AddNewTarget(cmStateEnums::UTILITY, utility_name.c_str()); + if (this->Makefile->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { + target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); + } target->SetProperty("GENERATOR_FILE_NAME", utility_name.c_str()); target->SetProperty("EXTERNAL_MSPROJECT", path.c_str()); - target->SetProperty("EXCLUDE_FROM_ALL", "FALSE"); if (!customType.empty()) target->SetProperty("VS_PROJECT_TYPE", customType.c_str()); diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 6e33cf7a3..20d1a3134 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -3,6 +3,7 @@ #include "cmInstallCommand.h" #include "cmsys/Glob.hxx" +#include <set> #include <sstream> #include <stddef.h> #include <utility> @@ -20,18 +21,20 @@ #include "cmInstallGenerator.h" #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" +#include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" -#include "cmake.h" class cmExecutionStatus; static cmInstallTargetGenerator* CreateInstallTargetGenerator( cmTarget& target, const cmInstallCommandArguments& args, bool impLib, + cmListFileBacktrace const& backtrace, const std::string& destination, bool forceOpt = false, bool namelink = false) { cmInstallGenerator::MessageLevel message = @@ -40,24 +43,49 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator( const char* component = namelink ? args.GetNamelinkComponent().c_str() : args.GetComponent().c_str(); return new cmInstallTargetGenerator( - target.GetName(), args.GetDestination().c_str(), impLib, + target.GetName(), destination.c_str(), impLib, args.GetPermissions().c_str(), args.GetConfigurations(), component, - message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt); + message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt, + backtrace); +} + +static cmInstallTargetGenerator* CreateInstallTargetGenerator( + cmTarget& target, const cmInstallCommandArguments& args, bool impLib, + cmListFileBacktrace const& backtrace, bool forceOpt = false, + bool namelink = false) +{ + return CreateInstallTargetGenerator(target, args, impLib, backtrace, + args.GetDestination(), forceOpt, + namelink); } static cmInstallFilesGenerator* CreateInstallFilesGenerator( cmMakefile* mf, const std::vector<std::string>& absFiles, - const cmInstallCommandArguments& args, bool programs) + const cmInstallCommandArguments& args, bool programs, + const std::string& destination) { cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(mf); return new cmInstallFilesGenerator( - absFiles, args.GetDestination().c_str(), programs, - args.GetPermissions().c_str(), args.GetConfigurations(), - args.GetComponent().c_str(), message, args.GetExcludeFromAll(), - args.GetRename().c_str(), args.GetOptional()); + absFiles, destination.c_str(), programs, args.GetPermissions().c_str(), + args.GetConfigurations(), args.GetComponent().c_str(), message, + args.GetExcludeFromAll(), args.GetRename().c_str(), args.GetOptional()); } +static cmInstallFilesGenerator* CreateInstallFilesGenerator( + cmMakefile* mf, const std::vector<std::string>& absFiles, + const cmInstallCommandArguments& args, bool programs) +{ + return CreateInstallFilesGenerator(mf, absFiles, args, programs, + args.GetDestination()); +} + +static const std::set<std::string> allowedTypes{ + "BIN", "SBIN", "LIB", "INCLUDE", "SYSCONF", + "SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA", "INFO", + "LOCALE", "MAN", "DOC", +}; + // cmInstallCommand bool cmInstallCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus&) @@ -332,6 +360,17 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) "At most one of these two options may be specified."); return false; } + if (!genericArgs.GetType().empty() || !archiveArgs.GetType().empty() || + !libraryArgs.GetType().empty() || !runtimeArgs.GetType().empty() || + !objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() || + !bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() || + !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) { + std::ostringstream e; + e << "TARGETS given TYPE option. The TYPE option may only be specified in " + " install(FILES) and install(DIRECTORIES)."; + this->SetError(e.str()); + return false; + } // Select the mode for installing symlinks to versioned shared libraries. cmInstallTargetGenerator::NamelinkModeType namelinkMode = @@ -363,7 +402,11 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) cmTarget* target = this->Makefile->FindLocalNonAliasTarget(tgt); if (!target) { // If no local target has been found, find it in the global scope. - target = this->Makefile->GetGlobalGenerator()->FindTarget(tgt, true); + cmTarget* const global_target = + this->Makefile->GetGlobalGenerator()->FindTarget(tgt, true); + if (global_target && !global_target->IsImported()) { + target = global_target; + } } if (target) { // Found the target. Check its type. @@ -435,17 +478,21 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // This is a DLL platform. if (!archiveArgs.GetDestination().empty()) { // The import library uses the ARCHIVE properties. - archiveGenerator = - CreateInstallTargetGenerator(target, archiveArgs, true); + archiveGenerator = CreateInstallTargetGenerator( + target, archiveArgs, true, this->Makefile->GetBacktrace()); } if (!runtimeArgs.GetDestination().empty()) { // The DLL uses the RUNTIME properties. - runtimeGenerator = - CreateInstallTargetGenerator(target, runtimeArgs, false); + runtimeGenerator = CreateInstallTargetGenerator( + target, runtimeArgs, false, this->Makefile->GetBacktrace()); } if ((archiveGenerator == nullptr) && (runtimeGenerator == nullptr)) { - this->SetError("Library TARGETS given no DESTINATION!"); - return false; + archiveGenerator = CreateInstallTargetGenerator( + target, archiveArgs, true, this->Makefile->GetBacktrace(), + this->GetArchiveDestination(nullptr)); + runtimeGenerator = CreateInstallTargetGenerator( + target, runtimeArgs, false, this->Makefile->GetBacktrace(), + this->GetRuntimeDestination(nullptr)); } } else { // This is a non-DLL platform. @@ -459,8 +506,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // Use the FRAMEWORK properties. if (!frameworkArgs.GetDestination().empty()) { - frameworkGenerator = - CreateInstallTargetGenerator(target, frameworkArgs, false); + frameworkGenerator = CreateInstallTargetGenerator( + target, frameworkArgs, false, this->Makefile->GetBacktrace()); } else { std::ostringstream e; e << "TARGETS given no FRAMEWORK DESTINATION for shared library " @@ -471,29 +518,22 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } } else { // The shared library uses the LIBRARY properties. - if (!libraryArgs.GetDestination().empty()) { - if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) { - libraryGenerator = - CreateInstallTargetGenerator(target, libraryArgs, false); - libraryGenerator->SetNamelinkMode( - cmInstallTargetGenerator::NamelinkModeSkip); - } - if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) { - namelinkGenerator = CreateInstallTargetGenerator( - target, libraryArgs, false, false, true); - namelinkGenerator->SetNamelinkMode( - cmInstallTargetGenerator::NamelinkModeOnly); - } - namelinkOnly = - (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); - } else { - std::ostringstream e; - e << "TARGETS given no LIBRARY DESTINATION for shared library " - "target \"" - << target.GetName() << "\"."; - this->SetError(e.str()); - return false; + if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) { + libraryGenerator = CreateInstallTargetGenerator( + target, libraryArgs, false, this->Makefile->GetBacktrace(), + this->GetLibraryDestination(&libraryArgs)); + libraryGenerator->SetNamelinkMode( + cmInstallTargetGenerator::NamelinkModeSkip); } + if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) { + namelinkGenerator = CreateInstallTargetGenerator( + target, libraryArgs, false, this->Makefile->GetBacktrace(), + this->GetLibraryDestination(&libraryArgs), false, true); + namelinkGenerator->SetNamelinkMode( + cmInstallTargetGenerator::NamelinkModeOnly); + } + namelinkOnly = + (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); } } } break; @@ -508,8 +548,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // Use the FRAMEWORK properties. if (!frameworkArgs.GetDestination().empty()) { - frameworkGenerator = - CreateInstallTargetGenerator(target, frameworkArgs, false); + frameworkGenerator = CreateInstallTargetGenerator( + target, frameworkArgs, false, this->Makefile->GetBacktrace()); } else { std::ostringstream e; e << "TARGETS given no FRAMEWORK DESTINATION for static library " @@ -520,24 +560,16 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } } else { // Static libraries use ARCHIVE properties. - if (!archiveArgs.GetDestination().empty()) { - archiveGenerator = - CreateInstallTargetGenerator(target, archiveArgs, false); - } else { - std::ostringstream e; - e << "TARGETS given no ARCHIVE DESTINATION for static library " - "target \"" - << target.GetName() << "\"."; - this->SetError(e.str()); - return false; - } + archiveGenerator = CreateInstallTargetGenerator( + target, archiveArgs, false, this->Makefile->GetBacktrace(), + this->GetArchiveDestination(&archiveArgs)); } } break; case cmStateEnums::MODULE_LIBRARY: { // Modules use LIBRARY properties. if (!libraryArgs.GetDestination().empty()) { - libraryGenerator = - CreateInstallTargetGenerator(target, libraryArgs, false); + libraryGenerator = CreateInstallTargetGenerator( + target, libraryArgs, false, this->Makefile->GetBacktrace()); libraryGenerator->SetNamelinkMode(namelinkMode); namelinkOnly = (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); @@ -563,8 +595,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) return false; } - objectGenerator = - CreateInstallTargetGenerator(target, objectArgs, false); + objectGenerator = CreateInstallTargetGenerator( + target, objectArgs, false, this->Makefile->GetBacktrace()); } else { // Installing an OBJECT library without a destination transforms // it to an INTERFACE library. It installs no files but can be @@ -575,15 +607,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) if (target.IsAppBundleOnApple()) { // Application bundles use the BUNDLE properties. if (!bundleArgs.GetDestination().empty()) { - bundleGenerator = - CreateInstallTargetGenerator(target, bundleArgs, false); + bundleGenerator = CreateInstallTargetGenerator( + target, bundleArgs, false, this->Makefile->GetBacktrace()); } else if (!runtimeArgs.GetDestination().empty()) { bool failure = false; if (this->CheckCMP0006(failure)) { // For CMake 2.4 compatibility fallback to the RUNTIME // properties. - bundleGenerator = - CreateInstallTargetGenerator(target, runtimeArgs, false); + bundleGenerator = CreateInstallTargetGenerator( + target, runtimeArgs, false, this->Makefile->GetBacktrace()); } else if (failure) { return false; } @@ -598,17 +630,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } } else { // Executables use the RUNTIME properties. - if (!runtimeArgs.GetDestination().empty()) { - runtimeGenerator = - CreateInstallTargetGenerator(target, runtimeArgs, false); - } else { - std::ostringstream e; - e << "TARGETS given no RUNTIME DESTINATION for executable " - "target \"" - << target.GetName() << "\"."; - this->SetError(e.str()); - return false; - } + runtimeGenerator = CreateInstallTargetGenerator( + target, runtimeArgs, false, this->Makefile->GetBacktrace(), + this->GetRuntimeDestination(&runtimeArgs)); } // On DLL platforms an executable may also have an import @@ -617,8 +641,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) if (dll_platform && !archiveArgs.GetDestination().empty() && target.IsExecutableWithExports()) { // The import library uses the ARCHIVE properties. - archiveGenerator = - CreateInstallTargetGenerator(target, archiveArgs, true, true); + archiveGenerator = CreateInstallTargetGenerator( + target, archiveArgs, true, this->Makefile->GetBacktrace(), true); } } break; case cmStateEnums::INTERFACE_LIBRARY: @@ -655,15 +679,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } // Create the files install generator. - if (!privateHeaderArgs.GetDestination().empty()) { - privateHeaderGenerator = CreateInstallFilesGenerator( - this->Makefile, absFiles, privateHeaderArgs, false); - } else { - std::ostringstream e; - e << "INSTALL TARGETS - target " << target.GetName() << " has " - << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION."; - cmSystemTools::Message(e.str().c_str(), "Warning"); - } + privateHeaderGenerator = CreateInstallFilesGenerator( + this->Makefile, absFiles, privateHeaderArgs, false, + this->GetIncludeDestination(&privateHeaderArgs)); } files = target.GetProperty("PUBLIC_HEADER"); @@ -676,15 +694,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } // Create the files install generator. - if (!publicHeaderArgs.GetDestination().empty()) { - publicHeaderGenerator = CreateInstallFilesGenerator( - this->Makefile, absFiles, publicHeaderArgs, false); - } else { - std::ostringstream e; - e << "INSTALL TARGETS - target " << target.GetName() << " has " - << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION."; - cmSystemTools::Message(e.str().c_str(), "Warning"); - } + publicHeaderGenerator = CreateInstallFilesGenerator( + this->Makefile, absFiles, publicHeaderArgs, false, + this->GetIncludeDestination(&publicHeaderArgs)); } files = target.GetProperty("RESOURCE"); @@ -704,7 +716,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) std::ostringstream e; e << "INSTALL TARGETS - target " << target.GetName() << " has " << "RESOURCE files but no RESOURCE DESTINATION."; - cmSystemTools::Message(e.str().c_str(), "Warning"); + cmSystemTools::Message(e.str(), "Warning"); } } } @@ -820,6 +832,14 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) return false; } + std::string type = ica.GetType(); + if (!type.empty() && allowedTypes.count(type) == 0) { + std::ostringstream e; + e << args[0] << " given non-type \"" << type << "\" with TYPE argument."; + this->SetError(e.str()); + return false; + } + const std::vector<std::string>& filesVector = files.GetVector(); // Check if there is something to do. @@ -848,7 +868,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) if (gg->IsExportedTargetsFile(file)) { const char* modal = nullptr; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (status) { case cmPolicies::WARN: @@ -860,7 +880,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: modal = "may"; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (modal) { e << "The file\n " << file @@ -871,7 +891,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) "install() command. Use the install(EXPORT) mechanism " "instead. See the cmake-packages(7) manual for more.\n"; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -882,7 +902,17 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) return false; } - if (ica.GetDestination().empty()) { + if (!type.empty() && !ica.GetDestination().empty()) { + std::ostringstream e; + e << args[0] + << " given both TYPE and DESTINATION arguments. You may only specify " + "one."; + this->SetError(e.str()); + return false; + } + + std::string destination = this->GetDestinationForType(&ica, type); + if (destination.empty()) { // A destination is required. std::ostringstream e; e << args[0] << " given no DESTINATION!"; @@ -891,8 +921,8 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) } // Create the files install generator. - this->Makefile->AddInstallGenerator( - CreateInstallFilesGenerator(this->Makefile, absFiles, ica, programs)); + this->Makefile->AddInstallGenerator(CreateInstallFilesGenerator( + this->Makefile, absFiles, ica, programs, destination)); // Tell the global generator about any installation component names // specified. @@ -916,7 +946,8 @@ bool cmInstallCommand::HandleDirectoryMode( DoingPermsDir, DoingPermsMatch, DoingConfigurations, - DoingComponent + DoingComponent, + DoingType }; Doing doing = DoingDirs; bool in_match_mode = false; @@ -930,6 +961,7 @@ bool cmInstallCommand::HandleDirectoryMode( std::vector<std::string> configurations; std::string component = this->DefaultComponentName; std::string literal_args; + std::string type; for (unsigned int i = 1; i < args.size(); ++i) { if (args[i] == "DESTINATION") { if (in_match_mode) { @@ -942,6 +974,17 @@ bool cmInstallCommand::HandleDirectoryMode( // Switch to setting the destination property. doing = DoingDestination; + } else if (args[i] == "TYPE") { + if (in_match_mode) { + std::ostringstream e; + e << args[0] << " does not allow \"" << args[i] + << "\" after PATTERN or REGEX."; + this->SetError(e.str()); + return false; + } + + // Switch to setting the type. + doing = DoingType; } else if (args[i] == "OPTIONAL") { if (in_match_mode) { std::ostringstream e; @@ -1102,6 +1145,17 @@ bool cmInstallCommand::HandleDirectoryMode( } else if (doing == DoingDestination) { destination = args[i].c_str(); doing = DoingNone; + } else if (doing == DoingType) { + if (allowedTypes.count(args[i]) == 0) { + std::ostringstream e; + e << args[0] << " given non-type \"" << args[i] + << "\" with TYPE argument."; + this->SetError(e.str()); + return false; + } + + type = args[i]; + doing = DoingNone; } else if (doing == DoingPattern) { // Convert the pattern to a regular expression. Require a // leading slash and trailing end-of-string in the matched @@ -1175,10 +1229,22 @@ bool cmInstallCommand::HandleDirectoryMode( if (dirs.empty()) { return true; } + std::string destinationStr; if (!destination) { - // A destination is required. + if (type.empty()) { + // A destination is required. + std::ostringstream e; + e << args[0] << " given no DESTINATION!"; + this->SetError(e.str()); + return false; + } + destinationStr = this->GetDestinationForType(nullptr, type); + destination = destinationStr.c_str(); + } else if (!type.empty()) { std::ostringstream e; - e << args[0] << " given no DESTINATION!"; + e << args[0] + << " given both TYPE and DESTINATION arguments. You may only specify " + "one."; this->SetError(e.str()); return false; } @@ -1433,7 +1499,7 @@ bool cmInstallCommand::CheckCMP0006(bool& failure) switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) { case cmPolicies::WARN: this->Makefile->IssueMessage( - cmake::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0006)); CM_FALLTHROUGH; case cmPolicies::OLD: @@ -1446,9 +1512,169 @@ bool cmInstallCommand::CheckCMP0006(bool& failure) case cmPolicies::REQUIRED_ALWAYS: failure = true; this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0006)); break; } return false; } + +std::string cmInstallCommand::GetDestination( + const cmInstallCommandArguments* args, const std::string& varName, + const std::string& guess) +{ + if (args && !args->GetDestination().empty()) { + return args->GetDestination(); + } + std::string val = this->Makefile->GetSafeDefinition(varName); + if (!val.empty()) { + return val; + } + return guess; +} + +std::string cmInstallCommand::GetRuntimeDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_BINDIR", "bin"); +} + +std::string cmInstallCommand::GetSbinDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_SBINDIR", "sbin"); +} + +std::string cmInstallCommand::GetArchiveDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib"); +} + +std::string cmInstallCommand::GetLibraryDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib"); +} + +std::string cmInstallCommand::GetIncludeDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_INCLUDEDIR", "include"); +} + +std::string cmInstallCommand::GetSysconfDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_SYSCONFDIR", "etc"); +} + +std::string cmInstallCommand::GetSharedStateDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_SHAREDSTATEDIR", "com"); +} + +std::string cmInstallCommand::GetLocalStateDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_LOCALSTATEDIR", "var"); +} + +std::string cmInstallCommand::GetRunStateDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_RUNSTATEDIR", + this->GetLocalStateDestination(nullptr) + + "/run"); +} + +std::string cmInstallCommand::GetDataRootDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_DATAROOTDIR", "share"); +} + +std::string cmInstallCommand::GetDataDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_DATADIR", + this->GetDataRootDestination(nullptr)); +} + +std::string cmInstallCommand::GetInfoDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_INFODIR", + this->GetDataRootDestination(nullptr) + "/info"); +} + +std::string cmInstallCommand::GetLocaleDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_LOCALEDIR", + this->GetDataRootDestination(nullptr) + + "/locale"); +} + +std::string cmInstallCommand::GetManDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_MANDIR", + this->GetDataRootDestination(nullptr) + "/man"); +} + +std::string cmInstallCommand::GetDocDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_DOCDIR", + this->GetDataRootDestination(nullptr) + "/doc"); +} + +std::string cmInstallCommand::GetDestinationForType( + const cmInstallCommandArguments* args, const std::string& type) +{ + if (args && !args->GetDestination().empty()) { + return args->GetDestination(); + } + if (type == "BIN") { + return this->GetRuntimeDestination(nullptr); + } + if (type == "SBIN") { + return this->GetSbinDestination(nullptr); + } + if (type == "SYSCONF") { + return this->GetSysconfDestination(nullptr); + } + if (type == "SHAREDSTATE") { + return this->GetSharedStateDestination(nullptr); + } + if (type == "LOCALSTATE") { + return this->GetLocalStateDestination(nullptr); + } + if (type == "RUNSTATE") { + return this->GetRunStateDestination(nullptr); + } + if (type == "LIB") { + return this->GetLibraryDestination(nullptr); + } + if (type == "INCLUDE") { + return this->GetIncludeDestination(nullptr); + } + if (type == "DATA") { + return this->GetDataDestination(nullptr); + } + if (type == "INFO") { + return this->GetInfoDestination(nullptr); + } + if (type == "LOCALE") { + return this->GetLocaleDestination(nullptr); + } + if (type == "MAN") { + return this->GetManDestination(nullptr); + } + if (type == "DOC") { + return this->GetDocDestination(nullptr); + } + return ""; +} diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 8bd015933..202c43810 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -11,6 +11,7 @@ #include "cmCommand.h" class cmExecutionStatus; +class cmInstallCommandArguments; /** \class cmInstallCommand * \brief Specifies where to install some files @@ -45,6 +46,27 @@ private: std::vector<std::string>& absFiles); bool CheckCMP0006(bool& failure); + std::string GetDestination(const cmInstallCommandArguments* args, + const std::string& varName, + const std::string& guess); + std::string GetRuntimeDestination(const cmInstallCommandArguments* args); + std::string GetSbinDestination(const cmInstallCommandArguments* args); + std::string GetArchiveDestination(const cmInstallCommandArguments* args); + std::string GetLibraryDestination(const cmInstallCommandArguments* args); + std::string GetIncludeDestination(const cmInstallCommandArguments* args); + std::string GetSysconfDestination(const cmInstallCommandArguments* args); + std::string GetSharedStateDestination(const cmInstallCommandArguments* args); + std::string GetLocalStateDestination(const cmInstallCommandArguments* args); + std::string GetRunStateDestination(const cmInstallCommandArguments* args); + std::string GetDataRootDestination(const cmInstallCommandArguments* args); + std::string GetDataDestination(const cmInstallCommandArguments* args); + std::string GetInfoDestination(const cmInstallCommandArguments* args); + std::string GetLocaleDestination(const cmInstallCommandArguments* args); + std::string GetManDestination(const cmInstallCommandArguments* args); + std::string GetDocDestination(const cmInstallCommandArguments* args); + std::string GetDestinationForType(const cmInstallCommandArguments* args, + const std::string& type); + std::string DefaultComponentName; }; diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx index 2d6dc1295..155f0559b 100644 --- a/Source/cmInstallCommandArguments.cxx +++ b/Source/cmInstallCommandArguments.cxx @@ -16,10 +16,8 @@ const char* cmInstallCommandArguments::PermissionsTable[] = { const std::string cmInstallCommandArguments::EmptyString; cmInstallCommandArguments::cmInstallCommandArguments( - const std::string& defaultComponent) - : Parser() - , ArgumentGroup() - , Destination(&Parser, "DESTINATION", &ArgumentGroup) + std::string defaultComponent) + : Destination(&Parser, "DESTINATION", &ArgumentGroup) , Component(&Parser, "COMPONENT", &ArgumentGroup) , NamelinkComponent(&Parser, "NAMELINK_COMPONENT", &ArgumentGroup) , ExcludeFromAll(&Parser, "EXCLUDE_FROM_ALL", &ArgumentGroup) @@ -29,8 +27,9 @@ cmInstallCommandArguments::cmInstallCommandArguments( , Optional(&Parser, "OPTIONAL", &ArgumentGroup) , NamelinkOnly(&Parser, "NAMELINK_ONLY", &ArgumentGroup) , NamelinkSkip(&Parser, "NAMELINK_SKIP", &ArgumentGroup) + , Type(&Parser, "TYPE", &ArgumentGroup) , GenericArguments(nullptr) - , DefaultComponentName(defaultComponent) + , DefaultComponentName(std::move(defaultComponent)) { } @@ -145,6 +144,11 @@ bool cmInstallCommandArguments::HasNamelinkComponent() const return false; } +const std::string& cmInstallCommandArguments::GetType() const +{ + return this->Type.GetString(); +} + const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations() const { @@ -177,7 +181,8 @@ bool cmInstallCommandArguments::CheckPermissions() { this->PermissionsString.clear(); for (std::string const& perm : this->Permissions.GetVector()) { - if (!this->CheckPermissions(perm, this->PermissionsString)) { + if (!cmInstallCommandArguments::CheckPermissions( + perm, this->PermissionsString)) { return false; } } @@ -201,9 +206,7 @@ bool cmInstallCommandArguments::CheckPermissions( return false; } -cmInstallCommandIncludesArgument::cmInstallCommandIncludesArgument() -{ -} +cmInstallCommandIncludesArgument::cmInstallCommandIncludesArgument() = default; const std::vector<std::string>& cmInstallCommandIncludesArgument::GetIncludeDirs() const diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h index ee6e86597..9c0d41763 100644 --- a/Source/cmInstallCommandArguments.h +++ b/Source/cmInstallCommandArguments.h @@ -13,7 +13,7 @@ class cmInstallCommandArguments { public: - cmInstallCommandArguments(const std::string& defaultComponent); + cmInstallCommandArguments(std::string defaultComponent); void SetGenericArguments(cmInstallCommandArguments* args) { this->GenericArguments = args; @@ -35,6 +35,7 @@ public: bool GetNamelinkOnly() const; bool GetNamelinkSkip() const; bool HasNamelinkComponent() const; + const std::string& GetType() const; // once HandleDirectoryMode() is also switched to using // cmInstallCommandArguments then these two functions can become non-static @@ -44,7 +45,6 @@ public: cmCommandArgumentGroup ArgumentGroup; private: - cmInstallCommandArguments(); // disabled cmCAString Destination; cmCAString Component; cmCAString NamelinkComponent; @@ -55,6 +55,7 @@ private: cmCAEnabler Optional; cmCAEnabler NamelinkOnly; cmCAEnabler NamelinkSkip; + cmCAString Type; std::string DestinationString; std::string PermissionsString; diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index c9b50a3b6..a88c7af3b 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -39,9 +39,7 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator( } } -cmInstallDirectoryGenerator::~cmInstallDirectoryGenerator() -{ -} +cmInstallDirectoryGenerator::~cmInstallDirectoryGenerator() = default; void cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg) { diff --git a/Source/cmInstallExportAndroidMKGenerator.cxx b/Source/cmInstallExportAndroidMKGenerator.cxx index dd85b8843..85b702142 100644 --- a/Source/cmInstallExportAndroidMKGenerator.cxx +++ b/Source/cmInstallExportAndroidMKGenerator.cxx @@ -13,7 +13,7 @@ #include "cmInstallTargetGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmake.h" +#include "cmMessageType.h" cmInstallExportAndroidMKGenerator::cmInstallExportAndroidMKGenerator( cmExportSet* exportSet, const char* destination, diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index d441e4138..47b9785e5 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -3,6 +3,7 @@ #include "cmInstallExportGenerator.h" #include <algorithm> +#include <map> #include <sstream> #include <utility> @@ -14,7 +15,6 @@ #include "cmInstallType.h" #include "cmLocalGenerator.h" #include "cmSystemTools.h" -#include "cmake.h" cmInstallExportGenerator::cmInstallExportGenerator( cmExportSet* exportSet, const char* destination, @@ -56,7 +56,7 @@ void cmInstallExportGenerator::ComputeTempDir() // Choose a temporary directory in which to generate the import // files to be installed. this->TempDir = this->LocalGenerator->GetCurrentBinaryDirectory(); - this->TempDir += cmake::GetCMakeFilesDirectory(); + this->TempDir += "/CMakeFiles"; this->TempDir += "/Export"; if (this->Destination.empty()) { return; @@ -126,7 +126,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os) std::ostringstream e; e << "INSTALL(EXPORT) given unknown export \"" << ExportSet->GetName() << "\""; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return; } diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index 68e3f86d1..07094cb68 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -38,9 +38,7 @@ cmInstallFilesGenerator::cmInstallFilesGenerator( } } -cmInstallFilesGenerator::~cmInstallFilesGenerator() -{ -} +cmInstallFilesGenerator::~cmInstallFilesGenerator() = default; void cmInstallFilesGenerator::Compute(cmLocalGenerator* lg) { diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index 53ac71622..d139190a4 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -18,8 +18,19 @@ cmInstallGenerator::cmInstallGenerator( { } -cmInstallGenerator::~cmInstallGenerator() +cmInstallGenerator::~cmInstallGenerator() = default; + +bool cmInstallGenerator::HaveInstall() { + return true; +} + +void cmInstallGenerator::CheckCMP0082(bool& haveSubdirectoryInstall, + bool& haveInstallAfterSubdirectory) +{ + if (haveSubdirectoryInstall) { + haveInstallAfterSubdirectory = true; + } } void cmInstallGenerator::AddInstallRule( diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index fc1ce864f..9bd7ac318 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -21,8 +21,6 @@ class cmMakefile; */ class cmInstallGenerator : public cmScriptGenerator { - CM_DISABLE_COPY(cmInstallGenerator) - public: enum MessageLevel { @@ -38,6 +36,13 @@ public: bool exclude_from_all); ~cmInstallGenerator() override; + cmInstallGenerator(cmInstallGenerator const&) = delete; + cmInstallGenerator& operator=(cmInstallGenerator const&) = delete; + + virtual bool HaveInstall(); + virtual void CheckCMP0082(bool& haveSubdirectoryInstall, + bool& haveInstallAfterSubdirectory); + void AddInstallRule( std::ostream& os, std::string const& dest, cmInstallType type, std::vector<std::string> const& files, bool optional = false, diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx index f7e6e44a3..a513958ed 100644 --- a/Source/cmInstallScriptGenerator.cxx +++ b/Source/cmInstallScriptGenerator.cxx @@ -2,11 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallScriptGenerator.h" -#include "cmScriptGenerator.h" - #include <ostream> #include <vector> +#include "cmGeneratorExpression.h" +#include "cmLocalGenerator.h" +#include "cmMessageType.h" +#include "cmPolicies.h" +#include "cmScriptGenerator.h" + cmInstallScriptGenerator::cmInstallScriptGenerator(const char* script, bool code, const char* component, @@ -15,25 +19,69 @@ cmInstallScriptGenerator::cmInstallScriptGenerator(const char* script, MessageDefault, exclude_from_all) , Script(script) , Code(code) + , AllowGenex(false) { + // We need per-config actions if the script has generator expressions. + if (cmGeneratorExpression::Find(Script) != std::string::npos) { + this->ActionsPerConfig = true; + } } -cmInstallScriptGenerator::~cmInstallScriptGenerator() +cmInstallScriptGenerator::~cmInstallScriptGenerator() = default; + +void cmInstallScriptGenerator::Compute(cmLocalGenerator* lg) { + this->LocalGenerator = lg; + + if (this->ActionsPerConfig) { + switch (this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0087)) { + case cmPolicies::WARN: + this->LocalGenerator->IssueMessage( + MessageType::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(cmPolicies::CMP0087)); + CM_FALLTHROUGH; + case cmPolicies::OLD: + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + this->AllowGenex = true; + break; + } + } } -void cmInstallScriptGenerator::GenerateScript(std::ostream& os) +void cmInstallScriptGenerator::AddScriptInstallRule(std::ostream& os, + Indent indent, + std::string const& script) { - Indent indent; - std::string component_test = - this->CreateComponentTest(this->Component.c_str(), this->ExcludeFromAll); - os << indent << "if(" << component_test << ")\n"; - if (this->Code) { - os << indent.Next() << this->Script << "\n"; + os << indent << script << "\n"; } else { - os << indent.Next() << "include(\"" << this->Script << "\")\n"; + os << indent << "include(\"" << script << "\")\n"; } +} - os << indent << "endif()\n\n"; +void cmInstallScriptGenerator::GenerateScriptActions(std::ostream& os, + Indent indent) +{ + if (this->AllowGenex && this->ActionsPerConfig) { + this->cmInstallGenerator::GenerateScriptActions(os, indent); + } else { + this->AddScriptInstallRule(os, indent, this->Script); + } +} + +void cmInstallScriptGenerator::GenerateScriptForConfig( + std::ostream& os, const std::string& config, Indent indent) +{ + if (this->AllowGenex) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(this->Script); + this->AddScriptInstallRule(os, indent, + cge->Evaluate(this->LocalGenerator, config)); + } else { + this->AddScriptInstallRule(os, indent, this->Script); + } } diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h index fe0f7c6f1..05199d790 100644 --- a/Source/cmInstallScriptGenerator.h +++ b/Source/cmInstallScriptGenerator.h @@ -6,10 +6,13 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmInstallGenerator.h" +#include "cmScriptGenerator.h" #include <iosfwd> #include <string> +class cmLocalGenerator; + /** \class cmInstallScriptGenerator * \brief Generate target installation rules. */ @@ -20,10 +23,19 @@ public: const char* component, bool exclude_from_all); ~cmInstallScriptGenerator() override; + void Compute(cmLocalGenerator* lg) override; + protected: - void GenerateScript(std::ostream& os) override; + void GenerateScriptActions(std::ostream& os, Indent indent) override; + void GenerateScriptForConfig(std::ostream& os, const std::string& config, + Indent indent) override; + void AddScriptInstallRule(std::ostream& os, Indent indent, + std::string const& script); + std::string Script; bool Code; + cmLocalGenerator* LocalGenerator; + bool AllowGenex; }; #endif diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx new file mode 100644 index 000000000..ad7121f2e --- /dev/null +++ b/Source/cmInstallSubdirectoryGenerator.cxx @@ -0,0 +1,75 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmInstallSubdirectoryGenerator.h" + +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmPolicies.h" +#include "cmScriptGenerator.h" +#include "cmSystemTools.h" + +#include <sstream> +#include <vector> + +cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator( + cmMakefile* makefile, const char* binaryDirectory, bool excludeFromAll) + : cmInstallGenerator(nullptr, std::vector<std::string>(), nullptr, + MessageDefault, excludeFromAll) + , Makefile(makefile) + , BinaryDirectory(binaryDirectory) +{ +} + +cmInstallSubdirectoryGenerator::~cmInstallSubdirectoryGenerator() = default; + +bool cmInstallSubdirectoryGenerator::HaveInstall() +{ + for (auto generator : this->Makefile->GetInstallGenerators()) { + if (generator->HaveInstall()) { + return true; + } + } + + return false; +} + +void cmInstallSubdirectoryGenerator::CheckCMP0082( + bool& haveSubdirectoryInstall, bool& /*unused*/) +{ + if (this->HaveInstall()) { + haveSubdirectoryInstall = true; + } +} + +void cmInstallSubdirectoryGenerator::Compute(cmLocalGenerator* lg) +{ + this->LocalGenerator = lg; +} + +void cmInstallSubdirectoryGenerator::GenerateScript(std::ostream& os) +{ + if (!this->ExcludeFromAll) { + cmPolicies::PolicyStatus status = + this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0082); + switch (status) { + case cmPolicies::WARN: + case cmPolicies::OLD: + // OLD behavior is handled in cmLocalGenerator::GenerateInstallRules() + break; + + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: { + Indent indent; + std::string odir = this->BinaryDirectory; + cmSystemTools::ConvertToUnixSlashes(odir); + os << indent << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n" + << indent.Next() + << "# Include the install script for the subdirectory.\n" + << indent.Next() << "include(\"" << odir + << "/cmake_install.cmake\")\n" + << indent << "endif()\n\n"; + } break; + } + } +} diff --git a/Source/cmInstallSubdirectoryGenerator.h b/Source/cmInstallSubdirectoryGenerator.h new file mode 100644 index 000000000..35471dda0 --- /dev/null +++ b/Source/cmInstallSubdirectoryGenerator.h @@ -0,0 +1,41 @@ +/* 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 + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmInstallGenerator.h" + +#include <iosfwd> +#include <string> + +class cmLocalGenerator; +class cmMakefile; + +/** \class cmInstallSubdirectoryGenerator + * \brief Generate target installation rules. + */ +class cmInstallSubdirectoryGenerator : public cmInstallGenerator +{ +public: + cmInstallSubdirectoryGenerator(cmMakefile* makefile, + const char* binaryDirectory, + bool excludeFromAll); + ~cmInstallSubdirectoryGenerator() override; + + bool HaveInstall() override; + void CheckCMP0082(bool& haveSubdirectoryInstall, + bool& haveInstallAfterSubdirectory) override; + + void Compute(cmLocalGenerator* lg) override; + +protected: + void GenerateScript(std::ostream& os) override; + + cmMakefile* Makefile; + std::string BinaryDirectory; + cmLocalGenerator* LocalGenerator; +}; + +#endif diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index bf0217a6e..9d3a6bb60 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -15,47 +15,31 @@ #include "cmInstallType.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmake.h" cmInstallTargetGenerator::cmInstallTargetGenerator( - const std::string& targetName, const char* dest, bool implib, + std::string targetName, const char* dest, bool implib, const char* file_permissions, std::vector<std::string> const& configurations, const char* component, MessageLevel message, bool exclude_from_all, - bool optional) + bool optional, cmListFileBacktrace backtrace) : cmInstallGenerator(dest, configurations, component, message, exclude_from_all) - , TargetName(targetName) + , TargetName(std::move(targetName)) , Target(nullptr) , FilePermissions(file_permissions) , ImportLibrary(implib) , Optional(optional) + , Backtrace(std::move(backtrace)) { this->ActionsPerConfig = true; this->NamelinkMode = NamelinkModeNone; } -cmInstallTargetGenerator::~cmInstallTargetGenerator() -{ -} - -void cmInstallTargetGenerator::GenerateScript(std::ostream& os) -{ - // Warn if installing an exclude-from-all target. - if (this->Target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { - std::ostringstream msg; - msg << "WARNING: Target \"" << this->Target->GetName() - << "\" has EXCLUDE_FROM_ALL set and will not be built by default " - << "but an install rule has been provided for it. CMake does " - << "not define behavior for this case."; - cmSystemTools::Message(msg.str().c_str(), "Warning"); - } - - // Perform the main install script generation. - this->cmInstallGenerator::GenerateScript(os); -} +cmInstallTargetGenerator::~cmInstallTargetGenerator() = default; void cmInstallTargetGenerator::GenerateScriptForConfig( std::ostream& os, const std::string& config, Indent indent) @@ -90,7 +74,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( case cmStateEnums::GLOBAL_TARGET: case cmStateEnums::UNKNOWN_LIBRARY: this->Target->GetLocalGenerator()->IssueMessage( - cmake::INTERNAL_ERROR, + MessageType::INTERNAL_ERROR, "cmInstallTargetGenerator created with non-installable target."); return; } @@ -100,7 +84,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( if (this->Target->NeedRelinkBeforeInstall(config)) { fromDirConfig = this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory(); - fromDirConfig += cmake::GetCMakeFilesDirectory(); + fromDirConfig += "/CMakeFiles"; fromDirConfig += "/CMakeRelink.dir/"; } else { cmStateEnums::ArtifactType artifact = this->ImportLibrary @@ -221,16 +205,21 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( // and one for the primary artifact component (NamelinkModeSkip). // Historically this was not diagnosed and resulted in silent // installation of a framework to the LIBRARY destination. - // Retain that behavior. + // Retain that behavior and warn about the case. switch (this->NamelinkMode) { case NamelinkModeNone: // Normal case. break; case NamelinkModeOnly: - // Assume the NamelinkModeSkip instance will install. + // Assume the NamelinkModeSkip instance will warn and install. return; case NamelinkModeSkip: { - // Proceed to install in the LIBRARY destination for compatibility. + std::string e = "Target '" + this->Target->GetName() + + "' was changed to a FRAMEWORK sometime after install(). " + "This may result in the wrong install DESTINATION. " + "Set the FRAMEWORK property earlier."; + this->Target->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( + MessageType::AUTHOR_WARNING, e, this->GetBacktrace()); } break; } @@ -715,7 +704,7 @@ void cmInstallTargetGenerator::AddChrpathPatchRule( << "Therefore, runtime paths will not be changed when installing. " << "CMAKE_BUILD_WITH_INSTALL_RPATH may be used to work around" " this limitation."; - mf->IssueMessage(cmake::WARNING, msg.str()); + mf->IssueMessage(MessageType::WARNING, msg.str()); } else { // Note: These paths are kept unique to avoid // install_name_tool corruption. @@ -787,10 +776,22 @@ void cmInstallTargetGenerator::AddStripRule(std::ostream& os, Indent indent, return; } + std::string stripArgs; + + // macOS 'strip' is picky, executables need '-u -r' and dylibs need '-x'. + if (this->Target->Target->GetMakefile()->IsOn("APPLE")) { + if (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY || + this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) { + stripArgs = "-x "; + } else if (this->Target->GetType() == cmStateEnums::EXECUTABLE) { + stripArgs = "-u -r "; + } + } + os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n"; os << indent << " execute_process(COMMAND \"" << this->Target->Target->GetMakefile()->GetDefinition("CMAKE_STRIP") - << "\" \"" << toDestDirPath << "\")\n"; + << "\" " << stripArgs << "\"" << toDestDirPath << "\")\n"; os << indent << "endif()\n"; } diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index f6bec20b3..6df5b1a50 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmInstallGenerator.h" +#include "cmListFileCache.h" #include "cmScriptGenerator.h" #include <iosfwd> @@ -21,11 +22,12 @@ class cmLocalGenerator; class cmInstallTargetGenerator : public cmInstallGenerator { public: - cmInstallTargetGenerator(std::string const& targetName, const char* dest, - bool implib, const char* file_permissions, - std::vector<std::string> const& configurations, - const char* component, MessageLevel message, - bool exclude_from_all, bool optional); + cmInstallTargetGenerator( + std::string targetName, const char* dest, bool implib, + const char* file_permissions, + std::vector<std::string> const& configurations, const char* component, + MessageLevel message, bool exclude_from_all, bool optional, + cmListFileBacktrace backtrace = cmListFileBacktrace()); ~cmInstallTargetGenerator() override; /** Select the policy for installing shared library linkable name @@ -64,8 +66,9 @@ public: std::string GetDestination(std::string const& config) const; + cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; } + protected: - void GenerateScript(std::ostream& os) override; void GenerateScriptForConfig(std::ostream& os, const std::string& config, Indent indent) override; void GenerateScriptForConfigObjectLibrary(std::ostream& os, @@ -108,6 +111,7 @@ protected: NamelinkModeType NamelinkMode; bool ImportLibrary; bool Optional; + cmListFileBacktrace Backtrace; }; #endif diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index 0e0602981..537b4ecec 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -9,19 +9,14 @@ #include <utility> -cmInstalledFile::cmInstalledFile() - : NameExpression(nullptr) -{ -} +cmInstalledFile::cmInstalledFile() = default; cmInstalledFile::~cmInstalledFile() { delete NameExpression; } -cmInstalledFile::Property::Property() -{ -} +cmInstalledFile::Property::Property() = default; cmInstalledFile::Property::~Property() { diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h index 47a49590d..070b954e6 100644 --- a/Source/cmInstalledFile.h +++ b/Source/cmInstalledFile.h @@ -68,7 +68,7 @@ public: private: std::string Name; - cmCompiledGeneratorExpression* NameExpression; + cmCompiledGeneratorExpression* NameExpression = nullptr; PropertyMapType Properties; }; diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx index 4148894f3..d723cedb5 100644 --- a/Source/cmJsonObjects.cxx +++ b/Source/cmJsonObjects.cxx @@ -6,6 +6,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmInstallGenerator.h" +#include "cmInstallSubdirectoryGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmJsonObjectDictionary.h" #include "cmJsonObjects.h" @@ -13,6 +14,7 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmProperty.h" +#include "cmPropertyMap.h" #include "cmSourceFile.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -47,7 +49,7 @@ std::vector<std::string> getConfigurations(const cmake* cm) makefiles[0]->GetConfigurations(configurations); if (configurations.empty()) { - configurations.push_back(""); + configurations.emplace_back(); } return configurations; } @@ -290,10 +292,10 @@ static Json::Value DumpSourceFilesList( lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file); for (const auto& include : includes) { - fileData.IncludePathList.push_back( - std::make_pair(include, - target->IsSystemIncludeDirectory( - include, config, fileData.Language))); + fileData.IncludePathList.emplace_back( + include, + target->IsSystemIncludeDirectory(include, config, + fileData.Language)); } } @@ -321,7 +323,7 @@ static Json::Value DumpSourceFilesList( fileData.SetDefines(defines); } - fileData.IsGenerated = file->GetPropertyAsBool("GENERATED"); + fileData.IsGenerated = file->GetIsGenerated(); std::vector<std::string>& groupFileList = fileGroups[fileData]; groupFileList.push_back(file->GetFullPath()); } @@ -450,10 +452,9 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, const std::string& config) { cmLocalGenerator* lg = target->GetLocalGenerator(); - const cmState* state = lg->GetState(); const cmStateEnums::TargetType type = target->GetType(); - const std::string typeName = state->GetTargetTypeName(type); + const std::string typeName = cmState::GetTargetTypeName(type); Json::Value ttl = Json::arrayValue; ttl.append("EXECUTABLE"); @@ -577,10 +578,10 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, lg->GetTargetDefines(target, config, lang, defines); ld.SetDefines(defines); std::vector<std::string> includePathList; - lg->GetIncludeDirectories(includePathList, target, lang, config, true); + lg->GetIncludeDirectories(includePathList, target, lang, config); for (std::string const& i : includePathList) { - ld.IncludePathList.push_back( - std::make_pair(i, target->IsSystemIncludeDirectory(i, config, lang))); + ld.IncludePathList.emplace_back( + i, target->IsSystemIncludeDirectory(i, config, lang)); } } @@ -641,8 +642,13 @@ static Json::Value DumpProjectList(const cmake* cm, std::string const& config) // associated generators. bool hasInstallRule = false; for (const auto generator : projectIt.second) { - hasInstallRule = - generator->GetMakefile()->GetInstallGenerators().empty() == false; + for (const auto installGen : + generator->GetMakefile()->GetInstallGenerators()) { + if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(installGen)) { + hasInstallRule = true; + break; + } + } if (hasInstallRule) { break; diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx index 10425fdb7..785097745 100644 --- a/Source/cmLinkDirectoriesCommand.cxx +++ b/Source/cmLinkDirectoriesCommand.cxx @@ -7,9 +7,9 @@ #include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -59,7 +59,7 @@ void cmLinkDirectoriesCommand::AddLinkDir( switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0015)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015); - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); break; case cmPolicies::OLD: // OLD behavior does not convert @@ -67,7 +67,7 @@ void cmLinkDirectoriesCommand::AddLinkDir( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0015); - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior converts diff --git a/Source/cmLinkItem.cxx b/Source/cmLinkItem.cxx index 69b6821c1..9b03ad011 100644 --- a/Source/cmLinkItem.cxx +++ b/Source/cmLinkItem.cxx @@ -6,21 +6,17 @@ #include <utility> // IWYU pragma: keep -cmLinkItem::cmLinkItem() - : String() - , Target(nullptr) -{ -} +cmLinkItem::cmLinkItem() = default; -cmLinkItem::cmLinkItem(std::string const& n) - : String(n) - , Target(nullptr) +cmLinkItem::cmLinkItem(std::string n, cmListFileBacktrace bt) + : String(std::move(n)) + , Backtrace(std::move(bt)) { } -cmLinkItem::cmLinkItem(cmGeneratorTarget const* t) - : String() - , Target(t) +cmLinkItem::cmLinkItem(cmGeneratorTarget const* t, cmListFileBacktrace bt) + : Target(t) + , Backtrace(std::move(bt)) { } @@ -58,15 +54,11 @@ std::ostream& operator<<(std::ostream& os, cmLinkItem const& item) cmLinkImplItem::cmLinkImplItem() : cmLinkItem() - , Backtrace() - , FromGenex(false) { } -cmLinkImplItem::cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt, - bool fromGenex) +cmLinkImplItem::cmLinkImplItem(cmLinkItem item, bool fromGenex) : cmLinkItem(std::move(item)) - , Backtrace(bt) , FromGenex(fromGenex) { } diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index 74fd298e4..5b635b5b3 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -24,10 +24,11 @@ class cmLinkItem public: cmLinkItem(); - explicit cmLinkItem(std::string const& s); - explicit cmLinkItem(cmGeneratorTarget const* t); + cmLinkItem(std::string s, cmListFileBacktrace bt); + cmLinkItem(cmGeneratorTarget const* t, cmListFileBacktrace bt); std::string const& AsStr() const; - cmGeneratorTarget const* Target; + cmGeneratorTarget const* Target = nullptr; + cmListFileBacktrace Backtrace; friend bool operator<(cmLinkItem const& l, cmLinkItem const& r); friend bool operator==(cmLinkItem const& l, cmLinkItem const& r); friend std::ostream& operator<<(std::ostream& os, cmLinkItem const& item); @@ -37,10 +38,8 @@ class cmLinkImplItem : public cmLinkItem { public: cmLinkImplItem(); - cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt, - bool fromGenex); - cmListFileBacktrace Backtrace; - bool FromGenex; + cmLinkImplItem(cmLinkItem item, bool fromGenex); + bool FromGenex = false; }; /** The link implementation specifies the direct library @@ -71,36 +70,22 @@ struct cmLinkInterface : public cmLinkInterfaceLibraries // Number of repetitions of a strongly connected component of two // or more static libraries. - unsigned int Multiplicity; + unsigned int Multiplicity = 0; // Libraries listed for other configurations. // Needed only for OLD behavior of CMP0003. std::vector<cmLinkItem> WrongConfigLibraries; - bool ImplementationIsInterface; - - cmLinkInterface() - : Multiplicity(0) - , ImplementationIsInterface(false) - { - } + bool ImplementationIsInterface = false; }; struct cmOptionalLinkInterface : public cmLinkInterface { - cmOptionalLinkInterface() - : LibrariesDone(false) - , AllDone(false) - , Exists(false) - , HadHeadSensitiveCondition(false) - , ExplicitLibraries(nullptr) - { - } - bool LibrariesDone; - bool AllDone; - bool Exists; - bool HadHeadSensitiveCondition; - const char* ExplicitLibraries; + bool LibrariesDone = false; + bool AllDone = false; + bool Exists = false; + bool HadHeadSensitiveCondition = false; + const char* ExplicitLibraries = nullptr; }; struct cmHeadToLinkInterfaceMap @@ -117,15 +102,9 @@ struct cmLinkImplementation : public cmLinkImplementationLibraries // Cache link implementation computation from each configuration. struct cmOptionalLinkImplementation : public cmLinkImplementation { - cmOptionalLinkImplementation() - : LibrariesDone(false) - , LanguagesDone(false) - , HadHeadSensitiveCondition(false) - { - } - bool LibrariesDone; - bool LanguagesDone; - bool HadHeadSensitiveCondition; + bool LibrariesDone = false; + bool LanguagesDone = false; + bool HadHeadSensitiveCondition = false; }; /** Compute the link type to use for the given configuration. */ diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 7511fd21b..2a8bee6e5 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -11,6 +11,7 @@ #include "cmOutputConverter.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" +#include "cmSystemTools.h" cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) @@ -22,9 +23,7 @@ cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter, { } -cmLinkLineComputer::~cmLinkLineComputer() -{ -} +cmLinkLineComputer::~cmLinkLineComputer() = default; void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote) { @@ -46,9 +45,8 @@ std::string cmLinkLineComputer::ConvertToLinkReference( { std::string relLib = lib; - if (cmOutputConverter::ContainedInDirectory( - this->StateDir.GetCurrentBinary(), lib, this->StateDir)) { - relLib = cmOutputConverter::ForceToRelativePath( + if (this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), lib)) { + relLib = cmSystemTools::ForceToRelativePath( this->StateDir.GetCurrentBinary(), lib); } return relLib; diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h index a016358fa..2355c3270 100644 --- a/Source/cmLinkLineComputer.h +++ b/Source/cmLinkLineComputer.h @@ -16,13 +16,14 @@ class cmOutputConverter; class cmLinkLineComputer { - CM_DISABLE_COPY(cmLinkLineComputer) - public: cmLinkLineComputer(cmOutputConverter* outputConverter, cmStateDirectory const& stateDir); virtual ~cmLinkLineComputer(); + cmLinkLineComputer(cmLinkLineComputer const&) = delete; + cmLinkLineComputer& operator=(cmLinkLineComputer const&) = delete; + void SetUseWatcomQuote(bool useWatcomQuote); void SetForResponse(bool forResponse); void SetRelink(bool relink); diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index a93ec1271..211d03bd8 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -21,9 +21,7 @@ cmLinkLineDeviceComputer::cmLinkLineDeviceComputer( { } -cmLinkLineDeviceComputer::~cmLinkLineDeviceComputer() -{ -} +cmLinkLineDeviceComputer::~cmLinkLineDeviceComputer() = default; static bool cmLinkItemValidForDevice(std::string const& item) { @@ -36,6 +34,7 @@ static bool cmLinkItemValidForDevice(std::string const& item) // * '-lpthread' => pass-along // * '-pthread' => drop // * '-a' => drop + // * '-framework Name' (as one string) => drop return (!cmHasLiteralPrefix(item, "-") || // cmHasLiteralPrefix(item, "-l") || // cmHasLiteralPrefix(item, "-L") || // @@ -56,7 +55,13 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( typedef cmComputeLinkInformation::ItemVector ItemVector; ItemVector const& items = cli.GetItems(); std::string config = cli.GetConfig(); + bool skipItemAfterFramework = false; for (auto const& item : items) { + if (skipItemAfterFramework) { + skipItemAfterFramework = false; + continue; + } + if (item.Target) { bool skip = false; switch (item.Target->GetType()) { @@ -86,6 +91,11 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( out += this->ConvertToOutputFormat( this->ConvertToLinkReference(item.Value)); } + } else if (item.Value == "-framework") { + // This is the first part of '-framework Name' where the framework + // name is specified as a following item. Ignore both. + skipItemAfterFramework = true; + continue; } else if (cmLinkItemValidForDevice(item.Value)) { out += item.Value; } diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h index 81b48b3d4..cf66f6475 100644 --- a/Source/cmLinkLineDeviceComputer.h +++ b/Source/cmLinkLineDeviceComputer.h @@ -18,13 +18,15 @@ class cmStateDirectory; class cmLinkLineDeviceComputer : public cmLinkLineComputer { - CM_DISABLE_COPY(cmLinkLineDeviceComputer) - public: cmLinkLineDeviceComputer(cmOutputConverter* outputConverter, cmStateDirectory const& stateDir); ~cmLinkLineDeviceComputer() override; + cmLinkLineDeviceComputer(cmLinkLineDeviceComputer const&) = delete; + cmLinkLineDeviceComputer& operator=(cmLinkLineDeviceComputer const&) = + delete; + std::string ComputeLinkLibraries(cmComputeLinkInformation& cli, std::string const& stdLibString) override; @@ -34,13 +36,15 @@ public: class cmNinjaLinkLineDeviceComputer : public cmLinkLineDeviceComputer { - CM_DISABLE_COPY(cmNinjaLinkLineDeviceComputer) - public: cmNinjaLinkLineDeviceComputer(cmOutputConverter* outputConverter, cmStateDirectory const& stateDir, cmGlobalNinjaGenerator const* gg); + cmNinjaLinkLineDeviceComputer(cmNinjaLinkLineDeviceComputer const&) = delete; + cmNinjaLinkLineDeviceComputer& operator=( + cmNinjaLinkLineDeviceComputer const&) = delete; + std::string ConvertToLinkReference(std::string const& input) const override; private: diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h index 975f05240..099fb6d11 100644 --- a/Source/cmLinkedTree.h +++ b/Source/cmLinkedTree.h @@ -6,7 +6,6 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <assert.h> -#include <iterator> #include <vector> /** @@ -33,7 +32,7 @@ class cmLinkedTree typedef T& ReferenceType; public: - class iterator : public std::iterator<std::forward_iterator_tag, T> + class iterator { friend class cmLinkedTree; cmLinkedTree* Tree; diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index d7de2fa5b..297babfd8 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -12,14 +12,15 @@ #include <stdexcept> #include <stdio.h> #include <stdlib.h> // required for atoi +#include <utility> #include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmStringReplaceHelper.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -122,7 +123,7 @@ bool cmListCommand::GetList(std::vector<std::string>& list, warn += " List has value = ["; warn += listString; warn += "]."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, warn); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, warn); return true; } case cmPolicies::OLD: @@ -137,7 +138,7 @@ bool cmListCommand::GetList(std::vector<std::string>& list, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0007)); return false; } @@ -152,7 +153,7 @@ bool cmListCommand::HandleLengthCommand(std::vector<std::string> const& args) } const std::string& listName = args[1]; - const std::string& variableName = args[args.size() - 1]; + const std::string& variableName = args.back(); std::vector<std::string> varArgsExpanded; // do not check the return value here // if the list var is not found varArgsExpanded will have size 0 @@ -174,7 +175,7 @@ bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args) } const std::string& listName = args[1]; - const std::string& variableName = args[args.size() - 1]; + const std::string& variableName = args.back(); // expand the variable std::vector<std::string> varArgsExpanded; if (!this->GetList(varArgsExpanded, listName)) { @@ -243,7 +244,7 @@ bool cmListCommand::HandleFindCommand(std::vector<std::string> const& args) } const std::string& listName = args[1]; - const std::string& variableName = args[args.size() - 1]; + const std::string& variableName = args.back(); // expand the variable std::vector<std::string> varArgsExpanded; if (!this->GetList(varArgsExpanded, listName)) { @@ -346,8 +347,7 @@ bool cmListCommand::HandleRemoveItemCommand( // expand the variable std::vector<std::string> varArgsExpanded; if (!this->GetList(varArgsExpanded, listName)) { - this->SetError("sub-command REMOVE_ITEM requires list to be present."); - return false; + return true; } std::vector<std::string> remove(args.begin() + 2, args.end()); @@ -376,8 +376,7 @@ bool cmListCommand::HandleReverseCommand(std::vector<std::string> const& args) // expand the variable std::vector<std::string> varArgsExpanded; if (!this->GetList(varArgsExpanded, listName)) { - this->SetError("sub-command REVERSE requires list to be present."); - return false; + return true; } std::string value = cmJoin(cmReverseRange(varArgsExpanded), ";"); @@ -399,9 +398,7 @@ bool cmListCommand::HandleRemoveDuplicatesCommand( // expand the variable std::vector<std::string> varArgsExpanded; if (!this->GetList(varArgsExpanded, listName)) { - this->SetError( - "sub-command REMOVE_DUPLICATES requires list to be present."); - return false; + return true; } std::vector<std::string>::const_iterator argsEnd = @@ -429,7 +426,7 @@ public: class TransformSelector { public: - virtual ~TransformSelector() {} + virtual ~TransformSelector() = default; std::string Tag; @@ -583,7 +580,7 @@ private: class TransformAction { public: - virtual ~TransformAction() {} + virtual ~TransformAction() = default; virtual std::string Transform(const std::string& input) = 0; }; @@ -662,15 +659,19 @@ bool cmListCommand::HandleTransformCommand( // Transform: lambda function implementing the action struct ActionDescriptor { - ActionDescriptor(const std::string& name) - : Name(name) + ActionDescriptor(std::string name) + : Name(std::move(name)) { } - ActionDescriptor(const std::string& name, int arity, - const transform_type& transform) - : Name(name) + ActionDescriptor(std::string name, int arity, transform_type transform) + : Name(std::move(name)) , Arity(arity) +#if defined(__GNUC__) && __GNUC__ == 6 && defined(__aarch64__) + // std::function move constructor miscompiles on this architecture , Transform(transform) +#else + , Transform(std::move(transform)) +#endif { } @@ -1152,8 +1153,7 @@ bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args) // expand the variable std::vector<std::string> varArgsExpanded; if (!this->GetList(varArgsExpanded, listName)) { - this->SetError("sub-command SORT requires list to be present."); - return false; + return true; } if ((sortCompare == cmStringSorter::Compare::STRING) && @@ -1181,7 +1181,7 @@ bool cmListCommand::HandleSublistCommand(std::vector<std::string> const& args) } const std::string& listName = args[1]; - const std::string& variableName = args[args.size() - 1]; + const std::string& variableName = args.back(); // expand the variable std::vector<std::string> varArgsExpanded; @@ -1230,13 +1230,17 @@ bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args) const std::string& listName = args[1]; // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { - this->SetError("sub-command REMOVE_AT requires list to be present."); - return false; - } - // FIXME: Add policy to make non-existing lists an error like empty lists. - if (varArgsExpanded.empty()) { - this->SetError("REMOVE_AT given empty list"); + if (!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) { + std::ostringstream str; + str << "index: "; + for (size_t i = 1; i < args.size(); ++i) { + str << args[i]; + if (i != args.size() - 1) { + str << ", "; + } + } + str << " out of range (0, 0)"; + this->SetError(str.str()); return false; } @@ -1289,14 +1293,6 @@ bool cmListCommand::HandleFilterCommand(std::vector<std::string> const& args) return false; } - const std::string& listName = args[1]; - // expand the variable - std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { - this->SetError("sub-command FILTER requires list to be present."); - return false; - } - const std::string& op = args[2]; bool includeMatches; if (op == "INCLUDE") { @@ -1308,6 +1304,13 @@ bool cmListCommand::HandleFilterCommand(std::vector<std::string> const& args) return false; } + const std::string& listName = args[1]; + // expand the variable + std::vector<std::string> varArgsExpanded; + if (!this->GetList(varArgsExpanded, listName)) { + return true; + } + const std::string& mode = args[3]; if (mode == "REGEX") { if (args.size() != 5) { diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 4d7e1e2ad..f85511964 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -3,16 +3,16 @@ #include "cmListFileCache.h" #include "cmListFileLexer.h" +#include "cmMessageType.h" #include "cmMessenger.h" -#include "cmOutputConverter.h" #include "cmState.h" +#include "cmStateDirectory.h" #include "cmSystemTools.h" -#include "cmake.h" -#include <algorithm> #include <assert.h> #include <memory> #include <sstream> +#include <utility> cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=( std::string const& name) @@ -24,7 +24,7 @@ cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=( struct cmListFileParser { - cmListFileParser(cmListFile* lf, cmListFileBacktrace const& lfbt, + cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt, cmMessenger* messenger, const char* filename); ~cmListFileParser(); void IssueFileOpenError(std::string const& text) const; @@ -47,12 +47,11 @@ struct cmListFileParser } Separation; }; -cmListFileParser::cmListFileParser(cmListFile* lf, - cmListFileBacktrace const& lfbt, +cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt, cmMessenger* messenger, const char* filename) : ListFile(lf) - , Backtrace(lfbt) + , Backtrace(std::move(lfbt)) , Messenger(messenger) , FileName(filename) , Lexer(cmListFileLexer_New()) @@ -66,7 +65,8 @@ cmListFileParser::~cmListFileParser() void cmListFileParser::IssueFileOpenError(const std::string& text) const { - this->Messenger->IssueMessage(cmake::FATAL_ERROR, text, this->Backtrace); + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text, + this->Backtrace); } void cmListFileParser::IssueError(const std::string& text) const @@ -76,7 +76,7 @@ void cmListFileParser::IssueError(const std::string& text) const lfc.Line = cmListFileLexer_GetCurrentLine(this->Lexer); cmListFileBacktrace lfbt = this->Backtrace; lfbt = lfbt.Push(lfc); - this->Messenger->IssueMessage(cmake::FATAL_ERROR, text, lfbt); + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text, lfbt); cmSystemTools::SetFatalErrorOccured(); } @@ -193,8 +193,9 @@ bool cmListFileParser::ParseFunction(const char* name, long line) unsigned long lastLine; unsigned long parenDepth = 0; this->Separation = SeparationOkay; - while ((lastLine = cmListFileLexer_GetCurrentLine(this->Lexer), - token = cmListFileLexer_Scan(this->Lexer))) { + while ( + (static_cast<void>(lastLine = cmListFileLexer_GetCurrentLine(this->Lexer)), + token = cmListFileLexer_Scan(this->Lexer))) { if (token->type == cmListFileLexer_Token_Space || token->type == cmListFileLexer_Token_Newline) { this->Separation = SeparationOkay; @@ -254,7 +255,7 @@ bool cmListFileParser::ParseFunction(const char* name, long line) lfbt = lfbt.Push(lfc); error << "Parse error. Function missing ending \")\". " << "End of file reached."; - this->Messenger->IssueMessage(cmake::FATAL_ERROR, error.str(), lfbt); + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, error.str(), lfbt); return false; } @@ -279,10 +280,10 @@ bool cmListFileParser::AddArgument(cmListFileLexer_Token* token, << "Argument not separated from preceding token by whitespace."; /* clang-format on */ if (isError) { - this->Messenger->IssueMessage(cmake::FATAL_ERROR, m.str(), lfbt); + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, m.str(), lfbt); return false; } - this->Messenger->IssueMessage(cmake::AUTHOR_WARNING, m.str(), lfbt); + this->Messenger->IssueMessage(MessageType::AUTHOR_WARNING, m.str(), lfbt); return true; } @@ -389,9 +390,8 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) const } cmListFileContext lfc = this->TopEntry->Context; cmStateSnapshot bottom = this->GetBottom(); - cmOutputConverter converter(bottom); if (!bottom.GetState()->GetIsInTryCompile()) { - lfc.FilePath = converter.ConvertToRelativePath( + lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained( bottom.GetState()->GetSourceDirectory(), lfc.FilePath); } out << (lfc.Line ? " at " : " in ") << lfc; @@ -408,7 +408,6 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const bool first = true; cmStateSnapshot bottom = this->GetBottom(); - cmOutputConverter converter(bottom); for (Entry const* cur = this->TopEntry->Parent.get(); !cur->IsBottom(); cur = cur->Parent.get()) { if (cur->Context.Name.empty()) { @@ -422,7 +421,7 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const } cmListFileContext lfc = cur->Context; if (!bottom.GetState()->GetIsInTryCompile()) { - lfc.FilePath = converter.ConvertToRelativePath( + lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained( bottom.GetState()->GetSourceDirectory(), lfc.FilePath); } out << " " << lfc << "\n"; @@ -474,3 +473,21 @@ bool operator!=(const cmListFileContext& lhs, const cmListFileContext& rhs) { return !(lhs == rhs); } + +std::ostream& operator<<(std::ostream& os, BT<std::string> const& s) +{ + return os << s.Value; +} + +std::vector<BT<std::string>> ExpandListWithBacktrace( + std::string const& list, cmListFileBacktrace const& bt) +{ + std::vector<BT<std::string>> result; + std::vector<std::string> tmp; + cmSystemTools::ExpandListArgument(list, tmp); + result.reserve(tmp.size()); + for (std::string& i : tmp) { + result.emplace_back(std::move(i), bt); + } + return result; +} diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 3d3afdf9b..945741540 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -9,6 +9,7 @@ #include <memory> // IWYU pragma: keep #include <stddef.h> #include <string> +#include <utility> #include <vector> #include "cmStateSnapshot.h" @@ -28,15 +29,12 @@ struct cmCommandContext { std::string Lower; std::string Original; - cmCommandName() {} + cmCommandName() = default; cmCommandName(std::string const& name) { *this = name; } cmCommandName& operator=(std::string const& name); } Name; - long Line; - cmCommandContext() - : Line(0) - { - } + long Line = 0; + cmCommandContext() = default; cmCommandContext(const char* name, int line) : Name(name) , Line(line) @@ -52,14 +50,9 @@ struct cmListFileArgument Quoted, Bracket }; - cmListFileArgument() - : Value() - , Delim(Unquoted) - , Line(0) - { - } - cmListFileArgument(const std::string& v, Delimiter d, long line) - : Value(v) + cmListFileArgument() = default; + cmListFileArgument(std::string v, Delimiter d, long line) + : Value(std::move(v)) , Delim(d) , Line(line) { @@ -70,8 +63,8 @@ struct cmListFileArgument } bool operator!=(const cmListFileArgument& r) const { return !(*this == r); } std::string Value; - Delimiter Delim; - long Line; + Delimiter Delim = Unquoted; + long Line = 0; }; class cmListFileContext @@ -79,13 +72,7 @@ class cmListFileContext public: std::string Name; std::string FilePath; - long Line; - cmListFileContext() - : Name() - , FilePath() - , Line(0) - { - } + long Line = 0; static cmListFileContext FromCommandContext(cmCommandContext const& lfcc, std::string const& fileName) @@ -122,15 +109,6 @@ public: // indicated by the given valid snapshot. cmListFileBacktrace(cmStateSnapshot const& snapshot); - // Backtraces may be copied, moved, and assigned as values. - cmListFileBacktrace(cmListFileBacktrace const&) = default; - cmListFileBacktrace(cmListFileBacktrace&&) // NOLINT(clang-tidy) - noexcept = default; - cmListFileBacktrace& operator=(cmListFileBacktrace const&) = default; - cmListFileBacktrace& operator=(cmListFileBacktrace&&) // NOLINT(clang-tidy) - noexcept = default; - ~cmListFileBacktrace() = default; - cmStateSnapshot GetBottom() const; // Get a backtrace with the given file scope added to the top. @@ -169,6 +147,38 @@ private: cmListFileBacktrace(std::shared_ptr<Entry const> top); }; +// Wrap type T as a value with a backtrace. For purposes of +// ordering and equality comparison, only the original value is +// used. The backtrace is considered incidental. +template <typename T> +class BT +{ +public: + BT(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace()) + : Value(std::move(v)) + , Backtrace(std::move(bt)) + { + } + T Value; + cmListFileBacktrace Backtrace; + friend bool operator==(BT<T> const& l, BT<T> const& r) + { + return l.Value == r.Value; + } + friend bool operator<(BT<T> const& l, BT<T> const& r) + { + return l.Value < r.Value; + } + friend bool operator==(BT<T> const& l, T const& r) { return l.Value == r; } + friend bool operator==(T const& l, BT<T> const& r) { return l == r.Value; } +}; + +std::ostream& operator<<(std::ostream& os, BT<std::string> const& s); + +std::vector<BT<std::string>> ExpandListWithBacktrace( + std::string const& list, + cmListFileBacktrace const& bt = cmListFileBacktrace()); + struct cmListFile { bool ParseFile(const char* path, cmMessenger* messenger, diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index 7ce2c828f..75ad2a658 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -12,10 +12,9 @@ class cmGlobalGenerator; cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, - cmMakefile* mf, - std::string const& wd) + cmMakefile* mf, std::string wd) : cmLocalGenerator(gg, mf) - , WorkingDirectory(wd) + , WorkingDirectory(std::move(wd)) { // Store the configuration name that will be generated. if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { @@ -27,9 +26,7 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, } } -cmLocalCommonGenerator::~cmLocalCommonGenerator() -{ -} +cmLocalCommonGenerator::~cmLocalCommonGenerator() = default; std::string cmLocalCommonGenerator::GetTargetFortranFlags( cmGeneratorTarget const* target, std::string const& config) @@ -47,7 +44,7 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags( target->GetFortranModuleDirectory(this->WorkingDirectory); if (!mod_dir.empty()) { mod_dir = this->ConvertToOutputFormat( - this->ConvertToRelativePath(this->WorkingDirectory, mod_dir), + this->MaybeConvertToRelativePath(this->WorkingDirectory, mod_dir), cmOutputConverter::SHELL); } else { mod_dir = diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h index 7b8e6fe8a..abebbc2a7 100644 --- a/Source/cmLocalCommonGenerator.h +++ b/Source/cmLocalCommonGenerator.h @@ -22,7 +22,7 @@ class cmLocalCommonGenerator : public cmLocalGenerator { public: cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf, - std::string const& wd); + std::string wd); ~cmLocalCommonGenerator() override; std::string const& GetConfigName() { return this->ConfigName; } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 70307252e..7e1523456 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -65,6 +65,7 @@ static const char* ruleReplaceVars[] = { "CMAKE_CURRENT_BINARY_DIR", "CMAKE_RANLIB", "CMAKE_LINKER", + "CMAKE_MT", "CMAKE_CUDA_HOST_COMPILER", "CMAKE_CUDA_HOST_LINK_LAUNCHER", "CMAKE_CL_SHOWINCLUDES_PREFIX" @@ -164,7 +165,7 @@ cmLocalGenerator::~cmLocalGenerator() cmDeleteAll(this->OwnedImportedGeneratorTargets); } -void cmLocalGenerator::IssueMessage(cmake::MessageType t, +void cmLocalGenerator::IssueMessage(MessageType t, std::string const& text) const { this->GetCMakeInstance()->IssueMessage(t, text, this->DirectoryBacktrace); @@ -189,22 +190,23 @@ void cmLocalGenerator::ComputeObjectMaxPath() w << "CMAKE_OBJECT_PATH_MAX is set to " << pmax << ", which is less than the minimum of 128. " << "The value will be ignored."; - this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } else { std::ostringstream w; w << "CMAKE_OBJECT_PATH_MAX is set to \"" << plen << "\", which fails to parse as a positive integer. " << "The value will be ignored."; - this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } this->ObjectMaxPathViolations.clear(); } -void cmLocalGenerator::MoveSystemIncludesToEnd( - std::vector<std::string>& includeDirs, const std::string& config, - const std::string& lang, const cmGeneratorTarget* target) const +static void MoveSystemIncludesToEnd(std::vector<std::string>& includeDirs, + const std::string& config, + const std::string& lang, + const cmGeneratorTarget* target) { if (!target) { return; @@ -218,6 +220,24 @@ void cmLocalGenerator::MoveSystemIncludesToEnd( }); } +static void MoveSystemIncludesToEnd(std::vector<BT<std::string>>& includeDirs, + const std::string& config, + const std::string& lang, + const cmGeneratorTarget* target) +{ + if (!target) { + return; + } + + std::stable_sort(includeDirs.begin(), includeDirs.end(), + [target, &config, &lang](BT<std::string> const& a, + BT<std::string> const& b) { + return !target->IsSystemIncludeDirectory(a.Value, config, + lang) && + target->IsSystemIncludeDirectory(b.Value, config, lang); + }); +} + void cmLocalGenerator::TraceDependencies() { std::vector<std::string> configs; @@ -296,7 +316,7 @@ void cmLocalGenerator::GenerateTestFiles() for (cmStateSnapshot const& i : children) { // TODO: Use add_subdirectory instead? std::string outP = i.GetDirectory().GetCurrentBinary(); - outP = this->ConvertToRelativePath(parentBinDir, outP); + outP = this->MaybeConvertToRelativePath(parentBinDir, outP); outP = cmOutputConverter::EscapeForCMake(outP); fout << "subdirs(" << outP << ")" << std::endl; } @@ -517,31 +537,62 @@ void cmLocalGenerator::GenerateInstallRules() } // Ask each install generator to write its code. + cmPolicies::PolicyStatus status = this->GetPolicyStatus(cmPolicies::CMP0082); std::vector<cmInstallGenerator*> const& installers = this->Makefile->GetInstallGenerators(); - for (cmInstallGenerator* installer : installers) { - installer->Generate(fout, config, configurationTypes); + bool haveSubdirectoryInstall = false; + bool haveInstallAfterSubdirectory = false; + if (status == cmPolicies::WARN) { + for (cmInstallGenerator* installer : installers) { + installer->CheckCMP0082(haveSubdirectoryInstall, + haveInstallAfterSubdirectory); + installer->Generate(fout, config, configurationTypes); + } + } else { + for (cmInstallGenerator* installer : installers) { + installer->Generate(fout, config, configurationTypes); + } } // Write rules from old-style specification stored in targets. this->GenerateTargetInstallRules(fout, config, configurationTypes); // Include install scripts from subdirectories. - std::vector<cmStateSnapshot> children = - this->Makefile->GetStateSnapshot().GetChildren(); - if (!children.empty()) { - fout << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n"; - fout << " # Include the install script for each subdirectory.\n"; - for (cmStateSnapshot const& c : children) { - if (!c.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) { - std::string odir = c.GetDirectory().GetCurrentBinary(); - cmSystemTools::ConvertToUnixSlashes(odir); - fout << " include(\"" << odir << "/cmake_install.cmake\")" - << std::endl; + switch (status) { + case cmPolicies::WARN: + if (haveInstallAfterSubdirectory && + this->Makefile->PolicyOptionalWarningEnabled( + "CMAKE_POLICY_WARNING_CMP0082")) { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0082) << "\n"; + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } - } - fout << "\n"; - fout << "endif()\n\n"; + CM_FALLTHROUGH; + case cmPolicies::OLD: { + std::vector<cmStateSnapshot> children = + this->Makefile->GetStateSnapshot().GetChildren(); + if (!children.empty()) { + fout << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n"; + fout << " # Include the install script for each subdirectory.\n"; + for (cmStateSnapshot const& c : children) { + if (!c.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) { + std::string odir = c.GetDirectory().GetCurrentBinary(); + cmSystemTools::ConvertToUnixSlashes(odir); + fout << " include(\"" << odir << "/cmake_install.cmake\")" + << std::endl; + } + } + fout << "\n"; + fout << "endif()\n\n"; + } + } break; + + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // NEW behavior is handled in + // cmInstallSubdirectoryGenerator::GenerateScript() + break; } // Record the install manifest. @@ -676,7 +727,7 @@ std::string cmLocalGenerator::GetIncludeFlags( } std::vector<std::string> includes = includeDirs; - this->MoveSystemIncludesToEnd(includes, config, lang, target); + MoveSystemIncludesToEnd(includes, config, lang, target); OutputFormat shellFormat = forResponseFile ? RESPONSE : SHELL; std::ostringstream includeFlags; @@ -756,33 +807,23 @@ std::string cmLocalGenerator::GetIncludeFlags( } std::string includePath = this->ConvertToIncludeReference(i, shellFormat, forceFullPaths); - if (quotePaths && !includePath.empty() && includePath[0] != '\"') { + if (quotePaths && !includePath.empty() && includePath.front() != '\"') { includeFlags << "\""; } includeFlags << includePath; - if (quotePaths && !includePath.empty() && includePath[0] != '\"') { + if (quotePaths && !includePath.empty() && includePath.front() != '\"') { includeFlags << "\""; } includeFlags << sep; } std::string flags = includeFlags.str(); // remove trailing separators - if ((sep[0] != ' ') && !flags.empty() && flags[flags.size() - 1] == sep[0]) { - flags[flags.size() - 1] = ' '; + if ((sep[0] != ' ') && !flags.empty() && flags.back() == sep[0]) { + flags.back() = ' '; } return flags; } -void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines, - cmGeneratorTarget const* target, - const std::string& config, - const std::string& lang) const -{ - std::vector<std::string> targetDefines; - target->GetCompileDefinitions(targetDefines, config, lang); - this->AppendDefines(defines, targetDefines); -} - void cmLocalGenerator::AddCompileOptions(std::string& flags, cmGeneratorTarget* target, const std::string& lang, @@ -833,23 +874,34 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags, "on " "and be depended on by the link implementation." << std::endl; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } } this->AddCompilerRequirementFlag(flags, target, lang); } -void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, - cmGeneratorTarget const* target, - const std::string& lang, - const std::string& config, - bool stripImplicitDirs, - bool appendAllImplicitDirs) const +std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( + cmGeneratorTarget const* target, std::string const& lang, + std::string const& config, bool stripImplicitDirs, + bool appendAllImplicitDirs) const { + std::vector<BT<std::string>> result; // Do not repeat an include path. std::set<std::string> emitted; + auto emitDir = [&result, &emitted](std::string const& dir) { + if (emitted.insert(dir).second) { + result.emplace_back(dir); + } + }; + + auto emitBT = [&result, &emitted](BT<std::string> const& dir) { + if (emitted.insert(dir.Value).second) { + result.emplace_back(dir); + } + }; + // When automatic include directories are requested for a build then // include the source and binary directories at the beginning of the // include path to approximate include file behavior for an @@ -859,58 +911,90 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, // per-source-file include paths. if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR")) { // Current binary directory - { - std::string binDir = - this->StateSnapshot.GetDirectory().GetCurrentBinary(); - if (emitted.insert(binDir).second) { - dirs.push_back(std::move(binDir)); - } - } + emitDir(this->StateSnapshot.GetDirectory().GetCurrentBinary()); // Current source directory - { - std::string srcDir = - this->StateSnapshot.GetDirectory().GetCurrentSource(); - if (emitted.insert(srcDir).second) { - dirs.push_back(std::move(srcDir)); - } - } + emitDir(this->StateSnapshot.GetDirectory().GetCurrentSource()); } if (!target) { - return; + return result; + } + + // Standard include directories to be added unconditionally at the end. + // These are intended to simulate additional implicit include directories. + std::vector<std::string> userStandardDirs; + { + std::string key = "CMAKE_"; + key += lang; + key += "_STANDARD_INCLUDE_DIRECTORIES"; + std::string const value = this->Makefile->GetSafeDefinition(key); + cmSystemTools::ExpandListArgument(value, userStandardDirs); + for (std::string& usd : userStandardDirs) { + cmSystemTools::ConvertToUnixSlashes(usd); + } } // Implicit include directories std::vector<std::string> implicitDirs; + std::set<std::string> implicitSet; + // Include directories to be excluded as if they were implicit. + std::set<std::string> implicitExclude; { - std::string rootPath; - if (const char* sysrootCompile = - this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { - rootPath = sysrootCompile; - } else { - rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); - } + // Raw list of implicit include directories + // Start with "standard" directories that we unconditionally add below. + std::vector<std::string> impDirVec = userStandardDirs; // Load implicit include directories for this language. - std::string key = "CMAKE_"; - key += lang; - key += "_IMPLICIT_INCLUDE_DIRECTORIES"; - if (const char* value = this->Makefile->GetDefinition(key)) { - std::vector<std::string> impDirVec; - cmSystemTools::ExpandListArgument(value, impDirVec); - for (std::string const& i : impDirVec) { - { - std::string d = rootPath + i; - cmSystemTools::ConvertToUnixSlashes(d); - emitted.insert(std::move(d)); + // We ignore this for Fortran because: + // * There are no standard library headers to avoid overriding. + // * Compilers like gfortran do not search their own implicit include + // directories for modules ('.mod' files). + if (lang != "Fortran") { + std::string key = "CMAKE_"; + key += lang; + key += "_IMPLICIT_INCLUDE_DIRECTORIES"; + if (const char* value = this->Makefile->GetDefinition(key)) { + size_t const impDirVecOldSize = impDirVec.size(); + cmSystemTools::ExpandListArgument(value, impDirVec); + // FIXME: Use cmRange with 'advance()' when it supports non-const. + for (size_t i = impDirVecOldSize; i < impDirVec.size(); ++i) { + cmSystemTools::ConvertToUnixSlashes(impDirVec[i]); } - implicitDirs.push_back(i); + } + } + + // The Platform/UnixPaths module used to hard-code /usr/include for C, CXX, + // and CUDA in CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES, but those + // variables are now computed. On macOS the /usr/include directory is + // inside the platform SDK so the computed value does not contain it + // directly. In this case adding -I/usr/include can hide SDK headers so we + // must still exclude it. + if ((lang == "C" || lang == "CXX" || lang == "CUDA") && + std::find(impDirVec.begin(), impDirVec.end(), "/usr/include") == + impDirVec.end() && + std::find_if(impDirVec.begin(), impDirVec.end(), + [](std::string const& d) { + return cmHasLiteralSuffix(d, "/usr/include"); + }) != impDirVec.end()) { + // Only exclude this hard coded path for backwards compatibility. + implicitExclude.emplace("/usr/include"); + } + + for (std::string const& i : impDirVec) { + if (implicitSet.insert(i).second) { + implicitDirs.emplace_back(i); } } } + // Checks if this is not an excluded (implicit) include directory. + auto notExcluded = [&implicitSet, &implicitExclude](std::string const& dir) { + return ((implicitSet.find(dir) == implicitSet.end()) && + (implicitExclude.find(dir) == implicitExclude.end())); + }; + // Get the target-specific include directories. - std::vector<std::string> userDirs = + std::vector<BT<std::string>> userDirs = target->GetIncludeDirectories(config, lang); // Support putting all the in-project include directories first if @@ -918,63 +1002,82 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, if (this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")) { std::string const &topSourceDir = this->GetState()->GetSourceDirectory(), &topBinaryDir = this->GetState()->GetBinaryDirectory(); - for (std::string const& i : userDirs) { + for (BT<std::string> const& udr : userDirs) { // Emit this directory only if it is a subdirectory of the // top-level source or binary tree. - if (cmSystemTools::ComparePath(i, topSourceDir) || - cmSystemTools::ComparePath(i, topBinaryDir) || - cmSystemTools::IsSubDirectory(i, topSourceDir) || - cmSystemTools::IsSubDirectory(i, topBinaryDir)) { - if (emitted.insert(i).second) { - dirs.push_back(i); + if (cmSystemTools::ComparePath(udr.Value, topSourceDir) || + cmSystemTools::ComparePath(udr.Value, topBinaryDir) || + cmSystemTools::IsSubDirectory(udr.Value, topSourceDir) || + cmSystemTools::IsSubDirectory(udr.Value, topBinaryDir)) { + if (notExcluded(udr.Value)) { + emitBT(udr); } } } } - // Construct the final ordered include directory list. - for (std::string const& i : userDirs) { - if (emitted.insert(i).second) { - dirs.push_back(i); + // Emit remaining non implicit user direcories. + for (BT<std::string> const& udr : userDirs) { + if (notExcluded(udr.Value)) { + emitBT(udr); } } - this->MoveSystemIncludesToEnd(dirs, config, lang, target); + // Sort result + MoveSystemIncludesToEnd(result, config, lang, target); - // Add standard include directories for this language. - { - std::vector<std::string>::size_type const before = userDirs.size(); - { - std::string key = "CMAKE_"; - key += lang; - key += "_STANDARD_INCLUDE_DIRECTORIES"; - std::string const value = this->Makefile->GetSafeDefinition(key); - cmSystemTools::ExpandListArgument(value, userDirs); - } - for (std::vector<std::string>::iterator i = userDirs.begin() + before, - ie = userDirs.end(); - i != ie; ++i) { - cmSystemTools::ConvertToUnixSlashes(*i); - dirs.push_back(*i); - } + // Append standard include directories for this language. + userDirs.reserve(userDirs.size() + userStandardDirs.size()); + for (std::string& usd : userStandardDirs) { + emitDir(usd); + userDirs.emplace_back(std::move(usd)); } + // Append compiler implicit include directories if (!stripImplicitDirs) { - // Append only implicit directories that were requested by the user - for (std::string const& i : implicitDirs) { - if (std::find(userDirs.begin(), userDirs.end(), i) != userDirs.end()) { - dirs.push_back(i); + // Append implicit directories that were requested by the user only + for (BT<std::string> const& udr : userDirs) { + if (implicitSet.find(udr.Value) != implicitSet.end()) { + emitBT(udr); } } - // Append remaining implicit directories on demand + // Append remaining implicit directories (on demand) if (appendAllImplicitDirs) { - for (std::string const& i : implicitDirs) { - if (std::find(dirs.begin(), dirs.end(), i) == dirs.end()) { - dirs.push_back(i); - } + for (std::string& imd : implicitDirs) { + emitDir(imd); } } } + + return result; +} + +void cmLocalGenerator::GetIncludeDirectoriesImplicit( + std::vector<std::string>& dirs, cmGeneratorTarget const* target, + const std::string& lang, const std::string& config, bool stripImplicitDirs, + bool appendAllImplicitDirs) const +{ + std::vector<BT<std::string>> tmp = this->GetIncludeDirectoriesImplicit( + target, lang, config, stripImplicitDirs, appendAllImplicitDirs); + dirs.reserve(dirs.size() + tmp.size()); + for (BT<std::string>& v : tmp) { + dirs.emplace_back(std::move(v.Value)); + } +} + +std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectories( + cmGeneratorTarget const* target, std::string const& lang, + std::string const& config) const +{ + return this->GetIncludeDirectoriesImplicit(target, lang, config); +} + +void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, + cmGeneratorTarget const* target, + const std::string& lang, + const std::string& config) const +{ + this->GetIncludeDirectoriesImplicit(dirs, target, lang, config); } void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags, @@ -1143,6 +1246,8 @@ void cmLocalGenerator::GetTargetFlags( break; } + this->AppendPositionIndependentLinkerFlags(linkFlags, target, config, + linkLanguage); this->AppendIPOLinkerFlags(linkFlags, target, config, linkLanguage); } @@ -1231,13 +1336,29 @@ void cmLocalGenerator::GetTargetDefines(cmGeneratorTarget const* target, std::string const& lang, std::set<std::string>& defines) const { + std::set<BT<std::string>> tmp = this->GetTargetDefines(target, config, lang); + for (BT<std::string> const& v : tmp) { + defines.emplace(v.Value); + } +} + +std::set<BT<std::string>> cmLocalGenerator::GetTargetDefines( + cmGeneratorTarget const* target, std::string const& config, + std::string const& lang) const +{ + std::set<BT<std::string>> defines; + // Add the export symbol definition for shared library objects. - if (const char* exportMacro = target->GetExportMacro()) { - this->AppendDefines(defines, exportMacro); + if (const std::string* exportMacro = target->GetExportMacro()) { + this->AppendDefines(defines, *exportMacro); } // Add preprocessor definitions for this target and configuration. - this->AddCompileDefinitions(defines, target, config, lang); + std::vector<BT<std::string>> targetDefines = + target->GetCompileDefinitions(config, lang); + this->AppendDefines(defines, targetDefines); + + return defines; } std::string cmLocalGenerator::GetTargetFortranFlags( @@ -1311,7 +1432,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( "additional flags may be added to export symbols on all " "executables regardless of their ENABLE_EXPORTS property."; /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } CM_FALLTHROUGH; case cmPolicies::OLD: @@ -1321,7 +1442,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065)); CM_FALLTHROUGH; case cmPolicies::NEW: @@ -1594,7 +1715,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( << (ext ? "(with compiler extensions)" : "") << ", but CMake " "does not know the compile flags to use to enable it."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); } else { std::vector<std::string> optVec; cmSystemTools::ExpandListArgument(opt, optVec); @@ -1608,19 +1729,19 @@ void cmLocalGenerator::AddCompilerRequirementFlag( static std::map<std::string, std::vector<std::string>> langStdMap; if (langStdMap.empty()) { // Maintain sorted order, most recent first. - langStdMap["CXX"].push_back("20"); - langStdMap["CXX"].push_back("17"); - langStdMap["CXX"].push_back("14"); - langStdMap["CXX"].push_back("11"); - langStdMap["CXX"].push_back("98"); + 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["C"].push_back("11"); - langStdMap["C"].push_back("99"); - langStdMap["C"].push_back("90"); + langStdMap["C"].emplace_back("11"); + langStdMap["C"].emplace_back("99"); + langStdMap["C"].emplace_back("90"); - langStdMap["CUDA"].push_back("14"); - langStdMap["CUDA"].push_back("11"); - langStdMap["CUDA"].push_back("98"); + langStdMap["CUDA"].emplace_back("14"); + langStdMap["CUDA"].emplace_back("11"); + langStdMap["CUDA"].emplace_back("98"); } std::string standard(standardProp); @@ -1633,7 +1754,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( std::string e = lang + "_STANDARD is set to invalid value '" + standard + "'"; this->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, e, target->GetBacktrace()); + MessageType::FATAL_ERROR, e, target->GetBacktrace()); return; } @@ -1643,7 +1764,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( std::string e = "CMAKE_" + lang + "_STANDARD_DEFAULT is set to invalid value '" + std::string(defaultStd) + "'"; - this->IssueMessage(cmake::INTERNAL_ERROR, e); + this->IssueMessage(MessageType::INTERNAL_ERROR, e); return; } @@ -1710,7 +1831,7 @@ static void AddVisibilityCompileOption(std::string& flags, std::ostringstream e; e << "Target " << target->GetName() << " uses unsupported value \"" << prop << "\" for " << flagDefine << "."; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return; } std::string option = std::string(opt) + prop; @@ -1781,7 +1902,7 @@ void cmLocalGenerator::AddVisibilityPresetFlags( "For compatibility CMake is not honoring them for this target."; /* clang-format on */ target->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - cmake::AUTHOR_WARNING, w.str(), target->GetBacktrace()); + MessageType::AUTHOR_WARNING, w.str(), target->GetBacktrace()); } } @@ -1840,7 +1961,7 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared, << flagsVar << " was removed.\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0018); - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -1953,6 +2074,42 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, } } +void cmLocalGenerator::AppendPositionIndependentLinkerFlags( + std::string& flags, cmGeneratorTarget* target, const std::string& config, + const std::string& lang) +{ + // For now, only EXECUTABLE is concerned + if (target->GetType() != cmStateEnums::EXECUTABLE) { + return; + } + + const char* PICValue = target->GetLinkPIEProperty(config); + if (PICValue == nullptr) { + // POSITION_INDEPENDENT_CODE is not set + return; + } + + const std::string mode = cmSystemTools::IsOn(PICValue) ? "PIE" : "NO_PIE"; + + std::string supported = "CMAKE_" + lang + "_LINK_" + mode + "_SUPPORTED"; + if (cmSystemTools::IsOff(this->Makefile->GetDefinition(supported))) { + return; + } + + std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_" + mode; + + auto pieFlags = this->Makefile->GetSafeDefinition(name); + if (pieFlags.empty()) { + return; + } + + std::vector<std::string> flagsList; + cmSystemTools::ExpandListArgument(pieFlags, flagsList); + for (const auto& flag : flagsList) { + this->AppendFlagEscape(flags, flag); + } +} + void cmLocalGenerator::AppendCompileOptions(std::string& options, const char* options_list, const char* regex) const @@ -2018,7 +2175,7 @@ void cmLocalGenerator::AppendIncludeDirectories( << sourceFile.GetLocation().GetName() << "\":\n \"" << include << "\"\n"; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -2035,26 +2192,34 @@ void cmLocalGenerator::AppendIncludeDirectories( } void cmLocalGenerator::AppendDefines(std::set<std::string>& defines, - const char* defines_list) const + std::string const& defines_list) const +{ + std::set<BT<std::string>> tmp; + this->AppendDefines(tmp, ExpandListWithBacktrace(defines_list)); + for (BT<std::string> const& i : tmp) { + defines.emplace(i.Value); + } +} + +void cmLocalGenerator::AppendDefines(std::set<BT<std::string>>& defines, + std::string const& defines_list) const { // Short-circuit if there are no definitions. - if (!defines_list) { + if (defines_list.empty()) { return; } // Expand the list of definitions. - std::vector<std::string> defines_vec; - cmSystemTools::ExpandListArgument(defines_list, defines_vec); - this->AppendDefines(defines, defines_vec); + this->AppendDefines(defines, ExpandListWithBacktrace(defines_list)); } void cmLocalGenerator::AppendDefines( - std::set<std::string>& defines, - const std::vector<std::string>& defines_vec) const + std::set<BT<std::string>>& defines, + const std::vector<BT<std::string>>& defines_vec) const { - for (std::string const& d : defines_vec) { + for (BT<std::string> const& d : defines_vec) { // Skip unsupported definitions. - if (!this->CheckDefinition(d)) { + if (!this->CheckDefinition(d.Value)) { continue; } defines.insert(d); @@ -2174,7 +2339,7 @@ std::string cmLocalGenerator::ConstructComment( std::string currentBinaryDir = this->GetCurrentBinaryDirectory(); for (std::string const& o : ccg.GetOutputs()) { comment += sep; - comment += this->ConvertToRelativePath(currentBinaryDir, o); + comment += this->MaybeConvertToRelativePath(currentBinaryDir, o); sep = ", "; } return comment; @@ -2380,7 +2545,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName( << "cannot be safely placed under this directory. " << "The build may not work correctly."; /* clang-format on */ - this->IssueMessage(cmake::WARNING, m.str()); + this->IssueMessage(MessageType::WARNING, m.str()); } } #else @@ -2431,15 +2596,15 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( std::string const& fullPath = source.GetFullPath(); // Try referencing the source relative to the source tree. - std::string relFromSource = - this->ConvertToRelativePath(this->GetCurrentSourceDirectory(), fullPath); + std::string relFromSource = this->MaybeConvertToRelativePath( + this->GetCurrentSourceDirectory(), fullPath); assert(!relFromSource.empty()); bool relSource = !cmSystemTools::FileIsFullPath(relFromSource); bool subSource = relSource && relFromSource[0] != '.'; // Try referencing the source relative to the binary tree. - std::string relFromBinary = - this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), fullPath); + std::string relFromBinary = this->MaybeConvertToRelativePath( + this->GetCurrentBinaryDirectory(), fullPath); assert(!relFromBinary.empty()); bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary); bool subBinary = relBinary && relFromBinary[0] != '.'; @@ -2538,6 +2703,13 @@ std::string const& cmLocalGenerator::GetCurrentSourceDirectory() const return this->StateSnapshot.GetDirectory().GetCurrentSource(); } +std::string cmLocalGenerator::MaybeConvertToRelativePath( + std::string const& local_path, std::string const& remote_path) const +{ + return this->StateSnapshot.GetDirectory().ConvertToRelPathIfNotContained( + local_path, remote_path); +} + std::string cmLocalGenerator::GetTargetDirectory( const cmGeneratorTarget* /*unused*/) const { @@ -2624,7 +2796,7 @@ bool cmLocalGenerator::CheckDefinition(std::string const& define) const << "CMake is dropping a preprocessor definition: " << define << "\n" << "Consider defining the macro in a (configured) header file.\n"; /* clang-format on */ - cmSystemTools::Message(e.str().c_str()); + cmSystemTools::Message(e.str()); return false; } } @@ -2639,7 +2811,7 @@ bool cmLocalGenerator::CheckDefinition(std::string const& define) const << "CMake is dropping a preprocessor definition: " << define << "\n" << "Consider defining the macro in a (configured) header file.\n"; /* clang-format on */ - cmSystemTools::Message(e.str().c_str()); + cmSystemTools::Message(e.str()); return false; } @@ -2663,7 +2835,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target, const char* in = target->GetProperty("MACOSX_BUNDLE_INFO_PLIST"); std::string inFile = (in && *in) ? in : "MacOSXBundleInfo.plist.in"; if (!cmSystemTools::FileIsFullPath(inFile)) { - std::string inMod = this->Makefile->GetModulesFile(inFile.c_str()); + std::string inMod = this->Makefile->GetModulesFile(inFile); if (!inMod.empty()) { inFile = inMod; } @@ -2672,7 +2844,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target, std::ostringstream e; e << "Target " << target->GetName() << " Info.plist template \"" << inFile << "\" could not be found."; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return; } @@ -2701,7 +2873,7 @@ void cmLocalGenerator::GenerateFrameworkInfoPList( const char* in = target->GetProperty("MACOSX_FRAMEWORK_INFO_PLIST"); std::string inFile = (in && *in) ? in : "MacOSXFrameworkInfo.plist.in"; if (!cmSystemTools::FileIsFullPath(inFile)) { - std::string inMod = this->Makefile->GetModulesFile(inFile.c_str()); + std::string inMod = this->Makefile->GetModulesFile(inFile); if (!inMod.empty()) { inFile = inMod; } @@ -2710,7 +2882,7 @@ void cmLocalGenerator::GenerateFrameworkInfoPList( std::ostringstream e; e << "Target " << target->GetName() << " Info.plist template \"" << inFile << "\" could not be found."; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return; } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 58b776225..f9839f6c1 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -14,10 +14,10 @@ #include <vector> #include "cmListFileCache.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmStateSnapshot.h" -#include "cmake.h" class cmComputeLinkInformation; class cmCustomCommandGenerator; @@ -28,6 +28,7 @@ class cmMakefile; class cmRulePlaceholderExpander; class cmSourceFile; class cmState; +class cmake; /** \class cmLocalGenerator * \brief Create required build files for a directory. @@ -126,6 +127,10 @@ public: void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, const std::string& config, const std::string& lang); + void AppendPositionIndependentLinkerFlags(std::string& flags, + cmGeneratorTarget* target, + const std::string& config, + const std::string& lang); ///! Get the include flags for the current makefile and language std::string GetIncludeFlags(const std::vector<std::string>& includes, cmGeneratorTarget* target, @@ -169,14 +174,11 @@ public: * command line. */ void AppendDefines(std::set<std::string>& defines, - const char* defines_list) const; - void AppendDefines(std::set<std::string>& defines, - std::string const& defines_list) const - { - this->AppendDefines(defines, defines_list.c_str()); - } - void AppendDefines(std::set<std::string>& defines, - const std::vector<std::string>& defines_vec) const; + std::string const& defines_list) const; + void AppendDefines(std::set<BT<std::string>>& defines, + std::string const& defines_list) const; + void AppendDefines(std::set<BT<std::string>>& defines, + const std::vector<BT<std::string>>& defines_vec) const; /** * Encode a list of compile options for the compiler @@ -231,30 +233,54 @@ public: virtual void ClearDependencies(cmMakefile* /* mf */, bool /* verbose */) {} /** Called from command-line hook to update dependencies. */ - virtual bool UpdateDependencies(const char* /* tgtInfo */, bool /*verbose*/, - bool /*color*/) + virtual bool UpdateDependencies(const std::string& /* tgtInfo */, + bool /*verbose*/, bool /*color*/) { return true; } - /** @brief Get the include directories for the current makefile and language. + /** @brief Get the include directories for the current makefile and language + * and optional the compiler implicit include directories. + * * @arg stripImplicitDirs Strip all directories found in * CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES from the result. * @arg appendAllImplicitDirs Append all directories found in * CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES to the result. */ + std::vector<BT<std::string>> GetIncludeDirectoriesImplicit( + cmGeneratorTarget const* target, std::string const& lang = "C", + std::string const& config = "", bool stripImplicitDirs = true, + bool appendAllImplicitDirs = false) const; + + /** @brief Get the include directories for the current makefile and language + * and optional the compiler implicit include directories. + * + * @arg dirs Directories are appended to this list + */ + void GetIncludeDirectoriesImplicit(std::vector<std::string>& dirs, + cmGeneratorTarget const* target, + const std::string& lang = "C", + const std::string& config = "", + bool stripImplicitDirs = true, + bool appendAllImplicitDirs = false) const; + + /** @brief Get the include directories for the current makefile and language. + * @arg dirs Include directories are appended to this list + */ void GetIncludeDirectories(std::vector<std::string>& dirs, cmGeneratorTarget const* target, const std::string& lang = "C", - const std::string& config = "", - bool stripImplicitDirs = true, - bool appendAllImplicitDirs = false) const; + const std::string& config = "") const; + + /** @brief Get the include directories for the current makefile and language. + * @return The include directory list + */ + std::vector<BT<std::string>> GetIncludeDirectories( + cmGeneratorTarget const* target, std::string const& lang = "C", + std::string const& config = "") const; + void AddCompileOptions(std::string& flags, cmGeneratorTarget* target, const std::string& lang, const std::string& config); - void AddCompileDefinitions(std::set<std::string>& defines, - cmGeneratorTarget const* target, - const std::string& config, - const std::string& lang) const; std::string GetProjectName() const; @@ -300,6 +326,16 @@ public: std::string const& GetCurrentSourceDirectory() const; /** + * Convert the given remote path to a relative path with respect to + * the given local path. Both paths must use forward slashes and not + * already be escaped or quoted. + * The conversion is skipped if the paths are not both in the source + * or both in the binary tree. + */ + std::string MaybeConvertToRelativePath(std::string const& local_path, + std::string const& remote_path) const; + + /** * Generate a macOS application bundle Info.plist file. */ void GenerateAppleInfoPList(cmGeneratorTarget* target, @@ -336,6 +372,9 @@ public: void GetTargetDefines(cmGeneratorTarget const* target, std::string const& config, std::string const& lang, std::set<std::string>& defines) const; + std::set<BT<std::string>> GetTargetDefines(cmGeneratorTarget const* target, + std::string const& config, + std::string const& lang) const; void GetTargetCompileFlags(cmGeneratorTarget* target, std::string const& config, std::string const& lang, std::string& flags); @@ -355,7 +394,7 @@ public: bool IsMinGWMake() const; bool IsNMake() const; - void IssueMessage(cmake::MessageType t, std::string const& text) const; + void IssueMessage(MessageType t, std::string const& text) const; void CreateEvaluationFileOutputs(const std::string& config); void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles); @@ -418,10 +457,6 @@ private: int targetType); void ComputeObjectMaxPath(); - void MoveSystemIncludesToEnd(std::vector<std::string>& includeDirs, - const std::string& config, - const std::string& lang, - cmGeneratorTarget const* target) const; }; #if defined(CMAKE_BUILD_WITH_CMAKE) diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx index ab6774e00..125e8b530 100644 --- a/Source/cmLocalGhsMultiGenerator.cxx +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -7,6 +7,7 @@ #include "cmGhsMultiTargetGenerator.h" #include "cmGlobalGhsMultiGenerator.h" #include "cmMakefile.h" +#include "cmSourceFile.h" cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator(cmGlobalGenerator* gg, cmMakefile* mf) @@ -18,16 +19,82 @@ cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator() { } +std::string cmLocalGhsMultiGenerator::GetTargetDirectory( + cmGeneratorTarget const* target) const +{ + std::string dir; + dir += target->GetName(); + dir += ".dir"; + 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() { - const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets(); + std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets(); + for (auto& t : remaining) { + if (t) { + GenerateTargetsDepthFirst(t, remaining); + } + } +} + +void cmLocalGhsMultiGenerator::ComputeObjectFilenames( + std::map<cmSourceFile const*, std::string>& mapping, + cmGeneratorTarget const* gt) +{ + std::string dir_max; + dir_max += this->GetCurrentBinaryDirectory(); + dir_max += "/"; + dir_max += this->GetTargetDirectory(gt); + dir_max += "/"; + + // Count the number of object files with each name. Note that + // filesystem may not be case sensitive. + std::map<std::string, int> counts; + + for (auto const& si : mapping) { + cmSourceFile const* sf = si.first; + std::string objectNameLower = cmSystemTools::LowerCase( + cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())); + objectNameLower += this->GlobalGenerator->GetLanguageOutputExtension(*sf); + counts[objectNameLower] += 1; + } + + // For all source files producing duplicate names we need unique + // object name computation. + for (auto& si : mapping) { + cmSourceFile const* sf = si.first; + std::string objectName = + cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()); + objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf); - for (std::vector<cmGeneratorTarget*>::const_iterator l = tgts.begin(); - l != tgts.end(); ++l) { - if ((*l)->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - continue; + if (counts[cmSystemTools::LowerCase(objectName)] > 1) { + const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf); + bool keptSourceExtension; + objectName = this->GetObjectFileNameWithoutTarget(*sf, dir_max, + &keptSourceExtension); + cmsys::SystemTools::ReplaceString(objectName, "/", "_"); } - cmGhsMultiTargetGenerator tg(*l); - tg.Generate(); + si.second = objectName; } } diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h index aa842d74b..d5bec4200 100644 --- a/Source/cmLocalGhsMultiGenerator.h +++ b/Source/cmLocalGhsMultiGenerator.h @@ -24,6 +24,17 @@ public: * Generate the makefile for this directory. */ virtual void Generate(); + + std::string GetTargetDirectory( + cmGeneratorTarget const* target) const override; + + 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 eb3147880..c0afc2542 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -17,6 +17,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmGlobalNinjaGenerator.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmNinjaTargetGenerator.h" #include "cmRulePlaceholderExpander.h" @@ -40,21 +41,18 @@ cmRulePlaceholderExpander* cmLocalNinjaGenerator::CreateRulePlaceholderExpander() const { cmRulePlaceholderExpander* ret = - new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings, - this->CompilerSysroot, this->LinkerSysroot); + this->cmLocalGenerator::CreateRulePlaceholderExpander(); ret->SetTargetImpLib("$TARGET_IMPLIB"); return ret; } -cmLocalNinjaGenerator::~cmLocalNinjaGenerator() -{ -} +cmLocalNinjaGenerator::~cmLocalNinjaGenerator() = default; void cmLocalNinjaGenerator::Generate() { // Compute the path to use when referencing the current output // directory from the top output directory. - this->HomeRelativeOutputPath = this->ConvertToRelativePath( + this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath( this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); if (this->HomeRelativeOutputPath == ".") { this->HomeRelativeOutputPath.clear(); @@ -90,9 +88,7 @@ void cmLocalNinjaGenerator::Generate() if (tg) { tg->Generate(); // Add the target to "all" if required. - if (!this->GetGlobalNinjaGenerator()->IsExcluded( - this->GetGlobalNinjaGenerator()->GetLocalGenerators()[0], - target)) { + if (!this->GetGlobalNinjaGenerator()->IsExcluded(target)) { this->GetGlobalNinjaGenerator()->AddDependencyToAll(target); } delete tg; @@ -106,7 +102,7 @@ void cmLocalNinjaGenerator::Generate() std::string cmLocalNinjaGenerator::GetTargetDirectory( cmGeneratorTarget const* target) const { - std::string dir = cmake::GetCMakeFilesDirectoryPostSlash(); + std::string dir = "CMakeFiles/"; dir += target->GetName(); #if defined(__VMS) dir += "_dir"; @@ -141,7 +137,8 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference( format); } return this->ConvertToOutputFormat( - this->ConvertToRelativePath(this->GetBinaryDirectory(), path), format); + this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), path), + format); } // Private methods. @@ -188,13 +185,12 @@ void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os) void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) { // Default required version - std::string requiredVersion = - this->GetGlobalNinjaGenerator()->RequiredNinjaVersion(); + std::string requiredVersion = cmGlobalNinjaGenerator::RequiredNinjaVersion(); // Ninja generator uses the 'console' pool if available (>= 1.5) if (this->GetGlobalNinjaGenerator()->SupportsConsolePool()) { requiredVersion = - this->GetGlobalNinjaGenerator()->RequiredNinjaVersionForConsolePool(); + cmGlobalNinjaGenerator::RequiredNinjaVersionForConsolePool(); } // The Ninja generator writes rules which require support for restat @@ -204,7 +200,7 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) !this->GetGlobalNinjaGenerator()->GlobalSettingIsOn( "CMAKE_SUPPRESS_REGENERATION")) { requiredVersion = - this->GetGlobalNinjaGenerator()->RequiredNinjaVersionForManifestRestat(); + cmGlobalNinjaGenerator::RequiredNinjaVersionForManifestRestat(); } cmGlobalNinjaGenerator::WriteComment( @@ -306,7 +302,7 @@ std::string cmLocalNinjaGenerator::WriteCommandScript( scriptPath = target->GetSupportDirectory(); } else { scriptPath = this->GetCurrentBinaryDirectory(); - scriptPath += cmake::GetCMakeFilesDirectory(); + scriptPath += "/CMakeFiles"; } cmSystemTools::MakeDirectory(scriptPath); scriptPath += '/'; @@ -319,7 +315,10 @@ std::string cmLocalNinjaGenerator::WriteCommandScript( cmsys::ofstream script(scriptPath.c_str()); -#ifndef _WIN32 +#ifdef _WIN32 + script << "@echo off\n"; + int line = 1; +#else script << "set -e\n\n"; #endif @@ -330,12 +329,22 @@ std::string cmLocalNinjaGenerator::WriteCommandScript( // for the raw shell script. cmSystemTools::ReplaceString(cmd, "$$", "$"); #ifdef _WIN32 - script << cmd << " || exit /b" << '\n'; + script << cmd << " || (set FAIL_LINE=" << ++line << "& goto :ABORT)" + << '\n'; #else script << cmd << '\n'; #endif } +#ifdef _WIN32 + script << "goto :EOF\n\n" + ":ABORT\n" + "set ERROR_CODE=%ERRORLEVEL%\n" + "echo Batch file failed at line %FAIL_LINE% " + "with errorcode %ERRORLEVEL%\n" + "exit /b %ERROR_CODE%"; +#endif + return scriptPath; } @@ -572,8 +581,8 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( if (!outputs.empty()) { output = outputs[0]; if (ccg.GetWorkingDirectory().empty()) { - output = - this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), output); + output = this->MaybeConvertToRelativePath( + this->GetCurrentBinaryDirectory(), output); } output = this->ConvertToOutputFormat(output, cmOutputConverter::SHELL); } diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 4d19b3acb..7eb4a03d5 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -17,6 +17,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmGlobalUnixMakefileGenerator3.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMakefileTargetGenerator.h" @@ -97,9 +98,7 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3( this->BorlandMakeCurlyHack = false; } -cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3() -{ -} +cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3() = default; void cmLocalUnixMakefileGenerator3::Generate() { @@ -247,8 +246,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() for (auto& localObjectFile : localObjectFiles) { // Add a convenience rule for building the object file. this->WriteObjectConvenienceRule( - ruleFileStream, "target to build an object file", - localObjectFile.first.c_str(), localObjectFile.second); + ruleFileStream, "target to build an object file", localObjectFile.first, + localObjectFile.second); // Check whether preprocessing and assembly rules make sense. // They make sense only for C and C++ sources. @@ -270,9 +269,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() if (lang_has_preprocessor && do_preprocess_rules) { std::string::size_type dot_pos = localObjectFile.first.rfind("."); std::string base = localObjectFile.first.substr(0, dot_pos); - this->WriteObjectConvenienceRule( - ruleFileStream, "target to preprocess a source file", - (base + ".i").c_str(), localObjectFile.second); + this->WriteObjectConvenienceRule(ruleFileStream, + "target to preprocess a source file", + (base + ".i"), localObjectFile.second); localObjectFile.second.HasPreprocessRule = true; } @@ -281,7 +280,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() std::string base = localObjectFile.first.substr(0, dot_pos); this->WriteObjectConvenienceRule( ruleFileStream, "target to generate assembly for a file", - (base + ".s").c_str(), localObjectFile.second); + (base + ".s"), localObjectFile.second); localObjectFile.second.HasAssembleRule = true; } } @@ -297,7 +296,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() } void cmLocalUnixMakefileGenerator3::WriteObjectConvenienceRule( - std::ostream& ruleFileStream, const char* comment, const char* output, + std::ostream& ruleFileStream, const char* comment, const std::string& output, LocalObjectInfo const& info) { // If the rule includes the source file extension then create a @@ -317,7 +316,7 @@ void cmLocalUnixMakefileGenerator3::WriteObjectConvenienceRule( // Add a rule to drive the rule below. std::vector<std::string> depends; - depends.push_back(output); + depends.emplace_back(output); std::vector<std::string> no_commands; this->WriteMakeRule(ruleFileStream, nullptr, outNoExt, depends, no_commands, true, true); @@ -333,7 +332,7 @@ void cmLocalUnixMakefileGenerator3::WriteObjectConvenienceRule( targetName += "/"; targetName += output; commands.push_back( - this->GetRecursiveMakeCall(tgtMakefileName.c_str(), targetName)); + this->GetRecursiveMakeCall(tgtMakefileName, targetName)); } this->CreateCDCommand(commands, this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); @@ -370,10 +369,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( depends.clear(); // Build the target for this pass. - std::string makefile2 = cmake::GetCMakeFilesDirectoryPostSlash(); + std::string makefile2 = "CMakeFiles/"; makefile2 += "Makefile2"; - commands.push_back( - this->GetRecursiveMakeCall(makefile2.c_str(), localName)); + commands.push_back(this->GetRecursiveMakeCall(makefile2, localName)); this->CreateCDCommand(commands, this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); this->WriteMakeRule(ruleFileStream, "Convenience name for target.", @@ -398,7 +396,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( depends.clear(); commands.clear(); commands.push_back( - this->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName)); + this->GetRecursiveMakeCall(makefileName, makeTargetName)); this->CreateCDCommand(commands, this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); this->WriteMakeRule(ruleFileStream, "fast build rule for target.", @@ -414,7 +412,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( depends.clear(); commands.clear(); commands.push_back( - this->GetRecursiveMakeCall(makefile2.c_str(), makeTargetName)); + this->GetRecursiveMakeCall(makefile2, makeTargetName)); this->CreateCDCommand(commands, this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); this->WriteMakeRule(ruleFileStream, @@ -428,7 +426,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile() { std::string infoFileName = this->GetCurrentBinaryDirectory(); - infoFileName += cmake::GetCMakeFilesDirectory(); + infoFileName += "/CMakeFiles"; infoFileName += "/CMakeDirectoryInformation.cmake"; // Open the output file. @@ -469,12 +467,12 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile() << "# The C and CXX include file regular expressions for " << "this directory.\n"; infoFileStream << "set(CMAKE_C_INCLUDE_REGEX_SCAN "; - this->WriteCMakeArgument(infoFileStream, - this->Makefile->GetIncludeRegularExpression()); + cmLocalUnixMakefileGenerator3::WriteCMakeArgument( + infoFileStream, this->Makefile->GetIncludeRegularExpression()); infoFileStream << ")\n"; infoFileStream << "set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "; - this->WriteCMakeArgument(infoFileStream, - this->Makefile->GetComplainRegularExpression()); + cmLocalUnixMakefileGenerator3::WriteCMakeArgument( + infoFileStream, this->Makefile->GetComplainRegularExpression()); infoFileStream << ")\n"; infoFileStream << "set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN})\n"; @@ -684,7 +682,7 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsTop( } // Add a fake suffix to keep HP happy. Must be max 32 chars for SGI make. std::vector<std::string> depends; - depends.push_back(".hpux_make_needs_suffix_list"); + depends.emplace_back(".hpux_make_needs_suffix_list"); this->WriteMakeRule(makefileStream, nullptr, ".SUFFIXES", depends, no_commands, false); if (this->IsWatcomWMake()) { @@ -770,7 +768,7 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom( cmOutputConverter::SHELL); commands.push_back(rescanRule); } - std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash(); + std::string cmakefileName = "CMakeFiles/"; cmakefileName += "Makefile.cmake"; std::string runRule = "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"; @@ -851,7 +849,7 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepend( const char* nodep = this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY"); if (!nodep || cmSystemTools::IsOff(nodep)) { - depends.push_back(ruleFileName); + depends.emplace_back(ruleFileName); } } @@ -1253,9 +1251,8 @@ std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable( return ret; } -bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, - bool verbose, - bool color) +bool cmLocalUnixMakefileGenerator3::UpdateDependencies( + const std::string& tgtInfo, bool verbose, bool color) { // read in the target info file if (!this->Makefile->ReadListFile(tgtInfo) || @@ -1279,13 +1276,13 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, this->GlobalGenerator->GetCMakeInstance()->GetFileComparison(); { int result; - if (!ftc->FileTimeCompare(internalDependFile.c_str(), tgtInfo, &result) || + if (!ftc->FileTimeCompare(internalDependFile, tgtInfo, &result) || result < 0) { if (verbose) { std::ostringstream msg; msg << "Dependee \"" << tgtInfo << "\" is newer than depender \"" << internalDependFile << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } needRescanDependInfo = true; } @@ -1295,18 +1292,17 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, // may have changed. In this case discard all old dependencies. bool needRescanDirInfo = false; std::string dirInfoFile = this->GetCurrentBinaryDirectory(); - dirInfoFile += cmake::GetCMakeFilesDirectory(); + dirInfoFile += "/CMakeFiles"; dirInfoFile += "/CMakeDirectoryInformation.cmake"; { int result; - if (!ftc->FileTimeCompare(internalDependFile.c_str(), dirInfoFile.c_str(), - &result) || + if (!ftc->FileTimeCompare(internalDependFile, dirInfoFile, &result) || result < 0) { if (verbose) { std::ostringstream msg; msg << "Dependee \"" << dirInfoFile << "\" is newer than depender \"" << internalDependFile << "\"." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } needRescanDirInfo = true; } @@ -1332,8 +1328,8 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, // dependency vector. This means that in the normal case, when only // few or one file have been edited, then also only this one file is // actually scanned again, instead of all files for this target. - needRescanDependencies = !checker.Check( - dependFile.c_str(), internalDependFile.c_str(), validDependencies); + needRescanDependencies = + !checker.Check(dependFile, internalDependFile, validDependencies); } if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) { @@ -1346,7 +1342,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, cmsysTerminal_Color_ForegroundBold, message.c_str(), true, color); - return this->ScanDependencies(dir.c_str(), validDependencies); + return this->ScanDependencies(dir, validDependencies); } // The dependencies are already up-to-date. @@ -1354,17 +1350,16 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo, } bool cmLocalUnixMakefileGenerator3::ScanDependencies( - const char* targetDir, + const std::string& targetDir, std::map<std::string, cmDepends::DependencyVector>& validDeps) { // Read the directory information file. cmMakefile* mf = this->Makefile; bool haveDirectoryInfo = false; std::string dirInfoFile = this->GetCurrentBinaryDirectory(); - dirInfoFile += cmake::GetCMakeFilesDirectory(); + dirInfoFile += "/CMakeFiles"; dirInfoFile += "/CMakeDirectoryInformation.cmake"; - if (mf->ReadListFile(dirInfoFile.c_str()) && - !cmSystemTools::GetErrorOccuredFlag()) { + if (mf->ReadListFile(dirInfoFile) && !cmSystemTools::GetErrorOccuredFlag()) { haveDirectoryInfo = true; } @@ -1392,12 +1387,9 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( cmSystemTools::Error("Directory Information file not found"); } - // create the file stream for the depends file - std::string dir = targetDir; - // Open the make depends file. This should be copy-if-different // because the make tool may try to reload it needlessly otherwise. - std::string ruleFileNameFull = dir; + std::string ruleFileNameFull = targetDir; ruleFileNameFull += "/depend.make"; cmGeneratedFileStream ruleFileStream( ruleFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); @@ -1409,7 +1401,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( // Open the cmake dependency tracking file. This should not be // copy-if-different because dependencies are re-scanned when it is // older than the DependInfo.cmake. - std::string internalRuleFileNameFull = dir; + std::string internalRuleFileNameFull = targetDir; internalRuleFileNameFull += "/depend.internal"; cmGeneratedFileStream internalRuleFileStream( internalRuleFileNameFull, false, @@ -1450,7 +1442,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( scanner->SetFileComparison( this->GlobalGenerator->GetCMakeInstance()->GetFileComparison()); scanner->SetLanguage(lang); - scanner->SetTargetDirectory(dir.c_str()); + scanner->SetTargetDirectory(targetDir); scanner->Write(ruleFileStream, internalRuleFileStream); // free the scanner for this language @@ -1488,7 +1480,7 @@ void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose) msg << "Deleting primary custom command output \"" << dependee << "\" because another output \"" << depender << "\" does not exist." << std::endl; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } cmSystemTools::RemoveFile(dependee); } @@ -1506,7 +1498,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( // Just depend on the all target to drive the build. std::vector<std::string> depends; std::vector<std::string> no_commands; - depends.push_back("all"); + depends.emplace_back("all"); // Write the rule. this->WriteMakeRule(ruleFileStream, @@ -1546,8 +1538,10 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( if (!text) { text = "Running external command ..."; } - depends.insert(depends.end(), gt->GetUtilities().begin(), - gt->GetUtilities().end()); + depends.reserve(gt->GetUtilities().size()); + for (BT<std::string> const& u : gt->GetUtilities()) { + depends.push_back(u.Value); + } this->AppendEcho(commands, text, cmLocalUnixMakefileGenerator3::EchoGlobal); @@ -1568,7 +1562,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( (targetName == "install/strip")) { // Provide a fast install target that does not depend on all // but has the same command. - depends.push_back("preinstall/fast"); + depends.emplace_back("preinstall/fast"); } else { // Just forward to the real target so at least it will work. depends.push_back(targetName); @@ -1590,18 +1584,18 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( bool regenerate = !this->GlobalGenerator->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); if (regenerate) { - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } std::string progressDir = this->GetBinaryDirectory(); - progressDir += cmake::GetCMakeFilesDirectory(); + progressDir += "/CMakeFiles"; { std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; progCmd << this->ConvertToOutputFormat( cmSystemTools::CollapseFullPath(progressDir), cmOutputConverter::SHELL); - std::string progressFile = cmake::GetCMakeFilesDirectory(); + std::string progressFile = "/CMakeFiles"; progressFile += "/progress.marks"; std::string progressFileNameFull = this->ConvertToFullPath(progressFile); progCmd << " " @@ -1610,10 +1604,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( cmOutputConverter::SHELL); commands.push_back(progCmd.str()); } - std::string mf2Dir = cmake::GetCMakeFilesDirectoryPostSlash(); + std::string mf2Dir = "CMakeFiles/"; mf2Dir += "Makefile2"; - commands.push_back( - this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget)); + commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget)); this->CreateCDCommand(commands, this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); { @@ -1632,15 +1625,14 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( recursiveTarget += "/clean"; commands.clear(); depends.clear(); - commands.push_back( - this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget)); + commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget)); this->CreateCDCommand(commands, this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); this->WriteMakeRule(ruleFileStream, "The main clean target", "clean", depends, commands, true); commands.clear(); depends.clear(); - depends.push_back("clean"); + depends.emplace_back("clean"); this->WriteMakeRule(ruleFileStream, "The main clean target", "clean/fast", depends, commands, true); @@ -1653,13 +1645,12 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( this->Makefile->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); if (!noall || cmSystemTools::IsOff(noall)) { // Drive the build before installing. - depends.push_back("all"); + depends.emplace_back("all"); } else if (regenerate) { // At least make sure the build system is up to date. - depends.push_back("cmake_check_build_system"); + depends.emplace_back("cmake_check_build_system"); } - commands.push_back( - this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget)); + commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget)); this->CreateCDCommand(commands, this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.", @@ -1679,7 +1670,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( cmOutputConverter::SHELL); commands.push_back(rescanRule); } - std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash(); + std::string cmakefileName = "CMakeFiles/"; cmakefileName += "Makefile.cmake"; { std::string runRule = @@ -1717,7 +1708,7 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf, // Clear the implicit dependency makefile. std::string dependFile = dir + "/depend.make"; - clearer.Clear(dependFile.c_str()); + clearer.Clear(dependFile); // Remove the internal dependency check file to force // regeneration. @@ -1734,9 +1725,9 @@ class NotInProjectDir { public: // Constructor with the source and binary directory's path - NotInProjectDir(const std::string& sourceDir, const std::string& binaryDir) - : SourceDir(sourceDir) - , BinaryDir(binaryDir) + NotInProjectDir(std::string sourceDir, std::string binaryDir) + : SourceDir(std::move(sourceDir)) + , BinaryDir(std::move(binaryDir)) { } @@ -1817,10 +1808,21 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( << "_COMPILER_ID \"" << cid << "\")\n"; } + if (implicitLang.first == "Fortran") { + std::string smodSep = + this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP"); + std::string smodExt = + this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT"); + cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_SEP \"" << smodSep + << "\")\n"; + cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_EXT \"" << smodExt + << "\")\n"; + } + // Build a list of preprocessor definitions for the target. std::set<std::string> defines; - this->AddCompileDefinitions(defines, target, this->ConfigName, - implicitLang.first); + this->GetTargetDefines(target, this->ConfigName, implicitLang.first, + defines); if (!defines.empty()) { /* clang-format off */ cmakefileStream @@ -1887,7 +1889,7 @@ void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream& os) } std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall( - const char* makefile, const std::string& tgt) + const std::string& makefile, const std::string& tgt) { // Call make on the given file. std::string cmd; @@ -1957,7 +1959,7 @@ void cmLocalUnixMakefileGenerator3::WriteCMakeArgument(std::ostream& os, } std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath( - const char* p, bool useWatcomQuote) + const std::string& p, bool useWatcomQuote) { // Split the path into its components. std::vector<std::string> components; @@ -2024,7 +2026,7 @@ std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath( std::string cmLocalUnixMakefileGenerator3::GetTargetDirectory( cmGeneratorTarget const* target) const { - std::string dir = cmake::GetCMakeFilesDirectoryPostSlash(); + std::string dir = "CMakeFiles/"; dir += target->GetName(); #if defined(__VMS) dir += "_dir"; @@ -2041,8 +2043,8 @@ cmLocalUnixMakefileGenerator3::GetImplicitDepends(const cmGeneratorTarget* tgt) } void cmLocalUnixMakefileGenerator3::AddImplicitDepends( - const cmGeneratorTarget* tgt, const std::string& lang, const char* obj, - const char* src) + const cmGeneratorTarget* tgt, const std::string& lang, + const std::string& obj, const std::string& src) { this->ImplicitDepends[tgt->GetName()][lang][obj].push_back(src); } @@ -2086,13 +2088,3 @@ void cmLocalUnixMakefileGenerator3::CreateCDCommand( [&prefix](std::string const& s) { return prefix + s; }); } } - -std::string cmLocalUnixMakefileGenerator3::MaybeConvertToRelativePath( - std::string const& base, std::string const& path) -{ - if (!cmOutputConverter::ContainedInDirectory( - base, path, this->GetStateSnapshot().GetDirectory())) { - return path; - } - return cmOutputConverter::ForceToRelativePath(base, path); -} diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 869ef1ee9..ced2dbd46 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -12,6 +12,7 @@ #include <map> #include <set> #include <string> +#include <utility> #include <vector> class cmCustomCommand; @@ -83,7 +84,7 @@ public: void WriteDivider(std::ostream& os); /** used to create a recursive make call */ - std::string GetRecursiveMakeCall(const char* makefile, + std::string GetRecursiveMakeCall(const std::string& makefile, const std::string& tgt); // append flags to a string @@ -120,7 +121,7 @@ public: std::string const& targetDir, std::string const& relDir); - static std::string ConvertToQuotedOutputPath(const char* p, + static std::string ConvertToQuotedOutputPath(const std::string& p, bool useWatcomQuote); std::string CreateMakeVariable(const std::string& sin, @@ -128,7 +129,7 @@ public: /** Called from command-line hook to bring dependencies up to date for a target. */ - bool UpdateDependencies(const char* tgtInfo, bool verbose, + bool UpdateDependencies(const std::string& tgtInfo, bool verbose, bool color) override; /** Called from command-line hook to clear dependencies. */ @@ -158,8 +159,8 @@ public: cmGeneratorTarget const* tgt); void AddImplicitDepends(cmGeneratorTarget const* tgt, - const std::string& lang, const char* obj, - const char* src); + const std::string& lang, const std::string& obj, + const std::string& src); // write the target rules for the local Makefile into the stream void WriteLocalAllRules(std::ostream& ruleFileStream); @@ -183,9 +184,6 @@ public: // Eclipse generator. void GetIndividualFileTargets(std::vector<std::string>& targets); - std::string MaybeConvertToRelativePath(std::string const& base, - std::string const& path); - protected: void WriteLocalMakefile(); @@ -200,9 +198,6 @@ protected: void WriteDependLanguageInfo(std::ostream& cmakefileStream, cmGeneratorTarget* tgt); - // write the local help rule - void WriteHelpRule(std::ostream& ruleFileStream); - // this converts a file name that is relative to the StartOuputDirectory // into a full path std::string ConvertToFullPath(const std::string& localPath); @@ -211,15 +206,6 @@ protected: const std::string& realTarget, const std::string& helpTarget); - void WriteTargetDependRule(std::ostream& ruleFileStream, - cmGeneratorTarget* target); - void WriteTargetCleanRule(std::ostream& ruleFileStream, - cmGeneratorTarget* target, - const std::vector<std::string>& files); - void WriteTargetRequiresRule(std::ostream& ruleFileStream, - cmGeneratorTarget* target, - const std::vector<std::string>& objects); - void AppendRuleDepend(std::vector<std::string>& depends, const char* ruleFileName); void AppendRuleDepends(std::vector<std::string>& depends, @@ -245,7 +231,7 @@ protected: // Helper methods for dependency updates. bool ScanDependencies( - const char* targetDir, + const std::string& targetDir, std::map<std::string, cmDepends::DependencyVector>& validDeps); void CheckMultipleOutputs(bool verbose); @@ -264,36 +250,27 @@ private: struct LocalObjectEntry { - cmGeneratorTarget* Target; + cmGeneratorTarget* Target = nullptr; std::string Language; - LocalObjectEntry() - : Target(nullptr) - , Language() - { - } - LocalObjectEntry(cmGeneratorTarget* t, const std::string& lang) + LocalObjectEntry() = default; + LocalObjectEntry(cmGeneratorTarget* t, std::string lang) : Target(t) - , Language(lang) + , Language(std::move(lang)) { } }; struct LocalObjectInfo : public std::vector<LocalObjectEntry> { - bool HasSourceExtension; - bool HasPreprocessRule; - bool HasAssembleRule; - LocalObjectInfo() - : HasSourceExtension(false) - , HasPreprocessRule(false) - , HasAssembleRule(false) - { - } + bool HasSourceExtension = false; + bool HasPreprocessRule = false; + bool HasAssembleRule = false; }; void GetLocalObjectFiles( std::map<std::string, LocalObjectInfo>& localObjectFiles); void WriteObjectConvenienceRule(std::ostream& ruleFileStream, - const char* comment, const char* output, + const char* comment, + const std::string& output, LocalObjectInfo const& info); std::vector<std::string> LocalHelp; diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index 0c2c64eb6..d45c3356d 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -7,6 +7,7 @@ #include "cmMakefile.h" #include "cmVisualStudio10TargetGenerator.h" #include "cmXMLParser.h" +#include "cmake.h" #include "cm_expat.h" diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 842867264..7019552c3 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -6,6 +6,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalVisualStudio7Generator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmSystemTools.h" #include "cmXMLParser.h" @@ -96,7 +97,7 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() force_commands.push_back(force_command); std::string no_main_dependency; std::string force = this->GetCurrentBinaryDirectory(); - force += cmake::GetCMakeFilesDirectory(); + force += "/CMakeFiles"; force += "/"; force += l->GetName(); force += "_force"; @@ -143,7 +144,7 @@ void cmLocalVisualStudio7Generator::WriteStampFiles() // Touch a timestamp file used to determine when the project file is // out of date. std::string stampName = this->GetCurrentBinaryDirectory(); - stampName += cmake::GetCMakeFilesDirectory(); + stampName += "/CMakeFiles"; cmSystemTools::MakeDirectory(stampName.c_str()); stampName += "/"; stampName += "generate.stamp"; @@ -253,7 +254,7 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() std::string stampName = this->GetCurrentBinaryDirectory(); stampName += "/"; - stampName += cmake::GetCMakeFilesDirectoryPostSlash(); + stampName += "CMakeFiles/"; stampName += "generate.stamp"; cmCustomCommandLine commandLine; commandLine.push_back(cmSystemTools::GetCMakeCommand()); @@ -362,7 +363,7 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranFlagTable[] = { { "EnableRecursion", "recursive", "", "true", 0 }, { "ReentrantCode", "reentrancy", "", "true", 0 }, // done up to Language - { 0, 0, 0, 0, 0 } + { "", "", "", "", 0 } }; // fill the table here currently the comment field is not used for // anything other than documentation NOTE: Make sure the longer @@ -472,7 +473,7 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] = { { "WarnAsError", "WX", "Treat warnings as errors", "true", 0 }, { "BrowseInformation", "FR", "Generate browse information", "1", 0 }, { "StringPooling", "GF", "Enable StringPooling", "true", 0 }, - { 0, 0, 0, 0, 0 } + { "", "", "", "", 0 } }; cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] = { @@ -537,7 +538,7 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] = { { "ModuleDefinitionFile", "DEF:", "add an export def file", "", cmVS7FlagTable::UserValue }, { "GenerateMapFile", "MAP", "enable generation of map file", "true", 0 }, - { 0, 0, 0, 0, 0 } + { "", "", "", "", 0 } }; cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranLinkFlagTable[] = { @@ -545,7 +546,7 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranLinkFlagTable[] = { "linkIncrementalNo", 0 }, { "LinkIncremental", "INCREMENTAL:YES", "link incremental", "linkIncrementalYes", 0 }, - { 0, 0, 0, 0, 0 } + { "", "", "", "", 0 } }; // Helper class to write build event <Tool .../> elements. @@ -735,8 +736,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( targetOptions.AddDefine(configDefine); // Add the export symbol definition for shared library objects. - if (const char* exportMacro = target->GetExportMacro()) { - targetOptions.AddDefine(exportMacro); + if (const std::string* exportMacro = target->GetExportMacro()) { + targetOptions.AddDefine(*exportMacro); } // The intermediate directory name consists of a directory for the @@ -802,8 +803,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( target->GetProperty("Fortran_MODULE_DIRECTORY"); std::string modDir; if (target_mod_dir) { - modDir = this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), - target_mod_dir); + modDir = this->MaybeConvertToRelativePath( + this->GetCurrentBinaryDirectory(), target_mod_dir); } else { modDir = "."; } @@ -1305,7 +1306,7 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries( for (ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) { if (l->IsPath) { std::string rel = - lg->ConvertToRelativePath(currentBinDir, l->Value.c_str()); + lg->MaybeConvertToRelativePath(currentBinDir, l->Value.c_str()); fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " "; } else if (!l->Target || l->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { @@ -1331,7 +1332,7 @@ void cmLocalVisualStudio7GeneratorInternals::OutputObjects( i != objs.end(); ++i) { if (!(*i)->GetObjectLibrary().empty()) { std::string const& objFile = (*i)->GetFullPath(); - std::string rel = lg->ConvertToRelativePath(currentBinDir, objFile); + std::string rel = lg->MaybeConvertToRelativePath(currentBinDir, objFile); fout << sep << lg->ConvertToXMLOutputPath(rel.c_str()); sep = " "; } @@ -1347,7 +1348,7 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories( d != dirs.end(); ++d) { // Remove any trailing slash and skip empty paths. std::string dir = *d; - if (dir[dir.size() - 1] == '/') { + if (dir.back() == '/') { dir = dir.substr(0, dir.size() - 1); } if (dir.empty()) { @@ -1357,7 +1358,7 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories( // Switch to a relative path specification if it is shorter. if (cmSystemTools::FileIsFullPath(dir.c_str())) { std::string rel = - this->ConvertToRelativePath(currentBinDir, dir.c_str()); + this->MaybeConvertToRelativePath(currentBinDir, dir.c_str()); if (rel.size() < dir.size()) { dir = rel; } diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 2237da75f..660729c3a 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -210,9 +210,10 @@ std::string cmLocalVisualStudioGenerator::ConstructScript( } if (workingDirectory.empty()) { - script += this->ConvertToOutputFormat( - this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), cmd), - cmOutputConverter::SHELL); + script += + this->ConvertToOutputFormat(this->MaybeConvertToRelativePath( + this->GetCurrentBinaryDirectory(), cmd), + cmOutputConverter::SHELL); } else { script += this->ConvertToOutputFormat(cmd.c_str(), SHELL); } diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index 92c958d05..9c36627b5 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -19,9 +19,7 @@ cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmGlobalGenerator* gg, this->EmitUniversalBinaryFlags = false; } -cmLocalXCodeGenerator::~cmLocalXCodeGenerator() -{ -} +cmLocalXCodeGenerator::~cmLocalXCodeGenerator() = default; std::string cmLocalXCodeGenerator::GetTargetDirectory( cmGeneratorTarget const*) const diff --git a/Source/cmLocale.h b/Source/cmLocale.h index 174f0f0f2..3580ec812 100644 --- a/Source/cmLocale.h +++ b/Source/cmLocale.h @@ -10,16 +10,18 @@ class cmLocaleRAII { - CM_DISABLE_COPY(cmLocaleRAII) - public: cmLocaleRAII() : OldLocale(setlocale(LC_CTYPE, nullptr)) { setlocale(LC_CTYPE, ""); } + ~cmLocaleRAII() { setlocale(LC_CTYPE, this->OldLocale.c_str()); } + cmLocaleRAII(cmLocaleRAII const&) = delete; + cmLocaleRAII& operator=(cmLocaleRAII const&) = delete; + private: std::string OldLocale; }; diff --git a/Source/cmMSVC60LinkLineComputer.h b/Source/cmMSVC60LinkLineComputer.h index 31223ecd4..d767914b9 100644 --- a/Source/cmMSVC60LinkLineComputer.h +++ b/Source/cmMSVC60LinkLineComputer.h @@ -15,12 +15,14 @@ class cmStateDirectory; class cmMSVC60LinkLineComputer : public cmLinkLineComputer { - CM_DISABLE_COPY(cmMSVC60LinkLineComputer) - public: cmMSVC60LinkLineComputer(cmOutputConverter* outputConverter, cmStateDirectory const& stateDir); + cmMSVC60LinkLineComputer(cmMSVC60LinkLineComputer const&) = delete; + cmMSVC60LinkLineComputer& operator=(cmMSVC60LinkLineComputer const&) = + delete; + std::string ConvertToLinkReference(std::string const& input) const override; }; diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx index 7294c1cbf..d4af1e0f3 100644 --- a/Source/cmMachO.cxx +++ b/Source/cmMachO.cxx @@ -52,10 +52,7 @@ bool peek(cmsys::ifstream& fin, T& v) template <typename T> bool read(cmsys::ifstream& fin, T& v) { - if (!fin.read(reinterpret_cast<char*>(&v), sizeof(T))) { - return false; - } - return true; + return !!fin.read(reinterpret_cast<char*>(&v), sizeof(T)); } // read from the file and fill multiple data structures where @@ -67,10 +64,7 @@ bool read(cmsys::ifstream& fin, std::vector<T>& v) if (v.empty()) { return true; } - if (!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size())) { - return false; - } - return true; + return !!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size()); } } @@ -97,7 +91,7 @@ public: : Swap(_swap) { } - virtual ~cmMachOHeaderAndLoadCommands() {} + virtual ~cmMachOHeaderAndLoadCommands() = default; virtual bool read_mach_o(cmsys::ifstream& fin) = 0; diff --git a/Source/cmMachO.h b/Source/cmMachO.h index 5886d7626..5482465d3 100644 --- a/Source/cmMachO.h +++ b/Source/cmMachO.h @@ -30,7 +30,7 @@ public: std::string const& GetErrorMessage() const; /** Boolean conversion. True if the Mach-O file is valid. */ - operator bool() const { return this->Valid(); } + explicit operator bool() const { return this->Valid(); } /** Get Install name from binary **/ bool GetInstallName(std::string& install_name); diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 23d93a381..7279d5fcf 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -17,11 +17,6 @@ class cmMacroHelperCommand : public cmCommand { public: - cmMacroHelperCommand() {} - - ///! clean up any memory allocated by the macro - ~cmMacroHelperCommand() override {} - /** * This is a virtual constructor for the command. */ @@ -94,7 +89,7 @@ bool cmMacroHelperCommand::InvokeInitialPass( char argvName[60]; for (unsigned int j = 0; j < expandedArgs.size(); ++j) { sprintf(argvName, "${ARGV%u}", j); - argVs.push_back(argvName); + argVs.emplace_back(argvName); } // Invoke all the functions that were collected in the block. cmListFileFunction newLFF; diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h index d967388bf..b54ed6605 100644 --- a/Source/cmMacroCommand.h +++ b/Source/cmMacroCommand.h @@ -18,15 +18,13 @@ class cmMakefile; class cmMacroFunctionBlocker : public cmFunctionBlocker { public: - cmMacroFunctionBlocker() { this->Depth = 0; } - ~cmMacroFunctionBlocker() override {} bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf, cmExecutionStatus&) override; bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override; std::vector<std::string> Args; std::vector<cmListFileFunction> Functions; - int Depth; + int Depth = 0; }; /// Starts macro() ... endmacro() block diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 8d163b77d..7e33bda27 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -28,7 +28,9 @@ #include "cmGeneratorExpressionEvaluationFile.h" #include "cmGlobalGenerator.h" #include "cmInstallGenerator.h" // IWYU pragma: keep +#include "cmInstallSubdirectoryGenerator.h" #include "cmListFileCache.h" +#include "cmMessageType.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" #include "cmState.h" @@ -43,6 +45,8 @@ #include "cm_sys_stat.h" #include "cmake.h" +#include "cmConfigure.h" // IWYU pragma: keep + #ifdef CMAKE_BUILD_WITH_CMAKE # include "cmVariableWatch.h" #endif @@ -66,7 +70,7 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused(); this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars(); - this->SuppressWatches = false; + this->SuppressSideEffects = false; // Setup the default include complaint regular expression (match nothing). this->ComplainFileRegularExpression = "^$"; @@ -81,6 +85,7 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, this->StateSnapshot = this->StateSnapshot.GetState()->CreatePolicyScopeSnapshot( this->StateSnapshot); + this->RecursionDepth = 0; // Enter a policy level for this directory. this->PushPolicy(); @@ -128,11 +133,11 @@ cmDirectoryId cmMakefile::GetDirectoryId() const return std::string(buf); } -void cmMakefile::IssueMessage(cmake::MessageType t, - std::string const& text) const +void cmMakefile::IssueMessage(MessageType t, std::string const& text) const { if (!this->ExecutionStatusStack.empty()) { - if ((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR)) { + if ((t == MessageType::FATAL_ERROR) || + (t == MessageType::INTERNAL_ERROR)) { this->ExecutionStatusStack.back()->SetNestedError(); } } @@ -142,7 +147,7 @@ void cmMakefile::IssueMessage(cmake::MessageType t, bool cmMakefile::CheckCMP0037(std::string const& targetName, cmStateEnums::TargetType targetType) const { - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; std::ostringstream e; bool issueMessage = false; switch (this->GetPolicyStatus(cmPolicies::CMP0037)) { @@ -158,7 +163,7 @@ bool cmMakefile::CheckCMP0037(std::string const& targetName, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: issueMessage = true; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; break; } if (issueMessage) { @@ -168,7 +173,7 @@ bool cmMakefile::CheckCMP0037(std::string const& targetName, "in undefined behavior."; this->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -197,7 +202,7 @@ void cmMakefile::MaybeWarnCMP0074(std::string const& pkg) << " " << env << "\n"; } w << "For compatibility, CMake is ignoring the variable."; - this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } @@ -317,7 +322,7 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const msg << " "; } msg << ")"; - cmSystemTools::Message(msg.str().c_str()); + cmSystemTools::Message(msg.str()); } // Helper class to make sure the call stack is valid. @@ -331,12 +336,14 @@ public: cmListFileContext const& lfc = cmListFileContext::FromCommandContext( cc, this->Makefile->StateSnapshot.GetExecutionListFile()); this->Makefile->Backtrace = this->Makefile->Backtrace.Push(lfc); + ++this->Makefile->RecursionDepth; this->Makefile->ExecutionStatusStack.push_back(&status); } ~cmMakefileCall() { this->Makefile->ExecutionStatusStack.pop_back(); + --this->Makefile->RecursionDepth; this->Makefile->Backtrace = this->Makefile->Backtrace.Pop(); } @@ -359,6 +366,24 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, cmMakefileCall stack_manager(this, lff, status); static_cast<void>(stack_manager); + // Check for maximum recursion depth. + int depth = CMake_DEFAULT_RECURSION_LIMIT; + const char* depthStr = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); + if (depthStr) { + std::istringstream s(depthStr); + int d; + if (s >> d) { + depth = d; + } + } + if (this->RecursionDepth > depth) { + std::ostringstream e; + e << "Maximum recursion depth of " << depth << " exceeded"; + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + // Lookup the command prototype. if (cmCommand* proto = this->GetState()->GetCommandByExactName(lff.Name.Lower)) { @@ -380,7 +405,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, // The command invocation requested that we report an error. std::string const error = std::string(lff.Name.Original) + " " + pcmd->GetError(); - this->IssueMessage(cmake::FATAL_ERROR, error); + this->IssueMessage(MessageType::FATAL_ERROR, error); } result = false; if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) { @@ -396,7 +421,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, std::string error = "Unknown CMake command \""; error += lff.Name.Original; error += "\"."; - this->IssueMessage(cmake::FATAL_ERROR, error); + this->IssueMessage(MessageType::FATAL_ERROR, error); result = false; cmSystemTools::SetFatalErrorOccured(); } @@ -508,7 +533,7 @@ void cmMakefile::IncludeScope::EnforceCMP0011() << "affects policy settings. " << "CMake is implying the NO_POLICY_SCOPE option for compatibility, " << "so the effects are applied to the including context."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } break; case cmPolicies::REQUIRED_IF_USED: @@ -520,7 +545,7 @@ void cmMakefile::IncludeScope::EnforceCMP0011() << this->Makefile->GetExecutionFilePath() << "\n" << "affects policy settings, so it requires this policy to be set."; /* clang-format on */ - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } break; case cmPolicies::OLD: case cmPolicies::NEW: @@ -531,7 +556,8 @@ void cmMakefile::IncludeScope::EnforceCMP0011() } } -bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope) +bool cmMakefile::ReadDependentFile(const std::string& filename, + bool noPolicyScope) { this->AddDefinition("CMAKE_PARENT_LIST_FILE", this->GetDefinition("CMAKE_CURRENT_LIST_FILE")); @@ -584,7 +610,7 @@ private: bool ReportError; }; -bool cmMakefile::ReadListFile(const char* filename) +bool cmMakefile::ReadListFile(const std::string& filename) { std::string filenametoread = cmSystemTools::CollapseFullPath( filename, this->GetCurrentSourceDirectory()); @@ -664,7 +690,7 @@ void cmMakefile::EnforceDirectoryLevelRules() const case cmPolicies::WARN: // Warn because the user did not provide a minimum required // version. - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, msg.str(), this->Backtrace); case cmPolicies::OLD: // OLD behavior is to use policy version 2.4 set in @@ -674,8 +700,8 @@ void cmMakefile::EnforceDirectoryLevelRules() const case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: // NEW behavior is to issue an error. - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, msg.str(), - this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + msg.str(), this->Backtrace); cmSystemTools::SetFatalErrorOccured(); return; } @@ -763,7 +789,7 @@ void cmMakefile::ConfigureFinalPass() if (oldValue && cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) { this->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "You have set CMAKE_BACKWARDS_COMPATIBILITY to a CMake version less " "than 2.4. This version of CMake only supports backwards compatibility " "with CMake 2.4 or later. For compatibility with older versions please " @@ -784,7 +810,7 @@ void cmMakefile::AddCustomCommandToTarget( cmTargets::iterator ti = this->Targets.find(target); if (ti == this->Targets.end()) { - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; bool issueMessage = false; std::ostringstream e; switch (this->GetPolicyStatus(cmPolicies::CMP0040)) { @@ -797,7 +823,7 @@ void cmMakefile::AddCustomCommandToTarget( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: issueMessage = true; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (issueMessage) { @@ -825,7 +851,7 @@ void cmMakefile::AddCustomCommandToTarget( e << "Target \"" << target << "\" is an OBJECT library " "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (t.GetType() == cmStateEnums::INTERFACE_LIBRARY) { @@ -833,7 +859,7 @@ void cmMakefile::AddCustomCommandToTarget( e << "Target \"" << target << "\" is an INTERFACE library " "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -885,7 +911,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput( if (!cl.empty() && !cl[0].empty() && cl[0][0] == '"') { std::ostringstream e; e << "COMMAND may not contain literal quotes:\n " << cl[0] << "\n"; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return nullptr; } } @@ -1125,7 +1151,7 @@ cmTarget* cmMakefile::AddUtilityCommand( // Create a target instance for this utility. cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName); target->SetIsGeneratorProvided(origin == TargetOrigin::Generator); - if (excludeFromAll) { + if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } if (!comment) { @@ -1136,7 +1162,7 @@ cmTarget* cmMakefile::AddUtilityCommand( // Store the custom command in the target. if (!commandLines.empty() || !depends.empty()) { std::string force = this->GetCurrentBinaryDirectory(); - force += cmake::GetCMakeFilesDirectory(); + force += "/CMakeFiles"; force += "/"; force += utilityName; std::vector<std::string> forced; @@ -1277,7 +1303,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) // This definition has a non-trivial value. switch (this->GetPolicyStatus(cmPolicies::CMP0005)) { case cmPolicies::WARN: - this->IssueMessage(cmake::AUTHOR_WARNING, + this->IssueMessage(MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0005)); CM_FALLTHROUGH; case cmPolicies::OLD: @@ -1287,7 +1313,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0005)); return false; case cmPolicies::NEW: @@ -1366,6 +1392,9 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent) // Imported targets. this->ImportedTargets = parent->ImportedTargets; + + // Recursion depth. + this->RecursionDepth = parent->RecursionDepth; } void cmMakefile::PushFunctionScope(std::string const& fileName, @@ -1490,7 +1519,7 @@ void cmMakefile::Configure() // make sure the CMakeFiles dir is there std::string filesDir = this->StateSnapshot.GetDirectory().GetCurrentBinary(); - filesDir += cmake::GetCMakeFilesDirectory(); + filesDir += "/CMakeFiles"; cmSystemTools::MakeDirectory(filesDir); assert(cmSystemTools::FileExists(currentStart, true)); @@ -1593,7 +1622,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) if (this->GetCMakeInstance()->GetDebugOutput()) { std::string msg = " Entering "; msg += currentStart; - cmSystemTools::Message(msg.c_str()); + cmSystemTools::Message(msg); } std::string const currentStartFile = currentStart + "/CMakeLists.txt"; @@ -1616,7 +1645,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) << "\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0014); /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); case cmPolicies::OLD: // OLD behavior does not warn. break; @@ -1626,7 +1655,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior prints the error. - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); } return; } @@ -1636,7 +1665,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) if (this->GetCMakeInstance()->GetDebugOutput()) { std::string msg = " Returning to "; msg += this->GetCurrentSourceDirectory(); - cmSystemTools::Message(msg.c_str()); + cmSystemTools::Message(msg); } } @@ -1660,7 +1689,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot); this->GetGlobalGenerator()->AddMakefile(subMf); - if (excludeFromAll) { + if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } @@ -1669,6 +1698,9 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, } else { this->UnConfiguredDirectories.push_back(subMf); } + + this->AddInstallGenerator(new cmInstallSubdirectoryGenerator( + subMf, binPath.c_str(), excludeFromAll)); } const std::string& cmMakefile::GetCurrentSourceDirectory() const @@ -1833,6 +1865,23 @@ bool cmMakefile::VariableInitialized(const std::string& var) const return this->StateSnapshot.IsInitialized(var); } +void cmMakefile::MaybeWarnUninitialized(std::string const& variable, + const char* sourceFilename) const +{ + // check to see if we need to print a warning + // if strict mode is on and the variable has + // not been "cleared"/initialized with a set(foo ) call + if (this->GetCMakeInstance()->GetWarnUninitialized() && + !this->VariableInitialized(variable)) { + if (this->CheckSystemVars || + (sourceFilename && this->IsProjectFile(sourceFilename))) { + std::ostringstream msg; + msg << "uninitialized variable \'" << variable << "\'"; + this->IssueMessage(MessageType::AUTHOR_WARNING, msg.str()); + } + } +} + void cmMakefile::LogUnused(const char* reason, const std::string& name) const { if (this->WarnUnused) { @@ -1844,14 +1893,10 @@ void cmMakefile::LogUnused(const char* reason, const std::string& name) const path += "/CMakeLists.txt"; } - if (this->CheckSystemVars || - cmSystemTools::IsSubDirectory(path, this->GetHomeDirectory()) || - (cmSystemTools::IsSubDirectory(path, this->GetHomeOutputDirectory()) && - !cmSystemTools::IsSubDirectory(path, - cmake::GetCMakeFilesDirectory()))) { + if (this->CheckSystemVars || this->IsProjectFile(path.c_str())) { std::ostringstream msg; msg << "unused variable (" << reason << ") \'" << name << "\'"; - this->IssueMessage(cmake::AUTHOR_WARNING, msg.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, msg.str()); } } } @@ -1940,7 +1985,9 @@ cmTarget* cmMakefile::AddLibrary(const std::string& lname, // over changes in CMakeLists.txt, making the information stale and // hence useless. target->ClearDependencyInformation(*this); - if (excludeFromAll) { + if (excludeFromAll || + (type != cmStateEnums::INTERFACE_LIBRARY && + this->GetPropertyAsBool("EXCLUDE_FROM_ALL"))) { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } target->AddSources(srcs); @@ -1953,7 +2000,7 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName, bool excludeFromAll) { cmTarget* target = this->AddNewTarget(cmStateEnums::EXECUTABLE, exeName); - if (excludeFromAll) { + if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } target->AddSources(srcs); @@ -2081,7 +2128,7 @@ void cmMakefile::AddSourceGroup(const std::vector<std::string>& name, if (i == -1) { // group does not exist nor belong to any existing group // add its first component - this->SourceGroups.push_back(cmSourceGroup(name[0], regex)); + this->SourceGroups.emplace_back(name[0], regex); sg = this->GetSourceGroup(currentName); i = 0; // last component found } @@ -2257,8 +2304,8 @@ void cmMakefile::ExpandVariablesCMP0019() << "The following variable evaluations were encountered:\n" << w.str(); /* clang-format on */ - this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, m.str(), - this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + m.str(), this->Backtrace); } } @@ -2338,7 +2385,7 @@ cmMakefile::AppleSDK cmMakefile::GetAppleSDKType() const { "watchsimulator", AppleSDK::WatchSimulator }, }; - for (auto entry : sdkDatabase) { + for (auto const& entry : sdkDatabase) { if (sdkRoot.find(entry.name) == 0 || sdkRoot.find(std::string("/") + entry.name) != std::string::npos) { return entry.sdk; @@ -2417,7 +2464,7 @@ const std::string* cmMakefile::GetDef(const std::string& name) const } #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); - if (vv && !this->SuppressWatches) { + if (vv && !this->SuppressSideEffects) { bool const watch_function_executed = vv->VariableAccessed(name, def ? cmVariableWatch::VARIABLE_READ_ACCESS @@ -2477,7 +2524,7 @@ const std::string& cmMakefile::ExpandVariablesInString( const char* filename, long line, bool removeEmpty, bool replaceAt) const { bool compareResults = false; - cmake::MessageType mtype = cmake::LOG; + MessageType mtype = MessageType::LOG; std::string errorstr; std::string original; @@ -2485,7 +2532,7 @@ const std::string& cmMakefile::ExpandVariablesInString( if (atOnly && (!noEscapes || !removeEmpty)) { // This case should never be called. At-only is for // configure-file/string which always does no escapes. - this->IssueMessage(cmake::INTERNAL_ERROR, + this->IssueMessage(MessageType::INTERNAL_ERROR, "ExpandVariablesInString @ONLY called " "on something with escapes."); return source; @@ -2494,7 +2541,7 @@ const std::string& cmMakefile::ExpandVariablesInString( // Variables used in the WARN case. std::string newResult; std::string newErrorstr; - cmake::MessageType newError = cmake::LOG; + MessageType newError = MessageType::LOG; switch (this->GetPolicyStatus(cmPolicies::CMP0053)) { case cmPolicies::WARN: { @@ -2504,11 +2551,11 @@ const std::string& cmMakefile::ExpandVariablesInString( compareResults = true; // Suppress variable watches to avoid calling hooks twice. Suppress new // dereferences since the OLD behavior is still what is actually used. - this->SuppressWatches = true; - newError = ExpandVariablesInStringNew( - newErrorstr, newResult, escapeQuotes, noEscapes, atOnly, filename, - line, removeEmpty, replaceAt); - this->SuppressWatches = false; + this->SuppressSideEffects = true; + newError = ExpandVariablesInStringNew(newErrorstr, newResult, + escapeQuotes, noEscapes, atOnly, + filename, line, replaceAt); + this->SuppressSideEffects = false; CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -2520,15 +2567,15 @@ const std::string& cmMakefile::ExpandVariablesInString( case cmPolicies::REQUIRED_ALWAYS: // Messaging here would be *very* verbose. case cmPolicies::NEW: - mtype = ExpandVariablesInStringNew(errorstr, source, escapeQuotes, - noEscapes, atOnly, filename, line, - removeEmpty, replaceAt); + mtype = + ExpandVariablesInStringNew(errorstr, source, escapeQuotes, noEscapes, + atOnly, filename, line, replaceAt); break; } // If it's an error in either case, just report the error... - if (mtype != cmake::LOG) { - if (mtype == cmake::FATAL_ERROR) { + if (mtype != MessageType::LOG) { + if (mtype == MessageType::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); } this->IssueMessage(mtype, errorstr); @@ -2567,20 +2614,20 @@ const std::string& cmMakefile::ExpandVariablesInString( msg += "Using the old result for compatibility since the policy is not set."; - this->IssueMessage(cmake::AUTHOR_WARNING, msg); + this->IssueMessage(MessageType::AUTHOR_WARNING, msg); } return source; } -cmake::MessageType cmMakefile::ExpandVariablesInStringOld( +MessageType cmMakefile::ExpandVariablesInStringOld( std::string& errorstr, std::string& source, bool escapeQuotes, bool noEscapes, bool atOnly, const char* filename, long line, bool removeEmpty, bool replaceAt) const { // Fast path strings without any special characters. if (source.find_first_of("$@\\") == std::string::npos) { - return cmake::LOG; + return MessageType::LOG; } // Special-case the @ONLY mode. @@ -2619,7 +2666,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( // Append the rest of the unchanged part of the string. source.append(in); - return cmake::LOG; + return MessageType::LOG; } // This method replaces ${VAR} and @VAR@ where VAR is looked up @@ -2636,7 +2683,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( parser.SetRemoveEmpty(removeEmpty); int res = parser.ParseString(source.c_str(), 0); const char* emsg = parser.GetError(); - cmake::MessageType mtype = cmake::LOG; + MessageType mtype = MessageType::LOG; if (res && !emsg[0]) { source = parser.GetResult(); } else { @@ -2659,7 +2706,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( // parser reported an error message without failing because the // helper implementation is unhappy, which has always reported an // error. - mtype = cmake::FATAL_ERROR; + mtype = MessageType::FATAL_ERROR; if (!res) { // This is a real argument parsing error. Use policy CMP0010 to // decide whether it is an error. @@ -2669,7 +2716,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to just warn and continue. - mtype = cmake::AUTHOR_WARNING; + mtype = MessageType::AUTHOR_WARNING; break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: @@ -2693,19 +2740,31 @@ typedef enum } t_domain; struct t_lookup { - t_lookup() - : domain(NORMAL) - , loc(0) - { - } - t_domain domain; - size_t loc; + t_domain domain = NORMAL; + size_t loc = 0; }; -cmake::MessageType cmMakefile::ExpandVariablesInStringNew( +bool cmMakefile::IsProjectFile(const char* filename) const +{ + return cmSystemTools::IsSubDirectory(filename, this->GetHomeDirectory()) || + (cmSystemTools::IsSubDirectory(filename, this->GetHomeOutputDirectory()) && + !cmSystemTools::IsSubDirectory(filename, "/CMakeFiles")); +} + +int cmMakefile::GetRecursionDepth() const +{ + return this->RecursionDepth; +} + +void cmMakefile::SetRecursionDepth(int recursionDepth) +{ + this->RecursionDepth = recursionDepth; +} + +MessageType cmMakefile::ExpandVariablesInStringNew( std::string& errorstr, std::string& source, bool escapeQuotes, bool noEscapes, bool atOnly, const char* filename, long line, - bool removeEmpty, bool replaceAt) const + bool replaceAt) const { // This method replaces ${VAR} and @VAR@ where VAR is looked up // with GetDefinition(), if not found in the map, nothing is expanded. @@ -2719,10 +2778,11 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( std::vector<t_lookup> openstack; bool error = false; bool done = false; - cmake::MessageType mtype = cmake::LOG; + MessageType mtype = MessageType::LOG; cmState* state = this->GetCMakeInstance()->GetState(); + static const std::string lineVar = "CMAKE_CURRENT_LIST_LINE"; do { char inc = *in; switch (inc) { @@ -2735,7 +2795,6 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( const char* value = nullptr; std::string varresult; std::string svalue; - static const std::string lineVar = "CMAKE_CURRENT_LIST_LINE"; switch (var.domain) { case NORMAL: if (filename && lookup == lineVar) { @@ -2762,23 +2821,8 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( } else { varresult = value; } - } else if (!removeEmpty) { - // check to see if we need to print a warning - // if strict mode is on and the variable has - // not been "cleared"/initialized with a set(foo ) call - if (this->GetCMakeInstance()->GetWarnUninitialized() && - !this->VariableInitialized(lookup)) { - if (this->CheckSystemVars || - (filename && - (cmSystemTools::IsSubDirectory(filename, - this->GetHomeDirectory()) || - cmSystemTools::IsSubDirectory( - filename, this->GetHomeOutputDirectory())))) { - std::ostringstream msg; - msg << "uninitialized variable \'" << lookup << "\'"; - this->IssueMessage(cmake::AUTHOR_WARNING, msg.str()); - } - } + } else if (!this->SuppressSideEffects) { + this->MaybeWarnUninitialized(lookup, filename); } result.replace(var.loc, result.size() - var.loc, varresult); // Start looking from here on out. @@ -2813,7 +2857,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( std::string(next, this->cmNamedCurly.end()) + "{} is not supported. Only ${}, $ENV{}, " "and $CACHE{} are allowed."; - mtype = cmake::FATAL_ERROR; + mtype = MessageType::FATAL_ERROR; error = true; } } @@ -2885,7 +2929,19 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( "abcdefghijklmnopqrstuvwxyz" "0123456789/_.+-")) { std::string variable(in + 1, nextAt - in - 1); - std::string varresult = this->GetSafeDefinition(variable); + + std::string varresult; + if (filename && variable == lineVar) { + varresult = std::to_string(line); + } else { + const std::string* def = this->GetDef(variable); + if (def) { + varresult = *def; + } else if (!this->SuppressSideEffects) { + this->MaybeWarnUninitialized(variable, filename); + } + } + if (escapeQuotes) { varresult = cmSystemTools::EscapeQuotes(varresult); } @@ -2909,7 +2965,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( errorstr += "\') in a variable name: " "'" + result.substr(openstack.back().loc) + "'"; - mtype = cmake::FATAL_ERROR; + mtype = MessageType::FATAL_ERROR; error = true; } break; @@ -2940,7 +2996,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( emsg << "when parsing string\n" << " " << source << "\n"; emsg << errorstr; - mtype = cmake::FATAL_ERROR; + mtype = MessageType::FATAL_ERROR; errorstr = emsg.str(); } else { // Append the rest of the unchanged part of the string. @@ -3034,7 +3090,7 @@ void cmMakefile::PopFunctionBlockerBarrier(bool reportError) << " " << lfc << "\n" << "is not closed."; /* clang-format on */ - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); reportError = false; } } @@ -3187,7 +3243,7 @@ std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker( << " " << closingContext << "\n" << "with mis-matching arguments."; /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } cmFunctionBlocker* b = *pos; this->FunctionBlockers.erase(pos); @@ -3344,7 +3400,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, // use the cmake object instead of calling cmake cmWorkingDirectory workdir(bindir); if (workdir.Failed()) { - this->IssueMessage(cmake::FATAL_ERROR, + this->IssueMessage(MessageType::FATAL_ERROR, "Failed to set working directory to " + bindir + " : " + std::strerror(workdir.GetLastResult())); cmSystemTools::SetFatalErrorOccured(); @@ -3355,12 +3411,12 @@ int cmMakefile::TryCompile(const std::string& srcdir, // make sure the same generator is used // use this program as the cmake to be run, it should not // be run that way but the cmake object requires a vailid path - cmake cm(cmake::RoleProject); + cmake cm(cmake::RoleProject, cmState::Project); cm.SetIsInTryCompile(true); cmGlobalGenerator* gg = cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName()); if (!gg) { - this->IssueMessage(cmake::INTERNAL_ERROR, + this->IssueMessage(MessageType::INTERNAL_ERROR, "Global generator '" + this->GetGlobalGenerator()->GetName() + "' could not be created."); @@ -3368,6 +3424,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, this->IsSourceFileTryCompile = false; return 1; } + gg->RecursionDepth = this->RecursionDepth; cm.SetGlobalGenerator(gg); // do a configure @@ -3387,6 +3444,12 @@ int cmMakefile::TryCompile(const std::string& srcdir, cmStateEnums::STRING); } } + const char* recursionDepth = + this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); + if (recursionDepth) { + cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth, + "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. @@ -3426,7 +3489,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, cmStateEnums::INTERNAL); } if (cm.Configure() != 0) { - this->IssueMessage(cmake::FATAL_ERROR, + this->IssueMessage(MessageType::FATAL_ERROR, "Failed to configure test project build system."); cmSystemTools::SetFatalErrorOccured(); this->IsSourceFileTryCompile = false; @@ -3434,7 +3497,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, } if (cm.Generate() != 0) { - this->IssueMessage(cmake::FATAL_ERROR, + this->IssueMessage(MessageType::FATAL_ERROR, "Failed to generate test project build system."); cmSystemTools::SetFatalErrorOccured(); this->IsSourceFileTryCompile = false; @@ -3496,7 +3559,8 @@ void cmMakefile::DisplayStatus(const char* message, float s) const cm->UpdateProgress(message, s); } -std::string cmMakefile::GetModulesFile(const char* filename) const +std::string cmMakefile::GetModulesFile(const std::string& filename, + bool& system) const { std::string result; @@ -3543,8 +3607,10 @@ std::string cmMakefile::GetModulesFile(const char* filename) const // Normally, prefer the files found in CMAKE_MODULE_PATH. Only when the file // from which we are being called is located itself in CMAKE_ROOT, then // prefer results from CMAKE_ROOT depending on the policy setting. + system = false; result = moduleInCMakeModulePath; if (result.empty()) { + system = true; result = moduleInCMakeRoot; } @@ -3563,15 +3629,17 @@ std::string cmMakefile::GetModulesFile(const char* filename) const << cmPolicies::GetPolicyWarning(cmPolicies::CMP0017); /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); CM_FALLTHROUGH; } case cmPolicies::OLD: + system = false; result = moduleInCMakeModulePath; break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: + system = true; result = moduleInCMakeRoot; break; } @@ -3639,8 +3707,15 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output, } // Perform variable replacements. - this->ExpandVariablesInString(output, escapeQuotes, true, atOnly, nullptr, - -1, true, true); + const char* filename = nullptr; + long lineNumber = -1; + if (!this->Backtrace.Empty()) { + const auto& currentTrace = this->Backtrace.Top(); + filename = currentTrace.FilePath.c_str(); + lineNumber = currentTrace.Line; + } + this->ExpandVariablesInString(output, escapeQuotes, true, atOnly, filename, + lineNumber, true, true); } int cmMakefile::ConfigureFile(const char* infile, const char* outfile, @@ -3676,8 +3751,7 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile, } if (copyonly) { - if (!cmSystemTools::CopyFileIfDifferent(sinfile.c_str(), - soutfile.c_str())) { + if (!cmSystemTools::CopyFileIfDifferent(sinfile, soutfile)) { return 0; } } else { @@ -3710,7 +3784,7 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile, std::ostringstream e; e << "File starts with a Byte-Order-Mark that is not UTF-8:\n " << sinfile; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return 0; } // rewind to copy BOM to output file @@ -3728,8 +3802,7 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile, // close the files before attempting to copy fin.close(); fout.close(); - if (!cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(), - soutfile.c_str())) { + if (!cmSystemTools::CopyFileIfDifferent(tempOutputFile, soutfile)) { res = 0; } else { cmSystemTools::SetPermissions(soutfile, perm); @@ -3907,7 +3980,7 @@ void cmMakefile::RaiseScope(const std::string& var, const char* varDef) if (!this->StateSnapshot.RaiseScope(var, varDef)) { std::ostringstream m; m << "Cannot set \"" << var << "\": current scope has no parent."; - this->IssueMessage(cmake::AUTHOR_WARNING, m.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, m.str()); return; } @@ -3992,7 +4065,7 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg, // target names must be globally unique switch (this->GetPolicyStatus(cmPolicies::CMP0002)) { case cmPolicies::WARN: - this->IssueMessage(cmake::AUTHOR_WARNING, + this->IssueMessage(MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0002)); CM_FALLTHROUGH; case cmPolicies::OLD: @@ -4000,7 +4073,7 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0002)); return true; case cmPolicies::NEW: @@ -4079,7 +4152,7 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath, << "to work accidentally and is being allowed for " << "compatibility."; /* clang-format on */ - this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior does not warn. @@ -4098,7 +4171,7 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath, << " " << srcPath << "\n" << "Specify a unique binary directory name."; /* clang-format on */ - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); break; } @@ -4183,7 +4256,7 @@ bool cmMakefile::SetPolicy(const char* id, cmPolicies::PolicyStatus status) if (!cmPolicies::GetPolicyID(id, /* out */ pid)) { std::ostringstream e; e << "Policy \"" << id << "\" is not known to this version of CMake."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } return this->SetPolicy(pid, status); @@ -4196,14 +4269,18 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, if (status != cmPolicies::NEW && cmPolicies::GetPolicyStatus(id) == cmPolicies::REQUIRED_ALWAYS) { std::string msg = cmPolicies::GetRequiredAlwaysPolicyError(id); - this->IssueMessage(cmake::FATAL_ERROR, msg); + this->IssueMessage(MessageType::FATAL_ERROR, msg); return false; } // Deprecate old policies, especially those that require a lot // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0063) { - this->IssueMessage(cmake::DEPRECATION_WARNING, + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0065 && + !(this->GetCMakeInstance()->GetIsInTryCompile() && + ( + // Policies set by cmCoreTryCompile::TryCompileCode. + id == cmPolicies::CMP0065))) { + this->IssueMessage(MessageType::DEPRECATION_WARNING, cmPolicies::GetPolicyDeprecatedWarning(id)); } @@ -4230,7 +4307,7 @@ void cmMakefile::PushPolicy(bool weak, cmPolicies::PolicyMap const& pm) void cmMakefile::PopPolicy() { if (!this->StateSnapshot.PopPolicy()) { - this->IssueMessage(cmake::FATAL_ERROR, + this->IssueMessage(MessageType::FATAL_ERROR, "cmake_policy POP without matching PUSH"); } } @@ -4242,7 +4319,7 @@ void cmMakefile::PopSnapshot(bool reportError) // reject any still-open nested policy scopes with an error. while (!this->StateSnapshot.CanPopPolicyScope()) { if (reportError) { - this->IssueMessage(cmake::FATAL_ERROR, + this->IssueMessage(MessageType::FATAL_ERROR, "cmake_policy PUSH without matching POP"); reportError = false; } @@ -4335,7 +4412,7 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Backtrace); } return false; @@ -4382,7 +4459,7 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Backtrace); } return false; @@ -4402,7 +4479,7 @@ const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Backtrace); } return nullptr; @@ -4425,7 +4502,7 @@ const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), this->Backtrace); } return nullptr; @@ -4450,7 +4527,7 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, std::ostringstream e; e << "CMAKE_C_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " "not fully configured for this compiler."; - this->IssueMessage(cmake::INTERNAL_ERROR, e.str()); + this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); // Return true so the caller does not try to lookup the default standard. return true; } @@ -4460,7 +4537,7 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, e << "The CMAKE_C_STANDARD_DEFAULT variable contains an " "invalid value: \"" << defaultCStandard << "\"."; - this->IssueMessage(cmake::INTERNAL_ERROR, e.str()); + this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); return false; } @@ -4480,7 +4557,7 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, std::ostringstream e; e << "The C_STANDARD property on target \"" << target->GetName() << "\" contained an invalid value: \"" << existingCStandard << "\"."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -4534,7 +4611,7 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, std::ostringstream e; e << "CMAKE_CXX_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " "not fully configured for this compiler."; - this->IssueMessage(cmake::INTERNAL_ERROR, e.str()); + this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); // Return true so the caller does not try to lookup the default standard. return true; } @@ -4544,7 +4621,7 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, e << "The CMAKE_CXX_STANDARD_DEFAULT variable contains an " "invalid value: \"" << defaultCxxStandard << "\"."; - this->IssueMessage(cmake::INTERNAL_ERROR, e.str()); + this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); return false; } @@ -4568,7 +4645,7 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, std::ostringstream e; e << "The CXX_STANDARD property on target \"" << target->GetName() << "\" contained an invalid value: \"" << existingCxxStandard << "\"."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -4648,8 +4725,8 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), this->Backtrace); } return false; } @@ -4669,8 +4746,8 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), this->Backtrace); } return false; } @@ -4747,8 +4824,8 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, if (error) { *error = e.str(); } else { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Backtrace); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + e.str(), this->Backtrace); } return false; } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index b30f281b5..70a5689e1 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -18,13 +18,13 @@ #include "cmAlgorithms.h" #include "cmListFileCache.h" +#include "cmMessageType.h" #include "cmNewLineStyle.h" #include "cmPolicies.h" #include "cmSourceFileLocationKind.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmTarget.h" -#include "cmake.h" #if defined(CMAKE_BUILD_WITH_CMAKE) # include "cmSourceGroup.h" @@ -46,6 +46,7 @@ class cmState; class cmTest; class cmTestGenerator; class cmVariableWatch; +class cmake; /** A type-safe wrapper for a string representing a directory id. */ class cmDirectoryId @@ -64,8 +65,6 @@ public: */ class cmMakefile { - CM_DISABLE_COPY(cmMakefile) - public: /* Mark a variable as used */ void MarkVariableAsUsed(const std::string& var); @@ -83,13 +82,15 @@ public: */ ~cmMakefile(); - cmDirectoryId GetDirectoryId() const; + cmMakefile(cmMakefile const&) = delete; + cmMakefile& operator=(cmMakefile const&) = delete; - bool ReadListFile(const char* filename); + cmDirectoryId GetDirectoryId() const; - bool ReadDependentFile(const char* filename, bool noPolicyScope = true); + bool ReadListFile(const std::string& filename); - bool ProcessBuildsystemFile(const char* filename); + bool ReadDependentFile(const std::string& filename, + bool noPolicyScope = true); /** * Add a function blocker to this makefile @@ -689,7 +690,13 @@ public: /** * Return a location of a file in cmake or custom modules directory */ - std::string GetModulesFile(const char* name) const; + std::string GetModulesFile(const std::string& name) const + { + bool system; + return this->GetModulesFile(name, system); + } + + std::string GetModulesFile(const std::string& name, bool& system) const; ///! Set/Get a property of this directory void SetProperty(const std::string& prop, const char* value); @@ -774,20 +781,23 @@ public: /** Helper class to push and pop scopes automatically. */ class ScopePushPop { - CM_DISABLE_COPY(ScopePushPop) public: ScopePushPop(cmMakefile* m) : Makefile(m) { this->Makefile->PushScope(); } + ~ScopePushPop() { this->Makefile->PopScope(); } + ScopePushPop(ScopePushPop const&) = delete; + ScopePushPop& operator=(ScopePushPop const&) = delete; + private: cmMakefile* Makefile; }; - void IssueMessage(cmake::MessageType t, std::string const& text) const; + void IssueMessage(MessageType t, std::string const& text) const; /** Set whether or not to report a CMP0000 violation. */ void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; } @@ -860,6 +870,12 @@ public: std::deque<std::vector<std::string>> FindPackageRootPathStack; void MaybeWarnCMP0074(std::string const& pkg); + void MaybeWarnUninitialized(std::string const& variable, + const char* sourceFilename) const; + bool IsProjectFile(const char* filename) const; + + int GetRecursionDepth() const; + void SetRecursionDepth(int recursionDepth); protected: // add link libraries and directories to the target @@ -921,6 +937,7 @@ protected: private: cmStateSnapshot StateSnapshot; cmListFileBacktrace Backtrace; + int RecursionDepth; void ReadListFile(cmListFile const& listFile, const std::string& filenametoread); @@ -973,15 +990,18 @@ private: friend class BuildsystemFileScope; // CMP0053 == old - cmake::MessageType ExpandVariablesInStringOld( - std::string& errorstr, std::string& source, bool escapeQuotes, - bool noEscapes, bool atOnly, const char* filename, long line, - bool removeEmpty, bool replaceAt) const; + MessageType ExpandVariablesInStringOld(std::string& errorstr, + std::string& source, + bool escapeQuotes, bool noEscapes, + bool atOnly, const char* filename, + long line, bool removeEmpty, + bool replaceAt) const; // CMP0053 == new - cmake::MessageType ExpandVariablesInStringNew( - std::string& errorstr, std::string& source, bool escapeQuotes, - bool noEscapes, bool atOnly, const char* filename, long line, - bool removeEmpty, bool replaceAt) const; + MessageType ExpandVariablesInStringNew(std::string& errorstr, + std::string& source, + bool escapeQuotes, bool noEscapes, + bool atOnly, const char* filename, + long line, bool replaceAt) const; /** * Old version of GetSourceFileWithOutput(const std::string&) kept for * backward-compatibility. It implements a linear search and support @@ -1025,7 +1045,7 @@ private: bool CheckCMP0000; std::set<std::string> WarnedCMP0074; bool IsSourceFileTryCompile; - mutable bool SuppressWatches; + mutable bool SuppressSideEffects; }; #endif diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 846b12ce1..e8ae5ae36 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -6,6 +6,7 @@ #include <memory> // IWYU pragma: keep #include <sstream> #include <string> +#include <utility> #include <vector> #include "cmGeneratedFileStream.h" @@ -24,7 +25,6 @@ #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmake.h" cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator( cmGeneratorTarget* target) @@ -95,7 +95,13 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( const bool hasCUDA = (std::find(closure->Languages.begin(), closure->Languages.end(), cuda_lang) != closure->Languages.end()); - if (!hasCUDA) { + + bool doDeviceLinking = true; + if (const char* resolveDeviceSymbols = + this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { + doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); + } + if (!hasCUDA || !doDeviceLinking) { return; } @@ -316,7 +322,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) std::string outpathImp; if (relink) { outpath = this->Makefile->GetCurrentBinaryDirectory(); - outpath += cmake::GetCMakeFilesDirectory(); + outpath += "/CMakeFiles"; outpath += "/CMakeRelink.dir"; cmSystemTools::MakeDirectory(outpath); outpath += "/"; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 2d2915c21..5a1ef4efe 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -6,6 +6,7 @@ #include <memory> // IWYU pragma: keep #include <sstream> #include <stddef.h> +#include <utility> #include <vector> #include "cmGeneratedFileStream.h" @@ -24,7 +25,6 @@ #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmake.h" cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator( cmGeneratorTarget* target) @@ -133,9 +133,12 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() (std::find(closure->Languages.begin(), closure->Languages.end(), cuda_lang) != closure->Languages.end()); - const bool resolveDeviceSymbols = - this->GeneratorTarget->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS"); - if (hasCUDA && resolveDeviceSymbols) { + bool doDeviceLinking = false; + if (const char* resolveDeviceSymbols = + this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { + doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); + } + if (hasCUDA && doDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, false); } @@ -168,7 +171,12 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) const bool hasCUDA = (std::find(closure->Languages.begin(), closure->Languages.end(), cuda_lang) != closure->Languages.end()); - if (hasCUDA) { + bool doDeviceLinking = true; + if (const char* resolveDeviceSymbols = + this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { + doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); + } + if (hasCUDA && doDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, relink); } @@ -209,7 +217,12 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) const bool hasCUDA = (std::find(closure->Languages.begin(), closure->Languages.end(), cuda_lang) != closure->Languages.end()); - if (hasCUDA) { + bool doDeviceLinking = true; + if (const char* resolveDeviceSymbols = + this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { + doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); + } + if (hasCUDA && doDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, relink); } @@ -498,7 +511,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( outpath += "/"; } else if (relink) { outpath = this->Makefile->GetCurrentBinaryDirectory(); - outpath += cmake::GetCMakeFilesDirectory(); + outpath += "/CMakeFiles"; outpath += "/CMakeRelink.dir"; cmSystemTools::MakeDirectory(outpath); outpath += "/"; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index f423560eb..af34169c3 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -97,6 +97,9 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags( this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage); // LINK_OPTIONS are escaped. this->LocalGenerator->AppendCompileOptions(flags, opts); + + this->LocalGenerator->AppendPositionIndependentLinkerFlags( + flags, this->GeneratorTarget, this->ConfigName, linkLanguage); } void cmMakefileTargetGenerator::CreateRuleFile() @@ -400,7 +403,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( err << "Warning: Source file \"" << source.GetFullPath() << "\" is listed multiple times for target \"" << this->GeneratorTarget->GetName() << "\"."; - cmSystemTools::Message(err.str().c_str(), "Warning"); + cmSystemTools::Message(err.str(), "Warning"); return; } @@ -432,8 +435,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( objFullPath = cmSystemTools::CollapseFullPath(objFullPath); std::string srcFullPath = cmSystemTools::CollapseFullPath(source.GetFullPath()); - this->LocalGenerator->AddImplicitDepends( - this->GeneratorTarget, lang, objFullPath.c_str(), srcFullPath.c_str()); + this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang, + objFullPath, srcFullPath); } void cmMakefileTargetGenerator::WriteObjectBuildFile( @@ -590,7 +593,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( // mingw32-make incorrectly interprets 'a\ b c' as 'a b' and 'c' // (but 'a\ b "c"' as 'a\', 'b', and 'c'!). Workaround this by // avoiding a trailing backslash in the argument. - targetOutPathCompilePDB[targetOutPathCompilePDB.size() - 1] = '/'; + targetOutPathCompilePDB.back() = '/'; } } cmRulePlaceholderExpander::RuleVariables vars; @@ -684,6 +687,17 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( std::string langIncludes = std::string("$(") + lang + "_INCLUDES)"; compileCommand.replace(compileCommand.find(langIncludes), langIncludes.size(), this->GetIncludes(lang)); + + const char* eliminate[] = { + this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"), + this->Makefile->GetDefinition("CMAKE_END_TEMP_FILE") + }; + for (const char* el : eliminate) { + if (el) { + cmSystemTools::ReplaceString(compileCommand, el, ""); + } + } + this->GlobalGenerator->AddCXXCompileCommand( source.GetFullPath(), workingDirectory, compileCommand); } @@ -802,7 +816,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( lang_has_assembly && this->LocalGenerator->GetCreateAssemblySourceRules(); if (do_preprocess_rules || do_assembly_rules) { std::vector<std::string> force_depends; - force_depends.push_back("cmake_force"); + force_depends.emplace_back("cmake_force"); std::string::size_type dot_pos = relativeObj.rfind('.'); std::string relativeObjBase = relativeObj.substr(0, dot_pos); dot_pos = obj.rfind('.'); @@ -1199,8 +1213,7 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( std::string objFullPath = cmSystemTools::CollapseFullPath(outputs[0]); std::string srcFullPath = cmSystemTools::CollapseFullPath(idi.second); this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, idi.first, - objFullPath.c_str(), - srcFullPath.c_str()); + objFullPath, srcFullPath); } } @@ -1208,7 +1221,7 @@ void cmMakefileTargetGenerator::MakeEchoProgress( cmLocalUnixMakefileGenerator3::EchoProgress& progress) const { progress.Dir = this->LocalGenerator->GetBinaryDirectory(); - progress.Dir += cmake::GetCMakeFilesDirectory(); + progress.Dir += "/CMakeFiles"; std::ostringstream progressArg; progressArg << "$(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")"; progress.Arg = progressArg.str(); @@ -1233,8 +1246,9 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( } for (std::string const& obj : this->Objects) { *this->BuildFileStream << " " << lineContinue << "\n"; - *this->BuildFileStream << this->LocalGenerator->ConvertToQuotedOutputPath( - obj.c_str(), useWatcomQuote); + *this->BuildFileStream + << cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath( + obj, useWatcomQuote); } *this->BuildFileStream << "\n"; @@ -1255,8 +1269,9 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( object = this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, obj); *this->BuildFileStream << " " << lineContinue << "\n"; - *this->BuildFileStream << this->LocalGenerator->ConvertToQuotedOutputPath( - obj.c_str(), useWatcomQuote); + *this->BuildFileStream + << cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath( + obj, useWatcomQuote); } *this->BuildFileStream << "\n" << "\n"; @@ -1303,11 +1318,10 @@ public: private: std::string MaybeConvertToRelativePath(std::string const& obj) { - if (!cmOutputConverter::ContainedInDirectory( - this->StateDir.GetCurrentBinary(), obj, this->StateDir)) { + if (!this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), obj)) { return obj; } - return cmOutputConverter::ForceToRelativePath( + return cmSystemTools::ForceToRelativePath( this->StateDir.GetCurrentBinary(), obj); } diff --git a/Source/cmMathCommand.cxx b/Source/cmMathCommand.cxx index a50e5fc33..48b9a27ad 100644 --- a/Source/cmMathCommand.cxx +++ b/Source/cmMathCommand.cxx @@ -4,8 +4,8 @@ #include "cmExprParserHelper.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cm_kwiml.h" -#include "cmake.h" #include <stdio.h> @@ -104,7 +104,7 @@ bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args) std::string const& w = helper.GetWarning(); if (!w.empty()) { - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w); } this->Makefile->AddDefinition(outputVariable, buffer); diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 5a341bd2b..95f5fcbbe 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -4,9 +4,9 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmMessenger.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -20,26 +20,26 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, } std::vector<std::string>::const_iterator i = args.begin(); - cmake::MessageType type = cmake::MESSAGE; + MessageType type = MessageType::MESSAGE; bool status = false; bool fatal = false; if (*i == "SEND_ERROR") { - type = cmake::FATAL_ERROR; + type = MessageType::FATAL_ERROR; ++i; } else if (*i == "FATAL_ERROR") { fatal = true; - type = cmake::FATAL_ERROR; + type = MessageType::FATAL_ERROR; ++i; } else if (*i == "WARNING") { - type = cmake::WARNING; + type = MessageType::WARNING; ++i; } else if (*i == "AUTHOR_WARNING") { if (this->Makefile->IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && !this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { fatal = true; - type = cmake::AUTHOR_ERROR; + type = MessageType::AUTHOR_ERROR; } else if (!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { - type = cmake::AUTHOR_WARNING; + type = MessageType::AUTHOR_WARNING; } else { return true; } @@ -50,10 +50,10 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, } else if (*i == "DEPRECATION") { if (this->Makefile->IsOn("CMAKE_ERROR_DEPRECATED")) { fatal = true; - type = cmake::DEPRECATION_ERROR; + type = MessageType::DEPRECATION_ERROR; } else if ((!this->Makefile->IsSet("CMAKE_WARN_DEPRECATED") || this->Makefile->IsOn("CMAKE_WARN_DEPRECATED"))) { - type = cmake::DEPRECATION_WARNING; + type = MessageType::DEPRECATION_WARNING; } else { return true; } @@ -62,7 +62,7 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, std::string message = cmJoin(cmMakeRange(i, args.end()), std::string()); - if (type != cmake::MESSAGE) { + if (type != MessageType::MESSAGE) { // we've overridden the message type, above, so display it directly cmMessenger* m = this->Makefile->GetMessenger(); m->DisplayMessage(type, message, this->Makefile->GetBacktrace()); @@ -70,7 +70,7 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, if (status) { this->Makefile->DisplayStatus(message.c_str(), -1); } else { - cmSystemTools::Message(message.c_str()); + cmSystemTools::Message(message); } } if (fatal) { diff --git a/Source/cmMessageType.h b/Source/cmMessageType.h new file mode 100644 index 000000000..b57b86bee --- /dev/null +++ b/Source/cmMessageType.h @@ -0,0 +1,21 @@ +/* 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 + +#include "cmConfigure.h" // IWYU pragma: keep + +enum class MessageType +{ + AUTHOR_WARNING, + AUTHOR_ERROR, + FATAL_ERROR, + INTERNAL_ERROR, + MESSAGE, + WARNING, + LOG, + DEPRECATION_ERROR, + DEPRECATION_WARNING +}; + +#endif diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index a81428aed..1d790e2e8 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -4,7 +4,6 @@ #include "cmAlgorithms.h" #include "cmDocumentationFormatter.h" -#include "cmState.h" #include "cmSystemTools.h" #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -13,47 +12,47 @@ #include <sstream> -cmake::MessageType cmMessenger::ConvertMessageType(cmake::MessageType t) const +MessageType cmMessenger::ConvertMessageType(MessageType t) const { bool warningsAsErrors; - if (t == cmake::AUTHOR_WARNING || t == cmake::AUTHOR_ERROR) { + if (t == MessageType::AUTHOR_WARNING || t == MessageType::AUTHOR_ERROR) { warningsAsErrors = this->GetDevWarningsAsErrors(); - if (warningsAsErrors && t == cmake::AUTHOR_WARNING) { - t = cmake::AUTHOR_ERROR; - } else if (!warningsAsErrors && t == cmake::AUTHOR_ERROR) { - t = cmake::AUTHOR_WARNING; + if (warningsAsErrors && t == MessageType::AUTHOR_WARNING) { + t = MessageType::AUTHOR_ERROR; + } else if (!warningsAsErrors && t == MessageType::AUTHOR_ERROR) { + t = MessageType::AUTHOR_WARNING; } - } else if (t == cmake::DEPRECATION_WARNING || - t == cmake::DEPRECATION_ERROR) { + } else if (t == MessageType::DEPRECATION_WARNING || + t == MessageType::DEPRECATION_ERROR) { warningsAsErrors = this->GetDeprecatedWarningsAsErrors(); - if (warningsAsErrors && t == cmake::DEPRECATION_WARNING) { - t = cmake::DEPRECATION_ERROR; - } else if (!warningsAsErrors && t == cmake::DEPRECATION_ERROR) { - t = cmake::DEPRECATION_WARNING; + if (warningsAsErrors && t == MessageType::DEPRECATION_WARNING) { + t = MessageType::DEPRECATION_ERROR; + } else if (!warningsAsErrors && t == MessageType::DEPRECATION_ERROR) { + t = MessageType::DEPRECATION_WARNING; } } return t; } -bool cmMessenger::IsMessageTypeVisible(cmake::MessageType t) const +bool cmMessenger::IsMessageTypeVisible(MessageType t) const { bool isVisible = true; - if (t == cmake::DEPRECATION_ERROR) { + if (t == MessageType::DEPRECATION_ERROR) { if (!this->GetDeprecatedWarningsAsErrors()) { isVisible = false; } - } else if (t == cmake::DEPRECATION_WARNING) { + } else if (t == MessageType::DEPRECATION_WARNING) { if (this->GetSuppressDeprecatedWarnings()) { isVisible = false; } - } else if (t == cmake::AUTHOR_ERROR) { + } else if (t == MessageType::AUTHOR_ERROR) { if (!this->GetDevWarningsAsErrors()) { isVisible = false; } - } else if (t == cmake::AUTHOR_WARNING) { + } else if (t == MessageType::AUTHOR_WARNING) { if (this->GetSuppressDevWarnings()) { isVisible = false; } @@ -62,22 +61,22 @@ bool cmMessenger::IsMessageTypeVisible(cmake::MessageType t) const return isVisible; } -static bool printMessagePreamble(cmake::MessageType t, std::ostream& msg) +static bool printMessagePreamble(MessageType t, std::ostream& msg) { // Construct the message header. - if (t == cmake::FATAL_ERROR) { + if (t == MessageType::FATAL_ERROR) { msg << "CMake Error"; - } else if (t == cmake::INTERNAL_ERROR) { + } else if (t == MessageType::INTERNAL_ERROR) { msg << "CMake Internal Error (please report a bug)"; - } else if (t == cmake::LOG) { + } else if (t == MessageType::LOG) { msg << "CMake Debug Log"; - } else if (t == cmake::DEPRECATION_ERROR) { + } else if (t == MessageType::DEPRECATION_ERROR) { msg << "CMake Deprecation Error"; - } else if (t == cmake::DEPRECATION_WARNING) { + } else if (t == MessageType::DEPRECATION_WARNING) { msg << "CMake Deprecation Warning"; - } else if (t == cmake::AUTHOR_WARNING) { + } else if (t == MessageType::AUTHOR_WARNING) { msg << "CMake Warning (dev)"; - } else if (t == cmake::AUTHOR_ERROR) { + } else if (t == MessageType::AUTHOR_ERROR) { msg << "CMake Error (dev)"; } else { msg << "CMake Warning"; @@ -93,13 +92,13 @@ void printMessageText(std::ostream& msg, std::string const& text) formatter.PrintFormatted(msg, text.c_str()); } -void displayMessage(cmake::MessageType t, std::ostringstream& msg) +void displayMessage(MessageType t, std::ostringstream& msg) { // Add a note about warning suppression. - if (t == cmake::AUTHOR_WARNING) { + if (t == MessageType::AUTHOR_WARNING) { msg << "This warning is for project developers. Use -Wno-dev to suppress " "it."; - } else if (t == cmake::AUTHOR_ERROR) { + } else if (t == MessageType::AUTHOR_ERROR) { msg << "This error is for project developers. Use -Wno-error=dev to " "suppress " "it."; @@ -110,7 +109,7 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg) #if defined(CMAKE_BUILD_WITH_CMAKE) // Add a C++ stack trace to internal errors. - if (t == cmake::INTERNAL_ERROR) { + if (t == MessageType::INTERNAL_ERROR) { std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0); if (!stack.empty()) { if (cmHasLiteralPrefix(stack, "WARNING:")) { @@ -122,27 +121,22 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg) #endif // Output the message. - if (t == cmake::FATAL_ERROR || t == cmake::INTERNAL_ERROR || - t == cmake::DEPRECATION_ERROR || t == cmake::AUTHOR_ERROR) { + if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR || + t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) { cmSystemTools::SetErrorOccured(); - cmSystemTools::Message(msg.str().c_str(), "Error"); + cmSystemTools::Message(msg.str(), "Error"); } else { - cmSystemTools::Message(msg.str().c_str(), "Warning"); + cmSystemTools::Message(msg.str(), "Warning"); } } -cmMessenger::cmMessenger(cmState* state) - : State(state) -{ -} - -void cmMessenger::IssueMessage(cmake::MessageType t, const std::string& text, +void cmMessenger::IssueMessage(MessageType t, const std::string& text, const cmListFileBacktrace& backtrace) const { bool force = false; if (!force) { // override the message type, if needed, for warnings and errors - cmake::MessageType override = this->ConvertMessageType(t); + MessageType override = this->ConvertMessageType(t); if (override != t) { t = override; force = true; @@ -155,7 +149,7 @@ void cmMessenger::IssueMessage(cmake::MessageType t, const std::string& text, this->DisplayMessage(t, text, backtrace); } -void cmMessenger::DisplayMessage(cmake::MessageType t, const std::string& text, +void cmMessenger::DisplayMessage(MessageType t, const std::string& text, const cmListFileBacktrace& backtrace) const { std::ostringstream msg; @@ -173,31 +167,3 @@ void cmMessenger::DisplayMessage(cmake::MessageType t, const std::string& text, displayMessage(t, msg); } - -bool cmMessenger::GetSuppressDevWarnings() const -{ - const char* cacheEntryValue = - this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_WARNINGS"); - return cmSystemTools::IsOn(cacheEntryValue); -} - -bool cmMessenger::GetSuppressDeprecatedWarnings() const -{ - const char* cacheEntryValue = - this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); - return cacheEntryValue && cmSystemTools::IsOff(cacheEntryValue); -} - -bool cmMessenger::GetDevWarningsAsErrors() const -{ - const char* cacheEntryValue = - this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS"); - return cacheEntryValue && cmSystemTools::IsOff(cacheEntryValue); -} - -bool cmMessenger::GetDeprecatedWarningsAsErrors() const -{ - const char* cacheEntryValue = - this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED"); - return cmSystemTools::IsOn(cacheEntryValue); -} diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h index 4aafbd40b..cf15adfc1 100644 --- a/Source/cmMessenger.h +++ b/Source/cmMessenger.h @@ -6,34 +6,56 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmListFileCache.h" -#include "cmake.h" +#include "cmMessageType.h" #include <string> -class cmState; - class cmMessenger { public: - cmMessenger(cmState* state); - void IssueMessage( - cmake::MessageType t, std::string const& text, + MessageType t, std::string const& text, cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; - void DisplayMessage(cmake::MessageType t, std::string const& text, + void DisplayMessage(MessageType t, std::string const& text, cmListFileBacktrace const& backtrace) const; - bool GetSuppressDevWarnings() const; - bool GetSuppressDeprecatedWarnings() const; - bool GetDevWarningsAsErrors() const; - bool GetDeprecatedWarningsAsErrors() const; + void SetSuppressDevWarnings(bool suppress) + { + this->SuppressDevWarnings = suppress; + } + void SetSuppressDeprecatedWarnings(bool suppress) + { + this->SuppressDeprecatedWarnings = suppress; + } + void SetDevWarningsAsErrors(bool error) + { + this->DevWarningsAsErrors = error; + } + void SetDeprecatedWarningsAsErrors(bool error) + { + this->DeprecatedWarningsAsErrors = error; + } + + bool GetSuppressDevWarnings() const { return this->SuppressDevWarnings; } + bool GetSuppressDeprecatedWarnings() const + { + return this->SuppressDeprecatedWarnings; + } + bool GetDevWarningsAsErrors() const { return this->DevWarningsAsErrors; } + bool GetDeprecatedWarningsAsErrors() const + { + return this->DeprecatedWarningsAsErrors; + } private: - bool IsMessageTypeVisible(cmake::MessageType t) const; - cmake::MessageType ConvertMessageType(cmake::MessageType t) const; + bool IsMessageTypeVisible(MessageType t) const; + MessageType ConvertMessageType(MessageType t) const; - cmState* State; + bool SuppressDevWarnings = false; + bool SuppressDeprecatedWarnings = false; + bool DevWarningsAsErrors = false; + bool DeprecatedWarningsAsErrors = false; }; #endif diff --git a/Source/cmNewLineStyle.cxx b/Source/cmNewLineStyle.cxx index 5500eba65..3f6523e09 100644 --- a/Source/cmNewLineStyle.cxx +++ b/Source/cmNewLineStyle.cxx @@ -4,10 +4,7 @@ #include <stddef.h> -cmNewLineStyle::cmNewLineStyle() - : NewLineStyle(Invalid) -{ -} +cmNewLineStyle::cmNewLineStyle() = default; bool cmNewLineStyle::IsValid() const { diff --git a/Source/cmNewLineStyle.h b/Source/cmNewLineStyle.h index 397cd2c50..f1a7bc6e0 100644 --- a/Source/cmNewLineStyle.h +++ b/Source/cmNewLineStyle.h @@ -33,7 +33,7 @@ public: const std::string GetCharacters() const; private: - Style NewLineStyle; + Style NewLineStyle = Invalid; }; #endif diff --git a/Source/cmNinjaLinkLineComputer.h b/Source/cmNinjaLinkLineComputer.h index 0ed53f45a..b2b2e84e1 100644 --- a/Source/cmNinjaLinkLineComputer.h +++ b/Source/cmNinjaLinkLineComputer.h @@ -16,13 +16,14 @@ class cmStateDirectory; class cmNinjaLinkLineComputer : public cmLinkLineComputer { - CM_DISABLE_COPY(cmNinjaLinkLineComputer) - public: cmNinjaLinkLineComputer(cmOutputConverter* outputConverter, cmStateDirectory const& stateDir, cmGlobalNinjaGenerator const* gg); + cmNinjaLinkLineComputer(cmNinjaLinkLineComputer const&) = delete; + cmNinjaLinkLineComputer& operator=(cmNinjaLinkLineComputer const&) = delete; + std::string ConvertToLinkReference(std::string const& input) const override; private: diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 8909e0663..cbc01035f 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -9,6 +9,7 @@ #include <memory> // IWYU pragma: keep #include <set> #include <sstream> +#include <utility> #include "cmAlgorithms.h" #include "cmCustomCommandGenerator.h" @@ -30,20 +31,13 @@ #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmake.h" class cmCustomCommand; cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator( cmGeneratorTarget* target) : cmNinjaTargetGenerator(target) - , TargetNameOut() - , TargetNameSO() - , TargetNameReal() - , TargetNameImport() - , TargetNamePDB() , TargetLinkLanguage("") - , DeviceLinkObject() { this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName()); if (target->GetType() == cmStateEnums::EXECUTABLE) { @@ -382,7 +376,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands()); linkCmds.insert(linkCmds.begin(), "$PRE_LINK"); - linkCmds.push_back("$POST_BUILD"); + linkCmds.emplace_back("$POST_BUILD"); std::string linkCmd = this->GetLocalGenerator()->BuildCommandLine(linkCmds); @@ -410,7 +404,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) std::vector<std::string> commandLines; commandLines.push_back(cmakeCommand + " -E cmake_symlink_executable $in $out"); - commandLines.push_back("$POST_BUILD"); + commandLines.emplace_back("$POST_BUILD"); this->GetGlobalGenerator()->AddRule( "CMAKE_SYMLINK_EXECUTABLE", @@ -428,7 +422,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) std::vector<std::string> commandLines; commandLines.push_back(cmakeCommand + " -E cmake_symlink_library $in $SONAME $out"); - commandLines.push_back("$POST_BUILD"); + commandLines.emplace_back("$POST_BUILD"); this->GetGlobalGenerator()->AddRule( "CMAKE_SYMLINK_LIBRARY", @@ -506,7 +500,6 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact, /*realname=*/true)); cmakeCommand += targetOutputReal; - cmakeCommand += " || true"; linkCmds.push_back(std::move(cmakeCommand)); } return linkCmds; @@ -573,22 +566,23 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() (std::find(closure->Languages.begin(), closure->Languages.end(), cuda_lang) != closure->Languages.end()); - bool shouldHaveDeviceLinking = false; - switch (genTarget.GetType()) { - case cmStateEnums::SHARED_LIBRARY: - case cmStateEnums::MODULE_LIBRARY: - case cmStateEnums::EXECUTABLE: - shouldHaveDeviceLinking = true; - break; - case cmStateEnums::STATIC_LIBRARY: - shouldHaveDeviceLinking = - genTarget.GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS"); - break; - default: - break; + bool doDeviceLinking = false; + if (const char* resolveDeviceSymbols = + genTarget.GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { + doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); + } else { + switch (genTarget.GetType()) { + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::EXECUTABLE: + doDeviceLinking = true; + break; + default: + break; + } } - if (!(shouldHaveDeviceLinking && hasCUDA)) { + if (!(doDeviceLinking && hasCUDA)) { return; } @@ -724,8 +718,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() globalGen.GetRuleCmdLength(this->LanguageLinkerDeviceRule()); const std::string rspfile = this->ConvertToNinjaPath( - std::string(cmake::GetCMakeFilesDirectoryPostSlash()) + - genTarget.GetName() + ".rsp"); + std::string("CMakeFiles/") + genTarget.GetName() + ".rsp"); // Gather order-only dependencies. cmNinjaDeps orderOnlyDeps; @@ -1010,8 +1003,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } const std::string rspfile = this->ConvertToNinjaPath( - std::string(cmake::GetCMakeFilesDirectoryPostSlash()) + gt.GetName() + - ".rsp"); + std::string("CMakeFiles/") + gt.GetName() + ".rsp"); // Gather order-only dependencies. cmNinjaDeps orderOnlyDeps; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 7ac8d1b91..82bc5f204 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -10,6 +10,7 @@ #include <map> #include <memory> // IWYU pragma: keep #include <sstream> +#include <utility> #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" @@ -18,6 +19,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalNinjaGenerator.h" +#include "cmListFileCache.h" // for BT #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" @@ -54,10 +56,8 @@ cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target) : cmCommonTargetGenerator(target) , MacOSXContentGenerator(nullptr) , OSXBundleGenerator(nullptr) - , MacContentFolders() , LocalGenerator( static_cast<cmLocalNinjaGenerator*>(target->GetLocalGenerator())) - , Objects() { MacOSXContentGenerator = new MacOSXContentGeneratorType(this); } @@ -173,8 +173,28 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags, bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const { - return (this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" + - lang) == "msvc"); + std::string const& deptype = + this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" + lang); + if (deptype == "msvc") { + return true; + } + if (deptype == "intel") { + // Ninja does not really define "intel", but we use it to switch based + // on whether this environment supports "gcc" or "msvc" deptype. + if (!this->GetGlobalGenerator()->SupportsMultilineDepfile()) { + // This ninja version is too old to support the Intel depfile format. + // Fall back to msvc deptype. + return true; + } + if ((this->Makefile->GetHomeDirectory().find(' ') != std::string::npos) || + (this->Makefile->GetHomeOutputDirectory().find(' ') != + std::string::npos)) { + // The Intel compiler does not properly escape spaces in a depfile. + // Fall back to msvc deptype. + return true; + } + } + return false; } // TODO: Refactor with @@ -431,6 +451,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) vars.TargetCompilePDB = "$TARGET_COMPILE_PDB"; vars.ObjectDir = "$OBJECT_DIR"; vars.ObjectFileDir = "$OBJECT_FILE_DIR"; + if (lang == "Swift") { + vars.SwiftAuxiliarySources = "$SWIFT_AUXILIARY_SOURCES"; + vars.SwiftModuleName = "$SWIFT_MODULE_NAME"; + } // For some cases we do an explicit preprocessor invocation. bool const explicitPP = this->NeedExplicitPreprocessing(lang); @@ -626,10 +650,6 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) } } else { deptype = "gcc"; - const char* langdeptype = mf->GetDefinition("CMAKE_NINJA_DEPTYPE_" + lang); - if (langdeptype) { - deptype = langdeptype; - } depfile = "$DEP_FILE"; const std::string flagsName = "CMAKE_DEPFILE_FLAGS_" + lang; std::string depfileFlags = mf->GetSafeDefinition(flagsName); @@ -901,6 +921,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["FLAGS"] = this->ComputeFlagsForObject(source, language); vars["DEFINES"] = this->ComputeDefines(source, language); vars["INCLUDES"] = this->ComputeIncludes(source, language); + if (language == "Swift") { + // The swift compiler needs all the sources besides the one being compiled + // in order to do the type checking. List all these "auxiliary" sources. + std::string aux_sources; + cmGeneratorTarget::KindedSources const& sources = + this->GeneratorTarget->GetKindedSources(this->GetConfigName()); + for (cmGeneratorTarget::SourceAndKind const& src : sources.Sources) { + if (src.Source.Value == source) { + continue; + } + aux_sources += " " + this->GetSourceFilePath(src.Source.Value); + } + vars["SWIFT_AUXILIARY_SOURCES"] = aux_sources; + + if (const char* name = + this->GeneratorTarget->GetProperty("SWIFT_MODULE_NAME")) { + vars["SWIFT_MODULE_NAME"] = name; + } else { + vars["SWIFT_MODULE_NAME"] = this->GeneratorTarget->GetName(); + } + } if (!this->NeedDepTypeMSVC(language)) { bool replaceExt(false); @@ -959,7 +1000,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( // (either attached to this source file or another one), assume that one of // the target dependencies, OBJECT_DEPENDS or header file custom commands // will rebuild the file. - if (source->GetPropertyAsBool("GENERATED") && + if (source->GetIsGenerated() && !source->GetPropertyAsBool("__CMAKE_GENERATED_BY_CMAKE") && !source->GetCustomCommand() && !this->GetGlobalGenerator()->HasCustomCommandOutput(sourceFileName)) { @@ -1103,6 +1144,10 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) mod_dir = this->Makefile->GetCurrentBinaryDirectory(); } tdi["module-dir"] = mod_dir; + tdi["submodule-sep"] = + this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP"); + tdi["submodule-ext"] = + this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT"); } tdi["dir-cur-bld"] = this->Makefile->GetCurrentBinaryDirectory(); diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index cc6d4b988..95fcf66f4 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -14,7 +14,6 @@ #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmake.h" #include <algorithm> #include <iterator> @@ -27,15 +26,13 @@ cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( { } -cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() -{ -} +cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() = default; void cmNinjaUtilityTargetGenerator::Generate() { std::string utilCommandName = this->GetLocalGenerator()->GetCurrentBinaryDirectory(); - utilCommandName += cmake::GetCMakeFilesDirectory(); + utilCommandName += "/CMakeFiles"; utilCommandName += "/"; utilCommandName += this->GetTargetName() + ".util"; utilCommandName = this->ConvertToNinjaPath(utilCommandName); diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index 2b9678596..6857d5a27 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -10,15 +10,16 @@ #include "cmTarget.h" #include <cassert> +#include <utility> class cmSourceFile; cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target, - const std::string& configName) + std::string configName) : GT(target) , Makefile(target->Target->GetMakefile()) , LocalGenerator(target->GetLocalGenerator()) - , ConfigName(configName) + , ConfigName(std::move(configName)) , MacContentFolders(nullptr) { if (this->MustSkip()) { diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index be7e932f9..3dea6cc8a 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -17,8 +17,7 @@ class cmSourceFile; class cmOSXBundleGenerator { public: - cmOSXBundleGenerator(cmGeneratorTarget* target, - const std::string& configName); + cmOSXBundleGenerator(cmGeneratorTarget* target, std::string configName); // create an app bundle at a given root, and return // the directory within the bundle that contains the executable @@ -32,7 +31,7 @@ public: struct MacOSXContentGeneratorType { - virtual ~MacOSXContentGeneratorType() {} + virtual ~MacOSXContentGeneratorType() = default; virtual void operator()(cmSourceFile const& source, const char* pkgloc) = 0; }; diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx index 006211ddc..52f63a379 100644 --- a/Source/cmOptionCommand.cxx +++ b/Source/cmOptionCommand.cxx @@ -6,12 +6,12 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -81,7 +81,7 @@ bool cmOptionCommand::InitialPass(std::vector<std::string> const& args, "For compatibility with older versions of CMake, option " "is clearing the normal variable '" << args[0] << "'."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } return true; diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 04a931854..2c28fc0b7 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -5,6 +5,7 @@ #include "cmAlgorithms.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmake.h" @@ -47,7 +48,7 @@ public: this->FileName = cmSystemTools::GetFilenameName(file); } } - virtual ~cmOrderDirectoriesConstraint() {} + virtual ~cmOrderDirectoriesConstraint() = default; void AddDirectory() { @@ -186,7 +187,7 @@ bool cmOrderDirectoriesConstraintSOName::FindConflict(std::string const& dir) // file name. Usually the soname starts with the library name. std::string base = this->FileName; std::set<std::string>::const_iterator first = files.lower_bound(base); - ++base[base.size() - 1]; + ++base.back(); std::set<std::string>::const_iterator last = files.upper_bound(base); if (first != last) { return true; @@ -475,7 +476,7 @@ void cmOrderDirectories::FindImplicitConflicts() << " libraries in implicit directories:\n" << text << "Some of these libraries may not be found correctly."; this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::WARNING, w.str(), this->Target->GetBacktrace()); + MessageType::WARNING, w.str(), this->Target->GetBacktrace()); } void cmOrderDirectories::OrderDirectories() @@ -544,7 +545,7 @@ void cmOrderDirectories::DiagnoseCycle() } e << "Some of these libraries may not be found correctly."; this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::WARNING, e.str(), this->Target->GetBacktrace()); + MessageType::WARNING, e.str(), this->Target->GetBacktrace()); } bool cmOrderDirectories::IsSameDirectory(std::string const& l, diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index dbe6fa1c8..7d88b088e 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -9,9 +9,7 @@ #include <string.h> #include <vector> -#include "cmAlgorithms.h" #include "cmState.h" -#include "cmStateDirectory.h" #include "cmSystemTools.h" cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot) @@ -73,121 +71,6 @@ std::string cmOutputConverter::ConvertDirectorySeparatorsForShell( return result; } -static bool cmOutputConverterNotAbove(const char* a, const char* b) -{ - return (cmSystemTools::ComparePath(a, b) || - cmSystemTools::IsSubDirectory(a, b)); -} - -bool cmOutputConverter::ContainedInDirectory(std::string const& local_path, - std::string const& remote_path, - cmStateDirectory const& directory) -{ - const std::string& relativePathTopBinary = - directory.GetRelativePathTopBinary(); - const std::string& relativePathTopSource = - directory.GetRelativePathTopSource(); - - const bool bothInBinary = - cmOutputConverterNotAbove(local_path.c_str(), - relativePathTopBinary.c_str()) && - cmOutputConverterNotAbove(remote_path.c_str(), - relativePathTopBinary.c_str()); - - const bool bothInSource = - cmOutputConverterNotAbove(local_path.c_str(), - relativePathTopSource.c_str()) && - cmOutputConverterNotAbove(remote_path.c_str(), - relativePathTopSource.c_str()); - - return bothInSource || bothInBinary; -} - -std::string cmOutputConverter::ConvertToRelativePath( - std::string const& local_path, std::string const& remote_path) const -{ - if (!ContainedInDirectory(local_path, remote_path, - this->StateSnapshot.GetDirectory())) { - return remote_path; - } - - return this->ForceToRelativePath(local_path, remote_path); -} - -std::string cmOutputConverter::ForceToRelativePath( - std::string const& local_path, std::string const& remote_path) -{ - // The paths should never be quoted. - assert(local_path[0] != '\"'); - assert(remote_path[0] != '\"'); - - // The local path should never have a trailing slash. - assert(local_path.empty() || local_path[local_path.size() - 1] != '/'); - - // If the path is already relative then just return the path. - if (!cmSystemTools::FileIsFullPath(remote_path)) { - return remote_path; - } - - // Identify the longest shared path component between the remote - // path and the local path. - std::vector<std::string> local; - cmSystemTools::SplitPath(local_path, local); - std::vector<std::string> remote; - cmSystemTools::SplitPath(remote_path, remote); - unsigned int common = 0; - while (common < remote.size() && common < local.size() && - cmSystemTools::ComparePath(remote[common], local[common])) { - ++common; - } - - // If no part of the path is in common then return the full path. - if (common == 0) { - return remote_path; - } - - // If the entire path is in common then just return a ".". - if (common == remote.size() && common == local.size()) { - return "."; - } - - // If the entire path is in common except for a trailing slash then - // just return a "./". - if (common + 1 == remote.size() && remote[common].empty() && - common == local.size()) { - return "./"; - } - - // Construct the relative path. - std::string relative; - - // First add enough ../ to get up to the level of the shared portion - // of the path. Leave off the trailing slash. Note that the last - // component of local will never be empty because local should never - // have a trailing slash. - for (unsigned int i = common; i < local.size(); ++i) { - relative += ".."; - if (i < local.size() - 1) { - relative += "/"; - } - } - - // Now add the portion of the destination path that is not included - // in the shared portion of the path. Add a slash the first time - // only if there was already something in the path. If there was a - // trailing slash in the input then the last iteration of the loop - // will add a slash followed by an empty string which will preserve - // the trailing slash in the output. - - if (!relative.empty() && !remote.empty()) { - relative += "/"; - } - relative += cmJoin(cmMakeRange(remote).advance(common), "/"); - - // Finally return the path. - return relative; -} - static bool cmOutputConverterIsShellOperator(const std::string& str) { static std::set<std::string> shellOperators; diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index ed7143c43..6438c7bad 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -10,7 +10,6 @@ #include "cmStateSnapshot.h" class cmState; -class cmStateDirectory; class cmOutputConverter { @@ -92,28 +91,6 @@ public: }; static FortranFormat GetFortranFormat(const char* value); - static bool ContainedInDirectory(std::string const& local_path, - std::string const& remote_path, - cmStateDirectory const& directory); - - /** - * Convert the given remote path to a relative path with respect to - * the given local path. Both paths must use forward slashes and not - * already be escaped or quoted. - * The conversion is skipped if the paths are not both in the source - * or both in the binary tree. - */ - std::string ConvertToRelativePath(std::string const& local_path, - std::string const& remote_path) const; - - /** - * Convert the given remote path to a relative path with respect to - * the given local path. Both paths must use forward slashes and not - * already be escaped or quoted. - */ - static std::string ForceToRelativePath(std::string const& local_path, - std::string const& remote_path); - private: cmState* GetState() const; diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index e2de3f98e..46d04a65f 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -28,11 +28,7 @@ public: * Construct with dependency generation marked not done; instance * not placed in cmMakefile's list. */ - cmDependInformation() - : DependDone(false) - , SourceFile(nullptr) - { - } + cmDependInformation() = default; /** * The set of files on which this one depends. @@ -44,13 +40,13 @@ public: * This flag indicates whether dependency checking has been * performed for this file. */ - bool DependDone; + bool DependDone = false; /** * If this object corresponds to a cmSourceFile instance, this points * to it. */ - const cmSourceFile* SourceFile; + const cmSourceFile* SourceFile = nullptr; /** * Full path to this file. @@ -198,7 +194,7 @@ protected: message += includeFile; message += " for file "; message += info->FullPath; - cmSystemTools::Error(message.c_str(), nullptr); + cmSystemTools::Error(message); } continue; } @@ -340,7 +336,7 @@ protected: } else { // try to guess which include path to use for (std::string incpath : this->IncludeDirectories) { - if (!incpath.empty() && incpath[incpath.size() - 1] != '/') { + if (!incpath.empty() && incpath.back() != '/') { incpath = incpath + "/"; } incpath = incpath + path; @@ -421,7 +417,7 @@ protected: } for (std::string path : this->IncludeDirectories) { - if (!path.empty() && path[path.size() - 1] != '/') { + if (!path.empty() && path.back() != '/') { path = path + "/"; } path = path + fname; @@ -435,7 +431,7 @@ protected: if (extraPath) { std::string path = extraPath; - if (!path.empty() && path[path.size() - 1] != '/') { + if (!path.empty() && path.back() != '/') { path = path + "/"; } path = path + fname; diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index 2d61cc355..796974cb3 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -9,8 +9,8 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -46,7 +46,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, if (*argIter == "PARSE_ARGV") { if (args.size() != 6) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "PARSE_ARGV must be called with exactly 6 arguments."); cmSystemTools::SetFatalErrorOccured(); return true; @@ -54,7 +54,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, parseFromArgV = true; argIter++; // move past PARSE_ARGV if (!cmSystemTools::StringToULong(argIter->c_str(), &argvStart)) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "PARSE_ARGV index '" + *argIter + "' is not an unsigned integer"); cmSystemTools::SetFatalErrorOccured(); @@ -86,7 +86,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::ExpandListArgument(*argIter++, list); for (std::string const& iter : list) { if (!used_keywords.insert(iter).second) { - this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + iter); + this->GetMakefile()->IssueMessage(MessageType::WARNING, + dup_warning + iter); } options[iter]; // default initialize } @@ -96,7 +97,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::ExpandListArgument(*argIter++, list); for (std::string const& iter : list) { if (!used_keywords.insert(iter).second) { - this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + iter); + this->GetMakefile()->IssueMessage(MessageType::WARNING, + dup_warning + iter); } singleValArgs[iter]; // default initialize } @@ -106,7 +108,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::ExpandListArgument(*argIter++, list); for (std::string const& iter : list) { if (!used_keywords.insert(iter).second) { - this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + iter); + this->GetMakefile()->IssueMessage(MessageType::WARNING, + dup_warning + iter); } multiValArgs[iter]; // default initialize } @@ -131,7 +134,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, std::string argc = this->Makefile->GetSafeDefinition("ARGC"); unsigned long count; if (!cmSystemTools::StringToULong(argc.c_str(), &count)) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "PARSE_ARGV called with ARGC='" + argc + "' that is not an unsigned integer"); cmSystemTools::SetFatalErrorOccured(); @@ -142,13 +145,13 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, argName << "ARGV" << i; const char* arg = this->Makefile->GetDefinition(argName.str()); if (!arg) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "PARSE_ARGV called with " + argName.str() + " not set"); cmSystemTools::SetFatalErrorOccured(); return true; } - list.push_back(arg); + list.emplace_back(arg); } } diff --git a/Source/cmPathLabel.cxx b/Source/cmPathLabel.cxx index 4793206f9..fb8135101 100644 --- a/Source/cmPathLabel.cxx +++ b/Source/cmPathLabel.cxx @@ -2,8 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmPathLabel.h" -cmPathLabel::cmPathLabel(const std::string& label) - : Label(label) +#include <utility> + +cmPathLabel::cmPathLabel(std::string label) + : Label(std::move(label)) , Hash(0) { // Use a Jenkins one-at-a-time hash with under/over-flow protection diff --git a/Source/cmPathLabel.h b/Source/cmPathLabel.h index 97551fb46..55dffabe0 100644 --- a/Source/cmPathLabel.h +++ b/Source/cmPathLabel.h @@ -17,7 +17,7 @@ class cmPathLabel { public: - cmPathLabel(const std::string& label); + cmPathLabel(std::string label); // The comparison operators are only for quick sorting and searching and // in no way imply any lexicographical order of the label diff --git a/Source/cmPipeConnection.cxx b/Source/cmPipeConnection.cxx index 3dab2f075..1eede13e0 100644 --- a/Source/cmPipeConnection.cxx +++ b/Source/cmPipeConnection.cxx @@ -2,14 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmPipeConnection.h" -#include <algorithm> +#include <utility> #include "cmServer.h" -cmPipeConnection::cmPipeConnection(const std::string& name, +cmPipeConnection::cmPipeConnection(std::string name, cmConnectionBufferStrategy* bufferStrategy) : cmEventBasedConnection(bufferStrategy) - , PipeName(name) + , PipeName(std::move(name)) { } diff --git a/Source/cmPipeConnection.h b/Source/cmPipeConnection.h index 49f9fdf8a..e67f15c57 100644 --- a/Source/cmPipeConnection.h +++ b/Source/cmPipeConnection.h @@ -13,7 +13,7 @@ class cmPipeConnection : public cmEventBasedConnection { public: - cmPipeConnection(const std::string& name, + cmPipeConnection(std::string name, cmConnectionBufferStrategy* bufferStrategy = nullptr); bool OnServeStart(std::string* pString) override; diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 5caea7d1f..0a234c52e 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -2,11 +2,11 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmVersion.h" -#include "cmake.h" #include <assert.h> #include <ctype.h> @@ -128,7 +128,7 @@ static void DiagnoseAncientPolicies( << "Please either update your CMakeLists.txt files to conform to " << "the new behavior or use an older version of CMake that still " << "supports the old behavior."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); } static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy, @@ -146,7 +146,7 @@ static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy, std::ostringstream e; e << defaultVar << " has value \"" << defaultValue << "\" but must be \"OLD\", \"NEW\", or \"\" (empty)."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -167,14 +167,14 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, std::ostringstream e; e << "Invalid policy version value \"" << version_min << "\". " << "A numeric major.minor[.patch[.tweak]] must be given."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } // it is an error if the policy version is less than 2.4 if (minMajor < 2 || (minMajor == 2 && minMinor < 4)) { mf->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0. " "For compatibility with older versions please use any CMake 2.8.x " "release or lower."); @@ -199,7 +199,7 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, << "This is not allowed because the greater version may have new " << "policies not known to this CMake. " << "You may need a newer CMake version to build this project."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -218,7 +218,7 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, std::ostringstream e; e << "Invalid policy max version value \"" << version_max << "\". " << "A numeric major.minor[.patch[.tweak]] must be given."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -232,7 +232,7 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, e << "Policy VERSION range \"" << version_min << "..." << version_max << "\"" << " specifies a larger minimum than maximum."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index a367e47dd..314f27dc5 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -236,11 +236,32 @@ class cmMakefile; "target_link_libraries allows use with targets in other directories.", 3, \ 13, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0080, \ - "BundleUtilities cannot be included at configure time", 3, 13, 0, \ + "BundleUtilities cannot be included at configure time.", 3, 13, 0, \ cmPolicies::WARN) \ SELECT(POLICY, CMP0081, \ "Relative paths not allowed in LINK_DIRECTORIES target property.", \ - 3, 13, 0, cmPolicies::WARN) + 3, 13, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0082, \ + "Install rules from add_subdirectory() are interleaved with those " \ + "in caller.", \ + 3, 14, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0083, "Add PIE options when linking executable.", 3, 14, \ + 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0084, \ + "The FindQt module does not exist for find_package().", 3, 14, 0, \ + cmPolicies::WARN) \ + SELECT(POLICY, CMP0085, "$<IN_LIST:...> handles empty list items.", 3, 14, \ + 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0086, \ + "UseSWIG honors SWIG_MODULE_NAME via -module flag.", 3, 14, 0, \ + cmPolicies::WARN) \ + SELECT(POLICY, CMP0087, \ + "Install CODE|SCRIPT allow the use of generator " \ + "expressions.", \ + 3, 14, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0088, \ + "FindBISON runs bison in CMAKE_CURRENT_BINARY_DIR when executing.", \ + 3, 14, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -267,7 +288,8 @@ class cmMakefile; F(CMP0069) \ F(CMP0073) \ F(CMP0076) \ - F(CMP0081) + F(CMP0081) \ + F(CMP0083) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Source/cmProcessOutput.cxx b/Source/cmProcessOutput.cxx index e4ca426cc..e80ea5c8d 100644 --- a/Source/cmProcessOutput.cxx +++ b/Source/cmProcessOutput.cxx @@ -48,9 +48,7 @@ cmProcessOutput::cmProcessOutput(Encoding encoding, unsigned int maxSize) #endif } -cmProcessOutput::~cmProcessOutput() -{ -} +cmProcessOutput::~cmProcessOutput() = default; bool cmProcessOutput::DecodeText(std::string raw, std::string& decoded, size_t id) diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx index 7ab1fa3fc..a2bc16ffb 100644 --- a/Source/cmProcessTools.cxx +++ b/Source/cmProcessTools.cxx @@ -16,7 +16,7 @@ void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out, cmProcessOutput processOutput(encoding); std::string strdata; while ((out || err) && - (p = cmsysProcess_WaitForData(cp, &data, &length, nullptr), p)) { + (p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) { if (out && p == cmsysProcess_Pipe_STDOUT) { processOutput.DecodeText(data, length, strdata, 1); if (!out->Process(strdata.c_str(), int(strdata.size()))) { @@ -45,10 +45,7 @@ void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out, } cmProcessTools::LineParser::LineParser(char sep, bool ignoreCR) - : Log(nullptr) - , Prefix(nullptr) - , Separator(sep) - , LineEnd('\0') + : Separator(sep) , IgnoreCR(ignoreCR) { } diff --git a/Source/cmProcessTools.h b/Source/cmProcessTools.h index f1c2a228e..76163167a 100644 --- a/Source/cmProcessTools.h +++ b/Source/cmProcessTools.h @@ -34,7 +34,7 @@ public: return this->Process(data, static_cast<int>(strlen(data))); } - virtual ~OutputParser() {} + virtual ~OutputParser() = default; protected: /** Implement in a subclass to process a chunk of data. It should @@ -54,11 +54,11 @@ public: void SetLog(std::ostream* log, const char* prefix); protected: - std::ostream* Log; - const char* Prefix; + std::ostream* Log = nullptr; + const char* Prefix = nullptr; std::string Line; char Separator; - char LineEnd; + char LineEnd = '\0'; bool IgnoreCR; bool ProcessChunk(const char* data, int length) override; diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 8f565c815..2fe9fe8b9 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -9,10 +9,10 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmake.h" class cmExecutionStatus; @@ -90,7 +90,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, if (args[i] == "LANGUAGES") { if (haveLanguages) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "LANGUAGES may be specified at most once."); + MessageType::FATAL_ERROR, + "LANGUAGES may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -105,11 +106,11 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, "keyword: "; msg += cmJoin(languages, ", "); msg += '.'; - this->Makefile->IssueMessage(cmake::WARNING, msg); + this->Makefile->IssueMessage(MessageType::WARNING, msg); } } else if (args[i] == "VERSION") { if (haveVersion) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "VERSION may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; @@ -121,7 +122,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, doing = DoingVersion; missedValueReporter = [this, &resetReporter]() { this->Makefile->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "VERSION keyword not followed by a value or was followed by a " "value that expanded to nothing."); resetReporter(); @@ -129,7 +130,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } else if (args[i] == "DESCRIPTION") { if (haveDescription) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "DESCRIPTION may be specified at most once."); + MessageType::FATAL_ERROR, + "DESCRIPTION may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -140,7 +142,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, doing = DoingDescription; missedValueReporter = [this, &resetReporter]() { this->Makefile->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "DESCRIPTION keyword not followed by a value or was followed " "by a value that expanded to nothing."); resetReporter(); @@ -148,7 +150,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } else if (args[i] == "HOMEPAGE_URL") { if (haveHomepage) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, "HOMEPAGE_URL may be specified at most once."); + MessageType::FATAL_ERROR, + "HOMEPAGE_URL may be specified at most once."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -156,7 +159,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, doing = DoingHomepage; missedValueReporter = [this, &resetReporter]() { this->Makefile->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "HOMEPAGE_URL keyword not followed by a value or was followed " "by a value that expanded to nothing."); resetReporter(); @@ -188,14 +191,14 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, if ((haveVersion || haveDescription || haveHomepage) && !haveLanguages && !languages.empty()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "project with VERSION, DESCRIPTION or HOMEPAGE_URL must " "use LANGUAGES before language names."); cmSystemTools::SetFatalErrorOccured(); return true; } if (haveLanguages && languages.empty()) { - languages.push_back("NONE"); + languages.emplace_back("NONE"); } cmPolicies::PolicyStatus cmp0048 = @@ -204,7 +207,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, // Set project VERSION variables to given values if (cmp0048 == cmPolicies::OLD || cmp0048 == cmPolicies::WARN) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "VERSION not allowed unless CMP0048 is set to NEW"); cmSystemTools::SetFatalErrorOccured(); return true; @@ -214,7 +217,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, "^([0-9]+(\\.[0-9]+(\\.[0-9]+(\\.[0-9]+)?)?)?)?$"); if (!vx.find(version)) { std::string e = "VERSION \"" + version + "\" format invalid."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -261,22 +264,22 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } else if (cmp0048 != cmPolicies::OLD) { // Set project VERSION variables to empty std::vector<std::string> vv; - vv.push_back("PROJECT_VERSION"); - vv.push_back("PROJECT_VERSION_MAJOR"); - vv.push_back("PROJECT_VERSION_MINOR"); - vv.push_back("PROJECT_VERSION_PATCH"); - vv.push_back("PROJECT_VERSION_TWEAK"); + vv.emplace_back("PROJECT_VERSION"); + vv.emplace_back("PROJECT_VERSION_MAJOR"); + vv.emplace_back("PROJECT_VERSION_MINOR"); + vv.emplace_back("PROJECT_VERSION_PATCH"); + vv.emplace_back("PROJECT_VERSION_TWEAK"); vv.push_back(projectName + "_VERSION"); vv.push_back(projectName + "_VERSION_MAJOR"); vv.push_back(projectName + "_VERSION_MINOR"); vv.push_back(projectName + "_VERSION_PATCH"); vv.push_back(projectName + "_VERSION_TWEAK"); if (this->Makefile->IsRootMakefile()) { - vv.push_back("CMAKE_PROJECT_VERSION"); - vv.push_back("CMAKE_PROJECT_VERSION_MAJOR"); - vv.push_back("CMAKE_PROJECT_VERSION_MINOR"); - vv.push_back("CMAKE_PROJECT_VERSION_PATCH"); - vv.push_back("CMAKE_PROJECT_VERSION_TWEAK"); + vv.emplace_back("CMAKE_PROJECT_VERSION"); + vv.emplace_back("CMAKE_PROJECT_VERSION_MAJOR"); + vv.emplace_back("CMAKE_PROJECT_VERSION_MINOR"); + vv.emplace_back("CMAKE_PROJECT_VERSION_PATCH"); + vv.emplace_back("CMAKE_PROJECT_VERSION_TWEAK"); } std::string vw; for (std::string const& i : vv) { @@ -296,7 +299,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, std::ostringstream w; w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0048) << "\nThe following variable(s) would be set to empty:" << vw; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } @@ -312,8 +315,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, if (languages.empty()) { // if no language is specified do c and c++ - languages.push_back("C"); - languages.push_back("CXX"); + languages.emplace_back("C"); + languages.emplace_back("CXX"); } this->Makefile->EnableLanguage(languages, false); std::string extraInclude = "CMAKE_PROJECT_" + projectName + "_INCLUDE"; diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx index d2133ed79..6acc7ef86 100644 --- a/Source/cmQTWrapCPPCommand.cxx +++ b/Source/cmQTWrapCPPCommand.cxx @@ -50,7 +50,7 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& args, if (cmSystemTools::FileIsFullPath(*j)) { hname = *j; } else { - if (curr && curr->GetPropertyAsBool("GENERATED")) { + if (curr && curr->GetIsGenerated()) { hname = this->Makefile->GetCurrentBinaryDirectory(); } else { hname = this->Makefile->GetCurrentSourceDirectory(); diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx index 25dcd1a64..43b1fb9b6 100644 --- a/Source/cmQTWrapUICommand.cxx +++ b/Source/cmQTWrapUICommand.cxx @@ -58,7 +58,7 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args, if (cmSystemTools::FileIsFullPath(*j)) { uiName = *j; } else { - if (curr && curr->GetPropertyAsBool("GENERATED")) { + if (curr && curr->GetIsGenerated()) { uiName = this->Makefile->GetCurrentBinaryDirectory(); } else { uiName = this->Makefile->GetCurrentSourceDirectory(); diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 000529d36..653caf75b 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -9,6 +9,7 @@ #include <algorithm> #include <iterator> #include <sstream> +#include <utility> // - Static variables @@ -99,6 +100,41 @@ std::string cmQtAutoGen::GeneratorNameUpper(GeneratorT genType) return cmSystemTools::UpperCase(cmQtAutoGen::GeneratorName(genType)); } +std::string cmQtAutoGen::Tools(bool moc, bool uic, bool rcc) +{ + std::string res; + std::vector<std::string> lst; + if (moc) { + lst.emplace_back("AUTOMOC"); + } + if (uic) { + lst.emplace_back("AUTOUIC"); + } + if (rcc) { + lst.emplace_back("AUTORCC"); + } + switch (lst.size()) { + case 1: + res += lst.at(0); + break; + case 2: + res += lst.at(0); + res += " and "; + res += lst.at(1); + break; + case 3: + res += lst.at(0); + res += ", "; + res += lst.at(1); + res += " and "; + res += lst.at(2); + break; + default: + break; + } + return res; +} + std::string cmQtAutoGen::Quoted(std::string const& text) { static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a", diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index 4118dc79c..96d1946f0 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -60,6 +60,9 @@ public: /// @brief Returns the generator name in upper case static std::string GeneratorNameUpper(GeneratorT genType); + /// @brief Returns a string with the requested tool names + static std::string Tools(bool moc, bool uic, bool rcc); + /// @brief Returns the string escaped and enclosed in quotes static std::string Quoted(std::string const& text); diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx new file mode 100644 index 000000000..3ad91eec6 --- /dev/null +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -0,0 +1,288 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmQtAutoGenGlobalInitializer.h" +#include "cmQtAutoGen.h" +#include "cmQtAutoGenInitializer.h" + +#include "cmAlgorithms.h" +#include "cmCustomCommandLines.h" +#include "cmDuration.h" +#include "cmGeneratorTarget.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmProcessOutput.h" +#include "cmState.h" +#include "cmStateTypes.h" +#include "cmSystemTools.h" +#include "cmTarget.h" + +#include <memory> +#include <utility> + +cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( + std::vector<cmLocalGenerator*> const& localGenerators) +{ + for (cmLocalGenerator* localGen : localGenerators) { + // Detect global autogen and autorcc target names + bool globalAutoGenTarget = false; + bool globalAutoRccTarget = false; + { + cmMakefile* makefile = localGen->GetMakefile(); + // Detect global autogen target name + if (cmSystemTools::IsOn( + makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET"))) { + std::string targetName = + makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET_NAME"); + if (targetName.empty()) { + targetName = "autogen"; + } + GlobalAutoGenTargets_.emplace(localGen, std::move(targetName)); + globalAutoGenTarget = true; + } + + // Detect global autorcc target name + if (cmSystemTools::IsOn( + makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET"))) { + std::string targetName = + makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET_NAME"); + if (targetName.empty()) { + targetName = "autorcc"; + } + GlobalAutoRccTargets_.emplace(localGen, std::move(targetName)); + globalAutoRccTarget = true; + } + } + + // Find targets that require AUTOMOC/UIC/RCC processing + for (cmGeneratorTarget* target : localGen->GetGeneratorTargets()) { + // Process only certain target types + switch (target->GetType()) { + case cmStateEnums::EXECUTABLE: + case cmStateEnums::STATIC_LIBRARY: + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::OBJECT_LIBRARY: + // Process target + break; + default: + // Don't process target + continue; + } + if (target->IsImported()) { + // Don't process target + continue; + } + + bool const moc = target->GetPropertyAsBool("AUTOMOC"); + bool const uic = target->GetPropertyAsBool("AUTOUIC"); + bool const rcc = target->GetPropertyAsBool("AUTORCC"); + if (moc || uic || rcc) { + std::string const mocExec = + target->GetSafeProperty("AUTOMOC_EXECUTABLE"); + std::string const uicExec = + target->GetSafeProperty("AUTOUIC_EXECUTABLE"); + std::string const rccExec = + target->GetSafeProperty("AUTORCC_EXECUTABLE"); + + // We support Qt4, Qt5 and Qt6 + auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target); + bool const validQt = (qtVersion.first.Major == 4) || + (qtVersion.first.Major == 5) || (qtVersion.first.Major == 6); + + bool const mocAvailable = (validQt || !mocExec.empty()); + bool const uicAvailable = (validQt || !uicExec.empty()); + bool const rccAvailable = (validQt || !rccExec.empty()); + bool const mocIsValid = (moc && mocAvailable); + bool const uicIsValid = (uic && uicAvailable); + bool const rccIsValid = (rcc && rccAvailable); + // Disabled AUTOMOC/UIC/RCC warning + bool const mocDisabled = (moc && !mocAvailable); + bool const uicDisabled = (uic && !uicAvailable); + bool const rccDisabled = (rcc && !rccAvailable); + if (mocDisabled || uicDisabled || rccDisabled) { + std::string msg = "AUTOGEN: No valid Qt version found for target "; + msg += target->GetName(); + msg += ". "; + msg += cmQtAutoGen::Tools(mocDisabled, uicDisabled, rccDisabled); + msg += " disabled. Consider adding:\n"; + { + std::string version = (qtVersion.second == 0) + ? std::string("<QTVERSION>") + : std::to_string(qtVersion.second); + std::string comp = uicDisabled ? "Widgets" : "Core"; + msg += " find_package(Qt"; + msg += version; + msg += " COMPONENTS "; + msg += comp; + msg += ")\n"; + } + msg += "to your CMakeLists.txt file."; + target->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); + } + if (mocIsValid || uicIsValid || rccIsValid) { + // Create autogen target initializer + Initializers_.emplace_back(cm::make_unique<cmQtAutoGenInitializer>( + this, target, qtVersion.first, mocIsValid, uicIsValid, rccIsValid, + globalAutoGenTarget, globalAutoRccTarget)); + } + } + } + } +} + +cmQtAutoGenGlobalInitializer::~cmQtAutoGenGlobalInitializer() = default; + +void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget( + cmLocalGenerator* localGen, std::string const& name, + std::string const& comment) +{ + // Test if the target already exists + if (localGen->FindGeneratorTargetToUse(name) == nullptr) { + cmMakefile* makefile = localGen->GetMakefile(); + + // Create utility target + cmTarget* target = makefile->AddUtilityCommand( + name, cmMakefile::TargetOrigin::Generator, true, + makefile->GetHomeOutputDirectory().c_str() /*work dir*/, + std::vector<std::string>() /*output*/, + std::vector<std::string>() /*depends*/, cmCustomCommandLines(), false, + comment.c_str()); + localGen->AddGeneratorTarget(new cmGeneratorTarget(target, localGen)); + + // Set FOLDER property in the target + { + char const* folder = + makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); + if (folder != nullptr) { + target->SetProperty("FOLDER", folder); + } + } + } +} + +void cmQtAutoGenGlobalInitializer::AddToGlobalAutoGen( + cmLocalGenerator* localGen, std::string const& targetName) +{ + auto it = GlobalAutoGenTargets_.find(localGen); + if (it != GlobalAutoGenTargets_.end()) { + cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second); + if (target != nullptr) { + target->Target->AddUtility(targetName, localGen->GetMakefile()); + } + } +} + +void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc( + cmLocalGenerator* localGen, std::string const& targetName) +{ + auto it = GlobalAutoRccTargets_.find(localGen); + if (it != GlobalAutoRccTargets_.end()) { + cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second); + if (target != nullptr) { + target->Target->AddUtility(targetName, localGen->GetMakefile()); + } + } +} + +bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput( + std::string const& generator, std::string const& executable, + std::string& error, std::string* output) +{ + // Check if we have cached output + { + auto it = this->ExecutableTestOutputs_.find(executable); + if (it != this->ExecutableTestOutputs_.end()) { + // Return output on demand + if (output != nullptr) { + *output = it->second; + } + return true; + } + } + + // Check if the executable exists + if (!cmSystemTools::FileExists(executable, true)) { + error = "The \""; + error += generator; + error += "\" executable "; + error += cmQtAutoGen::Quoted(executable); + error += " does not exist."; + return false; + } + + // Test the executable + std::string stdOut; + { + std::string stdErr; + std::vector<std::string> command; + command.push_back(executable); + command.emplace_back("-h"); + int retVal = 0; + const bool runResult = cmSystemTools::RunSingleCommand( + command, &stdOut, &stdErr, &retVal, nullptr, cmSystemTools::OUTPUT_NONE, + cmDuration::zero(), cmProcessOutput::Auto); + if (!runResult) { + error = "Test run of \""; + error += generator; + error += "\" executable "; + error += cmQtAutoGen::Quoted(executable) + " failed.\n"; + error += cmQtAutoGen::QuotedCommand(command); + error += "\n"; + error += stdOut; + error += "\n"; + error += stdErr; + return false; + } + } + + // Return executable output on demand + if (output != nullptr) { + *output = stdOut; + } + + // Register executable and output + this->ExecutableTestOutputs_.emplace(executable, std::move(stdOut)); + + return true; +} + +bool cmQtAutoGenGlobalInitializer::generate() +{ + return (InitializeCustomTargets() && SetupCustomTargets()); +} + +bool cmQtAutoGenGlobalInitializer::InitializeCustomTargets() +{ + // Initialize global autogen targets + { + std::string const comment = "Global AUTOGEN target"; + for (auto const& pair : GlobalAutoGenTargets_) { + GetOrCreateGlobalTarget(pair.first, pair.second, comment); + } + } + // Initialize global autorcc targets + { + std::string const comment = "Global AUTORCC target"; + for (auto const& pair : GlobalAutoRccTargets_) { + GetOrCreateGlobalTarget(pair.first, pair.second, comment); + } + } + // Initialize per target autogen targets + for (auto& initializer : Initializers_) { + if (!initializer->InitCustomTargets()) { + return false; + } + } + return true; +} + +bool cmQtAutoGenGlobalInitializer::SetupCustomTargets() +{ + for (auto& initializer : Initializers_) { + if (!initializer->SetupCustomTargets()) { + return false; + } + } + return true; +} diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h new file mode 100644 index 000000000..74184a0d5 --- /dev/null +++ b/Source/cmQtAutoGenGlobalInitializer.h @@ -0,0 +1,53 @@ +/* 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 + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <map> +#include <memory> // IWYU pragma: keep +#include <string> +#include <unordered_map> +#include <vector> + +class cmLocalGenerator; +class cmQtAutoGenInitializer; + +/// @brief Initializes the QtAutoGen generators +class cmQtAutoGenGlobalInitializer +{ +public: + cmQtAutoGenGlobalInitializer( + std::vector<cmLocalGenerator*> const& localGenerators); + ~cmQtAutoGenGlobalInitializer(); + + bool generate(); + +private: + friend class cmQtAutoGenInitializer; + + bool InitializeCustomTargets(); + bool SetupCustomTargets(); + + void GetOrCreateGlobalTarget(cmLocalGenerator* localGen, + std::string const& name, + std::string const& comment); + + void AddToGlobalAutoGen(cmLocalGenerator* localGen, + std::string const& targetName); + void AddToGlobalAutoRcc(cmLocalGenerator* localGen, + std::string const& targetName); + + bool GetExecutableTestOutput(std::string const& generator, + std::string const& executable, + std::string& error, std::string* output); + +private: + std::vector<std::unique_ptr<cmQtAutoGenInitializer>> Initializers_; + std::map<cmLocalGenerator*, std::string> GlobalAutoGenTargets_; + std::map<cmLocalGenerator*, std::string> GlobalAutoRccTargets_; + std::unordered_map<std::string, std::string> ExecutableTestOutputs_; +}; + +#endif diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 90111801d..614a88bde 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -2,18 +2,21 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGenInitializer.h" #include "cmQtAutoGen.h" +#include "cmQtAutoGenGlobalInitializer.h" #include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmDuration.h" #include "cmFilePathChecksum.h" -#include "cmGeneratedFileStream.h" +#include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLinkItem.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmProcessOutput.h" @@ -23,7 +26,6 @@ #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" #include "cmsys/FStream.hxx" #include "cmsys/SystemInformation.hxx" @@ -34,9 +36,25 @@ #include <set> #include <sstream> #include <string> +#include <type_traits> #include <utility> #include <vector> +std::string GetQtExecutableTargetName( + const cmQtAutoGen::IntegerVersion& qtVersion, std::string const& executable) +{ + if (qtVersion.Major == 6) { + return ("Qt6::" + executable); + } + if (qtVersion.Major == 5) { + return ("Qt5::" + executable); + } + if (qtVersion.Major == 4) { + return ("Qt4::" + executable); + } + return (""); +} + static std::size_t GetParallelCPUCount() { static std::size_t count = 0; @@ -92,7 +110,7 @@ static bool AddToSourceGroup(cmMakefile* makefile, std::string const& fileName, ost << ": " << property; ost << ": Could not find or create the source group "; ost << cmQtAutoGen::Quoted(groupName); - cmSystemTools::Error(ost.str().c_str()); + cmSystemTools::Error(ost.str()); return false; } } @@ -173,17 +191,116 @@ static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin, return cycle; } -cmQtAutoGenInitializer::cmQtAutoGenInitializer(cmGeneratorTarget* target, - bool mocEnabled, - bool uicEnabled, - bool rccEnabled, - IntegerVersion const& qtVersion) - : Target(target) +cmQtAutoGenInitializer::InfoWriter::InfoWriter(std::string const& filename) +{ + Ofs_.SetCopyIfDifferent(true); + Ofs_.Open(filename, false, true); +} + +template <class IT> +std::string cmQtAutoGenInitializer::InfoWriter::ListJoin(IT it_begin, + IT it_end) +{ + std::string res; + for (IT it = it_begin; it != it_end; ++it) { + if (it != it_begin) { + res += ';'; + } + for (const char* c = it->c_str(); *c; ++c) { + if (*c == '"') { + // Escape the double quote to avoid ending the argument. + res += "\\\""; + } else if (*c == '$') { + // Escape the dollar to avoid expanding variables. + res += "\\$"; + } else if (*c == '\\') { + // Escape the backslash to avoid other escapes. + res += "\\\\"; + } else if (*c == ';') { + // Escape the semicolon to avoid list expansion. + res += "\\;"; + } else { + // Other characters will be parsed correctly. + res += *c; + } + } + } + return res; +} + +std::string cmQtAutoGenInitializer::InfoWriter::ConfigKey( + const char* key, std::string const& config) +{ + std::string ckey = key; + ckey += '_'; + ckey += config; + return ckey; +} + +void cmQtAutoGenInitializer::InfoWriter::Write(const char* key, + std::string const& value) +{ + Ofs_ << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) + << ")\n"; +}; + +void cmQtAutoGenInitializer::InfoWriter::WriteUInt(const char* key, + unsigned int value) +{ + Ofs_ << "set(" << key << " " << value << ")\n"; +}; + +template <class C> +void cmQtAutoGenInitializer::InfoWriter::WriteStrings(const char* key, + C const& container) +{ + Ofs_ << "set(" << key << " \"" + << ListJoin(container.begin(), container.end()) << "\")\n"; +} + +void cmQtAutoGenInitializer::InfoWriter::WriteConfig( + const char* key, std::map<std::string, std::string> const& map) +{ + for (auto const& item : map) { + Write(ConfigKey(key, item.first).c_str(), item.second); + } +}; + +template <class C> +void cmQtAutoGenInitializer::InfoWriter::WriteConfigStrings( + const char* key, std::map<std::string, C> const& map) +{ + for (auto const& item : map) { + WriteStrings(ConfigKey(key, item.first).c_str(), item.second); + } +} + +void cmQtAutoGenInitializer::InfoWriter::WriteNestedLists( + const char* key, std::vector<std::vector<std::string>> const& lists) +{ + std::vector<std::string> seplist; + for (const std::vector<std::string>& list : lists) { + std::string blist = "{"; + blist += ListJoin(list.begin(), list.end()); + blist += "}"; + seplist.push_back(std::move(blist)); + } + Write(key, cmJoin(seplist, cmQtAutoGen::ListSep)); +}; + +cmQtAutoGenInitializer::cmQtAutoGenInitializer( + cmQtAutoGenGlobalInitializer* globalInitializer, cmGeneratorTarget* target, + IntegerVersion const& qtVersion, bool mocEnabled, bool uicEnabled, + bool rccEnabled, bool globalAutogenTarget, bool globalAutoRccTarget) + : GlobalInitializer(globalInitializer) + , Target(target) , QtVersion(qtVersion) { + AutogenTarget.GlobalTarget = globalAutogenTarget; Moc.Enabled = mocEnabled; Uic.Enabled = uicEnabled; Rcc.Enabled = rccEnabled; + Rcc.GlobalTarget = globalAutoRccTarget; } bool cmQtAutoGenInitializer::InitCustomTargets() @@ -234,7 +351,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // Info directory this->Dir.Info = cbd; - this->Dir.Info += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); + this->Dir.Info += "/CMakeFiles"; this->Dir.Info += '/'; this->Dir.Info += this->Target->GetName(); this->Dir.Info += "_autogen"; @@ -282,8 +399,16 @@ bool cmQtAutoGenInitializer::InitCustomTargets() } // Init uic specific settings - if (this->Uic.Enabled && !InitUic()) { - return false; + if (this->Uic.Enabled) { + if (InitUic()) { + auto* uicTarget = makefile->FindTargetToUse( + GetQtExecutableTargetName(this->QtVersion, "uic")); + if (uicTarget != nullptr) { + this->AutogenTarget.DependTargets.insert(uicTarget); + } + } else { + return false; + } } // Autogen target name @@ -321,6 +446,15 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // Autogen target: Compute user defined dependencies { + this->AutogenTarget.DependOrigin = + this->Target->GetPropertyAsBool("AUTOGEN_ORIGIN_DEPENDS"); + + auto* mocTarget = makefile->FindTargetToUse( + GetQtExecutableTargetName(this->QtVersion, "moc")); + if (mocTarget != nullptr) { + this->AutogenTarget.DependTargets.insert(mocTarget); + } + std::string const deps = this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS"); if (!deps.empty()) { @@ -386,20 +520,17 @@ bool cmQtAutoGenInitializer::InitMoc() // Moc includes { - // We need to disable this until we have all implicit includes available. - // See issue #18669. - // bool const appendImplicit = (this->QtVersion.Major == 5); - - auto GetIncludeDirs = [this, - localGen](std::string const& cfg) -> std::string { - bool const appendImplicit = false; + bool const appendImplicit = (this->QtVersion.Major >= 5); + auto GetIncludeDirs = + [this, localGen, + appendImplicit](std::string const& cfg) -> std::vector<std::string> { // Get the include dirs for this target, without stripping the implicit // include dirs off, see // https://gitlab.kitware.com/cmake/cmake/issues/13667 std::vector<std::string> dirs; - localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false, - appendImplicit); - return cmJoin(dirs, ";"); + localGen->GetIncludeDirectoriesImplicit(dirs, this->Target, "CXX", cfg, + false, appendImplicit); + return dirs; }; // Default configuration include directories @@ -407,7 +538,7 @@ bool cmQtAutoGenInitializer::InitMoc() // Other configuration settings if (this->MultiConfig) { for (std::string const& cfg : this->ConfigsList) { - std::string dirs = GetIncludeDirs(cfg); + std::vector<std::string> dirs = GetIncludeDirs(cfg); if (dirs != this->Moc.Includes) { this->Moc.ConfigIncludes[cfg] = std::move(dirs); } @@ -418,10 +549,16 @@ bool cmQtAutoGenInitializer::InitMoc() // Moc compile definitions { auto GetCompileDefinitions = - [this, localGen](std::string const& cfg) -> std::string { + [this, localGen](std::string const& cfg) -> std::set<std::string> { std::set<std::string> defines; - localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX"); - return cmJoin(defines, ";"); + localGen->GetTargetDefines(this->Target, cfg, "CXX", defines); +#ifdef _WIN32 + if (this->Moc.PredefsCmd.empty()) { + // Add WIN32 definition if we don't have a moc_predefs.h + defines.insert("WIN32"); + } +#endif + return defines; }; // Default configuration defines @@ -429,7 +566,7 @@ bool cmQtAutoGenInitializer::InitMoc() // Other configuration defines if (this->MultiConfig) { for (std::string const& cfg : this->ConfigsList) { - std::string defines = GetCompileDefinitions(cfg); + std::set<std::string> defines = GetCompileDefinitions(cfg); if (defines != this->Moc.Defines) { this->Moc.ConfigDefines[cfg] = std::move(defines); } @@ -438,11 +575,7 @@ bool cmQtAutoGenInitializer::InitMoc() } // Moc executable - if (!GetMocExecutable()) { - return false; - } - - return true; + return GetMocExecutable(); } bool cmQtAutoGenInitializer::InitUic() @@ -463,10 +596,11 @@ bool cmQtAutoGenInitializer::InitUic() } // Uic target options { - auto UicGetOpts = [this](std::string const& cfg) -> std::string { + auto UicGetOpts = + [this](std::string const& cfg) -> std::vector<std::string> { std::vector<std::string> opts; this->Target->GetAutoUicOptions(opts, cfg); - return cmJoin(opts, ";"); + return opts; }; // Default settings @@ -475,91 +609,64 @@ bool cmQtAutoGenInitializer::InitUic() // Configuration specific settings if (this->MultiConfig) { for (std::string const& cfg : this->ConfigsList) { - std::string options = UicGetOpts(cfg); + std::vector<std::string> options = UicGetOpts(cfg); if (options != this->Uic.Options) { this->Uic.ConfigOptions[cfg] = std::move(options); } } } } - // .ui files skip and options - { - std::string const uiExt = "ui"; - std::string pathError; - for (cmSourceFile* sf : makefile->GetSourceFiles()) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - // Since we're iterating over source files that might be not in the - // target we need to check for path errors (not existing files). - std::string const& fPath = sf->GetFullPath(&pathError); - if (!pathError.empty()) { - pathError.clear(); - continue; - } - if (sf->GetExtension() == uiExt) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - // Check if the .ui file should be skipped - if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || - sf->GetPropertyAsBool("SKIP_AUTOGEN")) { - this->Uic.Skip.insert(absFile); - } - // Check if the .ui file has uic options - std::string const uicOpts = sf->GetSafeProperty("AUTOUIC_OPTIONS"); - if (!uicOpts.empty()) { - // Check if file isn't skipped - if (this->Uic.Skip.count(absFile) == 0) { - this->Uic.FileFiles.push_back(absFile); - std::vector<std::string> optsVec; - cmSystemTools::ExpandListArgument(uicOpts, optsVec); - this->Uic.FileOptions.push_back(std::move(optsVec)); - } - } - } - } - } // Uic executable - if (!GetUicExecutable()) { - return false; - } - - return true; + return GetUicExecutable(); } bool cmQtAutoGenInitializer::InitRcc() { - if (!GetRccExecutable()) { - return false; - } - return true; + return GetRccExecutable(); } bool cmQtAutoGenInitializer::InitScanFiles() { cmMakefile* makefile = this->Target->Target->GetMakefile(); + // String constants + std::string const SKIP_AUTOGEN_str = "SKIP_AUTOGEN"; + std::string const SKIP_AUTOMOC_str = "SKIP_AUTOMOC"; + std::string const SKIP_AUTOUIC_str = "SKIP_AUTOUIC"; + // Scan through target files { - std::string const qrcExt = "qrc"; + // String constants + std::string const qrc_str = "qrc"; + std::string const SKIP_AUTORCC_str = "SKIP_AUTORCC"; + std::string const AUTORCC_OPTIONS_str = "AUTORCC_OPTIONS"; + + // Scan through target files std::vector<cmSourceFile*> srcFiles; this->Target->GetConfigCommonSourceFiles(srcFiles); for (cmSourceFile* sf : srcFiles) { - if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) { + if (sf->GetPropertyAsBool(SKIP_AUTOGEN_str)) { continue; } + // sf->GetExtension() is only valid after sf->GetFullPath() ... std::string const& fPath = sf->GetFullPath(); std::string const& ext = sf->GetExtension(); + // Register generated files that will be scanned by moc or uic if (this->Moc.Enabled || this->Uic.Enabled) { cmSystemTools::FileFormat const fileType = - cmSystemTools::GetFileFormat(ext.c_str()); + cmSystemTools::GetFileFormat(ext); if ((fileType == cmSystemTools::CXX_FILE_FORMAT) || (fileType == cmSystemTools::HEADER_FILE_FORMAT)) { std::string const absPath = cmSystemTools::GetRealPath(fPath); - if ((this->Moc.Enabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) || - (this->Uic.Enabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) { + if ((this->Moc.Enabled && + !sf->GetPropertyAsBool(SKIP_AUTOMOC_str)) || + (this->Uic.Enabled && + !sf->GetPropertyAsBool(SKIP_AUTOUIC_str))) { // Register source - const bool generated = sf->GetPropertyAsBool("GENERATED"); + const bool generated = sf->GetIsGenerated(); if (fileType == cmSystemTools::HEADER_FILE_FORMAT) { if (generated) { this->AutogenTarget.HeadersGenerated.push_back(absPath); @@ -577,18 +684,17 @@ bool cmQtAutoGenInitializer::InitScanFiles() } } // Register rcc enabled files - if (this->Rcc.Enabled && (ext == qrcExt) && - !sf->GetPropertyAsBool("SKIP_AUTORCC")) { - // Register qrc file - { + if (this->Rcc.Enabled) { + if ((ext == qrc_str) && !sf->GetPropertyAsBool(SKIP_AUTORCC_str)) { + // Register qrc file Qrc qrc; qrc.QrcFile = cmSystemTools::GetRealPath(fPath); qrc.QrcName = cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile); - qrc.Generated = sf->GetPropertyAsBool("GENERATED"); + qrc.Generated = sf->GetIsGenerated(); // RCC options { - std::string const opts = sf->GetSafeProperty("AUTORCC_OPTIONS"); + std::string const opts = sf->GetSafeProperty(AUTORCC_OPTIONS_str); if (!opts.empty()) { cmSystemTools::ExpandListArgument(opts, qrc.Options); } @@ -604,43 +710,65 @@ bool cmQtAutoGenInitializer::InitScanFiles() // mocs_compilation.cpp source acknowledged by this target. this->Target->ClearSourcesCache(); + // Scan through all source files in the makefile to extract moc and uic + // parameters. Historically we support non target source file parameters. + // The reason is that their file names might be discovered from source files + // at generation time. if (this->Moc.Enabled || this->Uic.Enabled) { - // Read skip files from makefile sources - { + // String constants + std::string const ui_str = "ui"; + std::string const AUTOUIC_OPTIONS_str = "AUTOUIC_OPTIONS"; + + for (cmSourceFile* sf : makefile->GetSourceFiles()) { + // sf->GetExtension() is only valid after sf->GetFullPath() ... + // Since we're iterating over source files that might be not in the + // target we need to check for path errors (not existing files). std::string pathError; - for (cmSourceFile* sf : makefile->GetSourceFiles()) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - // Since we're iterating over source files that might be not in the - // target we need to check for path errors (not existing files). - std::string const& fPath = sf->GetFullPath(&pathError); - if (!pathError.empty()) { - pathError.clear(); - continue; + std::string const& fullPath = sf->GetFullPath(&pathError); + if (!pathError.empty() || fullPath.empty()) { + continue; + } + + // Check file type + auto const fileType = cmSystemTools::GetFileFormat(sf->GetExtension()); + bool const isSource = (fileType == cmSystemTools::CXX_FILE_FORMAT) || + (fileType == cmSystemTools::HEADER_FILE_FORMAT); + bool const isUi = (this->Moc.Enabled && sf->GetExtension() == ui_str); + + // Process only certain file types + if (isSource || isUi) { + std::string const absFile = cmSystemTools::GetRealPath(fullPath); + // Acquire file properties + bool const skipAUTOGEN = sf->GetPropertyAsBool(SKIP_AUTOGEN_str); + bool const skipMoc = (this->Moc.Enabled && isSource) && + (skipAUTOGEN || sf->GetPropertyAsBool(SKIP_AUTOMOC_str)); + bool const skipUic = this->Uic.Enabled && + (skipAUTOGEN || sf->GetPropertyAsBool(SKIP_AUTOUIC_str)); + + // Register moc and uic skipped file + if (skipMoc) { + this->Moc.Skip.insert(absFile); } - cmSystemTools::FileFormat const fileType = - cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); - if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && - !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { - continue; + if (skipUic) { + this->Uic.Skip.insert(absFile); } - const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN"); - const bool mocSkip = this->Moc.Enabled && - (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); - const bool uicSkip = this->Uic.Enabled && - (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); - if (mocSkip || uicSkip) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - if (mocSkip) { - this->Moc.Skip.insert(absFile); - } - if (uicSkip) { - this->Uic.Skip.insert(absFile); + + // Check if the .ui file has uic options + if (isUi && !skipUic) { + std::string const uicOpts = sf->GetSafeProperty(AUTOUIC_OPTIONS_str); + if (!uicOpts.empty()) { + this->Uic.FileFiles.push_back(absFile); + std::vector<std::string> optsVec; + cmSystemTools::ExpandListArgument(uicOpts, optsVec); + this->Uic.FileOptions.push_back(std::move(optsVec)); } } } } + } - // Process GENERATED sources and headers + // Process GENERATED sources and headers + if (this->Moc.Enabled || this->Uic.Enabled) { if (!this->AutogenTarget.SourcesGenerated.empty() || !this->AutogenTarget.HeadersGenerated.empty()) { // Check status of policy CMP0071 @@ -712,22 +840,23 @@ bool cmQtAutoGenInitializer::InitScanFiles() msg += ":\n set_property(SOURCE file.h PROPERTY "; msg += property; msg += " ON)\n"; - makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); + makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); } } } - // Sort headers and sources - if (this->Moc.Enabled || this->Uic.Enabled) { - std::sort(this->AutogenTarget.Headers.begin(), - this->AutogenTarget.Headers.end()); - std::sort(this->AutogenTarget.Sources.begin(), - this->AutogenTarget.Sources.end()); - } + } + + // Sort headers and sources + if (this->Moc.Enabled || this->Uic.Enabled) { + std::sort(this->AutogenTarget.Headers.begin(), + this->AutogenTarget.Headers.end()); + std::sort(this->AutogenTarget.Sources.begin(), + this->AutogenTarget.Sources.end()); } // Process qrc files if (!this->Rcc.Qrcs.empty()) { - const bool QtV5 = (this->QtVersion.Major == 5); + const bool modernQt = (this->QtVersion.Major >= 5); // Target rcc options std::vector<std::string> optionsTarget; cmSystemTools::ExpandListArgument( @@ -799,10 +928,10 @@ bool cmQtAutoGenInitializer::InitScanFiles() std::vector<std::string> nameOpts; nameOpts.emplace_back("-name"); nameOpts.emplace_back(std::move(name)); - RccMergeOptions(opts, nameOpts, QtV5); + RccMergeOptions(opts, nameOpts, modernQt); } // Merge file option - RccMergeOptions(opts, qrc.Options, QtV5); + RccMergeOptions(opts, qrc.Options, modernQt); qrc.Options = std::move(opts); } // RCC resources @@ -810,7 +939,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (!qrc.Generated) { std::string error; if (!RccListInputs(qrc.QrcFile, qrc.Resources, error)) { - cmSystemTools::Error(error.c_str()); + cmSystemTools::Error(error); return false; } } @@ -832,7 +961,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Files provided by the autogen target std::vector<std::string> autogenProvides; if (this->Moc.Enabled) { - this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC); + this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC, true); autogenProvides.push_back(this->Moc.MocsCompilation); } @@ -882,6 +1011,10 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() if (!this->AutogenTarget.DependFiles.empty()) { usePRE_BUILD = false; } + // Cannot use PRE_BUILD when a global autogen target is in place + if (AutogenTarget.GlobalTarget) { + usePRE_BUILD = false; + } } // Create the autogen target/command if (usePRE_BUILD) { @@ -907,7 +1040,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Add link library target dependencies to the autogen target // dependencies - { + if (this->AutogenTarget.DependOrigin) { // add_dependencies/addUtility do not support generator expressions. // We depend only on the libraries found in all configs therefore. std::map<cmGeneratorTarget const*, std::size_t> commonTargets; @@ -944,8 +1077,10 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() new cmGeneratorTarget(autogenTarget, localGen)); // Forward origin utilities to autogen target - for (std::string const& depName : this->Target->Target->GetUtilities()) { - autogenTarget->AddUtility(depName, makefile); + if (this->AutogenTarget.DependOrigin) { + for (BT<std::string> const& depName : this->Target->GetUtilities()) { + autogenTarget->AddUtility(depName.Value, makefile); + } } // Add additional autogen target dependencies to autogen target for (cmTarget* depTarget : this->AutogenTarget.DependTargets) { @@ -959,6 +1094,12 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Add autogen target to the origin target dependencies this->Target->Target->AddUtility(this->AutogenTarget.Name, makefile); + + // Add autogen target to the global autogen target dependencies + if (this->AutogenTarget.GlobalTarget) { + this->GlobalInitializer->AddToGlobalAutoGen(localGen, + this->AutogenTarget.Name); + } } return true; @@ -968,6 +1109,7 @@ bool cmQtAutoGenInitializer::InitRccTargets() { cmMakefile* makefile = this->Target->Target->GetMakefile(); cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + auto rccTargetName = GetQtExecutableTargetName(this->QtVersion, "rcc"); for (Qrc const& qrc : this->Rcc.Qrcs) { // Register info file as generated by CMake @@ -978,6 +1120,11 @@ bool cmQtAutoGenInitializer::InitRccTargets() std::vector<std::string> ccOutput; ccOutput.push_back(qrc.RccFile); + std::vector<std::string> ccDepends; + // Add the .qrc and info file to the custom command dependencies + ccDepends.push_back(qrc.QrcFile); + ccDepends.push_back(qrc.InfoFile); + cmCustomCommandLines commandLines; if (this->MultiConfig) { // Build for all configurations @@ -1002,7 +1149,7 @@ bool cmQtAutoGenInitializer::InitRccTargets() std::string ccComment = "Automatic RCC for "; ccComment += FileProjectRelativePath(makefile, qrc.QrcFile); - if (qrc.Generated) { + if (qrc.Generated || this->Rcc.GlobalTarget) { // Create custom rcc target std::string ccName; { @@ -1013,15 +1160,12 @@ bool cmQtAutoGenInitializer::InitRccTargets() ccName += "_"; ccName += qrc.PathChecksum; } - std::vector<std::string> ccDepends; - // Add the .qrc and info file to the custom target dependencies - ccDepends.push_back(qrc.QrcFile); - ccDepends.push_back(qrc.InfoFile); cmTarget* autoRccTarget = makefile->AddUtilityCommand( ccName, cmMakefile::TargetOrigin::Generator, true, this->Dir.Work.c_str(), ccOutput, ccDepends, commandLines, false, ccComment.c_str()); + // Create autogen generator target localGen->AddGeneratorTarget( new cmGeneratorTarget(autoRccTarget, localGen)); @@ -1030,23 +1174,30 @@ bool cmQtAutoGenInitializer::InitRccTargets() if (!this->TargetsFolder.empty()) { autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str()); } + if (!rccTargetName.empty()) { + autoRccTarget->AddUtility(rccTargetName, makefile); + } } // Add autogen target to the origin target dependencies this->Target->Target->AddUtility(ccName, makefile); + + // Add autogen target to the global autogen target dependencies + if (this->Rcc.GlobalTarget) { + this->GlobalInitializer->AddToGlobalAutoRcc(localGen, ccName); + } } else { // Create custom rcc command { std::vector<std::string> ccByproducts; - std::vector<std::string> ccDepends; - // Add the .qrc and info file to the custom command dependencies - ccDepends.push_back(qrc.QrcFile); - ccDepends.push_back(qrc.InfoFile); // Add the resource files to the dependencies for (std::string const& fileName : qrc.Resources) { // Add resource file to the custom command dependencies ccDepends.push_back(fileName); } + if (!rccTargetName.empty()) { + ccDepends.push_back(rccTargetName); + } makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends, /*main_dependency*/ std::string(), commandLines, ccComment.c_str(), @@ -1066,7 +1217,7 @@ bool cmQtAutoGenInitializer::SetupCustomTargets() if (!cmSystemTools::MakeDirectory(this->Dir.Info)) { std::string emsg = ("AutoGen: Could not create directory: "); emsg += Quoted(this->Dir.Info); - cmSystemTools::Error(emsg.c_str()); + cmSystemTools::Error(emsg); return false; } @@ -1079,118 +1230,82 @@ bool cmQtAutoGenInitializer::SetupCustomTargets() } // Write AUTORCC info files - if (this->Rcc.Enabled && !this->SetupWriteRccInfo()) { - return false; - } - - return true; + return !this->Rcc.Enabled || this->SetupWriteRccInfo(); } bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() { - cmMakefile* makefile = this->Target->Target->GetMakefile(); - - cmGeneratedFileStream ofs; - ofs.SetCopyIfDifferent(true); - ofs.Open(this->AutogenTarget.InfoFile, false, true); + InfoWriter ofs(this->AutogenTarget.InfoFile); if (ofs) { // Utility lambdas - auto CWrite = [&ofs](const char* key, std::string const& value) { - ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) - << ")\n"; - }; - auto CWriteUInt = [&ofs](const char* key, unsigned int value) { - ofs << "set(" << key << " " << value << ")\n"; - }; - auto CWriteList = [&CWrite](const char* key, - std::vector<std::string> const& list) { - CWrite(key, cmJoin(list, ";")); - }; - auto CWriteNestedLists = - [&CWrite](const char* key, - std::vector<std::vector<std::string>> const& lists) { - std::vector<std::string> seplist; - for (const std::vector<std::string>& list : lists) { - std::string blist = "{"; - blist += cmJoin(list, ";"); - blist += "}"; - seplist.push_back(std::move(blist)); - } - CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep)); - }; - auto CWriteSet = [&CWrite](const char* key, - std::set<std::string> const& list) { - CWrite(key, cmJoin(list, ";")); - }; - auto CWriteMap = [&ofs](const char* key, - std::map<std::string, std::string> const& map) { - for (auto const& item : map) { - ofs << "set(" << key << "_" << item.first << " " - << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; - } - }; + cmMakefile* makefile = this->Target->Target->GetMakefile(); auto MfDef = [makefile](const char* key) { return makefile->GetSafeDefinition(key); }; - // Write - ofs << "# Meta\n"; - CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); - CWrite("AM_PARALLEL", this->AutogenTarget.Parallel); - CWrite("AM_VERBOSITY", this->Verbosity); - - ofs << "# Directories\n"; - CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR")); - CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR")); - CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR")); - CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR")); - CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE", - MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")); - CWrite("AM_BUILD_DIR", this->Dir.Build); - CWrite("AM_INCLUDE_DIR", this->Dir.Include); - CWriteMap("AM_INCLUDE_DIR", this->Dir.ConfigInclude); - - ofs << "# Files\n"; - CWriteList("AM_SOURCES", this->AutogenTarget.Sources); - CWriteList("AM_HEADERS", this->AutogenTarget.Headers); - CWrite("AM_SETTINGS_FILE", this->AutogenTarget.SettingsFile); - CWriteMap("AM_SETTINGS_FILE", this->AutogenTarget.ConfigSettingsFile); - - ofs << "# Qt\n"; - CWriteUInt("AM_QT_VERSION_MAJOR", this->QtVersion.Major); - CWrite("AM_QT_MOC_EXECUTABLE", this->Moc.Executable); - CWrite("AM_QT_UIC_EXECUTABLE", this->Uic.Executable); - + // Write common settings + ofs.Write("# Meta\n"); + ofs.Write("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); + ofs.Write("AM_PARALLEL", this->AutogenTarget.Parallel); + ofs.Write("AM_VERBOSITY", this->Verbosity); + + ofs.Write("# Directories\n"); + ofs.Write("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR")); + ofs.Write("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR")); + ofs.Write("AM_CMAKE_CURRENT_SOURCE_DIR", + MfDef("CMAKE_CURRENT_SOURCE_DIR")); + ofs.Write("AM_CMAKE_CURRENT_BINARY_DIR", + MfDef("CMAKE_CURRENT_BINARY_DIR")); + ofs.Write("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE", + MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")); + ofs.Write("AM_BUILD_DIR", this->Dir.Build); + ofs.Write("AM_INCLUDE_DIR", this->Dir.Include); + ofs.WriteConfig("AM_INCLUDE_DIR", this->Dir.ConfigInclude); + + ofs.Write("# Files\n"); + ofs.WriteStrings("AM_SOURCES", this->AutogenTarget.Sources); + ofs.WriteStrings("AM_HEADERS", this->AutogenTarget.Headers); + ofs.Write("AM_SETTINGS_FILE", this->AutogenTarget.SettingsFile); + ofs.WriteConfig("AM_SETTINGS_FILE", + this->AutogenTarget.ConfigSettingsFile); + + ofs.Write("# Qt\n"); + ofs.WriteUInt("AM_QT_VERSION_MAJOR", this->QtVersion.Major); + ofs.Write("AM_QT_MOC_EXECUTABLE", this->Moc.Executable); + ofs.Write("AM_QT_UIC_EXECUTABLE", this->Uic.Executable); + + // Write moc settings if (this->Moc.Enabled) { - ofs << "# MOC settings\n"; - CWriteSet("AM_MOC_SKIP", this->Moc.Skip); - CWrite("AM_MOC_DEFINITIONS", this->Moc.Defines); - CWriteMap("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines); - CWrite("AM_MOC_INCLUDES", this->Moc.Includes); - CWriteMap("AM_MOC_INCLUDES", this->Moc.ConfigIncludes); - CWrite("AM_MOC_OPTIONS", - this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS")); - CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE")); - CWrite("AM_MOC_MACRO_NAMES", - this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES")); - CWrite("AM_MOC_DEPEND_FILTERS", - this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS")); - CWrite("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd); + ofs.Write("# MOC settings\n"); + ofs.WriteStrings("AM_MOC_SKIP", this->Moc.Skip); + ofs.WriteStrings("AM_MOC_DEFINITIONS", this->Moc.Defines); + ofs.WriteConfigStrings("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines); + ofs.WriteStrings("AM_MOC_INCLUDES", this->Moc.Includes); + ofs.WriteConfigStrings("AM_MOC_INCLUDES", this->Moc.ConfigIncludes); + ofs.Write("AM_MOC_OPTIONS", + this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS")); + ofs.Write("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE")); + ofs.Write("AM_MOC_MACRO_NAMES", + this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES")); + ofs.Write("AM_MOC_DEPEND_FILTERS", + this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS")); + ofs.Write("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd); } + // Write uic settings if (this->Uic.Enabled) { - ofs << "# UIC settings\n"; - CWriteSet("AM_UIC_SKIP", this->Uic.Skip); - CWrite("AM_UIC_TARGET_OPTIONS", this->Uic.Options); - CWriteMap("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions); - CWriteList("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles); - CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions); - CWriteList("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths); + ofs.Write("# UIC settings\n"); + ofs.WriteStrings("AM_UIC_SKIP", this->Uic.Skip); + ofs.WriteStrings("AM_UIC_TARGET_OPTIONS", this->Uic.Options); + ofs.WriteConfigStrings("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions); + ofs.WriteStrings("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles); + ofs.WriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions); + ofs.WriteStrings("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths); } } else { std::string err = "AutoGen: Could not write file "; err += this->AutogenTarget.InfoFile; - cmSystemTools::Error(err.c_str()); + cmSystemTools::Error(err); return false; } @@ -1200,51 +1315,37 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() bool cmQtAutoGenInitializer::SetupWriteRccInfo() { for (Qrc const& qrc : this->Rcc.Qrcs) { - cmGeneratedFileStream ofs; - ofs.SetCopyIfDifferent(true); - ofs.Open(qrc.InfoFile, false, true); + InfoWriter ofs(qrc.InfoFile); if (ofs) { - // Utility lambdas - auto CWrite = [&ofs](const char* key, std::string const& value) { - ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) - << ")\n"; - }; - auto CWriteMap = [&ofs](const char* key, - std::map<std::string, std::string> const& map) { - for (auto const& item : map) { - ofs << "set(" << key << "_" << item.first << " " - << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; - } - }; - // Write - ofs << "# Configurations\n"; - CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); - CWrite("ARCC_VERBOSITY", this->Verbosity); - ofs << "# Settings file\n"; - CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile); - CWriteMap("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile); - - ofs << "# Directories\n"; - CWrite("ARCC_BUILD_DIR", this->Dir.Build); - CWrite("ARCC_INCLUDE_DIR", this->Dir.Include); - CWriteMap("ARCC_INCLUDE_DIR", this->Dir.ConfigInclude); - - ofs << "# Rcc executable\n"; - CWrite("ARCC_RCC_EXECUTABLE", this->Rcc.Executable); - CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->Rcc.ListOptions, ";")); - - ofs << "# Rcc job\n"; - CWrite("ARCC_LOCK_FILE", qrc.LockFile); - CWrite("ARCC_SOURCE", qrc.QrcFile); - CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum); - CWrite("ARCC_OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.RccFile)); - CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";")); - CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";")); + ofs.Write("# Configurations\n"); + ofs.Write("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); + ofs.Write("ARCC_VERBOSITY", this->Verbosity); + ofs.Write("# Settings file\n"); + ofs.Write("ARCC_SETTINGS_FILE", qrc.SettingsFile); + ofs.WriteConfig("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile); + + ofs.Write("# Directories\n"); + ofs.Write("ARCC_BUILD_DIR", this->Dir.Build); + ofs.Write("ARCC_INCLUDE_DIR", this->Dir.Include); + ofs.WriteConfig("ARCC_INCLUDE_DIR", this->Dir.ConfigInclude); + + ofs.Write("# Rcc executable\n"); + ofs.Write("ARCC_RCC_EXECUTABLE", this->Rcc.Executable); + ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS", this->Rcc.ListOptions); + + ofs.Write("# Rcc job\n"); + ofs.Write("ARCC_LOCK_FILE", qrc.LockFile); + ofs.Write("ARCC_SOURCE", qrc.QrcFile); + ofs.Write("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum); + ofs.Write("ARCC_OUTPUT_NAME", + cmSystemTools::GetFilenameName(qrc.RccFile)); + ofs.WriteStrings("ARCC_OPTIONS", qrc.Options); + ofs.WriteStrings("ARCC_INPUTS", qrc.Resources); } else { std::string err = "AutoRcc: Could not write file "; err += qrc.InfoFile; - cmSystemTools::Error(err.c_str()); + cmSystemTools::Error(err); return false; } } @@ -1253,7 +1354,8 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo() } void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename, - GeneratorT genType) + GeneratorT genType, + bool prepend) { // Register source file in makefile cmMakefile* makefile = this->Target->Target->GetMakefile(); @@ -1267,266 +1369,169 @@ void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename, AddToSourceGroup(makefile, filename, genType); // Add source file to target - this->Target->AddSource(filename); + this->Target->AddSource(filename, prepend); +} + +static unsigned int CharPtrToUInt(const char* const input) +{ + unsigned long tmp = 0; + if (input != nullptr && cmSystemTools::StringToULong(input, &tmp)) { + return static_cast<unsigned int>(tmp); + } + return 0; } -cmQtAutoGenInitializer::IntegerVersion cmQtAutoGenInitializer::GetQtVersion( +static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions( cmGeneratorTarget const* target) { - cmQtAutoGenInitializer::IntegerVersion res; cmMakefile* makefile = target->Target->GetMakefile(); - - // -- Major version - std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); - if (qtMajor.empty()) { - qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); - } - if (qtMajor.empty()) { - const char* dirprop = makefile->GetProperty("Qt5Core_VERSION_MAJOR"); - if (dirprop) { - qtMajor = dirprop; + std::vector<cmQtAutoGen::IntegerVersion> result; + // Adds a version to the result (nullptr safe) + auto addVersion = [&result](const char* major, const char* minor) { + cmQtAutoGen::IntegerVersion ver(CharPtrToUInt(major), + CharPtrToUInt(minor)); + if (ver.Major != 0) { + result.emplace_back(ver); } + }; + // Qt version variable prefixes + std::array<std::string, 3> const prefixes{ { "Qt6Core", "Qt5Core", "QT" } }; + + // Read versions from variables + for (const std::string& prefix : prefixes) { + addVersion(makefile->GetDefinition(prefix + "_VERSION_MAJOR"), + makefile->GetDefinition(prefix + "_VERSION_MINOR")); } - { - const char* targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""); - if (targetQtVersion != nullptr) { - qtMajor = targetQtVersion; - } + + // Read versions from directory properties + for (const std::string& prefix : prefixes) { + addVersion(makefile->GetProperty(prefix + "_VERSION_MAJOR"), + makefile->GetProperty(prefix + "_VERSION_MINOR")); } - // -- Minor version - std::string qtMinor; - if (!qtMajor.empty()) { - if (qtMajor == "5") { - qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR"); - if (qtMinor.empty()) { - const char* dirprop = makefile->GetProperty("Qt5Core_VERSION_MINOR"); - if (dirprop) { - qtMinor = dirprop; + return result; +} + +std::pair<cmQtAutoGen::IntegerVersion, unsigned int> +cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) +{ + std::pair<IntegerVersion, unsigned int> res( + IntegerVersion(), + CharPtrToUInt(target->GetLinkInterfaceDependentStringProperty( + "QT_MAJOR_VERSION", ""))); + + auto knownQtVersions = GetKnownQtVersions(target); + if (!knownQtVersions.empty()) { + if (res.second == 0) { + // No specific version was requested by the target: + // Use highest known Qt version. + res.first = knownQtVersions.at(0); + } else { + // Pick a version from the known versions: + for (auto it : knownQtVersions) { + if (it.Major == res.second) { + res.first = it; + break; } } } - if (qtMinor.empty()) { - qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR"); - } - { - const char* targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", - ""); - if (targetQtVersion != nullptr) { - qtMinor = targetQtVersion; - } - } } - - // -- Convert to integer - if (!qtMajor.empty() && !qtMinor.empty()) { - unsigned long majorUL(0); - unsigned long minorUL(0); - if (cmSystemTools::StringToULong(qtMajor.c_str(), &majorUL) && - cmSystemTools::StringToULong(qtMinor.c_str(), &minorUL)) { - res.Major = static_cast<unsigned int>(majorUL); - res.Minor = static_cast<unsigned int>(minorUL); - } - } - return res; } -bool cmQtAutoGenInitializer::GetMocExecutable() +std::pair<bool, std::string> cmQtAutoGenInitializer::GetQtExecutable( + const std::string& executable, bool ignoreMissingTarget, std::string* output) { + const std::string upperExecutable = cmSystemTools::UpperCase(executable); + std::string result = this->Target->Target->GetSafeProperty( + "AUTO" + upperExecutable + "_EXECUTABLE"); + if (!result.empty()) { + cmListFileBacktrace lfbt = + this->Target->Target->GetMakefile()->GetBacktrace(); + cmGeneratorExpression ge(lfbt); + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(result); + result = cge->Evaluate(this->Target->GetLocalGenerator(), ""); + + return std::make_pair(true, result); + } + std::string err; - // Find moc executable + // Find executable { - std::string targetName; - if (this->QtVersion.Major == 5) { - targetName = "Qt5::moc"; - } else if (this->QtVersion.Major == 4) { - targetName = "Qt4::moc"; + const std::string targetName = + GetQtExecutableTargetName(this->QtVersion, executable); + if (targetName.empty()) { + err = "The AUTO" + upperExecutable + " feature "; + err += "supports only Qt 4, Qt 5 and Qt 6."; } else { - err = "The AUTOMOC feature supports only Qt 4 and Qt 5"; - } - if (!targetName.empty()) { cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName); if (tgt != nullptr) { - this->Moc.Executable = tgt->ImportedGetLocation(""); + if (tgt->IsImported()) { + result = tgt->ImportedGetLocation(""); + } else { + result = tgt->GetLocation(""); + } } else { + if (ignoreMissingTarget) { + return std::make_pair(true, ""); + } + err = "Could not find target " + targetName; } } } - // Test moc command + // Test executable if (err.empty()) { - if (cmSystemTools::FileExists(this->Moc.Executable, true)) { - std::vector<std::string> command; - command.push_back(this->Moc.Executable); - command.push_back("-h"); - std::string stdOut; - std::string stdErr; - int retVal = 0; - bool result = cmSystemTools::RunSingleCommand( - command, &stdOut, &stdErr, &retVal, nullptr, - cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); - if (!result) { - err = "The moc test command failed: "; - err += QuotedCommand(command); - } - } else { - err = "The moc executable "; - err += Quoted(this->Moc.Executable); - err += " does not exist"; - } + this->GlobalInitializer->GetExecutableTestOutput(executable, result, err, + output); } // Print error if (!err.empty()) { - std::string msg = "AutoMoc ("; + std::string msg = "AutoGen ("; msg += this->Target->GetName(); msg += "): "; msg += err; - cmSystemTools::Error(msg.c_str()); - return false; + cmSystemTools::Error(msg); + return std::make_pair(false, ""); } - return true; + return std::make_pair(true, result); } -bool cmQtAutoGenInitializer::GetUicExecutable() +bool cmQtAutoGenInitializer::GetMocExecutable() { - std::string err; - - // Find uic executable - { - std::string targetName; - if (this->QtVersion.Major == 5) { - targetName = "Qt5::uic"; - } else if (this->QtVersion.Major == 4) { - targetName = "Qt4::uic"; - } else { - err = "The AUTOUIC feature supports only Qt 4 and Qt 5"; - } - if (!targetName.empty()) { - cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName); - if (tgt != nullptr) { - this->Uic.Executable = tgt->ImportedGetLocation(""); - } else { - if (this->QtVersion.Major == 5) { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway - } else { - err = "Could not find target " + targetName; - } - } - } - } - - // Test uic command - if (err.empty() && !this->Uic.Executable.empty()) { - if (cmSystemTools::FileExists(this->Uic.Executable, true)) { - std::vector<std::string> command; - command.push_back(this->Uic.Executable); - command.push_back("-h"); - std::string stdOut; - std::string stdErr; - int retVal = 0; - bool result = cmSystemTools::RunSingleCommand( - command, &stdOut, &stdErr, &retVal, nullptr, - cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); - if (!result) { - err = "The uic test command failed: "; - err += QuotedCommand(command); - } - } else { - err = "The uic executable "; - err += Quoted(this->Uic.Executable); - err += " does not exist"; - } - } - - // Print error - if (!err.empty()) { - std::string msg = "AutoUic ("; - msg += this->Target->GetName(); - msg += "): "; - msg += err; - cmSystemTools::Error(msg.c_str()); - return false; - } + const auto result = this->GetQtExecutable("moc", false, nullptr); + this->Moc.Executable = result.second; + return result.first; +} - return true; +bool cmQtAutoGenInitializer::GetUicExecutable() +{ + const auto result = this->GetQtExecutable("uic", true, nullptr); + this->Uic.Executable = result.second; + return result.first; } bool cmQtAutoGenInitializer::GetRccExecutable() { - std::string err; - - // Find rcc executable - { - std::string targetName; - if (this->QtVersion.Major == 5) { - targetName = "Qt5::rcc"; - } else if (this->QtVersion.Major == 4) { - targetName = "Qt4::rcc"; - } else { - err = "The AUTORCC feature supports only Qt 4 and Qt 5"; - } - if (!targetName.empty()) { - cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName); - if (tgt != nullptr) { - this->Rcc.Executable = tgt->ImportedGetLocation(""); - } else { - err = "Could not find target " + targetName; - } - } + std::string stdOut; + const auto result = this->GetQtExecutable("rcc", false, &stdOut); + this->Rcc.Executable = result.second; + if (!result.first) { + return false; } - // Test rcc command - if (err.empty()) { - if (cmSystemTools::FileExists(this->Rcc.Executable, true)) { - std::vector<std::string> command; - command.push_back(this->Rcc.Executable); - command.push_back("-h"); - std::string stdOut; - std::string stdErr; - int retVal = 0; - bool result = cmSystemTools::RunSingleCommand( - command, &stdOut, &stdErr, &retVal, nullptr, - cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); - if (result) { - // Detect if rcc supports (-)-list - if (this->QtVersion.Major == 5) { - if (stdOut.find("--list") != std::string::npos) { - this->Rcc.ListOptions.push_back("--list"); - } else { - this->Rcc.ListOptions.push_back("-list"); - } - } - } else { - err = "The rcc test command failed: "; - err += QuotedCommand(command); - } + if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) { + if (stdOut.find("--list") != std::string::npos) { + this->Rcc.ListOptions.emplace_back("--list"); } else { - err = "The rcc executable "; - err += Quoted(this->Rcc.Executable); - err += " does not exist"; + this->Rcc.ListOptions.emplace_back("-list"); } } - - // Print error - if (!err.empty()) { - std::string msg = "AutoRcc ("; - msg += this->Target->GetName(); - msg += "): "; - msg += err; - cmSystemTools::Error(msg.c_str()); - return false; - } - return true; } diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index ce00e00fe..781dd15d6 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -4,15 +4,19 @@ #define cmQtAutoGenInitializer_h #include "cmConfigure.h" // IWYU pragma: keep +#include "cmGeneratedFileStream.h" #include "cmQtAutoGen.h" #include <map> +#include <ostream> #include <set> #include <string> +#include <utility> #include <vector> class cmGeneratorTarget; class cmTarget; +class cmQtAutoGenGlobalInitializer; /// @brief Initializes the QtAutoGen generators class cmQtAutoGenInitializer : public cmQtAutoGen @@ -22,13 +26,6 @@ public: class Qrc { public: - Qrc() - : Generated(false) - , Unique(false) - { - } - - public: std::string LockFile; std::string QrcFile; std::string QrcName; @@ -37,18 +34,55 @@ public: std::string SettingsFile; std::map<std::string, std::string> ConfigSettingsFile; std::string RccFile; - bool Generated; - bool Unique; + bool Generated = false; + bool Unique = false; std::vector<std::string> Options; std::vector<std::string> Resources; }; + /// @brief Writes a CMake info file + class InfoWriter + { + public: + /// @brief Open the given file + InfoWriter(std::string const& filename); + + /// @return True if the file is open + explicit operator bool() const { return static_cast<bool>(Ofs_); } + + void Write(const char* text) { Ofs_ << text; } + void Write(const char* key, std::string const& value); + void WriteUInt(const char* key, unsigned int value); + + template <class C> + void WriteStrings(const char* key, C const& container); + void WriteConfig(const char* key, + std::map<std::string, std::string> const& map); + template <class C> + void WriteConfigStrings(const char* key, + std::map<std::string, C> const& map); + void WriteNestedLists(const char* key, + std::vector<std::vector<std::string>> const& lists); + + private: + template <class IT> + static std::string ListJoin(IT it_begin, IT it_end); + static std::string ConfigKey(const char* key, std::string const& config); + + private: + cmGeneratedFileStream Ofs_; + }; + public: - static IntegerVersion GetQtVersion(cmGeneratorTarget const* target); + /// @return The detected Qt version and the required Qt major version + static std::pair<IntegerVersion, unsigned int> GetQtVersion( + cmGeneratorTarget const* target); - cmQtAutoGenInitializer(cmGeneratorTarget* target, bool mocEnabled, + cmQtAutoGenInitializer(cmQtAutoGenGlobalInitializer* globalInitializer, + cmGeneratorTarget* target, + IntegerVersion const& qtVersion, bool mocEnabled, bool uicEnabled, bool rccEnabled, - IntegerVersion const& qtVersion); + bool globalAutogenTarget, bool globalAutoRccTarget); bool InitCustomTargets(); bool SetupCustomTargets(); @@ -65,7 +99,8 @@ private: bool SetupWriteAutogenInfo(); bool SetupWriteRccInfo(); - void AddGeneratedSource(std::string const& filename, GeneratorT genType); + void AddGeneratedSource(std::string const& filename, GeneratorT genType, + bool prepend = false); bool GetMocExecutable(); bool GetUicExecutable(); @@ -75,7 +110,12 @@ private: std::vector<std::string>& files, std::string& errorMessage); + std::pair<bool, std::string> GetQtExecutable(const std::string& executable, + bool ignoreMissingTarget, + std::string* output); + private: + cmQtAutoGenGlobalInitializer* GlobalInitializer; cmGeneratorTarget* Target; // Configuration @@ -100,6 +140,7 @@ private: struct { std::string Name; + bool GlobalTarget = false; // Settings std::string Parallel; // Configuration files @@ -107,6 +148,7 @@ private: std::string SettingsFile; std::map<std::string, std::string> ConfigSettingsFile; // Dependencies + bool DependOrigin = false; std::set<std::string> DependFiles; std::set<cmTarget*> DependTargets; // Sources to process @@ -123,10 +165,10 @@ private: std::string Executable; std::string PredefsCmd; std::set<std::string> Skip; - std::string Includes; - std::map<std::string, std::string> ConfigIncludes; - std::string Defines; - std::map<std::string, std::string> ConfigDefines; + std::vector<std::string> Includes; + std::map<std::string, std::vector<std::string>> ConfigIncludes; + std::set<std::string> Defines; + std::map<std::string, std::set<std::string>> ConfigDefines; std::string MocsCompilation; } Moc; @@ -137,8 +179,8 @@ private: std::string Executable; std::set<std::string> Skip; std::vector<std::string> SearchPaths; - std::string Options; - std::map<std::string, std::string> ConfigOptions; + std::vector<std::string> Options; + std::map<std::string, std::vector<std::string>> ConfigOptions; std::vector<std::string> FileFiles; std::vector<std::vector<std::string>> FileOptions; } Uic; @@ -147,6 +189,7 @@ private: struct { bool Enabled = false; + bool GlobalTarget = false; std::string Executable; std::vector<std::string> ListOptions; std::vector<Qrc> Qrcs; diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 734b2d70d..e2d7debed 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -8,12 +8,14 @@ #include "cmAlgorithms.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmake.h" #include <algorithm> +#include <utility> // -- Class methods @@ -52,7 +54,7 @@ void cmQtAutoGenerator::Logger::Info(GeneratorT genType, } { std::lock_guard<std::mutex> lock(Mutex_); - cmSystemTools::Stdout(msg.c_str(), msg.size()); + cmSystemTools::Stdout(msg); } } @@ -76,7 +78,7 @@ void cmQtAutoGenerator::Logger::Warning(GeneratorT genType, msg.push_back('\n'); { std::lock_guard<std::mutex> lock(Mutex_); - cmSystemTools::Stdout(msg.c_str(), msg.size()); + cmSystemTools::Stdout(msg); } } @@ -105,7 +107,7 @@ void cmQtAutoGenerator::Logger::Error(GeneratorT genType, msg.push_back('\n'); { std::lock_guard<std::mutex> lock(Mutex_); - cmSystemTools::Stderr(msg.c_str(), msg.size()); + cmSystemTools::Stderr(msg); } } @@ -147,7 +149,7 @@ void cmQtAutoGenerator::Logger::ErrorCommand( msg.push_back('\n'); { std::lock_guard<std::mutex> lock(Mutex_); - cmSystemTools::Stderr(msg.c_str(), msg.size()); + cmSystemTools::Stderr(msg); } } @@ -685,7 +687,7 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile, bool success = false; { - cmake cm(cmake::RoleScript); + cmake cm(cmake::RoleScript, cmState::Unknown); cm.SetHomeOutputDirectory(InfoDir()); cm.SetHomeDirectory(InfoDir()); cm.GetCurrentSnapshot().SetDefaultDefinitions(); diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index 75143f5a6..9956a99a3 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -24,7 +24,6 @@ class cmMakefile; /// @brief Base class for QtAutoGen gernerators class cmQtAutoGenerator : public cmQtAutoGen { - CM_DISABLE_COPY(cmQtAutoGenerator) public: // -- Types @@ -206,9 +205,6 @@ public: bool MergedOutput = false; }; - // -- Constructor - ReadOnlyProcessT() = default; - // -- Const accessors const SetupT& Setup() const { return Setup_; } ProcessResultT* Result() const { return Setup_.Result; } @@ -248,6 +244,9 @@ public: cmQtAutoGenerator(); virtual ~cmQtAutoGenerator(); + cmQtAutoGenerator(cmQtAutoGenerator const&) = delete; + cmQtAutoGenerator& operator=(cmQtAutoGenerator const&) = delete; + // -- Run bool Run(std::string const& infoFile, std::string const& config); diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index 2e6f90f7c..ddff4cf87 100644 --- a/Source/cmQtAutoGeneratorMocUic.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -1,19 +1,21 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGeneratorMocUic.h" -#include "cmQtAutoGen.h" #include <algorithm> #include <array> +#include <cstddef> #include <functional> #include <list> #include <memory> +#include <set> #include <sstream> #include <utility> #include "cmAlgorithms.h" #include "cmCryptoHash.h" #include "cmMakefile.h" +#include "cmQtAutoGen.h" #include "cmSystemTools.h" #include "cmake.h" @@ -676,19 +678,21 @@ void cmQtAutoGeneratorMocUic::JobMocT::Process(WorkerT& wrk) BuildFile += '/'; BuildFile += IncludeString; } else { - std::string rel = wrk.FileSys().GetFilePathChecksum(SourceFile); - rel += "/moc_"; - rel += wrk.FileSys().GetFilenameWithoutLastExtension(SourceFile); - rel += ".cpp"; - // Register relative file path - wrk.Gen().ParallelMocAutoRegister(rel); + // Relative build path + std::string relPath = wrk.FileSys().GetFilePathChecksum(SourceFile); + relPath += "/moc_"; + relPath += wrk.FileSys().GetFilenameWithoutLastExtension(SourceFile); + + // Register relative file path with duplication check + relPath = wrk.Gen().ParallelMocAutoRegister(relPath); + // Absolute build path if (wrk.Base().MultiConfig) { BuildFile = wrk.Base().AutogenIncludeDir; BuildFile += '/'; - BuildFile += rel; + BuildFile += relPath; } else { - BuildFile = wrk.Base().AbsoluteBuildPath(rel); + BuildFile = wrk.Base().AbsoluteBuildPath(relPath); } } @@ -842,10 +846,10 @@ void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk) wrk.Moc().AllOptions.end()); // Add predefs include if (!wrk.Moc().PredefsFileAbs.empty()) { - cmd.push_back("--include"); + cmd.emplace_back("--include"); cmd.push_back(wrk.Moc().PredefsFileAbs); } - cmd.push_back("-o"); + cmd.emplace_back("-o"); cmd.push_back(BuildFile); cmd.push_back(SourceFile); @@ -961,7 +965,7 @@ void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic(WorkerT& wrk) } cmd.insert(cmd.end(), allOpts.begin(), allOpts.end()); } - cmd.push_back("-o"); + cmd.emplace_back("-o"); cmd.push_back(BuildFile); cmd.push_back(SourceFile); @@ -1109,8 +1113,7 @@ void cmQtAutoGeneratorMocUic::WorkerT::UVProcessStart(uv_async_t* handle) { std::lock_guard<std::mutex> lock(wrk.ProcessMutex_); if (wrk.Process_ && !wrk.Process_->IsStarted()) { - wrk.Process_->start(handle->loop, - std::bind(&WorkerT::UVProcessFinished, &wrk)); + wrk.Process_->start(handle->loop, [&wrk] { wrk.UVProcessFinished(); }); } } } @@ -1130,11 +1133,6 @@ void cmQtAutoGeneratorMocUic::WorkerT::UVProcessFinished() cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic() : Base_(&FileSys()) , Moc_(&FileSys()) - , Stage_(StageT::SETTINGS_READ) - , JobsRemain_(0) - , JobError_(false) - , JobThreadsAbort_(false) - , MocAutoFileUpdated_(false) { // Precompile regular expressions Moc_.RegExpInclude.compile( @@ -1147,9 +1145,7 @@ cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic() UVRequest().init(*UVLoop(), &cmQtAutoGeneratorMocUic::UVPollStage, this); } -cmQtAutoGeneratorMocUic::~cmQtAutoGeneratorMocUic() -{ -} +cmQtAutoGeneratorMocUic::~cmQtAutoGeneratorMocUic() = default; bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) { @@ -1216,7 +1212,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) }; // -- Read info file - if (!makefile->ReadListFile(InfoFile().c_str())) { + if (!makefile->ReadListFile(InfoFile())) { Log().ErrorFile(GeneratorT::GEN, InfoFile(), "File processing failed"); return false; } @@ -1279,16 +1275,6 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) Moc_.SkipList.insert(lst.begin(), lst.end()); } Moc_.Definitions = InfoGetConfigList("AM_MOC_DEFINITIONS"); -#ifdef _WIN32 - { - std::string win32("WIN32"); - auto itB = Moc().Definitions.cbegin(); - auto itE = Moc().Definitions.cend(); - if (std::find(itB, itE, win32) == itE) { - Moc_.Definitions.emplace_back(std::move(win32)); - } - } -#endif Moc_.IncludePaths = InfoGetConfigList("AM_MOC_INCLUDES"); Moc_.Options = InfoGetList("AM_MOC_OPTIONS"); Moc_.RelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE"); @@ -1301,7 +1287,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) std::string& error) { if (!key.empty()) { if (!exp.empty()) { - Moc_.DependFilters.push_back(KeyExpT()); + Moc_.DependFilters.emplace_back(); KeyExpT& filter(Moc_.DependFilters.back()); if (filter.Exp.compile(exp)) { filter.Key = key; @@ -1519,7 +1505,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) } // Append framework includes for (std::string const& path : frameworkPaths) { - Moc_.Includes.push_back("-F"); + Moc_.Includes.emplace_back("-F"); Moc_.Includes.push_back(path); } } @@ -1969,11 +1955,31 @@ bool cmQtAutoGeneratorMocUic::ParallelMocIncluded( return (MocIncludedFiles_.find(sourceFile) != MocIncludedFiles_.end()); } -void cmQtAutoGeneratorMocUic::ParallelMocAutoRegister( - std::string const& mocFile) +std::string cmQtAutoGeneratorMocUic::ParallelMocAutoRegister( + std::string const& baseName) { - std::lock_guard<std::mutex> mocLock(JobsMutex_); - MocAutoFiles_.emplace(mocFile); + std::string res; + { + std::lock_guard<std::mutex> mocLock(JobsMutex_); + res = baseName; + res += ".cpp"; + if (MocAutoFiles_.find(res) == MocAutoFiles_.end()) { + MocAutoFiles_.emplace(res); + } else { + // Append number suffix to the file name + for (unsigned int ii = 2; ii != 1024; ++ii) { + res = baseName; + res += '_'; + res += std::to_string(ii); + res += ".cpp"; + if (MocAutoFiles_.find(res) == MocAutoFiles_.end()) { + MocAutoFiles_.emplace(res); + break; + } + } + } + } + return res; } void cmQtAutoGeneratorMocUic::ParallelMocAutoUpdated() diff --git a/Source/cmQtAutoGeneratorMocUic.h b/Source/cmQtAutoGeneratorMocUic.h index 222695411..c22df29ab 100644 --- a/Source/cmQtAutoGeneratorMocUic.h +++ b/Source/cmQtAutoGeneratorMocUic.h @@ -11,7 +11,6 @@ #include "cm_uv.h" #include "cmsys/RegularExpression.hxx" -#include <algorithm> #include <condition_variable> #include <cstddef> #include <deque> @@ -21,6 +20,7 @@ #include <set> #include <string> #include <thread> +#include <utility> #include <vector> class cmMakefile; @@ -28,11 +28,13 @@ class cmMakefile; // @brief AUTOMOC and AUTOUIC generator class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator { - CM_DISABLE_COPY(cmQtAutoGeneratorMocUic) public: cmQtAutoGeneratorMocUic(); ~cmQtAutoGeneratorMocUic() override; + cmQtAutoGeneratorMocUic(cmQtAutoGeneratorMocUic const&) = delete; + cmQtAutoGeneratorMocUic& operator=(cmQtAutoGeneratorMocUic const&) = delete; + public: // -- Types class WorkerT; @@ -49,8 +51,8 @@ public: { } - KeyExpT(std::string const& key, std::string const& exp) - : Key(key) + KeyExpT(std::string key, std::string const& exp) + : Key(std::move(key)) , Exp(exp) { } @@ -63,7 +65,6 @@ public: /// class BaseSettingsT { - CM_DISABLE_COPY(BaseSettingsT) public: // -- Volatile methods BaseSettingsT(FileSystem* fileSystem) @@ -75,6 +76,9 @@ public: { } + BaseSettingsT(BaseSettingsT const&) = delete; + BaseSettingsT& operator=(BaseSettingsT const&) = delete; + // -- Const methods std::string AbsoluteBuildPath(std::string const& relativePath) const; bool FindHeader(std::string& header, @@ -103,13 +107,15 @@ public: /// class MocSettingsT { - CM_DISABLE_COPY(MocSettingsT) public: MocSettingsT(FileSystem* fileSys) : FileSys(fileSys) { } + MocSettingsT(MocSettingsT const&) = delete; + MocSettingsT& operator=(MocSettingsT const&) = delete; + // -- Const methods bool skipped(std::string const& fileName) const; std::string FindMacro(std::string const& content) const; @@ -145,9 +151,12 @@ public: /// class UicSettingsT { - CM_DISABLE_COPY(UicSettingsT) public: UicSettingsT() = default; + + UicSettingsT(UicSettingsT const&) = delete; + UicSettingsT& operator=(UicSettingsT const&) = delete; + // -- Const methods bool skipped(std::string const& fileName) const; @@ -166,10 +175,13 @@ public: /// class JobT { - CM_DISABLE_COPY(JobT) public: JobT() = default; virtual ~JobT() = default; + + JobT(JobT const&) = delete; + JobT& operator=(JobT const&) = delete; + // -- Abstract processing interface virtual void Process(WorkerT& wrk) = 0; }; @@ -240,10 +252,10 @@ public: class JobMocT : public JobT { public: - JobMocT(std::string&& sourceFile, std::string const& includerFile, + JobMocT(std::string&& sourceFile, std::string includerFile, std::string&& includeString) : SourceFile(std::move(sourceFile)) - , IncluderFile(includerFile) + , IncluderFile(std::move(includerFile)) , IncludeString(std::move(includeString)) { } @@ -269,10 +281,10 @@ public: class JobUicT : public JobT { public: - JobUicT(std::string&& sourceFile, std::string const& includerFile, + JobUicT(std::string&& sourceFile, std::string includerFile, std::string&& includeString) : SourceFile(std::move(sourceFile)) - , IncluderFile(includerFile) + , IncluderFile(std::move(includerFile)) , IncludeString(std::move(includeString)) { } @@ -293,11 +305,13 @@ public: /// class WorkerT { - CM_DISABLE_COPY(WorkerT) public: WorkerT(cmQtAutoGeneratorMocUic* gen, uv_loop_t* uvLoop); ~WorkerT(); + WorkerT(WorkerT const&) = delete; + WorkerT& operator=(WorkerT const&) = delete; + // -- Const accessors cmQtAutoGeneratorMocUic& Gen() const { return *Gen_; } Logger& Log() const { return Gen_->Log(); } @@ -375,7 +389,7 @@ public: bool ParallelJobPushMoc(JobHandleT& jobHandle); bool ParallelJobPushUic(JobHandleT& jobHandle); bool ParallelMocIncluded(std::string const& sourceFile); - void ParallelMocAutoRegister(std::string const& mocFile); + std::string ParallelMocAutoRegister(std::string const& baseName); void ParallelMocAutoUpdated(); private: @@ -404,7 +418,7 @@ private: MocSettingsT Moc_; UicSettingsT Uic_; // -- Progress - StageT Stage_; + StageT Stage_ = StageT::SETTINGS_READ; // -- Job queues std::mutex JobsMutex_; struct @@ -416,15 +430,15 @@ private: JobQueueT Uic; } JobQueues_; JobQueueT JobQueue_; - std::size_t volatile JobsRemain_; - bool volatile JobError_; - bool volatile JobThreadsAbort_; + std::size_t volatile JobsRemain_ = 0; + bool volatile JobError_ = false; + bool volatile JobThreadsAbort_ = false; std::condition_variable JobsConditionRead_; // -- Moc meta std::set<std::string> MocIncludedStrings_; std::set<std::string> MocIncludedFiles_; std::set<std::string> MocAutoFiles_; - bool volatile MocAutoFileUpdated_; + bool volatile MocAutoFileUpdated_ = false; // -- Settings file std::string SettingsFile_; std::string SettingsStringMoc_; diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx index 65c674110..021a15f18 100644 --- a/Source/cmQtAutoGeneratorRcc.cxx +++ b/Source/cmQtAutoGeneratorRcc.cxx @@ -10,25 +10,15 @@ #include "cmSystemTools.h" #include "cmUVHandlePtr.h" -#include <functional> - // -- Class methods cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc() - : MultiConfig_(false) - , SettingsChanged_(false) - , Stage_(StageT::SETTINGS_READ) - , Error_(false) - , Generate_(false) - , BuildFileChanged_(false) { // Initialize libuv asynchronous iteration request UVRequest().init(*UVLoop(), &cmQtAutoGeneratorRcc::UVPollStage, this); } -cmQtAutoGeneratorRcc::~cmQtAutoGeneratorRcc() -{ -} +cmQtAutoGeneratorRcc::~cmQtAutoGeneratorRcc() = default; bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile) { @@ -64,7 +54,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile) }; // -- Read info file - if (!makefile->ReadListFile(InfoFile().c_str())) { + if (!makefile->ReadListFile(InfoFile())) { Log().ErrorFile(GeneratorT::RCC, InfoFile(), "File processing failed"); return false; } @@ -609,7 +599,7 @@ bool cmQtAutoGeneratorRcc::GenerateRcc() std::vector<std::string> cmd; cmd.push_back(RccExecutable_); cmd.insert(cmd.end(), Options_.begin(), Options_.end()); - cmd.push_back("-o"); + cmd.emplace_back("-o"); cmd.push_back(RccFileOutput_); cmd.push_back(QrcFile_); // We're done here if the process fails to start @@ -670,8 +660,7 @@ bool cmQtAutoGeneratorRcc::StartProcess( Process_ = cm::make_unique<ReadOnlyProcessT>(); Process_->setup(&ProcessResult_, mergedOutput, command, workingDirectory); // Start process - if (!Process_->start(UVLoop(), - std::bind(&cm::uv_async_ptr::send, &UVRequest()))) { + if (!Process_->start(UVLoop(), [this] { UVRequest().send(); })) { Log().ErrorFile(GeneratorT::RCC, QrcFile_, ProcessResult_.ErrorMessage); Error_ = true; // Clean up diff --git a/Source/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGeneratorRcc.h index 74cec3661..1ec1c4a8c 100644 --- a/Source/cmQtAutoGeneratorRcc.h +++ b/Source/cmQtAutoGeneratorRcc.h @@ -17,11 +17,13 @@ class cmMakefile; // @brief AUTORCC generator class cmQtAutoGeneratorRcc : public cmQtAutoGenerator { - CM_DISABLE_COPY(cmQtAutoGeneratorRcc) public: cmQtAutoGeneratorRcc(); ~cmQtAutoGeneratorRcc() override; + cmQtAutoGeneratorRcc(cmQtAutoGeneratorRcc const&) = delete; + cmQtAutoGeneratorRcc& operator=(cmQtAutoGeneratorRcc const&) = delete; + private: // -- Types @@ -70,7 +72,7 @@ private: private: // -- Config settings - bool MultiConfig_; + bool MultiConfig_ = false; // -- Directories std::string AutogenBuildDir_; std::string IncludeDir_; @@ -95,12 +97,12 @@ private: // -- Settings file std::string SettingsFile_; std::string SettingsString_; - bool SettingsChanged_; + bool SettingsChanged_ = false; // -- libuv loop - StageT Stage_; - bool Error_; - bool Generate_; - bool BuildFileChanged_; + StageT Stage_ = StageT::SETTINGS_READ; + bool Error_ = false; + bool Generate_ = false; + bool BuildFileChanged_ = false; }; #endif diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx index 32ad0b080..55204d708 100644 --- a/Source/cmRST.cxx +++ b/Source/cmRST.cxx @@ -13,9 +13,9 @@ #include <stddef.h> #include <utility> -cmRST::cmRST(std::ostream& os, std::string const& docroot) +cmRST::cmRST(std::ostream& os, std::string docroot) : OS(os) - , DocRoot(docroot) + , DocRoot(std::move(docroot)) , IncludeDepth(0) , OutputLinePending(false) , LastLineEndedInColonColon(false) @@ -122,7 +122,7 @@ void cmRST::ProcessModule(std::istream& is) void cmRST::Reset() { if (!this->MarkupLines.empty()) { - this->UnindentLines(this->MarkupLines); + cmRST::UnindentLines(this->MarkupLines); } switch (this->Directive) { case DirectiveNone: @@ -178,7 +178,7 @@ void cmRST::ProcessLine(std::string const& line) // Record the literal lines to output after whole block. // Ignore the language spec and record the opening line as blank. this->Directive = DirectiveCodeBlock; - this->MarkupLines.push_back(""); + this->MarkupLines.emplace_back(); } else if (this->ReplaceDirective.find(line)) { // Record the replace directive content. this->Directive = DirectiveReplace; @@ -221,15 +221,14 @@ void cmRST::ProcessLine(std::string const& line) // Record the literal lines to output after whole block. this->Markup = MarkupNormal; this->Directive = DirectiveLiteralBlock; - this->MarkupLines.push_back(""); + this->MarkupLines.emplace_back(); this->OutputLine("", false); } // Print non-markup lines. else { this->NormalLine(line); this->LastLineEndedInColonColon = - (line.size() >= 2 && line[line.size() - 2] == ':' && - line[line.size() - 1] == ':'); + (line.size() >= 2 && line[line.size() - 2] == ':' && line.back() == ':'); } } diff --git a/Source/cmRST.h b/Source/cmRST.h index ee478677d..d8d2a0bab 100644 --- a/Source/cmRST.h +++ b/Source/cmRST.h @@ -25,7 +25,7 @@ class cmRST { public: - cmRST(std::ostream& os, std::string const& docroot); + cmRST(std::ostream& os, std::string docroot); bool ProcessFile(std::string const& fname, bool isModule = false); private: diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx index a71861af7..e347a2cf5 100644 --- a/Source/cmRulePlaceholderExpander.cxx +++ b/Source/cmRulePlaceholderExpander.cxx @@ -10,13 +10,13 @@ #include "cmSystemTools.h" cmRulePlaceholderExpander::cmRulePlaceholderExpander( - std::map<std::string, std::string> const& compilers, - std::map<std::string, std::string> const& variableMappings, - std::string const& compilerSysroot, std::string const& linkerSysroot) - : Compilers(compilers) - , VariableMappings(variableMappings) - , CompilerSysroot(compilerSysroot) - , LinkerSysroot(linkerSysroot) + std::map<std::string, std::string> compilers, + std::map<std::string, std::string> variableMappings, + std::string compilerSysroot, std::string linkerSysroot) + : Compilers(std::move(compilers)) + , VariableMappings(std::move(variableMappings)) + , CompilerSysroot(std::move(compilerSysroot)) + , LinkerSysroot(std::move(linkerSysroot)) { } @@ -110,7 +110,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( if (replaceValues.Target) { if (variable == "TARGET_QUOTED") { std::string targetQuoted = replaceValues.Target; - if (!targetQuoted.empty() && targetQuoted[0] != '\"') { + if (!targetQuoted.empty() && targetQuoted.front() != '\"') { targetQuoted = '\"'; targetQuoted += replaceValues.Target; targetQuoted += '\"'; @@ -120,7 +120,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( if (variable == "TARGET_UNQUOTED") { std::string unquoted = replaceValues.Target; std::string::size_type sz = unquoted.size(); - if (sz > 2 && unquoted[0] == '\"' && unquoted[sz - 1] == '\"') { + if (sz > 2 && unquoted.front() == '\"' && unquoted.back() == '\"') { unquoted = unquoted.substr(1, sz - 2); } return unquoted; @@ -162,6 +162,16 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( } } } + if (replaceValues.SwiftAuxiliarySources) { + if (variable == "SWIFT_AUXILIARY_SOURCES") { + return replaceValues.SwiftAuxiliarySources; + } + } + if (replaceValues.SwiftModuleName) { + if (variable == "SWIFT_MODULE_NAME") { + return replaceValues.SwiftModuleName; + } + } if (variable == "TARGET_SONAME" || variable == "SONAME_FLAG" || variable == "TARGET_INSTALLNAME_DIR") { // All these variables depend on TargetSOName diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h index a7d8ceefb..5c0363729 100644 --- a/Source/cmRulePlaceholderExpander.h +++ b/Source/cmRulePlaceholderExpander.h @@ -15,9 +15,9 @@ class cmRulePlaceholderExpander { public: cmRulePlaceholderExpander( - std::map<std::string, std::string> const& compilers, - std::map<std::string, std::string> const& variableMappings, - std::string const& compilerSysroot, std::string const& linkerSysroot); + std::map<std::string, std::string> compilers, + std::map<std::string, std::string> variableMappings, + std::string compilerSysroot, std::string linkerSysroot); void SetTargetImpLib(std::string const& targetImpLib) { @@ -58,6 +58,8 @@ public: const char* Includes; const char* DependencyFile; const char* FilterPrefix; + const char* SwiftAuxiliarySources; + const char* SwiftModuleName; }; // Expand rule variables in CMake of the type found in language rules diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx index 2cae71436..9182b4165 100644 --- a/Source/cmScriptGenerator.cxx +++ b/Source/cmScriptGenerator.cxx @@ -4,20 +4,19 @@ #include "cmSystemTools.h" -cmScriptGenerator::cmScriptGenerator( - const std::string& config_var, - std::vector<std::string> const& configurations) - : RuntimeConfigVariable(config_var) - , Configurations(configurations) +#include <utility> + +cmScriptGenerator::cmScriptGenerator(std::string config_var, + std::vector<std::string> configurations) + : RuntimeConfigVariable(std::move(config_var)) + , Configurations(std::move(configurations)) , ConfigurationName("") , ConfigurationTypes(nullptr) , ActionsPerConfig(false) { } -cmScriptGenerator::~cmScriptGenerator() -{ -} +cmScriptGenerator::~cmScriptGenerator() = default; void cmScriptGenerator::Generate( std::ostream& os, const std::string& config, diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h index c8fed1950..e334d5bad 100644 --- a/Source/cmScriptGenerator.h +++ b/Source/cmScriptGenerator.h @@ -12,10 +12,7 @@ class cmScriptGeneratorIndent { public: - cmScriptGeneratorIndent() - : Level(0) - { - } + cmScriptGeneratorIndent() = default; cmScriptGeneratorIndent(int level) : Level(level) { @@ -32,7 +29,7 @@ public: } private: - int Level; + int Level = 0; }; inline std::ostream& operator<<(std::ostream& os, cmScriptGeneratorIndent indent) @@ -47,13 +44,14 @@ inline std::ostream& operator<<(std::ostream& os, */ class cmScriptGenerator { - CM_DISABLE_COPY(cmScriptGenerator) - public: - cmScriptGenerator(const std::string& config_var, - std::vector<std::string> const& configurations); + cmScriptGenerator(std::string config_var, + std::vector<std::string> configurations); virtual ~cmScriptGenerator(); + cmScriptGenerator(cmScriptGenerator const&) = delete; + cmScriptGenerator& operator=(cmScriptGenerator const&) = delete; + void Generate(std::ostream& os, const std::string& config, std::vector<std::string> const& configurationTypes); diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index 5dd4413c4..0f51e0eb6 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -16,9 +16,7 @@ cmSearchPath::cmSearchPath(cmFindCommon* findCmd) { } -cmSearchPath::~cmSearchPath() -{ -} +cmSearchPath::~cmSearchPath() = default; void cmSearchPath::ExtractWithout(const std::set<std::string>& ignore, std::vector<std::string>& outPaths, diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index f15a14a4c..e740c0519 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -96,11 +96,16 @@ void cmServer::ProcessRequest(cmConnection* connection, return; } - cmSystemTools::SetMessageCallback(reportMessage, - const_cast<cmServerRequest*>(&request)); + cmSystemTools::SetMessageCallback( + [&request](const char* msg, const char* title) { + reportMessage(msg, title, request); + }); + if (this->Protocol) { this->Protocol->CMakeInstance()->SetProgressCallback( - reportProgress, const_cast<cmServerRequest*>(&request)); + [&request](const char* msg, float prog) { + reportProgress(msg, prog, request); + }); this->WriteResponse(connection, this->Protocol->Process(request), debug.get()); } else { @@ -150,28 +155,25 @@ void cmServer::PrintHello(cmConnection* connection) const this->WriteJsonObject(connection, hello, nullptr); } -void cmServer::reportProgress(const char* msg, float progress, void* data) +void cmServer::reportProgress(const char* msg, float progress, + const cmServerRequest& request) { - const cmServerRequest* request = static_cast<const cmServerRequest*>(data); - assert(request); if (progress < 0.0f || progress > 1.0f) { - request->ReportMessage(msg, ""); + request.ReportMessage(msg, ""); } else { - request->ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg); + request.ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg); } } void cmServer::reportMessage(const char* msg, const char* title, - bool& /* cancel */, void* data) + const cmServerRequest& request) { - const cmServerRequest* request = static_cast<const cmServerRequest*>(data); - assert(request); assert(msg); std::string titleString; if (title) { titleString = title; } - request->ReportMessage(std::string(msg), titleString); + request.ReportMessage(std::string(msg), titleString); } cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request) @@ -216,7 +218,7 @@ cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request) } this->Protocol = - this->FindMatchingProtocol(this->SupportedProtocols, major, minor); + cmServer::FindMatchingProtocol(this->SupportedProtocols, major, minor); if (!this->Protocol) { return request.ReportError("Protocol version not supported."); } @@ -417,7 +419,7 @@ static void __start_thread(void* arg) auto server = static_cast<cmServerBase*>(arg); std::string error; bool success = server->Serve(&error); - if (!success || error.empty() == false) { + if (!success || !error.empty()) { std::cerr << "Error during serve: " << error << std::endl; } } diff --git a/Source/cmServer.h b/Source/cmServer.h index ca37ce276..e1ed27a0c 100644 --- a/Source/cmServer.h +++ b/Source/cmServer.h @@ -88,14 +88,15 @@ protected: class cmServer : public cmServerBase { - CM_DISABLE_COPY(cmServer) - public: class DebugInfo; cmServer(cmConnection* conn, bool supportExperimental); ~cmServer() override; + cmServer(cmServer const&) = delete; + cmServer& operator=(cmServer const&) = delete; + bool Serve(std::string* errorMessage) override; cmFileMonitor* FileMonitor() const; @@ -118,9 +119,10 @@ public: void OnConnected(cmConnection* connection) override; private: - static void reportProgress(const char* msg, float progress, void* data); - static void reportMessage(const char* msg, const char* title, bool& cancel, - void* data); + static void reportProgress(const char* msg, float progress, + const cmServerRequest& request); + static void reportMessage(const char* msg, const char* title, + const cmServerRequest& request); // Handle requests: cmServerResponse SetProtocolVersion(const cmServerRequest& request); diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx index 1fc8cf8ec..844a85890 100644 --- a/Source/cmServerConnection.cxx +++ b/Source/cmServerConnection.cxx @@ -7,13 +7,13 @@ #include "cmServerDictionary.h" #include "cm_uv.h" -#include <algorithm> #ifdef _WIN32 # include "io.h" #else # include <unistd.h> #endif #include <cassert> +#include <utility> cmStdIoConnection::cmStdIoConnection( cmConnectionBufferStrategy* bufferStrategy) @@ -119,9 +119,7 @@ cmServerStdIoConnection::cmServerStdIoConnection() { } -cmConnectionBufferStrategy::~cmConnectionBufferStrategy() -{ -} +cmConnectionBufferStrategy::~cmConnectionBufferStrategy() = default; void cmConnectionBufferStrategy::clear() { diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index f051fd9b1..203ee93e4 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -20,6 +20,7 @@ #include <functional> #include <memory> #include <string> +#include <utility> #include <vector> // Get rid of some windows macros: @@ -39,11 +40,10 @@ std::vector<std::string> toStringList(const Json::Value& in) } // namespace cmServerRequest::cmServerRequest(cmServer* server, cmConnection* connection, - const std::string& t, const std::string& c, - const Json::Value& d) - : Type(t) - , Cookie(c) - , Data(d) + std::string t, std::string c, Json::Value d) + : Type(std::move(t)) + , Cookie(std::move(c)) + , Data(std::move(d)) , Connection(connection) , m_Server(server) { @@ -130,7 +130,8 @@ bool cmServerProtocol::Activate(cmServer* server, { assert(server); this->m_Server = server; - this->m_CMakeInstance = cm::make_unique<cmake>(cmake::RoleProject); + this->m_CMakeInstance = + cm::make_unique<cmake>(cmake::RoleProject, cmState::Project); const bool result = this->DoActivate(request, errorMessage); if (!result) { this->m_CMakeInstance = nullptr; @@ -221,13 +222,22 @@ bool cmServerProtocol1::DoActivate(const cmServerRequest& request, std::string* errorMessage) { std::string sourceDirectory = request.Data[kSOURCE_DIRECTORY_KEY].asString(); - const std::string buildDirectory = - request.Data[kBUILD_DIRECTORY_KEY].asString(); + std::string buildDirectory = request.Data[kBUILD_DIRECTORY_KEY].asString(); std::string generator = request.Data[kGENERATOR_KEY].asString(); std::string extraGenerator = request.Data[kEXTRA_GENERATOR_KEY].asString(); std::string toolset = request.Data[kTOOLSET_KEY].asString(); std::string platform = request.Data[kPLATFORM_KEY].asString(); + // normalize source and build directory + if (!sourceDirectory.empty()) { + sourceDirectory = cmSystemTools::CollapseFullPath(sourceDirectory); + cmSystemTools::ConvertToUnixSlashes(sourceDirectory); + } + if (!buildDirectory.empty()) { + buildDirectory = cmSystemTools::CollapseFullPath(buildDirectory); + cmSystemTools::ConvertToUnixSlashes(buildDirectory); + } + if (buildDirectory.empty()) { setErrorMessage(errorMessage, std::string("\"") + kBUILD_DIRECTORY_KEY + @@ -244,7 +254,7 @@ bool cmServerProtocol1::DoActivate(const cmServerRequest& request, return false; } - const std::string cachePath = cm->FindCacheFile(buildDirectory); + const std::string cachePath = cmake::FindCacheFile(buildDirectory); if (cm->LoadCache(cachePath)) { cmState* state = cm->GetState(); @@ -706,15 +716,15 @@ cmServerResponse cmServerProtocol1::ProcessCTests( } cmServerProtocol1::GeneratorInformation::GeneratorInformation( - const std::string& generatorName, const std::string& extraGeneratorName, - const std::string& toolset, const std::string& platform, - const std::string& sourceDirectory, const std::string& buildDirectory) - : GeneratorName(generatorName) - , ExtraGeneratorName(extraGeneratorName) - , Toolset(toolset) - , Platform(platform) - , SourceDirectory(sourceDirectory) - , BuildDirectory(buildDirectory) + std::string generatorName, std::string extraGeneratorName, + std::string toolset, std::string platform, std::string sourceDirectory, + std::string buildDirectory) + : GeneratorName(std::move(generatorName)) + , ExtraGeneratorName(std::move(extraGeneratorName)) + , Toolset(std::move(toolset)) + , Platform(std::move(platform)) + , SourceDirectory(std::move(sourceDirectory)) + , BuildDirectory(std::move(buildDirectory)) { } diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index df71cffc7..2f55a208f 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -56,9 +56,8 @@ public: cmConnection* Connection; private: - cmServerRequest(cmServer* server, cmConnection* connection, - const std::string& t, const std::string& c, - const Json::Value& d); + cmServerRequest(cmServer* server, cmConnection* connection, std::string t, + std::string c, Json::Value d); void ReportProgress(int min, int current, int max, const std::string& message) const; @@ -72,12 +71,13 @@ private: class cmServerProtocol { - CM_DISABLE_COPY(cmServerProtocol) - public: cmServerProtocol() = default; virtual ~cmServerProtocol() = default; + cmServerProtocol(cmServerProtocol const&) = delete; + cmServerProtocol& operator=(cmServerProtocol const&) = delete; + virtual std::pair<int, int> ProtocolVersion() const = 0; virtual bool IsExperimental() const = 0; virtual const cmServerResponse Process(const cmServerRequest& request) = 0; @@ -140,12 +140,10 @@ private: { public: GeneratorInformation() = default; - GeneratorInformation(const std::string& generatorName, - const std::string& extraGeneratorName, - const std::string& toolset, - const std::string& platform, - const std::string& sourceDirectory, - const std::string& buildDirectory); + GeneratorInformation(std::string generatorName, + std::string extraGeneratorName, std::string toolset, + std::string platform, std::string sourceDirectory, + std::string buildDirectory); void SetupGenerator(cmake* cm, std::string* errorMessage); diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index 985aac80f..6bd071cfb 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -4,6 +4,7 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -37,6 +38,14 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, putEnvArg += args[1]; cmSystemTools::PutEnv(putEnvArg); } + // if there's extra arguments, warn user + // that they are ignored by this command. + if (args.size() > 2) { + std::string m = "Only the first value argument is used when setting " + "an environment variable. Argument '" + + args[2] + "' and later are unused."; + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m); + } return true; } @@ -54,7 +63,7 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, } // SET (VAR PARENT_SCOPE) // Removes the definition of VAR // in the parent scope. - if (args.size() == 2 && args[args.size() - 1] == "PARENT_SCOPE") { + if (args.size() == 2 && args.back() == "PARENT_SCOPE") { this->Makefile->RaiseScope(variable, nullptr); return true; } @@ -74,12 +83,12 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, unsigned int ignoreLastArgs = 0; // look for PARENT_SCOPE argument - if (args.size() > 1 && args[args.size() - 1] == "PARENT_SCOPE") { + if (args.size() > 1 && args.back() == "PARENT_SCOPE") { parentScope = true; ignoreLastArgs++; } else { // look for FORCE argument - if (args.size() > 4 && args[args.size() - 1] == "FORCE") { + if (args.size() > 4 && args.back() == "FORCE") { force = true; ignoreLastArgs++; } @@ -103,7 +112,7 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, // we should be nice and try to catch some simple screwups if the last or // next to last args are CACHE then they screwed up. If they used FORCE // without CACHE they screwed up - if ((args[args.size() - 1] == "CACHE") || + if ((args.back() == "CACHE") || (args.size() > 1 && args[args.size() - 2] == "CACHE") || (force && !cache)) { this->SetError("given invalid arguments for CACHE mode."); @@ -112,7 +121,15 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, if (cache) { std::string::size_type cacheStart = args.size() - 3 - (force ? 1 : 0); - type = cmState::StringToCacheEntryType(args[cacheStart + 1].c_str()); + if (!cmState::StringToCacheEntryType(args[cacheStart + 1].c_str(), type)) { + std::string m = "implicitly converting '" + args[cacheStart + 1] + + "' to 'STRING' type."; + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m); + // Setting this may not be required, since it's + // initialized as a string. Keeping this here to + // ensure that the type is actually converting to a string. + type = cmStateEnums::STRING; + } docstring = args[cacheStart + 2].c_str(); } diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx index 8445b027a..9388e7ccf 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.cxx +++ b/Source/cmSetSourceFilesPropertiesCommand.cxx @@ -53,17 +53,17 @@ bool cmSetSourceFilesPropertiesCommand::RunCommand( for (j = propbeg; j != propend; ++j) { // old style allows for specifier before PROPERTIES keyword if (*j == "ABSTRACT") { - propertyPairs.push_back("ABSTRACT"); - propertyPairs.push_back("1"); + propertyPairs.emplace_back("ABSTRACT"); + propertyPairs.emplace_back("1"); } else if (*j == "WRAP_EXCLUDE") { - propertyPairs.push_back("WRAP_EXCLUDE"); - propertyPairs.push_back("1"); + propertyPairs.emplace_back("WRAP_EXCLUDE"); + propertyPairs.emplace_back("1"); } else if (*j == "GENERATED") { generated = true; - propertyPairs.push_back("GENERATED"); - propertyPairs.push_back("1"); + propertyPairs.emplace_back("GENERATED"); + propertyPairs.emplace_back("1"); } else if (*j == "COMPILE_FLAGS") { - propertyPairs.push_back("COMPILE_FLAGS"); + propertyPairs.emplace_back("COMPILE_FLAGS"); ++j; if (j == propend) { errors = "called with incorrect number of arguments " @@ -72,7 +72,7 @@ bool cmSetSourceFilesPropertiesCommand::RunCommand( } propertyPairs.push_back(*j); } else if (*j == "OBJECT_DEPENDS") { - propertyPairs.push_back("OBJECT_DEPENDS"); + propertyPairs.emplace_back("OBJECT_DEPENDS"); ++j; if (j == propend) { errors = "called with incorrect number of arguments " diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index 7f33b7a33..01758ee3a 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -19,12 +19,12 @@ bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args, return false; } std::vector<std::string> paths; - paths.push_back("/usr/bsd"); - paths.push_back("/usr/sbin"); - paths.push_back("/usr/bin"); - paths.push_back("/bin"); - paths.push_back("/sbin"); - paths.push_back("/usr/local/bin"); + paths.emplace_back("/usr/bsd"); + paths.emplace_back("/usr/sbin"); + paths.emplace_back("/usr/bin"); + paths.emplace_back("/bin"); + paths.emplace_back("/sbin"); + paths.emplace_back("/usr/local/bin"); const char* cacheValue = this->Makefile->GetDefinition(args[0]); if (cacheValue) { diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 5d1f3f006..d05fb68d9 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -2,11 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSourceFile.h" -#include <sstream> +#include <array> +#include <utility> #include "cmCustomCommand.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmProperty.h" #include "cmState.h" #include "cmSystemTools.h" @@ -16,8 +18,6 @@ cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name, cmSourceFileLocationKind kind) : Location(mf, name, kind) { - this->CustomCommand = nullptr; - this->FindFullPathFailed = false; } cmSourceFile::~cmSourceFile() @@ -31,6 +31,8 @@ std::string const& cmSourceFile::GetExtension() const } const std::string cmSourceFile::propLANGUAGE = "LANGUAGE"; +const std::string cmSourceFile::propLOCATION = "LOCATION"; +const std::string cmSourceFile::propGENERATED = "GENERATED"; void cmSourceFile::SetObjectLibrary(std::string const& objlib) { @@ -111,91 +113,88 @@ std::string const& cmSourceFile::GetFullPath() const bool cmSourceFile::FindFullPath(std::string* error) { - // If this method has already failed once do not try again. - if (this->FindFullPathFailed) { - return false; - } - - // If the file is generated compute the location without checking on - // disk. - if (this->GetPropertyAsBool("GENERATED")) { + // If the file is generated compute the location without checking on disk. + if (this->GetIsGenerated()) { // The file is either already a full path or is relative to the // build directory for the target. this->Location.DirectoryUseBinary(); - this->FullPath = this->Location.GetDirectory(); - this->FullPath += "/"; - this->FullPath += this->Location.GetName(); + this->FullPath = this->Location.GetFullPath(); return true; } - // The file is not generated. It must exist on disk. - cmMakefile const* mf = this->Location.GetMakefile(); - const char* tryDirs[3] = { nullptr, nullptr, nullptr }; - if (this->Location.DirectoryIsAmbiguous()) { - tryDirs[0] = mf->GetCurrentSourceDirectory().c_str(); - tryDirs[1] = mf->GetCurrentBinaryDirectory().c_str(); - } else { - tryDirs[0] = ""; + // If this method has already failed once do not try again. + if (this->FindFullPathFailed) { + return false; } - cmake const* const cmakeInst = mf->GetCMakeInstance(); - std::vector<std::string> const& srcExts = cmakeInst->GetSourceExtensions(); - std::vector<std::string> const& hdrExts = cmakeInst->GetHeaderExtensions(); - for (const char* const* di = tryDirs; *di; ++di) { - std::string tryPath = this->Location.GetDirectory(); - if (!tryPath.empty()) { - tryPath += "/"; - } - tryPath += this->Location.GetName(); - tryPath = cmSystemTools::CollapseFullPath(tryPath, *di); - if (this->TryFullPath(tryPath, "")) { + // The file is not generated. It must exist on disk. + cmMakefile const* makefile = this->Location.GetMakefile(); + // 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() } + }; + + // Tries to find the file in a given directory + auto findInDir = [this, &extsLists, &lPath](std::string const& dir) -> bool { + // Compute full path + std::string const fullPath = cmSystemTools::CollapseFullPath(lPath, dir); + // Try full path + if (cmSystemTools::FileExists(fullPath)) { + this->FullPath = fullPath; return true; } - for (std::string const& ext : srcExts) { - if (this->TryFullPath(tryPath, ext)) { - return true; + // Try full path with extension + for (auto exts : extsLists) { + for (std::string const& ext : *exts) { + if (!ext.empty()) { + std::string extPath = fullPath; + extPath += '.'; + extPath += ext; + if (cmSystemTools::FileExists(extPath)) { + this->FullPath = extPath; + return true; + } + } } } - for (std::string const& ext : hdrExts) { - if (this->TryFullPath(tryPath, ext)) { - return true; - } + // File not found + return false; + }; + + // Try to find the file in various directories + if (this->Location.DirectoryIsAmbiguous()) { + if (findInDir(makefile->GetCurrentSourceDirectory()) || + findInDir(makefile->GetCurrentBinaryDirectory())) { + return true; + } + } else { + if (findInDir({})) { + return true; } } - std::ostringstream e; - std::string missing = this->Location.GetDirectory(); - if (!missing.empty()) { - missing += "/"; - } - missing += this->Location.GetName(); - e << "Cannot find source file:\n " << missing << "\nTried extensions"; - for (std::string const& srcExt : srcExts) { - e << " ." << srcExt; - } - for (std::string const& ext : hdrExts) { - e << " ." << ext; + // Compose error + std::string err; + err += "Cannot find source file:\n "; + err += lPath; + err += "\nTried extensions"; + for (auto exts : extsLists) { + for (std::string const& ext : *exts) { + err += " ."; + err += ext; + } } - if (error) { - *error = e.str(); + if (error != nullptr) { + *error = std::move(err); } else { - this->Location.GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str()); + makefile->IssueMessage(MessageType::FATAL_ERROR, err); } this->FindFullPathFailed = true; - return false; -} -bool cmSourceFile::TryFullPath(const std::string& path, const std::string& ext) -{ - std::string tryPath = path; - if (!ext.empty()) { - tryPath += "."; - tryPath += ext; - } - if (cmSystemTools::FileExists(tryPath)) { - this->FullPath = tryPath; - return true; - } + // File not found return false; } @@ -240,12 +239,22 @@ bool cmSourceFile::Matches(cmSourceFileLocation const& loc) void cmSourceFile::SetProperty(const std::string& prop, const char* value) { this->Properties.SetProperty(prop, value); + + // Update IsGenerated flag + if (prop == propGENERATED) { + this->IsGenerated = cmSystemTools::IsOn(value); + } } void cmSourceFile::AppendProperty(const std::string& prop, const char* value, bool asString) { this->Properties.AppendProperty(prop, value, asString); + + // Update IsGenerated flag + if (prop == propGENERATED) { + this->IsGenerated = this->GetPropertyAsBool(propGENERATED); + } } const char* cmSourceFile::GetPropertyForUser(const std::string& prop) @@ -264,7 +273,7 @@ const char* cmSourceFile::GetPropertyForUser(const std::string& prop) // cmSourceFileLocation class to commit to a particular full path to // the source file as late as possible. If the users requests the // LOCATION property we must commit now. - if (prop == "LOCATION") { + if (prop == propLOCATION) { // Commit to a location. this->GetFullPath(); } @@ -276,7 +285,7 @@ const char* cmSourceFile::GetPropertyForUser(const std::string& prop) const char* cmSourceFile::GetProperty(const std::string& prop) const { // Check for computed properties. - if (prop == "LOCATION") { + if (prop == propLOCATION) { if (this->FullPath.empty()) { return nullptr; } diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index ab0f22927..a82a58aa9 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -55,6 +55,10 @@ public: command like get_property or get_source_file_property. */ const char* GetPropertyForUser(const std::string& prop); + ///! Checks is the GENERATED property is set and true + /// @return Equivalent to GetPropertyAsBool("GENERATED") + bool GetIsGenerated() const { return this->IsGenerated; } + /** * The full path to the file. The non-const version of this method * may attempt to locate the file on disk and finalize its location. @@ -106,20 +110,22 @@ public: private: cmSourceFileLocation Location; cmPropertyMap Properties; - cmCustomCommand* CustomCommand; + cmCustomCommand* CustomCommand = nullptr; std::string Extension; std::string Language; std::string FullPath; std::string ObjectLibrary; std::vector<std::string> Depends; - bool FindFullPathFailed; + bool FindFullPathFailed = false; + bool IsGenerated = false; bool FindFullPath(std::string* error); - bool TryFullPath(const std::string& path, const std::string& ext); void CheckExtension(); void CheckLanguage(std::string const& ext); static const std::string propLANGUAGE; + static const std::string propLOCATION; + static const std::string propGENERATED; }; // TODO: Factor out into platform information modules. diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index 15433f94f..acacba26c 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -5,17 +5,13 @@ #include "cmAlgorithms.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmake.h" #include <assert.h> -cmSourceFileLocation::cmSourceFileLocation() - : Makefile(nullptr) - , AmbiguousDirectory(true) - , AmbiguousExtension(true) -{ -} +cmSourceFileLocation::cmSourceFileLocation() = default; cmSourceFileLocation::cmSourceFileLocation(const cmSourceFileLocation& loc) : Makefile(loc.Makefile) @@ -46,6 +42,16 @@ cmSourceFileLocation::cmSourceFileLocation(cmMakefile const* mf, } } +std::string cmSourceFileLocation::GetFullPath() const +{ + std::string path = this->GetDirectory(); + if (!path.empty()) { + path += '/'; + } + path += this->GetName(); + return path; +} + void cmSourceFileLocation::Update(cmSourceFileLocation const& loc) { if (this->AmbiguousDirectory && !loc.AmbiguousDirectory) { @@ -197,7 +203,7 @@ bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc) // This can occur when referencing a source file from a different // directory. This is not yet allowed. this->Makefile->IssueMessage( - cmake::INTERNAL_ERROR, + MessageType::INTERNAL_ERROR, "Matches error: Each side has a directory relative to a different " "location. This can occur when referencing a source file from a " "different directory. This is not yet allowed."); diff --git a/Source/cmSourceFileLocation.h b/Source/cmSourceFileLocation.h index 886a18458..87040b882 100644 --- a/Source/cmSourceFileLocation.h +++ b/Source/cmSourceFileLocation.h @@ -34,6 +34,8 @@ public: cmSourceFileLocation(); cmSourceFileLocation(const cmSourceFileLocation& loc); + cmSourceFileLocation& operator=(cmSourceFileLocation const&) = delete; + /** * Return whether the given source file location could refers to the * same source file as this location given the level of ambiguity in @@ -78,14 +80,19 @@ public: const std::string& GetName() const { return this->Name; } /** + * Get the full file path composed of GetDirectory() and GetName(). + */ + std::string GetFullPath() const; + + /** * Get the cmMakefile instance for which the source file was created. */ cmMakefile const* GetMakefile() const { return this->Makefile; } private: - cmMakefile const* const Makefile; - bool AmbiguousDirectory; - bool AmbiguousExtension; + cmMakefile const* const Makefile = nullptr; + bool AmbiguousDirectory = true; + bool AmbiguousExtension = true; std::string Directory; std::string Name; @@ -94,8 +101,6 @@ private: // Update the location with additional knowledge. void Update(cmSourceFileLocation const& loc); void UpdateExtension(const std::string& name); - - cmSourceFileLocation& operator=(const cmSourceFileLocation& loc) = delete; }; #endif diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx index 12ef62bc2..7e1e836a0 100644 --- a/Source/cmSourceGroup.cxx +++ b/Source/cmSourceGroup.cxx @@ -2,15 +2,17 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSourceGroup.h" +#include <utility> + class cmSourceGroupInternals { public: std::vector<cmSourceGroup> GroupChildren; }; -cmSourceGroup::cmSourceGroup(const std::string& name, const char* regex, +cmSourceGroup::cmSourceGroup(std::string name, const char* regex, const char* parentName) - : Name(name) + : Name(std::move(name)) { this->Internal = new cmSourceGroupInternals; this->SetGroupRegex(regex); diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h index b39f8ddb1..7c6549446 100644 --- a/Source/cmSourceGroup.h +++ b/Source/cmSourceGroup.h @@ -26,7 +26,7 @@ class cmSourceGroupInternals; class cmSourceGroup { public: - cmSourceGroup(const std::string& name, const char* regex, + cmSourceGroup(std::string name, const char* regex, const char* parentName = nullptr); cmSourceGroup(cmSourceGroup const& r); ~cmSourceGroup(); diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx index c3df313e1..34ded3890 100644 --- a/Source/cmSourceGroupCommand.cxx +++ b/Source/cmSourceGroupCommand.cxx @@ -105,7 +105,7 @@ bool addFilesToItsSourceGroups(const std::string& root, tokenizedPath.pop_back(); if (tokenizedPath.empty()) { - tokenizedPath.push_back(""); + tokenizedPath.emplace_back(); } sg = makefile.GetOrCreateSourceGroup(tokenizedPath); @@ -254,16 +254,12 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args, bool cmSourceGroupCommand::checkArgumentsPreconditions( const ParsedArguments& parsedArguments, std::string& errorMsg) const { - if (!checkSingleParameterArgumentPreconditions(kPrefixOptionName, - parsedArguments, errorMsg) || - !checkSingleParameterArgumentPreconditions(kTreeOptionName, - parsedArguments, errorMsg) || - !checkSingleParameterArgumentPreconditions(kRegexOptionName, - parsedArguments, errorMsg)) { - return false; - } - - return true; + return checkSingleParameterArgumentPreconditions( + kPrefixOptionName, parsedArguments, errorMsg) && + checkSingleParameterArgumentPreconditions(kTreeOptionName, parsedArguments, + errorMsg) && + checkSingleParameterArgumentPreconditions(kRegexOptionName, + parsedArguments, errorMsg); } bool cmSourceGroupCommand::processTree(ParsedArguments& parsedArguments, @@ -286,12 +282,8 @@ bool cmSourceGroupCommand::processTree(ParsedArguments& parsedArguments, std::set<std::string> sourceGroupPaths = getSourceGroupFilesPaths(root, filesVector); - if (!addFilesToItsSourceGroups(root, sourceGroupPaths, prefix, - *(this->Makefile), errorMsg)) { - return false; - } - - return true; + return addFilesToItsSourceGroups(root, sourceGroupPaths, prefix, + *(this->Makefile), errorMsg); } bool cmSourceGroupCommand::checkSingleParameterArgumentPreconditions( diff --git a/Source/cmState.cxx b/Source/cmState.cxx index a2008a0d1..a08e9b8ba 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -22,14 +22,6 @@ #include "cmake.h" cmState::cmState() - : IsInTryCompile(false) - , IsGeneratorMultiConfig(false) - , WindowsShell(false) - , WindowsVSIDE(false) - , WatcomWMake(false) - , MinGWMake(false) - , NMake(false) - , MSYSShell(false) { this->CacheManager = new cmCacheManager; this->GlobVerificationManager = new cmGlobVerificationManager; @@ -83,14 +75,23 @@ const char* cmState::CacheEntryTypeToString(cmStateEnums::CacheEntryType type) cmStateEnums::CacheEntryType cmState::StringToCacheEntryType(const char* s) { + cmStateEnums::CacheEntryType type = cmStateEnums::STRING; + StringToCacheEntryType(s, type); + return type; +} + +bool cmState::StringToCacheEntryType(const char* s, + cmStateEnums::CacheEntryType& type) +{ int i = 0; while (cmCacheEntryTypes[i]) { if (strcmp(s, cmCacheEntryTypes[i]) == 0) { - return static_cast<cmStateEnums::CacheEntryType>(i); + type = static_cast<cmStateEnums::CacheEntryType>(i); + return true; } ++i; } - return cmStateEnums::STRING; + return false; } bool cmState::IsCacheEntryType(std::string const& key) @@ -547,13 +548,16 @@ const char* cmState::GetGlobalProperty(const std::string& prop) std::string langs; langs = cmJoin(this->EnabledLanguages, ";"); this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str()); + } else if (prop == "CMAKE_ROLE") { + std::string mode = this->GetModeString(); + this->SetGlobalProperty("CMAKE_ROLE", mode.c_str()); } #define STRING_LIST_ELEMENT(F) ";" #F if (prop == "CMAKE_C_KNOWN_FEATURES") { - return FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT) + 1; + return &FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT)[1]; } if (prop == "CMAKE_CXX_KNOWN_FEATURES") { - return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1; + return &FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT)[1]; } #undef STRING_LIST_ELEMENT return this->GlobalProperties.GetPropertyValue(prop); @@ -601,6 +605,16 @@ bool cmState::UseWindowsVSIDE() const return this->WindowsVSIDE; } +void cmState::SetGhsMultiIDE(bool ghsMultiIDE) +{ + this->GhsMultiIDE = ghsMultiIDE; +} + +bool cmState::UseGhsMultiIDE() const +{ + return this->GhsMultiIDE; +} + void cmState::SetWatcomWMake(bool watcomWMake) { this->WatcomWMake = watcomWMake; @@ -651,6 +665,40 @@ unsigned int cmState::GetCacheMinorVersion() const return this->CacheManager->GetCacheMinorVersion(); } +cmState::Mode cmState::GetMode() const +{ + return this->CurrentMode; +} + +std::string cmState::GetModeString() const +{ + return ModeToString(this->CurrentMode); +} + +void cmState::SetMode(cmState::Mode mode) +{ + this->CurrentMode = mode; +} + +std::string cmState::ModeToString(cmState::Mode mode) +{ + switch (mode) { + case Project: + return "PROJECT"; + case Script: + return "SCRIPT"; + case FindPackage: + return "FIND_PACKAGE"; + case CTest: + return "CTEST"; + case CPack: + return "CPACK"; + case Unknown: + return "UNKNOWN"; + } + return "UNKNOWN"; +} + std::string const& cmState::GetBinaryDirectory() const { return this->BinaryDirectory; @@ -867,8 +915,8 @@ static bool ParseEntryWithoutType(const std::string& entry, std::string& var, // if value is enclosed in single quotes ('foo') then remove them // it is used to enclose trailing space or tab - if (flag && value.size() >= 2 && value[0] == '\'' && - value[value.size() - 1] == '\'') { + if (flag && value.size() >= 2 && value.front() == '\'' && + value.back() == '\'') { value = value.substr(1, value.size() - 2); } @@ -900,8 +948,8 @@ bool cmState::ParseCacheEntry(const std::string& entry, std::string& var, // if value is enclosed in single quotes ('foo') then remove them // it is used to enclose trailing space or tab - if (flag && value.size() >= 2 && value[0] == '\'' && - value[value.size() - 1] == '\'') { + if (flag && value.size() >= 2 && value.front() == '\'' && + value.back() == '\'') { value = value.substr(1, value.size() - 2); } diff --git a/Source/cmState.h b/Source/cmState.h index 916985dbb..f755f8362 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -35,6 +35,16 @@ public: cmState(); ~cmState(); + enum Mode + { + Unknown, + Project, + Script, + FindPackage, + CTest, + CPack, + }; + static const char* GetTargetTypeName(cmStateEnums::TargetType targetType); cmStateSnapshot CreateBaseSnapshot(); @@ -55,6 +65,8 @@ public: cmStateSnapshot Pop(cmStateSnapshot const& originSnapshot); static cmStateEnums::CacheEntryType StringToCacheEntryType(const char*); + static bool StringToCacheEntryType(const char*, + cmStateEnums::CacheEntryType& type); static const char* CacheEntryTypeToString(cmStateEnums::CacheEntryType); static bool IsCacheEntryType(std::string const& key); @@ -154,6 +166,8 @@ public: bool UseWindowsShell() const; void SetWindowsVSIDE(bool windowsVSIDE); bool UseWindowsVSIDE() const; + void SetGhsMultiIDE(bool ghsMultiIDE); + bool UseGhsMultiIDE() const; void SetWatcomWMake(bool watcomWMake); bool UseWatcomWMake() const; void SetMinGWMake(bool minGWMake); @@ -166,6 +180,12 @@ public: unsigned int GetCacheMajorVersion() const; unsigned int GetCacheMinorVersion() const; + Mode GetMode() const; + std::string GetModeString() const; + void SetMode(Mode mode); + + static std::string ModeToString(Mode mode); + private: friend class cmake; void AddCacheEntry(const std::string& key, const char* value, @@ -202,14 +222,16 @@ private: std::string SourceDirectory; std::string BinaryDirectory; - bool IsInTryCompile; - bool IsGeneratorMultiConfig; - bool WindowsShell; - bool WindowsVSIDE; - bool WatcomWMake; - bool MinGWMake; - bool NMake; - bool MSYSShell; + bool IsInTryCompile = false; + bool IsGeneratorMultiConfig = false; + bool WindowsShell = false; + bool WindowsVSIDE = false; + bool GhsMultiIDE = false; + bool WatcomWMake = false; + bool MinGWMake = false; + bool NMake = false; + bool MSYSShell = false; + Mode CurrentMode = Unknown; }; #endif diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index f94e7146e..6752743a1 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -138,6 +138,32 @@ void cmStateDirectory::SetRelativePathTopBinary(const char* dir) this->DirectoryState->RelativePathTopBinary = dir; } +bool cmStateDirectory::ContainsBoth(std::string const& local_path, + std::string const& remote_path) const +{ + auto PathEqOrSubDir = [](std::string const& a, std::string const& b) { + return (cmSystemTools::ComparePath(a, b) || + cmSystemTools::IsSubDirectory(a, b)); + }; + + bool bothInBinary = PathEqOrSubDir(local_path, GetRelativePathTopBinary()) && + PathEqOrSubDir(remote_path, GetRelativePathTopBinary()); + + bool bothInSource = PathEqOrSubDir(local_path, GetRelativePathTopSource()) && + PathEqOrSubDir(remote_path, GetRelativePathTopSource()); + + return bothInBinary || bothInSource; +} + +std::string cmStateDirectory::ConvertToRelPathIfNotContained( + std::string const& local_path, std::string const& remote_path) const +{ + if (!this->ContainsBoth(local_path, remote_path)) { + return remote_path; + } + return cmSystemTools::ForceToRelativePath(local_path, remote_path); +} + cmStateDirectory::cmStateDirectory( cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator iter, const cmStateSnapshot& snapshot) diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index e5f4d05d1..69565940d 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -32,6 +32,12 @@ public: void SetRelativePathTopSource(const char* dir); void SetRelativePathTopBinary(const char* dir); + bool ContainsBoth(std::string const& local_path, + std::string const& remote_path) const; + + std::string ConvertToRelPathIfNotContained( + std::string const& local_path, std::string const& remote_path) const; + cmStringRange GetIncludeDirectoriesEntries() const; cmBacktraceRange GetIncludeDirectoriesEntryBacktraces() const; void AppendIncludeDirectoriesEntry(std::string const& vec, diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h index e76f2af37..ec0ed6c93 100644 --- a/Source/cmStatePrivate.h +++ b/Source/cmStatePrivate.h @@ -50,8 +50,7 @@ struct cmStateDetail::PolicyStackEntry : public cmPolicies::PolicyMap { typedef cmPolicies::PolicyMap derived; PolicyStackEntry(bool w = false) - : derived() - , Weak(w) + : Weak(w) { } PolicyStackEntry(derived const& d, bool w) diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index c2510f355..63bec710b 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -16,7 +16,6 @@ #include "cmStateDirectory.h" #include "cmStatePrivate.h" #include "cmVersion.h" -#include "cmake.h" #if !defined(_WIN32) # include <sys/utsname.h> @@ -28,7 +27,6 @@ cmStateSnapshot::cmStateSnapshot(cmState* state) : State(state) - , Position() { } @@ -66,6 +64,12 @@ bool cmStateSnapshot::IsValid() const : false; } +cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const +{ + return cmStateSnapshot(this->State, + this->Position->BuildSystemDirectory->DirectoryEnd); +} + cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const { cmStateSnapshot snapshot; @@ -343,8 +347,7 @@ void cmStateSnapshot::SetDefaultDefinitions() std::to_string(cmVersion::GetTweakVersion())); this->SetDefinition("CMAKE_VERSION", cmVersion::GetCMakeVersion()); - this->SetDefinition("CMAKE_FILES_DIRECTORY", - cmake::GetCMakeFilesDirectory()); + this->SetDefinition("CMAKE_FILES_DIRECTORY", "/CMakeFiles"); // Setup the default include file regular expression (match everything). this->Position->BuildSystemDirectory->Properties.SetProperty( diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h index 014c62e9d..c315f4851 100644 --- a/Source/cmStateSnapshot.h +++ b/Source/cmStateSnapshot.h @@ -37,6 +37,7 @@ public: std::vector<cmStateSnapshot> GetChildren(); bool IsValid() const; + cmStateSnapshot GetBuildsystemDirectory() const; cmStateSnapshot GetBuildsystemDirectoryParent() const; cmStateSnapshot GetCallStackParent() const; cmStateSnapshot GetCallStackBottom() const; diff --git a/Source/cmString.cxx b/Source/cmString.cxx new file mode 100644 index 000000000..2a0c125e6 --- /dev/null +++ b/Source/cmString.cxx @@ -0,0 +1,152 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#define _SCL_SECURE_NO_WARNINGS + +#include "cmString.hxx" + +#include <memory> +#include <ostream> +#include <stdexcept> +#include <string> +#include <type_traits> + +namespace cm { + +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 + // by other threads. + *this = String(data(), size()); +} + +bool String::is_stable() const +{ + return str_if_stable() != nullptr; +} + +void String::stabilize() +{ + if (is_stable()) { + return; + } + this->internally_mutate_to_stable_string(); +} + +std::string const* String::str_if_stable() const +{ + if (!data()) { + // We view no string. + // This is stable for the lifetime of our current value. + return &empty_string_; + } + + if (string_ && data() == string_->data() && size() == string_->size()) { + // We view an entire string. + // This is stable for the lifetime of our current value. + return string_.get(); + } + + return nullptr; +} + +std::string const& String::str() +{ + if (std::string const* s = str_if_stable()) { + return *s; + } + // Mutate to hold a std::string that is stable for the lifetime + // of our current value. + this->internally_mutate_to_stable_string(); + return *string_; +} + +const char* String::c_str() +{ + const char* c = data(); + if (c == nullptr) { + return c; + } + + // We always point into a null-terminated string so it is safe to + // access one past the end. If it is a null byte then we can use + // the pointer directly. + if (c[size()] == '\0') { + return c; + } + + // Mutate to hold a std::string so we can get a null terminator. + this->internally_mutate_to_stable_string(); + c = string_->c_str(); + return c; +} + +String& String::insert(size_type index, size_type count, char ch) +{ + std::string s; + s.reserve(size() + count); + s.assign(data(), size()); + s.insert(index, count, ch); + return *this = std::move(s); +} + +String& String::erase(size_type index, size_type count) +{ + if (index > size()) { + throw std::out_of_range("Index out of range in String::erase"); + } + size_type const rcount = std::min(count, size() - index); + size_type const rindex = index + rcount; + std::string s; + s.reserve(size() - rcount); + s.assign(data(), index); + s.append(data() + rindex, size() - rindex); + return *this = std::move(s); +} + +String String::substr(size_type pos, size_type count) const +{ + if (pos > size()) { + throw std::out_of_range("Index out of range in String::substr"); + } + return String(*this, pos, count); +} + +String::String(std::string&& s, Private) + : string_(std::make_shared<std::string>(std::move(s))) + , view_(string_->data(), string_->size()) +{ +} + +String::size_type String::copy(char* dest, size_type count, + size_type pos) const +{ + return view_.copy(dest, count, pos); +} + +std::ostream& operator<<(std::ostream& os, String const& s) +{ + return os.write(s.data(), s.size()); +} + +std::string& operator+=(std::string& self, String const& s) +{ + return self += s.view(); +} + +String IntoString<char*>::into_string(const char* s) +{ + if (!s) { + return String(); + } + return std::string(s); +} + +string_view AsStringView<String>::view(String const& s) +{ + return s.view(); +} + +} // namespace cm diff --git a/Source/cmString.hxx b/Source/cmString.hxx new file mode 100644 index 000000000..49bad7870 --- /dev/null +++ b/Source/cmString.hxx @@ -0,0 +1,815 @@ +/* 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 + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" + +#include <algorithm> +#include <functional> +#include <initializer_list> +#include <memory> +#include <ostream> +#include <string> +#include <type_traits> +#include <utility> + +namespace cm { + +class String; + +/** + * Trait to convert type T into a String. + * Implementations must derive from 'std::true_type' + * and define an 'into_string' member that accepts + * type T (by value or reference) and returns one of: + * + * - 'std::string' to construct an owned instance. + * - 'cm::string_view' to construct a borrowed or null instances. + * The buffer from which the view is borrowed must outlive + * all copies of the resulting String, e.g. static storage. + * - 'cm::String' for already-constructed instances. + */ +template <typename T> +struct IntoString : std::false_type +{ +}; + +template <typename T> +struct IntoString<T&> : IntoString<T> +{ +}; + +template <typename T> +struct IntoString<T const> : IntoString<T> +{ +}; + +template <typename T> +struct IntoString<T const*> : IntoString<T*> +{ +}; + +template <typename T, std::string::size_type N> +struct IntoString<T const[N]> : IntoString<T[N]> +{ +}; + +template <> +struct IntoString<char*> : std::true_type +{ + static String into_string(const char* s); +}; + +template <> +struct IntoString<std::nullptr_t> : std::true_type +{ + static string_view into_string(std::nullptr_t) { return string_view(); } +}; + +template <std::string::size_type N> +struct IntoString<char[N]> : std::true_type +{ + static std::string into_string(char const (&s)[N]) + { + return std::string(s, N - 1); + } +}; + +template <> +struct IntoString<std::string> : std::true_type +{ + static std::string into_string(std::string s) { return s; } +}; + +template <> +struct IntoString<string_view> : std::true_type +{ + static std::string into_string(string_view s) { return std::string(s); } +}; + +template <> +struct IntoString<static_string_view> : std::true_type +{ + static string_view into_string(static_string_view s) { return s; } +}; + +template <> +struct IntoString<char> : std::true_type +{ + static std::string into_string(char const& c) { return std::string(1, c); } +}; + +/** + * Trait to convert type T into a 'cm::string_view'. + * Implementations must derive from 'std::true_type' and + * define a 'view' member that accepts type T (by reference) + * and returns a 'cm::string_view'. + */ +template <typename T> +struct AsStringView : std::false_type +{ +}; + +template <typename T> +struct AsStringView<T&> : AsStringView<T> +{ +}; + +template <typename T> +struct AsStringView<T const> : AsStringView<T> +{ +}; + +template <typename T> +struct AsStringView<T const*> : AsStringView<T*> +{ +}; + +template <typename T, std::string::size_type N> +struct AsStringView<T const[N]> : AsStringView<T[N]> +{ +}; + +template <> +struct AsStringView<char*> : std::true_type +{ + static string_view view(const char* s) { return s; } +}; + +template <std::string::size_type N> +struct AsStringView<char[N]> : std::true_type +{ + static string_view view(char const (&s)[N]) { return string_view(s, N - 1); } +}; + +template <> +struct AsStringView<std::string> : std::true_type +{ + static string_view view(std::string const& s) { return s; } +}; + +template <> +struct AsStringView<char> : std::true_type +{ + static string_view view(const char& s) { return string_view(&s, 1); } +}; + +template <> +struct AsStringView<string_view> : std::true_type +{ + static string_view view(string_view const& s) { return s; } +}; + +template <> +struct AsStringView<static_string_view> : std::true_type +{ + static string_view view(static_string_view const& s) { return s; } +}; + +template <> +struct AsStringView<String> : std::true_type +{ + static string_view view(String const& s); +}; + +/** + * \class String + * + * A custom string type that holds a view of a string buffer + * and optionally shares ownership of the buffer. Instances + * may have one of the following states: + * + * - null: views and owns nothing. + * Conversion to 'bool' is 'false'. + * 'data()' and 'c_str()' return nullptr. + * 'size()' returns 0. + * 'str()' returns an empty string. + * + * - borrowed: views a string but does not own it. This is used + * to bind to static storage (e.g. string literals) or for + * temporary instances that do not outlive the borrowed buffer. + * Copies and substrings still borrow the original buffer. + * Mutation allocates a new internal string and converts to + * the 'owned' state. + * Conversion to 'bool' is 'true'. + * 'c_str()' may internally mutate to the 'owned' state. + * 'str()' internally mutates to the 'owned' state. + * + * - owned: views an immutable 'std::string' instance owned internally. + * Copies and substrings share ownership of the internal string. + * Mutation allocates a new internal string. + * Conversion to 'bool' is 'true'. + */ +class String +{ + enum class Private + { + }; + +public: + using traits_type = std::string::traits_type; + using value_type = string_view::value_type; + using pointer = string_view::pointer; + using const_pointer = string_view::const_pointer; + using reference = string_view::reference; + using const_reference = string_view::const_reference; + using const_iterator = string_view::const_iterator; + using iterator = string_view::const_iterator; + using const_reverse_iterator = string_view::const_reverse_iterator; + using reverse_iterator = string_view::const_reverse_iterator; + using difference_type = string_view::difference_type; + using size_type = string_view::size_type; + + static size_type const npos = string_view::npos; + + /** Construct a null string. */ + String() = default; + + /** Construct from any type implementing the IntoString trait. */ + template <typename T, + typename = typename std::enable_if<IntoString<T>::value>::type> + String(T&& s) + : String(IntoString<T>::into_string(std::forward<T>(s)), Private()) + { + } + + /** Construct via std::string initializer list constructor. */ + String(std::initializer_list<char> il) + : String(std::string(il)) + { + } + + /** Construct by copying the specified buffer. */ + String(const char* d, size_type s) + : String(std::string(d, s)) + { + } + + /** Construct by copying from input iterator range. */ + template <typename InputIterator> + String(InputIterator first, InputIterator last) + : String(std::string(first, last)) + { + } + + /** Construct a string with 'n' copies of character 'c'. */ + String(size_type n, char c) + : String(std::string(n, c)) + { + } + + /** Construct from a substring of another String instance. + This shares ownership of the other string's buffer + but views only a substring. */ + String(String const& s, size_type pos, size_type count = npos) + : string_(s.string_) + , view_(s.data() + pos, std::min(count, s.size() - pos)) + { + } + + /** Construct by moving from another String instance. + The other instance is left as a null string. */ + String(String&& s) noexcept + : string_(std::move(s.string_)) + , view_(s.view_) + { + s.view_ = string_view(); + } + + /** Construct by copying from another String instance. + This shares ownership of the other string's buffer. */ + String(String const&) noexcept = default; + + ~String() = default; + + /** Construct by borrowing an externally-owned buffer. The buffer + must outlive the returned instance and all copies of it. */ + static String borrow(string_view v) { return String(v, Private()); } + + /** Assign by moving from another String instance. + The other instance is left as a null string. */ + String& operator=(String&& s) noexcept + { + string_ = std::move(s.string_); + view_ = s.view_; + s.view_ = string_view(); + return *this; + } + + /** Assign by copying from another String instance. + This shares ownership of the other string's buffer. */ + String& operator=(String const&) noexcept = default; + + /** Assign from any type implementing the IntoString trait. */ + template <typename T> + typename // NOLINT(*) + std::enable_if<IntoString<T>::value, String&>::type + operator=(T&& s) + { + *this = String(std::forward<T>(s)); + return *this; + } + + /** Assign via std::string initializer list constructor. */ + String& operator=(std::initializer_list<char> il) + { + *this = String(il); + return *this; + } + + /** Return true if the instance is not a null string. */ + explicit operator bool() const noexcept { return data() != nullptr; } + + /** Return a view of the string. */ + string_view view() const noexcept { return view_; } + + /** Return true if the instance is an empty stringn or null string. */ + bool empty() const noexcept { return view_.empty(); } + + /** Return a pointer to the start of the string. */ + const char* data() const noexcept { return view_.data(); } + + /** Return the length of the string in bytes. */ + size_type size() const noexcept { return view_.size(); } + size_type length() const noexcept { return view_.length(); } + + /** Return the character at the given position. + No bounds checking is performed. */ + char operator[](size_type pos) const noexcept { return view_[pos]; } + + /** Return the character at the given position. + If the position is out of bounds, throws std::out_of_range. */ + char at(size_type pos) const { return view_.at(pos); } + + char front() const noexcept { return view_.front(); } + + char back() const noexcept { return view_.back(); } + + /** Return true if this instance is stable and otherwise false. + An instance is stable if it is in the 'null' state or if it is + an 'owned' state not produced by substring operations, or + after a call to 'stabilize()' or 'str()'. */ + bool is_stable() const; + + /** If 'is_stable()' does not return true, mutate so it does. */ + void stabilize(); + + /** Get a pointer to a normal std::string if 'is_stable()' returns + true and otherwise nullptr. The pointer is valid until this + instance is mutated or destroyed. */ + std::string const* str_if_stable() const; + + /** Get a refernce to a normal std::string. The reference + is valid until this instance is mutated or destroyed. */ + std::string const& str(); + + /** Get a pointer to a C-style null-terminated string + containing the same value as this instance. The pointer + is valid until this instance is mutated, destroyed, + or str() is called. */ + const char* c_str(); + + const_iterator begin() const noexcept { return view_.begin(); } + const_iterator end() const noexcept { return view_.end(); } + const_iterator cbegin() const noexcept { return begin(); } + const_iterator cend() const noexcept { return end(); } + + const_reverse_iterator rbegin() const noexcept { return view_.rbegin(); } + const_reverse_iterator rend() const noexcept { return view_.rend(); } + const_reverse_iterator crbegin() const noexcept { return rbegin(); } + const_reverse_iterator crend() const noexcept { return rend(); } + + /** Append to the string using any type that implements the + AsStringView trait. */ + template <typename T> + typename std::enable_if<AsStringView<T>::value, String&>::type operator+=( + T&& s) + { + string_view v = AsStringView<T>::view(std::forward<T>(s)); + std::string r; + r.reserve(size() + v.size()); + r.assign(data(), size()); + r.append(v.data(), v.size()); + return *this = std::move(r); + } + + /** Assign to an empty string. */ + void clear() { *this = ""_s; } + + /** Insert 'count' copies of 'ch' at position 'index'. */ + String& insert(size_type index, size_type count, char ch); + + /** Erase 'count' characters starting at position 'index'. */ + String& erase(size_type index = 0, size_type count = npos); + + void push_back(char ch) + { + std::string s; + s.reserve(size() + 1); + s.assign(data(), size()); + s.push_back(ch); + *this = std::move(s); + } + + void pop_back() { *this = String(*this, 0, size() - 1); } + + template <typename T> + typename std::enable_if<AsStringView<T>::value, String&>::type replace( + size_type pos, size_type count, T&& s) + { + const_iterator first = begin() + pos; + const_iterator last = first + count; + return replace(first, last, std::forward<T>(s)); + } + + template <typename InputIterator> + String& replace(const_iterator first, const_iterator last, + InputIterator first2, InputIterator last2) + { + std::string out; + out.append(view_.begin(), first); + out.append(first2, last2); + out.append(last, view_.end()); + return *this = std::move(out); + } + + template <typename T> + typename std::enable_if<AsStringView<T>::value, String&>::type replace( + const_iterator first, const_iterator last, T&& s) + { + string_view v = AsStringView<T>::view(std::forward<T>(s)); + std::string out; + out.reserve((first - view_.begin()) + v.size() + (view_.end() - last)); + out.append(view_.begin(), first); + out.append(v.data(), v.size()); + out.append(last, view_.end()); + return *this = std::move(out); + } + + template <typename T> + typename std::enable_if<AsStringView<T>::value, String&>::type replace( + size_type pos, size_type count, T&& s, size_type pos2, + size_type count2 = npos) + { + string_view v = AsStringView<T>::view(std::forward<T>(s)); + v = v.substr(pos2, count2); + return replace(pos, count, v); + } + + String& replace(size_type pos, size_type count, size_type count2, char ch) + { + const_iterator first = begin() + pos; + const_iterator last = first + count; + return replace(first, last, count2, ch); + } + + String& replace(const_iterator first, const_iterator last, size_type count2, + char ch) + { + std::string out; + out.reserve((first - view_.begin()) + count2 + (view_.end() - last)); + out.append(view_.begin(), first); + out.append(count2, ch); + out.append(last, view_.end()); + return *this = std::move(out); + } + + size_type copy(char* dest, size_type count, size_type pos = 0) const; + + void resize(size_type count) { resize(count, char()); } + + void resize(size_type count, char ch) + { + std::string s; + s.reserve(count); + if (count <= size()) { + s.assign(data(), count); + } else { + s.assign(data(), size()); + s.resize(count, ch); + } + *this = std::move(s); + } + + void swap(String& other) + { + std::swap(string_, other.string_); + std::swap(view_, other.view_); + } + + /** Return a substring starting at position 'pos' and + consisting of at most 'count' characters. */ + String substr(size_type pos = 0, size_type count = npos) const; + + template <typename T> + typename std::enable_if<AsStringView<T>::value, int>::type compare( + T&& s) const + { + return view_.compare(AsStringView<T>::view(std::forward<T>(s))); + } + + int compare(size_type pos1, size_type count1, string_view v) const + { + return view_.compare(pos1, count1, v); + } + + int compare(size_type pos1, size_type count1, string_view v, size_type pos2, + size_type count2) const + { + return view_.compare(pos1, count1, v, pos2, count2); + } + + int compare(size_type pos1, size_type count1, const char* s) const + { + return view_.compare(pos1, count1, s); + } + + int compare(size_type pos1, size_type count1, const char* s, + size_type count2) const + { + return view_.compare(pos1, count1, s, count2); + } + + template <typename T> + typename std::enable_if<AsStringView<T>::value, size_type>::type find( + T&& s, size_type pos = 0) const + { + string_view v = AsStringView<T>::view(std::forward<T>(s)); + return view_.find(v, pos); + } + + size_type find(const char* s, size_type pos, size_type count) const + { + return view_.find(s, pos, count); + } + + template <typename T> + typename std::enable_if<AsStringView<T>::value, size_type>::type rfind( + T&& s, size_type pos = npos) const + { + string_view v = AsStringView<T>::view(std::forward<T>(s)); + return view_.rfind(v, pos); + } + + size_type rfind(const char* s, size_type pos, size_type count) const + { + return view_.rfind(s, pos, count); + } + + template <typename T> + typename std::enable_if<AsStringView<T>::value, size_type>::type + find_first_of(T&& s, size_type pos = 0) const + { + string_view v = AsStringView<T>::view(std::forward<T>(s)); + return view_.find_first_of(v, pos); + } + + size_type find_first_of(const char* s, size_type pos, size_type count) const + { + return view_.find_first_of(s, pos, count); + } + + template <typename T> + typename std::enable_if<AsStringView<T>::value, size_type>::type + find_first_not_of(T&& s, size_type pos = 0) const + { + string_view v = AsStringView<T>::view(std::forward<T>(s)); + return view_.find_first_not_of(v, pos); + } + + size_type find_first_not_of(const char* s, size_type pos, + size_type count) const + { + return view_.find_first_not_of(s, pos, count); + } + + template <typename T> + typename std::enable_if<AsStringView<T>::value, size_type>::type + find_last_of(T&& s, size_type pos = npos) const + { + string_view v = AsStringView<T>::view(std::forward<T>(s)); + return view_.find_last_of(v, pos); + } + + size_type find_last_of(const char* s, size_type pos, size_type count) const + { + return view_.find_last_of(s, pos, count); + } + + template <typename T> + typename std::enable_if<AsStringView<T>::value, size_type>::type + find_last_not_of(T&& s, size_type pos = npos) const + { + string_view v = AsStringView<T>::view(std::forward<T>(s)); + return view_.find_last_not_of(v, pos); + } + + size_type find_last_not_of(const char* s, size_type pos, + size_type count) const + { + return view_.find_last_not_of(s, pos, count); + } + +private: + // Internal constructor to move from existing String. + String(String&& s, Private) noexcept + : String(std::move(s)) + { + } + + // Internal constructor for dynamically allocated string. + String(std::string&& s, Private); + + // Internal constructor for view of statically allocated string. + String(string_view v, Private) + : view_(v) + { + } + + void internally_mutate_to_stable_string(); + + std::shared_ptr<std::string const> string_; + string_view view_; +}; + +template <typename L, typename R> +typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, + bool>::type +operator==(L&& l, R&& r) +{ + return (AsStringView<L>::view(std::forward<L>(l)) == + AsStringView<R>::view(std::forward<R>(r))); +} + +template <typename L, typename R> +typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, + bool>::type +operator!=(L&& l, R&& r) +{ + return (AsStringView<L>::view(std::forward<L>(l)) != + AsStringView<R>::view(std::forward<R>(r))); +} + +template <typename L, typename R> +typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, + bool>::type +operator<(L&& l, R&& r) +{ + return (AsStringView<L>::view(std::forward<L>(l)) < + AsStringView<R>::view(std::forward<R>(r))); +} + +template <typename L, typename R> +typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, + bool>::type +operator<=(L&& l, R&& r) +{ + return (AsStringView<L>::view(std::forward<L>(l)) <= + AsStringView<R>::view(std::forward<R>(r))); +} + +template <typename L, typename R> +typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, + bool>::type +operator>(L&& l, R&& r) +{ + return (AsStringView<L>::view(std::forward<L>(l)) > + AsStringView<R>::view(std::forward<R>(r))); +} + +template <typename L, typename R> +typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, + bool>::type +operator>=(L&& l, R&& r) +{ + return (AsStringView<L>::view(std::forward<L>(l)) >= + AsStringView<R>::view(std::forward<R>(r))); +} + +std::ostream& operator<<(std::ostream& os, String const& s); +std::string& operator+=(std::string& self, String const& s); + +template <typename L, typename R> +struct StringOpPlus +{ + L l; + R r; +#if defined(__SUNPRO_CC) + StringOpPlus(L in_l, R in_r) + : l(in_l) + , r(in_r) + { + } +#endif + operator std::string() const; + std::string::size_type size() const { return l.size() + r.size(); } +}; + +template <typename T> +struct StringAdd +{ + static const bool value = AsStringView<T>::value; + typedef string_view temp_type; + template <typename S> + static temp_type temp(S&& s) + { + return AsStringView<T>::view(std::forward<S>(s)); + } +}; + +template <typename L, typename R> +struct StringAdd<StringOpPlus<L, R>> : std::true_type +{ + typedef StringOpPlus<L, R> const& temp_type; + static temp_type temp(temp_type s) { return s; } +}; + +template <typename L, typename R> +StringOpPlus<L, R>::operator std::string() const +{ + std::string s; + s.reserve(size()); + s += *this; + return s; +} + +template <typename L, typename R> +std::string& operator+=(std::string& s, StringOpPlus<L, R> const& a) +{ + s.reserve(s.size() + a.size()); + s += a.l; + s += a.r; + return s; +} + +template <typename L, typename R> +String& operator+=(String& s, StringOpPlus<L, R> const& a) +{ + std::string r; + r.reserve(s.size() + a.size()); + r.assign(s.data(), s.size()); + r += a.l; + r += a.r; + s = std::move(r); + return s; +} + +template <typename L, typename R> +std::ostream& operator<<(std::ostream& os, StringOpPlus<L, R> const& a) +{ + return os << a.l << a.r; +} + +template <typename L, typename R> +struct IntoString<StringOpPlus<L, R>> : std::true_type +{ + static std::string into_string(StringOpPlus<L, R> const& a) { return a; } +}; + +template <typename L, typename R> +typename std::enable_if<StringAdd<L>::value && StringAdd<R>::value, + StringOpPlus<typename StringAdd<L>::temp_type, + typename StringAdd<R>::temp_type>>::type +operator+(L&& l, R&& r) +{ + return { StringAdd<L>::temp(std::forward<L>(l)), + StringAdd<R>::temp(std::forward<R>(r)) }; +} + +template <typename LL, typename LR, typename R> +typename std::enable_if<AsStringView<R>::value, bool>::type operator==( + StringOpPlus<LL, LR> const& l, R&& r) +{ + return std::string(l) == AsStringView<R>::view(std::forward<R>(r)); +} + +template <typename L, typename RL, typename RR> +typename std::enable_if<AsStringView<L>::value, bool>::type operator==( + L&& l, StringOpPlus<RL, RR> const& r) +{ + return AsStringView<L>::view(std::forward<L>(l)) == std::string(r); +} + +} // namespace cm + +namespace std { + +template <> +struct hash<cm::String> +{ + typedef cm::String argument_type; + typedef size_t result_type; + + result_type operator()(argument_type const& s) const noexcept + { + result_type const h(std::hash<cm::string_view>{}(s.view())); + return h; + } +}; +} + +#endif diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 1605fd7bc..91d619020 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -156,7 +156,7 @@ bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args) return false; } std::string::size_type cc; - std::string const& outvar = args[args.size() - 1]; + std::string const& outvar = args.back(); std::string output; for (cc = 1; cc < args.size() - 1; cc++) { int ch = atoi(args[cc].c_str()); @@ -755,7 +755,7 @@ bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args) this->SetError("sub-command RANDOM invoked with bad length."); return false; } - const std::string& variableName = args[args.size() - 1]; + const std::string& variableName = args.back(); std::vector<char> result; @@ -765,8 +765,7 @@ bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args) } const char* alphaPtr = alphabet.c_str(); - int cc; - for (cc = 0; cc < length; cc++) { + for (int cc = 0; cc < length; cc++) { int idx = static_cast<int>(sizeofAlphabet * rand() / (RAND_MAX + 1.0)); result.push_back(*(alphaPtr + idx)); } diff --git a/Source/cmStringReplaceHelper.cxx b/Source/cmStringReplaceHelper.cxx index 69b7cedd6..4a6298782 100644 --- a/Source/cmStringReplaceHelper.cxx +++ b/Source/cmStringReplaceHelper.cxx @@ -5,13 +5,14 @@ #include "cmMakefile.h" #include <sstream> +#include <utility> cmStringReplaceHelper::cmStringReplaceHelper(const std::string& regex, - const std::string& replace_expr, + std::string replace_expr, cmMakefile* makefile) : RegExString(regex) , RegularExpression(regex) - , ReplaceExpression(replace_expr) + , ReplaceExpression(std::move(replace_expr)) , Makefile(makefile) { this->ParseReplaceExpression(); @@ -85,10 +86,12 @@ void cmStringReplaceHelper::ParseReplaceExpression() auto r = this->ReplaceExpression.find('\\', l); if (r == std::string::npos) { r = this->ReplaceExpression.length(); - this->Replacements.push_back(this->ReplaceExpression.substr(l, r - l)); + this->Replacements.emplace_back( + this->ReplaceExpression.substr(l, r - l)); } else { if (r - l > 0) { - this->Replacements.push_back(this->ReplaceExpression.substr(l, r - l)); + this->Replacements.emplace_back( + this->ReplaceExpression.substr(l, r - l)); } if (r == (this->ReplaceExpression.length() - 1)) { this->ValidReplaceExpression = false; @@ -97,11 +100,11 @@ void cmStringReplaceHelper::ParseReplaceExpression() } if ((this->ReplaceExpression[r + 1] >= '0') && (this->ReplaceExpression[r + 1] <= '9')) { - this->Replacements.push_back(this->ReplaceExpression[r + 1] - '0'); + this->Replacements.emplace_back(this->ReplaceExpression[r + 1] - '0'); } else if (this->ReplaceExpression[r + 1] == 'n') { - this->Replacements.push_back("\n"); + this->Replacements.emplace_back("\n"); } else if (this->ReplaceExpression[r + 1] == '\\') { - this->Replacements.push_back("\\"); + this->Replacements.emplace_back("\\"); } else { this->ValidReplaceExpression = false; std::ostringstream error; diff --git a/Source/cmStringReplaceHelper.h b/Source/cmStringReplaceHelper.h index 938325a31..b3e470416 100644 --- a/Source/cmStringReplaceHelper.h +++ b/Source/cmStringReplaceHelper.h @@ -6,6 +6,7 @@ #include "cmsys/RegularExpression.hxx" #include <string> +#include <utility> #include <vector> class cmMakefile; @@ -13,8 +14,7 @@ class cmMakefile; class cmStringReplaceHelper { public: - cmStringReplaceHelper(const std::string& regex, - const std::string& replace_expr, + cmStringReplaceHelper(const std::string& regex, std::string replace_expr, cmMakefile* makefile = nullptr); bool IsRegularExpressionValid() const @@ -39,17 +39,16 @@ private: , Value(s) { } - RegexReplacement(const std::string& s) + RegexReplacement(std::string s) : Number(-1) - , Value(s) + , Value(std::move(s)) { } RegexReplacement(int n) : Number(n) - , Value() { } - RegexReplacement() {} + RegexReplacement() = default; int Number; std::string Value; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 568ee828a..1d20e2f1a 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -49,6 +49,7 @@ #include <string.h> #include <time.h> #include <utility> +#include <vector> #if defined(_WIN32) # include <windows.h> @@ -75,6 +76,15 @@ # include <malloc.h> /* for malloc/free on QNX */ #endif +namespace { + +cmSystemTools::InterruptCallback s_InterruptCallback; +cmSystemTools::MessageCallback s_MessageCallback; +cmSystemTools::OutputCallback s_StderrCallback; +cmSystemTools::OutputCallback s_StdoutCallback; + +} // namespace + static bool cm_isspace(char c) { return ((c & 0x80) == 0) && isspace(c); @@ -137,7 +147,10 @@ public: CloseHandle(this->handle_); } } - operator bool() const { return this->handle_ != INVALID_HANDLE_VALUE; } + explicit operator bool() const + { + return this->handle_ != INVALID_HANDLE_VALUE; + } bool operator!() const { return this->handle_ == INVALID_HANDLE_VALUE; } operator HANDLE() const { return this->handle_; } @@ -157,15 +170,6 @@ bool cmSystemTools::s_FatalErrorOccured = false; bool cmSystemTools::s_DisableMessages = false; bool cmSystemTools::s_ForceUnixPaths = false; -cmSystemTools::MessageCallback cmSystemTools::s_MessageCallback; -cmSystemTools::OutputCallback cmSystemTools::s_StdoutCallback; -cmSystemTools::OutputCallback cmSystemTools::s_StderrCallback; -cmSystemTools::InterruptCallback cmSystemTools::s_InterruptCallback; -void* cmSystemTools::s_MessageCallbackClientData; -void* cmSystemTools::s_StdoutCallbackClientData; -void* cmSystemTools::s_StderrCallbackClientData; -void* cmSystemTools::s_InterruptCallbackClientData; - // replace replace with with as many times as it shows up in source. // write the result into source. #if defined(_WIN32) && !defined(__CYGWIN__) @@ -263,68 +267,59 @@ void cmSystemTools::Error(const char* m1, const char* m2, const char* m3, message += m4; } cmSystemTools::s_ErrorOccured = true; - cmSystemTools::Message(message.c_str(), "Error"); + cmSystemTools::Message(message, "Error"); +} + +void cmSystemTools::Error(const std::string& m) +{ + std::string message = "CMake Error: " + m; + cmSystemTools::s_ErrorOccured = true; + cmSystemTools::Message(message, "Error"); } -void cmSystemTools::SetInterruptCallback(InterruptCallback f, void* clientData) +void cmSystemTools::SetInterruptCallback(InterruptCallback f) { - s_InterruptCallback = f; - s_InterruptCallbackClientData = clientData; + s_InterruptCallback = std::move(f); } bool cmSystemTools::GetInterruptFlag() { if (s_InterruptCallback) { - return (*s_InterruptCallback)(s_InterruptCallbackClientData); + return s_InterruptCallback(); } return false; } -void cmSystemTools::SetMessageCallback(MessageCallback f, void* clientData) -{ - s_MessageCallback = f; - s_MessageCallbackClientData = clientData; -} - -void cmSystemTools::SetStdoutCallback(OutputCallback f, void* clientData) -{ - s_StdoutCallback = f; - s_StdoutCallbackClientData = clientData; -} - -void cmSystemTools::SetStderrCallback(OutputCallback f, void* clientData) +void cmSystemTools::SetMessageCallback(MessageCallback f) { - s_StderrCallback = f; - s_StderrCallbackClientData = clientData; + s_MessageCallback = std::move(f); } -void cmSystemTools::Stdout(const char* s) +void cmSystemTools::SetStdoutCallback(OutputCallback f) { - cmSystemTools::Stdout(s, strlen(s)); + s_StdoutCallback = std::move(f); } -void cmSystemTools::Stderr(const char* s) +void cmSystemTools::SetStderrCallback(OutputCallback f) { - cmSystemTools::Stderr(s, strlen(s)); + s_StderrCallback = std::move(f); } -void cmSystemTools::Stderr(const char* s, size_t length) +void cmSystemTools::Stderr(const std::string& s) { if (s_StderrCallback) { - (*s_StderrCallback)(s, length, s_StderrCallbackClientData); + s_StderrCallback(s); } else { - std::cerr.write(s, length); - std::cerr.flush(); + std::cerr << s << std::flush; } } -void cmSystemTools::Stdout(const char* s, size_t length) +void cmSystemTools::Stdout(const std::string& s) { if (s_StdoutCallback) { - (*s_StdoutCallback)(s, length, s_StdoutCallbackClientData); + s_StdoutCallback(s); } else { - std::cout.write(s, length); - std::cout.flush(); + std::cout << s << std::flush; } } @@ -334,8 +329,7 @@ void cmSystemTools::Message(const char* m1, const char* title) return; } if (s_MessageCallback) { - (*s_MessageCallback)(m1, title, s_DisableMessages, - s_MessageCallbackClientData); + s_MessageCallback(m1, title); return; } std::cerr << m1 << std::endl << std::flush; @@ -346,7 +340,7 @@ void cmSystemTools::ReportLastSystemError(const char* msg) std::string m = msg; m += ": System Error: "; m += Superclass::GetLastSystemError(); - cmSystemTools::Error(m.c_str()); + cmSystemTools::Error(m); } bool cmSystemTools::IsInternallyOn(const char* val) @@ -530,7 +524,7 @@ public: void Store(std::vector<std::string>& args) const { for (char** arg = this->ArgV; arg && *arg; ++arg) { - args.push_back(*arg); + args.emplace_back(*arg); } } }; @@ -557,7 +551,7 @@ std::vector<std::string> cmSystemTools::HandleResponseFile( error += cmSystemTools::GetLastSystemError(); error += "):\n "; error += arg.substr(1); - cmSystemTools::Error(error.c_str()); + cmSystemTools::Error(error); } else { std::string line; cmSystemTools::GetLineFromStream(responseFile, line); @@ -788,7 +782,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, if (pipe == cmsysProcess_Pipe_STDOUT) { if (outputflag != OUTPUT_NONE) { processOutput.DecodeText(data, length, strdata, 1); - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } if (captureStdOut) { tempStdOut.insert(tempStdOut.end(), data, data + length); @@ -796,7 +790,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, } else if (pipe == cmsysProcess_Pipe_STDERR) { if (outputflag != OUTPUT_NONE) { processOutput.DecodeText(data, length, strdata, 2); - cmSystemTools::Stderr(strdata.c_str(), strdata.size()); + cmSystemTools::Stderr(strdata); } if (captureStdErr) { tempStdErr.insert(tempStdErr.end(), data, data + length); @@ -807,11 +801,11 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, if (outputflag != OUTPUT_NONE) { processOutput.DecodeText(std::string(), strdata, 1); if (!strdata.empty()) { - cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + cmSystemTools::Stdout(strdata); } processOutput.DecodeText(std::string(), strdata, 2); if (!strdata.empty()) { - cmSystemTools::Stderr(strdata.c_str(), strdata.size()); + cmSystemTools::Stderr(strdata); } } } @@ -941,17 +935,12 @@ std::string cmSystemTools::FileExistsInParentDirectories(const char* fname, return ""; } -bool cmSystemTools::cmCopyFile(const char* source, const char* destination) +bool cmSystemTools::cmCopyFile(const std::string& source, + const std::string& destination) { return Superclass::CopyFileAlways(source, destination); } -bool cmSystemTools::CopyFileIfDifferent(const char* source, - const char* destination) -{ - return Superclass::CopyFileIfDifferent(source, destination); -} - #ifdef _WIN32 cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry() { @@ -1036,7 +1025,8 @@ void cmSystemTools::InitializeLibUV() #endif } -bool cmSystemTools::RenameFile(const char* oldname, const char* newname) +bool cmSystemTools::RenameFile(const std::string& oldname, + const std::string& newname) { #ifdef _WIN32 # ifndef INVALID_FILE_ATTRIBUTES @@ -1074,7 +1064,7 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname) return retry.Count > 0; #else /* On UNIX we have an OS-provided call to do this atomically. */ - return rename(oldname, newname) == 0; + return rename(oldname.c_str(), newname.c_str()) == 0; #endif } @@ -1301,7 +1291,7 @@ bool cmSystemTools::SimpleGlob(const std::string& glob, int type /* = 0 */) { files.clear(); - if (glob[glob.size() - 1] != '*') { + if (glob.back() != '*') { return false; } std::string path = cmSystemTools::GetFilenamePath(glob); @@ -1318,7 +1308,7 @@ bool cmSystemTools::SimpleGlob(const std::string& glob, if ((std::string(d.GetFile(i)) != ".") && (std::string(d.GetFile(i)) != "..")) { std::string fname = path; - if (path[path.size() - 1] != '/') { + if (path.back() != '/') { fname += "/"; } fname += d.GetFile(i); @@ -1340,13 +1330,11 @@ bool cmSystemTools::SimpleGlob(const std::string& glob, return res; } -cmSystemTools::FileFormat cmSystemTools::GetFileFormat(const char* cext) +cmSystemTools::FileFormat cmSystemTools::GetFileFormat(std::string const& ext) { - if (!cext || *cext == 0) { + if (ext.empty()) { return cmSystemTools::NO_FILE_FORMAT; } - // std::string ext = cmSystemTools::LowerCase(cext); - std::string ext = cext; if (ext == "c" || ext == ".c" || ext == "m" || ext == ".m") { return cmSystemTools::C_FILE_FORMAT; } @@ -1460,6 +1448,80 @@ std::string cmSystemTools::RelativePath(std::string const& local, return cmsys::SystemTools::RelativePath(local, remote); } +std::string cmSystemTools::ForceToRelativePath(std::string const& local_path, + std::string const& remote_path) +{ + // The paths should never be quoted. + assert(local_path.front() != '\"'); + assert(remote_path.front() != '\"'); + + // The local path should never have a trailing slash. + assert(local_path.empty() || local_path.back() != '/'); + + // If the path is already relative then just return the path. + if (!cmSystemTools::FileIsFullPath(remote_path)) { + return remote_path; + } + + // Identify the longest shared path component between the remote + // path and the local path. + std::vector<std::string> local; + cmSystemTools::SplitPath(local_path, local); + std::vector<std::string> remote; + cmSystemTools::SplitPath(remote_path, remote); + unsigned int common = 0; + while (common < remote.size() && common < local.size() && + cmSystemTools::ComparePath(remote[common], local[common])) { + ++common; + } + + // If no part of the path is in common then return the full path. + if (common == 0) { + return remote_path; + } + + // If the entire path is in common then just return a ".". + if (common == remote.size() && common == local.size()) { + return "."; + } + + // If the entire path is in common except for a trailing slash then + // just return a "./". + if (common + 1 == remote.size() && remote[common].empty() && + common == local.size()) { + return "./"; + } + + // Construct the relative path. + std::string relative; + + // First add enough ../ to get up to the level of the shared portion + // of the path. Leave off the trailing slash. Note that the last + // component of local will never be empty because local should never + // have a trailing slash. + for (unsigned int i = common; i < local.size(); ++i) { + relative += ".."; + if (i < local.size() - 1) { + relative += "/"; + } + } + + // Now add the portion of the destination path that is not included + // in the shared portion of the path. Add a slash the first time + // only if there was already something in the path. If there was a + // trailing slash in the input then the last iteration of the loop + // will add a slash followed by an empty string which will preserve + // the trailing slash in the output. + + if (!relative.empty() && !remote.empty()) { + relative += "/"; + } + relative += cmJoin(cmMakeRange(remote).advance(common), "/"); + + // Finally return the path. + return relative; +} + std::string cmSystemTools::CollapseCombinedPath(std::string const& dir, std::string const& file) { @@ -1508,7 +1570,7 @@ std::vector<std::string> cmSystemTools::GetEnvironmentVariables() std::vector<std::string> env; int cc; for (cc = 0; environ[cc]; ++cc) { - env.push_back(environ[cc]); + env.emplace_back(environ[cc]); } return env; } @@ -1585,7 +1647,7 @@ bool cmSystemTools::CreateTar(const char* outFileName, e += outFileName; e += "\": "; e += cmSystemTools::GetLastSystemError(); - cmSystemTools::Error(e.c_str()); + cmSystemTools::Error(e); return false; } cmArchiveWrite::Compress compress = cmArchiveWrite::CompressNone; @@ -1618,7 +1680,7 @@ bool cmSystemTools::CreateTar(const char* outFileName, } } if (!a) { - cmSystemTools::Error(a.GetError().c_str()); + cmSystemTools::Error(a.GetError()); return false; } return true; @@ -1821,13 +1883,13 @@ bool extract_tar(const char* outFileName, bool verbose, bool extract) if (verbose) { if (extract) { cmSystemTools::Stdout("x "); - cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str()); + cmSystemTools::Stdout(cm_archive_entry_pathname(entry)); } else { list_item_verbose(stdout, entry); } cmSystemTools::Stdout("\n"); } else if (!extract) { - cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str()); + cmSystemTools::Stdout(cm_archive_entry_pathname(entry)); cmSystemTools::Stdout("\n"); } if (extract) { @@ -2985,7 +3047,7 @@ std::vector<std::string> cmSystemTools::tokenize(const std::string& str, } while (tokend != std::string::npos); if (tokens.empty()) { - tokens.push_back(""); + tokens.emplace_back(); } return tokens; } @@ -3006,8 +3068,38 @@ bool cmSystemTools::StringToULong(const char* str, unsigned long* value) return (*endp == '\0') && (endp != str) && (errno == 0); } +std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes) +{ + std::string out; + for (char c : in) { + char hexCh[4] = { 0, 0, 0, 0 }; + hexCh[0] = c; + switch (c) { + case '+': + case '?': + case '\\': + case '&': + case ' ': + case '=': + case '%': + sprintf(hexCh, "%%%02X", static_cast<int>(c)); + break; + case '/': + if (escapeSlashes) { + strcpy(hexCh, "%2F"); + } + break; + default: + break; + } + out.append(hexCh); + } + return out; +} + bool cmSystemTools::CreateSymlink(const std::string& origName, - const std::string& newName) + const std::string& newName, + std::string* errorMessage) { uv_fs_t req; int flags = 0; @@ -3021,7 +3113,32 @@ bool cmSystemTools::CreateSymlink(const std::string& origName, if (err) { std::string e = "failed to create symbolic link '" + newName + "': " + uv_strerror(err); - cmSystemTools::Error(e.c_str()); + if (errorMessage) { + *errorMessage = std::move(e); + } else { + cmSystemTools::Error(e); + } + return false; + } + + return true; +} + +bool cmSystemTools::CreateLink(const std::string& origName, + const std::string& newName, + std::string* errorMessage) +{ + uv_fs_t req; + int err = + uv_fs_link(nullptr, &req, origName.c_str(), newName.c_str(), nullptr); + if (err) { + std::string e = + "failed to create link '" + newName + "': " + uv_strerror(err); + if (errorMessage) { + *errorMessage = std::move(e); + } else { + cmSystemTools::Error(e); + } return false; } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 98300eb33..0f92fe257 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -10,6 +10,7 @@ #include "cmProcessOutput.h" #include "cmsys/Process.h" #include "cmsys/SystemTools.hxx" // IWYU pragma: export +#include <functional> #include <stddef.h> #include <string> #include <vector> @@ -55,42 +56,42 @@ public: */ static std::string TrimWhitespace(const std::string& s); - typedef void (*MessageCallback)(const char*, const char*, bool&, void*); + using MessageCallback = std::function<void(const char*, const char*)>; /** * Set the function used by GUIs to display error messages * Function gets passed: message as a const char*, - * title as a const char*, and a reference to bool that when - * set to false, will disable further messages (cancel). + * title as a const char*. */ - static void SetMessageCallback(MessageCallback f, - void* clientData = nullptr); + static void SetMessageCallback(MessageCallback f); /** * Display an error message. */ static void Error(const char* m, const char* m2 = nullptr, const char* m3 = nullptr, const char* m4 = nullptr); + static void Error(const std::string& m); /** * Display a message. */ static void Message(const char* m, const char* title = nullptr); + static void Message(const std::string& m, const char* title = nullptr) + { + Message(m.c_str(), title); + } - typedef void (*OutputCallback)(const char*, size_t length, void*); + using OutputCallback = std::function<void(std::string const&)>; ///! Send a string to stdout - static void Stdout(const char* s); - static void Stdout(const char* s, size_t length); - static void SetStdoutCallback(OutputCallback, void* clientData = nullptr); + static void Stdout(const std::string& s); + static void SetStdoutCallback(OutputCallback f); ///! Send a string to stderr - static void Stderr(const char* s); - static void Stderr(const char* s, size_t length); - static void SetStderrCallback(OutputCallback, void* clientData = nullptr); + static void Stderr(const std::string& s); + static void SetStderrCallback(OutputCallback f); - typedef bool (*InterruptCallback)(void*); - static void SetInterruptCallback(InterruptCallback f, - void* clientData = nullptr); + using InterruptCallback = std::function<bool()>; + static void SetInterruptCallback(InterruptCallback f); static bool GetInterruptFlag(); ///! Return true if there was an error at any point. @@ -176,12 +177,13 @@ public: std::vector<std::string>& files, int type = 0); ///! Copy a file. - static bool cmCopyFile(const char* source, const char* destination); - static bool CopyFileIfDifferent(const char* source, const char* destination); + static bool cmCopyFile(const std::string& source, + const std::string& destination); /** Rename a file or directory within a single disk volume (atomic if possible). */ - static bool RenameFile(const char* oldname, const char* newname); + static bool RenameFile(const std::string& oldname, + const std::string& newname); ///! Compute the hash of a file static std::string ComputeFileHash(const std::string& source, @@ -332,7 +334,7 @@ public: /** * Determine the file type based on the extension */ - static FileFormat GetFileFormat(const char* ext); + static FileFormat GetFileFormat(std::string const& ext); /** Windows if this is true, the CreateProcess in RunCommand will * not show new console windows when running programs. @@ -375,6 +377,14 @@ public: static std::string RelativePath(std::string const& local, std::string const& remote); + /** + * Convert the given remote path to a relative path with respect to + * the given local path. Both paths must use forward slashes and not + * already be escaped or quoted. + */ + static std::string ForceToRelativePath(std::string const& local_path, + std::string const& remote_path); + /** Joins two paths while collapsing x/../ parts * For example CollapseCombinedPath("a/b/c", "../../d") results in "a/d" */ @@ -398,11 +408,13 @@ public: original environment. */ class SaveRestoreEnvironment { - CM_DISABLE_COPY(SaveRestoreEnvironment) public: SaveRestoreEnvironment(); ~SaveRestoreEnvironment(); + SaveRestoreEnvironment(SaveRestoreEnvironment const&) = delete; + SaveRestoreEnvironment& operator=(SaveRestoreEnvironment const&) = delete; + private: std::vector<std::string> Env; }; @@ -495,6 +507,10 @@ public: static bool StringToLong(const char* str, long* value); static bool StringToULong(const char* str, unsigned long* value); + /** Encode a string as a URL. */ + static std::string EncodeURL(std::string const& in, + bool escapeSlashes = true); + #ifdef _WIN32 struct WindowsFileRetry { @@ -516,7 +532,14 @@ public: /** Create a symbolic link if the platform supports it. Returns whether creation succeeded. */ static bool CreateSymlink(const std::string& origName, - const std::string& newName); + const std::string& newName, + std::string* errorMessage = nullptr); + + /** Create a hard link if the platform supports it. Returns whether + creation succeeded. */ + static bool CreateLink(const std::string& origName, + const std::string& newName, + std::string* errorMessage = nullptr); private: static bool s_ForceUnixPaths; @@ -525,14 +548,6 @@ private: static bool s_FatalErrorOccured; static bool s_DisableMessages; static bool s_DisableRunCommandOutput; - static MessageCallback s_MessageCallback; - static OutputCallback s_StdoutCallback; - static OutputCallback s_StderrCallback; - static InterruptCallback s_InterruptCallback; - static void* s_MessageCallbackClientData; - static void* s_StdoutCallbackClientData; - static void* s_StderrCallbackClientData; - static void* s_InterruptCallbackClientData; }; #endif diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index f0d6519bb..93cdd46ce 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -6,7 +6,6 @@ #include <algorithm> #include <assert.h> #include <iterator> -#include <map> #include <set> #include <sstream> #include <string.h> @@ -18,8 +17,8 @@ #include "cmGlobalGenerator.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmMessenger.h" -#include "cmOutputConverter.h" #include "cmProperty.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" @@ -87,7 +86,7 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>( cmSystemTools::ExpandListArgument(entry, files); for (std::string const& file : files) { if (cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") && - file[file.size() - 1] == '>') { + file.back() == '>') { std::string objLibName = file.substr(17, file.size() - 18); if (cmGeneratorExpression::Find(objLibName) != std::string::npos) { @@ -100,7 +99,7 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>( bool addContent = false; bool noMessage = true; std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (context.GetBottom().GetPolicy(cmPolicies::CMP0051)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n"; @@ -218,6 +217,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("ANDROID_ASSETS_DIRECTORIES", nullptr); this->SetPropertyDefault("ANDROID_ANT_ADDITIONAL_OPTIONS", nullptr); this->SetPropertyDefault("BUILD_RPATH", nullptr); + this->SetPropertyDefault("BUILD_RPATH_USE_ORIGIN", nullptr); this->SetPropertyDefault("INSTALL_NAME_DIR", nullptr); this->SetPropertyDefault("INSTALL_RPATH", ""); this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF"); @@ -238,6 +238,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("AUTOMOC", nullptr); this->SetPropertyDefault("AUTOUIC", nullptr); this->SetPropertyDefault("AUTORCC", nullptr); + this->SetPropertyDefault("AUTOGEN_ORIGIN_DEPENDS", nullptr); this->SetPropertyDefault("AUTOGEN_PARALLEL", nullptr); this->SetPropertyDefault("AUTOMOC_COMPILER_PREDEFINES", nullptr); this->SetPropertyDefault("AUTOMOC_DEPEND_FILTERS", nullptr); @@ -486,24 +487,10 @@ cmGlobalGenerator* cmTarget::GetGlobalGenerator() const return this->GetMakefile()->GetGlobalGenerator(); } -void cmTarget::AddUtility(const std::string& u, cmMakefile* makefile) +void cmTarget::AddUtility(std::string const& u, cmMakefile* mf) { - if (this->Utilities.insert(u).second && makefile) { - this->UtilityBacktraces.insert( - std::make_pair(u, makefile->GetBacktrace())); - } -} - -cmListFileBacktrace const* cmTarget::GetUtilityBacktrace( - const std::string& u) const -{ - std::map<std::string, cmListFileBacktrace>::const_iterator i = - this->UtilityBacktraces.find(u); - if (i == this->UtilityBacktraces.end()) { - return nullptr; - } - - return &i->second; + BT<std::string> util(u, mf ? mf->GetBacktrace() : cmListFileBacktrace()); + this->Utilities.insert(util); } cmListFileBacktrace const& cmTarget::GetBacktrace() const @@ -583,7 +570,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s) if (src != s) { std::ostringstream e; bool noMessage = false; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0049)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0049) << "\n"; @@ -594,7 +581,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s) case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (!noMessage) { e << "Legacy variable expansion in source file \"" << s @@ -602,7 +589,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s) << "\". This behavior will be removed in a " "future version of CMake."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return ""; } } @@ -674,7 +661,7 @@ public: } }; -cmSourceFile* cmTarget::AddSource(const std::string& src) +cmSourceFile* cmTarget::AddSource(const std::string& src, bool before) { cmSourceFileLocation sfl(this->Makefile, src, cmSourceFileLocationKind::Known); @@ -683,8 +670,14 @@ cmSourceFile* cmTarget::AddSource(const std::string& src) TargetPropertyEntryFinder(sfl)) == this->Internal->SourceEntries.end()) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->Internal->SourceEntries.push_back(src); - this->Internal->SourceBacktraces.push_back(lfbt); + this->Internal->SourceEntries.insert( + before ? this->Internal->SourceEntries.begin() + : this->Internal->SourceEntries.end(), + src); + this->Internal->SourceBacktraces.insert( + before ? this->Internal->SourceBacktraces.begin() + : this->Internal->SourceBacktraces.end(), + lfbt); } if (cmGeneratorExpression::Find(src) != std::string::npos) { return nullptr; @@ -743,7 +736,7 @@ bool cmTarget::PushTLLCommandTrace(TLLSignature signature, } } if (this->TLLCommands.empty() || this->TLLCommands.back().second != lfc) { - this->TLLCommands.push_back(std::make_pair(signature, lfc)); + this->TLLCommands.emplace_back(signature, lfc); } return ret; } @@ -753,11 +746,12 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const const char* sigString = (sig == cmTarget::KeywordTLLSignature ? "keyword" : "plain"); s << "The uses of the " << sigString << " signature are here:\n"; - cmOutputConverter converter(this->GetMakefile()->GetStateSnapshot()); + cmStateDirectory cmDir = + this->GetMakefile()->GetStateSnapshot().GetDirectory(); for (auto const& cmd : this->TLLCommands) { if (cmd.first == sig) { cmListFileContext lfc = cmd.second; - lfc.FilePath = converter.ConvertToRelativePath( + lfc.FilePath = cmDir.ConvertToRelPathIfNotContained( this->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath); s << " * " << lfc << std::endl; } @@ -946,40 +940,40 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) if (prop == propMANUALLY_ADDED_DEPENDENCIES) { std::ostringstream e; e << "MANUALLY_ADDED_DEPENDENCIES property is read-only\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == propNAME) { std::ostringstream e; e << "NAME property is read-only\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == propTYPE) { std::ostringstream e; e << "TYPE property is read-only\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == propEXPORT_NAME && this->IsImported()) { std::ostringstream e; e << "EXPORT_NAME property can't be set on imported targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == propSOURCES && this->IsImported()) { std::ostringstream e; e << "SOURCES property can't be set on imported targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == propIMPORTED_GLOBAL && !this->IsImported()) { std::ostringstream e; e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } @@ -987,7 +981,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->IncludeDirectoriesEntries.clear(); this->Internal->IncludeDirectoriesBacktraces.clear(); if (value) { - this->Internal->IncludeDirectoriesEntries.push_back(value); + this->Internal->IncludeDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt); } @@ -995,7 +989,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->CompileOptionsEntries.clear(); this->Internal->CompileOptionsBacktraces.clear(); if (value) { - this->Internal->CompileOptionsEntries.push_back(value); + this->Internal->CompileOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileOptionsBacktraces.push_back(lfbt); } @@ -1003,7 +997,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->CompileFeaturesEntries.clear(); this->Internal->CompileFeaturesBacktraces.clear(); if (value) { - this->Internal->CompileFeaturesEntries.push_back(value); + this->Internal->CompileFeaturesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileFeaturesBacktraces.push_back(lfbt); } @@ -1011,7 +1005,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->CompileDefinitionsEntries.clear(); this->Internal->CompileDefinitionsBacktraces.clear(); if (value) { - this->Internal->CompileDefinitionsEntries.push_back(value); + this->Internal->CompileDefinitionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileDefinitionsBacktraces.push_back(lfbt); } @@ -1019,7 +1013,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->LinkOptionsEntries.clear(); this->Internal->LinkOptionsBacktraces.clear(); if (value) { - this->Internal->LinkOptionsEntries.push_back(value); + this->Internal->LinkOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->LinkOptionsBacktraces.push_back(lfbt); } @@ -1027,7 +1021,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->LinkDirectoriesEntries.clear(); this->Internal->LinkDirectoriesBacktraces.clear(); if (value) { - this->Internal->LinkDirectoriesEntries.push_back(value); + this->Internal->LinkDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->LinkDirectoriesBacktraces.push_back(lfbt); } @@ -1036,7 +1030,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->LinkImplementationPropertyBacktraces.clear(); if (value) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->Internal->LinkImplementationPropertyEntries.push_back(value); + this->Internal->LinkImplementationPropertyEntries.emplace_back(value); this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt); } } else if (prop == propSOURCES) { @@ -1044,7 +1038,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->SourceBacktraces.clear(); if (value) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->Internal->SourceEntries.push_back(value); + this->Internal->SourceEntries.emplace_back(value); this->Internal->SourceBacktraces.push_back(lfbt); } } else if (prop == propIMPORTED_GLOBAL) { @@ -1052,7 +1046,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) std::ostringstream e; e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } /* no need to change anything if value does not change */ @@ -1069,7 +1063,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) e << "CUDA_PTX_COMPILATION property can only be applied to OBJECT " "targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } else { this->Properties.SetProperty(prop, value); @@ -1087,21 +1081,21 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, if (prop == "NAME") { std::ostringstream e; e << "NAME property is read-only\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == "EXPORT_NAME" && this->IsImported()) { std::ostringstream e; e << "EXPORT_NAME property can't be set on imported targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == "SOURCES" && this->IsImported()) { std::ostringstream e; e << "SOURCES property can't be set on imported targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == "IMPORTED_GLOBAL") { @@ -1109,57 +1103,57 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, e << "IMPORTED_GLOBAL property can't be appended, only set on imported " "targets (\"" << this->Name << "\")\n"; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } if (prop == "INCLUDE_DIRECTORIES") { if (value && *value) { - this->Internal->IncludeDirectoriesEntries.push_back(value); + this->Internal->IncludeDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt); } } else if (prop == "COMPILE_OPTIONS") { if (value && *value) { - this->Internal->CompileOptionsEntries.push_back(value); + this->Internal->CompileOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileOptionsBacktraces.push_back(lfbt); } } else if (prop == "COMPILE_FEATURES") { if (value && *value) { - this->Internal->CompileFeaturesEntries.push_back(value); + this->Internal->CompileFeaturesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileFeaturesBacktraces.push_back(lfbt); } } else if (prop == "COMPILE_DEFINITIONS") { if (value && *value) { - this->Internal->CompileDefinitionsEntries.push_back(value); + this->Internal->CompileDefinitionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileDefinitionsBacktraces.push_back(lfbt); } } else if (prop == "LINK_OPTIONS") { if (value && *value) { - this->Internal->LinkOptionsEntries.push_back(value); + this->Internal->LinkOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->LinkOptionsBacktraces.push_back(lfbt); } } else if (prop == "LINK_DIRECTORIES") { if (value && *value) { - this->Internal->LinkDirectoriesEntries.push_back(value); + this->Internal->LinkDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->LinkDirectoriesBacktraces.push_back(lfbt); } } else if (prop == "LINK_LIBRARIES") { if (value && *value) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->Internal->LinkImplementationPropertyEntries.push_back(value); + this->Internal->LinkImplementationPropertyEntries.emplace_back(value); this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt); } } else if (prop == "SOURCES") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->Internal->SourceEntries.push_back(value); + this->Internal->SourceEntries.emplace_back(value); this->Internal->SourceBacktraces.push_back(lfbt); } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, prop + " property may not be APPENDed."); } else { this->Properties.AppendProperty(prop, value, asString); @@ -1296,7 +1290,7 @@ static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop, << "the LINK_INTERFACE_LIBRARIES and LINK_INTERFACE_LIBRARIES_DEBUG " << "properties accordingly."; } - context->IssueMessage(cmake::FATAL_ERROR, e.str()); + context->IssueMessage(MessageType::FATAL_ERROR, e.str()); } static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, @@ -1318,7 +1312,7 @@ static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, "property may contain configuration-sensitive generator-expressions " "which may be used to specify per-configuration rules."; - context->IssueMessage(cmake::FATAL_ERROR, e.str()); + context->IssueMessage(MessageType::FATAL_ERROR, e.str()); } static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target, @@ -1332,7 +1326,7 @@ static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target, e << "Attempt to promote imported target \"" << target->GetName() << "\" to global scope (by setting IMPORTED_GLOBAL) " "which is not built in this directory."; - context->IssueMessage(cmake::FATAL_ERROR, e.str()); + context->IssueMessage(MessageType::FATAL_ERROR, e.str()); } } @@ -1696,21 +1690,21 @@ bool cmTarget::CheckImportedLibName(std::string const& prop, if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY || !this->IsImported()) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, prop + " property may be set only on imported INTERFACE library targets."); return false; } if (!value.empty()) { if (value[0] == '-') { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, prop + " property value\n " + value + "\nmay not start with '-'."); return false; } std::string::size_type bad = value.find_first_of(":/\\;"); if (bad != std::string::npos) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, prop + " property value\n " + value + "\nmay not contain '" + value.substr(bad, 1) + "'."); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 694de1c3c..24b37423e 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -6,7 +6,6 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> -#include <map> #include <set> #include <string> #include <unordered_map> @@ -124,7 +123,7 @@ public: void AddSources(std::vector<std::string> const& srcs); void AddTracedSources(std::vector<std::string> const& srcs); cmSourceFile* AddSourceCMP0049(const std::string& src); - cmSourceFile* AddSource(const std::string& src); + cmSourceFile* AddSource(const std::string& src, bool before = false); //* how we identify a library, by name and type typedef std::pair<std::string, cmTargetLinkLibraryType> LibraryID; @@ -190,10 +189,12 @@ public: * name as would be specified to the ADD_EXECUTABLE or UTILITY_SOURCE * commands. It is not a full path nor does it have an extension. */ - void AddUtility(const std::string& u, cmMakefile* makefile = nullptr); + void AddUtility(std::string const& u, cmMakefile* mf = nullptr); ///! Get the utilities used by this target - std::set<std::string> const& GetUtilities() const { return this->Utilities; } - cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const; + std::set<BT<std::string>> const& GetUtilities() const + { + return this->Utilities; + } ///! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); @@ -307,8 +308,7 @@ private: bool IsGeneratorProvided; cmPropertyMap Properties; std::set<std::string> SystemIncludeDirectories; - std::set<std::string> Utilities; - std::map<std::string, cmListFileBacktrace> UtilityBacktraces; + std::set<BT<std::string>> Utilities; cmPolicies::PolicyMap PolicyMap; std::string Name; std::string InstallPath; @@ -343,11 +343,4 @@ private: typedef std::unordered_map<std::string, cmTarget> cmTargets; -class cmTargetSet : public std::set<std::string> -{ -}; -class cmTargetManifest : public std::map<std::string, cmTargetSet> -{ -}; - #endif diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index 4e716dc1f..c4dc8383b 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -6,8 +6,8 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -24,7 +24,7 @@ void cmTargetCompileDefinitionsCommand::HandleMissingTarget( e << "Cannot specify compile definitions for target \"" << name << "\" " "which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetCompileDefinitionsCommand::Join( diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx index f58e40414..c9e394b1c 100644 --- a/Source/cmTargetCompileFeaturesCommand.cxx +++ b/Source/cmTargetCompileFeaturesCommand.cxx @@ -6,7 +6,7 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" -#include "cmake.h" +#include "cmMessageType.h" class cmExecutionStatus; class cmTarget; @@ -24,7 +24,7 @@ void cmTargetCompileFeaturesCommand::HandleMissingTarget( e << "Cannot specify compile features for target \"" << name << "\" " "which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetCompileFeaturesCommand::Join( diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index 4df3630bb..8b4763a8c 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -7,8 +7,8 @@ #include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -24,7 +24,7 @@ void cmTargetCompileOptionsCommand::HandleMissingTarget( std::ostringstream e; e << "Cannot specify compile options for target \"" << name << "\" which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetCompileOptionsCommand::Join( diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h index b698db601..5ea008523 100644 --- a/Source/cmTargetDepend.h +++ b/Source/cmTargetDepend.h @@ -19,6 +19,7 @@ class cmTargetDepend // mutable members to achieve a map with set syntax. mutable bool Link; mutable bool Util; + mutable cmListFileBacktrace Backtrace; public: cmTargetDepend(cmGeneratorTarget const* t) @@ -42,8 +43,13 @@ public: this->Link = true; } } + void SetBacktrace(cmListFileBacktrace const& bt) const + { + this->Backtrace = bt; + } bool IsLink() const { return this->Link; } bool IsUtil() const { return this->Util; } + cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; } }; /** Unordered set of (direct) dependencies of a target. */ diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index af142aa97..d6918c09b 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -8,9 +8,9 @@ #include "cmGeneratorExpression.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -27,7 +27,7 @@ void cmTargetIncludeDirectoriesCommand::HandleMissingTarget( std::ostringstream e; e << "Cannot specify include directories for target \"" << name << "\" which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetIncludeDirectoriesCommand::Join( diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx index bca3e45dd..269f7513e 100644 --- a/Source/cmTargetLinkDirectoriesCommand.cxx +++ b/Source/cmTargetLinkDirectoriesCommand.cxx @@ -8,9 +8,9 @@ #include "cmGeneratorExpression.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -26,7 +26,7 @@ void cmTargetLinkDirectoriesCommand::HandleMissingTarget( std::ostringstream e; e << "Cannot specify link directories for target \"" << name << "\" which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetLinkDirectoriesCommand::Join( diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index ded683147..5c7b95cb1 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -8,6 +8,7 @@ #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" @@ -51,7 +52,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( } } if (!this->Target) { - cmake::MessageType t = cmake::FATAL_ERROR; // fail by default + MessageType t = MessageType::FATAL_ERROR; // fail by default std::ostringstream e; e << "Cannot specify link libraries for target \"" << args[0] << "\" " << "which is not built by this project."; @@ -60,7 +61,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( if (args.size() < 2) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0016)) { case cmPolicies::WARN: - t = cmake::AUTHOR_WARNING; + t = MessageType::AUTHOR_WARNING; // Print the warning. e << "\n" << "CMake does not support this but it used to work accidentally " @@ -69,7 +70,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( << cmPolicies::GetPolicyWarning(cmPolicies::CMP0016); break; case cmPolicies::OLD: // OLD behavior does not warn. - t = cmake::MESSAGE; + t = MessageType::MESSAGE; break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: @@ -81,11 +82,11 @@ bool cmTargetLinkLibrariesCommand::InitialPass( } // Now actually print the message. switch (t) { - case cmake::AUTHOR_WARNING: - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + case MessageType::AUTHOR_WARNING: + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); break; - case cmake::FATAL_ERROR: - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + case MessageType::FATAL_ERROR: + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); break; default: @@ -98,7 +99,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( if (this->Target->GetType() == cmStateEnums::UTILITY) { std::ostringstream e; const char* modal = nullptr; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0039)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0039) << "\n"; @@ -109,13 +110,13 @@ bool cmTargetLinkLibrariesCommand::InitialPass( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: modal = "must"; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (modal) { e << "Utility target \"" << this->Target->GetName() << "\" " << modal << " not be used as the target of a target_link_libraries call."; this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -141,7 +142,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState = ProcessingPlainLinkInterface; if (i != 1) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The LINK_INTERFACE_LIBRARIES option must appear as the second " "argument, just after the target name."); return true; @@ -152,7 +153,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState != ProcessingKeywordPublicInterface && this->CurrentProcessingState != ProcessingKeywordLinkInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The INTERFACE, PUBLIC or PRIVATE option must appear as the second " "argument, just after the target name."); return true; @@ -163,7 +164,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState != ProcessingPlainPrivateInterface && this->CurrentProcessingState != ProcessingPlainPublicInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second " "argument, just after the target name."); return true; @@ -175,7 +176,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState != ProcessingKeywordPublicInterface && this->CurrentProcessingState != ProcessingKeywordLinkInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The INTERFACE, PUBLIC or PRIVATE option must appear as the second " "argument, just after the target name."); return true; @@ -186,7 +187,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState != ProcessingPlainPublicInterface && this->CurrentProcessingState != ProcessingPlainPrivateInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second " "argument, just after the target name."); return true; @@ -198,7 +199,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->CurrentProcessingState != ProcessingKeywordPublicInterface && this->CurrentProcessingState != ProcessingKeywordLinkInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The INTERFACE, PUBLIC or PRIVATE option must appear as the second " "argument, just after the target name."); return true; @@ -256,9 +257,9 @@ bool cmTargetLinkLibrariesCommand::InitialPass( // Make sure the last argument was not a library type specifier. if (haveLLT) { std::ostringstream e; - e << "The \"" << this->LinkLibraryTypeNames[llt] + e << "The \"" << cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[llt] << "\" argument must be followed by a library."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); } @@ -284,11 +285,13 @@ void cmTargetLinkLibrariesCommand::LinkLibraryTypeSpecifierWarning(int left, int right) { std::ostringstream w; - w << "Link library type specifier \"" << this->LinkLibraryTypeNames[left] - << "\" is followed by specifier \"" << this->LinkLibraryTypeNames[right] + w << "Link library type specifier \"" + << cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[left] + << "\" is followed by specifier \"" + << cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[right] << "\" instead of a library name. " << "The first specifier will be ignored."; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, @@ -297,7 +300,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && this->CurrentProcessingState != ProcessingKeywordLinkInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "INTERFACE library can only be used with the INTERFACE keyword of " "target_link_libraries"); return false; @@ -305,7 +308,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, if (this->Target->IsImported() && this->CurrentProcessingState != ProcessingKeywordLinkInterface) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "IMPORTED library can only be used with the INTERFACE keyword of " "target_link_libraries"); return false; @@ -323,7 +326,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, sig, this->Makefile->GetExecutionContext())) { std::ostringstream e; const char* modal = nullptr; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0023)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n"; @@ -334,7 +337,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: modal = "must"; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (modal) { @@ -353,7 +356,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, ? cmTarget::PlainTLLSignature : cmTarget::KeywordTLLSignature); this->Makefile->IssueMessage(messageType, e.str()); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { return false; } } @@ -406,7 +409,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, << this->Target->GetName() << "\" which is not built in this directory.\n" << "This is allowed only when policy CMP0079 is set to NEW."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } @@ -424,7 +427,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, << " may not be linked into another target. One may link only to " "INTERFACE, OBJECT, STATIC or SHARED libraries, or to executables " "with the ENABLE_EXPORTS property set."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } this->Target->AddLinkLibrary(*this->Makefile, lib, libRef, llt); @@ -440,7 +443,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, "which the target was created rather than in this calling " "directory."; /* clang-format on */ - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } // Handle (additional) case where the command was called with PRIVATE / @@ -449,11 +452,12 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, // STATIC library.) if (this->CurrentProcessingState == ProcessingKeywordPrivateInterface || this->CurrentProcessingState == ProcessingPlainPrivateInterface) { - if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY) { + if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY || + this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { std::string configLib = this->Target->GetDebugGeneratorExpressions(libRef, llt); - if (cmGeneratorExpression::IsValidTargetName(lib) || - cmGeneratorExpression::Find(lib) != std::string::npos) { + if (cmGeneratorExpression::IsValidTargetName(libRef) || + cmGeneratorExpression::Find(libRef) != std::string::npos) { configLib = "$<LINK_ONLY:" + configLib + ">"; } this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES", diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx index d6ed5ae6e..536648638 100644 --- a/Source/cmTargetLinkOptionsCommand.cxx +++ b/Source/cmTargetLinkOptionsCommand.cxx @@ -7,8 +7,8 @@ #include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -23,7 +23,7 @@ void cmTargetLinkOptionsCommand::HandleMissingTarget(const std::string& name) std::ostringstream e; e << "Cannot specify link options for target \"" << name << "\" which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetLinkOptionsCommand::Join( diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 9a8fd96f1..1b8ee812f 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -84,15 +84,6 @@ bool cmTargetPropCommandBase::ProcessContentArgs( this->SetError("called with invalid arguments"); return false; } - if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && - scope != "INTERFACE") { - this->SetError("may only set INTERFACE properties on INTERFACE targets"); - return false; - } - if (this->Target->IsImported() && scope != "INTERFACE") { - this->SetError("may only set INTERFACE properties on IMPORTED targets"); - return false; - } ++argIndex; @@ -101,10 +92,21 @@ bool cmTargetPropCommandBase::ProcessContentArgs( for (unsigned int i = argIndex; i < args.size(); ++i, ++argIndex) { if (args[i] == "PUBLIC" || args[i] == "PRIVATE" || args[i] == "INTERFACE") { - return this->PopulateTargetProperies(scope, content, prepend, system); + break; } content.push_back(args[i]); } + if (!content.empty()) { + if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && + scope != "INTERFACE") { + this->SetError("may only set INTERFACE properties on INTERFACE targets"); + return false; + } + if (this->Target->IsImported() && scope != "INTERFACE") { + this->SetError("may only set INTERFACE properties on IMPORTED targets"); + return false; + } + } return this->PopulateTargetProperies(scope, content, prepend, system); } @@ -112,6 +114,9 @@ bool cmTargetPropCommandBase::PopulateTargetProperies( const std::string& scope, const std::vector<std::string>& content, bool prepend, bool system) { + if (content.empty()) { + return true; + } if (scope == "PRIVATE" || scope == "PUBLIC") { if (!this->HandleDirectContent(this->Target, content, prepend, system)) { return false; diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index 06ce0b1e6..d2c3496ed 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -7,10 +7,10 @@ #include <sstream> #include <unordered_set> +#include "cmMessageType.h" #include "cmMessenger.h" #include "cmPolicies.h" #include "cmStateSnapshot.h" -#include "cmake.h" bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( std::string const& tgtName, cmMessenger* messenger, @@ -18,7 +18,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( { std::ostringstream e; const char* modal = nullptr; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; + MessageType messageType = MessageType::AUTHOR_WARNING; switch (context.GetBottom().GetPolicy(cmPolicies::CMP0026)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0026) << "\n"; @@ -29,7 +29,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: modal = "may"; - messageType = cmake::FATAL_ERROR; + messageType = MessageType::FATAL_ERROR; } if (modal) { @@ -41,7 +41,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( messenger->IssueMessage(messageType, e.str(), context); } - return messageType != cmake::FATAL_ERROR; + return messageType != MessageType::FATAL_ERROR; } bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( @@ -65,6 +65,7 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( builtIns.insert("EXPORT_NAME"); builtIns.insert("IMPORTED"); builtIns.insert("IMPORTED_GLOBAL"); + builtIns.insert("MANUALLY_ADDED_DEPENDENCIES"); builtIns.insert("NAME"); builtIns.insert("TYPE"); } @@ -100,7 +101,7 @@ bool cmTargetPropertyComputer::PassesWhitelist( e << "INTERFACE_LIBRARY targets may only have whitelisted properties. " "The property \"" << prop << "\" is not allowed."; - messenger->IssueMessage(cmake::FATAL_ERROR, e.str(), context); + messenger->IssueMessage(MessageType::FATAL_ERROR, e.str(), context); return false; } return true; diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index 7429053ea..11e288fe6 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -7,10 +7,10 @@ #include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmPolicies.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -34,7 +34,7 @@ void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name) e << "Cannot specify sources for target \"" << name << "\" " "which is not built by this project."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); } std::string cmTargetSourcesCommand::Join( @@ -99,7 +99,7 @@ std::vector<std::string> cmTargetSourcesCommand::ConvertToAbsoluteContent( case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076)); break; case cmPolicies::NEW: { @@ -117,7 +117,7 @@ std::vector<std::string> cmTargetSourcesCommand::ConvertToAbsoluteContent( e << "A private source from a directory other than that of target \"" << tgt->GetName() << "\" has a relative path."; } - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } return useAbsoluteContent ? absoluteContent : content; diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index 4d0cbaafc..7d45cf5e3 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -14,9 +14,7 @@ cmTest::cmTest(cmMakefile* mf) this->OldStyle = true; } -cmTest::~cmTest() -{ -} +cmTest::~cmTest() = default; cmListFileBacktrace const& cmTest::GetBacktrace() const { diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 796d2df64..5102613eb 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -7,6 +7,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmOutputConverter.h" #include "cmProperty.h" @@ -25,9 +26,7 @@ cmTestGenerator::cmTestGenerator( this->LG = nullptr; } -cmTestGenerator::~cmTestGenerator() -{ -} +cmTestGenerator::~cmTestGenerator() = default; void cmTestGenerator::Compute(cmLocalGenerator* lg) { @@ -89,7 +88,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, // Prepend with the emulator when cross compiling if required. const char* emulator = target->GetProperty("CROSSCOMPILING_EMULATOR"); - if (emulator != nullptr) { + if (emulator != nullptr && *emulator) { std::vector<std::string> emulatorWithArgs; cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs); std::string emulatorExe(emulatorWithArgs[0]); @@ -121,16 +120,15 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, // Output properties for the test. cmPropertyMap& pm = this->Test->GetProperties(); - if (!pm.empty()) { - os << indent << "set_tests_properties(" << this->Test->GetName() - << " PROPERTIES "; - for (auto const& i : pm) { - os << " " << i.first << " " - << cmOutputConverter::EscapeForCMake( - ge.Parse(i.second.GetValue())->Evaluate(this->LG, config)); - } - os << ")" << std::endl; + os << indent << "set_tests_properties(" << this->Test->GetName() + << " PROPERTIES "; + for (auto const& i : pm) { + os << " " << i.first << " " + << cmOutputConverter::EscapeForCMake( + ge.Parse(i.second.GetValue())->Evaluate(this->LG, config)); } + this->GenerateInternalProperties(os); + os << ")" << std::endl; } void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent) @@ -179,13 +177,37 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent) // Output properties for the test. cmPropertyMap& pm = this->Test->GetProperties(); - if (!pm.empty()) { - fout << indent << "set_tests_properties(" << this->Test->GetName() - << " PROPERTIES "; - for (auto const& i : pm) { - fout << " " << i.first << " " - << cmOutputConverter::EscapeForCMake(i.second.GetValue()); + fout << indent << "set_tests_properties(" << this->Test->GetName() + << " PROPERTIES "; + for (auto const& i : pm) { + fout << " " << i.first << " " + << cmOutputConverter::EscapeForCMake(i.second.GetValue()); + } + this->GenerateInternalProperties(fout); + fout << ")" << std::endl; +} + +void cmTestGenerator::GenerateInternalProperties(std::ostream& os) +{ + cmListFileBacktrace bt = this->Test->GetBacktrace(); + if (bt.Empty()) { + return; + } + + os << " " + << "_BACKTRACE_TRIPLES" + << " \""; + + bool prependTripleSeparator = false; + while (!bt.Empty()) { + const auto& entry = bt.Top(); + if (prependTripleSeparator) { + os << ";"; } - fout << ")" << std::endl; + os << entry.FilePath << ";" << entry.Line << ";" << entry.Name; + bt = bt.Pop(); + prependTripleSeparator = true; } + + os << "\""; } diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h index 73d05a3bb..8b9cf78a1 100644 --- a/Source/cmTestGenerator.h +++ b/Source/cmTestGenerator.h @@ -20,14 +20,15 @@ class cmTest; */ class cmTestGenerator : public cmScriptGenerator { - CM_DISABLE_COPY(cmTestGenerator) - public: cmTestGenerator(cmTest* test, std::vector<std::string> const& configurations = std::vector<std::string>()); ~cmTestGenerator() override; + cmTestGenerator(cmTestGenerator const&) = delete; + cmTestGenerator& operator=(cmTestGenerator const&) = delete; + void Compute(cmLocalGenerator* lg); /** Test if this generator installs the test for a given configuration. */ @@ -35,6 +36,9 @@ public: cmTest* GetTest() const; +private: + void GenerateInternalProperties(std::ostream& os); + protected: void GenerateScriptConfigs(std::ostream& os, Indent indent) override; void GenerateScriptActions(std::ostream& os, Indent indent) override; diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h index 8dd499a3e..d5fbdfd67 100644 --- a/Source/cmTimestamp.h +++ b/Source/cmTimestamp.h @@ -15,20 +15,18 @@ class cmTimestamp { public: - cmTimestamp() {} - std::string CurrentTime(const std::string& formatString, bool utcFlag); std::string FileModificationTime(const char* path, const std::string& formatString, bool utcFlag); -private: - time_t CreateUtcTimeTFromTm(struct tm& timeStruct) const; - std::string CreateTimestampFromTimeT(time_t timeT, std::string formatString, bool utcFlag) const; +private: + time_t CreateUtcTimeTFromTm(struct tm& timeStruct) const; + std::string AddTimestampComponent(char flag, struct tm& timeStruct, time_t timeT) const; }; diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx index 3ff84ceb5..05b3f0587 100644 --- a/Source/cmTryCompileCommand.cxx +++ b/Source/cmTryCompileCommand.cxx @@ -3,6 +3,7 @@ #include "cmTryCompileCommand.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmake.h" class cmExecutionStatus; @@ -18,7 +19,7 @@ bool cmTryCompileCommand::InitialPass(std::vector<std::string> const& argv, if (this->Makefile->GetCMakeInstance()->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The TRY_COMPILE() command is not supported in --find-package mode."); return false; } diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index 939613802..c57aabdc3 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -7,6 +7,7 @@ #include "cmDuration.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -25,7 +26,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, if (this->Makefile->GetCMakeInstance()->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) { this->Makefile->IssueMessage( - cmake::FATAL_ERROR, + MessageType::FATAL_ERROR, "The TRY_RUN() command is not supported in --find-package mode."); return false; } @@ -45,7 +46,8 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, if (argv[i] == "ARGS") { ++i; while (i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" && - argv[i] != "CMAKE_FLAGS" && argv[i] != "LINK_LIBRARIES") { + argv[i] != "CMAKE_FLAGS" && argv[i] != "LINK_OPTIONS" && + argv[i] != "LINK_LIBRARIES") { runArgs += " "; runArgs += argv[i]; ++i; @@ -99,11 +101,11 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, bool captureRunOutput = false; if (!this->OutputVariable.empty()) { captureRunOutput = true; - tryCompile.push_back("OUTPUT_VARIABLE"); + tryCompile.emplace_back("OUTPUT_VARIABLE"); tryCompile.push_back(this->OutputVariable); } if (!this->CompileOutputVariable.empty()) { - tryCompile.push_back("OUTPUT_VARIABLE"); + tryCompile.emplace_back("OUTPUT_VARIABLE"); tryCompile.push_back(this->CompileOutputVariable); } if (!this->RunOutputVariable.empty()) { @@ -119,7 +121,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, // now try running the command if it compiled if (!res) { if (this->OutputFile.empty()) { - cmSystemTools::Error(this->FindErrorMessage.c_str()); + cmSystemTools::Error(this->FindErrorMessage); } else { // "run" it and capture the output std::string runOutputContents; @@ -215,7 +217,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, // removed at the end of TRY_RUN and the user can run it manually // on the target platform. std::string copyDest = this->Makefile->GetHomeOutputDirectory(); - copyDest += cmake::GetCMakeFilesDirectory(); + copyDest += "/CMakeFiles"; copyDest += "/"; copyDest += cmSystemTools::GetFilenameWithoutExtension(this->OutputFile); copyDest += "-"; @@ -352,7 +354,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, errorMessage += " " + internalRunOutputName + " (advanced)\n"; } errorMessage += detailsString; - cmSystemTools::Error(errorMessage.c_str()); + cmSystemTools::Error(errorMessage); return; } diff --git a/Source/cmUVHandlePtr.h b/Source/cmUVHandlePtr.h index 2937e0d1a..992c429b1 100644 --- a/Source/cmUVHandlePtr.h +++ b/Source/cmUVHandlePtr.h @@ -3,7 +3,6 @@ #pragma once #include "cmConfigure.h" // IWYU pragma: keep -#include <algorithm> #include <cstddef> #include <cstdint> #include <memory> @@ -11,12 +10,22 @@ #include "cm_uv.h" -#define CM_PERFECT_FWD_CTOR(Class, FwdTo) \ - template <typename... Args> \ - Class(Args&&... args) \ - : FwdTo(std::forward<Args>(args)...) \ - { \ - } +#if defined(__SUNPRO_CC) + +# include <utility> + +# define CM_INHERIT_CTOR(Class, Base, Tpl) \ + template <typename... Args> \ + Class(Args&&... args) \ + : Base Tpl(std::forward<Args>(args)...) \ + { \ + } + +#else + +# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base; + +#endif namespace cm { @@ -52,7 +61,8 @@ protected: void allocate(void* data = nullptr); public: - CM_DISABLE_COPY(uv_handle_ptr_base_) + uv_handle_ptr_base_(uv_handle_ptr_base_ const&) = delete; + uv_handle_ptr_base_& operator=(uv_handle_ptr_base_ const&) = delete; uv_handle_ptr_base_(uv_handle_ptr_base_&&) noexcept; uv_handle_ptr_base_& operator=(uv_handle_ptr_base_&&) noexcept; @@ -77,8 +87,8 @@ public: } // Dtor and ctor need to be inline defined like this for default ctors and - // dtors to work. - uv_handle_ptr_base_() {} + // dtors to work. Some compilers do not like '= default' here. + uv_handle_ptr_base_() {} // NOLINT(modernize-use-equals-default) uv_handle_ptr_base_(std::nullptr_t) {} ~uv_handle_ptr_base_() { reset(); } @@ -116,7 +126,7 @@ class uv_handle_ptr_ : public uv_handle_ptr_base_<T> friend class uv_handle_ptr_; public: - CM_PERFECT_FWD_CTOR(uv_handle_ptr_, uv_handle_ptr_base_<T>); + CM_INHERIT_CTOR(uv_handle_ptr_, uv_handle_ptr_base_, <T>); /*** * Allow less verbose calling of uv_<T> functions @@ -133,13 +143,13 @@ template <> class uv_handle_ptr_<uv_handle_t> : public uv_handle_ptr_base_<uv_handle_t> { public: - CM_PERFECT_FWD_CTOR(uv_handle_ptr_, uv_handle_ptr_base_<uv_handle_t>); + CM_INHERIT_CTOR(uv_handle_ptr_, uv_handle_ptr_base_, <uv_handle_t>); }; class uv_async_ptr : public uv_handle_ptr_<uv_async_t> { public: - CM_PERFECT_FWD_CTOR(uv_async_ptr, uv_handle_ptr_<uv_async_t>); + CM_INHERIT_CTOR(uv_async_ptr, uv_handle_ptr_, <uv_async_t>); int init(uv_loop_t& loop, uv_async_cb async_cb, void* data = nullptr); @@ -148,7 +158,7 @@ public: struct uv_signal_ptr : public uv_handle_ptr_<uv_signal_t> { - CM_PERFECT_FWD_CTOR(uv_signal_ptr, uv_handle_ptr_<uv_signal_t>); + CM_INHERIT_CTOR(uv_signal_ptr, uv_handle_ptr_, <uv_signal_t>); int init(uv_loop_t& loop, void* data = nullptr); @@ -159,7 +169,7 @@ struct uv_signal_ptr : public uv_handle_ptr_<uv_signal_t> struct uv_pipe_ptr : public uv_handle_ptr_<uv_pipe_t> { - CM_PERFECT_FWD_CTOR(uv_pipe_ptr, uv_handle_ptr_<uv_pipe_t>); + CM_INHERIT_CTOR(uv_pipe_ptr, uv_handle_ptr_, <uv_pipe_t>); operator uv_stream_t*() const; @@ -168,7 +178,7 @@ struct uv_pipe_ptr : public uv_handle_ptr_<uv_pipe_t> struct uv_process_ptr : public uv_handle_ptr_<uv_process_t> { - CM_PERFECT_FWD_CTOR(uv_process_ptr, uv_handle_ptr_<uv_process_t>); + CM_INHERIT_CTOR(uv_process_ptr, uv_handle_ptr_, <uv_process_t>); int spawn(uv_loop_t& loop, uv_process_options_t const& options, void* data = nullptr); @@ -176,7 +186,7 @@ struct uv_process_ptr : public uv_handle_ptr_<uv_process_t> struct uv_timer_ptr : public uv_handle_ptr_<uv_timer_t> { - CM_PERFECT_FWD_CTOR(uv_timer_ptr, uv_handle_ptr_<uv_timer_t>); + CM_INHERIT_CTOR(uv_timer_ptr, uv_handle_ptr_, <uv_timer_t>); int init(uv_loop_t& loop, void* data = nullptr); @@ -185,7 +195,7 @@ struct uv_timer_ptr : public uv_handle_ptr_<uv_timer_t> struct uv_tty_ptr : public uv_handle_ptr_<uv_tty_t> { - CM_PERFECT_FWD_CTOR(uv_tty_ptr, uv_handle_ptr_<uv_tty_t>); + CM_INHERIT_CTOR(uv_tty_ptr, uv_handle_ptr_, <uv_tty_t>); operator uv_stream_t*() const; diff --git a/Source/cmUnexpectedCommand.h b/Source/cmUnexpectedCommand.h index 7154881a4..33d6bdc2c 100644 --- a/Source/cmUnexpectedCommand.h +++ b/Source/cmUnexpectedCommand.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <string> +#include <utility> #include <vector> #include "cmCommand.h" @@ -15,8 +16,8 @@ class cmExecutionStatus; class cmUnexpectedCommand : public cmCommand { public: - cmUnexpectedCommand(std::string const& name, const char* error) - : Name(name) + cmUnexpectedCommand(std::string name, const char* error) + : Name(std::move(name)) , Error(error) { } diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index 01ef5cbea..9648b21d8 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -100,6 +100,6 @@ void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader(const char* source, // close the files before attempting to copy fin.close(); fout.close(); - cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(), outFile.c_str()); + cmSystemTools::CopyFileIfDifferent(tempOutputFile, outFile); cmSystemTools::RemoveFile(tempOutputFile); } diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index f37462644..231bca41d 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -40,7 +40,7 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args, msg += ". If your intention is to run this executable, you need to " "preload the cache with the full path to a version of that " "program, which runs on this build machine."; - cmSystemTools::Message(msg.c_str(), "Warning"); + cmSystemTools::Message(msg, "Warning"); } } else { cmState* state = this->Makefile->GetState(); diff --git a/Source/cmVS10CLFlagTable.h b/Source/cmVS10CLFlagTable.h deleted file mode 100644 index df4d58c03..000000000 --- a/Source/cmVS10CLFlagTable.h +++ /dev/null @@ -1,205 +0,0 @@ -static cmVS7FlagTable cmVS10CLFlagTable[] = { - - // Enum Properties - { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 }, - { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 }, - { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue", - "EditAndContinue", 0 }, - - { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 }, - { "WarningLevel", "W1", "Level1", "Level1", 0 }, - { "WarningLevel", "W2", "Level2", "Level2", 0 }, - { "WarningLevel", "W3", "Level3", "Level3", 0 }, - { "WarningLevel", "W4", "Level4", "Level4", 0 }, - { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 }, - - { "Optimization", "Od", "Disabled", "Disabled", 0 }, - { "Optimization", "O1", "Minimize Size", "MinSpace", 0 }, - { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 }, - { "Optimization", "Ox", "Full Optimization", "Full", 0 }, - - { "InlineFunctionExpansion", "", "Default", "Default", 0 }, - { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 }, - { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline", - 0 }, - { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 }, - - { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 }, - { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 }, - { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 }, - - { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 }, - { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 }, - { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow", - 0 }, - { "ExceptionHandling", "", "No", "false", 0 }, - - { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck", - 0 }, - { "BasicRuntimeChecks", "RTCu", "Uninitialized variables", - "UninitializedLocalUsageCheck", 0 }, - { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)", - "EnableFastChecks", 0 }, - { "BasicRuntimeChecks", "", "Default", "Default", 0 }, - - { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 }, - { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 }, - { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 }, - { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL", - "MultiThreadedDebugDLL", 0 }, - - { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 }, - { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 }, - { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 }, - { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 }, - { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 }, - { "StructMemberAlignment", "", "Default", "Default", 0 }, - - { "EnableEnhancedInstructionSet", "arch:SSE", - "Streaming SIMD Extensions (/arch:SSE)", "StreamingSIMDExtensions", 0 }, - { "EnableEnhancedInstructionSet", "arch:SSE2", - "Streaming SIMD Extensions 2 (/arch:SSE2)", "StreamingSIMDExtensions2", - 0 }, - { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 }, - - { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 }, - { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 }, - { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 }, - - { "PrecompiledHeader", "Yc", "Create", "Create", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "PrecompiledHeader", "Yu", "Use", "Use", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "PrecompiledHeader", "Y-", "Not Using Precompiled Headers", "NotUsing", - 0 }, - - { "AssemblerOutput", "", "No Listing", "NoListing", 0 }, - { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 }, - { "AssemblerOutput", "FAc", "Assembly With Machine Code", - "AssemblyAndMachineCode", 0 }, - { "AssemblerOutput", "FAs", "Assembly With Source Code", - "AssemblyAndSourceCode", 0 }, - { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 }, - - { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 }, - { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 }, - { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 }, - - { "CompileAs", "", "Default", "Default", 0 }, - { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 }, - { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 }, - - { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 }, - { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt", - 0 }, - { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue", - 0 }, - { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 }, - - { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 }, - { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 }, - { "CompileAsManaged", "clr:pure", - "Pure MSIL Common Language RunTime Support", "Pure", 0 }, - { "CompileAsManaged", "clr:safe", - "Safe MSIL Common Language RunTime Support", "Safe", 0 }, - { "CompileAsManaged", "clr:oldSyntax", - "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 }, - - // Bool Properties - { "SuppressStartupBanner", "nologo-", "", "false", 0 }, - { "SuppressStartupBanner", "nologo", "", "true", 0 }, - { "TreatWarningAsError", "WX-", "", "false", 0 }, - { "TreatWarningAsError", "WX", "", "true", 0 }, - { "IntrinsicFunctions", "Oi", "", "true", 0 }, - { "OmitFramePointers", "Oy-", "", "false", 0 }, - { "OmitFramePointers", "Oy", "", "true", 0 }, - { "EnableFiberSafeOptimizations", "GT", "", "true", 0 }, - { "WholeProgramOptimization", "GL", "", "true", 0 }, - { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 }, - { "IgnoreStandardIncludePath", "X", "", "true", 0 }, - { "PreprocessToFile", "P", "", "true", 0 }, - { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 }, - { "PreprocessKeepComments", "C", "", "true", 0 }, - { "StringPooling", "GF-", "", "false", 0 }, - { "StringPooling", "GF", "", "true", 0 }, - { "MinimalRebuild", "Gm-", "", "false", 0 }, - { "MinimalRebuild", "Gm", "", "true", 0 }, - { "SmallerTypeCheck", "RTCc", "", "true", 0 }, - { "BufferSecurityCheck", "GS-", "", "false", 0 }, - { "BufferSecurityCheck", "GS", "", "true", 0 }, - { "FunctionLevelLinking", "Gy-", "", "false", 0 }, - { "FunctionLevelLinking", "Gy", "", "true", 0 }, - { "FloatingPointExceptions", "fp:except-", "", "false", 0 }, - { "FloatingPointExceptions", "fp:except", "", "true", 0 }, - { "CreateHotpatchableImage", "hotpatch", "", "true", 0 }, - { "DisableLanguageExtensions", "Za", "", "true", 0 }, - { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 }, - { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 }, - { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 }, - { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 }, - { "RuntimeTypeInfo", "GR-", "", "false", 0 }, - { "RuntimeTypeInfo", "GR", "", "true", 0 }, - { "OpenMPSupport", "openmp-", "", "false", 0 }, - { "OpenMPSupport", "openmp", "", "true", 0 }, - { "ExpandAttributedSource", "Fx", "", "true", 0 }, - { "ShowIncludes", "showIncludes", "", "true", 0 }, - { "EnablePREfast", "analyze-", "", "false", 0 }, - { "EnablePREfast", "analyze", "", "true", 0 }, - { "UseFullPaths", "FC", "", "true", 0 }, - { "OmitDefaultLibName", "Zl", "", "true", 0 }, - { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 }, - - // Bool Properties With Argument - { "MultiProcessorCompilation", "MP", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "ProcessorNumber", "MP", "Multi-processor Compilation", "", - cmVS7FlagTable::UserValueRequired }, - { "GenerateXMLDocumentationFiles", "doc", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "", - cmVS7FlagTable::UserValueRequired }, - { "BrowseInformation", "FR", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "BrowseInformationFile", "FR", "Enable Browse Information", "", - cmVS7FlagTable::UserValueRequired }, - - // String List Properties - { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AdditionalUsingDirectories", "AI", "Resolve #using References", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "UndefinePreprocessorDefinitions", "U", - "Undefine Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForcedIncludeFiles", "FI", "Forced Include File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForcedUsingFiles", "FU", "Forced #using File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - // Skip [TrackerLogDirectory] - no command line Switch. - { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "", - cmVS7FlagTable::UserValue }, - { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired }, - { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired }, - { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "", - cmVS7FlagTable::UserValue }, - { "AssemblerListingLocation", "Fa", "ASM List Location", "", - cmVS7FlagTable::UserValue }, - { "ObjectFileName", "Fo", "Object File Name", "", - cmVS7FlagTable::UserValue }, - { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "", - cmVS7FlagTable::UserValue }, - // Skip [XMLDocumentationFileName] - no command line Switch. - // Skip [BrowseInformationFile] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS10CSharpFlagTable.h b/Source/cmVS10CSharpFlagTable.h deleted file mode 100644 index 6ac7a76ae..000000000 --- a/Source/cmVS10CSharpFlagTable.h +++ /dev/null @@ -1,121 +0,0 @@ -static cmVS7FlagTable cmVS10CSharpFlagTable[] = { - { "ProjectName", "out:", "", "", cmIDEFlagTable::UserValueRequired }, - - { "OutputType", "target:exe", "", "Exe", 0 }, - { "OutputType", "target:winexe", "", "Winexe", 0 }, - { "OutputType", "target:library", "", "Library", 0 }, - { "OutputType", "target:module", "", "Module", 0 }, - - { "DocumentationFile", "doc", "", "", cmIDEFlagTable::UserValueRequired }, - - { "Platform", "platform:x86", "", "x86", 0 }, - { "Platform", "platform:Itanium", "", "Itanium", 0 }, - { "Platform", "platform:x64", "", "x64", 0 }, - { "Platform", "platform:arm", "", "arm", 0 }, - { "Platform", "platform:anycpu32bitpreferred", "", "anycpu32bitpreferred", - 0 }, - { "Platform", "platform:anycpu", "", "anycpu", 0 }, - - { "References", "reference:", "mit alias", "", 0 }, - { "References", "reference:", "dateiliste", "", 0 }, - { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable }, - { "", "link", "", "", 0 }, - - { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired }, - { "ApplicationIcon", "win32icon:", "", "", - cmIDEFlagTable::UserValueRequired }, - - { "ApplicationManifest", "win32manifest:", "", "", - cmIDEFlagTable::UserValueRequired }, - - { "NoWin32Manifest", "nowin32manifest", "", "true", 0 }, - - { "DefineDebug", "debug", "", "true", cmIDEFlagTable::Continue }, - - { "DebugSymbols", "debug", "", "true", 0 }, - { "DebugSymbols", "debug-", "", "false", 0 }, - { "DebugSymbols", "debug+", "", "true", 0 }, - - { "DebugType", "debug:none", "", "none", 0 }, - { "DebugType", "debug:full", "", "full", 0 }, - { "DebugType", "debug:pdbonly", "", "pdbonly", 0 }, - - { "Optimize", "optimize", "", "true", 0 }, - { "Optimize", "optimize-", "", "false", 0 }, - { "Optimize", "optimize+", "", "true", 0 }, - - { "TreatWarningsAsErrors", "warnaserror", "", "true", 0 }, - { "TreatWarningsAsErrors", "warnaserror-", "", "false", 0 }, - { "TreatWarningsAsErrors", "warnaserror+", "", "true", 0 }, - - { "WarningsAsErrors", "warnaserror", "", "", 0 }, - { "WarningsAsErrors", "warnaserror-", "", "", 0 }, - { "WarningsAsErrors", "warnaserror+", "", "", 0 }, - - { "WarningLevel", "warn:0", "", "0", 0 }, - { "WarningLevel", "warn:1", "", "1", 0 }, - { "WarningLevel", "warn:2", "", "2", 0 }, - { "WarningLevel", "warn:3", "", "3", 0 }, - { "WarningLevel", "warn:4", "", "4", 0 }, - { "DisabledWarnings", "nowarn", "", "", 0 }, - - { "CheckForOverflowUnderflow", "checked", "", "true", 0 }, - { "CheckForOverflowUnderflow", "checked-", "", "false", 0 }, - { "CheckForOverflowUnderflow", "checked+", "", "true", 0 }, - - { "AllowUnsafeBlocks", "unsafe", "", "true", 0 }, - { "AllowUnsafeBlocks", "unsafe-", "", "false", 0 }, - { "AllowUnsafeBlocks", "unsafe+", "", "true", 0 }, - - { "DefineConstants", "define:", "", "", - cmIDEFlagTable::SemicolonAppendable | cmIDEFlagTable::UserValue }, - - { "LangVersion", "langversion:ISO-1", "", "ISO-1", 0 }, - { "LangVersion", "langversion:ISO-2", "", "ISO-2", 0 }, - { "LangVersion", "langversion:3", "", "3", 0 }, - { "LangVersion", "langversion:4", "", "4", 0 }, - { "LangVersion", "langversion:5", "", "5", 0 }, - { "LangVersion", "langversion:6", "", "6", 0 }, - { "LangVersion", "langversion:default", "", "default", 0 }, - - { "DelaySign", "delaysign", "", "true", 0 }, - { "DelaySign", "delaysign-", "", "false", 0 }, - { "DelaySign", "delaysign+", "", "true", 0 }, - - { "AssemblyOriginatorKeyFile", "keyfile", "", "", 0 }, - - { "KeyContainerName", "keycontainer", "", "", 0 }, - - { "NoLogo", "nologo", "", "", 0 }, - - { "NoConfig", "noconfig", "", "true", 0 }, - - { "BaseAddress", "baseaddress:", "", "", 0 }, - - { "CodePage", "codepage", "", "", 0 }, - - { "Utf8Output", "utf8output", "", "", 0 }, - - { "MainEntryPoint", "main:", "", "", 0 }, - - { "GenerateFullPaths", "fullpaths", "", "true", 0 }, - - { "FileAlignment", "filealign", "", "", 0 }, - - { "PdbFile", "pdb:", "", "", 0 }, - - { "NoStandardLib", "nostdlib", "", "true", 0 }, - { "NoStandardLib", "nostdlib-", "", "false", 0 }, - { "NoStandardLib", "nostdlib+", "", "true", 0 }, - - { "SubsystemVersion", "subsystemversion", "", "", 0 }, - - { "AdditionalLibPaths", "lib:", "", "", 0 }, - - { "ErrorReport", "errorreport:none", "Do Not Send Report", "none", 0 }, - { "ErrorReport", "errorreport:prompt", "Prompt Immediately", "prompt", 0 }, - { "ErrorReport", "errorreport:queue", "Queue For Next Login", "queue", 0 }, - { "ErrorReport", "errorreport:send", "Send Automatically", "send", 0 }, - - { 0, 0, 0, 0, 0 }, -}; diff --git a/Source/cmVS10CudaFlagTable.h b/Source/cmVS10CudaFlagTable.h deleted file mode 100644 index 2b57e08ab..000000000 --- a/Source/cmVS10CudaFlagTable.h +++ /dev/null @@ -1,54 +0,0 @@ -static cmVS7FlagTable cmVS10CudaFlagTable[] = { - // Collect options meant for the host compiler. - { "AdditionalCompilerOptions", "Xcompiler=", "Host compiler options", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SpaceAppendable }, - { "AdditionalCompilerOptions", "Xcompiler", "Host compiler options", "", - cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SpaceAppendable }, - - // Select the CUDA runtime library. - { "CudaRuntime", "cudart=none", "No CUDA runtime library", "None", 0 }, - { "CudaRuntime", "cudart=shared", "Shared/dynamic CUDA runtime library", - "Shared", 0 }, - { "CudaRuntime", "cudart=static", "Static CUDA runtime library", "Static", - 0 }, - { "CudaRuntime", "cudart", "CUDA runtime library", "", - cmVS7FlagTable::UserFollowing }, - - // Capture arch/code arguments into temporaries for post-processing. - { "cmake-temp-gencode", "gencode=", "", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "cmake-temp-gencode", "gencode", "", "", - cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable }, - { "cmake-temp-gencode", "-generate-code=", "", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "cmake-temp-gencode", "-generate-code", "", "", - cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable }, - - { "cmake-temp-code", "code=", "", "", cmVS7FlagTable::UserValue }, - { "cmake-temp-code", "code", "", "", cmVS7FlagTable::UserFollowing }, - { "cmake-temp-code", "-gpu-code=", "", "", cmVS7FlagTable::UserValue }, - { "cmake-temp-code", "-gpu-code", "", "", cmVS7FlagTable::UserFollowing }, - - { "cmake-temp-arch", "arch=", "", "", cmVS7FlagTable::UserValue }, - { "cmake-temp-arch", "arch", "", "", cmVS7FlagTable::UserFollowing }, - { "cmake-temp-arch", "-gpu-architecture=", "", "", - cmVS7FlagTable::UserValue }, - { "cmake-temp-arch", "-gpu-architecture", "", "", - cmVS7FlagTable::UserFollowing }, - - // Other flags. - - { "FastMath", "use_fast_math", "", "true", 0 }, - { "FastMath", "-use_fast_math", "", "true", 0 }, - - { "GPUDebugInfo", "G", "", "true", 0 }, - { "GPUDebugInfo", "-device-debug", "", "true", 0 }, - - { "HostDebugInfo", "g", "", "true", 0 }, - { "HostDebugInfo", "-debug", "", "true", 0 }, - - { "MaxRegCount", "maxrregcount=", "", "", cmVS7FlagTable::UserValue }, - { "MaxRegCount", "maxrregcount", "", "", cmVS7FlagTable::UserFollowing }, - - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS10CudaHostFlagTable.h b/Source/cmVS10CudaHostFlagTable.h deleted file mode 100644 index 5b61066ca..000000000 --- a/Source/cmVS10CudaHostFlagTable.h +++ /dev/null @@ -1,35 +0,0 @@ -static cmVS7FlagTable cmVS10CudaHostFlagTable[] = { - //{"Optimization", "", "<inherit from host>", "InheritFromHost", 0}, - { "Optimization", "Od", "Disabled", "Od", 0 }, - { "Optimization", "O1", "Minimize Size", "O1", 0 }, - { "Optimization", "O2", "Maximize Speed", "O2", 0 }, - { "Optimization", "Ox", "Full Optimization", "O3", 0 }, - - //{"Runtime", "", "<inherit from host>", "InheritFromHost", 0}, - { "Runtime", "MT", "Multi-Threaded", "MT", 0 }, - { "Runtime", "MTd", "Multi-Threaded Debug", "MTd", 0 }, - { "Runtime", "MD", "Multi-Threaded DLL", "MD", 0 }, - { "Runtime", "MDd", "Multi-threaded Debug DLL", "MDd", 0 }, - { "Runtime", "ML", "Single-Threaded", "ML", 0 }, - { "Runtime", "MLd", "Single-Threaded Debug", "MLd", 0 }, - - //{"RuntimeChecks", "", "<inherit from host>", "InheritFromHost", 0}, - //{"RuntimeChecks", "", "Default", "Default", 0}, - { "RuntimeChecks", "RTCs", "Stack Frames", "RTCs", 0 }, - { "RuntimeChecks", "RTCu", "Uninitialized Variables", "RTCu", 0 }, - { "RuntimeChecks", "RTC1", "Both", "RTC1", 0 }, - - //{"TypeInfo", "", "<inherit from host>", "InheritFromHost", 0}, - { "TypeInfo", "GR", "Yes", "true", 0 }, - { "TypeInfo", "GR-", "No", "false", 0 }, - - //{"Warning", "", "<inherit from host>", "InheritFromHost", 0}, - { "Warning", "W0", "Off: Turn Off All Warnings", "W0", 0 }, - { "Warning", "W1", "Level 1", "W1", 0 }, - { "Warning", "W2", "Level 2", "W2", 0 }, - { "Warning", "W3", "Level 3", "W3", 0 }, - { "Warning", "W4", "Level 4", "W4", 0 }, - { "Warning", "Wall", "Enable All Warnings", "Wall", 0 }, - - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS10LibFlagTable.h b/Source/cmVS10LibFlagTable.h deleted file mode 100644 index be4f4753b..000000000 --- a/Source/cmVS10LibFlagTable.h +++ /dev/null @@ -1,76 +0,0 @@ -static cmVS7FlagTable cmVS10LibFlagTable[] = { - - // Enum Properties - { "ErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately", - "PromptImmediately", 0 }, - { "ErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login", - "QueueForNextLogin", 0 }, - { "ErrorReporting", "ERRORREPORT:SEND", "Send Error Report", - "SendErrorReport", 0 }, - { "ErrorReporting", "ERRORREPORT:NONE", "No Error Report", "NoErrorReport", - 0 }, - - { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 }, - { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 }, - { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 }, - { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 }, - { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 }, - { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU", - 0 }, - { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16", - "MachineMIPSFPU16", 0 }, - { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 }, - { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 }, - { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 }, - { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 }, - - { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 }, - { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application", - "EFI Application", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", - "EFI Boot Service Driver", "EFI Boot Service Driver", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime", - 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWSCE", "WindowsCE", "WindowsCE", 0 }, - { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 }, - - // Bool Properties - { "SuppressStartupBanner", "NOLOGO", "", "true", 0 }, - { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 }, - { "TreatLibWarningAsErrors", "WX:NO", "", "false", 0 }, - { "TreatLibWarningAsErrors", "WX", "", "true", 0 }, - { "Verbose", "VERBOSE", "", "true", 0 }, - { "LinkTimeCodeGeneration", "LTCG", "", "true", 0 }, - - // Bool Properties With Argument - - // String List Properties - // Skip [AdditionalDependencies] - no command line Switch. - { "AdditionalLibraryDirectories", - "LIBPATH:", "Additional Library Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IgnoreSpecificDefaultLibraries", - "NODEFAULTLIB:", "Ignore Specific Default Libraries", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "RemoveObjects", "REMOVE:", "Remove Objects", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue }, - { "ModuleDefinitionFile", "DEF:", "Module Definition File Name", "", - cmVS7FlagTable::UserValue }, - { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "", - cmVS7FlagTable::UserValue }, - { "DisplayLibrary", "LIST:", "Display Library to standard output", "", - cmVS7FlagTable::UserValue }, - // Skip [MinimumRequiredVersion] - no command line Switch. - { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue }, - // Skip [TrackerLogDirectory] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS10LinkFlagTable.h b/Source/cmVS10LinkFlagTable.h deleted file mode 100644 index 8f5b59b03..000000000 --- a/Source/cmVS10LinkFlagTable.h +++ /dev/null @@ -1,247 +0,0 @@ -static cmVS7FlagTable cmVS10LinkFlagTable[] = { - - // Enum Properties - { "ShowProgress", "", "Not Set", "NotSet", 0 }, - { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose", - 0 }, - { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib", - 0 }, - { "ShowProgress", "VERBOSE:ICF", - "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 }, - { "ShowProgress", "VERBOSE:REF", - "About data removed during optimized linking", "LinkVerboseREF", 0 }, - { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH", - "LinkVerboseSAFESEH", 0 }, - { "ShowProgress", "VERBOSE:CLR", - "About linker activity related to managed code", "LinkVerboseCLR", 0 }, - - { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 }, - { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only", - "MultiplyDefinedSymbolOnly", 0 }, - { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only", - "UndefinedSymbolOnly", 0 }, - - { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only", - "X86Image", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only", - "X64Image", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", - "ItaniumImage", 0 }, - - // correct flags for uac should be /MANIFESTUAC, but some projects already - // use this bug to access uac field, so keep these for compatibility - { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, - { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", - "HighestAvailable", 0 }, - { "UACExecutionLevel", "level='requireAdministrator'", - "requireAdministrator", "RequireAdministrator", 0 }, - - { "SubSystem", "", "Not Set", "NotSet", 0 }, - { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 }, - { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application", - "EFI Application", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", - "EFI Boot Service Driver", "EFI Boot Service Driver", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime", - 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWSCE", "WindowsCE", "WindowsCE", 0 }, - { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 }, - - { "Driver", "", "Not Set", "NotSet", 0 }, - { "Driver", "Driver", "Driver", "Driver", 0 }, - { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 }, - { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 }, - - { "LinkTimeCodeGeneration", "", "Default", "Default", 0 }, - { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation", - "UseLinkTimeCodeGeneration", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGInstrument", - "Profile Guided Optimization - Instrument", "PGInstrument", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGOptimize", - "Profile Guided Optimization - Optimization", "PGOptimization", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGUpdate", - "Profile Guided Optimization - Update", "PGUpdate", 0 }, - - { "TargetMachine", "", "Not Set", "NotSet", 0 }, - { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 }, - { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 }, - { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 }, - { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 }, - { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 }, - { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU", - 0 }, - { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16", - "MachineMIPSFPU16", 0 }, - { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 }, - { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 }, - { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 }, - { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 }, - - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute", - "MTAThreadingAttribute", 0 }, - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute", - "STAThreadingAttribute", 0 }, - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE", - "Default threading attribute", "DefaultThreadingAttribute", 0 }, - - { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage", - 0 }, - { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image", - "ForcePureILImage", 0 }, - { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image", - "ForceSafeILImage", 0 }, - { "CLRImageType", "", "Default image type", "Default", 0 }, - - { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately", - "PromptImmediately", 0 }, - { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login", - "QueueForNextLogin", 0 }, - { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report", - "SendErrorReport", 0 }, - { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report", - "NoErrorReport", 0 }, - - { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 }, - { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled", - 0 }, - { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only", - "SystemDlls", 0 }, - - // Bool Properties - { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 }, - { "LinkIncremental", "INCREMENTAL", "", "true", 0 }, - { "SuppressStartupBanner", "NOLOGO", "", "true", 0 }, - { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 }, - { "LinkStatus", "LTCG:STATUS", "", "true", 0 }, - { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 }, - { "PreventDllBinding", "ALLOWBIND", "", "true", 0 }, - { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 }, - { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 }, - { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 }, - { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, - { "GenerateManifest", "MANIFEST", "", "true", 0 }, - { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, - - // correct flags for uac should be /MANIFESTUAC, but some projects already - // use this bug to access uac field, so keep these for compatibility - { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, - { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, - - { "GenerateDebugInformation", "DEBUG", "", "true", - cmVS7FlagTable::CaseInsensitive }, - { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 }, - { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 }, - { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 }, - { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 }, - { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 }, - { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 }, - { "TerminalServerAware", "TSAWARE", "", "true", 0 }, - { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 }, - { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 }, - { "OptimizeReferences", "OPT:NOREF", "", "false", 0 }, - { "OptimizeReferences", "OPT:REF", "", "true", 0 }, - { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 }, - { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 }, - { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 }, - { "NoEntryPoint", "NOENTRY", "", "true", 0 }, - { "SetChecksum", "RELEASE", "", "true", 0 }, - { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 }, - { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 }, - { "FixedBaseAddress", "FIXED:NO", "", "false", 0 }, - { "FixedBaseAddress", "FIXED", "", "true", 0 }, - { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 }, - { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 }, - { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 }, - { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 }, - { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 }, - { "Profile", "PROFILE", "", "true", 0 }, - { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 }, - { "LinkDelaySign", "DELAYSIGN", "", "true", 0 }, - { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 }, - { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 }, - { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 }, - { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 }, - { "LinkDLL", "DLL", "", "true", 0 }, - - // Bool Properties With Argument - { "EnableUAC", "MANIFESTUAC:", "", "", - cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SpaceAppendable }, - { "GenerateMapFile", "MAP", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "MapFileName", "MAP:", "Generate Map File", "", - cmVS7FlagTable::UserValueRequired }, - - // String List Properties - { "AdditionalLibraryDirectories", - "LIBPATH:", "Additional Library Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - // Skip [AdditionalDependencies] - no command line Switch. - { "IgnoreSpecificDefaultLibraries", - "NODEFAULTLIB:", "Ignore Specific Default Libraries", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "EmbedManagedResourceFile", - "ASSEMBLYRESOURCE:", "Embed Managed Resource File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AdditionalManifestDependencies", - "MANIFESTDEPENDENCY:", "Additional Manifest Dependencies", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue }, - { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue }, - { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "", - cmVS7FlagTable::UserValue }, - { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "", - cmVS7FlagTable::UserValue }, - // Skip [TrackerLogDirectory] - no command line Switch. - { "ModuleDefinitionFile", "DEF:", "Module Definition File", "", - cmVS7FlagTable::UserValue }, - { "ManifestFile", "ManifestFile:", "Manifest File", "", - cmVS7FlagTable::UserValue }, - { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "", - cmVS7FlagTable::UserValue }, - { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "", - cmVS7FlagTable::UserValue }, - // Skip [MapFileName] - no command line Switch. - // Skip [MinimumRequiredVersion] - no command line Switch. - { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "", - cmVS7FlagTable::UserValue }, - // Skip [HeapCommitSize] - no command line Switch. - { "StackReserveSize", "STACK:", "Stack Reserve Size", "", - cmVS7FlagTable::UserValue }, - // Skip [StackCommitSize] - no command line Switch. - { "FunctionOrder", "ORDER:@", "Function Order", "", - cmVS7FlagTable::UserValue }, - { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "", - cmVS7FlagTable::UserValue }, - { "MidlCommandFile", "MIDL:@", "MIDL Commands", "", - cmVS7FlagTable::UserValue }, - { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "", - cmVS7FlagTable::UserValue }, - { "TypeLibraryFile", "TLBOUT:", "Type Library", "", - cmVS7FlagTable::UserValue }, - { "EntryPointSymbol", "ENTRY:", "Entry Point", "", - cmVS7FlagTable::UserValue }, - { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue }, - { "ImportLibrary", "IMPLIB:", "Import Library", "", - cmVS7FlagTable::UserValue }, - { "MergeSections", "MERGE:", "Merge Sections", "", - cmVS7FlagTable::UserValue }, - { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue }, - { "KeyContainer", "KEYCONTAINER:", "Key Container", "", - cmVS7FlagTable::UserValue }, - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS10MASMFlagTable.h b/Source/cmVS10MASMFlagTable.h deleted file mode 100644 index 0a452453f..000000000 --- a/Source/cmVS10MASMFlagTable.h +++ /dev/null @@ -1,76 +0,0 @@ -static cmVS7FlagTable cmVS10MASMFlagTable[] = { - - // Enum Properties - { "PreserveIdentifierCase", "", "Default", "0", 0 }, - { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1", - 0 }, - { "PreserveIdentifierCase", "Cu", - "Maps all identifiers to upper case. (/Cu)", "2", 0 }, - { "PreserveIdentifierCase", "Cx", - "Preserves case in public and extern symbols. (/Cx)", "3", 0 }, - - { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 }, - { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 }, - { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 }, - { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 }, - - { "PackAlignmentBoundary", "", "Default", "0", 0 }, - { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, - { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, - { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, - { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, - { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 }, - - { "CallingConvention", "", "Default", "0", 0 }, - { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1", - 0 }, - { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2", - 0 }, - { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 }, - - { "ErrorReporting", "errorReport:prompt", - "Prompt to send report immediately (/errorReport:prompt)", "0", 0 }, - { "ErrorReporting", "errorReport:queue", - "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 }, - { "ErrorReporting", "errorReport:send", - "Automatically send report (/errorReport:send)", "2", 0 }, - { "ErrorReporting", "errorReport:none", - "Do not send report (/errorReport:none)", "3", 0 }, - - // Bool Properties - { "NoLogo", "nologo", "", "true", 0 }, - { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 }, - { "ListAllAvailableInformation", "Sa", "", "true", 0 }, - { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 }, - { "AddFirstPassListing", "Sf", "", "true", 0 }, - { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 }, - { "DisableSymbolTable", "Sn", "", "true", 0 }, - { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 }, - { "TreatWarningsAsErrors", "WX", "", "true", 0 }, - { "MakeAllSymbolsPublic", "Zf", "", "true", 0 }, - { "GenerateDebugInformation", "Zi", "", "true", 0 }, - { "EnableMASM51Compatibility", "Zm", "", "true", 0 }, - { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 }, - - // Bool Properties With Argument - - // String List Properties - { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IncludePaths", "I", "Include Paths", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "BrowseFile", "FR", "Generate Browse Information File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - // Skip [AdditionalDependencies] - no command line Switch. - - // String Properties - // Skip [Inputs] - no command line Switch. - { "ObjectFileName", "Fo", "Object File Name", "", - cmVS7FlagTable::UserValue }, - { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "", - cmVS7FlagTable::UserValue }, - // Skip [CommandLineTemplate] - no command line Switch. - // Skip [ExecutionDescription] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS10NASMFlagTable.h b/Source/cmVS10NASMFlagTable.h deleted file mode 100644 index b91af9270..000000000 --- a/Source/cmVS10NASMFlagTable.h +++ /dev/null @@ -1,50 +0,0 @@ -static cmVS7FlagTable cmVS10NASMFlagTable[] = { - - // Enum Properties - { "Outputswitch", "fwin32", "", "0", 0 }, - { "Outputswitch", "fwin", "", "0", 0 }, - { "Outputswitch", "fwin64", "", "1", 0 }, - { "Outputswitch", "felf", "", "2", 0 }, - { "Outputswitch", "felf32", "", "2", 0 }, - { "Outputswitch", "felf64", "", "3", 0 }, - - { "ErrorReportingFormat", "Xgnu", "", "-Xgnu GNU format: Default format", - 0 }, - { "ErrorReportingFormat", "Xvc", "", - "-Xvc Style used by Microsoft Visual C++", 0 }, - - // Bool Properties - { "TreatWarningsAsErrors", "Werror", "", "true", 0 }, - { "GenerateDebugInformation", "g", "", "true", 0 }, - { "floatunderflow", "w+float-underflow", "", "true", 0 }, - { "macrodefaults", "w-macro-defaults", "", "true", 0 }, - { "user", "w-user", "%warning directives (default on)", "true", 0 }, - { "floatoverflow", "w-float-overflow", "", "true", 0 }, - { "floatdenorm", "w+float-denorm", "", "true", 0 }, - { "numberoverflow", "w-number-overflow", "", "true", 0 }, - { "macroselfref", "w+macro-selfref", "", "true", 0 }, - { "floattoolong", "w-float-toolong", "", "true", 0 }, - { "orphanlabels", "w-orphan-labels", "", "true", 0 }, - { "tasmmode", "t", "", "true", 0 }, - - // Bool Properties With Argument - - // String List Properties - { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "UndefinePreprocessorDefinitions", "U", - "Undefine Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IncludePaths", "I", "Include Paths", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AssembledCodeListingFile", "l", - "Generates an assembled code listing file.", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - // Skip [Inputs] - no command line Switch. - // Skip [CommandLineTemplate] - no command line Switch. - // Skip [ExecutionDescription] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS10RCFlagTable.h b/Source/cmVS10RCFlagTable.h deleted file mode 100644 index 6e2b8344c..000000000 --- a/Source/cmVS10RCFlagTable.h +++ /dev/null @@ -1,7 +0,0 @@ -static cmVS7FlagTable cmVS10RCFlagTable[] = { - // Bool Properties - { "NullTerminateStrings", "n", "", "true", 0 }, - { "SuppressStartupBanner", "nologo", "", "true", 0 }, - - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS11CLFlagTable.h b/Source/cmVS11CLFlagTable.h deleted file mode 100644 index d156938e1..000000000 --- a/Source/cmVS11CLFlagTable.h +++ /dev/null @@ -1,220 +0,0 @@ -static cmVS7FlagTable cmVS11CLFlagTable[] = { - - // Enum Properties - { "DebugInformationFormat", "", "None", "None", 0 }, - { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 }, - { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 }, - { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue", - "EditAndContinue", 0 }, - - { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 }, - { "WarningLevel", "W1", "Level1", "Level1", 0 }, - { "WarningLevel", "W2", "Level2", "Level2", 0 }, - { "WarningLevel", "W3", "Level3", "Level3", 0 }, - { "WarningLevel", "W4", "Level4", "Level4", 0 }, - { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 }, - - { "Optimization", "Od", "Disabled", "Disabled", 0 }, - { "Optimization", "O1", "Minimize Size", "MinSpace", 0 }, - { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 }, - { "Optimization", "Ox", "Full Optimization", "Full", 0 }, - - { "InlineFunctionExpansion", "", "Default", "Default", 0 }, - { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 }, - { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline", - 0 }, - { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 }, - - { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 }, - { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 }, - { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 }, - - { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 }, - { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 }, - { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow", - 0 }, - { "ExceptionHandling", "", "No", "false", 0 }, - - { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck", - 0 }, - { "BasicRuntimeChecks", "RTCu", "Uninitialized variables", - "UninitializedLocalUsageCheck", 0 }, - { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)", - "EnableFastChecks", 0 }, - { "BasicRuntimeChecks", "", "Default", "Default", 0 }, - - { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 }, - { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 }, - { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 }, - { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL", - "MultiThreadedDebugDLL", 0 }, - - { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 }, - { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 }, - { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 }, - { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 }, - { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 }, - { "StructMemberAlignment", "", "Default", "Default", 0 }, - - { "EnableEnhancedInstructionSet", "arch:SSE", "Streaming SIMD Extensions", - "StreamingSIMDExtensions", 0 }, - { "EnableEnhancedInstructionSet", "arch:SSE2", "Streaming SIMD Extensions 2", - "StreamingSIMDExtensions2", 0 }, - { "EnableEnhancedInstructionSet", "arch:AVX", "Advanced Vector Extensions", - "AdvancedVectorExtensions", 0 }, - { "EnableEnhancedInstructionSet", "arch:IA32", "No Enhanced Instructions", - "NoExtensions", 0 }, - { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 }, - - { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 }, - { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 }, - { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 }, - - { "PrecompiledHeader", "Yc", "Create", "Create", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "PrecompiledHeader", "Yu", "Use", "Use", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "PrecompiledHeader", "Y-", "Not Using Precompiled Headers", "NotUsing", - 0 }, - - { "AssemblerOutput", "", "No Listing", "NoListing", 0 }, - { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 }, - { "AssemblerOutput", "FAc", "Assembly With Machine Code", - "AssemblyAndMachineCode", 0 }, - { "AssemblerOutput", "FAs", "Assembly With Source Code", - "AssemblyAndSourceCode", 0 }, - { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 }, - - { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 }, - { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 }, - { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 }, - - { "CompileAs", "", "Default", "Default", 0 }, - { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 }, - { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 }, - - { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 }, - { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt", - 0 }, - { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue", - 0 }, - { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 }, - - { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 }, - { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 }, - { "CompileAsManaged", "clr:pure", - "Pure MSIL Common Language RunTime Support", "Pure", 0 }, - { "CompileAsManaged", "clr:safe", - "Safe MSIL Common Language RunTime Support", "Safe", 0 }, - { "CompileAsManaged", "clr:oldSyntax", - "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 }, - - // Bool Properties - { "CompileAsWinRT", "ZW", "", "true", 0 }, - { "WinRTNoStdLib", "ZW:nostdlib", "", "true", 0 }, - { "SuppressStartupBanner", "nologo-", "", "false", 0 }, - { "SuppressStartupBanner", "nologo", "", "true", 0 }, - { "TreatWarningAsError", "WX-", "", "false", 0 }, - { "TreatWarningAsError", "WX", "", "true", 0 }, - { "SDLCheck", "sdl-", "", "false", 0 }, - { "SDLCheck", "sdl", "", "true", 0 }, - { "IntrinsicFunctions", "Oi", "", "true", 0 }, - { "OmitFramePointers", "Oy-", "", "false", 0 }, - { "OmitFramePointers", "Oy", "", "true", 0 }, - { "EnableFiberSafeOptimizations", "GT", "", "true", 0 }, - { "WholeProgramOptimization", "GL", "", "true", 0 }, - { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 }, - { "IgnoreStandardIncludePath", "X", "", "true", 0 }, - { "PreprocessToFile", "P", "", "true", 0 }, - { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 }, - { "PreprocessKeepComments", "C", "", "true", 0 }, - { "StringPooling", "GF-", "", "false", 0 }, - { "StringPooling", "GF", "", "true", 0 }, - { "MinimalRebuild", "Gm-", "", "false", 0 }, - { "MinimalRebuild", "Gm", "", "true", 0 }, - { "SmallerTypeCheck", "RTCc", "", "true", 0 }, - { "BufferSecurityCheck", "GS-", "", "false", 0 }, - { "BufferSecurityCheck", "GS", "", "true", 0 }, - { "FunctionLevelLinking", "Gy-", "", "false", 0 }, - { "FunctionLevelLinking", "Gy", "", "true", 0 }, - { "EnableParallelCodeGeneration", "Qpar-", "", "false", 0 }, - { "EnableParallelCodeGeneration", "Qpar", "", "true", 0 }, - { "FloatingPointExceptions", "fp:except-", "", "false", 0 }, - { "FloatingPointExceptions", "fp:except", "", "true", 0 }, - { "CreateHotpatchableImage", "hotpatch", "", "true", 0 }, - { "DisableLanguageExtensions", "Za", "", "true", 0 }, - { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 }, - { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 }, - { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 }, - { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 }, - { "RuntimeTypeInfo", "GR-", "", "false", 0 }, - { "RuntimeTypeInfo", "GR", "", "true", 0 }, - { "OpenMPSupport", "openmp-", "", "false", 0 }, - { "OpenMPSupport", "openmp", "", "true", 0 }, - { "ExpandAttributedSource", "Fx", "", "true", 0 }, - { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 }, - { "ShowIncludes", "showIncludes", "", "true", 0 }, - { "EnablePREfast", "analyze-", "", "false", 0 }, - { "EnablePREfast", "analyze", "", "true", 0 }, - { "UseFullPaths", "FC", "", "true", 0 }, - { "OmitDefaultLibName", "Zl", "", "true", 0 }, - - // Bool Properties With Argument - { "MultiProcessorCompilation", "MP", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "ProcessorNumber", "MP", "Multi-processor Compilation", "", - cmVS7FlagTable::UserValueRequired }, - { "GenerateXMLDocumentationFiles", "doc", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "", - cmVS7FlagTable::UserValueRequired }, - { "BrowseInformation", "FR", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "BrowseInformationFile", "FR", "Enable Browse Information", "", - cmVS7FlagTable::UserValueRequired }, - - // String List Properties - { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AdditionalUsingDirectories", "AI", "Additional #using Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "UndefinePreprocessorDefinitions", "U", - "Undefine Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForcedIncludeFiles", "FI", "Forced Include File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForcedUsingFiles", "FU", "Forced #using File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "PREfastLog", "analyze:log", "Code Analysis Log", "", - cmVS7FlagTable::UserFollowing }, - { "PREfastAdditionalPlugins", "analyze:plugin", - "Additional Code Analysis Native plugins", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - // Skip [TrackerLogDirectory] - no command line Switch. - { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "", - cmVS7FlagTable::UserValue }, - { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired }, - { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired }, - { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "", - cmVS7FlagTable::UserValue }, - { "AssemblerListingLocation", "Fa", "ASM List Location", "", - cmVS7FlagTable::UserValue }, - { "ObjectFileName", "Fo", "Object File Name", "", - cmVS7FlagTable::UserValue }, - { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "", - cmVS7FlagTable::UserValue }, - // Skip [XMLDocumentationFileName] - no command line Switch. - // Skip [BrowseInformationFile] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS11CSharpFlagTable.h b/Source/cmVS11CSharpFlagTable.h deleted file mode 100644 index 18b804a63..000000000 --- a/Source/cmVS11CSharpFlagTable.h +++ /dev/null @@ -1,121 +0,0 @@ -static cmVS7FlagTable cmVS11CSharpFlagTable[] = { - { "ProjectName", "out:", "", "", cmIDEFlagTable::UserValueRequired }, - - { "OutputType", "target:exe", "", "Exe", 0 }, - { "OutputType", "target:winexe", "", "Winexe", 0 }, - { "OutputType", "target:library", "", "Library", 0 }, - { "OutputType", "target:module", "", "Module", 0 }, - - { "DocumentationFile", "doc", "", "", cmIDEFlagTable::UserValueRequired }, - - { "Platform", "platform:x86", "", "x86", 0 }, - { "Platform", "platform:Itanium", "", "Itanium", 0 }, - { "Platform", "platform:x64", "", "x64", 0 }, - { "Platform", "platform:arm", "", "arm", 0 }, - { "Platform", "platform:anycpu32bitpreferred", "", "anycpu32bitpreferred", - 0 }, - { "Platform", "platform:anycpu", "", "anycpu", 0 }, - - { "References", "reference:", "mit alias", "", 0 }, - { "References", "reference:", "dateiliste", "", 0 }, - { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable }, - { "", "link", "", "", 0 }, - - { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired }, - { "ApplicationIcon", "win32icon:", "", "", - cmIDEFlagTable::UserValueRequired }, - - { "ApplicationManifest", "win32manifest:", "", "", - cmIDEFlagTable::UserValueRequired }, - - { "NoWin32Manifest", "nowin32manifest", "", "true", 0 }, - - { "DefineDebug", "debug", "", "true", cmIDEFlagTable::Continue }, - - { "DebugSymbols", "debug", "", "true", 0 }, - { "DebugSymbols", "debug-", "", "false", 0 }, - { "DebugSymbols", "debug+", "", "true", 0 }, - - { "DebugType", "debug:none", "", "none", 0 }, - { "DebugType", "debug:full", "", "full", 0 }, - { "DebugType", "debug:pdbonly", "", "pdbonly", 0 }, - - { "Optimize", "optimize", "", "true", 0 }, - { "Optimize", "optimize-", "", "false", 0 }, - { "Optimize", "optimize+", "", "true", 0 }, - - { "TreatWarningsAsErrors", "warnaserror", "", "true", 0 }, - { "TreatWarningsAsErrors", "warnaserror-", "", "false", 0 }, - { "TreatWarningsAsErrors", "warnaserror+", "", "true", 0 }, - - { "WarningsAsErrors", "warnaserror", "", "", 0 }, - { "WarningsAsErrors", "warnaserror-", "", "", 0 }, - { "WarningsAsErrors", "warnaserror+", "", "", 0 }, - - { "WarningLevel", "warn:0", "", "0", 0 }, - { "WarningLevel", "warn:1", "", "1", 0 }, - { "WarningLevel", "warn:2", "", "2", 0 }, - { "WarningLevel", "warn:3", "", "3", 0 }, - { "WarningLevel", "warn:4", "", "4", 0 }, - { "DisabledWarnings", "nowarn", "", "", 0 }, - - { "CheckForOverflowUnderflow", "checked", "", "true", 0 }, - { "CheckForOverflowUnderflow", "checked-", "", "false", 0 }, - { "CheckForOverflowUnderflow", "checked+", "", "true", 0 }, - - { "AllowUnsafeBlocks", "unsafe", "", "true", 0 }, - { "AllowUnsafeBlocks", "unsafe-", "", "false", 0 }, - { "AllowUnsafeBlocks", "unsafe+", "", "true", 0 }, - - { "DefineConstants", "define:", "", "", - cmIDEFlagTable::SemicolonAppendable | cmIDEFlagTable::UserValue }, - - { "LangVersion", "langversion:ISO-1", "", "ISO-1", 0 }, - { "LangVersion", "langversion:ISO-2", "", "ISO-2", 0 }, - { "LangVersion", "langversion:3", "", "3", 0 }, - { "LangVersion", "langversion:4", "", "4", 0 }, - { "LangVersion", "langversion:5", "", "5", 0 }, - { "LangVersion", "langversion:6", "", "6", 0 }, - { "LangVersion", "langversion:default", "", "default", 0 }, - - { "DelaySign", "delaysign", "", "true", 0 }, - { "DelaySign", "delaysign-", "", "false", 0 }, - { "DelaySign", "delaysign+", "", "true", 0 }, - - { "AssemblyOriginatorKeyFile", "keyfile", "", "", 0 }, - - { "KeyContainerName", "keycontainer", "", "", 0 }, - - { "NoLogo", "nologo", "", "", 0 }, - - { "NoConfig", "noconfig", "", "true", 0 }, - - { "BaseAddress", "baseaddress:", "", "", 0 }, - - { "CodePage", "codepage", "", "", 0 }, - - { "Utf8Output", "utf8output", "", "", 0 }, - - { "MainEntryPoint", "main:", "", "", 0 }, - - { "GenerateFullPaths", "fullpaths", "", "true", 0 }, - - { "FileAlignment", "filealign", "", "", 0 }, - - { "PdbFile", "pdb:", "", "", 0 }, - - { "NoStandardLib", "nostdlib", "", "true", 0 }, - { "NoStandardLib", "nostdlib-", "", "false", 0 }, - { "NoStandardLib", "nostdlib+", "", "true", 0 }, - - { "SubsystemVersion", "subsystemversion", "", "", 0 }, - - { "AdditionalLibPaths", "lib:", "", "", 0 }, - - { "ErrorReport", "errorreport:none", "Do Not Send Report", "none", 0 }, - { "ErrorReport", "errorreport:prompt", "Prompt Immediately", "prompt", 0 }, - { "ErrorReport", "errorreport:queue", "Queue For Next Login", "queue", 0 }, - { "ErrorReport", "errorreport:send", "Send Automatically", "send", 0 }, - - { 0, 0, 0, 0, 0 }, -}; diff --git a/Source/cmVS11LibFlagTable.h b/Source/cmVS11LibFlagTable.h deleted file mode 100644 index 15c8ddda3..000000000 --- a/Source/cmVS11LibFlagTable.h +++ /dev/null @@ -1,76 +0,0 @@ -static cmVS7FlagTable cmVS11LibFlagTable[] = { - - // Enum Properties - { "ErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately", - "PromptImmediately", 0 }, - { "ErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login", - "QueueForNextLogin", 0 }, - { "ErrorReporting", "ERRORREPORT:SEND", "Send Error Report", - "SendErrorReport", 0 }, - { "ErrorReporting", "ERRORREPORT:NONE", "No Error Report", "NoErrorReport", - 0 }, - - { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 }, - { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 }, - { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 }, - { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 }, - { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 }, - { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU", - 0 }, - { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16", - "MachineMIPSFPU16", 0 }, - { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 }, - { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 }, - { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 }, - { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 }, - - { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 }, - { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application", - "EFI Application", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", - "EFI Boot Service Driver", "EFI Boot Service Driver", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime", - 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWSCE", "WindowsCE", "WindowsCE", 0 }, - { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 }, - - // Bool Properties - { "SuppressStartupBanner", "NOLOGO", "", "true", 0 }, - { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 }, - { "TreatLibWarningAsErrors", "WX:NO", "", "false", 0 }, - { "TreatLibWarningAsErrors", "WX", "", "true", 0 }, - { "Verbose", "VERBOSE", "", "true", 0 }, - { "LinkTimeCodeGeneration", "LTCG", "", "true", 0 }, - - // Bool Properties With Argument - - // String List Properties - // Skip [AdditionalDependencies] - no command line Switch. - { "AdditionalLibraryDirectories", - "LIBPATH:", "Additional Library Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IgnoreSpecificDefaultLibraries", - "NODEFAULTLIB:", "Ignore Specific Default Libraries", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "RemoveObjects", "REMOVE:", "Remove Objects", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue }, - { "ModuleDefinitionFile", "DEF:", "Module Definition File Name", "", - cmVS7FlagTable::UserValue }, - { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "", - cmVS7FlagTable::UserValue }, - { "DisplayLibrary", "LIST:", "Display Library to standard output", "", - cmVS7FlagTable::UserValue }, - // Skip [MinimumRequiredVersion] - no command line Switch. - { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue }, - // Skip [AdditionalOptions] - no command line Switch. - // Skip [TrackerLogDirectory] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS11LinkFlagTable.h b/Source/cmVS11LinkFlagTable.h deleted file mode 100644 index 53f11392f..000000000 --- a/Source/cmVS11LinkFlagTable.h +++ /dev/null @@ -1,272 +0,0 @@ -static cmVS7FlagTable cmVS11LinkFlagTable[] = { - - // Enum Properties - { "ShowProgress", "", "Not Set", "NotSet", 0 }, - { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose", - 0 }, - { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib", - 0 }, - { "ShowProgress", "VERBOSE:ICF", - "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 }, - { "ShowProgress", "VERBOSE:REF", - "About data removed during optimized linking", "LinkVerboseREF", 0 }, - { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH", - "LinkVerboseSAFESEH", 0 }, - { "ShowProgress", "VERBOSE:CLR", - "About linker activity related to managed code", "LinkVerboseCLR", 0 }, - - { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 }, - { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only", - "MultiplyDefinedSymbolOnly", 0 }, - { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only", - "UndefinedSymbolOnly", 0 }, - - { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only", - "X86Image", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only", - "X64Image", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", - "ItaniumImage", 0 }, - - // correct flags for uac should be /MANIFESTUAC, but some projects already - // use this bug to access uac field, so keep these for compatibility - { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, - { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", - "HighestAvailable", 0 }, - { "UACExecutionLevel", "level='requireAdministrator'", - "requireAdministrator", "RequireAdministrator", 0 }, - - { "SubSystem", "", "Not Set", "NotSet", 0 }, - { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 }, - { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application", - "EFI Application", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", - "EFI Boot Service Driver", "EFI Boot Service Driver", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime", - 0 }, - { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 }, - - { "Driver", "", "Not Set", "NotSet", 0 }, - { "Driver", "Driver", "Driver", "Driver", 0 }, - { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 }, - { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 }, - - { "LinkTimeCodeGeneration", "", "Default", "Default", 0 }, - { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation", - "UseLinkTimeCodeGeneration", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGInstrument", - "Profile Guided Optimization - Instrument", "PGInstrument", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGOptimize", - "Profile Guided Optimization - Optimization", "PGOptimization", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGUpdate", - "Profile Guided Optimization - Update", "PGUpdate", 0 }, - - { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 }, - { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 }, - - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 }, - - { "TargetMachine", "", "Not Set", "NotSet", 0 }, - { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 }, - { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 }, - { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 }, - { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 }, - { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 }, - { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU", - 0 }, - { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16", - "MachineMIPSFPU16", 0 }, - { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 }, - { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 }, - { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 }, - { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 }, - - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute", - "MTAThreadingAttribute", 0 }, - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute", - "STAThreadingAttribute", 0 }, - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE", - "Default threading attribute", "DefaultThreadingAttribute", 0 }, - - { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage", - 0 }, - { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image", - "ForcePureILImage", 0 }, - { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image", - "ForceSafeILImage", 0 }, - { "CLRImageType", "", "Default image type", "Default", 0 }, - - { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 }, - { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 }, - { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 }, - { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 }, - - { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately", - "PromptImmediately", 0 }, - { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login", - "QueueForNextLogin", 0 }, - { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report", - "SendErrorReport", 0 }, - { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report", - "NoErrorReport", 0 }, - - { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 }, - { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled", - 0 }, - { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only", - "SystemDlls", 0 }, - - // Bool Properties - { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 }, - { "LinkIncremental", "INCREMENTAL", "", "true", 0 }, - { "SuppressStartupBanner", "NOLOGO", "", "true", 0 }, - { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 }, - { "LinkStatus", "LTCG:STATUS", "", "true", 0 }, - { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 }, - { "PreventDllBinding", "ALLOWBIND", "", "true", 0 }, - { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 }, - { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 }, - { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 }, - { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, - { "GenerateManifest", "MANIFEST", "", "true", 0 }, - { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, - - // correct flags for uac should be /MANIFESTUAC, but some projects already - // use this bug to access uac field, so keep these for compatibility - { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, - { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, - - { "ManifestEmbed", "manifest:embed", "", "true", 0 }, - { "GenerateDebugInformation", "DEBUG", "", "true", - cmVS7FlagTable::CaseInsensitive }, - { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 }, - { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 }, - { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 }, - { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 }, - { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 }, - { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 }, - { "TerminalServerAware", "TSAWARE", "", "true", 0 }, - { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 }, - { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 }, - { "OptimizeReferences", "OPT:NOREF", "", "false", 0 }, - { "OptimizeReferences", "OPT:REF", "", "true", 0 }, - { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 }, - { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 }, - { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 }, - { "AppContainer", "APPCONTAINER", "", "true", 0 }, - { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 }, - { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 }, - { "NoEntryPoint", "NOENTRY", "", "true", 0 }, - { "SetChecksum", "RELEASE", "", "true", 0 }, - { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 }, - { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 }, - { "FixedBaseAddress", "FIXED:NO", "", "false", 0 }, - { "FixedBaseAddress", "FIXED", "", "true", 0 }, - { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 }, - { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 }, - { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 }, - { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 }, - { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 }, - { "Profile", "PROFILE", "", "true", 0 }, - { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 }, - { "LinkDelaySign", "DELAYSIGN", "", "true", 0 }, - { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 }, - { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 }, - { "DetectOneDefinitionRule", "ODR", "", "true", 0 }, - { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 }, - { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 }, - { "LinkDLL", "DLL", "", "true", 0 }, - - // Bool Properties With Argument - { "EnableUAC", "MANIFESTUAC:", "", "", - cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SpaceAppendable }, - { "GenerateMapFile", "MAP", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "MapFileName", "MAP:", "Generate Map File", "", - cmVS7FlagTable::UserValueRequired }, - - // String List Properties - { "AdditionalLibraryDirectories", - "LIBPATH:", "Additional Library Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - // Skip [AdditionalDependencies] - no command line Switch. - { "IgnoreSpecificDefaultLibraries", - "NODEFAULTLIB:", "Ignore Specific Default Libraries", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "EmbedManagedResourceFile", - "ASSEMBLYRESOURCE:", "Embed Managed Resource File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AdditionalManifestDependencies", - "MANIFESTDEPENDENCY:", "Additional Manifest Dependencies", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ManifestInput", "manifestinput:", "Manifest Input", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue }, - { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue }, - { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "", - cmVS7FlagTable::UserValue }, - { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "", - cmVS7FlagTable::UserValue }, - // Skip [TrackerLogDirectory] - no command line Switch. - { "ModuleDefinitionFile", "DEF:", "Module Definition File", "", - cmVS7FlagTable::UserValue }, - { "ManifestFile", "ManifestFile:", "Manifest File", "", - cmVS7FlagTable::UserValue }, - { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "", - cmVS7FlagTable::UserValue }, - { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "", - cmVS7FlagTable::UserValue }, - // Skip [MapFileName] - no command line Switch. - // Skip [MinimumRequiredVersion] - no command line Switch. - { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "", - cmVS7FlagTable::UserValue }, - // Skip [HeapCommitSize] - no command line Switch. - { "StackReserveSize", "STACK:", "Stack Reserve Size", "", - cmVS7FlagTable::UserValue }, - // Skip [StackCommitSize] - no command line Switch. - { "FunctionOrder", "ORDER:@", "Function Order", "", - cmVS7FlagTable::UserValue }, - { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "", - cmVS7FlagTable::UserValue }, - { "MidlCommandFile", "MIDL:@", "MIDL Commands", "", - cmVS7FlagTable::UserValue }, - { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "", - cmVS7FlagTable::UserValue }, - { "TypeLibraryFile", "TLBOUT:", "Type Library", "", - cmVS7FlagTable::UserValue }, - { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "", - cmVS7FlagTable::UserValue }, - { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File", - "", cmVS7FlagTable::UserValue }, - { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:", - "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue }, - { "EntryPointSymbol", "ENTRY:", "Entry Point", "", - cmVS7FlagTable::UserValue }, - { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue }, - { "ImportLibrary", "IMPLIB:", "Import Library", "", - cmVS7FlagTable::UserValue }, - { "MergeSections", "MERGE:", "Merge Sections", "", - cmVS7FlagTable::UserValue }, - { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue }, - { "KeyContainer", "KEYCONTAINER:", "Key Container", "", - cmVS7FlagTable::UserValue }, - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS11MASMFlagTable.h b/Source/cmVS11MASMFlagTable.h deleted file mode 100644 index fdf8239da..000000000 --- a/Source/cmVS11MASMFlagTable.h +++ /dev/null @@ -1,76 +0,0 @@ -static cmVS7FlagTable cmVS11MASMFlagTable[] = { - - // Enum Properties - { "PreserveIdentifierCase", "", "Default", "0", 0 }, - { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1", - 0 }, - { "PreserveIdentifierCase", "Cu", - "Maps all identifiers to upper case. (/Cu)", "2", 0 }, - { "PreserveIdentifierCase", "Cx", - "Preserves case in public and extern symbols. (/Cx)", "3", 0 }, - - { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 }, - { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 }, - { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 }, - { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 }, - - { "PackAlignmentBoundary", "", "Default", "0", 0 }, - { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, - { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, - { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, - { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, - { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 }, - - { "CallingConvention", "", "Default", "0", 0 }, - { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1", - 0 }, - { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2", - 0 }, - { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 }, - - { "ErrorReporting", "errorReport:prompt", - "Prompt to send report immediately (/errorReport:prompt)", "0", 0 }, - { "ErrorReporting", "errorReport:queue", - "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 }, - { "ErrorReporting", "errorReport:send", - "Automatically send report (/errorReport:send)", "2", 0 }, - { "ErrorReporting", "errorReport:none", - "Do not send report (/errorReport:none)", "3", 0 }, - - // Bool Properties - { "NoLogo", "nologo", "", "true", 0 }, - { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 }, - { "ListAllAvailableInformation", "Sa", "", "true", 0 }, - { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 }, - { "AddFirstPassListing", "Sf", "", "true", 0 }, - { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 }, - { "DisableSymbolTable", "Sn", "", "true", 0 }, - { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 }, - { "TreatWarningsAsErrors", "WX", "", "true", 0 }, - { "MakeAllSymbolsPublic", "Zf", "", "true", 0 }, - { "GenerateDebugInformation", "Zi", "", "true", 0 }, - { "EnableMASM51Compatibility", "Zm", "", "true", 0 }, - { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 }, - - // Bool Properties With Argument - - // String List Properties - { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IncludePaths", "I", "Include Paths", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "BrowseFile", "FR", "Generate Browse Information File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - // Skip [AdditionalDependencies] - no command line Switch. - - // String Properties - // Skip [Inputs] - no command line Switch. - { "ObjectFileName", "Fo", "Object File Name", "", - cmVS7FlagTable::UserValue }, - { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "", - cmVS7FlagTable::UserValue }, - // Skip [CommandLineTemplate] - no command line Switch. - // Skip [ExecutionDescription] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS11RCFlagTable.h b/Source/cmVS11RCFlagTable.h deleted file mode 100644 index 4997fe115..000000000 --- a/Source/cmVS11RCFlagTable.h +++ /dev/null @@ -1,7 +0,0 @@ -static cmVS7FlagTable cmVS11RCFlagTable[] = { - // Bool Properties - { "NullTerminateStrings", "n", "", "true", 0 }, - { "SuppressStartupBanner", "nologo", "", "true", 0 }, - - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS12CLFlagTable.h b/Source/cmVS12CLFlagTable.h deleted file mode 100644 index a4f251808..000000000 --- a/Source/cmVS12CLFlagTable.h +++ /dev/null @@ -1,222 +0,0 @@ -static cmVS7FlagTable cmVS12CLFlagTable[] = { - - // Enum Properties - { "DebugInformationFormat", "", "None", "None", 0 }, - { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 }, - { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 }, - { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue", - "EditAndContinue", 0 }, - - { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 }, - { "WarningLevel", "W1", "Level1", "Level1", 0 }, - { "WarningLevel", "W2", "Level2", "Level2", 0 }, - { "WarningLevel", "W3", "Level3", "Level3", 0 }, - { "WarningLevel", "W4", "Level4", "Level4", 0 }, - { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 }, - - { "Optimization", "", "Custom", "Custom", 0 }, - { "Optimization", "Od", "Disabled", "Disabled", 0 }, - { "Optimization", "O1", "Minimize Size", "MinSpace", 0 }, - { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 }, - { "Optimization", "Ox", "Full Optimization", "Full", 0 }, - - { "InlineFunctionExpansion", "", "Default", "Default", 0 }, - { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 }, - { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline", - 0 }, - { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 }, - - { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 }, - { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 }, - { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 }, - - { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 }, - { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 }, - { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow", - 0 }, - { "ExceptionHandling", "", "No", "false", 0 }, - - { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck", - 0 }, - { "BasicRuntimeChecks", "RTCu", "Uninitialized variables", - "UninitializedLocalUsageCheck", 0 }, - { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)", - "EnableFastChecks", 0 }, - { "BasicRuntimeChecks", "", "Default", "Default", 0 }, - - { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 }, - { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 }, - { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 }, - { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL", - "MultiThreadedDebugDLL", 0 }, - - { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 }, - { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 }, - { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 }, - { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 }, - { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 }, - { "StructMemberAlignment", "", "Default", "Default", 0 }, - - { "BufferSecurityCheck", "GS-", "Disable Security Check", "false", 0 }, - { "BufferSecurityCheck", "GS", "Enable Security Check", "true", 0 }, - - { "EnableEnhancedInstructionSet", "arch:SSE", "Streaming SIMD Extensions", - "StreamingSIMDExtensions", 0 }, - { "EnableEnhancedInstructionSet", "arch:SSE2", "Streaming SIMD Extensions 2", - "StreamingSIMDExtensions2", 0 }, - { "EnableEnhancedInstructionSet", "arch:AVX", "Advanced Vector Extensions", - "AdvancedVectorExtensions", 0 }, - { "EnableEnhancedInstructionSet", "arch:IA32", "No Enhanced Instructions", - "NoExtensions", 0 }, - { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 }, - - { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 }, - { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 }, - { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 }, - - { "PrecompiledHeader", "Yc", "Create", "Create", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "PrecompiledHeader", "Yu", "Use", "Use", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "PrecompiledHeader", "Y-", "Not Using Precompiled Headers", "NotUsing", - 0 }, - - { "AssemblerOutput", "", "No Listing", "NoListing", 0 }, - { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 }, - { "AssemblerOutput", "FAc", "Assembly With Machine Code", - "AssemblyAndMachineCode", 0 }, - { "AssemblerOutput", "FAs", "Assembly With Source Code", - "AssemblyAndSourceCode", 0 }, - { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 }, - - { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 }, - { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 }, - { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 }, - { "CallingConvention", "Gv", "__vectorcall", "VectorCall", 0 }, - - { "CompileAs", "", "Default", "Default", 0 }, - { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 }, - { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 }, - - { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 }, - { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt", - 0 }, - { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue", - 0 }, - { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 }, - - { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 }, - { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 }, - { "CompileAsManaged", "clr:pure", - "Pure MSIL Common Language RunTime Support", "Pure", 0 }, - { "CompileAsManaged", "clr:safe", - "Safe MSIL Common Language RunTime Support", "Safe", 0 }, - { "CompileAsManaged", "clr:oldSyntax", - "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 }, - - // Bool Properties - { "CompileAsWinRT", "ZW", "", "true", 0 }, - { "WinRTNoStdLib", "ZW:nostdlib", "", "true", 0 }, - { "SuppressStartupBanner", "nologo", "", "true", 0 }, - { "TreatWarningAsError", "WX-", "", "false", 0 }, - { "TreatWarningAsError", "WX", "", "true", 0 }, - { "SDLCheck", "sdl-", "", "false", 0 }, - { "SDLCheck", "sdl", "", "true", 0 }, - { "IntrinsicFunctions", "Oi", "", "true", 0 }, - { "OmitFramePointers", "Oy-", "", "false", 0 }, - { "OmitFramePointers", "Oy", "", "true", 0 }, - { "EnableFiberSafeOptimizations", "GT", "", "true", 0 }, - { "WholeProgramOptimization", "GL", "", "true", 0 }, - { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 }, - { "IgnoreStandardIncludePath", "X", "", "true", 0 }, - { "PreprocessToFile", "P", "", "true", 0 }, - { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 }, - { "PreprocessKeepComments", "C", "", "true", 0 }, - { "StringPooling", "GF-", "", "false", 0 }, - { "StringPooling", "GF", "", "true", 0 }, - { "MinimalRebuild", "Gm-", "", "false", 0 }, - { "MinimalRebuild", "Gm", "", "true", 0 }, - { "SmallerTypeCheck", "RTCc", "", "true", 0 }, - { "FunctionLevelLinking", "Gy-", "", "false", 0 }, - { "FunctionLevelLinking", "Gy", "", "true", 0 }, - { "EnableParallelCodeGeneration", "Qpar-", "", "false", 0 }, - { "EnableParallelCodeGeneration", "Qpar", "", "true", 0 }, - { "FloatingPointExceptions", "fp:except-", "", "false", 0 }, - { "FloatingPointExceptions", "fp:except", "", "true", 0 }, - { "CreateHotpatchableImage", "hotpatch", "", "true", 0 }, - { "DisableLanguageExtensions", "Za", "", "true", 0 }, - { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 }, - { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 }, - { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 }, - { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 }, - { "RuntimeTypeInfo", "GR-", "", "false", 0 }, - { "RuntimeTypeInfo", "GR", "", "true", 0 }, - { "OpenMPSupport", "openmp-", "", "false", 0 }, - { "OpenMPSupport", "openmp", "", "true", 0 }, - { "ExpandAttributedSource", "Fx", "", "true", 0 }, - { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 }, - { "ShowIncludes", "showIncludes", "", "true", 0 }, - { "EnablePREfast", "analyze-", "", "false", 0 }, - { "EnablePREfast", "analyze", "", "true", 0 }, - { "UseFullPaths", "FC", "", "true", 0 }, - { "OmitDefaultLibName", "Zl", "", "true", 0 }, - - // Bool Properties With Argument - { "MultiProcessorCompilation", "MP", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "ProcessorNumber", "MP", "Multi-processor Compilation", "", - cmVS7FlagTable::UserValueRequired }, - { "GenerateXMLDocumentationFiles", "doc", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "", - cmVS7FlagTable::UserValueRequired }, - { "BrowseInformation", "FR", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "BrowseInformationFile", "FR", "Enable Browse Information", "", - cmVS7FlagTable::UserValueRequired }, - - // String List Properties - { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AdditionalUsingDirectories", "AI", "Additional #using Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "UndefinePreprocessorDefinitions", "U", - "Undefine Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForcedIncludeFiles", "FI", "Forced Include File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForcedUsingFiles", "FU", "Forced #using File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "PREfastLog", "analyze:log", "Code Analysis Log", "", - cmVS7FlagTable::UserFollowing }, - { "PREfastAdditionalPlugins", "analyze:plugin", - "Additional Code Analysis Native plugins", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - // Skip [TrackerLogDirectory] - no command line Switch. - { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "", - cmVS7FlagTable::UserValue }, - { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired }, - { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired }, - { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "", - cmVS7FlagTable::UserValue }, - { "AssemblerListingLocation", "Fa", "ASM List Location", "", - cmVS7FlagTable::UserValue }, - { "ObjectFileName", "Fo", "Object File Name", "", - cmVS7FlagTable::UserValue }, - { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "", - cmVS7FlagTable::UserValue }, - // Skip [XMLDocumentationFileName] - no command line Switch. - // Skip [BrowseInformationFile] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS12CSharpFlagTable.h b/Source/cmVS12CSharpFlagTable.h deleted file mode 100644 index 0370499db..000000000 --- a/Source/cmVS12CSharpFlagTable.h +++ /dev/null @@ -1,121 +0,0 @@ -static cmVS7FlagTable cmVS12CSharpFlagTable[] = { - { "ProjectName", "out:", "", "", cmIDEFlagTable::UserValueRequired }, - - { "OutputType", "target:exe", "", "Exe", 0 }, - { "OutputType", "target:winexe", "", "Winexe", 0 }, - { "OutputType", "target:library", "", "Library", 0 }, - { "OutputType", "target:module", "", "Module", 0 }, - - { "DocumentationFile", "doc", "", "", cmIDEFlagTable::UserValueRequired }, - - { "Platform", "platform:x86", "", "x86", 0 }, - { "Platform", "platform:Itanium", "", "Itanium", 0 }, - { "Platform", "platform:x64", "", "x64", 0 }, - { "Platform", "platform:arm", "", "arm", 0 }, - { "Platform", "platform:anycpu32bitpreferred", "", "anycpu32bitpreferred", - 0 }, - { "Platform", "platform:anycpu", "", "anycpu", 0 }, - - { "References", "reference:", "mit alias", "", 0 }, - { "References", "reference:", "dateiliste", "", 0 }, - { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable }, - { "", "link", "", "", 0 }, - - { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired }, - { "ApplicationIcon", "win32icon:", "", "", - cmIDEFlagTable::UserValueRequired }, - - { "ApplicationManifest", "win32manifest:", "", "", - cmIDEFlagTable::UserValueRequired }, - - { "NoWin32Manifest", "nowin32manifest", "", "true", 0 }, - - { "DefineDebug", "debug", "", "true", cmIDEFlagTable::Continue }, - - { "DebugSymbols", "debug", "", "true", 0 }, - { "DebugSymbols", "debug-", "", "false", 0 }, - { "DebugSymbols", "debug+", "", "true", 0 }, - - { "DebugType", "debug:none", "", "none", 0 }, - { "DebugType", "debug:full", "", "full", 0 }, - { "DebugType", "debug:pdbonly", "", "pdbonly", 0 }, - - { "Optimize", "optimize", "", "true", 0 }, - { "Optimize", "optimize-", "", "false", 0 }, - { "Optimize", "optimize+", "", "true", 0 }, - - { "TreatWarningsAsErrors", "warnaserror", "", "true", 0 }, - { "TreatWarningsAsErrors", "warnaserror-", "", "false", 0 }, - { "TreatWarningsAsErrors", "warnaserror+", "", "true", 0 }, - - { "WarningsAsErrors", "warnaserror", "", "", 0 }, - { "WarningsAsErrors", "warnaserror-", "", "", 0 }, - { "WarningsAsErrors", "warnaserror+", "", "", 0 }, - - { "WarningLevel", "warn:0", "", "0", 0 }, - { "WarningLevel", "warn:1", "", "1", 0 }, - { "WarningLevel", "warn:2", "", "2", 0 }, - { "WarningLevel", "warn:3", "", "3", 0 }, - { "WarningLevel", "warn:4", "", "4", 0 }, - { "DisabledWarnings", "nowarn", "", "", 0 }, - - { "CheckForOverflowUnderflow", "checked", "", "true", 0 }, - { "CheckForOverflowUnderflow", "checked-", "", "false", 0 }, - { "CheckForOverflowUnderflow", "checked+", "", "true", 0 }, - - { "AllowUnsafeBlocks", "unsafe", "", "true", 0 }, - { "AllowUnsafeBlocks", "unsafe-", "", "false", 0 }, - { "AllowUnsafeBlocks", "unsafe+", "", "true", 0 }, - - { "DefineConstants", "define:", "", "", - cmIDEFlagTable::SemicolonAppendable | cmIDEFlagTable::UserValue }, - - { "LangVersion", "langversion:ISO-1", "", "ISO-1", 0 }, - { "LangVersion", "langversion:ISO-2", "", "ISO-2", 0 }, - { "LangVersion", "langversion:3", "", "3", 0 }, - { "LangVersion", "langversion:4", "", "4", 0 }, - { "LangVersion", "langversion:5", "", "5", 0 }, - { "LangVersion", "langversion:6", "", "6", 0 }, - { "LangVersion", "langversion:default", "", "default", 0 }, - - { "DelaySign", "delaysign", "", "true", 0 }, - { "DelaySign", "delaysign-", "", "false", 0 }, - { "DelaySign", "delaysign+", "", "true", 0 }, - - { "AssemblyOriginatorKeyFile", "keyfile", "", "", 0 }, - - { "KeyContainerName", "keycontainer", "", "", 0 }, - - { "NoLogo", "nologo", "", "", 0 }, - - { "NoConfig", "noconfig", "", "true", 0 }, - - { "BaseAddress", "baseaddress:", "", "", 0 }, - - { "CodePage", "codepage", "", "", 0 }, - - { "Utf8Output", "utf8output", "", "", 0 }, - - { "MainEntryPoint", "main:", "", "", 0 }, - - { "GenerateFullPaths", "fullpaths", "", "true", 0 }, - - { "FileAlignment", "filealign", "", "", 0 }, - - { "PdbFile", "pdb:", "", "", 0 }, - - { "NoStandardLib", "nostdlib", "", "true", 0 }, - { "NoStandardLib", "nostdlib-", "", "false", 0 }, - { "NoStandardLib", "nostdlib+", "", "true", 0 }, - - { "SubsystemVersion", "subsystemversion", "", "", 0 }, - - { "AdditionalLibPaths", "lib:", "", "", 0 }, - - { "ErrorReport", "errorreport:none", "Do Not Send Report", "none", 0 }, - { "ErrorReport", "errorreport:prompt", "Prompt Immediately", "prompt", 0 }, - { "ErrorReport", "errorreport:queue", "Queue For Next Login", "queue", 0 }, - { "ErrorReport", "errorreport:send", "Send Automatically", "send", 0 }, - - { 0, 0, 0, 0, 0 }, -}; diff --git a/Source/cmVS12LibFlagTable.h b/Source/cmVS12LibFlagTable.h deleted file mode 100644 index 2229b97da..000000000 --- a/Source/cmVS12LibFlagTable.h +++ /dev/null @@ -1,76 +0,0 @@ -static cmVS7FlagTable cmVS12LibFlagTable[] = { - - // Enum Properties - { "ErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately", - "PromptImmediately", 0 }, - { "ErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login", - "QueueForNextLogin", 0 }, - { "ErrorReporting", "ERRORREPORT:SEND", "Send Error Report", - "SendErrorReport", 0 }, - { "ErrorReporting", "ERRORREPORT:NONE", "No Error Report", "NoErrorReport", - 0 }, - - { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 }, - { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 }, - { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 }, - { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 }, - { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 }, - { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU", - 0 }, - { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16", - "MachineMIPSFPU16", 0 }, - { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 }, - { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 }, - { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 }, - { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 }, - - { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 }, - { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application", - "EFI Application", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", - "EFI Boot Service Driver", "EFI Boot Service Driver", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime", - 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWSCE", "WindowsCE", "WindowsCE", 0 }, - { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 }, - - // Bool Properties - { "SuppressStartupBanner", "NOLOGO", "", "true", 0 }, - { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 }, - { "TreatLibWarningAsErrors", "WX:NO", "", "false", 0 }, - { "TreatLibWarningAsErrors", "WX", "", "true", 0 }, - { "Verbose", "VERBOSE", "", "true", 0 }, - { "LinkTimeCodeGeneration", "LTCG", "", "true", 0 }, - - // Bool Properties With Argument - - // String List Properties - // Skip [AdditionalDependencies] - no command line Switch. - { "AdditionalLibraryDirectories", - "LIBPATH:", "Additional Library Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IgnoreSpecificDefaultLibraries", - "NODEFAULTLIB:", "Ignore Specific Default Libraries", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "RemoveObjects", "REMOVE:", "Remove Objects", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue }, - { "ModuleDefinitionFile", "DEF:", "Module Definition File Name", "", - cmVS7FlagTable::UserValue }, - { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "", - cmVS7FlagTable::UserValue }, - { "DisplayLibrary", "LIST:", "Display Library to standard output", "", - cmVS7FlagTable::UserValue }, - // Skip [MinimumRequiredVersion] - no command line Switch. - { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue }, - // Skip [AdditionalOptions] - no command line Switch. - // Skip [TrackerLogDirectory] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS12LinkFlagTable.h b/Source/cmVS12LinkFlagTable.h deleted file mode 100644 index ddc3ea191..000000000 --- a/Source/cmVS12LinkFlagTable.h +++ /dev/null @@ -1,272 +0,0 @@ -static cmVS7FlagTable cmVS12LinkFlagTable[] = { - - // Enum Properties - { "ShowProgress", "", "Not Set", "NotSet", 0 }, - { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose", - 0 }, - { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib", - 0 }, - { "ShowProgress", "VERBOSE:ICF", - "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 }, - { "ShowProgress", "VERBOSE:REF", - "About data removed during optimized linking", "LinkVerboseREF", 0 }, - { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH", - "LinkVerboseSAFESEH", 0 }, - { "ShowProgress", "VERBOSE:CLR", - "About linker activity related to managed code", "LinkVerboseCLR", 0 }, - - { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 }, - { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only", - "MultiplyDefinedSymbolOnly", 0 }, - { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only", - "UndefinedSymbolOnly", 0 }, - - { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only", - "X86Image", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only", - "X64Image", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", - "ItaniumImage", 0 }, - - // correct flags for uac should be /MANIFESTUAC, but some projects already - // use this bug to access uac field, so keep these for compatibility - { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, - { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", - "HighestAvailable", 0 }, - { "UACExecutionLevel", "level='requireAdministrator'", - "requireAdministrator", "RequireAdministrator", 0 }, - - { "SubSystem", "", "Not Set", "NotSet", 0 }, - { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 }, - { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application", - "EFI Application", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", - "EFI Boot Service Driver", "EFI Boot Service Driver", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime", - 0 }, - { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 }, - - { "Driver", "", "Not Set", "NotSet", 0 }, - { "Driver", "Driver", "Driver", "Driver", 0 }, - { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 }, - { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 }, - - { "LinkTimeCodeGeneration", "", "Default", "Default", 0 }, - { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation", - "UseLinkTimeCodeGeneration", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGInstrument", - "Profile Guided Optimization - Instrument", "PGInstrument", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGOptimize", - "Profile Guided Optimization - Optimization", "PGOptimization", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGUpdate", - "Profile Guided Optimization - Update", "PGUpdate", 0 }, - - { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 }, - { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 }, - - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 }, - - { "TargetMachine", "", "Not Set", "NotSet", 0 }, - { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 }, - { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 }, - { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 }, - { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 }, - { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 }, - { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU", - 0 }, - { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16", - "MachineMIPSFPU16", 0 }, - { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 }, - { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 }, - { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 }, - { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 }, - - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute", - "MTAThreadingAttribute", 0 }, - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute", - "STAThreadingAttribute", 0 }, - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE", - "Default threading attribute", "DefaultThreadingAttribute", 0 }, - - { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage", - 0 }, - { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image", - "ForcePureILImage", 0 }, - { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image", - "ForceSafeILImage", 0 }, - { "CLRImageType", "", "Default image type", "Default", 0 }, - - { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 }, - { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 }, - { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 }, - { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 }, - - { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately", - "PromptImmediately", 0 }, - { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login", - "QueueForNextLogin", 0 }, - { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report", - "SendErrorReport", 0 }, - { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report", - "NoErrorReport", 0 }, - - { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 }, - { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled", - 0 }, - { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only", - "SystemDlls", 0 }, - - // Bool Properties - { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 }, - { "LinkIncremental", "INCREMENTAL", "", "true", 0 }, - { "SuppressStartupBanner", "NOLOGO", "", "true", 0 }, - { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 }, - { "LinkStatus", "LTCG:STATUS", "", "true", 0 }, - { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 }, - { "PreventDllBinding", "ALLOWBIND", "", "true", 0 }, - { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 }, - { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 }, - { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 }, - { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, - { "GenerateManifest", "MANIFEST", "", "true", 0 }, - { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, - - // correct flags for uac should be /MANIFESTUAC, but some projects already - // use this bug to access uac field, so keep these for compatibility - { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, - { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, - - { "ManifestEmbed", "manifest:embed", "", "true", 0 }, - { "GenerateDebugInformation", "DEBUG", "", "true", - cmVS7FlagTable::CaseInsensitive }, - { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 }, - { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 }, - { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 }, - { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 }, - { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 }, - { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 }, - { "TerminalServerAware", "TSAWARE", "", "true", 0 }, - { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 }, - { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 }, - { "OptimizeReferences", "OPT:NOREF", "", "false", 0 }, - { "OptimizeReferences", "OPT:REF", "", "true", 0 }, - { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 }, - { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 }, - { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 }, - { "AppContainer", "APPCONTAINER", "", "true", 0 }, - { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 }, - { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 }, - { "NoEntryPoint", "NOENTRY", "", "true", 0 }, - { "SetChecksum", "RELEASE", "", "true", 0 }, - { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 }, - { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 }, - { "FixedBaseAddress", "FIXED:NO", "", "false", 0 }, - { "FixedBaseAddress", "FIXED", "", "true", 0 }, - { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 }, - { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 }, - { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 }, - { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 }, - { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 }, - { "Profile", "PROFILE", "", "true", 0 }, - { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 }, - { "LinkDelaySign", "DELAYSIGN", "", "true", 0 }, - { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 }, - { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 }, - { "DetectOneDefinitionRule", "ODR", "", "true", 0 }, - { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 }, - { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 }, - { "LinkDLL", "DLL", "", "true", 0 }, - - // Bool Properties With Argument - { "EnableUAC", "MANIFESTUAC:", "", "", - cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SpaceAppendable }, - { "GenerateMapFile", "MAP", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "MapFileName", "MAP:", "Generate Map File", "", - cmVS7FlagTable::UserValueRequired }, - - // String List Properties - { "AdditionalLibraryDirectories", - "LIBPATH:", "Additional Library Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - // Skip [AdditionalDependencies] - no command line Switch. - { "IgnoreSpecificDefaultLibraries", - "NODEFAULTLIB:", "Ignore Specific Default Libraries", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "EmbedManagedResourceFile", - "ASSEMBLYRESOURCE:", "Embed Managed Resource File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AdditionalManifestDependencies", - "MANIFESTDEPENDENCY:", "Additional Manifest Dependencies", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ManifestInput", "manifestinput:", "Manifest Input", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue }, - { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue }, - { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "", - cmVS7FlagTable::UserValue }, - { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "", - cmVS7FlagTable::UserValue }, - // Skip [TrackerLogDirectory] - no command line Switch. - { "ModuleDefinitionFile", "DEF:", "Module Definition File", "", - cmVS7FlagTable::UserValue }, - { "ManifestFile", "ManifestFile:", "Manifest File", "", - cmVS7FlagTable::UserValue }, - { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "", - cmVS7FlagTable::UserValue }, - { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "", - cmVS7FlagTable::UserValue }, - // Skip [MapFileName] - no command line Switch. - // Skip [MinimumRequiredVersion] - no command line Switch. - { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "", - cmVS7FlagTable::UserValue }, - // Skip [HeapCommitSize] - no command line Switch. - { "StackReserveSize", "STACK:", "Stack Reserve Size", "", - cmVS7FlagTable::UserValue }, - // Skip [StackCommitSize] - no command line Switch. - { "FunctionOrder", "ORDER:@", "Function Order", "", - cmVS7FlagTable::UserValue }, - { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "", - cmVS7FlagTable::UserValue }, - { "MidlCommandFile", "MIDL:@", "MIDL Commands", "", - cmVS7FlagTable::UserValue }, - { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "", - cmVS7FlagTable::UserValue }, - { "TypeLibraryFile", "TLBOUT:", "Type Library", "", - cmVS7FlagTable::UserValue }, - { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "", - cmVS7FlagTable::UserValue }, - { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File", - "", cmVS7FlagTable::UserValue }, - { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:", - "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue }, - { "EntryPointSymbol", "ENTRY:", "Entry Point", "", - cmVS7FlagTable::UserValue }, - { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue }, - { "ImportLibrary", "IMPLIB:", "Import Library", "", - cmVS7FlagTable::UserValue }, - { "MergeSections", "MERGE:", "Merge Sections", "", - cmVS7FlagTable::UserValue }, - { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue }, - { "KeyContainer", "KEYCONTAINER:", "Key Container", "", - cmVS7FlagTable::UserValue }, - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS12MASMFlagTable.h b/Source/cmVS12MASMFlagTable.h deleted file mode 100644 index acc0d48e1..000000000 --- a/Source/cmVS12MASMFlagTable.h +++ /dev/null @@ -1,76 +0,0 @@ -static cmVS7FlagTable cmVS12MASMFlagTable[] = { - - // Enum Properties - { "PreserveIdentifierCase", "", "Default", "0", 0 }, - { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1", - 0 }, - { "PreserveIdentifierCase", "Cu", - "Maps all identifiers to upper case. (/Cu)", "2", 0 }, - { "PreserveIdentifierCase", "Cx", - "Preserves case in public and extern symbols. (/Cx)", "3", 0 }, - - { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 }, - { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 }, - { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 }, - { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 }, - - { "PackAlignmentBoundary", "", "Default", "0", 0 }, - { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, - { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, - { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, - { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, - { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 }, - - { "CallingConvention", "", "Default", "0", 0 }, - { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1", - 0 }, - { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2", - 0 }, - { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 }, - - { "ErrorReporting", "errorReport:prompt", - "Prompt to send report immediately (/errorReport:prompt)", "0", 0 }, - { "ErrorReporting", "errorReport:queue", - "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 }, - { "ErrorReporting", "errorReport:send", - "Automatically send report (/errorReport:send)", "2", 0 }, - { "ErrorReporting", "errorReport:none", - "Do not send report (/errorReport:none)", "3", 0 }, - - // Bool Properties - { "NoLogo", "nologo", "", "true", 0 }, - { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 }, - { "ListAllAvailableInformation", "Sa", "", "true", 0 }, - { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 }, - { "AddFirstPassListing", "Sf", "", "true", 0 }, - { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 }, - { "DisableSymbolTable", "Sn", "", "true", 0 }, - { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 }, - { "TreatWarningsAsErrors", "WX", "", "true", 0 }, - { "MakeAllSymbolsPublic", "Zf", "", "true", 0 }, - { "GenerateDebugInformation", "Zi", "", "true", 0 }, - { "EnableMASM51Compatibility", "Zm", "", "true", 0 }, - { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 }, - - // Bool Properties With Argument - - // String List Properties - { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IncludePaths", "I", "Include Paths", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "BrowseFile", "FR", "Generate Browse Information File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - // Skip [AdditionalDependencies] - no command line Switch. - - // String Properties - // Skip [Inputs] - no command line Switch. - { "ObjectFileName", "Fo", "Object File Name", "", - cmVS7FlagTable::UserValue }, - { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "", - cmVS7FlagTable::UserValue }, - // Skip [CommandLineTemplate] - no command line Switch. - // Skip [ExecutionDescription] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS12RCFlagTable.h b/Source/cmVS12RCFlagTable.h deleted file mode 100644 index a650f8522..000000000 --- a/Source/cmVS12RCFlagTable.h +++ /dev/null @@ -1,7 +0,0 @@ -static cmVS7FlagTable cmVS12RCFlagTable[] = { - // Bool Properties - { "NullTerminateStrings", "n", "", "true", 0 }, - { "SuppressStartupBanner", "nologo", "", "true", 0 }, - - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS140CLFlagTable.h b/Source/cmVS140CLFlagTable.h deleted file mode 100644 index 2b89042c8..000000000 --- a/Source/cmVS140CLFlagTable.h +++ /dev/null @@ -1,240 +0,0 @@ -static cmVS7FlagTable cmVS140CLFlagTable[] = { - - // Enum Properties - { "DebugInformationFormat", "", "None", "None", 0 }, - { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 }, - { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 }, - { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue", - "EditAndContinue", 0 }, - - { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 }, - { "WarningLevel", "W1", "Level1", "Level1", 0 }, - { "WarningLevel", "W2", "Level2", "Level2", 0 }, - { "WarningLevel", "W3", "Level3", "Level3", 0 }, - { "WarningLevel", "W4", "Level4", "Level4", 0 }, - { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 }, - - { "Optimization", "", "Custom", "Custom", 0 }, - { "Optimization", "Od", "Disabled", "Disabled", 0 }, - { "Optimization", "O1", "Minimize Size", "MinSpace", 0 }, - { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 }, - { "Optimization", "Ox", "Full Optimization", "Full", 0 }, - - { "InlineFunctionExpansion", "", "Default", "Default", 0 }, - { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 }, - { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline", - 0 }, - { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 }, - - { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 }, - { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 }, - { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 }, - - { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 }, - { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 }, - { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow", - 0 }, - { "ExceptionHandling", "", "No", "false", 0 }, - - { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck", - 0 }, - { "BasicRuntimeChecks", "RTCu", "Uninitialized variables", - "UninitializedLocalUsageCheck", 0 }, - { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)", - "EnableFastChecks", 0 }, - { "BasicRuntimeChecks", "", "Default", "Default", 0 }, - - { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 }, - { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 }, - { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 }, - { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL", - "MultiThreadedDebugDLL", 0 }, - - { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 }, - { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 }, - { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 }, - { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 }, - { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 }, - { "StructMemberAlignment", "", "Default", "Default", 0 }, - - { "BufferSecurityCheck", "GS-", "Disable Security Check", "false", 0 }, - { "BufferSecurityCheck", "GS", "Enable Security Check", "true", 0 }, - - { "EnableEnhancedInstructionSet", "arch:SSE", "Streaming SIMD Extensions", - "StreamingSIMDExtensions", 0 }, - { "EnableEnhancedInstructionSet", "arch:SSE2", "Streaming SIMD Extensions 2", - "StreamingSIMDExtensions2", 0 }, - { "EnableEnhancedInstructionSet", "arch:AVX", "Advanced Vector Extensions", - "AdvancedVectorExtensions", 0 }, - { "EnableEnhancedInstructionSet", "arch:AVX2", - "Advanced Vector Extensions 2", "AdvancedVectorExtensions2", 0 }, - { "EnableEnhancedInstructionSet", "arch:IA32", "No Enhanced Instructions", - "NoExtensions", 0 }, - { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 }, - - { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 }, - { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 }, - { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 }, - - { "PrecompiledHeader", "Yc", "Create", "Create", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "PrecompiledHeader", "Yu", "Use", "Use", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "PrecompiledHeader", "Y-", "Not Using Precompiled Headers", "NotUsing", - 0 }, - - { "AssemblerOutput", "", "No Listing", "NoListing", 0 }, - { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 }, - { "AssemblerOutput", "FAc", "Assembly With Machine Code", - "AssemblyAndMachineCode", 0 }, - { "AssemblerOutput", "FAs", "Assembly With Source Code", - "AssemblyAndSourceCode", 0 }, - { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 }, - - { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 }, - { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 }, - { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 }, - { "CallingConvention", "Gv", "__vectorcall", "VectorCall", 0 }, - - { "CompileAs", "", "Default", "Default", 0 }, - { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 }, - { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 }, - - { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 }, - { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt", - 0 }, - { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue", - 0 }, - { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 }, - - { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 }, - { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 }, - { "CompileAsManaged", "clr:pure", - "Pure MSIL Common Language RunTime Support", "Pure", 0 }, - { "CompileAsManaged", "clr:safe", - "Safe MSIL Common Language RunTime Support", "Safe", 0 }, - { "CompileAsManaged", "clr:oldSyntax", - "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 }, - - { "CppLanguageStandard", "", "Default", "Default", 0 }, - { "CppLanguageStandard", "std=c++98", "C++03", "c++98", 0 }, - { "CppLanguageStandard", "std=c++11", "C++11", "c++11", 0 }, - { "CppLanguageStandard", "std=c++1y", "C++14", "c++1y", 0 }, - { "CppLanguageStandard", "std=c++14", "C++14", "c++1y", 0 }, - { "CppLanguageStandard", "std=gnu++98", "C++03 (GNU Dialect)", "gnu++98", - 0 }, - { "CppLanguageStandard", "std=gnu++11", "C++11 (GNU Dialect)", "gnu++11", - 0 }, - { "CppLanguageStandard", "std=gnu++1y", "C++14 (GNU Dialect)", "gnu++1y", - 0 }, - { "CppLanguageStandard", "std=gnu++14", "C++14 (GNU Dialect)", "gnu++1y", - 0 }, - - // Bool Properties - { "CompileAsWinRT", "ZW", "", "true", 0 }, - { "WinRTNoStdLib", "ZW:nostdlib", "", "true", 0 }, - { "SuppressStartupBanner", "nologo", "", "true", 0 }, - { "TreatWarningAsError", "WX-", "", "false", 0 }, - { "TreatWarningAsError", "WX", "", "true", 0 }, - { "SDLCheck", "sdl-", "", "false", 0 }, - { "SDLCheck", "sdl", "", "true", 0 }, - { "IntrinsicFunctions", "Oi", "", "true", 0 }, - { "OmitFramePointers", "Oy-", "", "false", 0 }, - { "OmitFramePointers", "Oy", "", "true", 0 }, - { "EnableFiberSafeOptimizations", "GT", "", "true", 0 }, - { "WholeProgramOptimization", "GL", "", "true", 0 }, - { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 }, - { "IgnoreStandardIncludePath", "X", "", "true", 0 }, - { "PreprocessToFile", "P", "", "true", 0 }, - { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 }, - { "PreprocessKeepComments", "C", "", "true", 0 }, - { "StringPooling", "GF-", "", "false", 0 }, - { "StringPooling", "GF", "", "true", 0 }, - { "MinimalRebuild", "Gm-", "", "false", 0 }, - { "MinimalRebuild", "Gm", "", "true", 0 }, - { "SmallerTypeCheck", "RTCc", "", "true", 0 }, - { "FunctionLevelLinking", "Gy-", "", "false", 0 }, - { "FunctionLevelLinking", "Gy", "", "true", 0 }, - { "EnableParallelCodeGeneration", "Qpar-", "", "false", 0 }, - { "EnableParallelCodeGeneration", "Qpar", "", "true", 0 }, - { "FloatingPointExceptions", "fp:except-", "", "false", 0 }, - { "FloatingPointExceptions", "fp:except", "", "true", 0 }, - { "CreateHotpatchableImage", "hotpatch", "", "true", 0 }, - { "DisableLanguageExtensions", "Za", "", "true", 0 }, - { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 }, - { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 }, - { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 }, - { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 }, - { "RemoveUnreferencedCodeData", "Zc:inline-", "", "false", 0 }, - { "RemoveUnreferencedCodeData", "Zc:inline", "", "true", 0 }, - { "RuntimeTypeInfo", "GR-", "", "false", 0 }, - { "RuntimeTypeInfo", "GR", "", "true", 0 }, - { "OpenMPSupport", "openmp-", "", "false", 0 }, - { "OpenMPSupport", "openmp", "", "true", 0 }, - { "ExpandAttributedSource", "Fx", "", "true", 0 }, - { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 }, - { "ShowIncludes", "showIncludes", "", "true", 0 }, - { "EnablePREfast", "analyze-", "", "false", 0 }, - { "EnablePREfast", "analyze", "", "true", 0 }, - { "UseFullPaths", "FC", "", "true", 0 }, - { "OmitDefaultLibName", "Zl", "", "true", 0 }, - - // Bool Properties With Argument - { "MultiProcessorCompilation", "MP", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "ProcessorNumber", "MP", "Multi-processor Compilation", "", - cmVS7FlagTable::UserValueRequired }, - { "GenerateXMLDocumentationFiles", "doc", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "", - cmVS7FlagTable::UserValueRequired }, - { "BrowseInformation", "FR", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "BrowseInformationFile", "FR", "Enable Browse Information", "", - cmVS7FlagTable::UserValueRequired }, - - // String List Properties - { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AdditionalUsingDirectories", "AI", "Additional #using Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "UndefinePreprocessorDefinitions", "U", - "Undefine Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForcedIncludeFiles", "FI", "Forced Include File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForcedUsingFiles", "FU", "Forced #using File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "PREfastLog", "analyze:log", "Code Analysis Log", "", - cmVS7FlagTable::UserFollowing }, - { "PREfastAdditionalPlugins", "analyze:plugin", - "Additional Code Analysis Native plugins", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - // Skip [TrackerLogDirectory] - no command line Switch. - { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "", - cmVS7FlagTable::UserValue }, - { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired }, - { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired }, - { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "", - cmVS7FlagTable::UserValue }, - { "AssemblerListingLocation", "Fa", "ASM List Location", "", - cmVS7FlagTable::UserValue }, - { "ObjectFileName", "Fo", "Object File Name", "", - cmVS7FlagTable::UserValue }, - { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "", - cmVS7FlagTable::UserValue }, - // Skip [XMLDocumentationFileName] - no command line Switch. - // Skip [BrowseInformationFile] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS140CSharpFlagTable.h b/Source/cmVS140CSharpFlagTable.h deleted file mode 100644 index f695f4582..000000000 --- a/Source/cmVS140CSharpFlagTable.h +++ /dev/null @@ -1,121 +0,0 @@ -static cmVS7FlagTable cmVS140CSharpFlagTable[] = { - { "ProjectName", "out:", "", "", cmIDEFlagTable::UserValueRequired }, - - { "OutputType", "target:exe", "", "Exe", 0 }, - { "OutputType", "target:winexe", "", "Winexe", 0 }, - { "OutputType", "target:library", "", "Library", 0 }, - { "OutputType", "target:module", "", "Module", 0 }, - - { "DocumentationFile", "doc", "", "", cmIDEFlagTable::UserValueRequired }, - - { "Platform", "platform:x86", "", "x86", 0 }, - { "Platform", "platform:Itanium", "", "Itanium", 0 }, - { "Platform", "platform:x64", "", "x64", 0 }, - { "Platform", "platform:arm", "", "arm", 0 }, - { "Platform", "platform:anycpu32bitpreferred", "", "anycpu32bitpreferred", - 0 }, - { "Platform", "platform:anycpu", "", "anycpu", 0 }, - - { "References", "reference:", "mit alias", "", 0 }, - { "References", "reference:", "dateiliste", "", 0 }, - { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable }, - { "", "link", "", "", 0 }, - - { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired }, - { "ApplicationIcon", "win32icon:", "", "", - cmIDEFlagTable::UserValueRequired }, - - { "ApplicationManifest", "win32manifest:", "", "", - cmIDEFlagTable::UserValueRequired }, - - { "NoWin32Manifest", "nowin32manifest", "", "true", 0 }, - - { "DefineDebug", "debug", "", "true", cmIDEFlagTable::Continue }, - - { "DebugSymbols", "debug", "", "true", 0 }, - { "DebugSymbols", "debug-", "", "false", 0 }, - { "DebugSymbols", "debug+", "", "true", 0 }, - - { "DebugType", "debug:none", "", "none", 0 }, - { "DebugType", "debug:full", "", "full", 0 }, - { "DebugType", "debug:pdbonly", "", "pdbonly", 0 }, - - { "Optimize", "optimize", "", "true", 0 }, - { "Optimize", "optimize-", "", "false", 0 }, - { "Optimize", "optimize+", "", "true", 0 }, - - { "TreatWarningsAsErrors", "warnaserror", "", "true", 0 }, - { "TreatWarningsAsErrors", "warnaserror-", "", "false", 0 }, - { "TreatWarningsAsErrors", "warnaserror+", "", "true", 0 }, - - { "WarningsAsErrors", "warnaserror", "", "", 0 }, - { "WarningsAsErrors", "warnaserror-", "", "", 0 }, - { "WarningsAsErrors", "warnaserror+", "", "", 0 }, - - { "WarningLevel", "warn:0", "", "0", 0 }, - { "WarningLevel", "warn:1", "", "1", 0 }, - { "WarningLevel", "warn:2", "", "2", 0 }, - { "WarningLevel", "warn:3", "", "3", 0 }, - { "WarningLevel", "warn:4", "", "4", 0 }, - { "DisabledWarnings", "nowarn", "", "", 0 }, - - { "CheckForOverflowUnderflow", "checked", "", "true", 0 }, - { "CheckForOverflowUnderflow", "checked-", "", "false", 0 }, - { "CheckForOverflowUnderflow", "checked+", "", "true", 0 }, - - { "AllowUnsafeBlocks", "unsafe", "", "true", 0 }, - { "AllowUnsafeBlocks", "unsafe-", "", "false", 0 }, - { "AllowUnsafeBlocks", "unsafe+", "", "true", 0 }, - - { "DefineConstants", "define:", "", "", - cmIDEFlagTable::SemicolonAppendable | cmIDEFlagTable::UserValue }, - - { "LangVersion", "langversion:ISO-1", "", "ISO-1", 0 }, - { "LangVersion", "langversion:ISO-2", "", "ISO-2", 0 }, - { "LangVersion", "langversion:3", "", "3", 0 }, - { "LangVersion", "langversion:4", "", "4", 0 }, - { "LangVersion", "langversion:5", "", "5", 0 }, - { "LangVersion", "langversion:6", "", "6", 0 }, - { "LangVersion", "langversion:default", "", "default", 0 }, - - { "DelaySign", "delaysign", "", "true", 0 }, - { "DelaySign", "delaysign-", "", "false", 0 }, - { "DelaySign", "delaysign+", "", "true", 0 }, - - { "AssemblyOriginatorKeyFile", "keyfile", "", "", 0 }, - - { "KeyContainerName", "keycontainer", "", "", 0 }, - - { "NoLogo", "nologo", "", "", 0 }, - - { "NoConfig", "noconfig", "", "true", 0 }, - - { "BaseAddress", "baseaddress:", "", "", 0 }, - - { "CodePage", "codepage", "", "", 0 }, - - { "Utf8Output", "utf8output", "", "", 0 }, - - { "MainEntryPoint", "main:", "", "", 0 }, - - { "GenerateFullPaths", "fullpaths", "", "true", 0 }, - - { "FileAlignment", "filealign", "", "", 0 }, - - { "PdbFile", "pdb:", "", "", 0 }, - - { "NoStandardLib", "nostdlib", "", "true", 0 }, - { "NoStandardLib", "nostdlib-", "", "false", 0 }, - { "NoStandardLib", "nostdlib+", "", "true", 0 }, - - { "SubsystemVersion", "subsystemversion", "", "", 0 }, - - { "AdditionalLibPaths", "lib:", "", "", 0 }, - - { "ErrorReport", "errorreport:none", "Do Not Send Report", "none", 0 }, - { "ErrorReport", "errorreport:prompt", "Prompt Immediately", "prompt", 0 }, - { "ErrorReport", "errorreport:queue", "Queue For Next Login", "queue", 0 }, - { "ErrorReport", "errorreport:send", "Send Automatically", "send", 0 }, - - { 0, 0, 0, 0, 0 }, -}; diff --git a/Source/cmVS140LinkFlagTable.h b/Source/cmVS140LinkFlagTable.h deleted file mode 100644 index fe0315386..000000000 --- a/Source/cmVS140LinkFlagTable.h +++ /dev/null @@ -1,285 +0,0 @@ -static cmVS7FlagTable cmVS140LinkFlagTable[] = { - - // Enum Properties - { "ShowProgress", "", "Not Set", "NotSet", 0 }, - { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose", - 0 }, - { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib", - 0 }, - { "ShowProgress", "VERBOSE:ICF", - "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 }, - { "ShowProgress", "VERBOSE:REF", - "About data removed during optimized linking", "LinkVerboseREF", 0 }, - { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH", - "LinkVerboseSAFESEH", 0 }, - { "ShowProgress", "VERBOSE:CLR", - "About linker activity related to managed code", "LinkVerboseCLR", 0 }, - - { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 }, - { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only", - "MultiplyDefinedSymbolOnly", 0 }, - { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only", - "UndefinedSymbolOnly", 0 }, - - { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only", - "X86Image", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only", - "X64Image", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", - "ItaniumImage", 0 }, - - // correct flags for uac should be /MANIFESTUAC, but some projects already - // use this bug to access uac field, so keep these for compatibility - { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, - { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", - "HighestAvailable", 0 }, - { "UACExecutionLevel", "level='requireAdministrator'", - "requireAdministrator", "RequireAdministrator", 0 }, - - { "GenerateDebugInformation", "DEBUG:FASTLINK", - "Optimize for faster linking", "DebugFastLink", - cmVS7FlagTable::CaseInsensitive }, - { "GenerateDebugInformation", "DEBUG:FULL", "Optimize for debugging", "true", - cmVS7FlagTable::CaseInsensitive }, - { "GenerateDebugInformation", "DEBUG:NONE", - "Produces no debugging information", "false", - cmVS7FlagTable::CaseInsensitive }, - { "GenerateDebugInformation", "DEBUG", "Optimize for debugging", "true", - cmVS7FlagTable::CaseInsensitive }, - - { "SubSystem", "", "Not Set", "NotSet", 0 }, - { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 }, - { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application", - "EFI Application", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", - "EFI Boot Service Driver", "EFI Boot Service Driver", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime", - 0 }, - { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 }, - - { "Driver", "", "Not Set", "NotSet", 0 }, - { "Driver", "Driver", "Driver", "Driver", 0 }, - { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 }, - { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 }, - - { "LinkTimeCodeGeneration", "", "Default", "Default", 0 }, - { "LinkTimeCodeGeneration", "LTCG:incremental", - "Use Fast Link Time Code Generation", "UseFastLinkTimeCodeGeneration", 0 }, - { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation", - "UseLinkTimeCodeGeneration", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGInstrument", - "Profile Guided Optimization - Instrument", "PGInstrument", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGOptimize", - "Profile Guided Optimization - Optimization", "PGOptimization", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGUpdate", - "Profile Guided Optimization - Update", "PGUpdate", 0 }, - - { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 }, - { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 }, - - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 }, - - { "TargetMachine", "", "Not Set", "NotSet", 0 }, - { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 }, - { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 }, - { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 }, - { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 }, - { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 }, - { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU", - 0 }, - { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16", - "MachineMIPSFPU16", 0 }, - { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 }, - { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 }, - { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 }, - { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 }, - - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute", - "MTAThreadingAttribute", 0 }, - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute", - "STAThreadingAttribute", 0 }, - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE", - "Default threading attribute", "DefaultThreadingAttribute", 0 }, - - { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage", - 0 }, - { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image", - "ForcePureILImage", 0 }, - { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image", - "ForceSafeILImage", 0 }, - { "CLRImageType", "", "Default image type", "Default", 0 }, - - { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 }, - { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 }, - { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 }, - { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 }, - - { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately", - "PromptImmediately", 0 }, - { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login", - "QueueForNextLogin", 0 }, - { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report", - "SendErrorReport", 0 }, - { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report", - "NoErrorReport", 0 }, - - { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 }, - { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled", - 0 }, - { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only", - "SystemDlls", 0 }, - - // Bool Properties - { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 }, - { "LinkIncremental", "INCREMENTAL", "", "true", 0 }, - { "SuppressStartupBanner", "NOLOGO", "", "true", 0 }, - { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 }, - { "LinkStatus", "LTCG:STATUS", "", "true", 0 }, - { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 }, - { "PreventDllBinding", "ALLOWBIND", "", "true", 0 }, - { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 }, - { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 }, - { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 }, - { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, - { "GenerateManifest", "MANIFEST", "", "true", 0 }, - { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, - - // correct flags for uac should be /MANIFESTUAC, but some projects already - // use this bug to access uac field, so keep these for compatibility - { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, - { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, - - { "ManifestEmbed", "manifest:embed", "", "true", 0 }, - { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 }, - { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 }, - { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 }, - { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 }, - { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 }, - { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 }, - { "TerminalServerAware", "TSAWARE", "", "true", 0 }, - { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 }, - { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 }, - { "OptimizeReferences", "OPT:NOREF", "", "false", 0 }, - { "OptimizeReferences", "OPT:REF", "", "true", 0 }, - { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 }, - { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 }, - { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 }, - { "AppContainer", "APPCONTAINER", "", "true", 0 }, - { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 }, - { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 }, - { "NoEntryPoint", "NOENTRY", "", "true", 0 }, - { "SetChecksum", "RELEASE", "", "true", 0 }, - { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 }, - { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 }, - { "FixedBaseAddress", "FIXED:NO", "", "false", 0 }, - { "FixedBaseAddress", "FIXED", "", "true", 0 }, - { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 }, - { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 }, - { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 }, - { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 }, - { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 }, - { "Profile", "PROFILE", "", "true", 0 }, - { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 }, - { "LinkDelaySign", "DELAYSIGN", "", "true", 0 }, - { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 }, - { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 }, - { "DetectOneDefinitionRule", "ODR", "", "true", 0 }, - { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 }, - { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 }, - { "LinkDLL", "DLL", "", "true", 0 }, - - // Bool Properties With Argument - { "EnableUAC", "MANIFESTUAC:", "", "", - cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SpaceAppendable }, - { "GenerateMapFile", "MAP", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "MapFileName", "MAP:", "Generate Map File", "", - cmVS7FlagTable::UserValueRequired }, - - // String List Properties - { "AdditionalLibraryDirectories", - "LIBPATH:", "Additional Library Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "Natvis", "NATVIS:", "Natvis files", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - // Skip [AdditionalDependencies] - no command line Switch. - { "IgnoreSpecificDefaultLibraries", - "NODEFAULTLIB:", "Ignore Specific Default Libraries", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "EmbedManagedResourceFile", - "ASSEMBLYRESOURCE:", "Embed Managed Resource File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AdditionalManifestDependencies", - "MANIFESTDEPENDENCY:", "Additional Manifest Dependencies", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ManifestInput", "manifestinput:", "Manifest Input", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue }, - { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue }, - { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "", - cmVS7FlagTable::UserValue }, - { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "", - cmVS7FlagTable::UserValue }, - // Skip [TrackerLogDirectory] - no command line Switch. - { "ModuleDefinitionFile", "DEF:", "Module Definition File", "", - cmVS7FlagTable::UserValue }, - { "ManifestFile", "ManifestFile:", "Manifest File", "", - cmVS7FlagTable::UserValue }, - { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "", - cmVS7FlagTable::UserValue }, - { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "", - cmVS7FlagTable::UserValue }, - // Skip [MapFileName] - no command line Switch. - // Skip [MinimumRequiredVersion] - no command line Switch. - { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "", - cmVS7FlagTable::UserValue }, - // Skip [HeapCommitSize] - no command line Switch. - { "StackReserveSize", "STACK:", "Stack Reserve Size", "", - cmVS7FlagTable::UserValue }, - // Skip [StackCommitSize] - no command line Switch. - { "FunctionOrder", "ORDER:@", "Function Order", "", - cmVS7FlagTable::UserValue }, - { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "", - cmVS7FlagTable::UserValue }, - { "MidlCommandFile", "MIDL:@", "MIDL Commands", "", - cmVS7FlagTable::UserValue }, - { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "", - cmVS7FlagTable::UserValue }, - { "TypeLibraryFile", "TLBOUT:", "Type Library", "", - cmVS7FlagTable::UserValue }, - { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "", - cmVS7FlagTable::UserValue }, - { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File", - "", cmVS7FlagTable::UserValue }, - { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:", - "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue }, - { "EntryPointSymbol", "ENTRY:", "Entry Point", "", - cmVS7FlagTable::UserValue }, - { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue }, - { "ImportLibrary", "IMPLIB:", "Import Library", "", - cmVS7FlagTable::UserValue }, - { "MergeSections", "MERGE:", "Merge Sections", "", - cmVS7FlagTable::UserValue }, - { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue }, - { "KeyContainer", "KEYCONTAINER:", "Key Container", "", - cmVS7FlagTable::UserValue }, - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS141CLFlagTable.h b/Source/cmVS141CLFlagTable.h deleted file mode 100644 index 2a9944aab..000000000 --- a/Source/cmVS141CLFlagTable.h +++ /dev/null @@ -1,258 +0,0 @@ -static cmVS7FlagTable cmVS141CLFlagTable[] = { - - // Enum Properties - { "DiagnosticsFormat", "diagnostics:classic", "Classic", "Classic", 0 }, - { "DiagnosticsFormat", "diagnostics:column", "Column", "Column", 0 }, - { "DiagnosticsFormat", "diagnostics:caret", "Caret", "Caret", 0 }, - - { "DebugInformationFormat", "", "None", "None", 0 }, - { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 }, - { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 }, - { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue", - "EditAndContinue", 0 }, - - { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 }, - { "WarningLevel", "W1", "Level1", "Level1", 0 }, - { "WarningLevel", "W2", "Level2", "Level2", 0 }, - { "WarningLevel", "W3", "Level3", "Level3", 0 }, - { "WarningLevel", "W4", "Level4", "Level4", 0 }, - { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 }, - - { "Optimization", "", "Custom", "Custom", 0 }, - { "Optimization", "Od", "Disabled", "Disabled", 0 }, - { "Optimization", "O1", "Minimize Size", "MinSpace", 0 }, - { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 }, - { "Optimization", "Ox", "Full Optimization", "Full", 0 }, - - { "InlineFunctionExpansion", "", "Default", "Default", 0 }, - { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 }, - { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline", - 0 }, - { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 }, - - { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 }, - { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 }, - { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 }, - - { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 }, - { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 }, - { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow", - 0 }, - { "ExceptionHandling", "", "No", "false", 0 }, - - { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck", - 0 }, - { "BasicRuntimeChecks", "RTCu", "Uninitialized variables", - "UninitializedLocalUsageCheck", 0 }, - { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)", - "EnableFastChecks", 0 }, - { "BasicRuntimeChecks", "", "Default", "Default", 0 }, - - { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 }, - { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 }, - { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 }, - { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL", - "MultiThreadedDebugDLL", 0 }, - - { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 }, - { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 }, - { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 }, - { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 }, - { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 }, - { "StructMemberAlignment", "", "Default", "Default", 0 }, - - { "BufferSecurityCheck", "GS-", "Disable Security Check", "false", 0 }, - { "BufferSecurityCheck", "GS", "Enable Security Check", "true", 0 }, - - { "ControlFlowGuard", "guard:cf", "Yes", "Guard", 0 }, - { "ControlFlowGuard", "", "No", "false", 0 }, - - { "EnableEnhancedInstructionSet", "arch:SSE", "Streaming SIMD Extensions", - "StreamingSIMDExtensions", 0 }, - { "EnableEnhancedInstructionSet", "arch:SSE2", "Streaming SIMD Extensions 2", - "StreamingSIMDExtensions2", 0 }, - { "EnableEnhancedInstructionSet", "arch:AVX", "Advanced Vector Extensions", - "AdvancedVectorExtensions", 0 }, - { "EnableEnhancedInstructionSet", "arch:AVX2", - "Advanced Vector Extensions 2", "AdvancedVectorExtensions2", 0 }, - { "EnableEnhancedInstructionSet", "arch:IA32", "No Enhanced Instructions", - "NoExtensions", 0 }, - { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 }, - - { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 }, - { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 }, - { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 }, - - { "SpectreMitigation", "Qspectre", "Spectre mitigations", "Spectre", 0 }, - - { "LanguageStandard", "std:c++17", "ISO C++17 Standard", "stdcpp17", 0 }, - { "LanguageStandard", "std:c++14", "ISO C++14 Standard", "stdcpp14", 0 }, - { "LanguageStandard", "std:c++latest", "ISO C++ Latest Draft Standard", - "stdcpplatest", 0 }, - - { "PrecompiledHeader", "Yc", "Create", "Create", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "PrecompiledHeader", "Yu", "Use", "Use", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "PrecompiledHeader", "Y-", "Not Using Precompiled Headers", "NotUsing", - 0 }, - - { "AssemblerOutput", "", "No Listing", "NoListing", 0 }, - { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 }, - { "AssemblerOutput", "FAc", "Assembly With Machine Code", - "AssemblyAndMachineCode", 0 }, - { "AssemblerOutput", "FAs", "Assembly With Source Code", - "AssemblyAndSourceCode", 0 }, - { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 }, - - { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 }, - { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 }, - { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 }, - { "CallingConvention", "Gv", "__vectorcall", "VectorCall", 0 }, - - { "CompileAs", "", "Default", "Default", 0 }, - { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 }, - { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 }, - - { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 }, - { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt", - 0 }, - { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue", - 0 }, - { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 }, - - { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 }, - { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 }, - { "CompileAsManaged", "clr:pure", - "Pure MSIL Common Language RunTime Support", "Pure", 0 }, - { "CompileAsManaged", "clr:safe", - "Safe MSIL Common Language RunTime Support", "Safe", 0 }, - { "CompileAsManaged", "clr:oldSyntax", - "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 }, - - { "CppLanguageStandard", "", "Default", "Default", 0 }, - { "CppLanguageStandard", "std=c++98", "C++03", "c++98", 0 }, - { "CppLanguageStandard", "std=c++11", "C++11", "c++11", 0 }, - { "CppLanguageStandard", "std=c++1y", "C++14", "c++1y", 0 }, - { "CppLanguageStandard", "std=c++14", "C++14", "c++1y", 0 }, - { "CppLanguageStandard", "std=gnu++98", "C++03 (GNU Dialect)", "gnu++98", - 0 }, - { "CppLanguageStandard", "std=gnu++11", "C++11 (GNU Dialect)", "gnu++11", - 0 }, - { "CppLanguageStandard", "std=gnu++1y", "C++14 (GNU Dialect)", "gnu++1y", - 0 }, - { "CppLanguageStandard", "std=gnu++14", "C++14 (GNU Dialect)", "gnu++1y", - 0 }, - - // Bool Properties - { "CompileAsWinRT", "ZW", "", "true", 0 }, - { "WinRTNoStdLib", "ZW:nostdlib", "", "true", 0 }, - { "SuppressStartupBanner", "nologo", "", "true", 0 }, - { "TreatWarningAsError", "WX-", "", "false", 0 }, - { "TreatWarningAsError", "WX", "", "true", 0 }, - { "SDLCheck", "sdl-", "", "false", 0 }, - { "SDLCheck", "sdl", "", "true", 0 }, - { "IntrinsicFunctions", "Oi", "", "true", 0 }, - { "OmitFramePointers", "Oy-", "", "false", 0 }, - { "OmitFramePointers", "Oy", "", "true", 0 }, - { "EnableFiberSafeOptimizations", "GT", "", "true", 0 }, - { "WholeProgramOptimization", "GL", "", "true", 0 }, - { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 }, - { "IgnoreStandardIncludePath", "X", "", "true", 0 }, - { "PreprocessToFile", "P", "", "true", 0 }, - { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 }, - { "PreprocessKeepComments", "C", "", "true", 0 }, - { "StringPooling", "GF-", "", "false", 0 }, - { "StringPooling", "GF", "", "true", 0 }, - { "MinimalRebuild", "Gm-", "", "false", 0 }, - { "MinimalRebuild", "Gm", "", "true", 0 }, - { "SmallerTypeCheck", "RTCc", "", "true", 0 }, - { "FunctionLevelLinking", "Gy-", "", "false", 0 }, - { "FunctionLevelLinking", "Gy", "", "true", 0 }, - { "EnableParallelCodeGeneration", "Qpar-", "", "false", 0 }, - { "EnableParallelCodeGeneration", "Qpar", "", "true", 0 }, - { "FloatingPointExceptions", "fp:except-", "", "false", 0 }, - { "FloatingPointExceptions", "fp:except", "", "true", 0 }, - { "CreateHotpatchableImage", "hotpatch", "", "true", 0 }, - { "DisableLanguageExtensions", "Za", "", "true", 0 }, - { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 }, - { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 }, - { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 }, - { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 }, - { "RemoveUnreferencedCodeData", "Zc:inline-", "", "false", 0 }, - { "RemoveUnreferencedCodeData", "Zc:inline", "", "true", 0 }, - { "EnforceTypeConversionRules", "Zc:rvalueCast-", "", "false", 0 }, - { "EnforceTypeConversionRules", "Zc:rvalueCast", "", "true", 0 }, - { "RuntimeTypeInfo", "GR-", "", "false", 0 }, - { "RuntimeTypeInfo", "GR", "", "true", 0 }, - { "OpenMPSupport", "openmp-", "", "false", 0 }, - { "OpenMPSupport", "openmp", "", "true", 0 }, - { "ExpandAttributedSource", "Fx", "", "true", 0 }, - { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 }, - { "ShowIncludes", "showIncludes", "", "true", 0 }, - { "EnablePREfast", "analyze-", "", "false", 0 }, - { "EnablePREfast", "analyze", "", "true", 0 }, - { "UseFullPaths", "FC", "", "true", 0 }, - { "OmitDefaultLibName", "Zl", "", "true", 0 }, - - // Bool Properties With Argument - { "MultiProcessorCompilation", "MP", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "ProcessorNumber", "MP", "Multi-processor Compilation", "", - cmVS7FlagTable::UserValueRequired }, - { "GenerateXMLDocumentationFiles", "doc", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "", - cmVS7FlagTable::UserValueRequired }, - { "BrowseInformation", "FR", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "BrowseInformationFile", "FR", "Enable Browse Information", "", - cmVS7FlagTable::UserValueRequired }, - - // String List Properties - { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AdditionalUsingDirectories", "AI", "Additional #using Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "UndefinePreprocessorDefinitions", "U", - "Undefine Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForcedIncludeFiles", "FI", "Forced Include File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForcedUsingFiles", "FU", "Forced #using File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "PREfastLog", "analyze:log", "Code Analysis Log", "", - cmVS7FlagTable::UserFollowing }, - { "PREfastAdditionalPlugins", "analyze:plugin", - "Additional Code Analysis Native plugins", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - { "WarningVersion", "Wv:", "Warning Version", "", - cmVS7FlagTable::UserValue }, - // Skip [TrackerLogDirectory] - no command line Switch. - { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "", - cmVS7FlagTable::UserValue }, - { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired }, - { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired }, - { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "", - cmVS7FlagTable::UserValue }, - { "AssemblerListingLocation", "Fa", "ASM List Location", "", - cmVS7FlagTable::UserValue }, - { "ObjectFileName", "Fo", "Object File Name", "", - cmVS7FlagTable::UserValue }, - { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "", - cmVS7FlagTable::UserValue }, - // Skip [XMLDocumentationFileName] - no command line Switch. - // Skip [BrowseInformationFile] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS141CSharpFlagTable.h b/Source/cmVS141CSharpFlagTable.h deleted file mode 100644 index 1f840970b..000000000 --- a/Source/cmVS141CSharpFlagTable.h +++ /dev/null @@ -1,126 +0,0 @@ -static cmVS7FlagTable cmVS141CSharpFlagTable[] = { - { "ProjectName", "out:", "", "", cmIDEFlagTable::UserValueRequired }, - - { "OutputType", "target:exe", "", "Exe", 0 }, - { "OutputType", "target:winexe", "", "Winexe", 0 }, - { "OutputType", "target:library", "", "Library", 0 }, - { "OutputType", "target:module", "", "Module", 0 }, - - { "DocumentationFile", "doc", "", "", cmIDEFlagTable::UserValueRequired }, - - { "Platform", "platform:x86", "", "x86", 0 }, - { "Platform", "platform:Itanium", "", "Itanium", 0 }, - { "Platform", "platform:x64", "", "x64", 0 }, - { "Platform", "platform:arm", "", "arm", 0 }, - { "Platform", "platform:anycpu32bitpreferred", "", "anycpu32bitpreferred", - 0 }, - { "Platform", "platform:anycpu", "", "anycpu", 0 }, - - { "References", "reference:", "mit alias", "", 0 }, - { "References", "reference:", "dateiliste", "", 0 }, - { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable }, - { "", "link", "", "", 0 }, - - { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired }, - { "ApplicationIcon", "win32icon:", "", "", - cmIDEFlagTable::UserValueRequired }, - - { "ApplicationManifest", "win32manifest:", "", "", - cmIDEFlagTable::UserValueRequired }, - - { "NoWin32Manifest", "nowin32manifest", "", "true", 0 }, - - { "DefineDebug", "debug", "", "true", cmIDEFlagTable::Continue }, - - { "DebugSymbols", "debug", "", "true", 0 }, - { "DebugSymbols", "debug-", "", "false", 0 }, - { "DebugSymbols", "debug+", "", "true", 0 }, - - { "DebugType", "debug:none", "", "none", 0 }, - { "DebugType", "debug:full", "", "full", 0 }, - { "DebugType", "debug:pdbonly", "", "pdbonly", 0 }, - - { "Optimize", "optimize", "", "true", 0 }, - { "Optimize", "optimize-", "", "false", 0 }, - { "Optimize", "optimize+", "", "true", 0 }, - - { "TreatWarningsAsErrors", "warnaserror", "", "true", 0 }, - { "TreatWarningsAsErrors", "warnaserror-", "", "false", 0 }, - { "TreatWarningsAsErrors", "warnaserror+", "", "true", 0 }, - - { "WarningsAsErrors", "warnaserror", "", "", 0 }, - { "WarningsAsErrors", "warnaserror-", "", "", 0 }, - { "WarningsAsErrors", "warnaserror+", "", "", 0 }, - - { "WarningLevel", "warn:0", "", "0", 0 }, - { "WarningLevel", "warn:1", "", "1", 0 }, - { "WarningLevel", "warn:2", "", "2", 0 }, - { "WarningLevel", "warn:3", "", "3", 0 }, - { "WarningLevel", "warn:4", "", "4", 0 }, - { "DisabledWarnings", "nowarn", "", "", 0 }, - - { "CheckForOverflowUnderflow", "checked", "", "true", 0 }, - { "CheckForOverflowUnderflow", "checked-", "", "false", 0 }, - { "CheckForOverflowUnderflow", "checked+", "", "true", 0 }, - - { "AllowUnsafeBlocks", "unsafe", "", "true", 0 }, - { "AllowUnsafeBlocks", "unsafe-", "", "false", 0 }, - { "AllowUnsafeBlocks", "unsafe+", "", "true", 0 }, - - { "DefineConstants", "define:", "", "", - cmIDEFlagTable::SemicolonAppendable | cmIDEFlagTable::UserValue }, - - { "LangVersion", "langversion:ISO-1", "", "ISO-1", 0 }, - { "LangVersion", "langversion:ISO-2", "", "ISO-2", 0 }, - { "LangVersion", "langversion:3", "", "3", 0 }, - { "LangVersion", "langversion:4", "", "4", 0 }, - { "LangVersion", "langversion:5", "", "5", 0 }, - { "LangVersion", "langversion:6", "", "6", 0 }, - { "LangVersion", "langversion:7.0", "", "7.0", 0 }, - { "LangVersion", "langversion:7.1", "", "7.1", 0 }, - { "LangVersion", "langversion:7.2", "", "7.2", 0 }, - { "LangVersion", "langversion:7.3", "", "7.3", 0 }, - { "LangVersion", "langversion:default", "", "default", 0 }, - { "LangVersion", "langversion:latest", "", "latest", 0 }, - - { "DelaySign", "delaysign", "", "true", 0 }, - { "DelaySign", "delaysign-", "", "false", 0 }, - { "DelaySign", "delaysign+", "", "true", 0 }, - - { "AssemblyOriginatorKeyFile", "keyfile", "", "", 0 }, - - { "KeyContainerName", "keycontainer", "", "", 0 }, - - { "NoLogo", "nologo", "", "", 0 }, - - { "NoConfig", "noconfig", "", "true", 0 }, - - { "BaseAddress", "baseaddress:", "", "", 0 }, - - { "CodePage", "codepage", "", "", 0 }, - - { "Utf8Output", "utf8output", "", "", 0 }, - - { "MainEntryPoint", "main:", "", "", 0 }, - - { "GenerateFullPaths", "fullpaths", "", "true", 0 }, - - { "FileAlignment", "filealign", "", "", 0 }, - - { "PdbFile", "pdb:", "", "", 0 }, - - { "NoStandardLib", "nostdlib", "", "true", 0 }, - { "NoStandardLib", "nostdlib-", "", "false", 0 }, - { "NoStandardLib", "nostdlib+", "", "true", 0 }, - - { "SubsystemVersion", "subsystemversion", "", "", 0 }, - - { "AdditionalLibPaths", "lib:", "", "", 0 }, - - { "ErrorReport", "errorreport:none", "Do Not Send Report", "none", 0 }, - { "ErrorReport", "errorreport:prompt", "Prompt Immediately", "prompt", 0 }, - { "ErrorReport", "errorreport:queue", "Queue For Next Login", "queue", 0 }, - { "ErrorReport", "errorreport:send", "Send Automatically", "send", 0 }, - - { 0, 0, 0, 0, 0 }, -}; diff --git a/Source/cmVS141LinkFlagTable.h b/Source/cmVS141LinkFlagTable.h deleted file mode 100644 index 7e56c8e80..000000000 --- a/Source/cmVS141LinkFlagTable.h +++ /dev/null @@ -1,287 +0,0 @@ -static cmVS7FlagTable cmVS141LinkFlagTable[] = { - - // Enum Properties - { "ShowProgress", "", "Not Set", "NotSet", 0 }, - { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose", - 0 }, - { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib", - 0 }, - { "ShowProgress", "VERBOSE:ICF", - "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 }, - { "ShowProgress", "VERBOSE:REF", - "About data removed during optimized linking", "LinkVerboseREF", 0 }, - { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH", - "LinkVerboseSAFESEH", 0 }, - { "ShowProgress", "VERBOSE:CLR", - "About linker activity related to managed code", "LinkVerboseCLR", 0 }, - - { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 }, - { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only", - "MultiplyDefinedSymbolOnly", 0 }, - { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only", - "UndefinedSymbolOnly", 0 }, - - { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only", - "X86Image", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only", - "X64Image", 0 }, - { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", - "ItaniumImage", 0 }, - - // correct flags for uac should be /MANIFESTUAC, but some projects already - // use this bug to access uac field, so keep these for compatibility - { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, - { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", - "HighestAvailable", 0 }, - { "UACExecutionLevel", "level='requireAdministrator'", - "requireAdministrator", "RequireAdministrator", 0 }, - - { "GenerateDebugInformation", "DEBUG:FASTLINK", - "Generate Debug Information optimized for faster links", "DebugFastLink", - cmVS7FlagTable::CaseInsensitive }, - { "GenerateDebugInformation", "DEBUG:FULL", - "Generate Debug Information optimized for sharing and publishing", - "DebugFull", cmVS7FlagTable::CaseInsensitive }, - { "GenerateDebugInformation", "DEBUG:NONE", - "Produces no debugging information", "false", - cmVS7FlagTable::CaseInsensitive }, - { "GenerateDebugInformation", "DEBUG", "Generate Debug Information", "true", - cmVS7FlagTable::CaseInsensitive }, - - { "SubSystem", "", "Not Set", "NotSet", 0 }, - { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 }, - { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application", - "EFI Application", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", - "EFI Boot Service Driver", "EFI Boot Service Driver", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime", - 0 }, - { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 }, - - { "Driver", "", "Not Set", "NotSet", 0 }, - { "Driver", "Driver", "Driver", "Driver", 0 }, - { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 }, - { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 }, - - { "LinkTimeCodeGeneration", "", "Default", "Default", 0 }, - { "LinkTimeCodeGeneration", "LTCG:incremental", - "Use Fast Link Time Code Generation", "UseFastLinkTimeCodeGeneration", 0 }, - { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation", - "UseLinkTimeCodeGeneration", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGInstrument", - "Profile Guided Optimization - Instrument", "PGInstrument", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGOptimize", - "Profile Guided Optimization - Optimization", "PGOptimization", 0 }, - { "LinkTimeCodeGeneration", "LTCG:PGUpdate", - "Profile Guided Optimization - Update", "PGUpdate", 0 }, - - { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 }, - { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 }, - - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 }, - { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 }, - - { "TargetMachine", "", "Not Set", "NotSet", 0 }, - { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 }, - { "TargetMachine", "MACHINE:ARM64", "MachineARM64", "MachineARM64", 0 }, - { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 }, - { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 }, - { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 }, - { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 }, - { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU", - 0 }, - { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16", - "MachineMIPSFPU16", 0 }, - { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 }, - { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 }, - { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 }, - { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 }, - - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute", - "MTAThreadingAttribute", 0 }, - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute", - "STAThreadingAttribute", 0 }, - { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE", - "Default threading attribute", "DefaultThreadingAttribute", 0 }, - - { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage", - 0 }, - { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image", - "ForcePureILImage", 0 }, - { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image", - "ForceSafeILImage", 0 }, - { "CLRImageType", "", "Default image type", "Default", 0 }, - - { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 }, - { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 }, - { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 }, - { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 }, - - { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately", - "PromptImmediately", 0 }, - { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login", - "QueueForNextLogin", 0 }, - { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report", - "SendErrorReport", 0 }, - { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report", - "NoErrorReport", 0 }, - - { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 }, - { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled", - 0 }, - { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only", - "SystemDlls", 0 }, - - // Bool Properties - { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 }, - { "LinkIncremental", "INCREMENTAL", "", "true", 0 }, - { "SuppressStartupBanner", "NOLOGO", "", "true", 0 }, - { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 }, - { "LinkStatus", "LTCG:STATUS", "", "true", 0 }, - { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 }, - { "PreventDllBinding", "ALLOWBIND", "", "true", 0 }, - { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 }, - { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 }, - { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 }, - { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, - { "GenerateManifest", "MANIFEST", "", "true", 0 }, - { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, - - // correct flags for uac should be /MANIFESTUAC, but some projects already - // use this bug to access uac field, so keep these for compatibility - { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, - { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, - - { "ManifestEmbed", "manifest:embed", "", "true", 0 }, - { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 }, - { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 }, - { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 }, - { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 }, - { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 }, - { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 }, - { "TerminalServerAware", "TSAWARE", "", "true", 0 }, - { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 }, - { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 }, - { "OptimizeReferences", "OPT:NOREF", "", "false", 0 }, - { "OptimizeReferences", "OPT:REF", "", "true", 0 }, - { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 }, - { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 }, - { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 }, - { "AppContainer", "APPCONTAINER", "", "true", 0 }, - { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 }, - { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 }, - { "NoEntryPoint", "NOENTRY", "", "true", 0 }, - { "SetChecksum", "RELEASE", "", "true", 0 }, - { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 }, - { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 }, - { "FixedBaseAddress", "FIXED:NO", "", "false", 0 }, - { "FixedBaseAddress", "FIXED", "", "true", 0 }, - { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 }, - { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 }, - { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 }, - { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 }, - { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 }, - { "Profile", "PROFILE", "", "true", 0 }, - { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 }, - { "LinkDelaySign", "DELAYSIGN", "", "true", 0 }, - { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 }, - { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 }, - { "DetectOneDefinitionRule", "ODR", "", "true", 0 }, - { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 }, - { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 }, - { "LinkDLL", "DLL", "", "true", 0 }, - - // Bool Properties With Argument - { "EnableUAC", "MANIFESTUAC:", "", "", - cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SpaceAppendable }, - { "GenerateMapFile", "MAP", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "MapFileName", "MAP:", "Generate Map File", "", - cmVS7FlagTable::UserValueRequired }, - - // String List Properties - { "AdditionalLibraryDirectories", - "LIBPATH:", "Additional Library Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "Natvis", "NATVIS:", "Natvis files", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - // Skip [AdditionalDependencies] - no command line Switch. - { "IgnoreSpecificDefaultLibraries", - "NODEFAULTLIB:", "Ignore Specific Default Libraries", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "EmbedManagedResourceFile", - "ASSEMBLYRESOURCE:", "Embed Managed Resource File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource", - "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "AdditionalManifestDependencies", - "MANIFESTDEPENDENCY:", "Additional Manifest Dependencies", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ManifestInput", "manifestinput:", "Manifest Input", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue }, - { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue }, - { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "", - cmVS7FlagTable::UserValue }, - { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "", - cmVS7FlagTable::UserValue }, - // Skip [TrackerLogDirectory] - no command line Switch. - { "ModuleDefinitionFile", "DEF:", "Module Definition File", "", - cmVS7FlagTable::UserValue }, - { "ManifestFile", "ManifestFile:", "Manifest File", "", - cmVS7FlagTable::UserValue }, - { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "", - cmVS7FlagTable::UserValue }, - { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "", - cmVS7FlagTable::UserValue }, - // Skip [MapFileName] - no command line Switch. - // Skip [MinimumRequiredVersion] - no command line Switch. - { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "", - cmVS7FlagTable::UserValue }, - // Skip [HeapCommitSize] - no command line Switch. - { "StackReserveSize", "STACK:", "Stack Reserve Size", "", - cmVS7FlagTable::UserValue }, - // Skip [StackCommitSize] - no command line Switch. - { "FunctionOrder", "ORDER:@", "Function Order", "", - cmVS7FlagTable::UserValue }, - { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "", - cmVS7FlagTable::UserValue }, - { "MidlCommandFile", "MIDL:@", "MIDL Commands", "", - cmVS7FlagTable::UserValue }, - { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "", - cmVS7FlagTable::UserValue }, - { "TypeLibraryFile", "TLBOUT:", "Type Library", "", - cmVS7FlagTable::UserValue }, - { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "", - cmVS7FlagTable::UserValue }, - { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File", - "", cmVS7FlagTable::UserValue }, - { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:", - "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue }, - { "EntryPointSymbol", "ENTRY:", "Entry Point", "", - cmVS7FlagTable::UserValue }, - { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue }, - { "ImportLibrary", "IMPLIB:", "Import Library", "", - cmVS7FlagTable::UserValue }, - { "MergeSections", "MERGE:", "Merge Sections", "", - cmVS7FlagTable::UserValue }, - { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue }, - { "KeyContainer", "KEYCONTAINER:", "Key Container", "", - cmVS7FlagTable::UserValue }, - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS14LibFlagTable.h b/Source/cmVS14LibFlagTable.h deleted file mode 100644 index adce075fb..000000000 --- a/Source/cmVS14LibFlagTable.h +++ /dev/null @@ -1,77 +0,0 @@ -static cmVS7FlagTable cmVS14LibFlagTable[] = { - - // Enum Properties - { "ErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately", - "PromptImmediately", 0 }, - { "ErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login", - "QueueForNextLogin", 0 }, - { "ErrorReporting", "ERRORREPORT:SEND", "Send Error Report", - "SendErrorReport", 0 }, - { "ErrorReporting", "ERRORREPORT:NONE", "No Error Report", "NoErrorReport", - 0 }, - - { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 }, - { "TargetMachine", "MACHINE:ARM64", "MachineARM64", "MachineARM64", 0 }, - { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 }, - { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 }, - { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 }, - { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 }, - { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU", - 0 }, - { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16", - "MachineMIPSFPU16", 0 }, - { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 }, - { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 }, - { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 }, - { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 }, - - { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 }, - { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application", - "EFI Application", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", - "EFI Boot Service Driver", "EFI Boot Service Driver", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 }, - { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime", - 0 }, - { "SubSystem", "SUBSYSTEM:WINDOWSCE", "WindowsCE", "WindowsCE", 0 }, - { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 }, - - // Bool Properties - { "SuppressStartupBanner", "NOLOGO", "", "true", 0 }, - { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 }, - { "TreatLibWarningAsErrors", "WX:NO", "", "false", 0 }, - { "TreatLibWarningAsErrors", "WX", "", "true", 0 }, - { "Verbose", "VERBOSE", "", "true", 0 }, - { "LinkTimeCodeGeneration", "LTCG", "", "true", 0 }, - - // Bool Properties With Argument - - // String List Properties - // Skip [AdditionalDependencies] - no command line Switch. - { "AdditionalLibraryDirectories", - "LIBPATH:", "Additional Library Directories", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IgnoreSpecificDefaultLibraries", - "NODEFAULTLIB:", "Ignore Specific Default Libraries", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "RemoveObjects", "REMOVE:", "Remove Objects", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - - // String Properties - { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue }, - { "ModuleDefinitionFile", "DEF:", "Module Definition File Name", "", - cmVS7FlagTable::UserValue }, - { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "", - cmVS7FlagTable::UserValue }, - { "DisplayLibrary", "LIST:", "Display Library to standard output", "", - cmVS7FlagTable::UserValue }, - // Skip [MinimumRequiredVersion] - no command line Switch. - { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue }, - // Skip [AdditionalOptions] - no command line Switch. - // Skip [TrackerLogDirectory] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS14MASMFlagTable.h b/Source/cmVS14MASMFlagTable.h deleted file mode 100644 index 82ec9f1d0..000000000 --- a/Source/cmVS14MASMFlagTable.h +++ /dev/null @@ -1,76 +0,0 @@ -static cmVS7FlagTable cmVS14MASMFlagTable[] = { - - // Enum Properties - { "PreserveIdentifierCase", "", "Default", "0", 0 }, - { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1", - 0 }, - { "PreserveIdentifierCase", "Cu", - "Maps all identifiers to upper case. (/Cu)", "2", 0 }, - { "PreserveIdentifierCase", "Cx", - "Preserves case in public and extern symbols. (/Cx)", "3", 0 }, - - { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 }, - { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 }, - { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 }, - { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 }, - - { "PackAlignmentBoundary", "", "Default", "0", 0 }, - { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, - { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, - { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, - { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, - { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 }, - - { "CallingConvention", "", "Default", "0", 0 }, - { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1", - 0 }, - { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2", - 0 }, - { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 }, - - { "ErrorReporting", "errorReport:prompt", - "Prompt to send report immediately (/errorReport:prompt)", "0", 0 }, - { "ErrorReporting", "errorReport:queue", - "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 }, - { "ErrorReporting", "errorReport:send", - "Automatically send report (/errorReport:send)", "2", 0 }, - { "ErrorReporting", "errorReport:none", - "Do not send report (/errorReport:none)", "3", 0 }, - - // Bool Properties - { "NoLogo", "nologo", "", "true", 0 }, - { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 }, - { "ListAllAvailableInformation", "Sa", "", "true", 0 }, - { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 }, - { "AddFirstPassListing", "Sf", "", "true", 0 }, - { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 }, - { "DisableSymbolTable", "Sn", "", "true", 0 }, - { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 }, - { "TreatWarningsAsErrors", "WX", "", "true", 0 }, - { "MakeAllSymbolsPublic", "Zf", "", "true", 0 }, - { "GenerateDebugInformation", "Zi", "", "true", 0 }, - { "EnableMASM51Compatibility", "Zm", "", "true", 0 }, - { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 }, - - // Bool Properties With Argument - - // String List Properties - { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IncludePaths", "I", "Include Paths", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "BrowseFile", "FR", "Generate Browse Information File", "", - cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - // Skip [AdditionalDependencies] - no command line Switch. - - // String Properties - // Skip [Inputs] - no command line Switch. - { "ObjectFileName", "Fo", "Object File Name", "", - cmVS7FlagTable::UserValue }, - { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "", - cmVS7FlagTable::UserValue }, - // Skip [CommandLineTemplate] - no command line Switch. - // Skip [ExecutionDescription] - no command line Switch. - // Skip [AdditionalOptions] - no command line Switch. - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVS14RCFlagTable.h b/Source/cmVS14RCFlagTable.h deleted file mode 100644 index 5dc8d5ada..000000000 --- a/Source/cmVS14RCFlagTable.h +++ /dev/null @@ -1,7 +0,0 @@ -static cmVS7FlagTable cmVS14RCFlagTable[] = { - // Bool Properties - { "NullTerminateStrings", "n", "", "true", 0 }, - { "SuppressStartupBanner", "nologo", "", "true", 0 }, - - { 0, 0, 0, 0, 0 } -}; diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index 19c96b3bb..c78361e26 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -57,8 +57,9 @@ std::string VSInstanceInfo::GetInstallLocation() const return loc; } -cmVSSetupAPIHelper::cmVSSetupAPIHelper() - : setupConfig(NULL) +cmVSSetupAPIHelper::cmVSSetupAPIHelper(unsigned int version) + : Version(version) + , setupConfig(NULL) , setupConfig2(NULL) , setupHelper(NULL) , initializationFailure(false) @@ -88,7 +89,7 @@ bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation) return this->EnumerateAndChooseVSInstance(); } -bool cmVSSetupAPIHelper::IsVS2017Installed() +bool cmVSSetupAPIHelper::IsVSInstalled() { return this->EnumerateAndChooseVSInstance(); } @@ -187,7 +188,7 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo( // Check if a compiler is installed with this instance. { std::string const vcRoot = vsInstanceInfo.GetInstallLocation(); - std::string const vcToolsVersionFile = + std::string vcToolsVersionFile = vcRoot + "/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt"; std::string vcToolsVersion; cmsys::ifstream fin(vcToolsVersionFile.c_str()); @@ -267,6 +268,19 @@ bool cmVSSetupAPIHelper::GetVCToolsetVersion(std::string& vsToolsetVersion) return isInstalled && !vsToolsetVersion.empty(); } +bool cmVSSetupAPIHelper::IsEWDKEnabled() +{ + std::string envEnterpriseWDK, envDisableRegistryUse; + cmSystemTools::GetEnv("EnterpriseWDK", envEnterpriseWDK); + cmSystemTools::GetEnv("DisableRegistryUse", envDisableRegistryUse); + if (!cmSystemTools::Strucmp(envEnterpriseWDK.c_str(), "True") && + !cmSystemTools::Strucmp(envDisableRegistryUse.c_str(), "True")) { + return true; + } + + return false; +} + bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() { bool isVSInstanceExists = false; @@ -274,16 +288,36 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() return true; } + if (this->IsEWDKEnabled()) { + std::string envWindowsSdkDir81, envVSVersion, envVsInstallDir; + + cmSystemTools::GetEnv("WindowsSdkDir_81", envWindowsSdkDir81); + cmSystemTools::GetEnv("VisualStudioVersion", envVSVersion); + cmSystemTools::GetEnv("VSINSTALLDIR", envVsInstallDir); + if (envVSVersion.empty() || envVsInstallDir.empty()) + return false; + + chosenInstanceInfo.VSInstallLocation = + std::wstring(envVsInstallDir.begin(), envVsInstallDir.end()); + chosenInstanceInfo.Version = + std::wstring(envVSVersion.begin(), envVSVersion.end()); + chosenInstanceInfo.VCToolsetVersion = envVSVersion; + chosenInstanceInfo.ullVersion = std::stoi(envVSVersion); + chosenInstanceInfo.IsWin10SDKInstalled = true; + chosenInstanceInfo.IsWin81SDKInstalled = !envWindowsSdkDir81.empty(); + return true; + } + if (initializationFailure || setupConfig == NULL || setupConfig2 == NULL || setupHelper == NULL) return false; std::string envVSCommonToolsDir; + std::string envVSCommonToolsDirEnvName = + "VS" + std::to_string(this->Version) + "0COMNTOOLS"; - // FIXME: When we support VS versions beyond 2017, the version - // to choose will be passed in by the caller. We need to map that - // to a per-version name of this environment variable. - if (cmSystemTools::GetEnv("VS150COMNTOOLS", envVSCommonToolsDir)) { + if (cmSystemTools::GetEnv(envVSCommonToolsDirEnvName.c_str(), + envVSCommonToolsDir)) { cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir); } @@ -295,8 +329,7 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() return false; } - // FIXME: Add a way for caller to specify other versions. - std::wstring wantVersion = std::to_wstring(15) + L'.'; + std::wstring const wantVersion = std::to_wstring(this->Version) + L'.'; SmartCOMPtr<ISetupInstance> instance; while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index 4144c1541..1bda54a47 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -112,20 +112,18 @@ struct VSInstanceInfo bool IsWin10SDKInstalled = false; bool IsWin81SDKInstalled = false; - VSInstanceInfo() = default; - std::string GetInstallLocation() const; }; class cmVSSetupAPIHelper { public: - cmVSSetupAPIHelper(); + cmVSSetupAPIHelper(unsigned int version); ~cmVSSetupAPIHelper(); bool SetVSInstance(std::string const& vsInstallLocation); - bool IsVS2017Installed(); + bool IsVSInstalled(); bool GetVSInstanceInfo(std::string& vsInstallLocation); bool GetVCToolsetVersion(std::string& vsToolsetVersion); bool IsWin10SDKInstalled(); @@ -140,6 +138,8 @@ private: int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances); bool EnumerateAndChooseVSInstance(); + unsigned int Version; + // COM ptrs to query about VS instances SmartCOMPtr<ISetupConfiguration> setupConfig; SmartCOMPtr<ISetupConfiguration2> setupConfig2; @@ -150,6 +150,7 @@ private: HRESULT comInitialized; // current best instance of VS selected VSInstanceInfo chosenInstanceInfo; + bool IsEWDKEnabled(); std::string SpecifiedVSInstallLocation; }; diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index 06ca53c0a..c02157ad1 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -57,7 +57,7 @@ bool cmVariableRequiresCommand::InitialPass( "One or more of the required variables is advanced." " To set the variable, you must turn on advanced mode in cmake."; } - cmSystemTools::Error(message.c_str()); + cmSystemTools::Error(message); } return true; diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx index bd5d19c39..3df142099 100644 --- a/Source/cmVariableWatch.cxx +++ b/Source/cmVariableWatch.cxx @@ -19,13 +19,9 @@ const char* cmVariableWatch::GetAccessAsString(int access_type) return cmVariableWatchAccessStrings[access_type]; } -cmVariableWatch::cmVariableWatch() -{ -} +cmVariableWatch::cmVariableWatch() = default; -cmVariableWatch::~cmVariableWatch() -{ -} +cmVariableWatch::~cmVariableWatch() = default; bool cmVariableWatch::AddWatch(const std::string& variable, WatchMethod method, void* client_data /*=0*/, diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h index 27d1b12df..5855fed29 100644 --- a/Source/cmVariableWatch.h +++ b/Source/cmVariableWatch.h @@ -63,15 +63,9 @@ public: protected: struct Pair { - WatchMethod Method; - void* ClientData; - DeleteData DeleteDataCall; - Pair() - : Method(nullptr) - , ClientData(nullptr) - , DeleteDataCall(nullptr) - { - } + WatchMethod Method = nullptr; + void* ClientData = nullptr; + DeleteData DeleteDataCall = nullptr; ~Pair() { if (this->DeleteDataCall && this->ClientData) { diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index e080df1ec..5fe55bd53 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -7,6 +7,7 @@ #include "cmExecutionStatus.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" #include "cmVariableWatch.h" #include "cmake.h" @@ -59,7 +60,7 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable, error << "Error in cmake code at\nUnknown:0:\n" << "A command failed during the invocation of callback \"" << data->Command << "\"."; - cmSystemTools::Error(error.str().c_str()); + cmSystemTools::Error(error.str()); data->InCallback = false; return; } @@ -70,7 +71,7 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable, msg << "Variable \"" << variable << "\" was accessed using " << accessString << " with value \"" << (newValue ? newValue : "") << "\"."; - makefile->IssueMessage(cmake::LOG, msg.str()); + makefile->IssueMessage(MessageType::LOG, msg.str()); } data->InCallback = false; @@ -83,9 +84,7 @@ static void deleteVariableWatchCallbackData(void* client_data) delete data; } -cmVariableWatchCommand::cmVariableWatchCommand() -{ -} +cmVariableWatchCommand::cmVariableWatchCommand() = default; cmVariableWatchCommand::~cmVariableWatchCommand() { diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index d5e834b45..7736e593b 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -6,6 +6,7 @@ #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" #include "cmGeneratedFileStream.h" +#include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalVisualStudio10Generator.h" #include "cmLocalVisualStudio10Generator.h" @@ -34,6 +35,7 @@ static std::string cmVS10EscapeAttr(std::string arg) cmSystemTools::ReplaceString(arg, "<", "<"); cmSystemTools::ReplaceString(arg, ">", ">"); cmSystemTools::ReplaceString(arg, "\"", """); + cmSystemTools::ReplaceString(arg, "\n", " "); return arg; } @@ -45,24 +47,21 @@ struct cmVisualStudio10TargetGenerator::Elem bool HasContent = false; std::string Tag; - Elem(std::ostream& s) + Elem(std::ostream& s, const char* tag) : S(s) , Indent(0) + , Tag(tag) { + this->StartElement(); } Elem(const Elem&) = delete; - Elem(Elem& par) - : S(par.S) - , Indent(par.Indent + 1) - { - par.SetHasElements(); - } Elem(Elem& par, const char* tag) : S(par.S) , Indent(par.Indent + 1) + , Tag(tag) { par.SetHasElements(); - this->StartElement(tag); + this->StartElement(); } void SetHasElements() { @@ -72,12 +71,7 @@ struct cmVisualStudio10TargetGenerator::Elem } } std::ostream& WriteString(const char* line); - Elem& StartElement(const std::string& tag) - { - this->Tag = tag; - this->WriteString("<") << tag; - return *this; - } + void StartElement() { this->WriteString("<") << this->Tag; } void Element(const char* tag, const std::string& val) { Elem(*this, tag).Content(val); @@ -87,8 +81,6 @@ struct cmVisualStudio10TargetGenerator::Elem this->S << " " << an << "=\"" << cmVS10EscapeAttr(av) << "\""; return *this; } - // This method for now assumes that this->Tag has been set, e.g. by calling - // StartElement(). void Content(const std::string& val) { if (!this->HasContent) { @@ -307,6 +299,11 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString( "$(UserRootDir)\\Microsoft.CSharp.$(Platform).user.props" #define VS10_CSharp_TARGETS "$(MSBuildToolsPath)\\Microsoft.CSharp.targets" +#define VS10_CSharp_NETCF_TARGETS \ + "$(MSBuildExtensionsPath)\\Microsoft\\$(TargetFrameworkIdentifier)\\" \ + "$(TargetFrameworkTargetsVersion)\\Microsoft.$(TargetFrameworkIdentifier)" \ + ".CSharp.targets" + void cmVisualStudio10TargetGenerator::Generate() { // do not generate external ms projects @@ -325,8 +322,7 @@ void cmVisualStudio10TargetGenerator::Generate() this->GeneratorTarget->GetName() + "\" is of type STATIC_LIBRARY. This is discouraged (and may be " "disabled in future). Make it a SHARED library instead."; - this->Makefile->IssueMessage(cmake::MessageType::DEPRECATION_WARNING, - message); + this->Makefile->IssueMessage(MessageType::DEPRECATION_WARNING, message); } this->ProjectType = csproj; this->Managed = true; @@ -379,10 +375,15 @@ void cmVisualStudio10TargetGenerator::Generate() << this->GlobalGenerator->Encoding() << "\"?>" << "\n"; { - Elem e0(BuildFileStream); - e0.StartElement("Project"); + Elem e0(BuildFileStream, "Project"); e0.Attribute("DefaultTargets", "Build"); - e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion()); + const char* toolsVersion = this->GlobalGenerator->GetToolsVersion(); + if (this->GlobalGenerator->GetVersion() == + cmGlobalVisualStudioGenerator::VS12 && + this->GlobalGenerator->TargetsWindowsCE()) { + toolsVersion = "4.0"; + } + e0.Attribute("ToolsVersion", toolsVersion); e0.Attribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); @@ -491,9 +492,31 @@ void cmVisualStudio10TargetGenerator::Generate() targetFrameworkVersion = this->GeneratorTarget->GetProperty( "DOTNET_TARGET_FRAMEWORK_VERSION"); } + if (!targetFrameworkVersion && this->ProjectType == csproj && + this->GlobalGenerator->TargetsWindowsCE() && + this->GlobalGenerator->GetVersion() == + cmGlobalVisualStudioGenerator::VS12) { + // VS12 .NETCF default to .NET framework 3.9 + targetFrameworkVersion = "v3.9"; + } if (targetFrameworkVersion) { e1.Element("TargetFrameworkVersion", targetFrameworkVersion); } + if (this->ProjectType == csproj && + this->GlobalGenerator->TargetsWindowsCE()) { + const char* targetFrameworkId = this->GeneratorTarget->GetProperty( + "VS_TARGET_FRAMEWORK_IDENTIFIER"); + if (!targetFrameworkId) { + targetFrameworkId = "WindowsEmbeddedCompact"; + } + e1.Element("TargetFrameworkIdentifier", targetFrameworkId); + const char* targetFrameworkVer = this->GeneratorTarget->GetProperty( + "VS_TARGET_FRAMEWORKS_TARGET_VERSION"); + if (!targetFrameworkVer) { + targetFrameworkVer = "v8.0"; + } + e1.Element("TargetFrameworkTargetsVersion", targetFrameworkVer); + } } // Disable the project upgrade prompt that is displayed the first time a @@ -634,6 +657,7 @@ void cmVisualStudio10TargetGenerator::Generate() Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros"); this->WriteWinRTPackageCertificateKeyFile(e0); this->WritePathAndIncrementalLinkOptions(e0); + this->WriteCEDebugProjectConfigurationValues(e0); this->WriteItemDefinitionGroups(e0); this->WriteCustomCommands(e0); this->WriteAllSources(e0); @@ -648,7 +672,11 @@ void cmVisualStudio10TargetGenerator::Generate() Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS); break; case csproj: - Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS); + if (this->GlobalGenerator->TargetsWindowsCE()) { + Elem(e0, "Import").Attribute("Project", VS10_CSharp_NETCF_TARGETS); + } else { + Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS); + } break; } @@ -734,7 +762,8 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) // if the entry from VS_DOTNET_REFERENCES is an existing file, generate // a new hint-reference and name it from the filename if (cmsys::SystemTools::FileExists(ri, true)) { - std::string name = cmsys::SystemTools::GetFilenameWithoutExtension(ri); + std::string name = + cmsys::SystemTools::GetFilenameWithoutLastExtension(ri); std::string path = ri; ConvertToWindowsSlash(path); this->DotNetHintReferences[""].push_back( @@ -921,8 +950,8 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0) xamlType = "Page"; } - Elem e2(e1); - this->WriteSource(e2, xamlType, oi); + Elem e2(e1, xamlType); + this->WriteSource(e2, oi); e2.SetHasElements(); if (this->ProjectType == csproj && !this->InSourceBuild) { // add <Link> tag to written XAML source if necessary @@ -1081,6 +1110,32 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0) } } +void cmVisualStudio10TargetGenerator::WriteCEDebugProjectConfigurationValues( + Elem& e0) +{ + if (!this->GlobalGenerator->TargetsWindowsCE()) { + return; + } + const char* additionalFiles = + this->GeneratorTarget->GetProperty("DEPLOYMENT_ADDITIONAL_FILES"); + const char* remoteDirectory = + this->GeneratorTarget->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY"); + if (!(additionalFiles || remoteDirectory)) { + return; + } + for (std::string const& c : this->Configurations) { + Elem e1(e0, "PropertyGroup"); + e1.Attribute("Condition", this->CalcCondition(c)); + + if (remoteDirectory) { + e1.Element("RemoteDirectory", remoteDirectory); + } + if (additionalFiles) { + e1.Element("CEAdditionalFiles", additionalFiles); + } + } +} + void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( Elem& e1, std::string const& config) { @@ -1278,15 +1333,15 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( std::unique_ptr<Elem> spe2; if (this->ProjectType != csproj) { spe1 = cm::make_unique<Elem>(e0, "ItemGroup"); - spe2 = cm::make_unique<Elem>(*spe1); - this->WriteSource(*spe2, "CustomBuild", source); + spe2 = cm::make_unique<Elem>(*spe1, "CustomBuild"); + this->WriteSource(*spe2, source); spe2->SetHasElements(); } else { Elem e1(e0, "ItemGroup"); - Elem e2(e1); + Elem e2(e1, "None"); std::string link; this->GetCSharpSourceLink(source, link); - this->WriteSource(e2, "None", source); + this->WriteSource(e2, source); e2.SetHasElements(); if (!link.empty()) { e2.Element("Link", link); @@ -1402,6 +1457,14 @@ void cmVisualStudio10TargetGenerator::WriteGroups() groupsUsed.insert(sourceGroup); } + if (cmSourceFile const* srcCMakeLists = + this->LocalGenerator->CreateVCProjBuildRule()) { + std::string const& source = srcCMakeLists->GetFullPath(); + cmSourceGroup* sourceGroup = + this->Makefile->FindSourceGroup(source, sourceGroups); + groupsUsed.insert(sourceGroup); + } + this->AddMissingSourceGroups(groupsUsed, sourceGroups); // Write out group file @@ -1419,8 +1482,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() << this->GlobalGenerator->Encoding() << "\"?>" << "\n"; { - Elem e0(fout); - e0.StartElement("Project"); + Elem e0(fout, "Project"); e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion()); e0.Attribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); @@ -1571,8 +1633,8 @@ void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1, cmSourceFile const* sf) { std::string const& fileName = sf->GetFullPath(); - Elem e2(e1); - this->WriteSource(e2, "ClInclude", sf); + Elem e2(e1, "ClInclude"); + this->WriteSource(e2, sf); if (this->IsResxHeader(fileName)) { e2.Element("FileType", "CppForm"); } else if (this->IsXamlHeader(fileName)) { @@ -1692,6 +1754,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, subType = "Designer"; } if (const char* c = sf->GetProperty("VS_COPY_TO_OUT_DIR")) { + tool = "Content"; copyToOutDir = c; toolHasSettings = true; } @@ -1740,8 +1803,8 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, } } - Elem e2(e1); - this->WriteSource(e2, tool, sf); + Elem e2(e1, tool); + this->WriteSource(e2, sf); if (toolHasSettings) { e2.SetHasElements(); @@ -1861,7 +1924,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, } void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2, - std::string const& tool, cmSourceFile const* sf) { // Visual Studio tools append relative paths to the current dir, as in: @@ -1897,11 +1959,10 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2, } } ConvertToWindowsSlash(sourceFile); - e2.StartElement(tool); e2.Attribute("Include", sourceFile); ToolSource toolSource = { sf, forceRelative }; - this->Tools[tool].push_back(toolSource); + this->Tools[e2.Tag].push_back(toolSource); } void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) @@ -2005,8 +2066,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) include_configs.begin(), include_configs.end(), std::back_inserter(exclude_configs)); - Elem e2(e1); - this->WriteSource(e2, tool, si.Source); + Elem e2(e1, tool); + this->WriteSource(e2, si.Source); if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) { this->OutputSourceSpecificFlags(e2, si.Source); } @@ -2229,6 +2290,58 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( e1.Element("_ProjectFileVersion", "10.0.20506.1"); for (std::string const& config : this->Configurations) { const std::string cond = this->CalcCondition(config); + + if (ttype <= cmStateEnums::UTILITY) { + if (const char* workingDir = this->GeneratorTarget->GetProperty( + "VS_DEBUGGER_WORKING_DIRECTORY")) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(workingDir); + std::string genWorkingDir = + cge->Evaluate(this->LocalGenerator, config); + + e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond, + genWorkingDir); + } + + if (const char* environment = + this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(environment); + std::string genEnvironment = + cge->Evaluate(this->LocalGenerator, config); + + e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond, + genEnvironment); + } + + if (const char* debuggerCommand = + this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) { + + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(debuggerCommand); + std::string genDebuggerCommand = + cge->Evaluate(this->LocalGenerator, config); + + e1.WritePlatformConfigTag("LocalDebuggerCommand", cond, + genDebuggerCommand); + } + + if (const char* commandArguments = this->GeneratorTarget->GetProperty( + "VS_DEBUGGER_COMMAND_ARGUMENTS")) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(commandArguments); + std::string genCommandArguments = + cge->Evaluate(this->LocalGenerator, config); + + e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond, + genCommandArguments); + } + } + if (ttype >= cmStateEnums::UTILITY) { e1.WritePlatformConfigTag( "IntDir", cond, "$(Platform)\\$(Configuration)\\$(ProjectName)\\"); @@ -2293,55 +2406,6 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( e1.WritePlatformConfigTag("ExcludePath", cond, sdkExcludeDirectories); } - if (const char* workingDir = this->GeneratorTarget->GetProperty( - "VS_DEBUGGER_WORKING_DIRECTORY")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(workingDir); - std::string genWorkingDir = - cge->Evaluate(this->LocalGenerator, config); - - e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond, - genWorkingDir); - } - - if (const char* environment = - this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(environment); - std::string genEnvironment = - cge->Evaluate(this->LocalGenerator, config); - - e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond, - genEnvironment); - } - - if (const char* debuggerCommand = - this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) { - - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(debuggerCommand); - std::string genDebuggerCommand = - cge->Evaluate(this->LocalGenerator, config); - - e1.WritePlatformConfigTag("LocalDebuggerCommand", cond, - genDebuggerCommand); - } - - if (const char* commandArguments = this->GeneratorTarget->GetProperty( - "VS_DEBUGGER_COMMAND_ARGUMENTS")) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(commandArguments); - std::string genCommandArguments = - cge->Evaluate(this->LocalGenerator, config); - - e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond, - genCommandArguments); - } - std::string name = cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); e1.WritePlatformConfigTag("TargetName", cond, name); @@ -2536,7 +2600,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( "\" the /clr compiler flag was added manually. " + "Set usage of C++/CLI by setting COMMON_LANGUAGE_RUNTIME " "target property."; - this->Makefile->IssueMessage(cmake::MessageType::WARNING, message); + this->Makefile->IssueMessage(MessageType::WARNING, message); } } if (auto* clr = @@ -2566,6 +2630,10 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } clOptions.AddDefines(targetDefines); + if (this->ProjectType == csproj) { + clOptions.AppendFlag("DefineConstants", targetDefines); + } + // Get includes for this target if (!this->LangForClCompile.empty()) { clOptions.AddIncludes( @@ -2582,8 +2650,9 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( configDefine += configName; configDefine += "\""; clOptions.AddDefine(configDefine); - if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) { - clOptions.AddDefine(exportMacro); + if (const std::string* exportMacro = + this->GeneratorTarget->GetExportMacro()) { + clOptions.AddDefine(*exportMacro); } if (this->MSTools) { @@ -2879,8 +2948,9 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( configDefine += configName; configDefine += "\""; cudaOptions.AddDefine(configDefine); - if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) { - cudaOptions.AddDefine(exportMacro); + if (const std::string* exportMacro = + this->GeneratorTarget->GetExportMacro()) { + cudaOptions.AddDefine(*exportMacro); } // Get includes for this target @@ -2929,18 +2999,19 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( // Determine if we need to do a device link bool doDeviceLinking = false; - switch (this->GeneratorTarget->GetType()) { - case cmStateEnums::SHARED_LIBRARY: - case cmStateEnums::MODULE_LIBRARY: - case cmStateEnums::EXECUTABLE: - doDeviceLinking = true; - break; - case cmStateEnums::STATIC_LIBRARY: - doDeviceLinking = this->GeneratorTarget->GetPropertyAsBool( - "CUDA_RESOLVE_DEVICE_SYMBOLS"); - break; - default: - break; + if (const char* resolveDeviceSymbols = + this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { + doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); + } else { + switch (this->GeneratorTarget->GetType()) { + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::EXECUTABLE: + doDeviceLinking = true; + break; + default: + break; + } } cudaLinkOptions.AddFlag("PerformDeviceLink", @@ -3521,8 +3592,8 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions( this->LocalGenerator->GetCurrentBinaryDirectory(); for (cmComputeLinkInformation::Item const& l : libs) { if (l.IsPath && cmVS10IsTargetsFile(l.Value)) { - std::string path = - this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value); + std::string path = this->LocalGenerator->MaybeConvertToRelativePath( + currentBinDir, l.Value); ConvertToWindowsSlash(path); this->AddTargetsFileAndConfigPair(path, config); } @@ -3605,8 +3676,8 @@ void cmVisualStudio10TargetGenerator::AddLibraries( } if (l.IsPath) { - std::string path = - this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value); + std::string path = this->LocalGenerator->MaybeConvertToRelativePath( + currentBinDir, l.Value); ConvertToWindowsSlash(path); if (cmVS10IsTargetsFile(l.Value)) { vsTargetVec.push_back(path); @@ -3821,8 +3892,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) this->WriteDotNetReferenceCustomTags(e2, name); // If the dependency target is not managed (compiled with /clr or - // C# target) we cannot reference it and have to set - // 'ReferenceOutputAssembly' to false. + // C# target) and not a WinRT component we cannot reference it and + // have to set 'ReferenceOutputAssembly' to false. auto referenceNotManaged = dt->GetManagedType("") < cmGeneratorTarget::ManagedType::Mixed; // Workaround to check for manually set /clr flags. @@ -3839,6 +3910,12 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) if (referenceNotManaged && dt->GetType() == cmStateEnums::STATIC_LIBRARY) { referenceNotManaged = !dt->IsCSharpOnly(); } + + // Referencing WinRT components is okay. + if (referenceNotManaged) { + referenceNotManaged = !dt->GetPropertyAsBool("VS_WINRT_COMPONENT"); + } + if (referenceNotManaged) { e2.Element("ReferenceOutputAssembly", "false"); e2.Element("CopyToOutputDirectory", "Never"); @@ -3885,15 +3962,13 @@ void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension( void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0) { std::vector<std::string> sdkReferences; - Elem e1(e0); - bool hasWrittenItemGroup = false; + std::unique_ptr<Elem> spe1; if (const char* vsSDKReferences = this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) { cmSystemTools::ExpandListArgument(vsSDKReferences, sdkReferences); - e1.StartElement("ItemGroup"); - hasWrittenItemGroup = true; + spe1 = cm::make_unique<Elem>(e0, "ItemGroup"); for (std::string const& ri : sdkReferences) { - Elem(e1, "SDKReference").Attribute("Include", ri); + Elem(*spe1, "SDKReference").Attribute("Include", ri); } } @@ -3909,19 +3984,20 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0) if (desktopExtensionsVersion || mobileExtensionsVersion || iotExtensionsVersion) { - if (!hasWrittenItemGroup) { - e1.StartElement("ItemGroup"); + if (!spe1) { + spe1 = cm::make_unique<Elem>(e0, "ItemGroup"); } if (desktopExtensionsVersion) { - this->WriteSingleSDKReference(e1, "WindowsDesktop", + this->WriteSingleSDKReference(*spe1, "WindowsDesktop", desktopExtensionsVersion); } if (mobileExtensionsVersion) { - this->WriteSingleSDKReference(e1, "WindowsMobile", + this->WriteSingleSDKReference(*spe1, "WindowsMobile", mobileExtensionsVersion); } if (iotExtensionsVersion) { - this->WriteSingleSDKReference(e1, "WindowsIoT", iotExtensionsVersion); + this->WriteSingleSDKReference(*spe1, "WindowsIoT", + iotExtensionsVersion); } } } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 0dc03b655..590100496 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -25,12 +25,16 @@ class cmVS10GeneratorOptions; class cmVisualStudio10TargetGenerator { - CM_DISABLE_COPY(cmVisualStudio10TargetGenerator) - public: cmVisualStudio10TargetGenerator(cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg); ~cmVisualStudio10TargetGenerator(); + + cmVisualStudio10TargetGenerator(cmVisualStudio10TargetGenerator const&) = + delete; + cmVisualStudio10TargetGenerator& operator=( + cmVisualStudio10TargetGenerator const&) = delete; + void Generate(); private: @@ -57,13 +61,14 @@ private: void WriteProjectConfigurations(Elem& e0); void WriteProjectConfigurationValues(Elem& e0); void WriteMSToolConfigurationValues(Elem& e1, std::string const& config); + void WriteCEDebugProjectConfigurationValues(Elem& e0); void WriteMSToolConfigurationValuesManaged(Elem& e1, std::string const& config); void WriteHeaderSource(Elem& e1, cmSourceFile const* sf); void WriteExtraSource(Elem& e1, cmSourceFile const* sf); void WriteNsightTegraConfigurationValues(Elem& e1, std::string const& config); - void WriteSource(Elem& e2, std::string const& tool, cmSourceFile const* sf); + void WriteSource(Elem& e2, cmSourceFile const* sf); void WriteExcludeFromBuild(Elem& e2, std::vector<size_t> const& exclude_configs); void WriteAllSources(Elem& e0); diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx index 9a1d95078..a490e03df 100644 --- a/Source/cmVisualStudio10ToolsetOptions.cxx +++ b/Source/cmVisualStudio10ToolsetOptions.cxx @@ -6,145 +6,127 @@ #include "cmIDEFlagTable.h" #include "cmVisualStudioGeneratorOptions.h" -#include "cmVS10CLFlagTable.h" -#include "cmVS10CSharpFlagTable.h" -#include "cmVS10LibFlagTable.h" -#include "cmVS10LinkFlagTable.h" -#include "cmVS10MASMFlagTable.h" -#include "cmVS10RCFlagTable.h" -#include "cmVS11CLFlagTable.h" -#include "cmVS11CSharpFlagTable.h" -#include "cmVS11LibFlagTable.h" -#include "cmVS11LinkFlagTable.h" -#include "cmVS11MASMFlagTable.h" -#include "cmVS11RCFlagTable.h" -#include "cmVS12CLFlagTable.h" -#include "cmVS12CSharpFlagTable.h" -#include "cmVS12LibFlagTable.h" -#include "cmVS12LinkFlagTable.h" -#include "cmVS12MASMFlagTable.h" -#include "cmVS12RCFlagTable.h" -#include "cmVS140CLFlagTable.h" -#include "cmVS140CSharpFlagTable.h" -#include "cmVS140LinkFlagTable.h" -#include "cmVS141CLFlagTable.h" -#include "cmVS141CSharpFlagTable.h" -#include "cmVS141LinkFlagTable.h" -#include "cmVS14LibFlagTable.h" -#include "cmVS14MASMFlagTable.h" -#include "cmVS14RCFlagTable.h" - -cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetClFlagTable( +std::string cmVisualStudio10ToolsetOptions::GetClFlagTableName( std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); - if (toolset == "v141") { - return cmVS141CLFlagTable; + if (toolset == "v142") { + return "v142"; + } else if (toolset == "v141") { + return "v141"; } else if (useToolset == "v140") { - return cmVS140CLFlagTable; + return "v140"; } else if (useToolset == "v120") { - return cmVS12CLFlagTable; + return "v12"; } else if (useToolset == "v110") { - return cmVS11CLFlagTable; + return "v11"; } else if (useToolset == "v100") { - return cmVS10CLFlagTable; + return "v10"; } else { - return 0; + return ""; } } -cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetCSharpFlagTable( +std::string cmVisualStudio10ToolsetOptions::GetCSharpFlagTableName( std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); - if ((useToolset == "v141")) { - return cmVS141CSharpFlagTable; + if (useToolset == "v142") { + // FIXME: Add CSharp flag table for v142. + return "v141"; + } else if (useToolset == "v141") { + return "v141"; } else if (useToolset == "v140") { - return cmVS140CSharpFlagTable; + return "v140"; } else if (useToolset == "v120") { - return cmVS12CSharpFlagTable; + return "v12"; } else if (useToolset == "v110") { - return cmVS11CSharpFlagTable; + return "v11"; } else if (useToolset == "v100") { - return cmVS10CSharpFlagTable; + return "v10"; } else { - return 0; + return ""; } } -cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetRcFlagTable( +std::string cmVisualStudio10ToolsetOptions::GetRcFlagTableName( std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); - if ((useToolset == "v140") || (useToolset == "v141")) { - return cmVS14RCFlagTable; + if ((useToolset == "v140") || (useToolset == "v141") || + (useToolset == "v142")) { + return "v14"; } else if (useToolset == "v120") { - return cmVS12RCFlagTable; + return "v12"; } else if (useToolset == "v110") { - return cmVS11RCFlagTable; + return "v11"; } else if (useToolset == "v100") { - return cmVS10RCFlagTable; + return "v10"; } else { - return 0; + return ""; } } -cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetLibFlagTable( +std::string cmVisualStudio10ToolsetOptions::GetLibFlagTableName( std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); - if ((useToolset == "v140") || (useToolset == "v141")) { - return cmVS14LibFlagTable; + if ((useToolset == "v140") || (useToolset == "v141") || + (useToolset == "v142")) { + return "v14"; } else if (useToolset == "v120") { - return cmVS12LibFlagTable; + return "v12"; } else if (useToolset == "v110") { - return cmVS11LibFlagTable; + return "v11"; } else if (useToolset == "v100") { - return cmVS10LibFlagTable; + return "v10"; } else { - return 0; + return ""; } } -cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetLinkFlagTable( +std::string cmVisualStudio10ToolsetOptions::GetLinkFlagTableName( std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); - if (useToolset == "v141") { - return cmVS141LinkFlagTable; + if (useToolset == "v142") { + return "v142"; + } else if (useToolset == "v141") { + return "v141"; } else if (useToolset == "v140") { - return cmVS140LinkFlagTable; + return "v140"; } else if (useToolset == "v120") { - return cmVS12LinkFlagTable; + return "v12"; } else if (useToolset == "v110") { - return cmVS11LinkFlagTable; + return "v11"; } else if (useToolset == "v100") { - return cmVS10LinkFlagTable; + return "v10"; } else { - return 0; + return ""; } } -cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetMasmFlagTable( +std::string cmVisualStudio10ToolsetOptions::GetMasmFlagTableName( std::string const& name, std::string const& toolset) const { std::string const useToolset = this->GetToolsetName(name, toolset); - if ((useToolset == "v140") || (useToolset == "v141")) { - return cmVS14MASMFlagTable; + if ((useToolset == "v140") || (useToolset == "v141") || + (useToolset == "v142")) { + return "v14"; } else if (useToolset == "v120") { - return cmVS12MASMFlagTable; + return "v12"; } else if (useToolset == "v110") { - return cmVS11MASMFlagTable; + return "v11"; } else if (useToolset == "v100") { - return cmVS10MASMFlagTable; + return "v10"; } else { - return 0; + return ""; } } diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h index c736a49f5..875a35b24 100644 --- a/Source/cmVisualStudio10ToolsetOptions.h +++ b/Source/cmVisualStudio10ToolsetOptions.h @@ -7,8 +7,6 @@ #include <string> -struct cmIDEFlagTable; - /** \class cmVisualStudio10ToolsetOptions * \brief Retrieves toolset options for MSBuild. * @@ -17,20 +15,18 @@ struct cmIDEFlagTable; class cmVisualStudio10ToolsetOptions { public: - cmIDEFlagTable const* GetClFlagTable(std::string const& name, - std::string const& toolset) const; - cmIDEFlagTable const* GetCSharpFlagTable(std::string const& name, - std::string const& toolset) const; - cmIDEFlagTable const* GetRcFlagTable(std::string const& name, - std::string const& toolset) const; - cmIDEFlagTable const* GetLibFlagTable(std::string const& name, - std::string const& toolset) const; - cmIDEFlagTable const* GetLinkFlagTable(std::string const& name, - std::string const& toolset) const; - cmIDEFlagTable const* GetMasmFlagTable(std::string const& name, - std::string const& toolset) const; - -private: + std::string GetClFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetCSharpFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetRcFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetLibFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetLinkFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetMasmFlagTableName(std::string const& name, + std::string const& toolset) const; std::string GetToolsetName(std::string const& name, std::string const& toolset) const; }; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 5d67dcf51..5c3e533b8 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -70,6 +70,7 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() case cmGlobalVisualStudioGenerator::VS12: case cmGlobalVisualStudioGenerator::VS14: case cmGlobalVisualStudioGenerator::VS15: + case cmGlobalVisualStudioGenerator::VS16: // by default VS puts <ExceptionHandling></ExceptionHandling> empty // for a project, to make our projects look the same put a new line // and space over for the closing </ExceptionHandling> as the default @@ -269,7 +270,7 @@ void cmVisualStudioGeneratorOptions::FixManifestUACFlags() if (keyValue[1].front() == '\'' && keyValue[1].back() == '\'') { keyValue[1] = - keyValue[1].substr(1, std::max<int>(0, keyValue[1].size() - 2)); + keyValue[1].substr(1, std::max(0, cm::isize(keyValue[1]) - 2)); } if (keyValue[0] == "level") { diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx index a9acb3fce..93532765f 100644 --- a/Source/cmVisualStudioSlnParser.cxx +++ b/Source/cmVisualStudioSlnParser.cxx @@ -602,8 +602,8 @@ bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag, } const std::string& arg = cmSystemTools::TrimWhitespace( fullTag.substr(idxLeftParen + 1, idxRightParen - idxLeftParen - 1)); - if (arg[0] == '"') { - if (arg[arg.size() - 1] != '"') { + if (arg.front() == '"') { + if (arg.back() != '"') { this->LastResult.SetError(ResultErrorInputStructure, state.GetCurrentLine()); return false; @@ -620,7 +620,7 @@ bool cmVisualStudioSlnParser::ParseValue(const std::string& value, const std::string& trimmed = cmSystemTools::TrimWhitespace(value); if (trimmed.empty()) parsedLine.AddValue(trimmed); - else if (trimmed[0] == '"' && trimmed[trimmed.size() - 1] == '"') + else if (trimmed.front() == '"' && trimmed.back() == '"') parsedLine.AddQuotedValue(trimmed.substr(1, trimmed.size() - 2)); else parsedLine.AddValue(trimmed); diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index d5bcfc230..a01fa6f1c 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -6,8 +6,8 @@ #include "cmExecutionStatus.h" #include "cmExpandedCommandArgument.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmSystemTools.h" -#include "cmake.h" #include <memory> // IWYU pragma: keep @@ -37,7 +37,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, // Remove the function blocker for this scope or bail. std::unique_ptr<cmFunctionBlocker> fb( mf.RemoveFunctionBlocker(this, lff)); - if (!fb.get()) { + if (!fb) { return false; } @@ -45,7 +45,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, std::vector<cmExpandedCommandArgument> expandedArguments; mf.ExpandArguments(this->Args, expandedArguments); - cmake::MessageType messageType; + MessageType messageType; cmListFileContext execContext = this->GetStartingContext(); @@ -72,7 +72,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, err += errorString; err += ")."; mf.IssueMessage(messageType, err); - if (messageType == cmake::FATAL_ERROR) { + if (messageType == MessageType::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); return true; } diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx index c504ef436..49dbf1a19 100644 --- a/Source/cmWriteFileCommand.cxx +++ b/Source/cmWriteFileCommand.cxx @@ -50,7 +50,7 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args, // Set permissions to writable if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) { #if defined(_MSC_VER) || defined(__MINGW32__) - writable = mode & S_IWRITE; + writable = (mode & S_IWRITE) != 0; mode_t newMode = mode | S_IWRITE; #else writable = mode & S_IWUSR; diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index 58cb9c9d3..1b161987a 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -5,16 +5,17 @@ #include <iomanip> #include <iostream> #include <sstream> +#include <utility> #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmXMLSafe.h" -cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj, const TestObjects& tests, +cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj, TestObjects tests, const std::vector<std::string>& configList, unsigned int xcVersion) : Target(xcObj) - , Tests(tests) + , Tests(std::move(tests)) , TargetName(xcObj->GetTarget()->GetName()) , ConfigList(configList) , XcodeVersion(xcVersion) @@ -35,7 +36,7 @@ void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir, xcodeSchemeFile += this->TargetName; xcodeSchemeFile += ".xcscheme"; - cmGeneratedFileStream fout(xcodeSchemeFile.c_str()); + cmGeneratedFileStream fout(xcodeSchemeFile); fout.SetCopyIfDifferent(true); if (!fout) { return; @@ -216,7 +217,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, if (!arguments.empty()) { xout.StartElement("CommandLineArguments"); - for (auto argument : arguments) { + for (auto const& argument : arguments) { xout.StartElement("CommandLineArgument"); xout.BreakAttributes(); diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h index 96c76e642..8c4712359 100644 --- a/Source/cmXCodeScheme.h +++ b/Source/cmXCodeScheme.h @@ -20,7 +20,7 @@ class cmXCodeScheme public: typedef std::vector<const cmXCodeObject*> TestObjects; - cmXCodeScheme(cmXCodeObject* xcObj, const TestObjects& tests, + cmXCodeScheme(cmXCodeObject* xcObj, TestObjects tests, const std::vector<std::string>& configList, unsigned int xcVersion); diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h index b08065409..1df8a09d7 100644 --- a/Source/cmXMLWriter.h +++ b/Source/cmXMLWriter.h @@ -16,12 +16,13 @@ class cmXMLWriter { - CM_DISABLE_COPY(cmXMLWriter) - public: cmXMLWriter(std::ostream& output, std::size_t level = 0); ~cmXMLWriter(); + cmXMLWriter(cmXMLWriter const&) = delete; + cmXMLWriter& operator=(cmXMLWriter const&) = delete; + void StartDocument(const char* encoding = "UTF-8"); void EndDocument(); diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx index 9519f9155..821c112b3 100644 --- a/Source/cm_codecvt.cxx +++ b/Source/cm_codecvt.cxx @@ -38,9 +38,7 @@ codecvt::codecvt(Encoding e) } } -codecvt::~codecvt() -{ -} +codecvt::~codecvt() = default; bool codecvt::do_always_noconv() const throw() { diff --git a/Source/cm_static_string_view.hxx b/Source/cm_static_string_view.hxx new file mode 100644 index 000000000..1bef0c68b --- /dev/null +++ b/Source/cm_static_string_view.hxx @@ -0,0 +1,41 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_static_string_view_hxx +#define cm_static_string_view_hxx + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_string_view.hxx" + +#include <cstddef> + +namespace cm { + +/** A string_view that only binds to static storage. + * + * This is used together with the `""_s` user-defined literal operator + * to construct a type-safe abstraction of a string_view that only views + * statically allocated strings. These strings are const and available + * for the entire lifetime of the program. + */ +class static_string_view : public string_view +{ + static_string_view(string_view v) + : string_view(v) + { + } + + friend static_string_view operator"" _s(const char* data, size_t size); +}; + +/** Create a static_string_view using `""_s` literal syntax. */ +inline static_string_view operator"" _s(const char* data, size_t size) +{ + return string_view(data, size); +} + +} // namespace cm + +using cm::operator"" _s; + +#endif diff --git a/Source/cm_string_view.cxx b/Source/cm_string_view.cxx new file mode 100644 index 000000000..61fa80e82 --- /dev/null +++ b/Source/cm_string_view.cxx @@ -0,0 +1,301 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cm_string_view.hxx" + +#ifndef CMake_HAVE_CXX_STRING_VIEW + +# include "cm_kwiml.h" + +# include <algorithm> +# include <ostream> +# include <stdexcept> + +namespace cm { + +string_view::const_reference string_view::at(size_type pos) const +{ + if (pos >= size_) { + throw std::out_of_range("Index out of range in string_view::at"); + } + return data_[pos]; +} + +string_view::size_type string_view::copy(char* dest, size_type count, + size_type pos) const +{ + if (pos > size_) { + throw std::out_of_range("Index out of range in string_view::copy"); + } + size_type const rcount = std::min(count, size_ - pos); + traits_type::copy(dest, data_ + pos, rcount); + return rcount; +} + +string_view string_view::substr(size_type pos, size_type count) const +{ + if (pos > size_) { + throw std::out_of_range("Index out of range in string_view::substr"); + } + size_type const rcount = std::min(count, size_ - pos); + return string_view(data_ + pos, rcount); +} + +int string_view::compare(string_view v) const noexcept +{ + size_type const rlen = std::min(size_, v.size_); + int c = traits_type::compare(data_, v.data_, rlen); + if (c == 0) { + if (size_ < v.size_) { + c = -1; + } else if (size_ > v.size_) { + c = 1; + } + } + return c; +} + +int string_view::compare(size_type pos1, size_type count1, string_view v) const +{ + return substr(pos1, count1).compare(v); +} + +int string_view::compare(size_type pos1, size_type count1, string_view v, + size_type pos2, size_type count2) const +{ + return substr(pos1, count1).compare(v.substr(pos2, count2)); +} + +int string_view::compare(const char* s) const +{ + return compare(string_view(s)); +} + +int string_view::compare(size_type pos1, size_type count1, const char* s) const +{ + return substr(pos1, count1).compare(string_view(s)); +} + +int string_view::compare(size_type pos1, size_type count1, const char* s, + size_type count2) const +{ + return substr(pos1, count1).compare(string_view(s, count2)); +} + +string_view::size_type string_view::find(string_view v, size_type pos) const + noexcept +{ + for (; pos + v.size_ <= size_; ++pos) { + if (std::char_traits<char>::compare(data_ + pos, v.data_, v.size_) == 0) { + return pos; + } + } + return npos; +} + +string_view::size_type string_view::find(char c, size_type pos) const noexcept +{ + return find(string_view(&c, 1), pos); +} + +string_view::size_type string_view::find(const char* s, size_type pos, + size_type count) const +{ + return find(string_view(s, count), pos); +} + +string_view::size_type string_view::find(const char* s, size_type pos) const +{ + return find(string_view(s), pos); +} + +string_view::size_type string_view::rfind(string_view v, size_type pos) const + noexcept +{ + if (size_ >= v.size_) { + for (pos = std::min(pos, size_ - v.size_) + 1; pos > 0;) { + --pos; + if (std::char_traits<char>::compare(data_ + pos, v.data_, v.size_) == + 0) { + return pos; + } + } + } + return npos; +} + +string_view::size_type string_view::rfind(char c, size_type pos) const noexcept +{ + return rfind(string_view(&c, 1), pos); +} + +string_view::size_type string_view::rfind(const char* s, size_type pos, + size_type count) const +{ + return rfind(string_view(s, count), pos); +} + +string_view::size_type string_view::rfind(const char* s, size_type pos) const +{ + return rfind(string_view(s), pos); +} + +string_view::size_type string_view::find_first_of(string_view v, + size_type pos) const noexcept +{ + for (; pos < size_; ++pos) { + if (traits_type::find(v.data_, v.size_, data_[pos])) { + return pos; + } + } + return npos; +} + +string_view::size_type string_view::find_first_of(char c, size_type pos) const + noexcept +{ + return find_first_of(string_view(&c, 1), pos); +} + +string_view::size_type string_view::find_first_of(const char* s, size_type pos, + size_type count) const +{ + return find_first_of(string_view(s, count), pos); +} + +string_view::size_type string_view::find_first_of(const char* s, + size_type pos) const +{ + return find_first_of(string_view(s), pos); +} + +string_view::size_type string_view::find_last_of(string_view v, + size_type pos) const noexcept +{ + if (size_ > 0) { + for (pos = std::min(pos, size_ - 1) + 1; pos > 0;) { + --pos; + if (traits_type::find(v.data_, v.size_, data_[pos])) { + return pos; + } + } + } + return npos; +} + +string_view::size_type string_view::find_last_of(char c, size_type pos) const + noexcept +{ + return find_last_of(string_view(&c, 1), pos); +} + +string_view::size_type string_view::find_last_of(const char* s, size_type pos, + size_type count) const +{ + return find_last_of(string_view(s, count), pos); +} + +string_view::size_type string_view::find_last_of(const char* s, + size_type pos) const +{ + return find_last_of(string_view(s), pos); +} + +string_view::size_type string_view::find_first_not_of(string_view v, + size_type pos) const + noexcept +{ + for (; pos < size_; ++pos) { + if (!traits_type::find(v.data_, v.size_, data_[pos])) { + return pos; + } + } + return npos; +} + +string_view::size_type string_view::find_first_not_of(char c, + size_type pos) const + noexcept +{ + return find_first_not_of(string_view(&c, 1), pos); +} + +string_view::size_type string_view::find_first_not_of(const char* s, + size_type pos, + size_type count) const +{ + return find_first_not_of(string_view(s, count), pos); +} + +string_view::size_type string_view::find_first_not_of(const char* s, + size_type pos) const +{ + return find_first_not_of(string_view(s), pos); +} + +string_view::size_type string_view::find_last_not_of(string_view v, + size_type pos) const + noexcept +{ + if (size_ > 0) { + for (pos = std::min(pos, size_ - 1) + 1; pos > 0;) { + --pos; + if (!traits_type::find(v.data_, v.size_, data_[pos])) { + return pos; + } + } + } + return npos; +} + +string_view::size_type string_view::find_last_not_of(char c, + size_type pos) const + noexcept +{ + return find_last_not_of(string_view(&c, 1), pos); +} + +string_view::size_type string_view::find_last_not_of(const char* s, + size_type pos, + size_type count) const +{ + return find_last_not_of(string_view(s, count), pos); +} + +string_view::size_type string_view::find_last_not_of(const char* s, + size_type pos) const +{ + return find_last_not_of(string_view(s), pos); +} + +std::ostream& operator<<(std::ostream& o, string_view v) +{ + return o.write(v.data(), v.size()); +} + +std::string& operator+=(std::string& s, string_view v) +{ + s.append(v.data(), v.size()); + return s; +} +} + +std::hash<cm::string_view>::result_type std::hash<cm::string_view>::operator()( + argument_type const& s) const noexcept +{ + // FNV-1a hash. + static KWIML_INT_uint64_t const fnv_offset_basis = 0xcbf29ce484222325; + static KWIML_INT_uint64_t const fnv_prime = 0x100000001b3; + KWIML_INT_uint64_t h = fnv_offset_basis; + for (char const& c : s) { + h = h ^ KWIML_INT_uint64_t(KWIML_INT_uint8_t(c)); + h = h * fnv_prime; + } + return result_type(h); +} +#else +// Avoid empty translation unit. +void cm_string_view_cxx() +{ +} +#endif diff --git a/Source/cm_string_view.hxx b/Source/cm_string_view.hxx new file mode 100644 index 000000000..d368ed8e2 --- /dev/null +++ b/Source/cm_string_view.hxx @@ -0,0 +1,217 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_string_view_hxx +#define cm_string_view_hxx + +#include "cmConfigure.h" // IWYU pragma: keep + +#if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L +# define CMake_HAVE_CXX_STRING_VIEW +#endif + +#ifdef CMake_HAVE_CXX_STRING_VIEW +# include <string_view> +namespace cm { +using std::string_view; +} +#else +# include <cstddef> +# include <functional> +# include <iosfwd> +# include <iterator> +# include <string> + +namespace cm { + +class string_view +{ +public: + using traits_type = std::string::traits_type; + using value_type = char; + using pointer = char*; + using const_pointer = const char*; + using reference = char&; + using const_reference = char const&; + using const_iterator = const char*; + using iterator = const_iterator; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + using reverse_iterator = const_reverse_iterator; + using size_type = std::string::size_type; + using difference_type = std::string::difference_type; + + static size_type const npos = static_cast<size_type>(-1); + + string_view() noexcept = default; + string_view(string_view const&) noexcept = default; + + string_view(const char* s, size_t count) noexcept + : data_(s) + , size_(count) + { + } + + string_view(const char* s) noexcept + : data_(s) + , size_(traits_type::length(s)) + { + } + + // C++17 does not define this constructor. Instead it defines + // a conversion operator on std::string to create a string_view. + // Since this implementation is used in C++11, std::string does + // not have that conversion. + string_view(std::string const& s) noexcept + : data_(s.data()) + , size_(s.size()) + { + } + + // C++17 does not define this conversion. Instead it defines + // a constructor on std::string that can take a string_view. + // Since this implementation is used in C++11, std::string does + // not have that constructor. + explicit operator std::string() const { return std::string(data_, size_); } + + string_view& operator=(string_view const&) = default; + + const_iterator begin() const noexcept { return data_; } + const_iterator end() const noexcept { return data_ + size_; } + const_iterator cbegin() const noexcept { return begin(); } + const_iterator cend() const noexcept { return end(); } + + const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator crbegin() const noexcept { return rbegin(); } + const_reverse_iterator crend() const noexcept { return rend(); } + + const_reference operator[](size_type pos) const noexcept + { + return data_[pos]; + } + const_reference at(size_type pos) const; + const_reference front() const noexcept { return data_[0]; } + const_reference back() const noexcept { return data_[size_ - 1]; } + const_pointer data() const noexcept { return data_; } + + size_type size() const noexcept { return size_; } + size_type length() const noexcept { return size_; } + size_type max_size() const noexcept { return npos - 1; } + bool empty() const noexcept { return size_ == 0; } + + void remove_prefix(size_type n) noexcept + { + data_ += n; + size_ -= n; + } + void remove_suffix(size_type n) noexcept { size_ -= n; } + void swap(string_view& v) noexcept + { + string_view tmp = v; + v = *this; + *this = tmp; + } + + size_type copy(char* dest, size_type count, size_type pos = 0) const; + string_view substr(size_type pos = 0, size_type count = npos) const; + + int compare(string_view v) const noexcept; + int compare(size_type pos1, size_type count1, string_view v) const; + int compare(size_type pos1, size_type count1, string_view v, size_type pos2, + size_type count2) const; + int compare(const char* s) const; + int compare(size_type pos1, size_type count1, const char* s) const; + int compare(size_type pos1, size_type count1, const char* s, + size_type count2) const; + + size_type find(string_view v, size_type pos = 0) const noexcept; + size_type find(char c, size_type pos = 0) const noexcept; + size_type find(const char* s, size_type pos, size_type count) const; + size_type find(const char* s, size_type pos = 0) const; + + size_type rfind(string_view v, size_type pos = npos) const noexcept; + size_type rfind(char c, size_type pos = npos) const noexcept; + size_type rfind(const char* s, size_type pos, size_type count) const; + size_type rfind(const char* s, size_type pos = npos) const; + + size_type find_first_of(string_view v, size_type pos = 0) const noexcept; + size_type find_first_of(char c, size_type pos = 0) const noexcept; + size_type find_first_of(const char* s, size_type pos, size_type count) const; + size_type find_first_of(const char* s, size_type pos = 0) const; + + size_type find_last_of(string_view v, size_type pos = npos) const noexcept; + size_type find_last_of(char c, size_type pos = npos) const noexcept; + size_type find_last_of(const char* s, size_type pos, size_type count) const; + size_type find_last_of(const char* s, size_type pos = npos) const; + + size_type find_first_not_of(string_view v, size_type pos = 0) const noexcept; + size_type find_first_not_of(char c, size_type pos = 0) const noexcept; + size_type find_first_not_of(const char* s, size_type pos, + size_type count) const; + size_type find_first_not_of(const char* s, size_type pos = 0) const; + + size_type find_last_not_of(string_view v, size_type pos = npos) const + noexcept; + size_type find_last_not_of(char c, size_type pos = npos) const noexcept; + size_type find_last_not_of(const char* s, size_type pos, + size_type count) const; + size_type find_last_not_of(const char* s, size_type pos = npos) const; + +private: + const char* data_ = nullptr; + size_type size_ = 0; +}; + +std::ostream& operator<<(std::ostream& o, string_view v); + +std::string& operator+=(std::string& s, string_view v); + +inline bool operator==(string_view l, string_view r) noexcept +{ + return l.compare(r) == 0; +} + +inline bool operator!=(string_view l, string_view r) noexcept +{ + return l.compare(r) != 0; +} + +inline bool operator<(string_view l, string_view r) noexcept +{ + return l.compare(r) < 0; +} + +inline bool operator<=(string_view l, string_view r) noexcept +{ + return l.compare(r) <= 0; +} + +inline bool operator>(string_view l, string_view r) noexcept +{ + return l.compare(r) > 0; +} + +inline bool operator>=(string_view l, string_view r) noexcept +{ + return l.compare(r) >= 0; +} +} + +namespace std { + +template <> +struct hash<cm::string_view> +{ + typedef cm::string_view argument_type; + typedef size_t result_type; + result_type operator()(argument_type const& s) const noexcept; +}; +} + +#endif +#endif diff --git a/Source/cm_thread.hxx b/Source/cm_thread.hxx index 84e6a5c32..b1f064585 100644 --- a/Source/cm_thread.hxx +++ b/Source/cm_thread.hxx @@ -11,18 +11,18 @@ namespace cm { class shared_mutex { uv_rwlock_t _M_; - CM_DISABLE_COPY(shared_mutex) public: shared_mutex() { uv_rwlock_init(&_M_); } ~shared_mutex() { uv_rwlock_destroy(&_M_); } - void lock() { uv_rwlock_wrlock(&_M_); } + shared_mutex(shared_mutex const&) = delete; + shared_mutex& operator=(shared_mutex const&) = delete; + void lock() { uv_rwlock_wrlock(&_M_); } void unlock() { uv_rwlock_wrunlock(&_M_); } void lock_shared() { uv_rwlock_rdlock(&_M_); } - void unlock_shared() { uv_rwlock_rdunlock(&_M_); } }; @@ -30,7 +30,6 @@ template <typename T> class shared_lock { T& _mutex; - CM_DISABLE_COPY(shared_lock) public: shared_lock(T& m) @@ -38,7 +37,12 @@ public: { _mutex.lock_shared(); } + ~shared_lock() { _mutex.unlock_shared(); } + + shared_lock(shared_lock const&) = delete; + shared_lock& operator=(shared_lock const&) = delete; }; } + #endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index d0863b0cd..8023298f9 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -30,6 +30,7 @@ #if defined(CMAKE_BUILD_WITH_CMAKE) # include "cm_jsoncpp_writer.h" +# include "cmFileAPI.h" # include "cmGraphVizWriter.h" # include "cmVariableWatch.h" # include <unordered_map> @@ -54,8 +55,8 @@ # include "cmGlobalVisualStudio11Generator.h" # include "cmGlobalVisualStudio12Generator.h" # include "cmGlobalVisualStudio14Generator.h" -# include "cmGlobalVisualStudio15Generator.h" # include "cmGlobalVisualStudio9Generator.h" +# include "cmGlobalVisualStudioVersionedGenerator.h" # include "cmVSSetupHelper.h" # define CMAKE_HAVE_VS_GENERATORS @@ -114,8 +115,10 @@ typedef std::unordered_map<std::string, Json::Value> JsonValueMapType; } // namespace -static bool cmakeCheckStampFile(const char* stampName, bool verbose = true); -static bool cmakeCheckStampList(const char* stampList, bool verbose = true); +static bool cmakeCheckStampFile(const std::string& stampName, + bool verbose = true); +static bool cmakeCheckStampList(const std::string& stampList, + bool verbose = true); void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, void* ctx, const char* /*unused*/, @@ -125,7 +128,7 @@ void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, cm->MarkCliAsUsed(variable); } -cmake::cmake(Role role) +cmake::cmake(Role role, cmState::Mode mode) { this->Trace = false; this->TraceExpand = false; @@ -139,8 +142,9 @@ cmake::cmake(Role role) this->FileComparison = new cmFileTimeComparison; this->State = new cmState; + this->State->SetMode(mode); this->CurrentSnapshot = this->State->CreateBaseSnapshot(); - this->Messenger = new cmMessenger(this->State); + this->Messenger = new cmMessenger; #ifdef __APPLE__ struct rlimit rlp; @@ -153,8 +157,6 @@ cmake::cmake(Role role) #endif this->GlobalGenerator = nullptr; - this->ProgressCallback = nullptr; - this->ProgressCallbackClientData = nullptr; this->CurrentWorkingMode = NORMAL_MODE; #ifdef CMAKE_BUILD_WITH_CMAKE @@ -177,31 +179,31 @@ cmake::cmake(Role role) // these are used to find files when the extension // is not given // The "c" extension MUST precede the "C" extension. - this->SourceFileExtensions.push_back("c"); - this->SourceFileExtensions.push_back("C"); - - this->SourceFileExtensions.push_back("c++"); - this->SourceFileExtensions.push_back("cc"); - this->SourceFileExtensions.push_back("cpp"); - this->SourceFileExtensions.push_back("cxx"); - this->SourceFileExtensions.push_back("cu"); - this->SourceFileExtensions.push_back("m"); - this->SourceFileExtensions.push_back("M"); - this->SourceFileExtensions.push_back("mm"); + this->SourceFileExtensions.emplace_back("c"); + this->SourceFileExtensions.emplace_back("C"); + + this->SourceFileExtensions.emplace_back("c++"); + this->SourceFileExtensions.emplace_back("cc"); + this->SourceFileExtensions.emplace_back("cpp"); + this->SourceFileExtensions.emplace_back("cxx"); + this->SourceFileExtensions.emplace_back("cu"); + this->SourceFileExtensions.emplace_back("m"); + this->SourceFileExtensions.emplace_back("M"); + this->SourceFileExtensions.emplace_back("mm"); std::copy(this->SourceFileExtensions.begin(), this->SourceFileExtensions.end(), std::inserter(this->SourceFileExtensionsSet, this->SourceFileExtensionsSet.end())); - this->HeaderFileExtensions.push_back("h"); - this->HeaderFileExtensions.push_back("hh"); - this->HeaderFileExtensions.push_back("h++"); - this->HeaderFileExtensions.push_back("hm"); - this->HeaderFileExtensions.push_back("hpp"); - this->HeaderFileExtensions.push_back("hxx"); - this->HeaderFileExtensions.push_back("in"); - this->HeaderFileExtensions.push_back("txx"); + this->HeaderFileExtensions.emplace_back("h"); + this->HeaderFileExtensions.emplace_back("hh"); + this->HeaderFileExtensions.emplace_back("h++"); + this->HeaderFileExtensions.emplace_back("hm"); + this->HeaderFileExtensions.emplace_back("hpp"); + this->HeaderFileExtensions.emplace_back("hxx"); + this->HeaderFileExtensions.emplace_back("in"); + this->HeaderFileExtensions.emplace_back("txx"); std::copy(this->HeaderFileExtensions.begin(), this->HeaderFileExtensions.end(), @@ -435,7 +437,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) } } std::cout << "loading initial cache file " << path << "\n"; - this->ReadListFile(args, path.c_str()); + this->ReadListFile(args, path); } else if (arg.find("-P", 0) == 0) { i++; if (i >= args.size()) { @@ -449,7 +451,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) } // Register fake project commands that hint misuse in script mode. GetProjectCommandsInScriptMode(this->State); - this->ReadListFile(args, path.c_str()); + this->ReadListFile(args, path); } else if (arg.find("--find-package", 0) == 0) { findPackageMode = true; } @@ -463,7 +465,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) } void cmake::ReadListFile(const std::vector<std::string>& args, - const char* path) + const std::string& path) { // if a generator was not yet created, temporarily create one cmGlobalGenerator* gg = this->GetGlobalGenerator(); @@ -476,7 +478,7 @@ void cmake::ReadListFile(const std::vector<std::string>& args, } // read in the list file to fill the cache - if (path) { + if (!path.empty()) { this->CurrentSnapshot = this->State->Reset(); std::string homeDir = this->GetHomeDirectory(); std::string homeOutputDir = this->GetHomeOutputDirectory(); @@ -497,7 +499,7 @@ void cmake::ReadListFile(const std::vector<std::string>& args, mf.SetArgcArgv(args); } if (!mf.ReadListFile(path)) { - cmSystemTools::Error("Error processing file: ", path); + cmSystemTools::Error("Error processing file: " + path); } this->SetHomeDirectory(homeDir); this->SetHomeOutputDirectory(homeOutputDir); @@ -531,7 +533,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) mf->SetArgcArgv(args); std::string systemFile = mf->GetModulesFile("CMakeFindPackageMode.cmake"); - mf->ReadListFile(systemFile.c_str()); + mf->ReadListFile(systemFile); std::string language = mf->GetSafeDefinition("LANGUAGE"); std::string mode = mf->GetSafeDefinition("MODE"); @@ -809,7 +811,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) if (this->CurrentWorkingMode == cmake::NORMAL_MODE && !haveSourceDir && !haveBinaryDir) { this->IssueMessage( - cmake::WARNING, + MessageType::WARNING, "No source or binary directory provided. Both will be assumed to be " "the same as the current working directory, but note that this " "warning will become a fatal error in future CMake releases."); @@ -960,17 +962,25 @@ void cmake::AddDefaultExtraGenerators() #endif } -void cmake::GetRegisteredGenerators( - std::vector<GeneratorInfo>& generators) const +void cmake::GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, + bool includeNamesWithPlatform) const { for (cmGlobalGeneratorFactory* gen : this->Generators) { - std::vector<std::string> names; - gen->GetGenerators(names); + std::vector<std::string> names = gen->GetGeneratorNames(); + + if (includeNamesWithPlatform) { + std::vector<std::string> namesWithPlatform = + gen->GetGeneratorNamesWithPlatform(); + names.insert(names.end(), namesWithPlatform.begin(), + namesWithPlatform.end()); + } for (std::string const& name : names) { GeneratorInfo info; info.supportsToolset = gen->SupportsToolset(); info.supportsPlatform = gen->SupportsPlatform(); + info.supportedPlatforms = gen->GetKnownPlatforms(); + info.defaultPlatform = gen->GetDefaultPlatformName(); info.name = name; info.baseName = name; info.isAlias = false; @@ -1162,7 +1172,7 @@ int cmake::DoPreConfigureChecks() } err << "Specify --help for usage, or press the help button on the CMake " "GUI."; - cmSystemTools::Error(err.str().c_str()); + cmSystemTools::Error(err.str()); return -2; } @@ -1180,7 +1190,7 @@ int cmake::DoPreConfigureChecks() message += cacheStart; message += "\" used to generate cache. "; message += "Re-run cmake with a different source directory."; - cmSystemTools::Error(message.c_str()); + cmSystemTools::Error(message); return -2; } } else { @@ -1240,7 +1250,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) for (SaveCacheEntry const& i : saved) { this->AddCacheEntry(i.key, i.value.c_str(), i.help.c_str(), i.type); } - cmSystemTools::Message(warning.str().c_str()); + cmSystemTools::Message(warning.str()); // avoid reconfigure if there were errors if (!cmSystemTools::GetErrorOccuredFlag()) { // re-run configure @@ -1309,6 +1319,23 @@ int cmake::Configure() } } + // Cache variables may have already been set by a previous invocation, + // so we cannot rely on command line options alone. Always ensure our + // messenger is in sync with the cache. + const char* value = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); + this->Messenger->SetSuppressDeprecatedWarnings(value && + cmSystemTools::IsOff(value)); + + value = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED"); + this->Messenger->SetDeprecatedWarningsAsErrors(cmSystemTools::IsOn(value)); + + value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_WARNINGS"); + this->Messenger->SetSuppressDevWarnings(cmSystemTools::IsOn(value)); + + value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS"); + this->Messenger->SetDevWarningsAsErrors(value && + cmSystemTools::IsOff(value)); + int ret = this->ActualConfigure(); const char* delCacheVars = this->State->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_"); @@ -1373,7 +1400,7 @@ int cmake::ActualConfigure() message += *genName; message += "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."; - cmSystemTools::Error(message.c_str()); + cmSystemTools::Error(message); return -2; } } @@ -1397,7 +1424,7 @@ int cmake::ActualConfigure() message += *instance; message += "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."; - cmSystemTools::Error(message.c_str()); + cmSystemTools::Error(message); return -2; } } else { @@ -1416,7 +1443,7 @@ int cmake::ActualConfigure() message += *platformName; message += "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."; - cmSystemTools::Error(message.c_str()); + cmSystemTools::Error(message); return -2; } } else { @@ -1434,7 +1461,7 @@ int cmake::ActualConfigure() message += *tsName; message += "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."; - cmSystemTools::Error(message.c_str()); + cmSystemTools::Error(message); return -2; } } else { @@ -1453,6 +1480,11 @@ int cmake::ActualConfigure() this->TruncateOutputLog("CMakeError.log"); } +#if defined(CMAKE_BUILD_WITH_CMAKE) + this->FileAPI = cm::make_unique<cmFileAPI>(this); + this->FileAPI->ReadQueries(); +#endif + // actually do the configure this->GlobalGenerator->Configure(); // Before saving the cache @@ -1498,7 +1530,7 @@ int cmake::ActualConfigure() return 0; } -void cmake::CreateDefaultGlobalGenerator() +std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator() { #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW) std::string found; @@ -1515,7 +1547,6 @@ void cmake::CreateDefaultGlobalGenerator() const char* GeneratorName; }; static VSVersionedGenerator const vsGenerators[] = { - { "15.0", "Visual Studio 15 2017" }, // { "14.0", "Visual Studio 14 2015" }, // { "12.0", "Visual Studio 12 2013" }, // { "11.0", "Visual Studio 11 2012" }, // @@ -1526,8 +1557,9 @@ void cmake::CreateDefaultGlobalGenerator() "\\Setup\\VC;ProductDir", // ";InstallDir" // }; - cmVSSetupAPIHelper vsSetupAPIHelper; - if (vsSetupAPIHelper.IsVS2017Installed()) { + if (cmVSSetupAPIHelper(16).IsVSInstalled()) { + found = "Visual Studio 16 2019"; + } else if (cmVSSetupAPIHelper(15).IsVSInstalled()) { found = "Visual Studio 15 2017"; } else { for (VSVersionedGenerator const* g = cm::cbegin(vsGenerators); @@ -1551,13 +1583,22 @@ void cmake::CreateDefaultGlobalGenerator() if (!gen) { gen = new cmGlobalNMakeMakefileGenerator(this); } - this->SetGlobalGenerator(gen); - std::cout << "-- Building for: " << gen->GetName() << "\n"; + return std::unique_ptr<cmGlobalGenerator>(gen); #else - this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3(this)); + return cm::make_unique<cmGlobalUnixMakefileGenerator3>(this); #endif } +void cmake::CreateDefaultGlobalGenerator() +{ + auto gen = this->EvaluateDefaultGlobalGenerator(); +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW) + // This print could be unified for all platforms + std::cout << "-- Building for: " << gen->GetName() << "\n"; +#endif + this->SetGlobalGenerator(gen.release()); +} + void cmake::PreLoadCMakeFiles() { std::vector<std::string> args; @@ -1565,14 +1606,14 @@ void cmake::PreLoadCMakeFiles() if (!pre_load.empty()) { pre_load += "/PreLoad.cmake"; if (cmSystemTools::FileExists(pre_load)) { - this->ReadListFile(args, pre_load.c_str()); + this->ReadListFile(args, pre_load); } } pre_load = this->GetHomeOutputDirectory(); if (!pre_load.empty()) { pre_load += "/PreLoad.cmake"; if (cmSystemTools::FileExists(pre_load)) { - this->ReadListFile(args, pre_load.c_str()); + this->ReadListFile(args, pre_load); } } } @@ -1588,13 +1629,13 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) // If we are given a stamp list file check if it is really out of date. if (!this->CheckStampList.empty() && - cmakeCheckStampList(this->CheckStampList.c_str())) { + cmakeCheckStampList(this->CheckStampList)) { return 0; } // If we are given a stamp file check if it is really out of date. if (!this->CheckStampFile.empty() && - cmakeCheckStampFile(this->CheckStampFile.c_str())) { + cmakeCheckStampFile(this->CheckStampFile)) { return 0; } @@ -1692,6 +1733,10 @@ int cmake::Generate() // for the Visual Studio and Xcode generators.) this->SaveCache(this->GetHomeOutputDirectory()); +#if defined(CMAKE_BUILD_WITH_CMAKE) + this->FileAPI->WriteReplies(); +#endif + return 0; } @@ -1701,6 +1746,18 @@ void cmake::AddCacheEntry(const std::string& key, const char* value, this->State->AddCacheEntry(key, value, helpString, cmStateEnums::CacheEntryType(type)); this->UnwatchUnusedCli(key); + + if (key == "CMAKE_WARN_DEPRECATED") { + this->Messenger->SetSuppressDeprecatedWarnings( + value && cmSystemTools::IsOff(value)); + } else if (key == "CMAKE_ERROR_DEPRECATED") { + this->Messenger->SetDeprecatedWarningsAsErrors(cmSystemTools::IsOn(value)); + } else if (key == "CMAKE_SUPPRESS_DEVELOPER_WARNINGS") { + this->Messenger->SetSuppressDevWarnings(cmSystemTools::IsOn(value)); + } else if (key == "CMAKE_SUPPRESS_DEVELOPER_ERRORS") { + this->Messenger->SetDevWarningsAsErrors(value && + cmSystemTools::IsOff(value)); + } } bool cmake::DoWriteGlobVerifyTarget() const @@ -1765,7 +1822,10 @@ void cmake::AddDefaultGenerators() { #if defined(_WIN32) && !defined(__CYGWIN__) # if !defined(CMAKE_BOOT_MINGW) - this->Generators.push_back(cmGlobalVisualStudio15Generator::NewFactory()); + this->Generators.push_back( + cmGlobalVisualStudioVersionedGenerator::NewFactory16()); + this->Generators.push_back( + cmGlobalVisualStudioVersionedGenerator::NewFactory15()); this->Generators.push_back(cmGlobalVisualStudio14Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio12Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio11Generator::NewFactory()); @@ -1860,17 +1920,15 @@ bool cmake::DeleteCache(const std::string& path) return this->State->DeleteCache(path); } -void cmake::SetProgressCallback(ProgressCallbackType f, void* cd) +void cmake::SetProgressCallback(ProgressCallbackType f) { - this->ProgressCallback = f; - this->ProgressCallbackClientData = cd; + this->ProgressCallback = std::move(f); } void cmake::UpdateProgress(const char* msg, float prog) { if (this->ProgressCallback && !this->State->GetIsInTryCompile()) { - (*this->ProgressCallback)(msg, prog, this->ProgressCallbackClientData); - return; + this->ProgressCallback(msg, prog); } } @@ -1884,13 +1942,28 @@ void cmake::SetIsInTryCompile(bool b) this->State->SetIsInTryCompile(b); } -void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v) +void cmake::AppendGlobalGeneratorsDocumentation( + std::vector<cmDocumentationEntry>& v) { + const auto defaultGenerator = this->EvaluateDefaultGlobalGenerator(); + const std::string defaultName = defaultGenerator->GetName(); + bool foundDefaultOne = false; + for (cmGlobalGeneratorFactory* g : this->Generators) { cmDocumentationEntry e; g->GetDocumentation(e); + if (!foundDefaultOne && + cmSystemTools::StringStartsWith(e.Name, defaultName.c_str())) { + e.CustomNamePrefix = '*'; + foundDefaultOne = true; + } v.push_back(std::move(e)); } +} + +void cmake::AppendExtraGeneratorsDocumentation( + std::vector<cmDocumentationEntry>& v) +{ for (cmExternalMakefileProjectGeneratorFactory* eg : this->ExtraGenerators) { const std::string doc = eg->GetDocumentation(); const std::string name = eg->GetName(); @@ -1916,12 +1989,19 @@ void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v) } } +std::vector<cmDocumentationEntry> cmake::GetGeneratorsDocumentation() +{ + std::vector<cmDocumentationEntry> v; + this->AppendGlobalGeneratorsDocumentation(v); + this->AppendExtraGeneratorsDocumentation(v); + return v; +} + void cmake::PrintGeneratorList() { #ifdef CMAKE_BUILD_WITH_CMAKE cmDocumentation doc; - std::vector<cmDocumentationEntry> generators; - this->GetGeneratorDocumentation(generators); + auto generators = this->GetGeneratorsDocumentation(); doc.AppendSection("Generators", generators); std::cerr << "\n"; doc.PrintDocumentation(cmDocumentation::ListGenerators, std::cerr); @@ -1966,7 +2046,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake no build system arguments\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -1977,26 +2057,27 @@ int cmake::CheckBuildSystem() std::ostringstream msg; msg << "Re-run cmake missing file: " << this->CheckBuildSystemArgument << "\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } // Read the rerun check file and use it to decide whether to do the // global generate. - cmake cm(RoleScript); // Actually, all we need is the `set` command. + // Actually, all we need is the `set` command. + cmake cm(RoleScript, cmState::Unknown); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); cmGlobalGenerator gg(&cm); cmMakefile mf(&gg, cm.GetCurrentSnapshot()); - if (!mf.ReadListFile(this->CheckBuildSystemArgument.c_str()) || + if (!mf.ReadListFile(this->CheckBuildSystemArgument) || cmSystemTools::GetErrorOccuredFlag()) { if (verbose) { std::ostringstream msg; msg << "Re-run cmake error reading : " << this->CheckBuildSystemArgument << "\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } // There was an error reading the file. Just rerun. return 1; @@ -2030,7 +2111,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake, missing byproduct: " << p << "\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2051,7 +2132,7 @@ int cmake::CheckBuildSystem() std::ostringstream msg; msg << "Re-run cmake no CMAKE_MAKEFILE_DEPENDS " "or CMAKE_MAKEFILE_OUTPUTS :\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2061,8 +2142,7 @@ int cmake::CheckBuildSystem() std::string dep_newest = *dep++; for (; dep != depends.end(); ++dep) { int result = 0; - if (this->FileComparison->FileTimeCompare(dep_newest.c_str(), dep->c_str(), - &result)) { + if (this->FileComparison->FileTimeCompare(dep_newest, *dep, &result)) { if (result < 0) { dep_newest = *dep; } @@ -2070,7 +2150,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake: build system dependency is missing\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2081,8 +2161,7 @@ int cmake::CheckBuildSystem() std::string out_oldest = *out++; for (; out != outputs.end(); ++out) { int result = 0; - if (this->FileComparison->FileTimeCompare(out_oldest.c_str(), out->c_str(), - &result)) { + if (this->FileComparison->FileTimeCompare(out_oldest, *out, &result)) { if (result > 0) { out_oldest = *out; } @@ -2090,7 +2169,7 @@ int cmake::CheckBuildSystem() if (verbose) { std::ostringstream msg; msg << "Re-run cmake: build system output is missing\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2099,14 +2178,14 @@ int cmake::CheckBuildSystem() // If any output is older than any dependency then rerun. { int result = 0; - if (!this->FileComparison->FileTimeCompare(out_oldest.c_str(), - dep_newest.c_str(), &result) || + if (!this->FileComparison->FileTimeCompare(out_oldest, dep_newest, + &result) || result < 0) { if (verbose) { std::ostringstream msg; msg << "Re-run cmake file: " << out_oldest << " older than: " << dep_newest << "\n"; - cmSystemTools::Stdout(msg.str().c_str()); + cmSystemTools::Stdout(msg.str()); } return 1; } @@ -2139,7 +2218,7 @@ void cmake::TruncateOutputLog(const char* fname) inline std::string removeQuotes(const std::string& s) { - if (s[0] == '\"' && s[s.size() - 1] == '\"') { + if (s.front() == '\"' && s.back() == '\"') { return s.substr(1, s.size() - 2); } return s; @@ -2153,7 +2232,7 @@ void cmake::MarkCliAsUsed(const std::string& variable) void cmake::GenerateGraphViz(const char* fileName) const { #ifdef CMAKE_BUILD_WITH_CMAKE - cmGraphVizWriter gvWriter(this->GetGlobalGenerator()->GetLocalGenerators()); + cmGraphVizWriter gvWriter(this->GetGlobalGenerator()); std::string settingsFile = this->GetHomeOutputDirectory(); settingsFile += "/CMakeGraphVizOptions.cmake"; @@ -2275,7 +2354,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) outFile += "/CMakeLists.txt"; // Copy file - if (!cmSystemTools::cmCopyFile(inFile.c_str(), outFile.c_str())) { + if (!cmSystemTools::cmCopyFile(inFile, outFile)) { std::cerr << "Error copying file \"" << inFile << "\" to \"" << outFile << "\".\n"; return 1; @@ -2333,7 +2412,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) return 0; } -static bool cmakeCheckStampFile(const char* stampName, bool verbose) +static bool cmakeCheckStampFile(const std::string& stampName, bool verbose) { // The stamp file does not exist. Use the stamp dependencies to // determine whether it is really out of date. This works in @@ -2361,8 +2440,7 @@ static bool cmakeCheckStampFile(const char* stampName, bool verbose) while (cmSystemTools::GetLineFromStream(fin, dep)) { int result; if (!dep.empty() && dep[0] != '#' && - (!ftc.FileTimeCompare(stampDepends.c_str(), dep.c_str(), &result) || - result < 0)) { + (!ftc.FileTimeCompare(stampDepends, dep, &result) || result < 0)) { // The stamp depends file is older than this dependency. The // build system is really out of date. std::cout << "CMake is re-running because " << stampName @@ -2378,12 +2456,11 @@ static bool cmakeCheckStampFile(const char* stampName, bool verbose) // by the VS IDE due to a "rebuild" request. Restore it atomically. std::ostringstream stampTempStream; stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed(); - std::string stampTempString = stampTempStream.str(); - const char* stampTemp = stampTempString.c_str(); + std::string stampTemp = stampTempStream.str(); { // TODO: Teach cmGeneratedFileStream to use a random temp file (with // multiple tries in unlikely case of conflict) and use that here. - cmsys::ofstream stamp(stampTemp); + cmsys::ofstream stamp(stampTemp.c_str()); stamp << "# CMake generation timestamp file for this directory.\n"; } if (cmSystemTools::RenameFile(stampTemp, stampName)) { @@ -2397,11 +2474,11 @@ static bool cmakeCheckStampFile(const char* stampName, bool verbose) return true; } cmSystemTools::RemoveFile(stampTemp); - cmSystemTools::Error("Cannot restore timestamp ", stampName); + cmSystemTools::Error("Cannot restore timestamp ", stampName.c_str()); return false; } -static bool cmakeCheckStampList(const char* stampList, bool verbose) +static bool cmakeCheckStampList(const std::string& stampList, bool verbose) { // If the stamp list does not exist CMake must rerun to generate it. if (!cmSystemTools::FileExists(stampList)) { @@ -2409,7 +2486,7 @@ static bool cmakeCheckStampList(const char* stampList, bool verbose) << "is missing.\n"; return false; } - cmsys::ifstream fin(stampList); + cmsys::ifstream fin(stampList.c_str()); if (!fin) { std::cout << "CMake is re-running because generate.stamp.list " << "could not be read.\n"; @@ -2419,14 +2496,14 @@ static bool cmakeCheckStampList(const char* stampList, bool verbose) // Check each stamp. std::string stampName; while (cmSystemTools::GetLineFromStream(fin, stampName)) { - if (!cmakeCheckStampFile(stampName.c_str(), verbose)) { + if (!cmakeCheckStampFile(stampName, verbose)) { return false; } } return true; } -void cmake::IssueMessage(cmake::MessageType t, std::string const& text, +void cmake::IssueMessage(MessageType t, std::string const& text, cmListFileBacktrace const& backtrace) const { this->Messenger->IssueMessage(t, text, backtrace); @@ -2444,7 +2521,7 @@ std::vector<std::string> cmake::GetDebugConfigs() } // If no configurations were specified, use a default list. if (configs.empty()) { - configs.push_back("DEBUG"); + configs.emplace_back("DEBUG"); } return configs; } @@ -2456,7 +2533,8 @@ cmMessenger* cmake::GetMessenger() const int cmake::Build(int jobs, const std::string& dir, const std::string& target, const std::string& config, - const std::vector<std::string>& nativeOptions, bool clean) + const std::vector<std::string>& nativeOptions, bool clean, + bool verbose) { this->SetHomeDirectory(""); @@ -2509,11 +2587,11 @@ int cmake::Build(int jobs, const std::string& dir, const std::string& target, return 1; } projName = cachedProjectName; - bool verbose = false; + const char* cachedVerbose = this->State->GetCacheEntryValue("CMAKE_VERBOSE_MAKEFILE"); - if (cachedVerbose) { - verbose = cmSystemTools::IsOn(cachedVerbose); + if (cmSystemTools::IsOn(cachedVerbose)) { + verbose = true; } #ifdef CMAKE_HAVE_VS_GENERATORS @@ -2521,8 +2599,7 @@ int cmake::Build(int jobs, const std::string& dir, const std::string& target, // actually starting the build. If not done separately from the build // itself, there is the risk of building an out-of-date solution file due // to limitations of the underlying build system. - std::string const stampList = cachePath + "/" + - GetCMakeFilesDirectoryPostSlash() + + std::string const stampList = cachePath + "/" + "CMakeFiles/" + cmGlobalVisualStudio9Generator::GetGenerateStampList(); // Note that the stampList file only exists for VS generators. @@ -2532,15 +2609,15 @@ int cmake::Build(int jobs, const std::string& dir, const std::string& target, // the glob verification script before starting the build this->AddScriptingCommands(); if (this->GlobalGenerator->MatchesGeneratorName("Visual Studio 9 2008")) { - std::string const globVerifyScript = cachePath + "/" + - GetCMakeFilesDirectoryPostSlash() + "VerifyGlobs.cmake"; + std::string const globVerifyScript = + cachePath + "/" + "CMakeFiles/" + "VerifyGlobs.cmake"; if (cmSystemTools::FileExists(globVerifyScript)) { std::vector<std::string> args; - this->ReadListFile(args, globVerifyScript.c_str()); + this->ReadListFile(args, globVerifyScript); } } - if (!cmakeCheckStampList(stampList.c_str(), false)) { + if (!cmakeCheckStampList(stampList, false)) { // Correctly initialize the home (=source) and home output (=binary) // directories, which is required for running the generation step. std::string homeOrig = this->GetHomeDirectory(); @@ -2606,7 +2683,7 @@ bool cmake::Open(const std::string& dir, bool dryRun) std::unique_ptr<cmGlobalGenerator> gen( this->CreateGlobalGenerator(fullName)); - if (!gen.get()) { + if (!gen) { std::cerr << "Error: could create CMAKE_GENERATOR \"" << fullName << "\"\n"; return false; @@ -2653,7 +2730,7 @@ void cmake::RunCheckForUnusedVariables() } } if (haveUnused) { - this->IssueMessage(cmake::WARNING, msg.str()); + this->IssueMessage(MessageType::WARNING, msg.str()); } #endif } diff --git a/Source/cmake.h b/Source/cmake.h index 5bca30693..53d44f148 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -5,7 +5,9 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <functional> #include <map> +#include <memory> // IWYU pragma: keep #include <set> #include <string> #include <unordered_set> @@ -13,6 +15,8 @@ #include "cmInstalledFile.h" #include "cmListFileCache.h" +#include "cmMessageType.h" +#include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" @@ -21,12 +25,12 @@ #endif class cmExternalMakefileProjectGeneratorFactory; +class cmFileAPI; class cmFileTimeComparison; class cmGlobalGenerator; class cmGlobalGeneratorFactory; class cmMakefile; class cmMessenger; -class cmState; class cmVariableWatch; struct cmDocumentationEntry; @@ -56,8 +60,6 @@ struct cmDocumentationEntry; class cmake { - CM_DISABLE_COPY(cmake) - public: enum Role { @@ -66,19 +68,6 @@ public: RoleProject // all commands }; - enum MessageType - { - AUTHOR_WARNING, - AUTHOR_ERROR, - FATAL_ERROR, - INTERNAL_ERROR, - MESSAGE, - WARNING, - LOG, - DEPRECATION_ERROR, - DEPRECATION_WARNING - }; - enum DiagLevel { DIAG_IGNORE, @@ -114,6 +103,8 @@ public: std::string extraName; bool supportsToolset; bool supportsPlatform; + std::vector<std::string> supportedPlatforms; + std::string defaultPlatform; bool isAlias; }; @@ -123,22 +114,19 @@ public: static const int DEFAULT_BUILD_PARALLEL_LEVEL = 0; /// Default constructor - cmake(Role role); + cmake(Role role, cmState::Mode mode); /// Destructor ~cmake(); + cmake(cmake const&) = delete; + cmake& operator=(cmake const&) = delete; + #if defined(CMAKE_BUILD_WITH_CMAKE) Json::Value ReportVersionJson() const; Json::Value ReportCapabilitiesJson(bool haveServerMode) const; #endif std::string ReportCapabilities(bool haveServerMode) const; - static const char* GetCMakeFilesDirectory() { return "/CMakeFiles"; } - static const char* GetCMakeFilesDirectoryPostSlash() - { - return "CMakeFiles/"; - } - //@{ /** * Set/Get the home directory (or output directory) in the project. The @@ -206,7 +194,8 @@ public: void SetGlobalGenerator(cmGlobalGenerator*); ///! Get the names of the current registered generators - void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators) const; + void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, + bool includeNamesWithPlatform = true) const; ///! Set the name of the selected generator-specific instance. void SetGeneratorInstance(std::string const& instance) @@ -284,7 +273,7 @@ public: ///! Parse command line arguments that might set cache values bool SetCacheArgs(const std::vector<std::string>&); - typedef void (*ProgressCallbackType)(const char* msg, float progress, void*); + using ProgressCallbackType = std::function<void(const char*, float)>; /** * Set the function used by GUIs to receive progress updates * Function gets passed: message as a const char*, a progress @@ -292,7 +281,7 @@ public: * number provided may be negative in cases where a message is * to be displayed without any progress percentage. */ - void SetProgressCallback(ProgressCallbackType f, void* clientData = nullptr); + void SetProgressCallback(ProgressCallbackType f); ///! this is called by generators to update the progress void UpdateProgress(const char* msg, float prog); @@ -302,7 +291,7 @@ public: cmVariableWatch* GetVariableWatch() { return this->VariableWatch; } #endif - void GetGeneratorDocumentation(std::vector<cmDocumentationEntry>&); + std::vector<cmDocumentationEntry> GetGeneratorsDocumentation(); ///! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); @@ -431,13 +420,14 @@ public: /** Display a message to the user. */ void IssueMessage( - cmake::MessageType t, std::string const& text, + MessageType t, std::string const& text, cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; ///! run the --build option int Build(int jobs, const std::string& dir, const std::string& target, const std::string& config, - const std::vector<std::string>& nativeOptions, bool clean); + const std::vector<std::string>& nativeOptions, bool clean, + bool verbose); ///! run the --open option bool Open(const std::string& dir, bool dryRun); @@ -454,7 +444,6 @@ public: protected: void RunCheckForUnusedVariables(); - void InitializeProperties(); int HandleDeleteCacheVariables(const std::string& var); typedef std::vector<cmGlobalGeneratorFactory*> RegisteredGeneratorsVector; @@ -474,7 +463,8 @@ protected: std::string GeneratorToolset; ///! read in a cmake list file to initialize the cache - void ReadListFile(const std::vector<std::string>& args, const char* path); + void ReadListFile(const std::vector<std::string>& args, + const std::string& path); bool FindPackage(const std::vector<std::string>& args); ///! Check if CMAKE_CACHEFILE_DIR is set. If it is not, delete the log file. @@ -497,8 +487,6 @@ protected: private: ProgressCallbackType ProgressCallback; - void* ProgressCallbackClientData; - bool InTryCompile; WorkingMode CurrentWorkingMode; bool DebugOutput; bool Trace; @@ -527,6 +515,7 @@ private: #if defined(CMAKE_BUILD_WITH_CMAKE) cmVariableWatch* VariableWatch; + std::unique_ptr<cmFileAPI> FileAPI; #endif cmState* State; @@ -540,19 +529,11 @@ private: // Print a list of valid generators to stderr. void PrintGeneratorList(); + std::unique_ptr<cmGlobalGenerator> EvaluateDefaultGlobalGenerator(); void CreateDefaultGlobalGenerator(); - /** - * Convert a message type between a warning and an error, based on the state - * of the error output CMake variables, in the cache. - */ - cmake::MessageType ConvertMessageType(cmake::MessageType t) const; - - /* - * Check if messages of this type should be output, based on the state of the - * warning and error output CMake variables, in the cache. - */ - bool IsMessageTypeVisible(cmake::MessageType t) const; + void AppendGlobalGeneratorsDocumentation(std::vector<cmDocumentationEntry>&); + void AppendExtraGeneratorsDocumentation(std::vector<cmDocumentationEntry>&); }; #define CMAKE_STANDARD_OPTIONS_TABLE \ diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index e52f2b361..a83f7dc8b 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAlgorithms.h" -#include "cmDocumentationEntry.h" +#include "cmDocumentationEntry.h" // IWYU pragma: keep #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmState.h" @@ -68,6 +68,8 @@ static const char* cmDocumentationUsageNote[][2] = { " --clean-first = Build target 'clean' first, then build.\n" \ " (To clean only, use --target 'clean'.)\n" \ " --use-stderr = Ignored. Behavior is default in CMake >= 3.0.\n" \ + " -v --verbose = Enable verbose output - if supported - including\n" \ + " the build commands to be executed. \n" \ " -- = Pass remaining options to the native tool.\n" static const char* cmDocumentationOptions[][2] = { @@ -106,7 +108,7 @@ static int do_command(int ac, char const* const* av) { std::vector<std::string> args; args.reserve(ac - 1); - args.push_back(av[0]); + args.emplace_back(av[0]); args.insert(args.end(), av + 2, av + ac); return cmcmd::ExecuteCMakeCommand(args); } @@ -115,9 +117,8 @@ int do_cmake(int ac, char const* const* av); static int do_build(int ac, char const* const* av); static int do_open(int ac, char const* const* av); -static cmMakefile* cmakemainGetMakefile(void* clientdata) +static cmMakefile* cmakemainGetMakefile(cmake* cm) { - cmake* cm = static_cast<cmake*>(clientdata); if (cm && cm->GetDebugOutput()) { cmGlobalGenerator* gg = cm->GetGlobalGenerator(); if (gg) { @@ -127,10 +128,10 @@ static cmMakefile* cmakemainGetMakefile(void* clientdata) return nullptr; } -static std::string cmakemainGetStack(void* clientdata) +static std::string cmakemainGetStack(cmake* cm) { std::string msg; - cmMakefile* mf = cmakemainGetMakefile(clientdata); + cmMakefile* mf = cmakemainGetMakefile(cm); if (mf) { msg = mf->FormatListFileStack(); if (!msg.empty()) { @@ -142,15 +143,14 @@ static std::string cmakemainGetStack(void* clientdata) } static void cmakemainMessageCallback(const char* m, const char* /*unused*/, - bool& /*unused*/, void* clientdata) + cmake* cm) { - std::cerr << m << cmakemainGetStack(clientdata) << std::endl << std::flush; + std::cerr << m << cmakemainGetStack(cm) << std::endl << std::flush; } -static void cmakemainProgressCallback(const char* m, float prog, - void* clientdata) +static void cmakemainProgressCallback(const char* m, float prog, cmake* cm) { - cmMakefile* mf = cmakemainGetMakefile(clientdata); + cmMakefile* mf = cmakemainGetMakefile(cm); std::string dir; if ((mf) && (strstr(m, "Configuring") == m) && (prog < 0)) { dir = " "; @@ -161,8 +161,7 @@ static void cmakemainProgressCallback(const char* m, float prog, } if ((prog < 0) || (!dir.empty())) { - std::cout << "-- " << m << dir << cmakemainGetStack(clientdata) - << std::endl; + std::cout << "-- " << m << dir << cmakemainGetStack(cm) << std::endl; } std::cout.flush(); @@ -217,7 +216,7 @@ int do_cmake(int ac, char const* const* av) doc.addCMakeStandardDocSections(); if (doc.CheckOptions(ac, av)) { // Construct and print requested documentation. - cmake hcm(cmake::RoleInternal); + cmake hcm(cmake::RoleInternal, cmState::Unknown); hcm.SetHomeDirectory(""); hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); @@ -227,9 +226,7 @@ int do_cmake(int ac, char const* const* av) std::vector<std::string> args(av, av + ac); hcm.SetCacheArgs(args); - std::vector<cmDocumentationEntry> generators; - - hcm.GetGeneratorDocumentation(generators); + auto generators = hcm.GetGeneratorsDocumentation(); doc.SetName("cmake"); doc.SetSection("Name", cmDocumentationName); @@ -288,18 +285,18 @@ int do_cmake(int ac, char const* const* av) return 1; } workingMode = cmake::SCRIPT_MODE; - args.push_back(av[i]); + args.emplace_back(av[i]); i++; - args.push_back(av[i]); + args.emplace_back(av[i]); } else if (cmHasLiteralPrefix(av[i], "--find-package")) { workingMode = cmake::FIND_PACKAGE_MODE; - args.push_back(av[i]); + args.emplace_back(av[i]); } else { - args.push_back(av[i]); + args.emplace_back(av[i]); } } if (sysinfo) { - cmake cm(cmake::RoleProject); + cmake cm(cmake::RoleProject, cmState::Project); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); int ret = cm.GetSystemInformation(args); @@ -307,11 +304,27 @@ int do_cmake(int ac, char const* const* av) } cmake::Role const role = workingMode == cmake::SCRIPT_MODE ? cmake::RoleScript : cmake::RoleProject; - cmake cm(role); + cmState::Mode mode = cmState::Unknown; + switch (workingMode) { + case cmake::NORMAL_MODE: + mode = cmState::Project; + break; + case cmake::SCRIPT_MODE: + mode = cmState::Script; + break; + case cmake::FIND_PACKAGE_MODE: + mode = cmState::FindPackage; + break; + } + cmake cm(role, mode); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); - cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm); - cm.SetProgressCallback(cmakemainProgressCallback, &cm); + cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) { + cmakemainMessageCallback(msg, title, &cm); + }); + cm.SetProgressCallback([&cm](const char* msg, float prog) { + cmakemainProgressCallback(msg, prog, &cm); + }); cm.SetWorkingMode(workingMode); int res = cm.Run(args, view_only); @@ -348,6 +361,31 @@ int do_cmake(int ac, char const* const* av) return 0; } +namespace { +int extract_job_number(int& index, char const* current, char const* next, + int len_of_flag) +{ + std::string command(current); + std::string jobString = command.substr(len_of_flag); + if (jobString.empty() && next && isdigit(next[0])) { + ++index; // skip parsing the job number + jobString = std::string(next); + } + + int jobs = -1; + unsigned long numJobs = 0; + if (jobString.empty()) { + jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL; + } else if (cmSystemTools::StringToULong(jobString.c_str(), &numJobs)) { + jobs = int(numJobs); + } else { + std::cerr << "'" << command.substr(0, len_of_flag) << "' invalid number '" + << jobString << "' given.\n\n"; + } + return jobs; +} +} + static int do_build(int ac, char const* const* av) { #ifndef CMAKE_BUILD_WITH_CMAKE @@ -360,12 +398,12 @@ static int do_build(int ac, char const* const* av) std::string dir; std::vector<std::string> nativeOptions; bool clean = false; + bool verbose = cmSystemTools::HasEnv("VERBOSE"); bool hasTarget = false; enum Doing { DoingNone, - DoingJobs, DoingDir, DoingTarget, DoingConfig, @@ -374,13 +412,18 @@ static int do_build(int ac, char const* const* av) Doing doing = DoingDir; for (int i = 2; i < ac; ++i) { if (doing == DoingNative) { - nativeOptions.push_back(av[i]); - } else if ((strcmp(av[i], "-j") == 0) || - (strcmp(av[i], "--parallel") == 0)) { - jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL; - /* does the next argument start with a number? */ - if ((i + 1 < ac) && (isdigit(*av[i + 1]))) { - doing = DoingJobs; + nativeOptions.emplace_back(av[i]); + } else if (cmHasLiteralPrefix(av[i], "-j")) { + const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr); + jobs = extract_job_number(i, av[i], nextArg, sizeof("-j") - 1); + if (jobs < 0) { + dir.clear(); + } + } else if (cmHasLiteralPrefix(av[i], "--parallel")) { + const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr); + jobs = extract_job_number(i, av[i], nextArg, sizeof("--parallel") - 1); + if (jobs < 0) { + dir.clear(); } } else if (strcmp(av[i], "--target") == 0) { if (!hasTarget) { @@ -396,24 +439,16 @@ static int do_build(int ac, char const* const* av) } else if (strcmp(av[i], "--clean-first") == 0) { clean = true; doing = DoingNone; + } else if ((strcmp(av[i], "--verbose") == 0) || + (strcmp(av[i], "-v") == 0)) { + verbose = true; + doing = DoingNone; } else if (strcmp(av[i], "--use-stderr") == 0) { /* tolerate legacy option */ } else if (strcmp(av[i], "--") == 0) { doing = DoingNative; } else { switch (doing) { - case DoingJobs: { - unsigned long numJobs = 0; - if (cmSystemTools::StringToULong(av[i], &numJobs)) { - jobs = int(numJobs); - doing = DoingNone; - } else { - std::cerr << "'" << av[i - 1] << "' invalid number '" << av[i] - << "' given.\n\n"; - dir.clear(); - break; - } - } break; case DoingDir: dir = cmSystemTools::CollapseFullPath(av[i]); doing = DoingNone; @@ -463,10 +498,14 @@ static int do_build(int ac, char const* const* av) return 1; } - cmake cm(cmake::RoleInternal); - cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm); - cm.SetProgressCallback(cmakemainProgressCallback, &cm); - return cm.Build(jobs, dir, target, config, nativeOptions, clean); + cmake cm(cmake::RoleInternal, cmState::Project); + cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) { + cmakemainMessageCallback(msg, title, &cm); + }); + cm.SetProgressCallback([&cm](const char* msg, float prog) { + cmakemainProgressCallback(msg, prog, &cm); + }); + return cm.Build(jobs, dir, target, config, nativeOptions, clean, verbose); #endif } @@ -501,9 +540,13 @@ static int do_open(int ac, char const* const* av) return 1; } - cmake cm(cmake::RoleInternal); - cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm); - cm.SetProgressCallback(cmakemainProgressCallback, &cm); + cmake cm(cmake::RoleInternal, cmState::Unknown); + cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) { + cmakemainMessageCallback(msg, title, &cm); + }); + cm.SetProgressCallback([&cm](const char* msg, float prog) { + cmakemainProgressCallback(msg, prog, &cm); + }); return cm.Open(dir, false) ? 0 : 1; #endif } diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx index 0c5bbe2df..1a10666c5 100644 --- a/Source/cmcldeps.cxx +++ b/Source/cmcldeps.cxx @@ -221,7 +221,7 @@ static int process(const std::string& srcfilename, const std::string& dfile, while (std::getline(ss, line)) { if (startsWith(line, prefix)) { std::string inc = trimLeadingSpace(line.substr(prefix.size()).c_str()); - if (inc[inc.size() - 1] == '\r') // blech, stupid \r\n + if (inc.back() == '\r') // blech, stupid \r\n inc = inc.substr(0, inc.size() - 1); includes.push_back(inc); } else { diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 1d2f741d8..d20c5d23a 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -9,6 +9,7 @@ #include "cmMakefile.h" #include "cmQtAutoGeneratorMocUic.h" #include "cmQtAutoGeneratorRcc.h" +#include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" @@ -44,6 +45,7 @@ #include <stdlib.h> #include <string.h> #include <time.h> +#include <utility> class cmConnection; @@ -76,7 +78,8 @@ void CMakeCommandUsage(const char* program) << " capabilities - Report capabilities built into cmake " "in JSON format\n" << " chdir dir cmd [args...] - run command in a given directory\n" - << " compare_files file1 file2 - check if file1 is same as file2\n" + << " compare_files [--ignore-eol] file1 file2\n" + << " - check if file1 is same as file2\n" << " copy <file>... destination - copy files to destination " "(either file or directory)\n" << " copy_directory <dir>... destination - copy content of <dir>... " @@ -121,7 +124,7 @@ void CMakeCommandUsage(const char* program) ; /* clang-format on */ - cmSystemTools::Error(errorStream.str().c_str()); + cmSystemTools::Error(errorStream.str()); } static bool cmTarFilesFrom(std::string const& file, @@ -130,14 +133,14 @@ static bool cmTarFilesFrom(std::string const& file, if (cmSystemTools::FileIsDirectory(file)) { std::ostringstream e; e << "-E tar --files-from= file '" << file << "' is a directory"; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return false; } cmsys::ifstream fin(file.c_str()); if (!fin) { std::ostringstream e; e << "-E tar --files-from= file '" << file << "' not found"; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return false; } std::string line; @@ -151,7 +154,7 @@ static bool cmTarFilesFrom(std::string const& file, std::ostringstream e; e << "-E tar --files-from='" << file << "' file invalid line:\n" << line << "\n"; - cmSystemTools::Error(e.str().c_str()); + cmSystemTools::Error(e.str()); return false; } else { files.push_back(line); @@ -199,7 +202,7 @@ static int HandleTidy(const std::string& runCmd, const std::string& sourceFile, std::vector<std::string> tidy_cmd; cmSystemTools::ExpandListArgument(runCmd, tidy_cmd, true); tidy_cmd.push_back(sourceFile); - tidy_cmd.push_back("--"); + tidy_cmd.emplace_back("--"); tidy_cmd.insert(tidy_cmd.end(), orig_cmd.begin(), orig_cmd.end()); // Run the tidy command line. Capture its stdout and hide its stderr. @@ -226,9 +229,9 @@ static int HandleLWYU(const std::string& runCmd, // Construct the ldd -r -u (link what you use lwyu) command line // ldd -u -r lwuy target std::vector<std::string> lwyu_cmd; - lwyu_cmd.push_back("ldd"); - lwyu_cmd.push_back("-u"); - lwyu_cmd.push_back("-r"); + lwyu_cmd.emplace_back("ldd"); + lwyu_cmd.emplace_back("-u"); + lwyu_cmd.emplace_back("-r"); lwyu_cmd.push_back(runCmd); // Run the ldd -u -r command line. @@ -270,9 +273,12 @@ static int HandleCppLint(const std::string& runCmd, << "\n"; return 1; } - std::cerr << "Warning: cpplint diagnostics:\n"; - // Output the output from cpplint to stderr - std::cerr << stdOut; + if (!stdOut.empty()) { + std::cerr << "Warning: cpplint diagnostics:\n"; + // Output the output from cpplint to stderr + std::cerr << stdOut; + } + // always return 0 so the build can continue as cpplint returns non-zero // for any warning return 0; @@ -323,11 +329,15 @@ static int HandleCppCheck(const std::string& runCmd, stdErr.find("(performance)") != std::string::npos || stdErr.find("(portability)") != std::string::npos || stdErr.find("(information)") != std::string::npos) { - std::cerr << "Warning: cppcheck reported diagnostics:\n"; + if (ret == 0) { + std::cerr << "Warning: cppcheck reported diagnostics:\n"; + } else { + std::cerr << "Error: cppcheck reported failure:\n"; + } } std::cerr << stdErr; - // ignore errors so build continues - return 0; + + return ret; } typedef int (*CoCompileHandler)(const std::string&, const std::string&, @@ -464,18 +474,17 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) // If multiple source files specified, // then destination must be directory if ((args.size() > 4) && - (!cmSystemTools::FileIsDirectory(args[args.size() - 1]))) { - std::cerr << "Error: Target (for copy command) \"" - << args[args.size() - 1] << "\" is not a directory.\n"; + (!cmSystemTools::FileIsDirectory(args.back()))) { + std::cerr << "Error: Target (for copy command) \"" << args.back() + << "\" is not a directory.\n"; return 1; } // If error occurs we want to continue copying next files. bool return_value = false; for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) { - if (!cmSystemTools::cmCopyFile(args[cc].c_str(), - args[args.size() - 1].c_str())) { + if (!cmSystemTools::cmCopyFile(args[cc], args.back())) { std::cerr << "Error copying file \"" << args[cc] << "\" to \"" - << args[args.size() - 1] << "\".\n"; + << args.back() << "\".\n"; return_value = true; } } @@ -487,18 +496,17 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) // If multiple source files specified, // then destination must be directory if ((args.size() > 4) && - (!cmSystemTools::FileIsDirectory(args[args.size() - 1]))) { + (!cmSystemTools::FileIsDirectory(args.back()))) { std::cerr << "Error: Target (for copy_if_different command) \"" - << args[args.size() - 1] << "\" is not a directory.\n"; + << args.back() << "\" is not a directory.\n"; return 1; } // If error occurs we want to continue copying next files. bool return_value = false; for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) { - if (!cmSystemTools::CopyFileIfDifferent( - args[cc].c_str(), args[args.size() - 1].c_str())) { + if (!cmSystemTools::CopyFileIfDifferent(args[cc], args.back())) { std::cerr << "Error copying file (if different) from \"" << args[cc] - << "\" to \"" << args[args.size() - 1] << "\".\n"; + << "\" to \"" << args.back() << "\".\n"; return_value = true; } } @@ -510,9 +518,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) // If error occurs we want to continue copying next files. bool return_value = false; for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) { - if (!cmSystemTools::CopyADirectory(args[cc], args[args.size() - 1])) { + if (!cmSystemTools::CopyADirectory(args[cc], args.back())) { std::cerr << "Error copying directory from \"" << args[cc] - << "\" to \"" << args[args.size() - 1] << "\".\n"; + << "\" to \"" << args.back() << "\".\n"; return_value = true; } } @@ -521,7 +529,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) // Rename a file or directory if (args[1] == "rename" && args.size() == 4) { - if (!cmSystemTools::RenameFile(args[2].c_str(), args[3].c_str())) { + if (!cmSystemTools::RenameFile(args[2], args[3])) { std::string e = cmSystemTools::GetLastSystemError(); std::cerr << "Error renaming from \"" << args[2] << "\" to \"" << args[3] << "\": " << e << "\n"; @@ -531,10 +539,20 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) } // Compare files - if (args[1] == "compare_files" && args.size() == 4) { - if (cmSystemTools::FilesDiffer(args[2], args[3])) { - std::cerr << "Files \"" << args[2] << "\" to \"" << args[3] - << "\" are different.\n"; + if (args[1] == "compare_files" && (args.size() == 4 || args.size() == 5)) { + bool filesDiffer; + if (args.size() == 4) { + filesDiffer = cmSystemTools::FilesDiffer(args[2], args[3]); + } else if (args[2] == "--ignore-eol") { + filesDiffer = cmsys::SystemTools::TextFilesDiffer(args[3], args[4]); + } else { + ::CMakeCommandUsage(args[0].c_str()); + return 1; + } + + if (filesDiffer) { + std::cerr << "Files \"" << args[args.size() - 2] << "\" to \"" + << args[args.size() - 1] << "\" are different.\n"; return 1; } return 0; @@ -687,6 +705,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) if (args[1] == "touch" && args.size() > 2) { for (std::string::size_type cc = 2; cc < args.size(); cc++) { if (!cmSystemTools::Touch(args[cc], true)) { + std::cerr << "cmake -E touch: failed to update \""; + std::cerr << args[cc] << "\".\n"; return 1; } } @@ -697,6 +717,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) if (args[1] == "touch_nocreate" && args.size() > 2) { for (std::string::size_type cc = 2; cc < args.size(); cc++) { if (!cmSystemTools::Touch(args[cc], false)) { + std::cerr << "cmake -E touch_nocreate: failed to update \""; + std::cerr << args[cc] << "\".\n"; return 1; } } @@ -709,7 +731,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) std::cerr << "-E capabilities accepts no additional arguments\n"; return 1; } - cmake cm(cmake::RoleInternal); + cmake cm(cmake::RoleInternal, cmState::Unknown); #if defined(CMAKE_BUILD_WITH_CMAKE) std::cout << cm.ReportCapabilities(true); #else @@ -886,7 +908,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) const bool verbose = isCMakeVerbose(); // Create a cmake object instance to process dependencies. - cmake cm(cmake::RoleScript); // All we need is the `set` command. + // All we need is the `set` command. + cmake cm(cmake::RoleScript, cmState::Unknown); std::string gen; std::string homeDir; std::string startDir; @@ -950,8 +973,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) std::unique_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(&mf)); // Actually scan dependencies. - return lgd->UpdateDependencies(depInfo.c_str(), verbose, color) ? 0 - : 2; + return lgd->UpdateDependencies(depInfo, verbose, color) ? 0 : 2; } return 1; } @@ -1009,7 +1031,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) std::string config; if (args.size() > 3) { config = args[3]; - }; + } return autoGen.Run(infoFile, config) ? 0 : 1; } #endif @@ -1159,7 +1181,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) if (server.Serve(&errorMessage)) { return 0; } - cmSystemTools::Error(errorMessage.c_str()); + cmSystemTools::Error(errorMessage); #else static_cast<void>(supportExperimental); static_cast<void>(isDebug); @@ -1280,7 +1302,7 @@ bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link) cmSystemTools::RemoveFile(link); } #if defined(_WIN32) && !defined(__CYGWIN__) - return cmSystemTools::CopyFileAlways(file.c_str(), link.c_str()); + return cmSystemTools::CopyFileAlways(file, link); #else std::string linktext = cmSystemTools::GetFilenameName(file); return cmSystemTools::CreateSymlink(linktext, link); @@ -1337,8 +1359,8 @@ static void cmcmdProgressReport(std::string const& dir, std::string const& num) int cmcmd::ExecuteEchoColor(std::vector<std::string>& args) { // The arguments are - // argv[0] == <cmake-executable> - // argv[1] == cmake_echo_color + // args[0] == <cmake-executable> + // args[1] == cmake_echo_color bool enabled = true; int color = cmsysTerminal_Color_Normal; @@ -1395,10 +1417,10 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string>& args) int cmcmd::ExecuteLinkScript(std::vector<std::string>& args) { // The arguments are - // argv[0] == <cmake-executable> - // argv[1] == cmake_link_script - // argv[2] == <link-script-name> - // argv[3] == --verbose=? + // args[0] == <cmake-executable> + // args[1] == cmake_link_script + // args[2] == <link-script-name> + // args[3] == --verbose=? bool verbose = false; if (args.size() >= 4) { if (args[3].find("--verbose=") == 0) { @@ -1473,7 +1495,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string>& args) break; default: break; - }; + } } // Free the process instance. @@ -1517,6 +1539,8 @@ class cmVSLink std::string ManifestFileRC; std::string ManifestFileRes; std::string TargetFile; + std::string MtPath; + std::string RcPath; public: cmVSLink(int type, bool verbose) @@ -1660,6 +1684,12 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg, } else if (cmHasLiteralPrefix(*arg, "--intdir=")) { intDir = arg->substr(9); ++arg; + } else if (cmHasLiteralPrefix(*arg, "--rc=")) { + this->RcPath = arg->substr(5); + ++arg; + } else if (cmHasLiteralPrefix(*arg, "--mt=")) { + this->MtPath = arg->substr(5); + ++arg; } else { std::cerr << "unknown argument '" << *arg << "'\n"; return false; @@ -1711,7 +1741,7 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg, } if (this->LinkGeneratesManifest) { - this->LinkCommand.push_back("/MANIFEST"); + this->LinkCommand.emplace_back("/MANIFEST"); this->LinkCommand.push_back("/MANIFESTFILE:" + this->LinkerManifestFile); } @@ -1799,7 +1829,7 @@ int cmVSLink::LinkIncremental() // Compile the resource file. std::vector<std::string> rcCommand; - rcCommand.push_back("rc"); + rcCommand.push_back(this->RcPath.empty() ? "rc" : this->RcPath); rcCommand.push_back("/fo" + this->ManifestFileRes); rcCommand.push_back(this->ManifestFileRC); if (!RunCommand("RC Pass 1", rcCommand, this->Verbose, FORMAT_DECIMAL)) { @@ -1858,9 +1888,9 @@ int cmVSLink::LinkNonIncremental() int cmVSLink::RunMT(std::string const& out, bool notify) { std::vector<std::string> mtCommand; - mtCommand.push_back("mt"); - mtCommand.push_back("/nologo"); - mtCommand.push_back("/manifest"); + mtCommand.push_back(this->MtPath.empty() ? "mt" : this->MtPath); + mtCommand.emplace_back("/nologo"); + mtCommand.emplace_back("/manifest"); if (this->LinkGeneratesManifest) { mtCommand.push_back(this->LinkerManifestFile); } @@ -1870,7 +1900,7 @@ int cmVSLink::RunMT(std::string const& out, bool notify) if (notify) { // Add an undocumented option that enables a special return // code to notify us when the manifest is modified. - mtCommand.push_back("/notify_update"); + mtCommand.emplace_back("/notify_update"); } int mtRet = 0; if (!RunCommand("MT", mtCommand, this->Verbose, FORMAT_HEX, &mtRet, diff --git a/Source/cmparseMSBuildXML.py b/Source/cmparseMSBuildXML.py deleted file mode 100755 index 1b38d1547..000000000 --- a/Source/cmparseMSBuildXML.py +++ /dev/null @@ -1,341 +0,0 @@ -# This python script parses the spec files from MSBuild to create -# mappings from compiler options to IDE XML specifications. For -# more information see here: - -# http://blogs.msdn.com/vcblog/archive/2008/12/16/msbuild-task.aspx -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/1033/cl.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/1033/lib.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/1033/link.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/cl.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/lib.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/link.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/cl.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/lib.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/link.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/cl.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/lib.xml" -# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/link.xml" -# "${PROGRAMFILES}/Microsoft Visual Studio/VS15Preview/Common7/IDE/VC/VCTargets/1033/cl.xml" -# "${PROGRAMFILES}/Microsoft Visual Studio/VS15Preview/Common7/IDE/VC/VCTargets/1033/lib.xml" -# "${PROGRAMFILES}/Microsoft Visual Studio/VS15Preview/Common7/IDE/VC/VCTargets/1033/link.xml" -# -# BoolProperty <Name>true|false</Name> -# simple example: -# <BoolProperty ReverseSwitch="Oy-" Name="OmitFramePointers" -# Category="Optimization" Switch="Oy"> -# <BoolProperty.DisplayName> <BoolProperty.Description> -# <CLCompile> -# <OmitFramePointers>true</OmitFramePointers> -# </ClCompile> -# -# argument means it might be this: /MP3 -# example with argument: -# <BoolProperty Name="MultiProcessorCompilation" Category="General" Switch="MP"> -# <BoolProperty.DisplayName> -# <sys:String>Multi-processor Compilation</sys:String> -# </BoolProperty.DisplayName> -# <BoolProperty.Description> -# <sys:String>Multi-processor Compilation</sys:String> -# </BoolProperty.Description> -# <Argument Property="ProcessorNumber" IsRequired="false" /> -# </BoolProperty> -# <CLCompile> -# <MultiProcessorCompilation>true</MultiProcessorCompilation> -# <ProcessorNumber>4</ProcessorNumber> -# </ClCompile> -# IntProperty -# not used AFIT -# <IntProperty Name="ProcessorNumber" Category="General" Visible="false"> - - -# per config options example -# <EnableFiberSafeOptimizations Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EnableFiberSafeOptimizations> -# -# EnumProperty -# <EnumProperty Name="Optimization" Category="Optimization"> -# <EnumProperty.DisplayName> -# <sys:String>Optimization</sys:String> -# </EnumProperty.DisplayName> -# <EnumProperty.Description> -# <sys:String>Select option for code optimization; choose Custom to use specific optimization options. (/Od, /O1, /O2, /Ox)</sys:String> -# </EnumProperty.Description> -# <EnumValue Name="MaxSpeed" Switch="O2"> -# <EnumValue.DisplayName> -# <sys:String>Maximize Speed</sys:String> -# </EnumValue.DisplayName> -# <EnumValue.Description> -# <sys:String>Equivalent to /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy</sys:String> -# </EnumValue.Description> -# </EnumValue> -# <EnumValue Name="MinSpace" Switch="O1"> -# <EnumValue.DisplayName> -# <sys:String>Minimize Size</sys:String> -# </EnumValue.DisplayName> -# <EnumValue.Description> -# <sys:String>Equivalent to /Og /Os /Oy /Ob2 /Gs /GF /Gy</sys:String> -# </EnumValue.Description> -# </EnumValue> -# example for O2 would be this: -# <Optimization>MaxSpeed</Optimization> -# example for O1 would be this: -# <Optimization>MinSpace</Optimization> -# -# StringListProperty -# <StringListProperty Name="PreprocessorDefinitions" Category="Preprocessor" Switch="D "> -# <StringListProperty.DisplayName> -# <sys:String>Preprocessor Definitions</sys:String> -# </StringListProperty.DisplayName> -# <StringListProperty.Description> -# <sys:String>Defines a preprocessing symbols for your source file.</sys:String> -# </StringListProperty.Description> -# </StringListProperty> - -# <StringListProperty Subtype="folder" Name="AdditionalIncludeDirectories" Category="General" Switch="I"> -# <StringListProperty.DisplayName> -# <sys:String>Additional Include Directories</sys:String> -# </StringListProperty.DisplayName> -# <StringListProperty.Description> -# <sys:String>Specifies one or more directories to add to the include path; separate with semi-colons if more than one. (/I[path])</sys:String> -# </StringListProperty.Description> -# </StringListProperty> -# StringProperty - -# Example add bill include: - -# <AdditionalIncludeDirectories>..\..\..\..\..\..\bill;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - - -import sys -from xml.dom.minidom import parse, parseString - -def getText(node): - nodelist = node.childNodes - rc = "" - for child in nodelist: - if child.nodeType == child.TEXT_NODE: - rc = rc + child.data - return rc - -def print_tree(document, spaces=""): - for i in range(len(document.childNodes)): - if document.childNodes[i].nodeType == document.childNodes[i].ELEMENT_NODE: - print spaces+str(document.childNodes[i].nodeName ) - print_tree(document.childNodes[i],spaces+"----") - pass - -########################################################################################### -#Data structure that stores a property of MSBuild -class Property: - #type = type of MSBuild property (ex. if the property is EnumProperty type should be "Enum") - #attributeNames = a list of any attributes that this property could have (ex. if this was a EnumProperty it should be ["Name","Category"]) - #document = the dom file that's root node is the Property node (ex. if you were parsing a BoolProperty the root node should be something like <BoolProperty Name="RegisterOutput" Category="General" IncludeInCommandLine="false"> - def __init__(self,type,attributeNames,document=None): - self.suffix_type = "Property" - self.prefix_type = type - self.attributeNames = attributeNames - self.attributes = {} - self.DisplayName = "" - self.Description = "" - self.argumentProperty = "" - self.argumentIsRequired = "" - self.values = [] - if document is not None: - self.populate(document) - pass - - #document = the dom file that's root node is the Property node (ex. if you were parsing a BoolProperty the root node should be something like <BoolProperty Name="RegisterOutput" Category="General" IncludeInCommandLine="false"> - #spaces = do not use - def populate(self,document, spaces = ""): - if document.nodeName == self.prefix_type+self.suffix_type: - for i in self.attributeNames: - self.attributes[i] = document.getAttribute(i) - for i in range(len(document.childNodes)): - child = document.childNodes[i] - if child.nodeType == child.ELEMENT_NODE: - if child.nodeName == self.prefix_type+self.suffix_type+".DisplayName": - self.DisplayName = getText(child.childNodes[1]) - if child.nodeName == self.prefix_type+self.suffix_type+".Description": - self.Description = getText(child.childNodes[1]) - if child.nodeName == "Argument": - self.argumentProperty = child.getAttribute("Property") - self.argumentIsRequired = child.getAttribute("IsRequired") - if child.nodeName == self.prefix_type+"Value": - va = Property(self.prefix_type,["Name","DisplayName","Switch"]) - va.suffix_type = "Value" - va.populate(child) - self.values.append(va) - self.populate(child,spaces+"----") - pass - - #toString function - def __str__(self): - toReturn = self.prefix_type+self.suffix_type+":" - for i in self.attributeNames: - toReturn += "\n "+i+": "+self.attributes[i] - if self.argumentProperty != "": - toReturn += "\n Argument:\n Property: "+self.argumentProperty+"\n IsRequired: "+self.argumentIsRequired - for i in self.values: - toReturn+="\n "+str(i).replace("\n","\n ") - return toReturn -########################################################################################### - -########################################################################################### -#Class that populates itself from an MSBuild file and outputs it in CMake -#format - -class MSBuildToCMake: - #document = the entire MSBuild xml file - def __init__(self,document=None): - self.enumProperties = [] - self.stringProperties = [] - self.stringListProperties = [] - self.boolProperties = [] - self.intProperties = [] - if document!=None : - self.populate(document) - pass - - #document = the entire MSBuild xml file - #spaces = don't use - #To add a new property (if they exist) copy and paste this code and fill in appropriate places - # - #if child.nodeName == "<Name>Property": - # self.<Name>Properties.append(Property("<Name>",[<List of attributes>],child)) - # - #Replace <Name> with the name of the new property (ex. if property is StringProperty replace <Name> with String) - #Replace <List of attributes> with a list of attributes in your property's root node - #in the __init__ function add the line self.<Name>Properties = [] - # - #That is all that is required to add new properties - # - def populate(self,document, spaces=""): - for i in range(len(document.childNodes)): - child = document.childNodes[i] - if child.nodeType == child.ELEMENT_NODE: - if child.nodeName == "EnumProperty": - self.enumProperties.append(Property("Enum",["Name","Category"],child)) - if child.nodeName == "StringProperty": - self.stringProperties.append(Property("String",["Name","Subtype","Separator","Category","Visible","IncludeInCommandLine","Switch","DisplayName","ReadOnly"],child)) - if child.nodeName == "StringListProperty": - self.stringListProperties.append(Property("StringList",["Name","Category","Switch","DisplayName","Subtype"],child)) - if child.nodeName == "BoolProperty": - self.boolProperties.append(Property("Bool",["ReverseSwitch","Name","Category","Switch","DisplayName","SwitchPrefix","IncludeInCommandLine"],child)) - if child.nodeName == "IntProperty": - self.intProperties.append(Property("Int",["Name","Category","Visible"],child)) - self.populate(child,spaces+"----") - pass - - #outputs information that CMake needs to know about MSBuild xml files - def toCMake(self): - toReturn = "static cmVS7FlagTable cmVS10CxxTable[] =\n{\n" - toReturn += "\n //Enum Properties\n" - lastProp = {} - for i in self.enumProperties: - if i.attributes["Name"] == "CompileAsManaged": - #write these out after the rest of the enumProperties - lastProp = i - continue - for j in i.values: - #hardcore Brad King's manual fixes for cmVS10CLFlagTable.h - if i.attributes["Name"] == "PrecompiledHeader" and j.attributes["Switch"] != "": - toReturn+=" {\""+i.attributes["Name"]+"\", \""+j.attributes["Switch"]+"\",\n \""+j.attributes["DisplayName"]+"\", \""+j.attributes["Name"]+"\",\n cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},\n" - else: - #default (normal, non-hardcoded) case - toReturn+=" {\""+i.attributes["Name"]+"\", \""+j.attributes["Switch"]+"\",\n \""+j.attributes["DisplayName"]+"\", \""+j.attributes["Name"]+"\", 0},\n" - toReturn += "\n" - - if lastProp != {}: - for j in lastProp.values: - toReturn+=" {\""+lastProp.attributes["Name"]+"\", \""+j.attributes["Switch"]+"\",\n \""+j.attributes["DisplayName"]+"\", \""+j.attributes["Name"]+"\", 0},\n" - toReturn += "\n" - - toReturn += "\n //Bool Properties\n" - for i in self.boolProperties: - if i.argumentProperty == "": - if i.attributes["ReverseSwitch"] != "": - toReturn += " {\""+i.attributes["Name"]+"\", \""+i.attributes["ReverseSwitch"]+"\", \"\", \"false\", 0},\n" - if i.attributes["Switch"] != "": - toReturn += " {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+"\", \"\", \"true\", 0},\n" - - toReturn += "\n //Bool Properties With Argument\n" - for i in self.boolProperties: - if i.argumentProperty != "": - if i.attributes["ReverseSwitch"] != "": - toReturn += " {\""+i.attributes["Name"]+"\", \""+i.attributes["ReverseSwitch"]+"\", \"\", \"false\",\n cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},\n" - toReturn += " {\""+i.attributes["Name"]+"\", \""+i.attributes["ReverseSwitch"]+"\", \""+i.attributes["DisplayName"]+"\", \"\",\n cmVS7FlagTable::UserValueRequired},\n" - if i.attributes["Switch"] != "": - toReturn += " {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+"\", \"\", \"true\",\n cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},\n" - toReturn += " {\""+i.argumentProperty+"\", \""+i.attributes["Switch"]+"\", \""+i.attributes["DisplayName"]+"\", \"\",\n cmVS7FlagTable::UserValueRequired},\n" - - toReturn += "\n //String List Properties\n" - for i in self.stringListProperties: - if i.attributes["Switch"] == "": - toReturn += " // Skip [" + i.attributes["Name"] + "] - no command line Switch.\n"; - else: - toReturn +=" {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+"\",\n \""+i.attributes["DisplayName"]+"\",\n \"\", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},\n" - - toReturn += "\n //String Properties\n" - for i in self.stringProperties: - if i.attributes["Switch"] == "": - if i.attributes["Name"] == "PrecompiledHeaderFile": - #more hardcoding - toReturn += " {\"PrecompiledHeaderFile\", \"Yc\",\n" - toReturn += " \"Precompiled Header Name\",\n" - toReturn += " \"\", cmVS7FlagTable::UserValueRequired},\n" - toReturn += " {\"PrecompiledHeaderFile\", \"Yu\",\n" - toReturn += " \"Precompiled Header Name\",\n" - toReturn += " \"\", cmVS7FlagTable::UserValueRequired},\n" - else: - toReturn += " // Skip [" + i.attributes["Name"] + "] - no command line Switch.\n"; - else: - toReturn +=" {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+i.attributes["Separator"]+"\",\n \""+i.attributes["DisplayName"]+"\",\n \"\", cmVS7FlagTable::UserValue},\n" - - toReturn += " {0,0,0,0,0}\n};" - return toReturn - pass - - #toString function - def __str__(self): - toReturn = "" - allList = [self.enumProperties,self.stringProperties,self.stringListProperties,self.boolProperties,self.intProperties] - for p in allList: - for i in p: - toReturn += "==================================================\n"+str(i).replace("\n","\n ")+"\n==================================================\n" - - return toReturn -########################################################################################### - -########################################################################################### -# main function -def main(argv): - xml_file = None - help = """ - Please specify an input xml file with -x - - Exiting... - Have a nice day :)""" - for i in range(0,len(argv)): - if argv[i] == "-x": - xml_file = argv[i+1] - if argv[i] == "-h": - print help - sys.exit(0) - pass - if xml_file == None: - print help - sys.exit(1) - - f = open(xml_file,"r") - xml_str = f.read() - xml_dom = parseString(xml_str) - - convertor = MSBuildToCMake(xml_dom) - print convertor.toCMake() - - xml_dom.unlink() -########################################################################################### -# main entry point -if __name__ == "__main__": - main(sys.argv) - -sys.exit(0) diff --git a/Source/ctest.cxx b/Source/ctest.cxx index ca8a7763a..4a2531a4e 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -46,7 +46,10 @@ static const char* cmDocumentationOptions[][2] = { "given number of jobs." }, { "-Q,--quiet", "Make ctest quiet." }, { "-O <file>, --output-log <file>", "Output to log file" }, - { "-N,--show-only", "Disable actual execution of tests." }, + { "-N,--show-only[=format]", + "Disable actual execution of tests. The optional 'format' defines the " + "format of the test information and can be 'human' for the current text " + "format or 'json-v1' for json format. Defaults to 'human'." }, { "-L <regex>, --label-regex <regex>", "Run tests with labels matching " "regular expression." }, @@ -128,7 +131,7 @@ static const char* cmDocumentationOptions[][2] = { { "--schedule-random", "Use a random order for scheduling tests" }, { "--submit-index", "Submit individual dashboard tests with specific index" }, - { "--timeout <seconds>", "Set a global timeout on all tests." }, + { "--timeout <seconds>", "Set the default test timeout." }, { "--stop-time <time>", "Set a time at which all tests should stop running." }, { "--http1.0", "Submit using HTTP 1.0." }, @@ -205,7 +208,7 @@ int main(int argc, char const* const* argv) std::vector<std::string> args; args.reserve(argc); for (int i = 0; i < argc; ++i) { - args.push_back(argv[i]); + args.emplace_back(argv[i]); } // run ctest std::string output; diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 43aec00bf..e7da99462 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -42,6 +42,10 @@ # SET(KWSYS_HEADER_ROOT ${PROJECT_BINARY_DIR}) # INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR}) # +# KWSYS_CXX_STANDARD = A value for CMAKE_CXX_STANDARD within KWSys. +# Set to empty string to use no default value. +# KWSYS_CXX_COMPILE_FEATURES = target_compile_features arguments for KWSys. +# # Optional settings to setup install rules are as follows: # # KWSYS_INSTALL_BIN_DIR = The installation target directories into @@ -82,24 +86,17 @@ # any outside mailing list and no documentation of the change will be # written. -CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR) +CMAKE_MINIMUM_REQUIRED(VERSION 3.1 FATAL_ERROR) FOREACH(p - CMP0022 # CMake 2.8, Define link interface - required by android_mk export - CMP0025 # CMake 3.0, Compiler id for Apple Clang is now AppleClang. - CMP0042 # CMake 3.0, MACOSX_RPATH is enabled by default. - CMP0048 # CMake 3.0, Let the project command manage version variables. CMP0056 # CMake 3.2, Honor link flags in try_compile() source-file signature. CMP0063 # CMake 3.3, Honor visibility properties for all target types. + CMP0067 # CMake 3.8, Honor language standard in try_compile source-file signature. + CMP0069 # CMake 3.9, INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. ) IF(POLICY ${p}) CMAKE_POLICY(SET ${p} NEW) ENDIF() ENDFOREACH() -SET(CMAKE_LEGACY_CYGWIN_WIN32 0) - -IF(CMAKE_VERSION VERSION_LESS 3.0) - SET(KWSYS_SPLIT_OBJECTS_FROM_INTERFACE 0) -ENDIF() #----------------------------------------------------------------------------- # If a namespace is not specified, use "kwsys" and enable testing. @@ -120,6 +117,12 @@ SET_PROPERTY(DIRECTORY "KWSYS_HEADER(%)=<${KWSYS_NAMESPACE}/%>" ) +if(KWSYS_CXX_STANDARD) + set(CMAKE_CXX_STANDARD "${KWSYS_CXX_STANDARD}") +elseif(NOT DEFINED CMAKE_CXX_STANDARD AND NOT DEFINED KWSYS_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 11) +endif() + # Select library components. IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) SET(KWSYS_ENABLE_C 1) @@ -453,6 +456,10 @@ ELSE() SET(KWSYS_LIBRARY_TYPE STATIC) ENDIF() +if(NOT DEFINED KWSYS_BUILD_PIC) + set(KWSYS_BUILD_PIC 0) +endif() + #----------------------------------------------------------------------------- # Configure some implementation details. @@ -869,7 +876,7 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) SET(KWSYS_LINK_DEPENDENCY INTERFACE) ADD_LIBRARY(${KWSYS_TARGET_OBJECT} OBJECT ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS}) - IF(KWSYS_BUILD_SHARED) + IF(KWSYS_BUILD_SHARED OR KWSYS_BUILD_PIC) SET_PROPERTY(TARGET ${KWSYS_TARGET_OBJECT} PROPERTY POSITION_INDEPENDENT_CODE TRUE) ENDIF() @@ -879,6 +886,8 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) ${KWSYS_TARGET_INTERFACE}) TARGET_SOURCES(${KWSYS_TARGET_LINK} INTERFACE $<TARGET_OBJECTS:${KWSYS_TARGET_OBJECT}>) + target_compile_features(${KWSYS_TARGET_OBJECT} PRIVATE ${KWSYS_CXX_COMPILE_FEATURES}) + target_compile_features(${KWSYS_TARGET_INTERFACE} INTERFACE ${KWSYS_CXX_COMPILE_FEATURES}) ELSE() SET(KWSYS_TARGET_INTERFACE ${KWSYS_NAMESPACE}) SET(KWSYS_TARGET_OBJECT ${KWSYS_NAMESPACE}) @@ -887,6 +896,7 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) SET(KWSYS_LINK_DEPENDENCY PUBLIC) ADD_LIBRARY(${KWSYS_TARGET_INTERFACE} ${KWSYS_LIBRARY_TYPE} ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS}) + target_compile_features(${KWSYS_TARGET_INTERFACE} PUBLIC ${KWSYS_CXX_COMPILE_FEATURES}) ENDIF() if (KWSYS_ALIAS_TARGET) add_library(${KWSYS_ALIAS_TARGET} ALIAS ${KWSYS_TARGET_INTERFACE}) @@ -964,7 +974,7 @@ IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS) ${KWSYS_TARGET_C_INTERFACE} ${KWSYS_TARGET_C_LINK}) SET(KWSYS_LINK_DEPENDENCY INTERFACE) ADD_LIBRARY(${KWSYS_TARGET_C_OBJECT} OBJECT ${KWSYS_C_SRCS}) - IF(KWSYS_BUILD_SHARED) + IF(KWSYS_BUILD_SHARED OR KWSYS_BUILD_PIC) SET_PROPERTY(TARGET ${KWSYS_TARGET_C_OBJECT} PROPERTY POSITION_INDEPENDENT_CODE TRUE) ENDIF() diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 094c2ee23..f65690b31 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -1162,7 +1162,7 @@ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length, case KWSYSPE_PIPE_STDERR: wd->PipeId = kwsysProcess_Pipe_STDERR; break; - }; + } return 1; } } else if (n < 0 && errno == EAGAIN) { diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index d368fa29f..f323efc4b 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -3871,7 +3871,8 @@ SystemInformation::LongLong SystemInformationImplementation::GetProcessId() { #if defined(_WIN32) return GetCurrentProcessId(); -#elif defined(__linux) || defined(__APPLE__) +#elif defined(__linux) || defined(__APPLE__) || defined(__OpenBSD__) || \ + defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) return getpid(); #else return -1; @@ -4423,7 +4424,8 @@ bool SystemInformationImplementation::ParseSysCtl() &count) == KERN_SUCCESS) { len = sizeof(value); err = sysctlbyname("hw.pagesize", &value, &len, KWSYS_NULLPTR, 0); - int64_t available_memory = vmstat.free_count * value; + int64_t available_memory = + (vmstat.free_count + vmstat.inactive_count) * value; this->AvailablePhysicalMemory = static_cast<size_t>(available_memory / 1048576); } diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 0a4ad7aac..d8904fed7 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -82,6 +82,10 @@ # include <signal.h> /* sigprocmask */ #endif +#ifdef __linux +# include <linux/fs.h> +#endif + // Windows API. #if defined(_WIN32) # include <windows.h> @@ -1355,39 +1359,15 @@ bool SystemTools::Touch(const std::string& filename, bool create) } CloseHandle(h); #elif KWSYS_CXX_HAS_UTIMENSAT - struct timespec times[2] = { { 0, UTIME_OMIT }, { 0, UTIME_NOW } }; - if (utimensat(AT_FDCWD, filename.c_str(), times, 0) < 0) { + // utimensat is only available on newer Unixes and macOS 10.13+ + if (utimensat(AT_FDCWD, filename.c_str(), NULL, 0) < 0) { return false; } #else - struct stat st; - if (stat(filename.c_str(), &st) < 0) { - return false; - } - struct timeval mtime; - gettimeofday(&mtime, 0); -# if KWSYS_CXX_HAS_UTIMES - struct timeval atime; -# if KWSYS_CXX_STAT_HAS_ST_MTIM - atime.tv_sec = st.st_atim.tv_sec; - atime.tv_usec = st.st_atim.tv_nsec / 1000; -# elif KWSYS_CXX_STAT_HAS_ST_MTIMESPEC - atime.tv_sec = st.st_atimespec.tv_sec; - atime.tv_usec = st.st_atimespec.tv_nsec / 1000; -# else - atime.tv_sec = st.st_atime; - atime.tv_usec = 0; -# endif - struct timeval times[2] = { atime, mtime }; - if (utimes(filename.c_str(), times) < 0) { + // fall back to utimes + if (utimes(filename.c_str(), NULL) < 0) { return false; } -# else - struct utimbuf times = { st.st_atime, mtime.tv_sec }; - if (utime(filename.c_str(), ×) < 0) { - return false; - } -# endif #endif return true; } @@ -2181,16 +2161,152 @@ bool SystemTools::FilesDiffer(const std::string& source, return false; } +bool SystemTools::TextFilesDiffer(const std::string& path1, + const std::string& path2) +{ + kwsys::ifstream if1(path1.c_str()); + kwsys::ifstream if2(path2.c_str()); + if (!if1 || !if2) { + return true; + } + + for (;;) { + std::string line1, line2; + bool hasData1 = GetLineFromStream(if1, line1); + bool hasData2 = GetLineFromStream(if2, line2); + if (hasData1 != hasData2) { + return true; + } + if (!hasData1) { + break; + } + if (line1 != line2) { + return true; + } + } + return false; +} + +/** + * Blockwise copy source to destination file + */ +static bool CopyFileContentBlockwise(const std::string& source, + const std::string& destination) +{ +// Open files +#if defined(_WIN32) + kwsys::ifstream fin( + Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(), + std::ios::in | std::ios::binary); +#else + kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); +#endif + if (!fin) { + return false; + } + + // try and remove the destination file so that read only destination files + // can be written to. + // If the remove fails continue so that files in read only directories + // that do not allow file removal can be modified. + SystemTools::RemoveFile(destination); + +#if defined(_WIN32) + kwsys::ofstream fout( + Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(destination)).c_str(), + std::ios::out | std::ios::trunc | std::ios::binary); +#else + kwsys::ofstream fout(destination.c_str(), + std::ios::out | std::ios::trunc | std::ios::binary); +#endif + if (!fout) { + return false; + } + + // This copy loop is very sensitive on certain platforms with + // slightly broken stream libraries (like HPUX). Normally, it is + // incorrect to not check the error condition on the fin.read() + // before using the data, but the fin.gcount() will be zero if an + // error occurred. Therefore, the loop should be safe everywhere. + while (fin) { + const int bufferSize = 4096; + char buffer[bufferSize]; + + fin.read(buffer, bufferSize); + if (fin.gcount()) { + fout.write(buffer, fin.gcount()); + } else { + break; + } + } + + // Make sure the operating system has finished writing the file + // before closing it. This will ensure the file is finished before + // the check below. + fout.flush(); + + fin.close(); + fout.close(); + + if (!fout) { + return false; + } + + return true; +} + +/** + * Clone the source file to the destination file + * + * If available, the Linux FICLONE ioctl is used to create a check + * copy-on-write clone of the source file. + * + * The method returns false for the following cases: + * - The code has not been compiled on Linux or the ioctl was unknown + * - The source and destination is on different file systems + * - The underlying filesystem does not support file cloning + * - An unspecified error occurred + */ +static bool CloneFileContent(const std::string& source, + const std::string& destination) +{ +#if defined(__linux) && defined(FICLONE) + int in = open(source.c_str(), O_RDONLY); + if (in < 0) { + return false; + } + + SystemTools::RemoveFile(destination); + + int out = + open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (out < 0) { + close(in); + return false; + } + + int result = ioctl(out, FICLONE, in); + close(in); + close(out); + + if (result < 0) { + return false; + } + + return true; +#else + (void)source; + (void)destination; + return false; +#endif +} + /** * Copy a file named by "source" to the file named by "destination". */ bool SystemTools::CopyFileAlways(const std::string& source, const std::string& destination) { - // If files are the same do not copy - if (SystemTools::SameFile(source, destination)) { - return true; - } mode_t perm = 0; bool perms = SystemTools::GetPermissions(source, perm); std::string real_destination = destination; @@ -2198,9 +2314,6 @@ bool SystemTools::CopyFileAlways(const std::string& source, if (SystemTools::FileIsDirectory(source)) { SystemTools::MakeDirectory(destination); } else { - const int bufferSize = 4096; - char buffer[bufferSize]; - // If destination is a directory, try to create a file with the same // name as the source in that directory. @@ -2214,67 +2327,21 @@ bool SystemTools::CopyFileAlways(const std::string& source, } else { destination_dir = SystemTools::GetFilenamePath(destination); } + // If files are the same do not copy + if (SystemTools::SameFile(source, real_destination)) { + return true; + } // Create destination directory SystemTools::MakeDirectory(destination_dir); -// Open files -#if defined(_WIN32) - kwsys::ifstream fin( - Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(), - std::ios::in | std::ios::binary); -#else - kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); -#endif - if (!fin) { - return false; - } - - // try and remove the destination file so that read only destination files - // can be written to. - // If the remove fails continue so that files in read only directories - // that do not allow file removal can be modified. - SystemTools::RemoveFile(real_destination); - -#if defined(_WIN32) - kwsys::ofstream fout( - Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(real_destination)) - .c_str(), - std::ios::out | std::ios::trunc | std::ios::binary); -#else - kwsys::ofstream fout(real_destination.c_str(), - std::ios::out | std::ios::trunc | std::ios::binary); -#endif - if (!fout) { - return false; - } - - // This copy loop is very sensitive on certain platforms with - // slightly broken stream libraries (like HPUX). Normally, it is - // incorrect to not check the error condition on the fin.read() - // before using the data, but the fin.gcount() will be zero if an - // error occurred. Therefore, the loop should be safe everywhere. - while (fin) { - fin.read(buffer, bufferSize); - if (fin.gcount()) { - fout.write(buffer, fin.gcount()); - } else { - break; + if (!CloneFileContent(source, real_destination)) { + // if cloning did not succeed, fall back to blockwise copy + if (!CopyFileContentBlockwise(source, real_destination)) { + return false; } } - - // Make sure the operating system has finished writing the file - // before closing it. This will ensure the file is finished before - // the check below. - fout.flush(); - - fin.close(); - fout.close(); - - if (!fout) { - return false; - } } if (perms) { if (!SystemTools::SetPermissions(real_destination, perm)) { @@ -2938,10 +3005,36 @@ bool SystemTools::FileIsDirectory(const std::string& inName) bool SystemTools::FileIsSymlink(const std::string& name) { #if defined(_WIN32) - DWORD attr = - GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str()); + std::wstring path = Encoding::ToWindowsExtendedPath(name); + DWORD attr = GetFileAttributesW(path.c_str()); if (attr != INVALID_FILE_ATTRIBUTES) { - return (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0; + if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { + // FILE_ATTRIBUTE_REPARSE_POINT means: + // * a file or directory that has an associated reparse point, or + // * a file that is a symbolic link. + HANDLE hFile = CreateFileW( + path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return false; + } + byte buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + DWORD bytesReturned = 0; + if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned, + NULL)) { + CloseHandle(hFile); + // Since FILE_ATTRIBUTE_REPARSE_POINT is set this file must be + // a symbolic link if it is not a reparse point. + return GetLastError() == ERROR_NOT_A_REPARSE_POINT; + } + CloseHandle(hFile); + ULONG reparseTag = + reinterpret_cast<PREPARSE_GUID_DATA_BUFFER>(&buffer[0])->ReparseTag; + return (reparseTag == IO_REPARSE_TAG_SYMLINK) || + (reparseTag == IO_REPARSE_TAG_MOUNT_POINT); + } + return false; } else { return false; } diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 8d1f78cf7..1967860ab 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -579,6 +579,13 @@ public: const std::string& destination); /** + * Compare the contents of two files, ignoring line ending differences. + * Return true if different + */ + static bool TextFilesDiffer(const std::string& path1, + const std::string& path2); + + /** * Return true if the two files are the same file */ static bool SameFile(const std::string& file1, const std::string& file2); diff --git a/Source/kwsys/kwsysPlatformTests.cmake b/Source/kwsys/kwsysPlatformTests.cmake index 5386a49a3..28d3f68e2 100644 --- a/Source/kwsys/kwsysPlatformTests.cmake +++ b/Source/kwsys/kwsysPlatformTests.cmake @@ -7,11 +7,16 @@ SET(KWSYS_PLATFORM_TEST_FILE_CXX kwsysPlatformTestsCXX.cxx) MACRO(KWSYS_PLATFORM_TEST lang var description invert) IF(NOT DEFINED ${var}_COMPILED) MESSAGE(STATUS "${description}") + set(maybe_cxx_standard "") + if(CMAKE_VERSION VERSION_LESS 3.8 AND CMAKE_CXX_STANDARD) + set(maybe_cxx_standard "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}") + endif() TRY_COMPILE(${var}_COMPILED ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}} COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_TEST_DEFINES} ${KWSYS_PLATFORM_TEST_EXTRA_FLAGS} CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${KWSYS_PLATFORM_TEST_LINK_LIBRARIES}" + ${maybe_cxx_standard} OUTPUT_VARIABLE OUTPUT) IF(${var}_COMPILED) FILE(APPEND diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx index ef874361f..15f9c02ba 100644 --- a/Source/kwsys/testCommandLineArguments.cxx +++ b/Source/kwsys/testCommandLineArguments.cxx @@ -165,25 +165,26 @@ int testCommandLineArguments(int argc, char* argv[]) } size_t cc; #define CompareTwoLists(list1, list_valid, lsize) \ - if (list1.size() != lsize) { \ - std::cerr << "Problem setting " #list1 ". Size is: " << list1.size() \ - << " should be: " << lsize << std::endl; \ - res = 1; \ - } else { \ - std::cout << #list1 " argument set:"; \ - for (cc = 0; cc < lsize; ++cc) { \ - std::cout << " " << list1[cc]; \ - if (!CompareTwoItemsOnList(list1[cc], list_valid[cc])) { \ - std::cerr << "Problem setting " #list1 ". Value of " << cc \ - << " is: [" << list1[cc] << "] <> [" << list_valid[cc] \ - << "]" << std::endl; \ - res = 1; \ - break; \ + do { \ + if (list1.size() != lsize) { \ + std::cerr << "Problem setting " #list1 ". Size is: " << list1.size() \ + << " should be: " << lsize << std::endl; \ + res = 1; \ + } else { \ + std::cout << #list1 " argument set:"; \ + for (cc = 0; cc < lsize; ++cc) { \ + std::cout << " " << list1[cc]; \ + if (!CompareTwoItemsOnList(list1[cc], list_valid[cc])) { \ + std::cerr << "Problem setting " #list1 ". Value of " << cc \ + << " is: [" << list1[cc] << "] <> [" << list_valid[cc] \ + << "]" << std::endl; \ + res = 1; \ + break; \ + } \ } \ + std::cout << std::endl; \ } \ - std::cout << std::endl; \ - } - + } while (0) CompareTwoLists(numbers_argument, valid_numbers, 10); CompareTwoLists(doubles_argument, valid_doubles, 3); CompareTwoLists(bools_argument, valid_bools, 3); diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 0477d5937..9a40b5330 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -984,6 +984,50 @@ static bool CheckGetLineFromStreamLongLine() return true; } +static bool writeFile(const char* fileName, const char* data) +{ + kwsys::ofstream out(fileName, std::ios::binary); + out << data; + if (!out) { + std::cerr << "Failed to write file: " << fileName << std::endl; + return false; + } + return true; +} + +static bool CheckTextFilesDiffer() +{ + struct + { + const char* a; + const char* b; + bool differ; + } test_cases[] = { { "one", "one", false }, + { "one", "two", true }, + { "", "", false }, + { "\n", "\r\n", false }, + { "one\n", "one\n", false }, + { "one\r\n", "one\n", false }, + { "one\n", "one", false }, + { "one\ntwo", "one\ntwo", false }, + { "one\ntwo", "one\r\ntwo", false } }; + const int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]); + for (int i = 0; i < num_test_cases; ++i) { + if (!writeFile("file_a", test_cases[i].a) || + !writeFile("file_b", test_cases[i].b)) { + return false; + } + if (kwsys::SystemTools::TextFilesDiffer("file_a", "file_b") != + test_cases[i].differ) { + std::cerr << "Incorrect TextFilesDiffer result for test case " << i + 1 + << "." << std::endl; + return false; + } + } + + return true; +} + int testSystemTools(int, char* []) { bool res = true; @@ -1027,5 +1071,7 @@ int testSystemTools(int, char* []) res &= CheckGetFilenameName(); + res &= CheckTextFilesDiffer(); + return res ? 0 : 1; } |