diff options
Diffstat (limited to 'Source')
180 files changed, 8114 insertions, 4224 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index ddcdd7e..2deaaaa 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -182,6 +182,8 @@ set(SRCS cmComputeTargetDepends.cxx cmConsoleBuf.h cmConsoleBuf.cxx + cmConstStack.h + cmConstStack.tcc cmCPackPropertiesGenerator.h cmCPackPropertiesGenerator.cxx cmCryptoHash.cxx @@ -358,6 +360,8 @@ set(SRCS cmLocalCommonGenerator.h cmLocalGenerator.cxx cmLocalGenerator.h + cmPlaceholderExpander.cxx + cmPlaceholderExpander.h cmRulePlaceholderExpander.cxx cmRulePlaceholderExpander.h cmLocalUnixMakefileGenerator3.cxx @@ -456,6 +460,8 @@ set(SRCS cmVariableWatch.h cmVersion.cxx cmVersion.h + cmWindowsRegistry.cxx + cmWindowsRegistry.h cmWorkerPool.cxx cmWorkerPool.h cmWorkingDirectory.cxx @@ -728,7 +734,7 @@ set(SRCS bindexplib.cxx ) -SET_PROPERTY(SOURCE cmProcessOutput.cxx APPEND PROPERTY COMPILE_DEFINITIONS +SET_PROPERTY(SOURCE cmProcessOutput.cxx cmWindowsRegistry.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE}) # Xcode only works on Apple @@ -1115,7 +1121,6 @@ if(APPLE) CPack/cmCPackBundleGenerator.cxx CPack/cmCPackDragNDropGenerator.cxx CPack/cmCPackPKGGenerator.cxx - CPack/cmCPackPackageMakerGenerator.cxx CPack/cmCPackProductBuildGenerator.cxx ) endif() diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 19359d8..e650f7f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 23) -set(CMake_VERSION_PATCH 1) +set(CMake_VERSION_PATCH 20220518) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 6a0095b..594f408 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -89,10 +89,21 @@ bool cmCPackWIXGenerator::RunCandleCommand(std::string const& sourceFile, return false; } + std::string arch; + if (cmValue archOpt = GetOption("CPACK_WIX_ARCHITECTURE")) { + arch = *archOpt; + } else { + arch = GetArchitecture(); + cmCPackLogger( + cmCPackLog::LOG_VERBOSE, + "CPACK_WIX_ARCHITECTURE was not set. Invoking WiX with architecture " + << arch << " . " << std::endl); + } + std::ostringstream command; command << QuotePath(executable); command << " -nologo"; - command << " -arch " << GetArchitecture(); + command << " -arch " << arch; command << " -out " << QuotePath(objectFile); for (std::string const& ext : CandleExtensions) { diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index 0b2acca..725ea8a 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -21,7 +21,6 @@ #ifdef __APPLE__ # include "cmCPackBundleGenerator.h" # include "cmCPackDragNDropGenerator.h" -# include "cmCPackPackageMakerGenerator.h" # include "cmCPackProductBuildGenerator.h" #endif @@ -108,10 +107,6 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("Bundle", "Mac OSX bundle", cmCPackBundleGenerator::CreateGenerator); } - if (cmCPackPackageMakerGenerator::CanGenerate()) { - this->RegisterGenerator("PackageMaker", "Mac OSX Package Maker installer", - cmCPackPackageMakerGenerator::CreateGenerator); - } if (cmCPackProductBuildGenerator::CanGenerate()) { this->RegisterGenerator("productbuild", "Mac OSX pkg", cmCPackProductBuildGenerator::CreateGenerator); diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx deleted file mode 100644 index a8cf1fa..0000000 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ /dev/null @@ -1,577 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmCPackPackageMakerGenerator.h" - -#include <cassert> -#include <cstdio> -#include <cstdlib> -#include <map> -#include <sstream> -#include <string> - -#include "cmsys/FStream.hxx" -#include "cmsys/RegularExpression.hxx" - -#include "cmCPackComponentGroup.h" -#include "cmCPackLog.h" -#include "cmDuration.h" -#include "cmGeneratedFileStream.h" -#include "cmStringAlgorithms.h" -#include "cmSystemTools.h" -#include "cmValue.h" -#include "cmXMLWriter.h" - -static inline unsigned int getVersion(unsigned int major, unsigned int minor) -{ - assert(major < 256 && minor < 256); - return ((major & 0xFF) << 16 | minor); -} - -cmCPackPackageMakerGenerator::cmCPackPackageMakerGenerator() -{ - this->PackageMakerVersion = 0.0; - this->PackageCompatibilityVersion = getVersion(10, 4); -} - -cmCPackPackageMakerGenerator::~cmCPackPackageMakerGenerator() = default; - -bool cmCPackPackageMakerGenerator::SupportsComponentInstallation() const -{ - return this->PackageCompatibilityVersion >= getVersion(10, 4); -} - -int cmCPackPackageMakerGenerator::PackageFiles() -{ - // TODO: Use toplevel - // It is used! Is this an obsolete comment? - - std::string resDir; // Where this package's resources will go. - std::string packageDirFileName = - this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - if (this->Components.empty()) { - packageDirFileName += ".pkg"; - resDir = - cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources"); - } else { - packageDirFileName += ".mpkg"; - if (!cmsys::SystemTools::MakeDirectory(packageDirFileName.c_str())) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "unable to create package directory " << packageDirFileName - << std::endl); - return 0; - } - - resDir = cmStrCat(packageDirFileName, "/Contents"); - if (!cmsys::SystemTools::MakeDirectory(resDir.c_str())) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "unable to create package subdirectory " << resDir - << std::endl); - return 0; - } - - resDir += "/Resources"; - if (!cmsys::SystemTools::MakeDirectory(resDir.c_str())) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "unable to create package subdirectory " << resDir - << std::endl); - return 0; - } - - resDir += "/en.lproj"; - } - - cmValue preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT"); - cmValue postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT"); - cmValue postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT"); - - if (this->Components.empty()) { - // Create directory structure - std::string preflightDirName = resDir + "/PreFlight"; - std::string postflightDirName = resDir + "/PostFlight"; - // if preflight or postflight scripts not there create directories - // of the same name, I think this makes it work - if (!preflight) { - if (!cmsys::SystemTools::MakeDirectory(preflightDirName.c_str())) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem creating installer directory: " - << preflightDirName << std::endl); - return 0; - } - } - if (!postflight) { - if (!cmsys::SystemTools::MakeDirectory(postflightDirName.c_str())) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem creating installer directory: " - << postflightDirName << std::endl); - return 0; - } - } - // if preflight, postflight, or postupgrade are set - // then copy them into the resource directory and make - // them executable - if (preflight) { - this->CopyInstallScript(resDir, preflight, "preflight"); - } - if (postflight) { - this->CopyInstallScript(resDir, postflight, "postflight"); - } - if (postupgrade) { - this->CopyInstallScript(resDir, postupgrade, "postupgrade"); - } - } else if (postflight) { - // create a postflight component to house the script - this->PostFlightComponent.Name = "PostFlight"; - this->PostFlightComponent.DisplayName = "PostFlight"; - this->PostFlightComponent.Description = "PostFlight"; - this->PostFlightComponent.IsHidden = true; - - // empty directory for pkg contents - std::string packageDir = toplevel + "/" + PostFlightComponent.Name; - if (!cmsys::SystemTools::MakeDirectory(packageDir.c_str())) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem creating component packages directory: " - << packageDir << std::endl); - return 0; - } - - // create package - std::string packageFileDir = packageDirFileName + "/Contents/Packages/"; - if (!cmsys::SystemTools::MakeDirectory(packageFileDir.c_str())) { - cmCPackLogger( - cmCPackLog::LOG_ERROR, - "Problem creating component PostFlight Packages directory: " - << packageFileDir << std::endl); - return 0; - } - std::string packageFile = - packageFileDir + this->GetPackageName(PostFlightComponent); - if (!this->GenerateComponentPackage( - packageFile.c_str(), packageDir.c_str(), PostFlightComponent)) { - return 0; - } - - // copy postflight script into resource directory of .pkg - std::string resourceDir = packageFile + "/Contents/Resources"; - this->CopyInstallScript(resourceDir, postflight, "postflight"); - } - - if (!this->Components.empty()) { - // Create the directory where component packages will be built. - std::string basePackageDir = - cmStrCat(packageDirFileName, "/Contents/Packages"); - if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem creating component packages directory: " - << basePackageDir << std::endl); - return 0; - } - - // Create the directory where downloaded component packages will - // be placed. - cmValue userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY"); - std::string uploadDirectory; - if (userUploadDirectory && !userUploadDirectory->empty()) { - uploadDirectory = userUploadDirectory; - } else { - uploadDirectory = - cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads"); - } - - // Create packages for each component - bool warnedAboutDownloadCompatibility = false; - - std::map<std::string, cmCPackComponent>::iterator compIt; - for (compIt = this->Components.begin(); compIt != this->Components.end(); - ++compIt) { - std::string packageFile; - if (compIt->second.IsDownloaded) { - if (this->PackageCompatibilityVersion >= getVersion(10, 5) && - this->PackageMakerVersion >= 3.0) { - // Build this package within the upload directory. - packageFile = uploadDirectory; - - if (!cmSystemTools::FileExists(uploadDirectory.c_str())) { - if (!cmSystemTools::MakeDirectory(uploadDirectory.c_str())) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Unable to create package upload directory " - << uploadDirectory << std::endl); - return 0; - } - } - } else if (!warnedAboutDownloadCompatibility) { - if (this->PackageCompatibilityVersion < getVersion(10, 5)) { - cmCPackLogger( - cmCPackLog::LOG_WARNING, - "CPack warning: please set CPACK_OSX_PACKAGE_VERSION to 10.5 " - "or greater enable downloaded packages. CPack will build a " - "non-downloaded package." - << std::endl); - } - - if (this->PackageMakerVersion < 3) { - cmCPackLogger(cmCPackLog::LOG_WARNING, - "CPack warning: unable to build downloaded " - "packages with PackageMaker versions prior " - "to 3.0. CPack will build a non-downloaded package." - << std::endl); - } - - warnedAboutDownloadCompatibility = true; - } - } - - if (packageFile.empty()) { - // Build this package within the overall distribution - // metapackage. - packageFile = basePackageDir; - - // We're not downloading this component, even if the user - // requested it. - compIt->second.IsDownloaded = false; - } - - packageFile += '/'; - packageFile += GetPackageName(compIt->second); - - std::string packageDir = cmStrCat(toplevel, '/', compIt->first); - if (!this->GenerateComponentPackage( - packageFile.c_str(), packageDir.c_str(), compIt->second)) { - return 0; - } - } - } - this->SetOption("CPACK_MODULE_VERSION_SUFFIX", ""); - - // Copy or create all of the resource files we need. - if (!this->CopyCreateResourceFile("License", resDir) || - !this->CopyCreateResourceFile("ReadMe", resDir) || - !this->CopyCreateResourceFile("Welcome", resDir) || - !this->CopyResourcePlistFile("Info.plist") || - !this->CopyResourcePlistFile("Description.plist")) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem copying the resource files" << std::endl); - return 0; - } - - if (this->Components.empty()) { - // Use PackageMaker to build the package. - std::ostringstream pkgCmd; - pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM") - << "\" -build -p \"" << packageDirFileName << "\""; - if (this->Components.empty()) { - pkgCmd << " -f \"" << this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - } else { - pkgCmd << " -mi \"" << this->GetOption("CPACK_TEMPORARY_DIRECTORY") - << "/packages/"; - } - pkgCmd << "\" -r \"" << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") - << "/Resources\" -i \"" - << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") - << "/Info.plist\" -d \"" - << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") - << "/Description.plist\""; - if (this->PackageMakerVersion > 2.0) { - pkgCmd << " -v"; - } - if (!RunPackageMaker(pkgCmd.str().c_str(), packageDirFileName.c_str())) { - return 0; - } - } else { - // We have built the package in place. Generate the - // distribution.dist file to describe it for the installer. - WriteDistributionFile(packageDirFileName.c_str(), "PACKAGEMAKER"); - } - - std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), - "/hdiutilOutput.log"); - std::ostringstream dmgCmd; - dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE") - << "\" create -ov -fs HFS+ -format UDZO -srcfolder \"" - << packageDirFileName << "\" \"" << packageFileNames[0] << "\""; - std::string output; - int retVal = 1; - int numTries = 10; - bool res = false; - while (numTries > 0) { - res = cmSystemTools::RunSingleCommand( - dmgCmd.str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose, - cmDuration::zero()); - if (res && !retVal) { - numTries = -1; - break; - } - cmSystemTools::Delay(500); - numTries--; - } - if (!res || retVal) { - cmGeneratedFileStream ofs(tmpFile); - ofs << "# Run command: " << dmgCmd.str() << std::endl - << "# Output:" << std::endl - << output << std::endl; - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem running hdiutil command: " - << dmgCmd.str() << std::endl - << "Please check " << tmpFile << " for errors" - << std::endl); - return 0; - } - - return 1; -} - -int cmCPackPackageMakerGenerator::InitializeInternal() -{ - cmCPackLogger(cmCPackLog::LOG_WARNING, - "The PackageMaker generator is deprecated " - "and will be removed in a future version.\n"); - this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr"); - - // Starting with Xcode 4.3, PackageMaker is a separate app, and you - // can put it anywhere you want. So... use a variable for its location. - // People who put it in unexpected places can use the variable to tell - // us where it is. - // - // Use the following locations, in "most recent installation" order, - // to search for the PackageMaker app. Assume people who copy it into - // the new Xcode 4.3 app in "/Applications" will copy it into the nested - // Applications folder inside the Xcode bundle itself. Or directly in - // the "/Applications" directory. - // - // If found, save result in the CPACK_INSTALLER_PROGRAM variable. - - std::vector<std::string> paths; - 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; - cmValue inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM"); - if (inst_program && !inst_program->empty()) { - pkgPath = inst_program; - } else { - pkgPath = cmSystemTools::FindProgram("PackageMaker", paths, false); - if (pkgPath.empty()) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find PackageMaker compiler" << std::endl); - return 0; - } - this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath); - } - - // Get path to the real PackageMaker, not a symlink: - pkgPath = cmSystemTools::GetRealPath(pkgPath); - // Up from there to find the version.plist file in the "Contents" dir: - std::string contents_dir; - contents_dir = cmSystemTools::GetFilenamePath(pkgPath); - contents_dir = cmSystemTools::GetFilenamePath(contents_dir); - - std::string versionFile = contents_dir + "/version.plist"; - - if (!cmSystemTools::FileExists(versionFile.c_str())) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find PackageMaker compiler version file: " - << versionFile << std::endl); - return 0; - } - - cmsys::ifstream ifs(versionFile.c_str()); - if (!ifs) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot open PackageMaker compiler version file" - << std::endl); - return 0; - } - - // Check the PackageMaker version - cmsys::RegularExpression rexKey("<key>CFBundleShortVersionString</key>"); - cmsys::RegularExpression rexVersion("<string>([0-9]+.[0-9.]+)</string>"); - std::string line; - bool foundKey = false; - while (cmSystemTools::GetLineFromStream(ifs, line)) { - if (rexKey.find(line)) { - foundKey = true; - break; - } - } - if (!foundKey) { - cmCPackLogger( - cmCPackLog::LOG_ERROR, - "Cannot find CFBundleShortVersionString in the PackageMaker compiler " - "version file" - << std::endl); - return 0; - } - if (!cmSystemTools::GetLineFromStream(ifs, line) || !rexVersion.find(line)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem reading the PackageMaker compiler version file: " - << versionFile << std::endl); - return 0; - } - this->PackageMakerVersion = atof(rexVersion.match(1).c_str()); - if (this->PackageMakerVersion < 1.0) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Require PackageMaker 1.0 or higher" << std::endl); - return 0; - } - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "PackageMaker version is: " << this->PackageMakerVersion - << std::endl); - - // Determine the package compatibility version. If it wasn't - // specified by the user, we define it based on which features the - // user requested. - cmValue packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION"); - if (packageCompat && !packageCompat->empty()) { - unsigned int majorVersion = 10; - unsigned int minorVersion = 5; - int res = - sscanf(packageCompat->c_str(), "%u.%u", &majorVersion, &minorVersion); - if (res == 2) { - this->PackageCompatibilityVersion = - getVersion(majorVersion, minorVersion); - } - } else if (this->GetOption("CPACK_DOWNLOAD_SITE")) { - this->SetOption("CPACK_OSX_PACKAGE_VERSION", "10.5"); - this->PackageCompatibilityVersion = getVersion(10, 5); - } else if (this->GetOption("CPACK_COMPONENTS_ALL")) { - this->SetOption("CPACK_OSX_PACKAGE_VERSION", "10.4"); - this->PackageCompatibilityVersion = getVersion(10, 4); - } else { - this->SetOption("CPACK_OSX_PACKAGE_VERSION", "10.3"); - this->PackageCompatibilityVersion = getVersion(10, 3); - } - - std::vector<std::string> no_paths; - pkgPath = cmSystemTools::FindProgram("hdiutil", no_paths, false); - if (pkgPath.empty()) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find hdiutil compiler" << std::endl); - return 0; - } - this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE", pkgPath); - - return this->Superclass::InitializeInternal(); -} - -bool cmCPackPackageMakerGenerator::RunPackageMaker(const char* command, - const char* packageFile) -{ - std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), - "/PackageMakerOutput.log"); - - cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl); - std::string output; - int retVal = 1; - bool res = cmSystemTools::RunSingleCommand( - command, &output, &output, &retVal, nullptr, this->GeneratorVerbose, - cmDuration::zero()); - cmCPackLogger(cmCPackLog::LOG_VERBOSE, - "Done running package maker" << std::endl); - if (!res || retVal) { - cmGeneratedFileStream ofs(tmpFile); - ofs << "# Run command: " << command << std::endl - << "# Output:" << std::endl - << output << std::endl; - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem running PackageMaker command: " - << command << std::endl - << "Please check " << tmpFile << " for errors" - << std::endl); - return false; - } - // sometimes the command finishes but the directory is not yet - // created, so try 10 times to see if it shows up - int tries = 10; - while (tries > 0 && !cmSystemTools::FileExists(packageFile)) { - cmSystemTools::Delay(500); - tries--; - } - if (!cmSystemTools::FileExists(packageFile)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem running PackageMaker command: " - << command << std::endl - << "Package not created: " << packageFile << std::endl); - return false; - } - - return true; -} - -bool cmCPackPackageMakerGenerator::GenerateComponentPackage( - const char* packageFile, const char* packageDir, - const cmCPackComponent& component) -{ - cmCPackLogger(cmCPackLog::LOG_OUTPUT, - "- Building component package: " << packageFile - << std::endl); - - // The command that will be used to run PackageMaker - std::ostringstream pkgCmd; - - if (this->PackageCompatibilityVersion < getVersion(10, 5) || - this->PackageMakerVersion < 3.0) { - // Create Description.plist and Info.plist files for normal Mac OS - // X packages, which work on Mac OS X 10.3 and newer. - std::string descriptionFile = - cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', - component.Name, "-Description.plist"); - cmsys::ofstream out(descriptionFile.c_str()); - cmXMLWriter xout(out); - xout.StartDocument(); - xout.Doctype("plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"" - "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\""); - xout.StartElement("plist"); - xout.Attribute("version", "1.4"); - xout.StartElement("dict"); - xout.Element("key", "IFPkgDescriptionTitle"); - xout.Element("string", component.DisplayName); - xout.Element("key", "IFPkgDescriptionVersion"); - xout.Element("string", this->GetOption("CPACK_PACKAGE_VERSION")); - xout.Element("key", "IFPkgDescriptionDescription"); - xout.Element("string", component.Description); - xout.EndElement(); // dict - xout.EndElement(); // plist - xout.EndDocument(); - out.close(); - - // Create the Info.plist file for this component - std::string moduleVersionSuffix = cmStrCat('.', component.Name); - this->SetOption("CPACK_MODULE_VERSION_SUFFIX", moduleVersionSuffix); - std::string infoFileName = cmStrCat(component.Name, "-Info.plist"); - if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str())) { - return false; - } - - pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM") - << "\" -build -p \"" << packageFile << "\"" - << " -f \"" << packageDir << "\"" - << " -i \"" << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "/" - << infoFileName << "\"" - << " -d \"" << descriptionFile << "\""; - } else { - // Create a "flat" package on Mac OS X 10.5 and newer. Flat - // packages are stored in a single file, rather than a directory - // like normal packages, and can be downloaded by the installer - // on-the-fly in Mac OS X 10.5 or newer. Thus, we need to create - // flat packages when the packages will be downloaded on the fly. - std::string pkgId = - cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.', - this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name); - - pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM") - << "\" --root \"" << packageDir << "\"" - << " --id " << pkgId << " --target " - << this->GetOption("CPACK_OSX_PACKAGE_VERSION") << " --out \"" - << packageFile << "\""; - } - - // Run PackageMaker - return RunPackageMaker(pkgCmd.str().c_str(), packageFile); -} diff --git a/Source/CPack/cmCPackPackageMakerGenerator.h b/Source/CPack/cmCPackPackageMakerGenerator.h deleted file mode 100644 index cda9277..0000000 --- a/Source/CPack/cmCPackPackageMakerGenerator.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#pragma once - -#include "cmConfigure.h" // IWYU pragma: keep - -#include "cmCPackGenerator.h" -#include "cmCPackPKGGenerator.h" - -class cmCPackComponent; - -/** \class cmCPackPackageMakerGenerator - * \brief A generator for PackageMaker files - * - * http://developer.apple.com/documentation/Darwin - * /Reference/ManPages/man1/packagemaker.1.html - */ -class cmCPackPackageMakerGenerator : public cmCPackPKGGenerator -{ -public: - cmCPackTypeMacro(cmCPackPackageMakerGenerator, cmCPackPKGGenerator); - - /** - * Construct generator - */ - cmCPackPackageMakerGenerator(); - ~cmCPackPackageMakerGenerator() override; - bool SupportsComponentInstallation() const override; - -protected: - int InitializeInternal() override; - int PackageFiles() override; - const char* GetOutputExtension() override { return ".dmg"; } - - // Run PackageMaker with the given command line, which will (if - // successful) produce the given package file. Returns true if - // PackageMaker succeeds, false otherwise. - bool RunPackageMaker(const char* command, const char* packageFile); - - // Generate a package in the file packageFile for the given - // component. All of the files within this component are stored in - // the directory packageDir. Returns true if successful, false - // otherwise. - bool GenerateComponentPackage(const char* packageFile, - const char* packageDir, - const cmCPackComponent& component); - - double PackageMakerVersion; - unsigned int PackageCompatibilityVersion; -}; diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index f43642f..6c6d0ca 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include <cstddef> +#include <functional> #include <iostream> #include <map> #include <memory> @@ -10,12 +11,14 @@ #include <utility> #include <vector> -#include "cmsys/CommandLineArguments.hxx" +#include <cmext/algorithm> + #include "cmsys/Encoding.hxx" #include "cmCPackGenerator.h" #include "cmCPackGeneratorFactory.h" #include "cmCPackLog.h" +#include "cmCommandLineArgument.h" #include "cmConsoleBuf.h" #include "cmDocumentation.h" #include "cmDocumentationEntry.h" @@ -58,39 +61,6 @@ const char* cmDocumentationOptions[][2] = { { nullptr, nullptr } }; -int cpackUnknownArgument(const char* /*unused*/, void* /*unused*/) -{ - return 1; -} - -struct cpackDefinitions -{ - using MapType = std::map<std::string, std::string>; - MapType Map; - cmCPackLog* Log{}; -}; - -int cpackDefinitionArgument(const char* argument, const char* cValue, - void* call_data) -{ - (void)argument; - cpackDefinitions* def = static_cast<cpackDefinitions*>(call_data); - std::string value = cValue; - size_t pos = value.find_first_of('='); - if (pos == std::string::npos) { - cmCPack_Log(def->Log, cmCPackLog::LOG_ERROR, - "Please specify CPack definitions as: KEY=VALUE" << std::endl); - return 0; - } - std::string key = value.substr(0, pos); - value.erase(0, pos + 1); - def->Map[key] = value; - cmCPack_Log(def->Log, cmCPackLog::LOG_DEBUG, - "Set CPack variable: " << key << " to \"" << value << "\"" - << std::endl); - return 1; -} - void cpackProgressCallback(const std::string& message, float /*unused*/) { std::cout << "-- " << message << std::endl; @@ -111,6 +81,10 @@ int main(int argc, char const* const* argv) argc = args.argc(); argv = args.argv(); + std::vector<std::string> inputArgs; + inputArgs.reserve(argc - 1); + cm::append(inputArgs, argv + 1, argv + argc); + cmSystemTools::InitializeLibUV(); cmSystemTools::FindCMakeResources(argv[0]); cmCPackLog log; @@ -130,10 +104,6 @@ int main(int argc, char const* const* argv) std::string generator; bool help = false; bool helpVersion = false; - bool verbose = false; - bool trace = false; - bool traceExpand = false; - bool debug = false; std::string helpFull; std::string helpMAN; std::string helpHTML; @@ -146,64 +116,93 @@ int main(int argc, char const* const* argv) std::string cpackProjectVendor; std::string cpackConfigFile; - cpackDefinitions definitions; - definitions.Log = &log; - - cpackConfigFile.clear(); - - cmsys::CommandLineArguments arg; - arg.Initialize(argc, argv); - using argT = cmsys::CommandLineArguments; - // Help arguments - arg.AddArgument("--help", argT::NO_ARGUMENT, &help, "CPack help"); - arg.AddArgument("--help-full", argT::SPACE_ARGUMENT, &helpFull, - "CPack help"); - arg.AddArgument("--help-html", argT::SPACE_ARGUMENT, &helpHTML, - "CPack help"); - arg.AddArgument("--help-man", argT::SPACE_ARGUMENT, &helpMAN, "CPack help"); - arg.AddArgument("--version", argT::NO_ARGUMENT, &helpVersion, "CPack help"); - - arg.AddArgument("-V", argT::NO_ARGUMENT, &verbose, "CPack verbose"); - arg.AddArgument("--verbose", argT::NO_ARGUMENT, &verbose, "-V"); - arg.AddArgument("--debug", argT::NO_ARGUMENT, &debug, "-V"); - arg.AddArgument("--config", argT::SPACE_ARGUMENT, &cpackConfigFile, - "CPack configuration file"); - arg.AddArgument("--trace", argT::NO_ARGUMENT, &trace, - "Put underlying cmake scripts in trace mode."); - arg.AddArgument("--trace-expand", argT::NO_ARGUMENT, &traceExpand, - "Put underlying cmake scripts in expanded trace mode."); - arg.AddArgument("-C", argT::SPACE_ARGUMENT, &cpackBuildConfig, - "CPack build configuration"); - arg.AddArgument("-G", argT::SPACE_ARGUMENT, &generator, "CPack generator"); - arg.AddArgument("-P", argT::SPACE_ARGUMENT, &cpackProjectName, - "CPack project name"); - arg.AddArgument("-R", argT::SPACE_ARGUMENT, &cpackProjectVersion, - "CPack project version"); - arg.AddArgument("-B", argT::SPACE_ARGUMENT, &cpackProjectDirectory, - "CPack project directory"); - arg.AddArgument("--patch", argT::SPACE_ARGUMENT, &cpackProjectPatch, - "CPack project patch"); - arg.AddArgument("--vendor", argT::SPACE_ARGUMENT, &cpackProjectVendor, - "CPack project vendor"); - arg.AddCallback("-D", argT::SPACE_ARGUMENT, cpackDefinitionArgument, - &definitions, "CPack Definitions"); - arg.SetUnknownArgumentCallback(cpackUnknownArgument); - - // Parse command line - int parsed = arg.Parse(); - - // Setup logging - if (verbose) { - log.SetVerbose(verbose); + std::map<std::string, std::string> definitions; + + auto const verboseLambda = [&log](const std::string&, cmake*, + cmMakefile*) -> bool { + log.SetVerbose(true); cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Verbose" << std::endl); - } - if (debug) { - log.SetDebug(debug); - cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Debug" << std::endl); - } + return true; + }; - cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, - "Read CPack config file: " << cpackConfigFile << std::endl); + auto const debugLambda = [&log](const std::string&, cmake*, + cmMakefile*) -> bool { + log.SetDebug(true); + cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Debug" << std::endl); + return true; + }; + + auto const traceLambda = [](const std::string&, cmake* state, + cmMakefile*) -> bool { + state->SetTrace(true); + return true; + }; + + auto const traceExpandLambda = [](const std::string&, cmake* state, + cmMakefile*) -> bool { + state->SetTrace(true); + state->SetTraceExpand(true); + return true; + }; + + using CommandArgument = + cmCommandLineArgument<bool(std::string const&, cmake*, cmMakefile*)>; + + std::vector<CommandArgument> arguments = { + CommandArgument{ "--help", CommandArgument::Values::Zero, + CommandArgument::setToTrue(help) }, + CommandArgument{ "--help-full", CommandArgument::Values::Zero, + CommandArgument::setToValue(helpFull) }, + CommandArgument{ "--help-html", CommandArgument::Values::Zero, + CommandArgument::setToValue(helpHTML) }, + CommandArgument{ "--help-man", CommandArgument::Values::Zero, + CommandArgument::setToValue(helpMAN) }, + CommandArgument{ "--version", CommandArgument::Values::Zero, + CommandArgument::setToTrue(helpVersion) }, + CommandArgument{ "-V", CommandArgument::Values::Zero, verboseLambda }, + CommandArgument{ "--verbose", CommandArgument::Values::Zero, + verboseLambda }, + CommandArgument{ "--debug", CommandArgument::Values::Zero, debugLambda }, + CommandArgument{ "--config", CommandArgument::Values::One, + CommandArgument::setToValue(cpackConfigFile) }, + CommandArgument{ "--trace", CommandArgument::Values::One, traceLambda }, + CommandArgument{ "--trace-expand", CommandArgument::Values::One, + traceExpandLambda }, + CommandArgument{ "-C", CommandArgument::Values::One, + CommandArgument::setToValue(cpackBuildConfig) }, + CommandArgument{ "-G", CommandArgument::Values::One, + CommandArgument::setToValue(generator) }, + CommandArgument{ "-P", CommandArgument::Values::One, + CommandArgument::setToValue(cpackProjectName) }, + CommandArgument{ "-R", CommandArgument::Values::One, + CommandArgument::setToValue(cpackProjectVersion) }, + CommandArgument{ "-B", CommandArgument::Values::One, + CommandArgument::setToValue(cpackProjectDirectory) }, + CommandArgument{ "--patch", CommandArgument::Values::One, + CommandArgument::setToValue(cpackProjectPatch) }, + CommandArgument{ "--vendor", CommandArgument::Values::One, + CommandArgument::setToValue(cpackProjectVendor) }, + CommandArgument{ + "-D", CommandArgument::Values::One, + [&log, &definitions](const std::string& arg, cmake*, + cmMakefile*) -> bool { + std::string value = arg; + size_t pos = value.find_first_of('='); + if (pos == std::string::npos) { + cmCPack_Log(&log, cmCPackLog::LOG_ERROR, + "Please specify CPack definitions as: KEY=VALUE" + << std::endl); + return false; + } + std::string key = value.substr(0, pos); + value.erase(0, pos + 1); + definitions[key] = value; + cmCPack_Log(&log, cmCPackLog::LOG_DEBUG, + "Set CPack variable: " << key << " to \"" << value << "\"" + << std::endl); + return true; + } }, + }; cmake cminst(cmake::RoleScript, cmState::CPack); cminst.SetHomeDirectory(""); @@ -216,14 +215,22 @@ int main(int argc, char const* const* argv) globalMF.AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0"); #endif - if (trace) { - cminst.SetTrace(true); - } - if (traceExpand) { - cminst.SetTrace(true); - cminst.SetTraceExpand(true); + bool parsed = true; + for (std::size_t i = 0; i < inputArgs.size(); i++) { + auto const& arg = inputArgs[i]; + for (auto const& m : arguments) { + if (m.matches(arg)) { + if (!m.parse(arg, i, inputArgs, &cminst, &globalMF)) { + parsed = false; + } + break; + } + } } + cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, + "Read CPack config file: " << cpackConfigFile << std::endl); + bool cpackConfigFileSpecified = true; if (cpackConfigFile.empty()) { cpackConfigFile = cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), @@ -315,7 +322,7 @@ int main(int argc, char const* const* argv) cpackProjectDirectory); } } - for (auto const& cd : definitions.Map) { + for (auto const& cd : definitions) { globalMF.AddDefinition(cd.first, cd.second); } @@ -344,7 +351,7 @@ int main(int argc, char const* const* argv) if (!mf->GetDefinition("CPACK_PACKAGE_NAME")) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "CPack project name not specified" << std::endl); - parsed = 0; + parsed = false; } if (parsed && !(mf->GetDefinition("CPACK_PACKAGE_VERSION") || @@ -359,14 +366,14 @@ int main(int argc, char const* const* argv) "CPACK_PACKAGE_VERSION_MINOR, and " "CPACK_PACKAGE_VERSION_PATCH." << std::endl); - parsed = 0; + parsed = false; } if (parsed) { std::unique_ptr<cmCPackGenerator> cpackGenerator = generators.NewGenerator(gen); if (cpackGenerator) { - cpackGenerator->SetTrace(trace); - cpackGenerator->SetTraceExpand(traceExpand); + cpackGenerator->SetTrace(cminst.GetTrace()); + cpackGenerator->SetTraceExpand(cminst.GetTraceExpand()); } else { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Could not create CPack generator: " << gen @@ -384,14 +391,14 @@ int main(int argc, char const* const* argv) std::cerr << "\n"; generatorDocs.PrintDocumentation(cmDocumentation::ListGenerators, std::cerr); - parsed = 0; + parsed = false; } if (parsed && !cpackGenerator->Initialize(gen, mf)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot initialize the generator " << gen << std::endl); - parsed = 0; + parsed = false; } if (!mf->GetDefinition("CPACK_INSTALL_COMMANDS") && @@ -405,7 +412,7 @@ int main(int argc, char const* const* argv) "CPACK_INSTALL_COMMANDS, CPACK_INSTALL_SCRIPT, or " "CPACK_INSTALLED_DIRECTORIES." << std::endl); - parsed = 0; + parsed = false; } if (parsed) { cmValue projName = mf->GetDefinition("CPACK_PACKAGE_NAME"); diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 1b2f769..aef58c5 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -1218,11 +1218,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open file: " << gcovFile << std::endl); } else { - long cnt = -1; std::string nl; while (cmSystemTools::GetLineFromStream(ifile, nl)) { - cnt++; - // Skip empty lines if (nl.empty()) { continue; @@ -1528,7 +1525,6 @@ int cmCTestCoverageHandler::HandleLCovCoverage( cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open file: " << lcovFile << std::endl); } else { - long cnt = -1; std::string nl; // Skip the first line @@ -1537,8 +1533,6 @@ int cmCTestCoverageHandler::HandleLCovCoverage( "File is ready, start reading." << std::endl, this->Quiet); while (cmSystemTools::GetLineFromStream(ifile, nl)) { - cnt++; - // Skip empty lines if (nl.empty()) { continue; diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 6bb8e79..2d8276a 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -371,7 +371,8 @@ void cmCTestMemCheckHandler::GenerateCTestXML(cmXMLWriter& xml) } this->CleanTestOutput( memcheckstr, - static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)); + static_cast<size_t>(this->CustomMaximumFailedTestOutputSize), + this->TestOutputTruncation); this->WriteTestResultHeader(xml, result); xml.StartElement("Results"); int memoryErrors = 0; diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index d90c4a6..abd1aa6 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -1284,10 +1284,8 @@ void cmCTestMultiProcessHandler::PrintTestList() } this->TestHandler->SetMaxIndex(this->FindMaxIndex()); - int count = 0; for (auto& it : this->Properties) { - count++; cmCTestTestHandler::cmCTestTestProperties& p = *it.second; // Don't worry if this fails, we are only showing the test list, not diff --git a/Source/CTest/cmCTestResourceSpec.cxx b/Source/CTest/cmCTestResourceSpec.cxx index 101dc2c..142b07d 100644 --- a/Source/CTest/cmCTestResourceSpec.cxx +++ b/Source/CTest/cmCTestResourceSpec.cxx @@ -19,6 +19,8 @@ #include "cmJSONHelpers.h" namespace { +using JSONHelperBuilder = + cmJSONHelperBuilder<cmCTestResourceSpec::ReadFileResult>; const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" }; const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" }; @@ -34,21 +36,19 @@ struct TopVersion }; auto const VersionFieldHelper = - cmJSONIntHelper<cmCTestResourceSpec::ReadFileResult>( - cmCTestResourceSpec::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_VERSION); + JSONHelperBuilder::Int(cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_VERSION); -auto const VersionHelper = - cmJSONRequiredHelper<Version, cmCTestResourceSpec::ReadFileResult>( - cmCTestResourceSpec::ReadFileResult::NO_VERSION, - cmJSONObjectHelper<Version, cmCTestResourceSpec::ReadFileResult>( - cmCTestResourceSpec::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_VERSION) - .Bind("major"_s, &Version::Major, VersionFieldHelper) - .Bind("minor"_s, &Version::Minor, VersionFieldHelper)); +auto const VersionHelper = JSONHelperBuilder::Required<Version>( + cmCTestResourceSpec::ReadFileResult::NO_VERSION, + JSONHelperBuilder::Object<Version>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_VERSION) + .Bind("major"_s, &Version::Major, VersionFieldHelper) + .Bind("minor"_s, &Version::Minor, VersionFieldHelper)); auto const RootVersionHelper = - cmJSONObjectHelper<TopVersion, cmCTestResourceSpec::ReadFileResult>( + JSONHelperBuilder::Object<TopVersion>( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_ROOT) .Bind("version"_s, &TopVersion::Version, VersionHelper, false); @@ -56,7 +56,7 @@ auto const RootVersionHelper = cmCTestResourceSpec::ReadFileResult ResourceIdHelper(std::string& out, const Json::Value* value) { - auto result = cmJSONStringHelper( + auto result = JSONHelperBuilder::String( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE)(out, value); if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) { @@ -70,27 +70,24 @@ cmCTestResourceSpec::ReadFileResult ResourceIdHelper(std::string& out, } auto const ResourceHelper = - cmJSONObjectHelper<cmCTestResourceSpec::Resource, - cmCTestResourceSpec::ReadFileResult>( + JSONHelperBuilder::Object<cmCTestResourceSpec::Resource>( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE) .Bind("id"_s, &cmCTestResourceSpec::Resource::Id, ResourceIdHelper) .Bind("slots"_s, &cmCTestResourceSpec::Resource::Capacity, - cmJSONUIntHelper( + JSONHelperBuilder::UInt( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, 1), false); auto const ResourceListHelper = - cmJSONVectorHelper<cmCTestResourceSpec::Resource, - cmCTestResourceSpec::ReadFileResult>( + JSONHelperBuilder::Vector<cmCTestResourceSpec::Resource>( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE_TYPE, ResourceHelper); auto const ResourceMapHelper = - cmJSONMapFilterHelper<std::vector<cmCTestResourceSpec::Resource>, - cmCTestResourceSpec::ReadFileResult>( + JSONHelperBuilder::MapFilter<std::vector<cmCTestResourceSpec::Resource>>( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, ResourceListHelper, [](const std::string& key) -> bool { @@ -98,7 +95,7 @@ auto const ResourceMapHelper = return IdentifierRegex.find(key.c_str(), match); }); -auto const SocketSetHelper = cmJSONVectorHelper< +auto const SocketSetHelper = JSONHelperBuilder::Vector< std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>( cmCTestResourceSpec::ReadFileResult::READ_OK, cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, ResourceMapHelper); @@ -125,16 +122,14 @@ cmCTestResourceSpec::ReadFileResult SocketHelper( } auto const LocalRequiredHelper = - cmJSONRequiredHelper<cmCTestResourceSpec::Socket, - cmCTestResourceSpec::ReadFileResult>( + JSONHelperBuilder::Required<cmCTestResourceSpec::Socket>( cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, SocketHelper); -auto const RootHelper = - cmJSONObjectHelper<cmCTestResourceSpec, cmCTestResourceSpec::ReadFileResult>( - cmCTestResourceSpec::ReadFileResult::READ_OK, - cmCTestResourceSpec::ReadFileResult::INVALID_ROOT) - .Bind("local", &cmCTestResourceSpec::LocalSocket, LocalRequiredHelper, - false); +auto const RootHelper = JSONHelperBuilder::Object<cmCTestResourceSpec>( + cmCTestResourceSpec::ReadFileResult::READ_OK, + cmCTestResourceSpec::ReadFileResult::INVALID_ROOT) + .Bind("local", &cmCTestResourceSpec::LocalSocket, + LocalRequiredHelper, false); } cmCTestResourceSpec::ReadFileResult cmCTestResourceSpec::ReadFromJSONFile( diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 6cd3b09..2a2cb1c 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -277,7 +277,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) static_cast<size_t>( this->TestResult.Status == cmCTestTestHandler::COMPLETED ? this->TestHandler->CustomMaximumPassedTestOutputSize - : this->TestHandler->CustomMaximumFailedTestOutputSize)); + : this->TestHandler->CustomMaximumFailedTestOutputSize), + this->TestHandler->TestOutputTruncation); } this->TestResult.Reason = reason; if (this->TestHandler->LogFile) { @@ -694,6 +695,14 @@ void cmCTestRunTest::ComputeArguments() << " command: " << testCommand << std::endl); // Print any test-specific env vars in verbose mode + if (!this->TestProperties->Directory.empty()) { + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->Index << ": " + << "Working Directory: " + << this->TestProperties->Directory << std::endl); + } + + // Print any test-specific env vars in verbose mode if (!this->TestProperties->Environment.empty()) { cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index << ": " diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 5a3a8d0..696a5ea 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -281,6 +281,7 @@ cmCTestTestHandler::cmCTestTestHandler() this->CustomMaximumPassedTestOutputSize = 1 * 1024; this->CustomMaximumFailedTestOutputSize = 300 * 1024; + this->TestOutputTruncation = cmCTestTypes::TruncationMode::Tail; this->MemCheck = false; @@ -325,6 +326,7 @@ void cmCTestTestHandler::Initialize() this->CustomPostTest.clear(); this->CustomMaximumPassedTestOutputSize = 1 * 1024; this->CustomMaximumFailedTestOutputSize = 300 * 1024; + this->TestOutputTruncation = cmCTestTypes::TruncationMode::Tail; this->TestsToRun.clear(); @@ -358,6 +360,11 @@ void cmCTestTestHandler::PopulateCustomVectors(cmMakefile* mf) this->CTest->PopulateCustomInteger( mf, "CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE", this->CustomMaximumFailedTestOutputSize); + + cmValue dval = mf->GetDefinition("CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION"); + if (dval) { + this->SetTestOutputTruncation(dval); + } } int cmCTestTestHandler::PreProcessHandler() @@ -2076,6 +2083,20 @@ void cmCTestTestHandler::SetExcludeRegExp(const std::string& arg) this->ExcludeRegExp = arg; } +bool cmCTestTestHandler::SetTestOutputTruncation(const std::string& mode) +{ + if (mode == "tail") { + this->TestOutputTruncation = cmCTestTypes::TruncationMode::Tail; + } else if (mode == "middle") { + this->TestOutputTruncation = cmCTestTypes::TruncationMode::Middle; + } else if (mode == "head") { + this->TestOutputTruncation = cmCTestTypes::TruncationMode::Head; + } else { + return false; + } + return true; +} + void cmCTestTestHandler::SetTestsToRunInformation(cmValue in) { if (!in) { @@ -2094,41 +2115,58 @@ void cmCTestTestHandler::SetTestsToRunInformation(cmValue in) } } -void cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length) +void cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length, + cmCTestTypes::TruncationMode truncate) { if (!length || length >= output.size() || output.find("CTEST_FULL_OUTPUT") != std::string::npos) { return; } - // Truncate at given length but do not break in the middle of a multi-byte - // UTF-8 encoding. - char const* const begin = output.c_str(); - char const* const end = begin + output.size(); - char const* const truncate = begin + length; - char const* current = begin; - while (current < truncate) { - unsigned int ch; - if (const char* next = cm_utf8_decode_character(current, end, &ch)) { - if (next > truncate) { - break; + // Advance n bytes in string delimited by begin/end but do not break in the + // middle of a multi-byte UTF-8 encoding. + auto utf8_advance = [](char const* const begin, char const* const end, + size_t n) -> const char* { + char const* const stop = begin + n; + char const* current = begin; + while (current < stop) { + unsigned int ch; + if (const char* next = cm_utf8_decode_character(current, end, &ch)) { + if (next > stop) { + break; + } + current = next; + } else // Bad byte will be handled by cmXMLWriter. + { + ++current; } - current = next; - } else // Bad byte will be handled by cmXMLWriter. - { - ++current; } - } - output.erase(current - begin); + return current; + }; - // Append truncation message. - std::ostringstream msg; - msg << "...\n" - "The rest of the test output was removed since it exceeds the " - "threshold " - "of " - << length << " bytes.\n"; - output += msg.str(); + // Truncation message. + const std::string msg = + "\n[This part of the test output was removed since it " + "exceeds the threshold of " + + std::to_string(length) + " bytes.]\n"; + + char const* const begin = output.c_str(); + char const* const end = begin + output.size(); + + // Erase head, middle or tail of output. + if (truncate == cmCTestTypes::TruncationMode::Head) { + char const* current = utf8_advance(begin, end, output.size() - length); + output.erase(0, current - begin); + output.insert(0, msg + "..."); + } else if (truncate == cmCTestTypes::TruncationMode::Middle) { + char const* current = utf8_advance(begin, end, length / 2); + output.erase(current - begin, output.size() - length); + output.insert(current - begin, "..." + msg + "..."); + } else { // default or "tail" + char const* current = utf8_advance(begin, end, length); + output.erase(current - begin); + output += ("..." + msg); + } } bool cmCTestTestHandler::SetTestsProperties( @@ -2448,22 +2486,19 @@ bool cmCTestTestHandler::WriteJUnitXML() // Iterate over the test results to get the number of tests that // passed, failed, etc. auto num_tests = 0; - auto num_passed = 0; auto num_failed = 0; auto num_notrun = 0; auto num_disabled = 0; SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end()); for (cmCTestTestResult const& result : resultsSet) { num_tests++; - if (result.Status == cmCTestTestHandler::COMPLETED) { - num_passed++; - } else if (result.Status == cmCTestTestHandler::NOT_RUN) { + if (result.Status == cmCTestTestHandler::NOT_RUN) { if (result.CompletionStatus == "Disabled") { num_disabled++; } else { num_notrun++; } - } else { + } else if (result.Status != cmCTestTestHandler::COMPLETED) { num_failed++; } } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 135e764..d0049da 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -19,6 +19,7 @@ #include "cmCTest.h" #include "cmCTestGenericHandler.h" #include "cmCTestResourceSpec.h" +#include "cmCTestTypes.h" #include "cmDuration.h" #include "cmListFileCache.h" #include "cmValue.h" @@ -32,6 +33,7 @@ class cmXMLWriter; */ class cmCTestTestHandler : public cmCTestGenericHandler { + friend class cmCTest; friend class cmCTestRunTest; friend class cmCTestMultiProcessHandler; @@ -80,6 +82,9 @@ public: this->CustomMaximumFailedTestOutputSize = n; } + //! Set test output truncation mode. Return false if unknown mode. + bool SetTestOutputTruncation(const std::string& mode); + //! pass the -I argument down void SetTestsToRunInformation(cmValue); @@ -242,8 +247,9 @@ protected: void AttachFile(cmXMLWriter& xml, std::string const& file, std::string const& name); - //! Clean test output to specified length - void CleanTestOutput(std::string& output, size_t length); + //! Clean test output to specified length and truncation mode + void CleanTestOutput(std::string& output, size_t length, + cmCTestTypes::TruncationMode truncate); cmDuration ElapsedTestingTime; @@ -258,6 +264,7 @@ protected: bool MemCheck; int CustomMaximumPassedTestOutputSize; int CustomMaximumFailedTestOutputSize; + cmCTestTypes::TruncationMode TestOutputTruncation; int MaxIndex; public: diff --git a/Source/CTest/cmCTestTypes.h b/Source/CTest/cmCTestTypes.h new file mode 100644 index 0000000..843d27a --- /dev/null +++ b/Source/CTest/cmCTestTypes.h @@ -0,0 +1,16 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +namespace cmCTestTypes { + +enum class TruncationMode +{ // Test output truncation mode + Tail, + Middle, + Head +}; +} diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index 9b3a649..8a7bb86 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -191,9 +191,9 @@ void cmCursesLongMessageForm::HandleInput() if (key == 'o' || key == 'e') { break; } - if (key == KEY_DOWN || key == ctrl('n')) { + if (key == KEY_DOWN || key == ctrl('n') || key == 'j') { form_driver(this->Form, REQ_SCR_FLINE); - } else if (key == KEY_UP || key == ctrl('p')) { + } else if (key == KEY_UP || key == ctrl('p') || key == 'k') { form_driver(this->Form, REQ_SCR_BLINE); } else if (key == KEY_NPAGE || key == ctrl('d')) { form_driver(this->Form, REQ_SCR_FPAGE); diff --git a/Source/CursesDialog/form/frm_driver.c b/Source/CursesDialog/form/frm_driver.c index 112ab08..9cbb12f 100644 --- a/Source/CursesDialog/form/frm_driver.c +++ b/Source/CursesDialog/form/frm_driver.c @@ -1456,7 +1456,7 @@ static int IFN_Beginning_Of_Field(FORM * form) | | Description : Place the cursor after the last non-pad character in | the field. If the field occupies the last position in -| the buffer, the cursos is positioned on the last +| the buffer, the cursor is positioned on the last | character. | | Return Values : E_OK - success diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx index 5727992..4c49e0f 100644 --- a/Source/LexerParser/cmCommandArgumentParser.cxx +++ b/Source/LexerParser/cmCommandArgumentParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.7.5. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison implementation for Yacc-like parsers in C @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30705 +#define YYBISON 30802 /* Bison version string. */ -#define YYBISON_VERSION "3.7.5" +#define YYBISON_VERSION "3.8.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -131,8 +131,13 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wfree-nonheap-object" #endif +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wunused-but-set-variable") +# pragma clang diagnostic ignored "-Wunused-but-set-variable" +# endif +#endif -#line 136 "cmCommandArgumentParser.cxx" +#line 141 "cmCommandArgumentParser.cxx" # ifndef YY_CAST # ifdef __cplusplus @@ -342,12 +347,18 @@ typedef int yy_state_fast_t; # define YY_USE(E) /* empty */ #endif -#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else @@ -562,12 +573,12 @@ static const yytype_int8 yytranslate[] = }; #if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 97, 97, 103, 106, 111, 114, 119, 122, 127, - 130, 133, 136, 139, 142, 147, 150, 153, 156, 161, - 164, 169, 172, 177, 180 + 0, 102, 102, 108, 111, 116, 119, 124, 127, 132, + 135, 138, 141, 144, 147, 152, 155, 158, 161, 166, + 169, 174, 177, 182, 185 }; #endif @@ -597,16 +608,6 @@ yysymbol_name (yysymbol_kind_t yysymbol) } #endif -#ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_int16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269 -}; -#endif - #define YYPACT_NINF (-3) #define yypact_value_is_default(Yyn) \ @@ -617,8 +618,8 @@ static const yytype_int16 yytoknum[] = #define yytable_value_is_error(Yyn) \ 0 - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ static const yytype_int8 yypact[] = { 0, 14, 26, 26, -3, -3, -3, -3, -3, -3, @@ -627,9 +628,9 @@ static const yytype_int8 yypact[] = -3, -3, -3 }; - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ static const yytype_int8 yydefact[] = { 5, 21, 21, 21, 11, 12, 13, 9, 14, 10, @@ -638,21 +639,21 @@ static const yytype_int8 yydefact[] = 22, 16, 17 }; - /* YYPGOTO[NTERM-NUM]. */ +/* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -3, -3, -3, 8, -3, -3, 2, 9, -2, -3 }; - /* YYDEFGOTO[NTERM-NUM]. */ +/* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { 0, 11, 12, 13, 14, 15, 19, 20, 21, 22 }; - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int8 yytable[] = { 23, 24, 16, 1, 2, 3, 4, 5, 6, 7, @@ -671,8 +672,8 @@ static const yytype_int8 yycheck[] = 14 }; - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ static const yytype_int8 yystos[] = { 0, 3, 4, 5, 6, 7, 8, 9, 11, 12, @@ -681,7 +682,7 @@ static const yytype_int8 yystos[] = 23, 8, 8 }; - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int8 yyr1[] = { 0, 15, 16, 17, 17, 18, 18, 19, 19, 20, @@ -689,7 +690,7 @@ static const yytype_int8 yyr1[] = 22, 23, 23, 24, 24 }; - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ static const yytype_int8 yyr2[] = { 0, 2, 1, 1, 2, 0, 2, 1, 1, 1, @@ -706,6 +707,7 @@ enum { YYENOMEM = -2 }; #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab #define YYRECOVERING() (!!yyerrstatus) @@ -746,10 +748,7 @@ do { \ YYFPRINTF Args; \ } while (0) -/* This macro is provided for backward compatibility. */ -# ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif + # define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ @@ -777,10 +776,6 @@ yy_symbol_value_print (FILE *yyo, YY_USE (yyscanner); if (!yyvaluep) return; -# ifdef YYPRINT - if (yykind < YYNTOKENS) - YYPRINT (yyo, yytoknum[yykind], *yyvaluep); -# endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END @@ -1242,6 +1237,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); YYDPRINTF ((stderr, "Starting parse\n")); yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; @@ -1267,7 +1263,7 @@ yysetstate: if (yyss + yystacksize - 1 <= yyssp) #if !defined yyoverflow && !defined YYSTACK_RELOCATE - goto yyexhaustedlab; + YYNOMEM; #else { /* Get the current used size of the three stacks, in elements. */ @@ -1295,7 +1291,7 @@ yysetstate: # else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; + YYNOMEM; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; @@ -1306,7 +1302,7 @@ yysetstate: YY_CAST (union yyalloc *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); if (! yyptr) - goto yyexhaustedlab; + YYNOMEM; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE @@ -1328,6 +1324,7 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + if (yystate == YYFINAL) YYACCEPT; @@ -1440,192 +1437,192 @@ yyreduce: switch (yyn) { case 2: /* Start: GoalWithOptionalBackSlash */ -#line 97 "cmCommandArgumentParser.y" +#line 102 "cmCommandArgumentParser.y" { (yyval.str) = 0; yyGetParser->SetResult((yyvsp[0].str)); } -#line 1449 "cmCommandArgumentParser.cxx" +#line 1446 "cmCommandArgumentParser.cxx" break; case 3: /* GoalWithOptionalBackSlash: Goal */ -#line 103 "cmCommandArgumentParser.y" +#line 108 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1457 "cmCommandArgumentParser.cxx" +#line 1454 "cmCommandArgumentParser.cxx" break; case 4: /* GoalWithOptionalBackSlash: Goal "\\" */ -#line 106 "cmCommandArgumentParser.y" +#line 111 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1465 "cmCommandArgumentParser.cxx" +#line 1462 "cmCommandArgumentParser.cxx" break; case 5: /* Goal: %empty */ -#line 111 "cmCommandArgumentParser.y" +#line 116 "cmCommandArgumentParser.y" { (yyval.str) = 0; } -#line 1473 "cmCommandArgumentParser.cxx" +#line 1470 "cmCommandArgumentParser.cxx" break; case 6: /* Goal: String Goal */ -#line 114 "cmCommandArgumentParser.y" +#line 119 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1481 "cmCommandArgumentParser.cxx" +#line 1478 "cmCommandArgumentParser.cxx" break; case 7: /* String: OuterText */ -#line 119 "cmCommandArgumentParser.y" +#line 124 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1489 "cmCommandArgumentParser.cxx" +#line 1486 "cmCommandArgumentParser.cxx" break; case 8: /* String: Variable */ -#line 122 "cmCommandArgumentParser.y" +#line 127 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1497 "cmCommandArgumentParser.cxx" +#line 1494 "cmCommandArgumentParser.cxx" break; case 9: /* OuterText: cal_NAME */ -#line 127 "cmCommandArgumentParser.y" +#line 132 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1505 "cmCommandArgumentParser.cxx" +#line 1502 "cmCommandArgumentParser.cxx" break; case 10: /* OuterText: "@" */ -#line 130 "cmCommandArgumentParser.y" +#line 135 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1513 "cmCommandArgumentParser.cxx" +#line 1510 "cmCommandArgumentParser.cxx" break; case 11: /* OuterText: "$" */ -#line 133 "cmCommandArgumentParser.y" +#line 138 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1521 "cmCommandArgumentParser.cxx" +#line 1518 "cmCommandArgumentParser.cxx" break; case 12: /* OuterText: "{" */ -#line 136 "cmCommandArgumentParser.y" +#line 141 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1529 "cmCommandArgumentParser.cxx" +#line 1526 "cmCommandArgumentParser.cxx" break; case 13: /* OuterText: "}" */ -#line 139 "cmCommandArgumentParser.y" +#line 144 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1537 "cmCommandArgumentParser.cxx" +#line 1534 "cmCommandArgumentParser.cxx" break; case 14: /* OuterText: cal_SYMBOL */ -#line 142 "cmCommandArgumentParser.y" +#line 147 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1545 "cmCommandArgumentParser.cxx" +#line 1542 "cmCommandArgumentParser.cxx" break; case 15: /* Variable: cal_ENVCURLY EnvVarName "}" */ -#line 147 "cmCommandArgumentParser.y" +#line 152 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1553 "cmCommandArgumentParser.cxx" +#line 1550 "cmCommandArgumentParser.cxx" break; case 16: /* Variable: cal_NCURLY MultipleIds "}" */ -#line 150 "cmCommandArgumentParser.y" +#line 155 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1561 "cmCommandArgumentParser.cxx" +#line 1558 "cmCommandArgumentParser.cxx" break; case 17: /* Variable: cal_DCURLY MultipleIds "}" */ -#line 153 "cmCommandArgumentParser.y" +#line 158 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); } -#line 1569 "cmCommandArgumentParser.cxx" +#line 1566 "cmCommandArgumentParser.cxx" break; case 18: /* Variable: cal_ATNAME */ -#line 156 "cmCommandArgumentParser.y" +#line 161 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); } -#line 1577 "cmCommandArgumentParser.cxx" +#line 1574 "cmCommandArgumentParser.cxx" break; case 19: /* EnvVarName: MultipleIds */ -#line 161 "cmCommandArgumentParser.y" +#line 166 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1585 "cmCommandArgumentParser.cxx" +#line 1582 "cmCommandArgumentParser.cxx" break; case 20: /* EnvVarName: cal_SYMBOL EnvVarName */ -#line 164 "cmCommandArgumentParser.y" +#line 169 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[-1].str); } -#line 1593 "cmCommandArgumentParser.cxx" +#line 1590 "cmCommandArgumentParser.cxx" break; case 21: /* MultipleIds: %empty */ -#line 169 "cmCommandArgumentParser.y" +#line 174 "cmCommandArgumentParser.y" { (yyval.str) = 0; } -#line 1601 "cmCommandArgumentParser.cxx" +#line 1598 "cmCommandArgumentParser.cxx" break; case 22: /* MultipleIds: ID MultipleIds */ -#line 172 "cmCommandArgumentParser.y" +#line 177 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1609 "cmCommandArgumentParser.cxx" +#line 1606 "cmCommandArgumentParser.cxx" break; case 23: /* ID: cal_NAME */ -#line 177 "cmCommandArgumentParser.y" +#line 182 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1617 "cmCommandArgumentParser.cxx" +#line 1614 "cmCommandArgumentParser.cxx" break; case 24: /* ID: Variable */ -#line 180 "cmCommandArgumentParser.y" +#line 185 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1625 "cmCommandArgumentParser.cxx" +#line 1622 "cmCommandArgumentParser.cxx" break; -#line 1629 "cmCommandArgumentParser.cxx" +#line 1626 "cmCommandArgumentParser.cxx" default: break; } @@ -1701,7 +1698,7 @@ yyerrlab: } yyerror (yyscanner, yymsgp); if (yysyntax_error_status == YYENOMEM) - goto yyexhaustedlab; + YYNOMEM; } } @@ -1737,6 +1734,7 @@ yyerrorlab: label yyerrorlab therefore never appears in user code. */ if (0) YYERROR; + ++yynerrs; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ @@ -1797,7 +1795,7 @@ yyerrlab1: `-------------------------------------*/ yyacceptlab: yyresult = 0; - goto yyreturn; + goto yyreturnlab; /*-----------------------------------. @@ -1805,24 +1803,22 @@ yyacceptlab: `-----------------------------------*/ yyabortlab: yyresult = 1; - goto yyreturn; + goto yyreturnlab; -#if 1 -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ yyexhaustedlab: yyerror (yyscanner, YY_("memory exhausted")); yyresult = 2; - goto yyreturn; -#endif + goto yyreturnlab; -/*-------------------------------------------------------. -| yyreturn -- parsing is finished, clean up and return. | -`-------------------------------------------------------*/ -yyreturn: +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: if (yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at @@ -1850,7 +1846,7 @@ yyreturn: return yyresult; } -#line 185 "cmCommandArgumentParser.y" +#line 190 "cmCommandArgumentParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmCommandArgumentParser.y b/Source/LexerParser/cmCommandArgumentParser.y index 2689415..602e1c3 100644 --- a/Source/LexerParser/cmCommandArgumentParser.y +++ b/Source/LexerParser/cmCommandArgumentParser.y @@ -56,6 +56,11 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wfree-nonheap-object" #endif +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wunused-but-set-variable") +# pragma clang diagnostic ignored "-Wunused-but-set-variable" +# endif +#endif %} /* Generate a reentrant parser object. */ diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h index 414c6dd..6365d5b 100644 --- a/Source/LexerParser/cmCommandArgumentParserTokens.h +++ b/Source/LexerParser/cmCommandArgumentParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.7.5. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison interface for Yacc-like parsers in C @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -74,6 +74,8 @@ extern int cmCommandArgument_yydebug; + int cmCommandArgument_yyparse (yyscan_t yyscanner); + #endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED */ diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx index e6b3a7e..59cf1be 100644 --- a/Source/LexerParser/cmDependsJavaParser.cxx +++ b/Source/LexerParser/cmDependsJavaParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.7.5. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison implementation for Yacc-like parsers in C @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30705 +#define YYBISON 30802 /* Bison version string. */ -#define YYBISON_VERSION "3.7.5" +#define YYBISON_VERSION "3.8.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -120,8 +120,13 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wfree-nonheap-object" #endif +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wunused-but-set-variable") +# pragma clang diagnostic ignored "-Wunused-but-set-variable" +# endif +#endif -#line 125 "cmDependsJavaParser.cxx" +#line 130 "cmDependsJavaParser.cxx" # ifndef YY_CAST # ifdef __cplusplus @@ -570,12 +575,18 @@ typedef int yy_state_fast_t; # define YY_USE(E) /* empty */ #endif -#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else @@ -800,45 +811,45 @@ static const yytype_int8 yytranslate[] = }; #if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = { - 0, 180, 180, 189, 197, 205, 213, 221, 229, 238, - 246, 255, 263, 272, 277, 282, 287, 292, 297, 302, - 307, 313, 321, 330, 340, 349, 358, 366, 376, 382, - 389, 396, 402, 409, 418, 428, 438, 447, 455, 464, - 473, 479, 488, 494, 503, 509, 518, 530, 538, 547, - 559, 572, 580, 588, 597, 605, 614, 614, 614, 615, - 616, 616, 616, 616, 616, 616, 617, 620, 630, 639, - 648, 657, 667, 673, 682, 691, 700, 708, 717, 726, - 732, 741, 749, 757, 765, 774, 782, 791, 797, 805, - 814, 822, 831, 840, 849, 857, 866, 874, 882, 891, - 900, 910, 917, 927, 937, 944, 951, 954, 960, 970, - 980, 990, 996, 1006, 1016, 1026, 1035, 1045, 1056, 1066, - 1073, 1083, 1092, 1102, 1111, 1121, 1127, 1137, 1146, 1156, - 1166, 1173, 1182, 1191, 1200, 1209, 1217, 1226, 1235, 1245, - 1255, 1264, 1274, 1284, 1291, 1300, 1310, 1319, 1329, 1338, - 1345, 1355, 1364, 1374, 1383, 1392, 1402, 1412, 1421, 1431, - 1440, 1449, 1458, 1467, 1476, 1486, 1495, 1504, 1513, 1522, - 1532, 1541, 1550, 1559, 1568, 1577, 1586, 1595, 1604, 1613, - 1622, 1631, 1641, 1651, 1662, 1672, 1682, 1691, 1700, 1709, - 1718, 1727, 1736, 1746, 1756, 1766, 1776, 1783, 1790, 1797, - 1807, 1814, 1824, 1834, 1843, 1853, 1862, 1872, 1879, 1886, - 1893, 1901, 1908, 1918, 1925, 1935, 1945, 1952, 1962, 1971, - 1981, 1991, 2000, 2010, 2019, 2029, 2040, 2047, 2054, 2065, - 2075, 2085, 2095, 2104, 2114, 2121, 2131, 2140, 2150, 2157, - 2167, 2176, 2186, 2195, 2201, 2210, 2219, 2228, 2237, 2247, - 2257, 2264, 2274, 2281, 2291, 2300, 2310, 2319, 2328, 2337, - 2347, 2354, 2364, 2373, 2383, 2393, 2399, 2406, 2416, 2426, - 2436, 2447, 2457, 2468, 2478, 2489, 2499, 2509, 2518, 2527, - 2536, 2545, 2555, 2565, 2575, 2584, 2593, 2602, 2611, 2621, - 2631, 2641, 2650, 2659, 2668, 2678, 2687, 2696, 2703, 2712, - 2721, 2730, 2740, 2749, 2758, 2768, 2777, 2786, 2795, 2805, - 2814, 2823, 2832, 2841, 2850, 2860, 2869, 2878, 2888, 2897, - 2907, 2916, 2926, 2935, 2945, 2954, 2964, 2973, 2983, 2992, - 3002, 3011, 3021, 3031, 3041, 3050, 3060, 3069, 3078, 3087, - 3096, 3105, 3114, 3123, 3132, 3141, 3150, 3159, 3169, 3179, - 3189, 3198 + 0, 185, 185, 194, 202, 210, 218, 226, 234, 243, + 251, 260, 268, 277, 282, 287, 292, 297, 302, 307, + 312, 318, 326, 335, 345, 354, 363, 371, 381, 387, + 394, 401, 407, 414, 423, 433, 443, 452, 460, 469, + 478, 484, 493, 499, 508, 514, 523, 535, 543, 552, + 564, 577, 585, 593, 602, 610, 619, 619, 619, 620, + 621, 621, 621, 621, 621, 621, 622, 625, 635, 644, + 653, 662, 672, 678, 687, 696, 705, 713, 722, 731, + 737, 746, 754, 762, 770, 779, 787, 796, 802, 810, + 819, 827, 836, 845, 854, 862, 871, 879, 887, 896, + 905, 915, 922, 932, 942, 949, 956, 959, 965, 975, + 985, 995, 1001, 1011, 1021, 1031, 1040, 1050, 1061, 1071, + 1078, 1088, 1097, 1107, 1116, 1126, 1132, 1142, 1151, 1161, + 1171, 1178, 1187, 1196, 1205, 1214, 1222, 1231, 1240, 1250, + 1260, 1269, 1279, 1289, 1296, 1305, 1315, 1324, 1334, 1343, + 1350, 1360, 1369, 1379, 1388, 1397, 1407, 1417, 1426, 1436, + 1445, 1454, 1463, 1472, 1481, 1491, 1500, 1509, 1518, 1527, + 1537, 1546, 1555, 1564, 1573, 1582, 1591, 1600, 1609, 1618, + 1627, 1636, 1646, 1656, 1667, 1677, 1687, 1696, 1705, 1714, + 1723, 1732, 1741, 1751, 1761, 1771, 1781, 1788, 1795, 1802, + 1812, 1819, 1829, 1839, 1848, 1858, 1867, 1877, 1884, 1891, + 1898, 1906, 1913, 1923, 1930, 1940, 1950, 1957, 1967, 1976, + 1986, 1996, 2005, 2015, 2024, 2034, 2045, 2052, 2059, 2070, + 2080, 2090, 2100, 2109, 2119, 2126, 2136, 2145, 2155, 2162, + 2172, 2181, 2191, 2200, 2206, 2215, 2224, 2233, 2242, 2252, + 2262, 2269, 2279, 2286, 2296, 2305, 2315, 2324, 2333, 2342, + 2352, 2359, 2369, 2378, 2388, 2398, 2404, 2411, 2421, 2431, + 2441, 2452, 2462, 2473, 2483, 2494, 2504, 2514, 2523, 2532, + 2541, 2550, 2560, 2570, 2580, 2589, 2598, 2607, 2616, 2626, + 2636, 2646, 2655, 2664, 2673, 2683, 2692, 2701, 2708, 2717, + 2726, 2735, 2745, 2754, 2763, 2773, 2782, 2791, 2800, 2810, + 2819, 2828, 2837, 2846, 2855, 2865, 2874, 2883, 2893, 2902, + 2912, 2921, 2931, 2940, 2950, 2959, 2969, 2978, 2988, 2997, + 3007, 3016, 3026, 3036, 3046, 3055, 3065, 3074, 3083, 3092, + 3101, 3110, 3119, 3128, 3137, 3146, 3155, 3164, 3174, 3184, + 3194, 3203 }; #endif @@ -938,25 +949,6 @@ yysymbol_name (yysymbol_kind_t yysymbol) } #endif -#ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_int16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360 -}; -#endif - #define YYPACT_NINF (-503) #define yypact_value_is_default(Yyn) \ @@ -967,8 +959,8 @@ static const yytype_int16 yytoknum[] = #define yytable_value_is_error(Yyn) \ 0 - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ static const yytype_int16 yypact[] = { 159, 1039, 236, -503, -503, -503, -503, -503, -503, -503, @@ -1031,9 +1023,9 @@ static const yytype_int16 yypact[] = 1699, 432, -503, 1699, -503 }; - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ static const yytype_int16 yydefact[] = { 40, 0, 0, 2, 42, 41, 20, 13, 17, 19, @@ -1096,7 +1088,7 @@ static const yytype_int16 yydefact[] = 0, 0, 195, 0, 215 }; - /* YYPGOTO[NTERM-NUM]. */ +/* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { -503, -503, -503, -503, -85, 2, 181, -41, -198, -45, @@ -1117,7 +1109,7 @@ static const yytype_int16 yypgoto[] = 95, 274, 350, -503, -503, 660, -503, -503 }; - /* YYDEFGOTO[NTERM-NUM]. */ +/* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { 0, 2, 156, 157, 158, 229, 112, 113, 75, 78, @@ -1138,9 +1130,9 @@ static const yytype_int16 yydefgoto[] = 252, 253, 254, 203, 306, 386, 557, 204 }; - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { 18, 82, 83, 17, 287, 61, 309, 56, 114, 364, @@ -1593,8 +1585,8 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, 104 }; - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ static const yytype_int16 yystos[] = { 0, 31, 107, 122, 123, 126, 5, 7, 10, 15, @@ -1657,7 +1649,7 @@ static const yytype_int16 yystos[] = 16, 205, 184, 90, 184 }; - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int16 yyr1[] = { 0, 106, 107, 108, 108, 108, 108, 108, 108, 109, @@ -1698,7 +1690,7 @@ static const yytype_int16 yyr1[] = 263, 263 }; - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ static const yytype_int8 yyr2[] = { 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1748,6 +1740,7 @@ enum { YYENOMEM = -2 }; #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab #define YYRECOVERING() (!!yyerrstatus) @@ -1788,10 +1781,7 @@ do { \ YYFPRINTF Args; \ } while (0) -/* This macro is provided for backward compatibility. */ -# ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif + # define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ @@ -1819,10 +1809,6 @@ yy_symbol_value_print (FILE *yyo, YY_USE (yyscanner); if (!yyvaluep) return; -# ifdef YYPRINT - if (yykind < YYNTOKENS) - YYPRINT (yyo, yytoknum[yykind], *yyvaluep); -# endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END @@ -2284,6 +2270,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); YYDPRINTF ((stderr, "Starting parse\n")); yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; @@ -2309,7 +2296,7 @@ yysetstate: if (yyss + yystacksize - 1 <= yyssp) #if !defined yyoverflow && !defined YYSTACK_RELOCATE - goto yyexhaustedlab; + YYNOMEM; #else { /* Get the current used size of the three stacks, in elements. */ @@ -2337,7 +2324,7 @@ yysetstate: # else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; + YYNOMEM; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; @@ -2348,7 +2335,7 @@ yysetstate: YY_CAST (union yyalloc *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); if (! yyptr) - goto yyexhaustedlab; + YYNOMEM; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE @@ -2370,6 +2357,7 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + if (yystate == YYFINAL) YYACCEPT; @@ -2482,214 +2470,214 @@ yyreduce: switch (yyn) { case 2: /* Goal: CompilationUnit */ -#line 181 "cmDependsJavaParser.y" +#line 186 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2493 "cmDependsJavaParser.cxx" +#line 2481 "cmDependsJavaParser.cxx" break; case 3: /* Literal: IntegerLiteral */ -#line 190 "cmDependsJavaParser.y" +#line 195 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2504 "cmDependsJavaParser.cxx" +#line 2492 "cmDependsJavaParser.cxx" break; case 4: /* Literal: jp_FLOATINGPOINTLITERAL */ -#line 198 "cmDependsJavaParser.y" +#line 203 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2515 "cmDependsJavaParser.cxx" +#line 2503 "cmDependsJavaParser.cxx" break; case 5: /* Literal: jp_BOOLEANLITERAL */ -#line 206 "cmDependsJavaParser.y" +#line 211 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2526 "cmDependsJavaParser.cxx" +#line 2514 "cmDependsJavaParser.cxx" break; case 6: /* Literal: jp_CHARACTERLITERAL */ -#line 214 "cmDependsJavaParser.y" +#line 219 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2537 "cmDependsJavaParser.cxx" +#line 2525 "cmDependsJavaParser.cxx" break; case 7: /* Literal: jp_STRINGLITERAL */ -#line 222 "cmDependsJavaParser.y" +#line 227 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2548 "cmDependsJavaParser.cxx" +#line 2536 "cmDependsJavaParser.cxx" break; case 8: /* Literal: jp_NULLLITERAL */ -#line 230 "cmDependsJavaParser.y" +#line 235 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2559 "cmDependsJavaParser.cxx" +#line 2547 "cmDependsJavaParser.cxx" break; case 9: /* IntegerLiteral: jp_DECIMALINTEGERLITERAL */ -#line 239 "cmDependsJavaParser.y" +#line 244 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2570 "cmDependsJavaParser.cxx" +#line 2558 "cmDependsJavaParser.cxx" break; case 10: /* IntegerLiteral: jp_HEXINTEGERLITERAL */ -#line 247 "cmDependsJavaParser.y" +#line 252 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2581 "cmDependsJavaParser.cxx" +#line 2569 "cmDependsJavaParser.cxx" break; case 11: /* Type: PrimitiveType */ -#line 256 "cmDependsJavaParser.y" +#line 261 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2592 "cmDependsJavaParser.cxx" +#line 2580 "cmDependsJavaParser.cxx" break; case 12: /* Type: ReferenceType */ -#line 264 "cmDependsJavaParser.y" +#line 269 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2603 "cmDependsJavaParser.cxx" +#line 2591 "cmDependsJavaParser.cxx" break; case 13: /* PrimitiveType: jp_BYTE_TYPE */ -#line 273 "cmDependsJavaParser.y" +#line 278 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2611 "cmDependsJavaParser.cxx" +#line 2599 "cmDependsJavaParser.cxx" break; case 14: /* PrimitiveType: jp_SHORT_TYPE */ -#line 278 "cmDependsJavaParser.y" +#line 283 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2619 "cmDependsJavaParser.cxx" +#line 2607 "cmDependsJavaParser.cxx" break; case 15: /* PrimitiveType: jp_INT_TYPE */ -#line 283 "cmDependsJavaParser.y" +#line 288 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2627 "cmDependsJavaParser.cxx" +#line 2615 "cmDependsJavaParser.cxx" break; case 16: /* PrimitiveType: jp_LONG_TYPE */ -#line 288 "cmDependsJavaParser.y" +#line 293 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2635 "cmDependsJavaParser.cxx" +#line 2623 "cmDependsJavaParser.cxx" break; case 17: /* PrimitiveType: jp_CHAR_TYPE */ -#line 293 "cmDependsJavaParser.y" +#line 298 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2643 "cmDependsJavaParser.cxx" +#line 2631 "cmDependsJavaParser.cxx" break; case 18: /* PrimitiveType: jp_FLOAT_TYPE */ -#line 298 "cmDependsJavaParser.y" +#line 303 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2651 "cmDependsJavaParser.cxx" +#line 2639 "cmDependsJavaParser.cxx" break; case 19: /* PrimitiveType: jp_DOUBLE_TYPE */ -#line 303 "cmDependsJavaParser.y" +#line 308 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2659 "cmDependsJavaParser.cxx" +#line 2647 "cmDependsJavaParser.cxx" break; case 20: /* PrimitiveType: jp_BOOLEAN_TYPE */ -#line 308 "cmDependsJavaParser.y" +#line 313 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2667 "cmDependsJavaParser.cxx" +#line 2655 "cmDependsJavaParser.cxx" break; case 21: /* ReferenceType: ClassOrInterfaceType */ -#line 314 "cmDependsJavaParser.y" +#line 319 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2678 "cmDependsJavaParser.cxx" +#line 2666 "cmDependsJavaParser.cxx" break; case 22: /* ReferenceType: ArrayType */ -#line 322 "cmDependsJavaParser.y" +#line 327 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2689 "cmDependsJavaParser.cxx" +#line 2677 "cmDependsJavaParser.cxx" break; case 23: /* ClassOrInterfaceType: Name */ -#line 331 "cmDependsJavaParser.y" +#line 336 "cmDependsJavaParser.y" { jpElementStart(1); jpStoreClass((yyvsp[0].str)); @@ -2697,44 +2685,44 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2701 "cmDependsJavaParser.cxx" +#line 2689 "cmDependsJavaParser.cxx" break; case 24: /* ClassType: ClassOrInterfaceType */ -#line 341 "cmDependsJavaParser.y" +#line 346 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2712 "cmDependsJavaParser.cxx" +#line 2700 "cmDependsJavaParser.cxx" break; case 25: /* InterfaceType: ClassOrInterfaceType */ -#line 350 "cmDependsJavaParser.y" +#line 355 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2723 "cmDependsJavaParser.cxx" +#line 2711 "cmDependsJavaParser.cxx" break; case 26: /* ArrayType: PrimitiveType Dims */ -#line 359 "cmDependsJavaParser.y" +#line 364 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2734 "cmDependsJavaParser.cxx" +#line 2722 "cmDependsJavaParser.cxx" break; case 27: /* ArrayType: Name Dims */ -#line 367 "cmDependsJavaParser.y" +#line 372 "cmDependsJavaParser.y" { jpElementStart(2); jpStoreClass((yyvsp[-1].str)); @@ -2742,56 +2730,56 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2746 "cmDependsJavaParser.cxx" +#line 2734 "cmDependsJavaParser.cxx" break; case 28: /* Name: SimpleName */ -#line 377 "cmDependsJavaParser.y" +#line 382 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2755 "cmDependsJavaParser.cxx" +#line 2743 "cmDependsJavaParser.cxx" break; case 29: /* Name: QualifiedName */ -#line 383 "cmDependsJavaParser.y" +#line 388 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2764 "cmDependsJavaParser.cxx" +#line 2752 "cmDependsJavaParser.cxx" break; case 30: /* SimpleName: Identifier */ -#line 390 "cmDependsJavaParser.y" +#line 395 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2773 "cmDependsJavaParser.cxx" +#line 2761 "cmDependsJavaParser.cxx" break; case 31: /* Identifier: jp_NAME */ -#line 397 "cmDependsJavaParser.y" +#line 402 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2782 "cmDependsJavaParser.cxx" +#line 2770 "cmDependsJavaParser.cxx" break; case 32: /* Identifier: jp_DOLLAR jp_NAME */ -#line 403 "cmDependsJavaParser.y" +#line 408 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = (yyvsp[0].str); } -#line 2791 "cmDependsJavaParser.cxx" +#line 2779 "cmDependsJavaParser.cxx" break; case 33: /* QualifiedName: Name jp_DOT Identifier */ -#line 410 "cmDependsJavaParser.y" +#line 415 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->AddClassFound((yyvsp[-2].str)); @@ -2799,11 +2787,11 @@ yyreduce: yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); (yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine()); } -#line 2803 "cmDependsJavaParser.cxx" +#line 2791 "cmDependsJavaParser.cxx" break; case 34: /* QualifiedName: Name jp_DOT jp_CLASS */ -#line 419 "cmDependsJavaParser.y" +#line 424 "cmDependsJavaParser.y" { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2812,11 +2800,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2816 "cmDependsJavaParser.cxx" +#line 2804 "cmDependsJavaParser.cxx" break; case 35: /* QualifiedName: Name jp_DOT jp_THIS */ -#line 429 "cmDependsJavaParser.y" +#line 434 "cmDependsJavaParser.y" { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2825,118 +2813,118 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2829 "cmDependsJavaParser.cxx" +#line 2817 "cmDependsJavaParser.cxx" break; case 36: /* QualifiedName: SimpleType jp_DOT jp_CLASS */ -#line 439 "cmDependsJavaParser.y" +#line 444 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2840 "cmDependsJavaParser.cxx" +#line 2828 "cmDependsJavaParser.cxx" break; case 37: /* SimpleType: PrimitiveType */ -#line 448 "cmDependsJavaParser.y" +#line 453 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2851 "cmDependsJavaParser.cxx" +#line 2839 "cmDependsJavaParser.cxx" break; case 38: /* SimpleType: jp_VOID */ -#line 456 "cmDependsJavaParser.y" +#line 461 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2862 "cmDependsJavaParser.cxx" +#line 2850 "cmDependsJavaParser.cxx" break; case 39: /* CompilationUnit: PackageDeclarationopt ImportDeclarations TypeDeclarations */ -#line 465 "cmDependsJavaParser.y" +#line 470 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2873 "cmDependsJavaParser.cxx" +#line 2861 "cmDependsJavaParser.cxx" break; case 40: /* PackageDeclarationopt: %empty */ -#line 473 "cmDependsJavaParser.y" +#line 478 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2883 "cmDependsJavaParser.cxx" +#line 2871 "cmDependsJavaParser.cxx" break; case 41: /* PackageDeclarationopt: PackageDeclaration */ -#line 480 "cmDependsJavaParser.y" +#line 485 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2894 "cmDependsJavaParser.cxx" +#line 2882 "cmDependsJavaParser.cxx" break; case 42: /* ImportDeclarations: %empty */ -#line 488 "cmDependsJavaParser.y" +#line 493 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2904 "cmDependsJavaParser.cxx" +#line 2892 "cmDependsJavaParser.cxx" break; case 43: /* ImportDeclarations: ImportDeclarations ImportDeclaration */ -#line 495 "cmDependsJavaParser.y" +#line 500 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2915 "cmDependsJavaParser.cxx" +#line 2903 "cmDependsJavaParser.cxx" break; case 44: /* TypeDeclarations: %empty */ -#line 503 "cmDependsJavaParser.y" +#line 508 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2925 "cmDependsJavaParser.cxx" +#line 2913 "cmDependsJavaParser.cxx" break; case 45: /* TypeDeclarations: TypeDeclarations TypeDeclaration */ -#line 510 "cmDependsJavaParser.y" +#line 515 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2936 "cmDependsJavaParser.cxx" +#line 2924 "cmDependsJavaParser.cxx" break; case 46: /* PackageDeclaration: jp_PACKAGE Name jp_SEMICOL */ -#line 519 "cmDependsJavaParser.y" +#line 524 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->SetCurrentPackage((yyvsp[-1].str)); @@ -2946,33 +2934,33 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2950 "cmDependsJavaParser.cxx" +#line 2938 "cmDependsJavaParser.cxx" break; case 47: /* ImportDeclaration: SingleTypeImportDeclaration */ -#line 531 "cmDependsJavaParser.y" +#line 536 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2961 "cmDependsJavaParser.cxx" +#line 2949 "cmDependsJavaParser.cxx" break; case 48: /* ImportDeclaration: TypeImportOnDemandDeclaration */ -#line 539 "cmDependsJavaParser.y" +#line 544 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2972 "cmDependsJavaParser.cxx" +#line 2960 "cmDependsJavaParser.cxx" break; case 49: /* SingleTypeImportDeclaration: jp_IMPORT Name jp_SEMICOL */ -#line 548 "cmDependsJavaParser.y" +#line 553 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->AddPackagesImport((yyvsp[-1].str)); @@ -2982,11 +2970,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2986 "cmDependsJavaParser.cxx" +#line 2974 "cmDependsJavaParser.cxx" break; case 50: /* TypeImportOnDemandDeclaration: jp_IMPORT Name jp_DOT jp_TIMES jp_SEMICOL */ -#line 560 "cmDependsJavaParser.y" +#line 565 "cmDependsJavaParser.y" { jpElementStart(5); std::string str = (yyvsp[-3].str); @@ -2997,77 +2985,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3001 "cmDependsJavaParser.cxx" +#line 2989 "cmDependsJavaParser.cxx" break; case 51: /* TypeDeclaration: ClassDeclaration */ -#line 573 "cmDependsJavaParser.y" +#line 578 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3012 "cmDependsJavaParser.cxx" +#line 3000 "cmDependsJavaParser.cxx" break; case 52: /* TypeDeclaration: InterfaceDeclaration */ -#line 581 "cmDependsJavaParser.y" +#line 586 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3023 "cmDependsJavaParser.cxx" +#line 3011 "cmDependsJavaParser.cxx" break; case 53: /* TypeDeclaration: jp_SEMICOL */ -#line 589 "cmDependsJavaParser.y" +#line 594 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3034 "cmDependsJavaParser.cxx" +#line 3022 "cmDependsJavaParser.cxx" break; case 54: /* Modifiers: Modifier */ -#line 598 "cmDependsJavaParser.y" +#line 603 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3045 "cmDependsJavaParser.cxx" +#line 3033 "cmDependsJavaParser.cxx" break; case 55: /* Modifiers: Modifiers Modifier */ -#line 606 "cmDependsJavaParser.y" +#line 611 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3056 "cmDependsJavaParser.cxx" +#line 3044 "cmDependsJavaParser.cxx" break; case 67: /* ClassHeader: Modifiersopt jp_CLASS Identifier */ -#line 621 "cmDependsJavaParser.y" +#line 626 "cmDependsJavaParser.y" { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3067 "cmDependsJavaParser.cxx" +#line 3055 "cmDependsJavaParser.cxx" break; case 68: /* ClassDeclaration: ClassHeader ClassBody */ -#line 631 "cmDependsJavaParser.y" +#line 636 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3075,11 +3063,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3079 "cmDependsJavaParser.cxx" +#line 3067 "cmDependsJavaParser.cxx" break; case 69: /* ClassDeclaration: ClassHeader Interfaces ClassBody */ -#line 640 "cmDependsJavaParser.y" +#line 645 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(2); @@ -3087,11 +3075,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3091 "cmDependsJavaParser.cxx" +#line 3079 "cmDependsJavaParser.cxx" break; case 70: /* ClassDeclaration: ClassHeader Super ClassBody */ -#line 649 "cmDependsJavaParser.y" +#line 654 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3099,11 +3087,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3103 "cmDependsJavaParser.cxx" +#line 3091 "cmDependsJavaParser.cxx" break; case 71: /* ClassDeclaration: ClassHeader Super Interfaces ClassBody */ -#line 658 "cmDependsJavaParser.y" +#line 663 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3111,226 +3099,226 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3115 "cmDependsJavaParser.cxx" +#line 3103 "cmDependsJavaParser.cxx" break; case 72: /* Modifiersopt: %empty */ -#line 667 "cmDependsJavaParser.y" +#line 672 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3125 "cmDependsJavaParser.cxx" +#line 3113 "cmDependsJavaParser.cxx" break; case 73: /* Modifiersopt: Modifiers */ -#line 674 "cmDependsJavaParser.y" +#line 679 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3136 "cmDependsJavaParser.cxx" +#line 3124 "cmDependsJavaParser.cxx" break; case 74: /* Super: jp_EXTENDS ClassType */ -#line 683 "cmDependsJavaParser.y" +#line 688 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3147 "cmDependsJavaParser.cxx" +#line 3135 "cmDependsJavaParser.cxx" break; case 75: /* Interfaces: jp_IMPLEMENTS InterfaceTypeList */ -#line 692 "cmDependsJavaParser.y" +#line 697 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3158 "cmDependsJavaParser.cxx" +#line 3146 "cmDependsJavaParser.cxx" break; case 76: /* InterfaceTypeList: InterfaceType */ -#line 701 "cmDependsJavaParser.y" +#line 706 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3169 "cmDependsJavaParser.cxx" +#line 3157 "cmDependsJavaParser.cxx" break; case 77: /* InterfaceTypeList: InterfaceTypeList jp_COMMA InterfaceType */ -#line 709 "cmDependsJavaParser.y" +#line 714 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3180 "cmDependsJavaParser.cxx" +#line 3168 "cmDependsJavaParser.cxx" break; case 78: /* ClassBody: jp_CURLYSTART ClassBodyDeclarations jp_CURLYEND */ -#line 718 "cmDependsJavaParser.y" +#line 723 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3191 "cmDependsJavaParser.cxx" +#line 3179 "cmDependsJavaParser.cxx" break; case 79: /* ClassBodyDeclarations: %empty */ -#line 726 "cmDependsJavaParser.y" +#line 731 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3201 "cmDependsJavaParser.cxx" +#line 3189 "cmDependsJavaParser.cxx" break; case 80: /* ClassBodyDeclarations: ClassBodyDeclarations ClassBodyDeclaration */ -#line 733 "cmDependsJavaParser.y" +#line 738 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3212 "cmDependsJavaParser.cxx" +#line 3200 "cmDependsJavaParser.cxx" break; case 81: /* ClassBodyDeclaration: ClassMemberDeclaration */ -#line 742 "cmDependsJavaParser.y" +#line 747 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3223 "cmDependsJavaParser.cxx" +#line 3211 "cmDependsJavaParser.cxx" break; case 82: /* ClassBodyDeclaration: StaticInitializer */ -#line 750 "cmDependsJavaParser.y" +#line 755 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3234 "cmDependsJavaParser.cxx" +#line 3222 "cmDependsJavaParser.cxx" break; case 83: /* ClassBodyDeclaration: ConstructorDeclaration */ -#line 758 "cmDependsJavaParser.y" +#line 763 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3245 "cmDependsJavaParser.cxx" +#line 3233 "cmDependsJavaParser.cxx" break; case 84: /* ClassBodyDeclaration: TypeDeclaration */ -#line 766 "cmDependsJavaParser.y" +#line 771 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3256 "cmDependsJavaParser.cxx" +#line 3244 "cmDependsJavaParser.cxx" break; case 85: /* ClassMemberDeclaration: FieldDeclaration */ -#line 775 "cmDependsJavaParser.y" +#line 780 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3267 "cmDependsJavaParser.cxx" +#line 3255 "cmDependsJavaParser.cxx" break; case 86: /* ClassMemberDeclaration: MethodDeclaration */ -#line 783 "cmDependsJavaParser.y" +#line 788 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3278 "cmDependsJavaParser.cxx" +#line 3266 "cmDependsJavaParser.cxx" break; case 87: /* FieldDeclaration: Modifiersopt Type VariableDeclarators jp_SEMICOL */ -#line 792 "cmDependsJavaParser.y" +#line 797 "cmDependsJavaParser.y" { jpElementStart(4); } -#line 3286 "cmDependsJavaParser.cxx" +#line 3274 "cmDependsJavaParser.cxx" break; case 88: /* VariableDeclarators: VariableDeclarator */ -#line 798 "cmDependsJavaParser.y" +#line 803 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3297 "cmDependsJavaParser.cxx" +#line 3285 "cmDependsJavaParser.cxx" break; case 89: /* VariableDeclarators: VariableDeclarators jp_COMMA VariableDeclarator */ -#line 806 "cmDependsJavaParser.y" +#line 811 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3308 "cmDependsJavaParser.cxx" +#line 3296 "cmDependsJavaParser.cxx" break; case 90: /* VariableDeclarator: VariableDeclaratorId */ -#line 815 "cmDependsJavaParser.y" +#line 820 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3319 "cmDependsJavaParser.cxx" +#line 3307 "cmDependsJavaParser.cxx" break; case 91: /* VariableDeclarator: VariableDeclaratorId jp_EQUALS VariableInitializer */ -#line 823 "cmDependsJavaParser.y" +#line 828 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3330 "cmDependsJavaParser.cxx" +#line 3318 "cmDependsJavaParser.cxx" break; case 92: /* VariableDeclaratorId: Identifier */ -#line 832 "cmDependsJavaParser.y" +#line 837 "cmDependsJavaParser.y" { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -3338,77 +3326,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3342 "cmDependsJavaParser.cxx" +#line 3330 "cmDependsJavaParser.cxx" break; case 93: /* VariableDeclaratorId: VariableDeclaratorId jp_BRACKETSTART jp_BRACKETEND */ -#line 841 "cmDependsJavaParser.y" +#line 846 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3353 "cmDependsJavaParser.cxx" +#line 3341 "cmDependsJavaParser.cxx" break; case 94: /* VariableInitializer: Expression */ -#line 850 "cmDependsJavaParser.y" +#line 855 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3364 "cmDependsJavaParser.cxx" +#line 3352 "cmDependsJavaParser.cxx" break; case 95: /* VariableInitializer: ArrayInitializer */ -#line 858 "cmDependsJavaParser.y" +#line 863 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3375 "cmDependsJavaParser.cxx" +#line 3363 "cmDependsJavaParser.cxx" break; case 96: /* MethodDeclaration: MethodHeader jp_SEMICOL */ -#line 867 "cmDependsJavaParser.y" +#line 872 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3386 "cmDependsJavaParser.cxx" +#line 3374 "cmDependsJavaParser.cxx" break; case 97: /* MethodDeclaration: MethodHeader MethodBody */ -#line 875 "cmDependsJavaParser.y" +#line 880 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3397 "cmDependsJavaParser.cxx" +#line 3385 "cmDependsJavaParser.cxx" break; case 98: /* MethodDeclaration: MethodHeader MethodBody jp_SEMICOL */ -#line 883 "cmDependsJavaParser.y" +#line 888 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3408 "cmDependsJavaParser.cxx" +#line 3396 "cmDependsJavaParser.cxx" break; case 99: /* MethodHeader: Modifiersopt Type MethodDeclarator Throwsopt */ -#line 892 "cmDependsJavaParser.y" +#line 897 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3416,11 +3404,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3420 "cmDependsJavaParser.cxx" +#line 3408 "cmDependsJavaParser.cxx" break; case 100: /* MethodHeader: Modifiersopt jp_VOID MethodDeclarator Throwsopt */ -#line 901 "cmDependsJavaParser.y" +#line 906 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3428,22 +3416,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3432 "cmDependsJavaParser.cxx" +#line 3420 "cmDependsJavaParser.cxx" break; case 101: /* Throwsopt: %empty */ -#line 910 "cmDependsJavaParser.y" +#line 915 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3443 "cmDependsJavaParser.cxx" +#line 3431 "cmDependsJavaParser.cxx" break; case 102: /* Throwsopt: Throws */ -#line 918 "cmDependsJavaParser.y" +#line 923 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3451,11 +3439,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3455 "cmDependsJavaParser.cxx" +#line 3443 "cmDependsJavaParser.cxx" break; case 103: /* MethodDeclarator: Identifier jp_PARESTART FormalParameterListopt jp_PAREEND */ -#line 928 "cmDependsJavaParser.y" +#line 933 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3464,40 +3452,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3468 "cmDependsJavaParser.cxx" +#line 3456 "cmDependsJavaParser.cxx" break; case 104: /* MethodDeclarator: MethodDeclarator jp_BRACKETSTART jp_BRACKETEND */ -#line 938 "cmDependsJavaParser.y" +#line 943 "cmDependsJavaParser.y" { jpElementStart(3); } -#line 3477 "cmDependsJavaParser.cxx" +#line 3465 "cmDependsJavaParser.cxx" break; case 105: /* FormalParameterListopt: %empty */ -#line 944 "cmDependsJavaParser.y" +#line 949 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3488 "cmDependsJavaParser.cxx" +#line 3476 "cmDependsJavaParser.cxx" break; case 107: /* FormalParameterList: FormalParameter */ -#line 955 "cmDependsJavaParser.y" +#line 960 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 3497 "cmDependsJavaParser.cxx" +#line 3485 "cmDependsJavaParser.cxx" break; case 108: /* FormalParameterList: FormalParameterList jp_COMMA FormalParameter */ -#line 961 "cmDependsJavaParser.y" +#line 966 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3505,11 +3493,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3509 "cmDependsJavaParser.cxx" +#line 3497 "cmDependsJavaParser.cxx" break; case 109: /* FormalParameter: Modifiersopt Type VariableDeclaratorId */ -#line 971 "cmDependsJavaParser.y" +#line 976 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3517,11 +3505,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3521 "cmDependsJavaParser.cxx" +#line 3509 "cmDependsJavaParser.cxx" break; case 110: /* Throws: jp_THROWS ClassTypeList */ -#line 981 "cmDependsJavaParser.y" +#line 986 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3529,20 +3517,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3533 "cmDependsJavaParser.cxx" +#line 3521 "cmDependsJavaParser.cxx" break; case 111: /* ClassTypeList: ClassType */ -#line 991 "cmDependsJavaParser.y" +#line 996 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 3542 "cmDependsJavaParser.cxx" +#line 3530 "cmDependsJavaParser.cxx" break; case 112: /* ClassTypeList: ClassTypeList jp_COMMA ClassType */ -#line 997 "cmDependsJavaParser.y" +#line 1002 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3550,11 +3538,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3554 "cmDependsJavaParser.cxx" +#line 3542 "cmDependsJavaParser.cxx" break; case 113: /* MethodBody: Block */ -#line 1007 "cmDependsJavaParser.y" +#line 1012 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3562,11 +3550,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3566 "cmDependsJavaParser.cxx" +#line 3554 "cmDependsJavaParser.cxx" break; case 114: /* StaticInitializer: jp_STATIC Block */ -#line 1017 "cmDependsJavaParser.y" +#line 1022 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3574,11 +3562,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3578 "cmDependsJavaParser.cxx" +#line 3566 "cmDependsJavaParser.cxx" break; case 115: /* ConstructorDeclaration: Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody */ -#line 1027 "cmDependsJavaParser.y" +#line 1032 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3586,11 +3574,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3590 "cmDependsJavaParser.cxx" +#line 3578 "cmDependsJavaParser.cxx" break; case 116: /* ConstructorDeclaration: Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody jp_SEMICOL */ -#line 1036 "cmDependsJavaParser.y" +#line 1041 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -3598,11 +3586,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3602 "cmDependsJavaParser.cxx" +#line 3590 "cmDependsJavaParser.cxx" break; case 117: /* ConstructorDeclarator: SimpleName jp_PARESTART FormalParameterListopt jp_PAREEND */ -#line 1046 "cmDependsJavaParser.y" +#line 1051 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3611,11 +3599,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3615 "cmDependsJavaParser.cxx" +#line 3603 "cmDependsJavaParser.cxx" break; case 118: /* ConstructorBody: jp_CURLYSTART ExplicitConstructorInvocationopt BlockStatementsopt jp_CURLYEND */ -#line 1057 "cmDependsJavaParser.y" +#line 1062 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3623,22 +3611,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3627 "cmDependsJavaParser.cxx" +#line 3615 "cmDependsJavaParser.cxx" break; case 119: /* ExplicitConstructorInvocationopt: %empty */ -#line 1066 "cmDependsJavaParser.y" +#line 1071 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3638 "cmDependsJavaParser.cxx" +#line 3626 "cmDependsJavaParser.cxx" break; case 120: /* ExplicitConstructorInvocationopt: ExplicitConstructorInvocationopt ExplicitConstructorInvocation */ -#line 1074 "cmDependsJavaParser.y" +#line 1079 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3646,11 +3634,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3650 "cmDependsJavaParser.cxx" +#line 3638 "cmDependsJavaParser.cxx" break; case 121: /* ExplicitConstructorInvocation: jp_THIS jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL */ -#line 1084 "cmDependsJavaParser.y" +#line 1089 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -3658,11 +3646,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3662 "cmDependsJavaParser.cxx" +#line 3650 "cmDependsJavaParser.cxx" break; case 122: /* ExplicitConstructorInvocation: jp_SUPER jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL */ -#line 1093 "cmDependsJavaParser.y" +#line 1098 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -3670,22 +3658,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3674 "cmDependsJavaParser.cxx" +#line 3662 "cmDependsJavaParser.cxx" break; case 123: /* InterfaceHeader: Modifiersopt jp_INTERFACE Identifier */ -#line 1103 "cmDependsJavaParser.y" +#line 1108 "cmDependsJavaParser.y" { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3685 "cmDependsJavaParser.cxx" +#line 3673 "cmDependsJavaParser.cxx" break; case 124: /* InterfaceDeclaration: InterfaceHeader ExtendsInterfacesopt InterfaceBody */ -#line 1112 "cmDependsJavaParser.y" +#line 1117 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3693,21 +3681,21 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3697 "cmDependsJavaParser.cxx" +#line 3685 "cmDependsJavaParser.cxx" break; case 125: /* ExtendsInterfacesopt: %empty */ -#line 1121 "cmDependsJavaParser.y" +#line 1126 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3707 "cmDependsJavaParser.cxx" +#line 3695 "cmDependsJavaParser.cxx" break; case 126: /* ExtendsInterfacesopt: ExtendsInterfaces */ -#line 1128 "cmDependsJavaParser.y" +#line 1133 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3715,11 +3703,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3719 "cmDependsJavaParser.cxx" +#line 3707 "cmDependsJavaParser.cxx" break; case 127: /* ExtendsInterfaces: jp_EXTENDS InterfaceType */ -#line 1138 "cmDependsJavaParser.y" +#line 1143 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3727,11 +3715,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3731 "cmDependsJavaParser.cxx" +#line 3719 "cmDependsJavaParser.cxx" break; case 128: /* ExtendsInterfaces: ExtendsInterfaces jp_COMMA InterfaceType */ -#line 1147 "cmDependsJavaParser.y" +#line 1152 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3739,11 +3727,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3743 "cmDependsJavaParser.cxx" +#line 3731 "cmDependsJavaParser.cxx" break; case 129: /* InterfaceBody: jp_CURLYSTART InterfaceMemberDeclarations jp_CURLYEND */ -#line 1157 "cmDependsJavaParser.y" +#line 1162 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3751,33 +3739,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3755 "cmDependsJavaParser.cxx" +#line 3743 "cmDependsJavaParser.cxx" break; case 130: /* InterfaceMemberDeclarations: %empty */ -#line 1166 "cmDependsJavaParser.y" +#line 1171 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3766 "cmDependsJavaParser.cxx" +#line 3754 "cmDependsJavaParser.cxx" break; case 131: /* InterfaceMemberDeclarations: InterfaceMemberDeclarations InterfaceMemberDeclaration */ -#line 1174 "cmDependsJavaParser.y" +#line 1179 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3777 "cmDependsJavaParser.cxx" +#line 3765 "cmDependsJavaParser.cxx" break; case 132: /* InterfaceMemberDeclaration: ConstantDeclaration */ -#line 1183 "cmDependsJavaParser.y" +#line 1188 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3785,11 +3773,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3789 "cmDependsJavaParser.cxx" +#line 3777 "cmDependsJavaParser.cxx" break; case 133: /* InterfaceMemberDeclaration: AbstractMethodDeclaration */ -#line 1192 "cmDependsJavaParser.y" +#line 1197 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3797,11 +3785,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3801 "cmDependsJavaParser.cxx" +#line 3789 "cmDependsJavaParser.cxx" break; case 134: /* InterfaceMemberDeclaration: ClassDeclaration */ -#line 1201 "cmDependsJavaParser.y" +#line 1206 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3809,22 +3797,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3813 "cmDependsJavaParser.cxx" +#line 3801 "cmDependsJavaParser.cxx" break; case 135: /* InterfaceMemberDeclaration: ClassDeclaration jp_SEMICOL */ -#line 1210 "cmDependsJavaParser.y" +#line 1215 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3824 "cmDependsJavaParser.cxx" +#line 3812 "cmDependsJavaParser.cxx" break; case 136: /* InterfaceMemberDeclaration: InterfaceDeclaration */ -#line 1218 "cmDependsJavaParser.y" +#line 1223 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3832,22 +3820,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3836 "cmDependsJavaParser.cxx" +#line 3824 "cmDependsJavaParser.cxx" break; case 137: /* InterfaceMemberDeclaration: InterfaceDeclaration jp_SEMICOL */ -#line 1227 "cmDependsJavaParser.y" +#line 1232 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3847 "cmDependsJavaParser.cxx" +#line 3835 "cmDependsJavaParser.cxx" break; case 138: /* ConstantDeclaration: FieldDeclaration */ -#line 1236 "cmDependsJavaParser.y" +#line 1241 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3855,11 +3843,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3859 "cmDependsJavaParser.cxx" +#line 3847 "cmDependsJavaParser.cxx" break; case 139: /* AbstractMethodDeclaration: MethodHeader Semicols */ -#line 1246 "cmDependsJavaParser.y" +#line 1251 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3867,11 +3855,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3871 "cmDependsJavaParser.cxx" +#line 3859 "cmDependsJavaParser.cxx" break; case 140: /* Semicols: jp_SEMICOL */ -#line 1256 "cmDependsJavaParser.y" +#line 1261 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3879,11 +3867,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3883 "cmDependsJavaParser.cxx" +#line 3871 "cmDependsJavaParser.cxx" break; case 141: /* Semicols: Semicols jp_SEMICOL */ -#line 1265 "cmDependsJavaParser.y" +#line 1270 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3891,11 +3879,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3895 "cmDependsJavaParser.cxx" +#line 3883 "cmDependsJavaParser.cxx" break; case 142: /* ArrayInitializer: jp_CURLYSTART VariableInitializersOptional jp_CURLYEND */ -#line 1275 "cmDependsJavaParser.y" +#line 1280 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3903,22 +3891,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3907 "cmDependsJavaParser.cxx" +#line 3895 "cmDependsJavaParser.cxx" break; case 143: /* VariableInitializersOptional: %empty */ -#line 1284 "cmDependsJavaParser.y" +#line 1289 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3918 "cmDependsJavaParser.cxx" +#line 3906 "cmDependsJavaParser.cxx" break; case 144: /* VariableInitializersOptional: VariableInitializers */ -#line 1292 "cmDependsJavaParser.y" +#line 1297 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3926,11 +3914,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3930 "cmDependsJavaParser.cxx" +#line 3918 "cmDependsJavaParser.cxx" break; case 145: /* VariableInitializersOptional: VariableInitializers jp_COMMA */ -#line 1301 "cmDependsJavaParser.y" +#line 1306 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3938,11 +3926,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3942 "cmDependsJavaParser.cxx" +#line 3930 "cmDependsJavaParser.cxx" break; case 146: /* VariableInitializers: VariableInitializer */ -#line 1311 "cmDependsJavaParser.y" +#line 1316 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3950,11 +3938,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3954 "cmDependsJavaParser.cxx" +#line 3942 "cmDependsJavaParser.cxx" break; case 147: /* VariableInitializers: VariableInitializers jp_COMMA VariableInitializer */ -#line 1320 "cmDependsJavaParser.y" +#line 1325 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3962,33 +3950,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3966 "cmDependsJavaParser.cxx" +#line 3954 "cmDependsJavaParser.cxx" break; case 148: /* Block: jp_CURLYSTART BlockStatementsopt jp_CURLYEND */ -#line 1330 "cmDependsJavaParser.y" +#line 1335 "cmDependsJavaParser.y" { jpElementStart(4); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3977 "cmDependsJavaParser.cxx" +#line 3965 "cmDependsJavaParser.cxx" break; case 149: /* BlockStatementsopt: %empty */ -#line 1338 "cmDependsJavaParser.y" +#line 1343 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3988 "cmDependsJavaParser.cxx" +#line 3976 "cmDependsJavaParser.cxx" break; case 150: /* BlockStatementsopt: BlockStatements */ -#line 1346 "cmDependsJavaParser.y" +#line 1351 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3996,11 +3984,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4000 "cmDependsJavaParser.cxx" +#line 3988 "cmDependsJavaParser.cxx" break; case 151: /* BlockStatements: BlockStatement */ -#line 1356 "cmDependsJavaParser.y" +#line 1361 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4008,11 +3996,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4012 "cmDependsJavaParser.cxx" +#line 4000 "cmDependsJavaParser.cxx" break; case 152: /* BlockStatements: BlockStatements BlockStatement */ -#line 1365 "cmDependsJavaParser.y" +#line 1370 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(2); @@ -4020,11 +4008,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4024 "cmDependsJavaParser.cxx" +#line 4012 "cmDependsJavaParser.cxx" break; case 153: /* BlockStatement: LocalVariableDeclarationStatement */ -#line 1375 "cmDependsJavaParser.y" +#line 1380 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4032,11 +4020,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4036 "cmDependsJavaParser.cxx" +#line 4024 "cmDependsJavaParser.cxx" break; case 154: /* BlockStatement: Statement */ -#line 1384 "cmDependsJavaParser.y" +#line 1389 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4044,11 +4032,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4048 "cmDependsJavaParser.cxx" +#line 4036 "cmDependsJavaParser.cxx" break; case 155: /* BlockStatement: ClassDeclaration */ -#line 1393 "cmDependsJavaParser.y" +#line 1398 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4056,11 +4044,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4060 "cmDependsJavaParser.cxx" +#line 4048 "cmDependsJavaParser.cxx" break; case 156: /* LocalVariableDeclarationStatement: LocalVariableDeclaration jp_SEMICOL */ -#line 1403 "cmDependsJavaParser.y" +#line 1408 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(2); @@ -4068,11 +4056,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4072 "cmDependsJavaParser.cxx" +#line 4060 "cmDependsJavaParser.cxx" break; case 157: /* LocalVariableDeclaration: Modifiers Type VariableDeclarators */ -#line 1413 "cmDependsJavaParser.y" +#line 1418 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(3); @@ -4080,11 +4068,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4084 "cmDependsJavaParser.cxx" +#line 4072 "cmDependsJavaParser.cxx" break; case 158: /* LocalVariableDeclaration: Type VariableDeclarators */ -#line 1422 "cmDependsJavaParser.y" +#line 1427 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(2); @@ -4092,11 +4080,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4096 "cmDependsJavaParser.cxx" +#line 4084 "cmDependsJavaParser.cxx" break; case 159: /* Statement: StatementWithoutTrailingSubstatement */ -#line 1432 "cmDependsJavaParser.y" +#line 1437 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4104,11 +4092,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4108 "cmDependsJavaParser.cxx" +#line 4096 "cmDependsJavaParser.cxx" break; case 160: /* Statement: LabeledStatement */ -#line 1441 "cmDependsJavaParser.y" +#line 1446 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4116,11 +4104,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4120 "cmDependsJavaParser.cxx" +#line 4108 "cmDependsJavaParser.cxx" break; case 161: /* Statement: IfThenStatement */ -#line 1450 "cmDependsJavaParser.y" +#line 1455 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4128,11 +4116,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4132 "cmDependsJavaParser.cxx" +#line 4120 "cmDependsJavaParser.cxx" break; case 162: /* Statement: IfThenElseStatement */ -#line 1459 "cmDependsJavaParser.y" +#line 1464 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4140,11 +4128,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4144 "cmDependsJavaParser.cxx" +#line 4132 "cmDependsJavaParser.cxx" break; case 163: /* Statement: WhileStatement */ -#line 1468 "cmDependsJavaParser.y" +#line 1473 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4152,11 +4140,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4156 "cmDependsJavaParser.cxx" +#line 4144 "cmDependsJavaParser.cxx" break; case 164: /* Statement: ForStatement */ -#line 1477 "cmDependsJavaParser.y" +#line 1482 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4164,11 +4152,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4168 "cmDependsJavaParser.cxx" +#line 4156 "cmDependsJavaParser.cxx" break; case 165: /* StatementNoShortIf: StatementWithoutTrailingSubstatement */ -#line 1487 "cmDependsJavaParser.y" +#line 1492 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4176,11 +4164,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4180 "cmDependsJavaParser.cxx" +#line 4168 "cmDependsJavaParser.cxx" break; case 166: /* StatementNoShortIf: LabeledStatementNoShortIf */ -#line 1496 "cmDependsJavaParser.y" +#line 1501 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4188,11 +4176,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4192 "cmDependsJavaParser.cxx" +#line 4180 "cmDependsJavaParser.cxx" break; case 167: /* StatementNoShortIf: IfThenElseStatementNoShortIf */ -#line 1505 "cmDependsJavaParser.y" +#line 1510 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4200,11 +4188,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4204 "cmDependsJavaParser.cxx" +#line 4192 "cmDependsJavaParser.cxx" break; case 168: /* StatementNoShortIf: WhileStatementNoShortIf */ -#line 1514 "cmDependsJavaParser.y" +#line 1519 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4212,11 +4200,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4216 "cmDependsJavaParser.cxx" +#line 4204 "cmDependsJavaParser.cxx" break; case 169: /* StatementNoShortIf: ForStatementNoShortIf */ -#line 1523 "cmDependsJavaParser.y" +#line 1528 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4224,11 +4212,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4228 "cmDependsJavaParser.cxx" +#line 4216 "cmDependsJavaParser.cxx" break; case 170: /* StatementWithoutTrailingSubstatement: Block */ -#line 1533 "cmDependsJavaParser.y" +#line 1538 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4236,11 +4224,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4240 "cmDependsJavaParser.cxx" +#line 4228 "cmDependsJavaParser.cxx" break; case 171: /* StatementWithoutTrailingSubstatement: EmptyStatement */ -#line 1542 "cmDependsJavaParser.y" +#line 1547 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4248,11 +4236,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4252 "cmDependsJavaParser.cxx" +#line 4240 "cmDependsJavaParser.cxx" break; case 172: /* StatementWithoutTrailingSubstatement: ExpressionStatement */ -#line 1551 "cmDependsJavaParser.y" +#line 1556 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4260,11 +4248,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4264 "cmDependsJavaParser.cxx" +#line 4252 "cmDependsJavaParser.cxx" break; case 173: /* StatementWithoutTrailingSubstatement: SwitchStatement */ -#line 1560 "cmDependsJavaParser.y" +#line 1565 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4272,11 +4260,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4276 "cmDependsJavaParser.cxx" +#line 4264 "cmDependsJavaParser.cxx" break; case 174: /* StatementWithoutTrailingSubstatement: DoStatement */ -#line 1569 "cmDependsJavaParser.y" +#line 1574 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4284,11 +4272,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4288 "cmDependsJavaParser.cxx" +#line 4276 "cmDependsJavaParser.cxx" break; case 175: /* StatementWithoutTrailingSubstatement: BreakStatement */ -#line 1578 "cmDependsJavaParser.y" +#line 1583 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4296,11 +4284,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4300 "cmDependsJavaParser.cxx" +#line 4288 "cmDependsJavaParser.cxx" break; case 176: /* StatementWithoutTrailingSubstatement: ContinueStatement */ -#line 1587 "cmDependsJavaParser.y" +#line 1592 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4308,11 +4296,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4312 "cmDependsJavaParser.cxx" +#line 4300 "cmDependsJavaParser.cxx" break; case 177: /* StatementWithoutTrailingSubstatement: ReturnStatement */ -#line 1596 "cmDependsJavaParser.y" +#line 1601 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4320,11 +4308,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4324 "cmDependsJavaParser.cxx" +#line 4312 "cmDependsJavaParser.cxx" break; case 178: /* StatementWithoutTrailingSubstatement: SynchronizedStatement */ -#line 1605 "cmDependsJavaParser.y" +#line 1610 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4332,11 +4320,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4336 "cmDependsJavaParser.cxx" +#line 4324 "cmDependsJavaParser.cxx" break; case 179: /* StatementWithoutTrailingSubstatement: ThrowStatement */ -#line 1614 "cmDependsJavaParser.y" +#line 1619 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4344,11 +4332,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4348 "cmDependsJavaParser.cxx" +#line 4336 "cmDependsJavaParser.cxx" break; case 180: /* StatementWithoutTrailingSubstatement: TryStatement */ -#line 1623 "cmDependsJavaParser.y" +#line 1628 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4356,11 +4344,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4360 "cmDependsJavaParser.cxx" +#line 4348 "cmDependsJavaParser.cxx" break; case 181: /* StatementWithoutTrailingSubstatement: AssertStatement */ -#line 1632 "cmDependsJavaParser.y" +#line 1637 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4368,11 +4356,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4372 "cmDependsJavaParser.cxx" +#line 4360 "cmDependsJavaParser.cxx" break; case 182: /* EmptyStatement: jp_SEMICOL */ -#line 1642 "cmDependsJavaParser.y" +#line 1647 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4380,11 +4368,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4384 "cmDependsJavaParser.cxx" +#line 4372 "cmDependsJavaParser.cxx" break; case 183: /* LabeledStatement: Identifier jp_COLON Statement */ -#line 1652 "cmDependsJavaParser.y" +#line 1657 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); @@ -4393,11 +4381,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4397 "cmDependsJavaParser.cxx" +#line 4385 "cmDependsJavaParser.cxx" break; case 184: /* LabeledStatementNoShortIf: Identifier jp_COLON StatementNoShortIf */ -#line 1663 "cmDependsJavaParser.y" +#line 1668 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4405,11 +4393,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4409 "cmDependsJavaParser.cxx" +#line 4397 "cmDependsJavaParser.cxx" break; case 185: /* ExpressionStatement: StatementExpression jp_SEMICOL */ -#line 1673 "cmDependsJavaParser.y" +#line 1678 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4417,11 +4405,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4421 "cmDependsJavaParser.cxx" +#line 4409 "cmDependsJavaParser.cxx" break; case 186: /* StatementExpression: Assignment */ -#line 1683 "cmDependsJavaParser.y" +#line 1688 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4429,11 +4417,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4433 "cmDependsJavaParser.cxx" +#line 4421 "cmDependsJavaParser.cxx" break; case 187: /* StatementExpression: PreIncrementExpression */ -#line 1692 "cmDependsJavaParser.y" +#line 1697 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4441,11 +4429,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4445 "cmDependsJavaParser.cxx" +#line 4433 "cmDependsJavaParser.cxx" break; case 188: /* StatementExpression: PreDecrementExpression */ -#line 1701 "cmDependsJavaParser.y" +#line 1706 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4453,11 +4441,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4457 "cmDependsJavaParser.cxx" +#line 4445 "cmDependsJavaParser.cxx" break; case 189: /* StatementExpression: PostIncrementExpression */ -#line 1710 "cmDependsJavaParser.y" +#line 1715 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4465,11 +4453,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4469 "cmDependsJavaParser.cxx" +#line 4457 "cmDependsJavaParser.cxx" break; case 190: /* StatementExpression: PostDecrementExpression */ -#line 1719 "cmDependsJavaParser.y" +#line 1724 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4477,11 +4465,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4481 "cmDependsJavaParser.cxx" +#line 4469 "cmDependsJavaParser.cxx" break; case 191: /* StatementExpression: MethodInvocation */ -#line 1728 "cmDependsJavaParser.y" +#line 1733 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4489,11 +4477,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4493 "cmDependsJavaParser.cxx" +#line 4481 "cmDependsJavaParser.cxx" break; case 192: /* StatementExpression: ClassInstanceCreationExpression */ -#line 1737 "cmDependsJavaParser.y" +#line 1742 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4501,11 +4489,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4505 "cmDependsJavaParser.cxx" +#line 4493 "cmDependsJavaParser.cxx" break; case 193: /* IfThenStatement: jp_IF jp_PARESTART Expression jp_PAREEND Statement */ -#line 1747 "cmDependsJavaParser.y" +#line 1752 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -4513,11 +4501,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4517 "cmDependsJavaParser.cxx" +#line 4505 "cmDependsJavaParser.cxx" break; case 194: /* IfThenElseStatement: jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE Statement */ -#line 1757 "cmDependsJavaParser.y" +#line 1762 "cmDependsJavaParser.y" { jpElementStart(7); jpCheckEmpty(7); @@ -4525,11 +4513,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4529 "cmDependsJavaParser.cxx" +#line 4517 "cmDependsJavaParser.cxx" break; case 195: /* IfThenElseStatementNoShortIf: jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE StatementNoShortIf */ -#line 1767 "cmDependsJavaParser.y" +#line 1772 "cmDependsJavaParser.y" { jpElementStart(7); jpCheckEmpty(7); @@ -4537,40 +4525,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4541 "cmDependsJavaParser.cxx" +#line 4529 "cmDependsJavaParser.cxx" break; case 196: /* SwitchStatement: jp_SWITCH jp_PARESTART Expression jp_PAREEND SwitchBlock */ -#line 1777 "cmDependsJavaParser.y" +#line 1782 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4550 "cmDependsJavaParser.cxx" +#line 4538 "cmDependsJavaParser.cxx" break; case 197: /* SwitchBlock: jp_CURLYSTART SwitchBlockStatementGroups SwitchLabelsopt jp_CURLYEND */ -#line 1784 "cmDependsJavaParser.y" +#line 1789 "cmDependsJavaParser.y" { jpElementStart(4); } -#line 4559 "cmDependsJavaParser.cxx" +#line 4547 "cmDependsJavaParser.cxx" break; case 198: /* SwitchLabelsopt: %empty */ -#line 1790 "cmDependsJavaParser.y" +#line 1795 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4570 "cmDependsJavaParser.cxx" +#line 4558 "cmDependsJavaParser.cxx" break; case 199: /* SwitchLabelsopt: SwitchLabels */ -#line 1798 "cmDependsJavaParser.y" +#line 1803 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4578,22 +4566,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4582 "cmDependsJavaParser.cxx" +#line 4570 "cmDependsJavaParser.cxx" break; case 200: /* SwitchBlockStatementGroups: %empty */ -#line 1807 "cmDependsJavaParser.y" +#line 1812 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4593 "cmDependsJavaParser.cxx" +#line 4581 "cmDependsJavaParser.cxx" break; case 201: /* SwitchBlockStatementGroups: SwitchBlockStatementGroups SwitchBlockStatementGroup */ -#line 1815 "cmDependsJavaParser.y" +#line 1820 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4601,11 +4589,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4605 "cmDependsJavaParser.cxx" +#line 4593 "cmDependsJavaParser.cxx" break; case 202: /* SwitchBlockStatementGroup: SwitchLabels BlockStatements */ -#line 1825 "cmDependsJavaParser.y" +#line 1830 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4613,11 +4601,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4617 "cmDependsJavaParser.cxx" +#line 4605 "cmDependsJavaParser.cxx" break; case 203: /* SwitchLabels: SwitchLabel */ -#line 1835 "cmDependsJavaParser.y" +#line 1840 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4625,11 +4613,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4629 "cmDependsJavaParser.cxx" +#line 4617 "cmDependsJavaParser.cxx" break; case 204: /* SwitchLabels: SwitchLabels SwitchLabel */ -#line 1844 "cmDependsJavaParser.y" +#line 1849 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4637,11 +4625,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4641 "cmDependsJavaParser.cxx" +#line 4629 "cmDependsJavaParser.cxx" break; case 205: /* SwitchLabel: jp_CASE ConstantExpression jp_COLON */ -#line 1854 "cmDependsJavaParser.y" +#line 1859 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4649,11 +4637,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4653 "cmDependsJavaParser.cxx" +#line 4641 "cmDependsJavaParser.cxx" break; case 206: /* SwitchLabel: jp_DEFAULT jp_COLON */ -#line 1863 "cmDependsJavaParser.y" +#line 1868 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4661,58 +4649,58 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4665 "cmDependsJavaParser.cxx" +#line 4653 "cmDependsJavaParser.cxx" break; case 207: /* WhileStatement: jp_WHILE jp_PARESTART Expression jp_PAREEND Statement */ -#line 1873 "cmDependsJavaParser.y" +#line 1878 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4674 "cmDependsJavaParser.cxx" +#line 4662 "cmDependsJavaParser.cxx" break; case 208: /* WhileStatementNoShortIf: jp_WHILE jp_PARESTART Expression jp_PAREEND StatementNoShortIf */ -#line 1880 "cmDependsJavaParser.y" +#line 1885 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4683 "cmDependsJavaParser.cxx" +#line 4671 "cmDependsJavaParser.cxx" break; case 209: /* DoStatement: jp_DO Statement jp_WHILE jp_PARESTART Expression jp_PAREEND jp_SEMICOL */ -#line 1887 "cmDependsJavaParser.y" +#line 1892 "cmDependsJavaParser.y" { jpElementStart(7); } -#line 4692 "cmDependsJavaParser.cxx" +#line 4680 "cmDependsJavaParser.cxx" break; case 210: /* ForStatement: jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND Statement */ -#line 1895 "cmDependsJavaParser.y" +#line 1900 "cmDependsJavaParser.y" { jpElementStart(9); } -#line 4701 "cmDependsJavaParser.cxx" +#line 4689 "cmDependsJavaParser.cxx" break; case 211: /* ForUpdateopt: %empty */ -#line 1901 "cmDependsJavaParser.y" +#line 1906 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4712 "cmDependsJavaParser.cxx" +#line 4700 "cmDependsJavaParser.cxx" break; case 212: /* ForUpdateopt: ForUpdate */ -#line 1909 "cmDependsJavaParser.y" +#line 1914 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4720,22 +4708,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4724 "cmDependsJavaParser.cxx" +#line 4712 "cmDependsJavaParser.cxx" break; case 213: /* ForInitopt: %empty */ -#line 1918 "cmDependsJavaParser.y" +#line 1923 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4735 "cmDependsJavaParser.cxx" +#line 4723 "cmDependsJavaParser.cxx" break; case 214: /* ForInitopt: ForInit */ -#line 1926 "cmDependsJavaParser.y" +#line 1931 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4743,33 +4731,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4747 "cmDependsJavaParser.cxx" +#line 4735 "cmDependsJavaParser.cxx" break; case 215: /* ForStatementNoShortIf: jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND StatementNoShortIf */ -#line 1937 "cmDependsJavaParser.y" +#line 1942 "cmDependsJavaParser.y" { jpElementStart(9); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4758 "cmDependsJavaParser.cxx" +#line 4746 "cmDependsJavaParser.cxx" break; case 216: /* Expressionopt: %empty */ -#line 1945 "cmDependsJavaParser.y" +#line 1950 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4769 "cmDependsJavaParser.cxx" +#line 4757 "cmDependsJavaParser.cxx" break; case 217: /* Expressionopt: Expression */ -#line 1953 "cmDependsJavaParser.y" +#line 1958 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4777,11 +4765,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4781 "cmDependsJavaParser.cxx" +#line 4769 "cmDependsJavaParser.cxx" break; case 218: /* ForInit: StatementExpressionList */ -#line 1963 "cmDependsJavaParser.y" +#line 1968 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4789,11 +4777,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4793 "cmDependsJavaParser.cxx" +#line 4781 "cmDependsJavaParser.cxx" break; case 219: /* ForInit: LocalVariableDeclaration */ -#line 1972 "cmDependsJavaParser.y" +#line 1977 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4801,11 +4789,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4805 "cmDependsJavaParser.cxx" +#line 4793 "cmDependsJavaParser.cxx" break; case 220: /* ForUpdate: StatementExpressionList */ -#line 1982 "cmDependsJavaParser.y" +#line 1987 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4813,11 +4801,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4817 "cmDependsJavaParser.cxx" +#line 4805 "cmDependsJavaParser.cxx" break; case 221: /* StatementExpressionList: StatementExpression */ -#line 1992 "cmDependsJavaParser.y" +#line 1997 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4825,11 +4813,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4829 "cmDependsJavaParser.cxx" +#line 4817 "cmDependsJavaParser.cxx" break; case 222: /* StatementExpressionList: StatementExpressionList jp_COMMA StatementExpression */ -#line 2001 "cmDependsJavaParser.y" +#line 2006 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4837,11 +4825,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4841 "cmDependsJavaParser.cxx" +#line 4829 "cmDependsJavaParser.cxx" break; case 223: /* AssertStatement: jp_ASSERT Expression jp_SEMICOL */ -#line 2011 "cmDependsJavaParser.y" +#line 2016 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4849,11 +4837,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4853 "cmDependsJavaParser.cxx" +#line 4841 "cmDependsJavaParser.cxx" break; case 224: /* AssertStatement: jp_ASSERT Expression jp_COLON Expression jp_SEMICOL */ -#line 2020 "cmDependsJavaParser.y" +#line 2025 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -4861,11 +4849,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4865 "cmDependsJavaParser.cxx" +#line 4853 "cmDependsJavaParser.cxx" break; case 225: /* BreakStatement: jp_BREAK Identifieropt jp_SEMICOL */ -#line 2030 "cmDependsJavaParser.y" +#line 2035 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4874,31 +4862,31 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4878 "cmDependsJavaParser.cxx" +#line 4866 "cmDependsJavaParser.cxx" break; case 226: /* Identifieropt: %empty */ -#line 2040 "cmDependsJavaParser.y" +#line 2045 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4889 "cmDependsJavaParser.cxx" +#line 4877 "cmDependsJavaParser.cxx" break; case 227: /* Identifieropt: Identifier */ -#line 2048 "cmDependsJavaParser.y" +#line 2053 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 4898 "cmDependsJavaParser.cxx" +#line 4886 "cmDependsJavaParser.cxx" break; case 228: /* ContinueStatement: jp_CONTINUE Identifieropt jp_SEMICOL */ -#line 2055 "cmDependsJavaParser.y" +#line 2060 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4907,11 +4895,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4911 "cmDependsJavaParser.cxx" +#line 4899 "cmDependsJavaParser.cxx" break; case 229: /* ReturnStatement: jp_RETURN Expressionopt jp_SEMICOL */ -#line 2066 "cmDependsJavaParser.y" +#line 2071 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4919,11 +4907,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4923 "cmDependsJavaParser.cxx" +#line 4911 "cmDependsJavaParser.cxx" break; case 230: /* ThrowStatement: jp_THROW Expression jp_SEMICOL */ -#line 2076 "cmDependsJavaParser.y" +#line 2081 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4931,11 +4919,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4935 "cmDependsJavaParser.cxx" +#line 4923 "cmDependsJavaParser.cxx" break; case 231: /* SynchronizedStatement: jp_SYNCHRONIZED jp_PARESTART Expression jp_PAREEND Block */ -#line 2086 "cmDependsJavaParser.y" +#line 2091 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -4943,11 +4931,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4947 "cmDependsJavaParser.cxx" +#line 4935 "cmDependsJavaParser.cxx" break; case 232: /* TryStatement: jp_TRY Block Catches */ -#line 2096 "cmDependsJavaParser.y" +#line 2101 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4955,11 +4943,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4959 "cmDependsJavaParser.cxx" +#line 4947 "cmDependsJavaParser.cxx" break; case 233: /* TryStatement: jp_TRY Block Catchesopt Finally */ -#line 2105 "cmDependsJavaParser.y" +#line 2110 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -4967,22 +4955,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4971 "cmDependsJavaParser.cxx" +#line 4959 "cmDependsJavaParser.cxx" break; case 234: /* Catchesopt: %empty */ -#line 2114 "cmDependsJavaParser.y" +#line 2119 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4982 "cmDependsJavaParser.cxx" +#line 4970 "cmDependsJavaParser.cxx" break; case 235: /* Catchesopt: Catches */ -#line 2122 "cmDependsJavaParser.y" +#line 2127 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4990,11 +4978,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4994 "cmDependsJavaParser.cxx" +#line 4982 "cmDependsJavaParser.cxx" break; case 236: /* Catches: CatchClause */ -#line 2132 "cmDependsJavaParser.y" +#line 2137 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5002,11 +4990,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5006 "cmDependsJavaParser.cxx" +#line 4994 "cmDependsJavaParser.cxx" break; case 237: /* Catches: Catches CatchClause */ -#line 2141 "cmDependsJavaParser.y" +#line 2146 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5014,20 +5002,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5018 "cmDependsJavaParser.cxx" +#line 5006 "cmDependsJavaParser.cxx" break; case 238: /* CatchClause: jp_CATCH jp_PARESTART FormalParameter jp_PAREEND Block */ -#line 2151 "cmDependsJavaParser.y" +#line 2156 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 5027 "cmDependsJavaParser.cxx" +#line 5015 "cmDependsJavaParser.cxx" break; case 239: /* Finally: jp_FINALLY Block */ -#line 2158 "cmDependsJavaParser.y" +#line 2163 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5035,11 +5023,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5039 "cmDependsJavaParser.cxx" +#line 5027 "cmDependsJavaParser.cxx" break; case 240: /* Primary: PrimaryNoNewArray */ -#line 2168 "cmDependsJavaParser.y" +#line 2173 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5047,11 +5035,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5051 "cmDependsJavaParser.cxx" +#line 5039 "cmDependsJavaParser.cxx" break; case 241: /* Primary: ArrayCreationExpression */ -#line 2177 "cmDependsJavaParser.y" +#line 2182 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5059,11 +5047,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5063 "cmDependsJavaParser.cxx" +#line 5051 "cmDependsJavaParser.cxx" break; case 242: /* PrimaryNoNewArray: Literal */ -#line 2187 "cmDependsJavaParser.y" +#line 2192 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5071,20 +5059,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5075 "cmDependsJavaParser.cxx" +#line 5063 "cmDependsJavaParser.cxx" break; case 243: /* PrimaryNoNewArray: jp_THIS */ -#line 2196 "cmDependsJavaParser.y" +#line 2201 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 5084 "cmDependsJavaParser.cxx" +#line 5072 "cmDependsJavaParser.cxx" break; case 244: /* PrimaryNoNewArray: jp_PARESTART Expression jp_PAREEND */ -#line 2202 "cmDependsJavaParser.y" +#line 2207 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5092,11 +5080,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5096 "cmDependsJavaParser.cxx" +#line 5084 "cmDependsJavaParser.cxx" break; case 245: /* PrimaryNoNewArray: ClassInstanceCreationExpression */ -#line 2211 "cmDependsJavaParser.y" +#line 2216 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5104,11 +5092,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5108 "cmDependsJavaParser.cxx" +#line 5096 "cmDependsJavaParser.cxx" break; case 246: /* PrimaryNoNewArray: FieldAccess */ -#line 2220 "cmDependsJavaParser.y" +#line 2225 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5116,11 +5104,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5120 "cmDependsJavaParser.cxx" +#line 5108 "cmDependsJavaParser.cxx" break; case 247: /* PrimaryNoNewArray: MethodInvocation */ -#line 2229 "cmDependsJavaParser.y" +#line 2234 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5128,11 +5116,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5132 "cmDependsJavaParser.cxx" +#line 5120 "cmDependsJavaParser.cxx" break; case 248: /* PrimaryNoNewArray: ArrayAccess */ -#line 2238 "cmDependsJavaParser.y" +#line 2243 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5140,11 +5128,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5144 "cmDependsJavaParser.cxx" +#line 5132 "cmDependsJavaParser.cxx" break; case 249: /* ClassInstanceCreationExpression: New ClassType jp_PARESTART ArgumentListopt jp_PAREEND ClassBodyOpt */ -#line 2248 "cmDependsJavaParser.y" +#line 2253 "cmDependsJavaParser.y" { jpElementStart(6); jpCheckEmpty(6); @@ -5152,22 +5140,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5156 "cmDependsJavaParser.cxx" +#line 5144 "cmDependsJavaParser.cxx" break; case 250: /* ClassBodyOpt: %empty */ -#line 2257 "cmDependsJavaParser.y" +#line 2262 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 5167 "cmDependsJavaParser.cxx" +#line 5155 "cmDependsJavaParser.cxx" break; case 251: /* ClassBodyOpt: ClassBody */ -#line 2265 "cmDependsJavaParser.y" +#line 2270 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5175,22 +5163,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5179 "cmDependsJavaParser.cxx" +#line 5167 "cmDependsJavaParser.cxx" break; case 252: /* ArgumentListopt: %empty */ -#line 2274 "cmDependsJavaParser.y" +#line 2279 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 5190 "cmDependsJavaParser.cxx" +#line 5178 "cmDependsJavaParser.cxx" break; case 253: /* ArgumentListopt: ArgumentList */ -#line 2282 "cmDependsJavaParser.y" +#line 2287 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5198,11 +5186,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5202 "cmDependsJavaParser.cxx" +#line 5190 "cmDependsJavaParser.cxx" break; case 254: /* ArgumentList: Expression */ -#line 2292 "cmDependsJavaParser.y" +#line 2297 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5210,11 +5198,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5214 "cmDependsJavaParser.cxx" +#line 5202 "cmDependsJavaParser.cxx" break; case 255: /* ArgumentList: ArgumentList jp_COMMA Expression */ -#line 2301 "cmDependsJavaParser.y" +#line 2306 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5222,11 +5210,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5226 "cmDependsJavaParser.cxx" +#line 5214 "cmDependsJavaParser.cxx" break; case 256: /* ArrayCreationExpression: New PrimitiveType DimExprs Dimsopt */ -#line 2311 "cmDependsJavaParser.y" +#line 2316 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5234,11 +5222,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5238 "cmDependsJavaParser.cxx" +#line 5226 "cmDependsJavaParser.cxx" break; case 257: /* ArrayCreationExpression: New ClassOrInterfaceType DimExprs Dimsopt */ -#line 2320 "cmDependsJavaParser.y" +#line 2325 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5246,11 +5234,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5250 "cmDependsJavaParser.cxx" +#line 5238 "cmDependsJavaParser.cxx" break; case 258: /* ArrayCreationExpression: New PrimitiveType Dims ArrayInitializer */ -#line 2329 "cmDependsJavaParser.y" +#line 2334 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5258,11 +5246,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5262 "cmDependsJavaParser.cxx" +#line 5250 "cmDependsJavaParser.cxx" break; case 259: /* ArrayCreationExpression: New ClassOrInterfaceType Dims ArrayInitializer */ -#line 2338 "cmDependsJavaParser.y" +#line 2343 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5270,22 +5258,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5274 "cmDependsJavaParser.cxx" +#line 5262 "cmDependsJavaParser.cxx" break; case 260: /* Dimsopt: %empty */ -#line 2347 "cmDependsJavaParser.y" +#line 2352 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 5285 "cmDependsJavaParser.cxx" +#line 5273 "cmDependsJavaParser.cxx" break; case 261: /* Dimsopt: Dims */ -#line 2355 "cmDependsJavaParser.y" +#line 2360 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5293,11 +5281,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5297 "cmDependsJavaParser.cxx" +#line 5285 "cmDependsJavaParser.cxx" break; case 262: /* DimExprs: DimExpr */ -#line 2365 "cmDependsJavaParser.y" +#line 2370 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5305,11 +5293,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5309 "cmDependsJavaParser.cxx" +#line 5297 "cmDependsJavaParser.cxx" break; case 263: /* DimExprs: DimExprs DimExpr */ -#line 2374 "cmDependsJavaParser.y" +#line 2379 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5317,11 +5305,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5321 "cmDependsJavaParser.cxx" +#line 5309 "cmDependsJavaParser.cxx" break; case 264: /* DimExpr: jp_BRACKETSTART Expression jp_BRACKETEND */ -#line 2384 "cmDependsJavaParser.y" +#line 2389 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5329,29 +5317,29 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5333 "cmDependsJavaParser.cxx" +#line 5321 "cmDependsJavaParser.cxx" break; case 265: /* Dims: jp_BRACKETSTART jp_BRACKETEND */ -#line 2394 "cmDependsJavaParser.y" +#line 2399 "cmDependsJavaParser.y" { jpElementStart(2); } -#line 5342 "cmDependsJavaParser.cxx" +#line 5330 "cmDependsJavaParser.cxx" break; case 266: /* Dims: Dims jp_BRACKETSTART jp_BRACKETEND */ -#line 2400 "cmDependsJavaParser.y" +#line 2405 "cmDependsJavaParser.y" { jpElementStart(3); } -#line 5351 "cmDependsJavaParser.cxx" +#line 5339 "cmDependsJavaParser.cxx" break; case 267: /* FieldAccess: Primary jp_DOT Identifier */ -#line 2407 "cmDependsJavaParser.y" +#line 2412 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5360,11 +5348,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5364 "cmDependsJavaParser.cxx" +#line 5352 "cmDependsJavaParser.cxx" break; case 268: /* FieldAccess: jp_SUPER jp_DOT Identifier */ -#line 2417 "cmDependsJavaParser.y" +#line 2422 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5373,11 +5361,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5377 "cmDependsJavaParser.cxx" +#line 5365 "cmDependsJavaParser.cxx" break; case 269: /* FieldAccess: jp_THIS jp_DOT Identifier */ -#line 2427 "cmDependsJavaParser.y" +#line 2432 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5386,11 +5374,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5390 "cmDependsJavaParser.cxx" +#line 5378 "cmDependsJavaParser.cxx" break; case 270: /* FieldAccess: Primary jp_DOT jp_THIS */ -#line 2437 "cmDependsJavaParser.y" +#line 2442 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5399,11 +5387,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5403 "cmDependsJavaParser.cxx" +#line 5391 "cmDependsJavaParser.cxx" break; case 271: /* MethodInvocation: Name jp_PARESTART ArgumentListopt jp_PAREEND */ -#line 2448 "cmDependsJavaParser.y" +#line 2453 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5412,11 +5400,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5416 "cmDependsJavaParser.cxx" +#line 5404 "cmDependsJavaParser.cxx" break; case 272: /* MethodInvocation: Primary jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */ -#line 2458 "cmDependsJavaParser.y" +#line 2463 "cmDependsJavaParser.y" { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-5].str))); @@ -5426,11 +5414,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5430 "cmDependsJavaParser.cxx" +#line 5418 "cmDependsJavaParser.cxx" break; case 273: /* MethodInvocation: jp_SUPER jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */ -#line 2469 "cmDependsJavaParser.y" +#line 2474 "cmDependsJavaParser.y" { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5439,11 +5427,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5443 "cmDependsJavaParser.cxx" +#line 5431 "cmDependsJavaParser.cxx" break; case 274: /* MethodInvocation: jp_THIS jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */ -#line 2479 "cmDependsJavaParser.y" +#line 2484 "cmDependsJavaParser.y" { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5452,11 +5440,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5456 "cmDependsJavaParser.cxx" +#line 5444 "cmDependsJavaParser.cxx" break; case 275: /* ArrayAccess: Name jp_BRACKETSTART Expression jp_BRACKETEND */ -#line 2490 "cmDependsJavaParser.y" +#line 2495 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5465,11 +5453,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5469 "cmDependsJavaParser.cxx" +#line 5457 "cmDependsJavaParser.cxx" break; case 276: /* ArrayAccess: PrimaryNoNewArray jp_BRACKETSTART Expression jp_BRACKETEND */ -#line 2500 "cmDependsJavaParser.y" +#line 2505 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5477,11 +5465,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5481 "cmDependsJavaParser.cxx" +#line 5469 "cmDependsJavaParser.cxx" break; case 277: /* PostfixExpression: Primary */ -#line 2510 "cmDependsJavaParser.y" +#line 2515 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5489,11 +5477,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5493 "cmDependsJavaParser.cxx" +#line 5481 "cmDependsJavaParser.cxx" break; case 278: /* PostfixExpression: Name */ -#line 2519 "cmDependsJavaParser.y" +#line 2524 "cmDependsJavaParser.y" { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5501,11 +5489,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5505 "cmDependsJavaParser.cxx" +#line 5493 "cmDependsJavaParser.cxx" break; case 279: /* PostfixExpression: ArrayType jp_DOT jp_CLASS */ -#line 2528 "cmDependsJavaParser.y" +#line 2533 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5513,11 +5501,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5517 "cmDependsJavaParser.cxx" +#line 5505 "cmDependsJavaParser.cxx" break; case 280: /* PostfixExpression: PostIncrementExpression */ -#line 2537 "cmDependsJavaParser.y" +#line 2542 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5525,11 +5513,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5529 "cmDependsJavaParser.cxx" +#line 5517 "cmDependsJavaParser.cxx" break; case 281: /* PostfixExpression: PostDecrementExpression */ -#line 2546 "cmDependsJavaParser.y" +#line 2551 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5537,11 +5525,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5541 "cmDependsJavaParser.cxx" +#line 5529 "cmDependsJavaParser.cxx" break; case 282: /* PostIncrementExpression: PostfixExpression jp_PLUSPLUS */ -#line 2556 "cmDependsJavaParser.y" +#line 2561 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5549,11 +5537,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5553 "cmDependsJavaParser.cxx" +#line 5541 "cmDependsJavaParser.cxx" break; case 283: /* PostDecrementExpression: PostfixExpression jp_MINUSMINUS */ -#line 2566 "cmDependsJavaParser.y" +#line 2571 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5561,11 +5549,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5565 "cmDependsJavaParser.cxx" +#line 5553 "cmDependsJavaParser.cxx" break; case 284: /* UnaryExpression: PreIncrementExpression */ -#line 2576 "cmDependsJavaParser.y" +#line 2581 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5573,11 +5561,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5577 "cmDependsJavaParser.cxx" +#line 5565 "cmDependsJavaParser.cxx" break; case 285: /* UnaryExpression: PreDecrementExpression */ -#line 2585 "cmDependsJavaParser.y" +#line 2590 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5585,11 +5573,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5589 "cmDependsJavaParser.cxx" +#line 5577 "cmDependsJavaParser.cxx" break; case 286: /* UnaryExpression: jp_PLUS UnaryExpression */ -#line 2594 "cmDependsJavaParser.y" +#line 2599 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5597,11 +5585,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5601 "cmDependsJavaParser.cxx" +#line 5589 "cmDependsJavaParser.cxx" break; case 287: /* UnaryExpression: jp_MINUS UnaryExpression */ -#line 2603 "cmDependsJavaParser.y" +#line 2608 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5609,11 +5597,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5613 "cmDependsJavaParser.cxx" +#line 5601 "cmDependsJavaParser.cxx" break; case 288: /* UnaryExpression: UnaryExpressionNotPlusMinus */ -#line 2612 "cmDependsJavaParser.y" +#line 2617 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5621,11 +5609,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5625 "cmDependsJavaParser.cxx" +#line 5613 "cmDependsJavaParser.cxx" break; case 289: /* PreIncrementExpression: jp_PLUSPLUS UnaryExpression */ -#line 2622 "cmDependsJavaParser.y" +#line 2627 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5633,11 +5621,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5637 "cmDependsJavaParser.cxx" +#line 5625 "cmDependsJavaParser.cxx" break; case 290: /* PreDecrementExpression: jp_MINUSMINUS UnaryExpression */ -#line 2632 "cmDependsJavaParser.y" +#line 2637 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5645,11 +5633,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5649 "cmDependsJavaParser.cxx" +#line 5637 "cmDependsJavaParser.cxx" break; case 291: /* UnaryExpressionNotPlusMinus: PostfixExpression */ -#line 2642 "cmDependsJavaParser.y" +#line 2647 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5657,11 +5645,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5661 "cmDependsJavaParser.cxx" +#line 5649 "cmDependsJavaParser.cxx" break; case 292: /* UnaryExpressionNotPlusMinus: jp_TILDE UnaryExpression */ -#line 2651 "cmDependsJavaParser.y" +#line 2656 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5669,11 +5657,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5673 "cmDependsJavaParser.cxx" +#line 5661 "cmDependsJavaParser.cxx" break; case 293: /* UnaryExpressionNotPlusMinus: jp_EXCLAMATION UnaryExpression */ -#line 2660 "cmDependsJavaParser.y" +#line 2665 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5681,11 +5669,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5685 "cmDependsJavaParser.cxx" +#line 5673 "cmDependsJavaParser.cxx" break; case 294: /* UnaryExpressionNotPlusMinus: CastExpression */ -#line 2669 "cmDependsJavaParser.y" +#line 2674 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5693,11 +5681,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5697 "cmDependsJavaParser.cxx" +#line 5685 "cmDependsJavaParser.cxx" break; case 295: /* CastExpression: jp_PARESTART PrimitiveType Dimsopt jp_PAREEND UnaryExpression */ -#line 2679 "cmDependsJavaParser.y" +#line 2684 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -5705,11 +5693,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5709 "cmDependsJavaParser.cxx" +#line 5697 "cmDependsJavaParser.cxx" break; case 296: /* CastExpression: jp_PARESTART Expression jp_PAREEND UnaryExpressionNotPlusMinus */ -#line 2688 "cmDependsJavaParser.y" +#line 2693 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5717,20 +5705,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5721 "cmDependsJavaParser.cxx" +#line 5709 "cmDependsJavaParser.cxx" break; case 297: /* CastExpression: jp_PARESTART Name Dims jp_PAREEND UnaryExpressionNotPlusMinus */ -#line 2697 "cmDependsJavaParser.y" +#line 2702 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 5730 "cmDependsJavaParser.cxx" +#line 5718 "cmDependsJavaParser.cxx" break; case 298: /* MultiplicativeExpression: UnaryExpression */ -#line 2704 "cmDependsJavaParser.y" +#line 2709 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5738,11 +5726,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5742 "cmDependsJavaParser.cxx" +#line 5730 "cmDependsJavaParser.cxx" break; case 299: /* MultiplicativeExpression: MultiplicativeExpression jp_TIMES UnaryExpression */ -#line 2713 "cmDependsJavaParser.y" +#line 2718 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5750,11 +5738,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5754 "cmDependsJavaParser.cxx" +#line 5742 "cmDependsJavaParser.cxx" break; case 300: /* MultiplicativeExpression: MultiplicativeExpression jp_DIVIDE UnaryExpression */ -#line 2722 "cmDependsJavaParser.y" +#line 2727 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5762,11 +5750,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5766 "cmDependsJavaParser.cxx" +#line 5754 "cmDependsJavaParser.cxx" break; case 301: /* MultiplicativeExpression: MultiplicativeExpression jp_PERCENT UnaryExpression */ -#line 2731 "cmDependsJavaParser.y" +#line 2736 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5774,11 +5762,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5778 "cmDependsJavaParser.cxx" +#line 5766 "cmDependsJavaParser.cxx" break; case 302: /* AdditiveExpression: MultiplicativeExpression */ -#line 2741 "cmDependsJavaParser.y" +#line 2746 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5786,11 +5774,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5790 "cmDependsJavaParser.cxx" +#line 5778 "cmDependsJavaParser.cxx" break; case 303: /* AdditiveExpression: AdditiveExpression jp_PLUS MultiplicativeExpression */ -#line 2750 "cmDependsJavaParser.y" +#line 2755 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5798,11 +5786,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5802 "cmDependsJavaParser.cxx" +#line 5790 "cmDependsJavaParser.cxx" break; case 304: /* AdditiveExpression: AdditiveExpression jp_MINUS MultiplicativeExpression */ -#line 2759 "cmDependsJavaParser.y" +#line 2764 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5810,11 +5798,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5814 "cmDependsJavaParser.cxx" +#line 5802 "cmDependsJavaParser.cxx" break; case 305: /* ShiftExpression: AdditiveExpression */ -#line 2769 "cmDependsJavaParser.y" +#line 2774 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5822,11 +5810,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5826 "cmDependsJavaParser.cxx" +#line 5814 "cmDependsJavaParser.cxx" break; case 306: /* ShiftExpression: ShiftExpression jp_LTLT AdditiveExpression */ -#line 2778 "cmDependsJavaParser.y" +#line 2783 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5834,11 +5822,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5838 "cmDependsJavaParser.cxx" +#line 5826 "cmDependsJavaParser.cxx" break; case 307: /* ShiftExpression: ShiftExpression jp_GTGT AdditiveExpression */ -#line 2787 "cmDependsJavaParser.y" +#line 2792 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5846,11 +5834,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5850 "cmDependsJavaParser.cxx" +#line 5838 "cmDependsJavaParser.cxx" break; case 308: /* ShiftExpression: ShiftExpression jp_GTGTGT AdditiveExpression */ -#line 2796 "cmDependsJavaParser.y" +#line 2801 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5858,11 +5846,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5862 "cmDependsJavaParser.cxx" +#line 5850 "cmDependsJavaParser.cxx" break; case 309: /* RelationalExpression: ShiftExpression */ -#line 2806 "cmDependsJavaParser.y" +#line 2811 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5870,11 +5858,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5874 "cmDependsJavaParser.cxx" +#line 5862 "cmDependsJavaParser.cxx" break; case 310: /* RelationalExpression: RelationalExpression jp_LESSTHAN ShiftExpression */ -#line 2815 "cmDependsJavaParser.y" +#line 2820 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5882,11 +5870,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5886 "cmDependsJavaParser.cxx" +#line 5874 "cmDependsJavaParser.cxx" break; case 311: /* RelationalExpression: RelationalExpression jp_GREATER ShiftExpression */ -#line 2824 "cmDependsJavaParser.y" +#line 2829 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5894,11 +5882,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5898 "cmDependsJavaParser.cxx" +#line 5886 "cmDependsJavaParser.cxx" break; case 312: /* RelationalExpression: RelationalExpression jp_LTEQUALS ShiftExpression */ -#line 2833 "cmDependsJavaParser.y" +#line 2838 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5906,11 +5894,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5910 "cmDependsJavaParser.cxx" +#line 5898 "cmDependsJavaParser.cxx" break; case 313: /* RelationalExpression: RelationalExpression jp_GTEQUALS ShiftExpression */ -#line 2842 "cmDependsJavaParser.y" +#line 2847 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5918,11 +5906,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5922 "cmDependsJavaParser.cxx" +#line 5910 "cmDependsJavaParser.cxx" break; case 314: /* RelationalExpression: RelationalExpression jp_INSTANCEOF ReferenceType */ -#line 2851 "cmDependsJavaParser.y" +#line 2856 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5930,11 +5918,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5934 "cmDependsJavaParser.cxx" +#line 5922 "cmDependsJavaParser.cxx" break; case 315: /* EqualityExpression: RelationalExpression */ -#line 2861 "cmDependsJavaParser.y" +#line 2866 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5942,11 +5930,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5946 "cmDependsJavaParser.cxx" +#line 5934 "cmDependsJavaParser.cxx" break; case 316: /* EqualityExpression: EqualityExpression jp_EQUALSEQUALS RelationalExpression */ -#line 2870 "cmDependsJavaParser.y" +#line 2875 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5954,11 +5942,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5958 "cmDependsJavaParser.cxx" +#line 5946 "cmDependsJavaParser.cxx" break; case 317: /* EqualityExpression: EqualityExpression jp_EXCLAMATIONEQUALS RelationalExpression */ -#line 2879 "cmDependsJavaParser.y" +#line 2884 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5966,11 +5954,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5970 "cmDependsJavaParser.cxx" +#line 5958 "cmDependsJavaParser.cxx" break; case 318: /* AndExpression: EqualityExpression */ -#line 2889 "cmDependsJavaParser.y" +#line 2894 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5978,11 +5966,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5982 "cmDependsJavaParser.cxx" +#line 5970 "cmDependsJavaParser.cxx" break; case 319: /* AndExpression: AndExpression jp_AND EqualityExpression */ -#line 2898 "cmDependsJavaParser.y" +#line 2903 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5990,11 +5978,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5994 "cmDependsJavaParser.cxx" +#line 5982 "cmDependsJavaParser.cxx" break; case 320: /* ExclusiveOrExpression: AndExpression */ -#line 2908 "cmDependsJavaParser.y" +#line 2913 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6002,11 +5990,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6006 "cmDependsJavaParser.cxx" +#line 5994 "cmDependsJavaParser.cxx" break; case 321: /* ExclusiveOrExpression: ExclusiveOrExpression jp_CARROT AndExpression */ -#line 2917 "cmDependsJavaParser.y" +#line 2922 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -6014,11 +6002,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6018 "cmDependsJavaParser.cxx" +#line 6006 "cmDependsJavaParser.cxx" break; case 322: /* InclusiveOrExpression: ExclusiveOrExpression */ -#line 2927 "cmDependsJavaParser.y" +#line 2932 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6026,11 +6014,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6030 "cmDependsJavaParser.cxx" +#line 6018 "cmDependsJavaParser.cxx" break; case 323: /* InclusiveOrExpression: InclusiveOrExpression jp_PIPE ExclusiveOrExpression */ -#line 2936 "cmDependsJavaParser.y" +#line 2941 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -6038,11 +6026,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6042 "cmDependsJavaParser.cxx" +#line 6030 "cmDependsJavaParser.cxx" break; case 324: /* ConditionalAndExpression: InclusiveOrExpression */ -#line 2946 "cmDependsJavaParser.y" +#line 2951 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6050,11 +6038,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6054 "cmDependsJavaParser.cxx" +#line 6042 "cmDependsJavaParser.cxx" break; case 325: /* ConditionalAndExpression: ConditionalAndExpression jp_ANDAND InclusiveOrExpression */ -#line 2955 "cmDependsJavaParser.y" +#line 2960 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -6062,11 +6050,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6066 "cmDependsJavaParser.cxx" +#line 6054 "cmDependsJavaParser.cxx" break; case 326: /* ConditionalOrExpression: ConditionalAndExpression */ -#line 2965 "cmDependsJavaParser.y" +#line 2970 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6074,11 +6062,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6078 "cmDependsJavaParser.cxx" +#line 6066 "cmDependsJavaParser.cxx" break; case 327: /* ConditionalOrExpression: ConditionalOrExpression jp_PIPEPIPE ConditionalAndExpression */ -#line 2974 "cmDependsJavaParser.y" +#line 2979 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -6086,11 +6074,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6090 "cmDependsJavaParser.cxx" +#line 6078 "cmDependsJavaParser.cxx" break; case 328: /* ConditionalExpression: ConditionalOrExpression */ -#line 2984 "cmDependsJavaParser.y" +#line 2989 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6098,11 +6086,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6102 "cmDependsJavaParser.cxx" +#line 6090 "cmDependsJavaParser.cxx" break; case 329: /* ConditionalExpression: ConditionalOrExpression jp_QUESTION Expression jp_COLON ConditionalExpression */ -#line 2993 "cmDependsJavaParser.y" +#line 2998 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -6110,11 +6098,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6114 "cmDependsJavaParser.cxx" +#line 6102 "cmDependsJavaParser.cxx" break; case 330: /* AssignmentExpression: ConditionalExpression */ -#line 3003 "cmDependsJavaParser.y" +#line 3008 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6122,11 +6110,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6126 "cmDependsJavaParser.cxx" +#line 6114 "cmDependsJavaParser.cxx" break; case 331: /* AssignmentExpression: Assignment */ -#line 3012 "cmDependsJavaParser.y" +#line 3017 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6134,11 +6122,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6138 "cmDependsJavaParser.cxx" +#line 6126 "cmDependsJavaParser.cxx" break; case 332: /* Assignment: LeftHandSide AssignmentOperator AssignmentExpression */ -#line 3022 "cmDependsJavaParser.y" +#line 3027 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -6146,11 +6134,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6150 "cmDependsJavaParser.cxx" +#line 6138 "cmDependsJavaParser.cxx" break; case 333: /* LeftHandSide: Name */ -#line 3032 "cmDependsJavaParser.y" +#line 3037 "cmDependsJavaParser.y" { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -6159,11 +6147,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6163 "cmDependsJavaParser.cxx" +#line 6151 "cmDependsJavaParser.cxx" break; case 334: /* LeftHandSide: FieldAccess */ -#line 3042 "cmDependsJavaParser.y" +#line 3047 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6171,11 +6159,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6175 "cmDependsJavaParser.cxx" +#line 6163 "cmDependsJavaParser.cxx" break; case 335: /* LeftHandSide: ArrayAccess */ -#line 3051 "cmDependsJavaParser.y" +#line 3056 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6183,11 +6171,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6187 "cmDependsJavaParser.cxx" +#line 6175 "cmDependsJavaParser.cxx" break; case 336: /* AssignmentOperator: jp_EQUALS */ -#line 3061 "cmDependsJavaParser.y" +#line 3066 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6195,11 +6183,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6199 "cmDependsJavaParser.cxx" +#line 6187 "cmDependsJavaParser.cxx" break; case 337: /* AssignmentOperator: jp_TIMESEQUALS */ -#line 3070 "cmDependsJavaParser.y" +#line 3075 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6207,11 +6195,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6211 "cmDependsJavaParser.cxx" +#line 6199 "cmDependsJavaParser.cxx" break; case 338: /* AssignmentOperator: jp_DIVIDEEQUALS */ -#line 3079 "cmDependsJavaParser.y" +#line 3084 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6219,11 +6207,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6223 "cmDependsJavaParser.cxx" +#line 6211 "cmDependsJavaParser.cxx" break; case 339: /* AssignmentOperator: jp_PERCENTEQUALS */ -#line 3088 "cmDependsJavaParser.y" +#line 3093 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6231,11 +6219,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6235 "cmDependsJavaParser.cxx" +#line 6223 "cmDependsJavaParser.cxx" break; case 340: /* AssignmentOperator: jp_PLUSEQUALS */ -#line 3097 "cmDependsJavaParser.y" +#line 3102 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6243,11 +6231,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6247 "cmDependsJavaParser.cxx" +#line 6235 "cmDependsJavaParser.cxx" break; case 341: /* AssignmentOperator: jp_MINUSEQUALS */ -#line 3106 "cmDependsJavaParser.y" +#line 3111 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6255,11 +6243,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6259 "cmDependsJavaParser.cxx" +#line 6247 "cmDependsJavaParser.cxx" break; case 342: /* AssignmentOperator: jp_LESLESEQUALS */ -#line 3115 "cmDependsJavaParser.y" +#line 3120 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6267,11 +6255,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6271 "cmDependsJavaParser.cxx" +#line 6259 "cmDependsJavaParser.cxx" break; case 343: /* AssignmentOperator: jp_GTGTEQUALS */ -#line 3124 "cmDependsJavaParser.y" +#line 3129 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6279,11 +6267,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6283 "cmDependsJavaParser.cxx" +#line 6271 "cmDependsJavaParser.cxx" break; case 344: /* AssignmentOperator: jp_GTGTGTEQUALS */ -#line 3133 "cmDependsJavaParser.y" +#line 3138 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6291,11 +6279,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6295 "cmDependsJavaParser.cxx" +#line 6283 "cmDependsJavaParser.cxx" break; case 345: /* AssignmentOperator: jp_ANDEQUALS */ -#line 3142 "cmDependsJavaParser.y" +#line 3147 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6303,11 +6291,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6307 "cmDependsJavaParser.cxx" +#line 6295 "cmDependsJavaParser.cxx" break; case 346: /* AssignmentOperator: jp_CARROTEQUALS */ -#line 3151 "cmDependsJavaParser.y" +#line 3156 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6315,11 +6303,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6319 "cmDependsJavaParser.cxx" +#line 6307 "cmDependsJavaParser.cxx" break; case 347: /* AssignmentOperator: jp_PIPEEQUALS */ -#line 3160 "cmDependsJavaParser.y" +#line 3165 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6327,11 +6315,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6331 "cmDependsJavaParser.cxx" +#line 6319 "cmDependsJavaParser.cxx" break; case 348: /* Expression: AssignmentExpression */ -#line 3170 "cmDependsJavaParser.y" +#line 3175 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6339,11 +6327,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6343 "cmDependsJavaParser.cxx" +#line 6331 "cmDependsJavaParser.cxx" break; case 349: /* ConstantExpression: Expression */ -#line 3180 "cmDependsJavaParser.y" +#line 3185 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6351,11 +6339,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6355 "cmDependsJavaParser.cxx" +#line 6343 "cmDependsJavaParser.cxx" break; case 350: /* New: jp_NEW */ -#line 3190 "cmDependsJavaParser.y" +#line 3195 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6363,11 +6351,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6367 "cmDependsJavaParser.cxx" +#line 6355 "cmDependsJavaParser.cxx" break; case 351: /* New: Name jp_DOT jp_NEW */ -#line 3199 "cmDependsJavaParser.y" +#line 3204 "cmDependsJavaParser.y" { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -6376,11 +6364,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6380 "cmDependsJavaParser.cxx" +#line 6368 "cmDependsJavaParser.cxx" break; -#line 6384 "cmDependsJavaParser.cxx" +#line 6372 "cmDependsJavaParser.cxx" default: break; } @@ -6456,7 +6444,7 @@ yyerrlab: } yyerror (yyscanner, yymsgp); if (yysyntax_error_status == YYENOMEM) - goto yyexhaustedlab; + YYNOMEM; } } @@ -6492,6 +6480,7 @@ yyerrorlab: label yyerrorlab therefore never appears in user code. */ if (0) YYERROR; + ++yynerrs; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ @@ -6552,7 +6541,7 @@ yyerrlab1: `-------------------------------------*/ yyacceptlab: yyresult = 0; - goto yyreturn; + goto yyreturnlab; /*-----------------------------------. @@ -6560,24 +6549,22 @@ yyacceptlab: `-----------------------------------*/ yyabortlab: yyresult = 1; - goto yyreturn; + goto yyreturnlab; -#if 1 -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ yyexhaustedlab: yyerror (yyscanner, YY_("memory exhausted")); yyresult = 2; - goto yyreturn; -#endif + goto yyreturnlab; -/*-------------------------------------------------------. -| yyreturn -- parsing is finished, clean up and return. | -`-------------------------------------------------------*/ -yyreturn: +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: if (yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at @@ -6605,7 +6592,7 @@ yyreturn: return yyresult; } -#line 3208 "cmDependsJavaParser.y" +#line 3213 "cmDependsJavaParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmDependsJavaParser.y b/Source/LexerParser/cmDependsJavaParser.y index a76ec50..ff37af2 100644 --- a/Source/LexerParser/cmDependsJavaParser.y +++ b/Source/LexerParser/cmDependsJavaParser.y @@ -45,6 +45,11 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wfree-nonheap-object" #endif +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wunused-but-set-variable") +# pragma clang diagnostic ignored "-Wunused-but-set-variable" +# endif +#endif %} /* Generate a reentrant parser object. */ diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h index 885cc66..02f40aa 100644 --- a/Source/LexerParser/cmDependsJavaParserTokens.h +++ b/Source/LexerParser/cmDependsJavaParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.7.5. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison interface for Yacc-like parsers in C @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -165,6 +165,8 @@ extern int cmDependsJava_yydebug; + int cmDependsJava_yyparse (yyscan_t yyscanner); + #endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED */ diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx index d9b0ae3..cb5e498 100644 --- a/Source/LexerParser/cmExprParser.cxx +++ b/Source/LexerParser/cmExprParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.7.5. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison implementation for Yacc-like parsers in C @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30705 +#define YYBISON 30802 /* Bison version string. */ -#define YYBISON_VERSION "3.7.5" +#define YYBISON_VERSION "3.8.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -115,6 +115,9 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wfree-nonheap-object" #endif #if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wunused-but-set-variable") +# pragma clang diagnostic ignored "-Wunused-but-set-variable" +# endif # if __has_warning("-Wused-but-marked-unused") # pragma clang diagnostic ignored "-Wused-but-marked-unused" # endif @@ -124,7 +127,7 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma diag_suppress 550 /* variable set but never used */ #endif -#line 128 "cmExprParser.cxx" +#line 131 "cmExprParser.cxx" # ifndef YY_CAST # ifdef __cplusplus @@ -336,12 +339,18 @@ typedef int yy_state_fast_t; # define YY_USE(E) /* empty */ #endif -#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else @@ -557,12 +566,12 @@ static const yytype_int8 yytranslate[] = }; #if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 85, 85, 90, 93, 98, 101, 106, 109, 114, - 117, 120, 125, 128, 131, 136, 139, 142, 148, 153, - 156, 159, 162, 167, 170 + 0, 88, 88, 93, 96, 101, 104, 109, 112, 117, + 120, 123, 128, 131, 134, 139, 142, 145, 151, 156, + 159, 162, 165, 170, 173 }; #endif @@ -593,16 +602,6 @@ yysymbol_name (yysymbol_kind_t yysymbol) } #endif -#ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_int16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271 -}; -#endif - #define YYPACT_NINF (-11) #define yypact_value_is_default(Yyn) \ @@ -613,8 +612,8 @@ static const yytype_int16 yytoknum[] = #define yytable_value_is_error(Yyn) \ 0 - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ static const yytype_int8 yypact[] = { 1, 1, 1, 1, 1, -11, 6, -10, -4, 9, @@ -624,9 +623,9 @@ static const yytype_int8 yypact[] = -11 }; - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ static const yytype_int8 yydefact[] = { 0, 0, 0, 0, 0, 23, 0, 2, 3, 5, @@ -636,21 +635,21 @@ static const yytype_int8 yydefact[] = 18 }; - /* YYPGOTO[NTERM-NUM]. */ +/* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -11, -11, 22, 10, 8, 12, -3, -2, -1, -11 }; - /* YYDEFGOTO[NTERM-NUM]. */ +/* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { 0, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int8 yytable[] = { 15, 16, 20, 18, 1, 2, 19, 27, 28, 29, @@ -667,8 +666,8 @@ static const yytype_int8 yycheck[] = 20, -1, -1, -1, 22 }; - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ static const yytype_int8 yystos[] = { 0, 3, 4, 10, 15, 16, 18, 19, 20, 21, @@ -678,7 +677,7 @@ static const yytype_int8 yystos[] = 25 }; - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int8 yyr1[] = { 0, 17, 18, 19, 19, 20, 20, 21, 21, 22, @@ -686,7 +685,7 @@ static const yytype_int8 yyr1[] = 25, 25, 25, 26, 26 }; - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ static const yytype_int8 yyr2[] = { 0, 2, 1, 1, 3, 1, 3, 1, 3, 1, @@ -703,6 +702,7 @@ enum { YYENOMEM = -2 }; #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab #define YYRECOVERING() (!!yyerrstatus) @@ -743,10 +743,7 @@ do { \ YYFPRINTF Args; \ } while (0) -/* This macro is provided for backward compatibility. */ -# ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif + # define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ @@ -774,10 +771,6 @@ yy_symbol_value_print (FILE *yyo, YY_USE (yyscanner); if (!yyvaluep) return; -# ifdef YYPRINT - if (yykind < YYNTOKENS) - YYPRINT (yyo, yytoknum[yykind], *yyvaluep); -# endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END @@ -1239,6 +1232,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); YYDPRINTF ((stderr, "Starting parse\n")); yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; @@ -1264,7 +1258,7 @@ yysetstate: if (yyss + yystacksize - 1 <= yyssp) #if !defined yyoverflow && !defined YYSTACK_RELOCATE - goto yyexhaustedlab; + YYNOMEM; #else { /* Get the current used size of the three stacks, in elements. */ @@ -1292,7 +1286,7 @@ yysetstate: # else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; + YYNOMEM; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; @@ -1303,7 +1297,7 @@ yysetstate: YY_CAST (union yyalloc *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); if (! yyptr) - goto yyexhaustedlab; + YYNOMEM; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE @@ -1325,6 +1319,7 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + if (yystate == YYFINAL) YYACCEPT; @@ -1437,194 +1432,194 @@ yyreduce: switch (yyn) { case 2: /* start: exp */ -#line 85 "cmExprParser.y" +#line 88 "cmExprParser.y" { cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number)); } -#line 1445 "cmExprParser.cxx" +#line 1440 "cmExprParser.cxx" break; case 3: /* exp: bitwiseor */ -#line 90 "cmExprParser.y" +#line 93 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1453 "cmExprParser.cxx" +#line 1448 "cmExprParser.cxx" break; case 4: /* exp: exp exp_OR bitwiseor */ -#line 93 "cmExprParser.y" +#line 96 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number); } -#line 1461 "cmExprParser.cxx" +#line 1456 "cmExprParser.cxx" break; case 5: /* bitwiseor: bitwisexor */ -#line 98 "cmExprParser.y" +#line 101 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1469 "cmExprParser.cxx" +#line 1464 "cmExprParser.cxx" break; case 6: /* bitwiseor: bitwiseor exp_XOR bitwisexor */ -#line 101 "cmExprParser.y" +#line 104 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number); } -#line 1477 "cmExprParser.cxx" +#line 1472 "cmExprParser.cxx" break; case 7: /* bitwisexor: bitwiseand */ -#line 106 "cmExprParser.y" +#line 109 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1485 "cmExprParser.cxx" +#line 1480 "cmExprParser.cxx" break; case 8: /* bitwisexor: bitwisexor exp_AND bitwiseand */ -#line 109 "cmExprParser.y" +#line 112 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number); } -#line 1493 "cmExprParser.cxx" +#line 1488 "cmExprParser.cxx" break; case 9: /* bitwiseand: shift */ -#line 114 "cmExprParser.y" +#line 117 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1501 "cmExprParser.cxx" +#line 1496 "cmExprParser.cxx" break; case 10: /* bitwiseand: bitwiseand exp_SHIFTLEFT shift */ -#line 117 "cmExprParser.y" +#line 120 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number); } -#line 1509 "cmExprParser.cxx" +#line 1504 "cmExprParser.cxx" break; case 11: /* bitwiseand: bitwiseand exp_SHIFTRIGHT shift */ -#line 120 "cmExprParser.y" +#line 123 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number); } -#line 1517 "cmExprParser.cxx" +#line 1512 "cmExprParser.cxx" break; case 12: /* shift: term */ -#line 125 "cmExprParser.y" +#line 128 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1525 "cmExprParser.cxx" +#line 1520 "cmExprParser.cxx" break; case 13: /* shift: shift exp_PLUS term */ -#line 128 "cmExprParser.y" +#line 131 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number); } -#line 1533 "cmExprParser.cxx" +#line 1528 "cmExprParser.cxx" break; case 14: /* shift: shift exp_MINUS term */ -#line 131 "cmExprParser.y" +#line 134 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number); } -#line 1541 "cmExprParser.cxx" +#line 1536 "cmExprParser.cxx" break; case 15: /* term: unary */ -#line 136 "cmExprParser.y" +#line 139 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1549 "cmExprParser.cxx" +#line 1544 "cmExprParser.cxx" break; case 16: /* term: term exp_TIMES unary */ -#line 139 "cmExprParser.y" +#line 142 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number); } -#line 1557 "cmExprParser.cxx" +#line 1552 "cmExprParser.cxx" break; case 17: /* term: term exp_DIVIDE unary */ -#line 142 "cmExprParser.y" +#line 145 "cmExprParser.y" { if (yyvsp[0].Number == 0) { throw std::overflow_error("divide by zero"); } (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number); } -#line 1568 "cmExprParser.cxx" +#line 1563 "cmExprParser.cxx" break; case 18: /* term: term exp_MOD unary */ -#line 148 "cmExprParser.y" +#line 151 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number); } -#line 1576 "cmExprParser.cxx" +#line 1571 "cmExprParser.cxx" break; case 19: /* unary: factor */ -#line 153 "cmExprParser.y" +#line 156 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1584 "cmExprParser.cxx" +#line 1579 "cmExprParser.cxx" break; case 20: /* unary: exp_PLUS unary */ -#line 156 "cmExprParser.y" +#line 159 "cmExprParser.y" { (yyval.Number) = + (yyvsp[0].Number); } -#line 1592 "cmExprParser.cxx" +#line 1587 "cmExprParser.cxx" break; case 21: /* unary: exp_MINUS unary */ -#line 159 "cmExprParser.y" +#line 162 "cmExprParser.y" { (yyval.Number) = - (yyvsp[0].Number); } -#line 1600 "cmExprParser.cxx" +#line 1595 "cmExprParser.cxx" break; case 22: /* unary: exp_NOT unary */ -#line 162 "cmExprParser.y" +#line 165 "cmExprParser.y" { (yyval.Number) = ~ (yyvsp[0].Number); } -#line 1608 "cmExprParser.cxx" +#line 1603 "cmExprParser.cxx" break; case 23: /* factor: exp_NUMBER */ -#line 167 "cmExprParser.y" +#line 170 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1616 "cmExprParser.cxx" +#line 1611 "cmExprParser.cxx" break; case 24: /* factor: exp_OPENPARENT exp exp_CLOSEPARENT */ -#line 170 "cmExprParser.y" +#line 173 "cmExprParser.y" { (yyval.Number) = (yyvsp[-1].Number); } -#line 1624 "cmExprParser.cxx" +#line 1619 "cmExprParser.cxx" break; -#line 1628 "cmExprParser.cxx" +#line 1623 "cmExprParser.cxx" default: break; } @@ -1700,7 +1695,7 @@ yyerrlab: } yyerror (yyscanner, yymsgp); if (yysyntax_error_status == YYENOMEM) - goto yyexhaustedlab; + YYNOMEM; } } @@ -1736,6 +1731,7 @@ yyerrorlab: label yyerrorlab therefore never appears in user code. */ if (0) YYERROR; + ++yynerrs; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ @@ -1796,7 +1792,7 @@ yyerrlab1: `-------------------------------------*/ yyacceptlab: yyresult = 0; - goto yyreturn; + goto yyreturnlab; /*-----------------------------------. @@ -1804,24 +1800,22 @@ yyacceptlab: `-----------------------------------*/ yyabortlab: yyresult = 1; - goto yyreturn; + goto yyreturnlab; -#if 1 -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ yyexhaustedlab: yyerror (yyscanner, YY_("memory exhausted")); yyresult = 2; - goto yyreturn; -#endif + goto yyreturnlab; -/*-------------------------------------------------------. -| yyreturn -- parsing is finished, clean up and return. | -`-------------------------------------------------------*/ -yyreturn: +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: if (yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at @@ -1849,7 +1843,7 @@ yyreturn: return yyresult; } -#line 175 "cmExprParser.y" +#line 178 "cmExprParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y index fda2395..1c959f6 100644 --- a/Source/LexerParser/cmExprParser.y +++ b/Source/LexerParser/cmExprParser.y @@ -40,6 +40,9 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wfree-nonheap-object" #endif #if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wunused-but-set-variable") +# pragma clang diagnostic ignored "-Wunused-but-set-variable" +# endif # if __has_warning("-Wused-but-marked-unused") # pragma clang diagnostic ignored "-Wused-but-marked-unused" # endif diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h index 67b03de..e552fbe 100644 --- a/Source/LexerParser/cmExprParserTokens.h +++ b/Source/LexerParser/cmExprParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.7.5. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison interface for Yacc-like parsers in C @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -76,6 +76,8 @@ extern int cmExpr_yydebug; + int cmExpr_yyparse (yyscan_t yyscanner); + #endif /* !YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED */ diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index 50e9752..b177296 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.7.5. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison implementation for Yacc-like parsers in C @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30705 +#define YYBISON 30802 /* Bison version string. */ -#define YYBISON_VERSION "3.7.5" +#define YYBISON_VERSION "3.8.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -132,8 +132,13 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wfree-nonheap-object" #endif +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wunused-but-set-variable") +# pragma clang diagnostic ignored "-Wunused-but-set-variable" +# endif +#endif -#line 137 "cmFortranParser.cxx" +#line 142 "cmFortranParser.cxx" # ifndef YY_CAST # ifdef __cplusplus @@ -373,12 +378,18 @@ typedef int yy_state_fast_t; # define YY_USE(E) /* empty */ #endif -#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else @@ -596,16 +607,16 @@ static const yytype_int8 yytranslate[] = }; #if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_uint8 yyrline[] = +/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_int16 yyrline[] = { - 0, 101, 101, 101, 104, 108, 113, 122, 128, 135, - 140, 144, 149, 161, 166, 171, 176, 181, 186, 191, - 196, 201, 205, 209, 213, 217, 218, 223, 223, 223, - 224, 224, 225, 225, 226, 226, 227, 227, 228, 228, - 229, 229, 230, 230, 231, 231, 232, 232, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251 + 0, 106, 106, 106, 109, 113, 118, 127, 133, 140, + 145, 149, 154, 166, 171, 176, 181, 186, 191, 196, + 201, 206, 210, 214, 218, 222, 223, 228, 228, 228, + 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, + 234, 234, 235, 235, 236, 236, 237, 237, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256 }; #endif @@ -641,19 +652,6 @@ yysymbol_name (yysymbol_kind_t yysymbol) } #endif -#ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_int16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295 -}; -#endif - #define YYPACT_NINF (-39) #define yypact_value_is_default(Yyn) \ @@ -664,8 +662,8 @@ static const yytype_int16 yytoknum[] = #define yytable_value_is_error(Yyn) \ 0 - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ static const yytype_int16 yypact[] = { -39, 21, -39, 1, -39, -20, -39, -39, -39, -39, @@ -683,9 +681,9 @@ static const yytype_int16 yypact[] = 501, 539, -39, -39, -39, 554, -39 }; - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ static const yytype_int8 yydefact[] = { 2, 0, 1, 0, 25, 0, 27, 28, 29, 31, @@ -703,23 +701,23 @@ static const yytype_int8 yydefact[] = 0, 0, 46, 7, 12, 0, 8 }; - /* YYPGOTO[NTERM-NUM]. */ +/* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -38, -39 }; - /* YYDEFGOTO[NTERM-NUM]. */ +/* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { 0, 1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 44, 82 }; - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int8 yytable[] = { 59, 60, 61, 62, 42, 63, 105, 83, 84, 106, @@ -848,8 +846,8 @@ static const yytype_int8 yycheck[] = 36, 37, 38, 39, 40 }; - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ static const yytype_int8 yystos[] = { 0, 42, 0, 1, 3, 6, 7, 8, 9, 10, @@ -867,7 +865,7 @@ static const yytype_int8 yystos[] = 53, 53, 33, 3, 3, 53, 3 }; - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int8 yyr1[] = { 0, 41, 42, 42, 43, 43, 43, 43, 43, 43, @@ -879,7 +877,7 @@ static const yytype_int8 yyr1[] = 54, 54, 54, 54, 54 }; - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ static const yytype_int8 yyr2[] = { 0, 2, 0, 2, 2, 4, 4, 7, 9, 4, @@ -900,6 +898,7 @@ enum { YYENOMEM = -2 }; #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab #define YYRECOVERING() (!!yyerrstatus) @@ -940,10 +939,7 @@ do { \ YYFPRINTF Args; \ } while (0) -/* This macro is provided for backward compatibility. */ -# ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif + # define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ @@ -971,10 +967,6 @@ yy_symbol_value_print (FILE *yyo, YY_USE (yyscanner); if (!yyvaluep) return; -# ifdef YYPRINT - if (yykind < YYNTOKENS) - YYPRINT (yyo, yytoknum[yykind], *yyvaluep); -# endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END @@ -1367,21 +1359,21 @@ yydestruct (const char *yymsg, switch (yykind) { case YYSYMBOL_STRING: /* STRING */ -#line 95 "cmFortranParser.y" +#line 100 "cmFortranParser.y" { free(((*yyvaluep).string)); } -#line 1373 "cmFortranParser.cxx" +#line 1365 "cmFortranParser.cxx" break; case YYSYMBOL_WORD: /* WORD */ -#line 95 "cmFortranParser.y" +#line 100 "cmFortranParser.y" { free(((*yyvaluep).string)); } -#line 1379 "cmFortranParser.cxx" +#line 1371 "cmFortranParser.cxx" break; case YYSYMBOL_CPP_INCLUDE_ANGLE: /* CPP_INCLUDE_ANGLE */ -#line 95 "cmFortranParser.y" +#line 100 "cmFortranParser.y" { free(((*yyvaluep).string)); } -#line 1385 "cmFortranParser.cxx" +#line 1377 "cmFortranParser.cxx" break; default: @@ -1458,6 +1450,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); YYDPRINTF ((stderr, "Starting parse\n")); yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; @@ -1483,7 +1476,7 @@ yysetstate: if (yyss + yystacksize - 1 <= yyssp) #if !defined yyoverflow && !defined YYSTACK_RELOCATE - goto yyexhaustedlab; + YYNOMEM; #else { /* Get the current used size of the three stacks, in elements. */ @@ -1511,7 +1504,7 @@ yysetstate: # else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; + YYNOMEM; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; @@ -1522,7 +1515,7 @@ yysetstate: YY_CAST (union yyalloc *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); if (! yyptr) - goto yyexhaustedlab; + YYNOMEM; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE @@ -1544,6 +1537,7 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + if (yystate == YYFINAL) YYACCEPT; @@ -1656,26 +1650,26 @@ yyreduce: switch (yyn) { case 4: /* stmt: INTERFACE EOSTMT */ -#line 104 "cmFortranParser.y" +#line 109 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1665 "cmFortranParser.cxx" +#line 1659 "cmFortranParser.cxx" break; case 5: /* stmt: USE WORD other EOSTMT */ -#line 108 "cmFortranParser.y" +#line 113 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1675 "cmFortranParser.cxx" +#line 1669 "cmFortranParser.cxx" break; case 6: /* stmt: MODULE WORD other EOSTMT */ -#line 113 "cmFortranParser.y" +#line 118 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 && @@ -1685,22 +1679,22 @@ yyreduce: } free((yyvsp[-2].string)); } -#line 1689 "cmFortranParser.cxx" +#line 1683 "cmFortranParser.cxx" break; case 7: /* stmt: SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT */ -#line 122 "cmFortranParser.y" +#line 127 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1700 "cmFortranParser.cxx" +#line 1694 "cmFortranParser.cxx" break; case 8: /* stmt: SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT */ -#line 128 "cmFortranParser.y" +#line 133 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string)); @@ -1708,40 +1702,40 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1712 "cmFortranParser.cxx" +#line 1706 "cmFortranParser.cxx" break; case 9: /* stmt: INTERFACE WORD other EOSTMT */ -#line 135 "cmFortranParser.y" +#line 140 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1722 "cmFortranParser.cxx" +#line 1716 "cmFortranParser.cxx" break; case 10: /* stmt: END INTERFACE other EOSTMT */ -#line 140 "cmFortranParser.y" +#line 145 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1731 "cmFortranParser.cxx" +#line 1725 "cmFortranParser.cxx" break; case 11: /* stmt: USE DCOLON WORD other EOSTMT */ -#line 144 "cmFortranParser.y" +#line 149 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1741 "cmFortranParser.cxx" +#line 1735 "cmFortranParser.cxx" break; case 12: /* stmt: USE COMMA WORD DCOLON WORD other EOSTMT */ -#line 149 "cmFortranParser.y" +#line 154 "cmFortranParser.y" { if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); @@ -1754,139 +1748,139 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1758 "cmFortranParser.cxx" +#line 1752 "cmFortranParser.cxx" break; case 13: /* stmt: INCLUDE STRING other EOSTMT */ -#line 161 "cmFortranParser.y" +#line 166 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1768 "cmFortranParser.cxx" +#line 1762 "cmFortranParser.cxx" break; case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */ -#line 166 "cmFortranParser.y" +#line 171 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1778 "cmFortranParser.cxx" +#line 1772 "cmFortranParser.cxx" break; case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */ -#line 171 "cmFortranParser.y" +#line 176 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1788 "cmFortranParser.cxx" +#line 1782 "cmFortranParser.cxx" break; case 16: /* stmt: include STRING other EOSTMT */ -#line 176 "cmFortranParser.y" +#line 181 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1798 "cmFortranParser.cxx" +#line 1792 "cmFortranParser.cxx" break; case 17: /* stmt: define WORD other EOSTMT */ -#line 181 "cmFortranParser.y" +#line 186 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1808 "cmFortranParser.cxx" +#line 1802 "cmFortranParser.cxx" break; case 18: /* stmt: undef WORD other EOSTMT */ -#line 186 "cmFortranParser.y" +#line 191 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1818 "cmFortranParser.cxx" +#line 1812 "cmFortranParser.cxx" break; case 19: /* stmt: ifdef WORD other EOSTMT */ -#line 191 "cmFortranParser.y" +#line 196 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1828 "cmFortranParser.cxx" +#line 1822 "cmFortranParser.cxx" break; case 20: /* stmt: ifndef WORD other EOSTMT */ -#line 196 "cmFortranParser.y" +#line 201 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1838 "cmFortranParser.cxx" +#line 1832 "cmFortranParser.cxx" break; case 21: /* stmt: if other EOSTMT */ -#line 201 "cmFortranParser.y" +#line 206 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1847 "cmFortranParser.cxx" +#line 1841 "cmFortranParser.cxx" break; case 22: /* stmt: elif other EOSTMT */ -#line 205 "cmFortranParser.y" +#line 210 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1856 "cmFortranParser.cxx" +#line 1850 "cmFortranParser.cxx" break; case 23: /* stmt: else other EOSTMT */ -#line 209 "cmFortranParser.y" +#line 214 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1865 "cmFortranParser.cxx" +#line 1859 "cmFortranParser.cxx" break; case 24: /* stmt: endif other EOSTMT */ -#line 213 "cmFortranParser.y" +#line 218 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1874 "cmFortranParser.cxx" +#line 1868 "cmFortranParser.cxx" break; case 48: /* misc_code: WORD */ -#line 235 "cmFortranParser.y" +#line 240 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1880 "cmFortranParser.cxx" +#line 1874 "cmFortranParser.cxx" break; case 55: /* misc_code: STRING */ -#line 242 "cmFortranParser.y" +#line 247 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1886 "cmFortranParser.cxx" +#line 1880 "cmFortranParser.cxx" break; -#line 1890 "cmFortranParser.cxx" +#line 1884 "cmFortranParser.cxx" default: break; } @@ -1962,7 +1956,7 @@ yyerrlab: } yyerror (yyscanner, yymsgp); if (yysyntax_error_status == YYENOMEM) - goto yyexhaustedlab; + YYNOMEM; } } @@ -1998,6 +1992,7 @@ yyerrorlab: label yyerrorlab therefore never appears in user code. */ if (0) YYERROR; + ++yynerrs; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ @@ -2058,7 +2053,7 @@ yyerrlab1: `-------------------------------------*/ yyacceptlab: yyresult = 0; - goto yyreturn; + goto yyreturnlab; /*-----------------------------------. @@ -2066,24 +2061,22 @@ yyacceptlab: `-----------------------------------*/ yyabortlab: yyresult = 1; - goto yyreturn; + goto yyreturnlab; -#if 1 -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ yyexhaustedlab: yyerror (yyscanner, YY_("memory exhausted")); yyresult = 2; - goto yyreturn; -#endif + goto yyreturnlab; -/*-------------------------------------------------------. -| yyreturn -- parsing is finished, clean up and return. | -`-------------------------------------------------------*/ -yyreturn: +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: if (yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at @@ -2111,6 +2104,6 @@ yyreturn: return yyresult; } -#line 254 "cmFortranParser.y" +#line 259 "cmFortranParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y index 8ef1903..07ca630 100644 --- a/Source/LexerParser/cmFortranParser.y +++ b/Source/LexerParser/cmFortranParser.y @@ -57,6 +57,11 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wfree-nonheap-object" #endif +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wunused-but-set-variable") +# pragma clang diagnostic ignored "-Wunused-but-set-variable" +# endif +#endif %} /* Generate a reentrant parser object. */ diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h index 3a19cfb..cb2b999 100644 --- a/Source/LexerParser/cmFortranParserTokens.h +++ b/Source/LexerParser/cmFortranParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.7.5. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison interface for Yacc-like parsers in C @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -100,7 +100,7 @@ extern int cmFortran_yydebug; #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { -#line 71 "cmFortranParser.y" +#line 76 "cmFortranParser.y" char* string; @@ -114,6 +114,8 @@ typedef union YYSTYPE YYSTYPE; + int cmFortran_yyparse (yyscan_t yyscanner); + #endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED */ diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index f90b781..3c41fce 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -226,7 +226,8 @@ CMakeSetupDialog::CMakeSetupDialog() this->SourceDirectory->setCompleter(new QCMakeFileCompleter(this, true)); // fixed pitch font in output window - QFont outputFont("Courier"); + QFont outputFont("Courier New"); + outputFont.setStyleHint(QFont::Monospace); this->Output->setFont(outputFont); this->ErrorFormat.setForeground(QBrush(Qt::red)); diff --git a/Source/QtDialog/cmake-gui.desktop b/Source/QtDialog/cmake-gui.desktop index 842091f..0299c9d 100644 --- a/Source/QtDialog/cmake-gui.desktop +++ b/Source/QtDialog/cmake-gui.desktop @@ -7,6 +7,6 @@ Icon=CMakeSetup Terminal=false X-MultipleArgs=false Type=Application -Categories=Development; +Categories=Development;Building; StartupNotify=true MimeType=application/x-cmakecache; diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index 9dd8a19..16a8965 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -54,6 +54,10 @@ bool cmAddExecutableCommand(std::vector<std::string> const& args, } } + if (importTarget && !importGlobal) { + importGlobal = mf.IsImportedTargetGlobalScope(); + } + bool nameOk = cmGeneratorExpression::IsValidTargetName(exename) && !cmGlobalGenerator::IsReservedTarget(exename); diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index a5d1f6a..29fc09b 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -131,6 +131,10 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, } } + if (importTarget && !importGlobal) { + importGlobal = mf.IsImportedTargetGlobalScope(); + } + if (type == cmStateEnums::INTERFACE_LIBRARY) { if (importGlobal && !importTarget) { status.SetError( diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 9e0d80c..cfde37c 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -95,6 +95,19 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, , Verbose(false) , Format(format) { + // Upstream fixed an issue with their integer parsing in 3.4.0 + // which would cause spurious errors to be raised from `strtoull`. + + if (numThreads < 1) { + int upperLimit = (numThreads == 0) ? std::numeric_limits<int>::max() + : std::abs(numThreads); + + numThreads = + cm::clamp<int>(std::thread::hardware_concurrency(), 1, upperLimit); + } + + std::string sNumThreads = std::to_string(numThreads); + switch (c) { case CompressNone: if (archive_write_add_filter_none(this->Archive) != ARCHIVE_OK) { @@ -150,36 +163,23 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, return; } - { #if ARCHIVE_VERSION_NUMBER >= 3004000 - // Upstream fixed an issue with their integer parsing in 3.4.0 - // which would cause spurious errors to be raised from `strtoull`. - - if (numThreads < 1) { - int upperLimit = (numThreads == 0) ? std::numeric_limits<int>::max() - : std::abs(numThreads); - - numThreads = - cm::clamp<int>(std::thread::hardware_concurrency(), 1, upperLimit); - } # ifdef _AIX - // FIXME: Using more than 2 threads creates an empty archive. - // Enforce this limit pending further investigation. - numThreads = std::min(numThreads, 2); + // FIXME: Using more than 2 threads creates an empty archive. + // Enforce this limit pending further investigation. + if (numThreads > 2) { + numThreads = 2; + sNumThreads = std::to_string(numThreads); + } # endif - - std::string sNumThreads = std::to_string(numThreads); - - if (archive_write_set_filter_option(this->Archive, "xz", "threads", - sNumThreads.c_str()) != - ARCHIVE_OK) { - this->Error = cmStrCat("archive_compressor_xz_options: ", - cm_archive_error_string(this->Archive)); - return; - } -#endif + if (archive_write_set_filter_option(this->Archive, "xz", "threads", + sNumThreads.c_str()) != ARCHIVE_OK) { + this->Error = cmStrCat("archive_compressor_xz_options: ", + cm_archive_error_string(this->Archive)); + return; } +#endif break; case CompressZstd: @@ -188,6 +188,15 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, cm_archive_error_string(this->Archive)); return; } + +#if ARCHIVE_VERSION_NUMBER >= 3006000 + if (archive_write_set_filter_option(this->Archive, "zstd", "threads", + sNumThreads.c_str()) != ARCHIVE_OK) { + this->Error = cmStrCat("archive_compressor_zstd_options: ", + cm_archive_error_string(this->Archive)); + return; + } +#endif break; } diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 3922c56..2a019b1 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -19,10 +19,13 @@ #include "cmsys/Glob.hxx" #include "cmsys/SystemInformation.hxx" +#include "cmArgumentParser.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmWindowsRegistry.h" #ifdef _WIN32 # include "cmAlgorithms.h" @@ -459,6 +462,98 @@ cm::optional<std::string> GetValueChained(GetterFn current, Next... chain) } return GetValueChained(chain...); } + +template <typename Range> +bool QueryWindowsRegistry(Range args, cmExecutionStatus& status, + std::string const& variable) +{ + using View = cmWindowsRegistry::View; + if (args.empty()) { + status.SetError("missing <key> specification."); + return false; + } + std::string const& key = *args.begin(); + + struct Arguments + { + std::string ValueName; + bool ValueNames = false; + bool SubKeys = false; + std::string View; + std::string Separator; + std::string ErrorVariable; + }; + cmArgumentParser<Arguments> parser; + parser.Bind("VALUE"_s, &Arguments::ValueName) + .Bind("VALUE_NAMES"_s, &Arguments::ValueNames) + .Bind("SUBKEYS"_s, &Arguments::SubKeys) + .Bind("VIEW"_s, &Arguments::View) + .Bind("SEPARATOR"_s, &Arguments::Separator) + .Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable); + std::vector<std::string> invalidArgs; + std::vector<std::string> keywordsMissingValue; + + Arguments const arguments = + parser.Parse(args.advance(1), &invalidArgs, &keywordsMissingValue); + if (!invalidArgs.empty()) { + status.SetError(cmStrCat("given invalid argument(s) \"", + cmJoin(invalidArgs, ", "_s), "\".")); + return false; + } + if (!keywordsMissingValue.empty()) { + status.SetError(cmStrCat("missing expected value for argument(s) \"", + cmJoin(keywordsMissingValue, ", "_s), "\".")); + return false; + } + if ((!arguments.ValueName.empty() && + (arguments.ValueNames || arguments.SubKeys)) || + (arguments.ValueName.empty() && arguments.ValueNames && + arguments.SubKeys)) { + status.SetError("given mutually exclusive sub-options \"VALUE\", " + "\"VALUE_NAMES\" or \"SUBKEYS\"."); + return false; + } + + if (!arguments.View.empty() && !cmWindowsRegistry::ToView(arguments.View)) { + status.SetError( + cmStrCat("given invalid value for \"VIEW\": ", arguments.View, '.')); + return false; + } + + auto& makefile = status.GetMakefile(); + + makefile.AddDefinition(variable, ""_s); + + auto view = arguments.View.empty() + ? View::Both + : *cmWindowsRegistry::ToView(arguments.View); + cmWindowsRegistry registry(makefile); + if (arguments.ValueNames) { + auto result = registry.GetValueNames(key, view); + if (result) { + makefile.AddDefinition(variable, cmJoin(*result, ";"_s)); + } + } else if (arguments.SubKeys) { + auto result = registry.GetSubKeys(key, view); + if (result) { + makefile.AddDefinition(variable, cmJoin(*result, ";"_s)); + } + } else { + auto result = + registry.ReadValue(key, arguments.ValueName, view, arguments.Separator); + if (result) { + makefile.AddDefinition(variable, *result); + } + } + + // return error message if requested + if (!arguments.ErrorVariable.empty()) { + makefile.AddDefinition(arguments.ErrorVariable, registry.GetLastError()); + } + + return true; +} + // END Private functions } // anonymous namespace @@ -481,6 +576,11 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, return false; } + if (args[current_index + 1] == "WINDOWS_REGISTRY"_s) { + return QueryWindowsRegistry(cmMakeRange(args).advance(current_index + 2), + status, variable); + } + static cmsys::SystemInformation info; static auto initialized = false; if (!initialized) { diff --git a/Source/cmCMakeLanguageCommand.cxx b/Source/cmCMakeLanguageCommand.cxx index 789c78d..27d8cb8 100644 --- a/Source/cmCMakeLanguageCommand.cxx +++ b/Source/cmCMakeLanguageCommand.cxx @@ -84,7 +84,8 @@ bool cmCMakeLanguageCommandCALL(std::vector<cmListFileArgument> const& args, for (size_t i = startArg; i < args.size(); ++i) { funcArgs.emplace_back(args[i].Value, args[i].Delim, context.Line); } - cmListFileFunction func{ callCommand, context.Line, std::move(funcArgs) }; + cmListFileFunction func{ callCommand, context.Line, context.Line, + std::move(funcArgs) }; if (defer) { if (defer->Id.empty()) { diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx index dc14831..b737c1f 100644 --- a/Source/cmCMakePresetsGraph.cxx +++ b/Source/cmCMakePresetsGraph.cxx @@ -361,6 +361,13 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset, cmSystemTools::GetParentDirectory(preset.OriginFile->Filename); return ExpandMacroResult::Ok; } + if (macroName == "pathListSep") { + if (version < 5) { + return ExpandMacroResult::Error; + } + macroOut += cmSystemTools::GetSystemPathlistSeparator(); + return ExpandMacroResult::Ok; + } } return ExpandMacroResult::Ignore; @@ -781,6 +788,8 @@ cmCMakePresetsGraph::TestPreset::VisitPresetInherit( parentOutput.MaxPassedTestOutputSize); InheritOptionalValue(output.MaxFailedTestOutputSize, parentOutput.MaxFailedTestOutputSize); + InheritOptionalValue(output.TestOutputTruncation, + parentOutput.TestOutputTruncation); InheritOptionalValue(output.MaxTestNameWidth, parentOutput.MaxTestNameWidth); } else { @@ -1035,6 +1044,9 @@ const char* cmCMakePresetsGraph::ResultToString(ReadFileResult result) "support."; case ReadFileResult::CYCLIC_INCLUDE: return "Cyclic include among preset files"; + case ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED: + return "File version must be 5 or higher for testOutputTruncation " + "preset support."; } return "Unknown error"; diff --git a/Source/cmCMakePresetsGraph.h b/Source/cmCMakePresetsGraph.h index 9d6c61a..f1f8662 100644 --- a/Source/cmCMakePresetsGraph.h +++ b/Source/cmCMakePresetsGraph.h @@ -14,6 +14,8 @@ #include <cm/optional> +#include "CTest/cmCTestTypes.h" + enum class PackageResolveMode; class cmCMakePresetsGraph @@ -47,6 +49,7 @@ public: CONDITION_UNSUPPORTED, TOOLCHAIN_FILE_UNSUPPORTED, CYCLIC_INCLUDE, + TEST_OUTPUT_TRUNCATION_UNSUPPORTED, }; enum class ArchToolsetStrategy @@ -226,6 +229,7 @@ public: cm::optional<bool> SubprojectSummary; cm::optional<int> MaxPassedTestOutputSize; cm::optional<int> MaxFailedTestOutputSize; + cm::optional<cmCTestTypes::TruncationMode> TestOutputTruncation; cm::optional<int> MaxTestNameWidth; }; diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx index 85cf5be..d11e839 100644 --- a/Source/cmCMakePresetsGraphReadJSON.cxx +++ b/Source/cmCMakePresetsGraphReadJSON.cxx @@ -31,9 +31,10 @@ using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset; using BuildPreset = cmCMakePresetsGraph::BuildPreset; using TestPreset = cmCMakePresetsGraph::TestPreset; using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy; +using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>; constexpr int MIN_VERSION = 1; -constexpr int MAX_VERSION = 4; +constexpr int MAX_VERSION = 5; struct CMakeVersion { @@ -59,29 +60,26 @@ std::unique_ptr<cmCMakePresetsGraphInternal::NotCondition> InvertCondition( return retval; } -auto const ConditionStringHelper = cmJSONStringHelper<ReadFileResult>( +auto const ConditionStringHelper = JSONHelperBuilder::String( ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION); -auto const ConditionBoolHelper = cmJSONBoolHelper<ReadFileResult>( +auto const ConditionBoolHelper = JSONHelperBuilder::Bool( ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION); -auto const ConditionStringListHelper = - cmJSONVectorHelper<std::string, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, - ConditionStringHelper); +auto const ConditionStringListHelper = JSONHelperBuilder::Vector<std::string>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, + ConditionStringHelper); auto const ConstConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::ConstCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::ConstCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("value"_s, &cmCMakePresetsGraphInternal::ConstCondition::Value, ConditionBoolHelper, true); auto const EqualsConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::EqualsCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::EqualsCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("lhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Lhs, ConditionStringHelper, true) @@ -89,9 +87,8 @@ auto const EqualsConditionHelper = ConditionStringHelper, true); auto const InListConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::InListCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::InListCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("string"_s, &cmCMakePresetsGraphInternal::InListCondition::String, ConditionStringHelper, true) @@ -99,9 +96,8 @@ auto const InListConditionHelper = ConditionStringListHelper, true); auto const MatchesConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::MatchesCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::MatchesCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("string"_s, &cmCMakePresetsGraphInternal::MatchesCondition::String, ConditionStringHelper, true) @@ -113,23 +109,20 @@ ReadFileResult SubConditionHelper( const Json::Value* value); auto const ListConditionVectorHelper = - cmJSONVectorHelper<std::unique_ptr<cmCMakePresetsGraph::Condition>, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, - SubConditionHelper); + JSONHelperBuilder::Vector<std::unique_ptr<cmCMakePresetsGraph::Condition>>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, + SubConditionHelper); auto const AnyAllOfConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::AnyAllOfCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::AnyAllOfCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("conditions"_s, &cmCMakePresetsGraphInternal::AnyAllOfCondition::Conditions, ListConditionVectorHelper); auto const NotConditionHelper = - cmJSONObjectHelper<cmCMakePresetsGraphInternal::NotCondition, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_CONDITION, false) + JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::NotCondition>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) .Bind("condition"_s, &cmCMakePresetsGraphInternal::NotCondition::SubCondition, @@ -251,37 +244,36 @@ ReadFileResult EnvironmentHelper(cm::optional<std::string>& out, return ReadFileResult::INVALID_PRESET; } -auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>( +auto const VersionIntHelper = JSONHelperBuilder::Int( ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); -auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>( +auto const VersionHelper = JSONHelperBuilder::Required<int>( ReadFileResult::NO_VERSION, VersionIntHelper); auto const RootVersionHelper = - cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_ROOT) + JSONHelperBuilder::Object<int>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_ROOT) .Bind("version"_s, VersionHelper, false); -auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>( +auto const CMakeVersionUIntHelper = JSONHelperBuilder::UInt( ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); auto const CMakeVersionHelper = - cmJSONObjectHelper<CMakeVersion, ReadFileResult>( + JSONHelperBuilder::Object<CMakeVersion>( ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false) .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false) .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false) .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false); -auto const IncludeHelper = cmJSONStringHelper<ReadFileResult>( +auto const IncludeHelper = JSONHelperBuilder::String( ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE); -auto const IncludeVectorHelper = - cmJSONVectorHelper<std::string, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE, IncludeHelper); +auto const IncludeVectorHelper = JSONHelperBuilder::Vector<std::string>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE, IncludeHelper); auto const RootPresetsHelper = - cmJSONObjectHelper<RootPresets, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false) + JSONHelperBuilder::Object<RootPresets>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_ROOT, false) .Bind<int>("version"_s, nullptr, VersionHelper) .Bind("configurePresets"_s, &RootPresets::ConfigurePresets, cmCMakePresetsGraphInternal::ConfigurePresetsHelper, false) @@ -302,7 +294,7 @@ namespace cmCMakePresetsGraphInternal { cmCMakePresetsGraph::ReadFileResult PresetStringHelper( std::string& out, const Json::Value* value) { - static auto const helper = cmJSONStringHelper<ReadFileResult>( + static auto const helper = JSONHelperBuilder::String( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); return helper(out, value); @@ -311,7 +303,7 @@ cmCMakePresetsGraph::ReadFileResult PresetStringHelper( cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper( std::vector<std::string>& out, const Json::Value* value) { - static auto const helper = cmJSONVectorHelper<std::string, ReadFileResult>( + static auto const helper = JSONHelperBuilder::Vector<std::string>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, cmCMakePresetsGraphInternal::PresetStringHelper); @@ -321,7 +313,7 @@ cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper( cmCMakePresetsGraph::ReadFileResult PresetBoolHelper(bool& out, const Json::Value* value) { - static auto const helper = cmJSONBoolHelper<ReadFileResult>( + static auto const helper = JSONHelperBuilder::Bool( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); return helper(out, value); @@ -330,7 +322,7 @@ cmCMakePresetsGraph::ReadFileResult PresetBoolHelper(bool& out, cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper( cm::optional<bool>& out, const Json::Value* value) { - static auto const helper = cmJSONOptionalHelper<bool, ReadFileResult>( + static auto const helper = JSONHelperBuilder::Optional<bool>( ReadFileResult::READ_OK, PresetBoolHelper); return helper(out, value); @@ -339,7 +331,7 @@ cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper( cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out, const Json::Value* value) { - static auto const helper = cmJSONIntHelper<ReadFileResult>( + static auto const helper = JSONHelperBuilder::Int( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); return helper(out, value); @@ -348,8 +340,8 @@ cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out, cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper( cm::optional<int>& out, const Json::Value* value) { - static auto const helper = cmJSONOptionalHelper<int, ReadFileResult>( - ReadFileResult::READ_OK, PresetIntHelper); + static auto const helper = + JSONHelperBuilder::Optional<int>(ReadFileResult::READ_OK, PresetIntHelper); return helper(out, value); } @@ -357,7 +349,7 @@ cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper( cmCMakePresetsGraph::ReadFileResult PresetVectorIntHelper( std::vector<int>& out, const Json::Value* value) { - static auto const helper = cmJSONVectorHelper<int, ReadFileResult>( + static auto const helper = JSONHelperBuilder::Vector<int>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper); return helper(out, value); @@ -409,10 +401,9 @@ cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper( std::map<std::string, cm::optional<std::string>>& out, const Json::Value* value) { - static auto const helper = - cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, - EnvironmentHelper); + static auto const helper = JSONHelperBuilder::Map<cm::optional<std::string>>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, + EnvironmentHelper); return helper(out, value); } @@ -568,6 +559,11 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( return ReadFileResult::CONDITION_UNSUPPORTED; } + // Support for TestOutputTruncation added in version 5. + if (v < 5 && preset.Output && preset.Output->TestOutputTruncation) { + return ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED; + } + this->TestPresetOrder.push_back(preset.Name); } diff --git a/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx b/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx index eefe2fe..430d7ee 100644 --- a/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx @@ -20,6 +20,7 @@ namespace { using ReadFileResult = cmCMakePresetsGraph::ReadFileResult; using BuildPreset = cmCMakePresetsGraph::BuildPreset; +using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>; ReadFileResult PackageResolveModeHelper(cm::optional<PackageResolveMode>& out, const Json::Value* value) @@ -53,8 +54,8 @@ std::function<ReadFileResult(BuildPreset&, const Json::Value*)> const }; auto const BuildPresetHelper = - cmJSONObjectHelper<BuildPreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + JSONHelperBuilder::Object<BuildPreset>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &BuildPreset::Name, cmCMakePresetsGraphInternal::PresetStringHelper) .Bind("inherits"_s, &BuildPreset::Inherits, @@ -99,7 +100,7 @@ namespace cmCMakePresetsGraphInternal { ReadFileResult BuildPresetsHelper(std::vector<BuildPreset>& out, const Json::Value* value) { - static auto const helper = cmJSONVectorHelper<BuildPreset, ReadFileResult>( + static auto const helper = JSONHelperBuilder::Vector<BuildPreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, BuildPresetHelper); diff --git a/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx b/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx index 0f44546..7cff55a 100644 --- a/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx @@ -21,6 +21,7 @@ using ReadFileResult = cmCMakePresetsGraph::ReadFileResult; using CacheVariable = cmCMakePresetsGraph::CacheVariable; using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset; using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy; +using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>; ReadFileResult ArchToolsetStrategyHelper( cm::optional<ArchToolsetStrategy>& out, const Json::Value* value) @@ -53,7 +54,7 @@ ArchToolsetHelper( cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField) { auto const objectHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + JSONHelperBuilder::Object<ConfigurePreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("value", valueField, cmCMakePresetsGraphInternal::PresetStringHelper, false) @@ -85,7 +86,7 @@ auto const ArchitectureHelper = ArchToolsetHelper( auto const ToolsetHelper = ArchToolsetHelper( &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy); -auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>( +auto const VariableStringHelper = JSONHelperBuilder::String( ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE); ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value) @@ -104,7 +105,7 @@ ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value) } auto const VariableObjectHelper = - cmJSONObjectHelper<CacheVariable, ReadFileResult>( + JSONHelperBuilder::Object<CacheVariable>( ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false) .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false) .Bind("value"_s, &CacheVariable::Value, VariableValueHelper); @@ -138,11 +139,11 @@ ReadFileResult VariableHelper(cm::optional<CacheVariable>& out, } auto const VariablesHelper = - cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>( + JSONHelperBuilder::Map<cm::optional<CacheVariable>>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper); auto const PresetWarningsHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + JSONHelperBuilder::Object<ConfigurePreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("dev"_s, &ConfigurePreset::WarnDev, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) @@ -156,7 +157,7 @@ auto const PresetWarningsHelper = cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false); auto const PresetErrorsHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + JSONHelperBuilder::Object<ConfigurePreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("dev"_s, &ConfigurePreset::ErrorDev, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) @@ -164,7 +165,7 @@ auto const PresetErrorsHelper = cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false); auto const PresetDebugHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + JSONHelperBuilder::Object<ConfigurePreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("output"_s, &ConfigurePreset::DebugOutput, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) @@ -174,7 +175,7 @@ auto const PresetDebugHelper = cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false); auto const ConfigurePresetHelper = - cmJSONObjectHelper<ConfigurePreset, ReadFileResult>( + JSONHelperBuilder::Object<ConfigurePreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &ConfigurePreset::Name, cmCMakePresetsGraphInternal::PresetStringHelper) @@ -218,10 +219,9 @@ namespace cmCMakePresetsGraphInternal { ReadFileResult ConfigurePresetsHelper(std::vector<ConfigurePreset>& out, const Json::Value* value) { - static auto const helper = - cmJSONVectorHelper<ConfigurePreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - ConfigurePresetHelper); + static auto const helper = JSONHelperBuilder::Vector<ConfigurePreset>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, + ConfigurePresetHelper); return helper(out, value); } diff --git a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx index 4d6474a..c07d380 100644 --- a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx @@ -16,9 +16,12 @@ #include "cmCMakePresetsGraphInternal.h" #include "cmJSONHelpers.h" +#include "CTest/cmCTestTypes.h" + namespace { using ReadFileResult = cmCMakePresetsGraph::ReadFileResult; using TestPreset = cmCMakePresetsGraph::TestPreset; +using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>; ReadFileResult TestPresetOutputVerbosityHelper( TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value) @@ -51,14 +54,43 @@ ReadFileResult TestPresetOutputVerbosityHelper( } auto const TestPresetOptionalOutputVerbosityHelper = - cmJSONOptionalHelper<TestPreset::OutputOptions::VerbosityEnum, - ReadFileResult>(ReadFileResult::READ_OK, - TestPresetOutputVerbosityHelper); + JSONHelperBuilder::Optional<TestPreset::OutputOptions::VerbosityEnum>( + ReadFileResult::READ_OK, TestPresetOutputVerbosityHelper); + +ReadFileResult TestPresetOutputTruncationHelper( + cm::optional<cmCTestTypes::TruncationMode>& out, const Json::Value* value) +{ + if (!value) { + out = cm::nullopt; + return ReadFileResult::READ_OK; + } + + if (!value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "tail") { + out = cmCTestTypes::TruncationMode::Tail; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "middle") { + out = cmCTestTypes::TruncationMode::Middle; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "head") { + out = cmCTestTypes::TruncationMode::Head; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} auto const TestPresetOptionalOutputHelper = - cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::OutputOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::OutputOptions, ReadFileResult>( + JSONHelperBuilder::Object<TestPreset::OutputOptions>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) @@ -83,16 +115,17 @@ auto const TestPresetOptionalOutputHelper = .Bind("maxFailedTestOutputSize"_s, &TestPreset::OutputOptions::MaxFailedTestOutputSize, cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false) + .Bind("testOutputTruncation"_s, + &TestPreset::OutputOptions::TestOutputTruncation, + TestPresetOutputTruncationHelper, false) .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth, cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)); auto const TestPresetOptionalFilterIncludeIndexObjectHelper = - cmJSONOptionalHelper<TestPreset::IncludeOptions::IndexOptions, - ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::IncludeOptions::IndexOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::IncludeOptions::IndexOptions, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object<TestPreset::IncludeOptions::IndexOptions>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start, cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false) .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End, @@ -126,9 +159,9 @@ ReadFileResult TestPresetOptionalFilterIncludeIndexHelper( } auto const TestPresetOptionalFilterIncludeHelper = - cmJSONOptionalHelper<TestPreset::IncludeOptions, ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::IncludeOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::IncludeOptions, ReadFileResult>( + JSONHelperBuilder::Object<TestPreset::IncludeOptions>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("name"_s, &TestPreset::IncludeOptions::Name, cmCMakePresetsGraphInternal::PresetStringHelper, false) @@ -140,12 +173,10 @@ auto const TestPresetOptionalFilterIncludeHelper = cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)); auto const TestPresetOptionalFilterExcludeFixturesHelper = - cmJSONOptionalHelper<TestPreset::ExcludeOptions::FixturesOptions, - ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::ExcludeOptions::FixturesOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExcludeOptions::FixturesOptions, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object<TestPreset::ExcludeOptions::FixturesOptions>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any, cmCMakePresetsGraphInternal::PresetStringHelper, false) .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup, @@ -154,9 +185,9 @@ auto const TestPresetOptionalFilterExcludeFixturesHelper = cmCMakePresetsGraphInternal::PresetStringHelper, false)); auto const TestPresetOptionalFilterExcludeHelper = - cmJSONOptionalHelper<TestPreset::ExcludeOptions, ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::ExcludeOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExcludeOptions, ReadFileResult>( + JSONHelperBuilder::Object<TestPreset::ExcludeOptions>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("name"_s, &TestPreset::ExcludeOptions::Name, cmCMakePresetsGraphInternal::PresetStringHelper, false) @@ -186,9 +217,8 @@ ReadFileResult TestPresetExecutionShowOnlyHelper( } auto const TestPresetOptionalExecutionShowOnlyHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions::ShowOnlyEnum, - ReadFileResult>(ReadFileResult::READ_OK, - TestPresetExecutionShowOnlyHelper); + JSONHelperBuilder::Optional<TestPreset::ExecutionOptions::ShowOnlyEnum>( + ReadFileResult::READ_OK, TestPresetExecutionShowOnlyHelper); ReadFileResult TestPresetExecutionModeHelper( TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out, @@ -221,12 +251,10 @@ ReadFileResult TestPresetExecutionModeHelper( } auto const TestPresetOptionalExecutionRepeatHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions::RepeatOptions, - ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::ExecutionOptions::RepeatOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExecutionOptions::RepeatOptions, - ReadFileResult>(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) + JSONHelperBuilder::Object<TestPreset::ExecutionOptions::RepeatOptions>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode, TestPresetExecutionModeHelper, true) .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count, @@ -264,14 +292,13 @@ ReadFileResult TestPresetExecutionNoTestsActionHelper( } auto const TestPresetOptionalExecutionNoTestsActionHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions::NoTestsActionEnum, - ReadFileResult>(ReadFileResult::READ_OK, - TestPresetExecutionNoTestsActionHelper); + JSONHelperBuilder::Optional<TestPreset::ExecutionOptions::NoTestsActionEnum>( + ReadFileResult::READ_OK, TestPresetExecutionNoTestsActionHelper); auto const TestPresetExecutionHelper = - cmJSONOptionalHelper<TestPreset::ExecutionOptions, ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::ExecutionOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::ExecutionOptions, ReadFileResult>( + JSONHelperBuilder::Object<TestPreset::ExecutionOptions>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) @@ -299,9 +326,9 @@ auto const TestPresetExecutionHelper = TestPresetOptionalExecutionNoTestsActionHelper, false)); auto const TestPresetFilterHelper = - cmJSONOptionalHelper<TestPreset::FilterOptions, ReadFileResult>( + JSONHelperBuilder::Optional<TestPreset::FilterOptions>( ReadFileResult::READ_OK, - cmJSONObjectHelper<TestPreset::FilterOptions, ReadFileResult>( + JSONHelperBuilder::Object<TestPreset::FilterOptions>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) .Bind("include"_s, &TestPreset::FilterOptions::Include, TestPresetOptionalFilterIncludeHelper, false) @@ -309,8 +336,8 @@ auto const TestPresetFilterHelper = TestPresetOptionalFilterExcludeHelper, false)); auto const TestPresetHelper = - cmJSONObjectHelper<TestPreset, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + JSONHelperBuilder::Object<TestPreset>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &TestPreset::Name, cmCMakePresetsGraphInternal::PresetStringHelper) .Bind("inherits"_s, &TestPreset::Inherits, @@ -351,7 +378,7 @@ namespace cmCMakePresetsGraphInternal { cmCMakePresetsGraph::ReadFileResult TestPresetsHelper( std::vector<cmCMakePresetsGraph::TestPreset>& out, const Json::Value* value) { - static auto const helper = cmJSONVectorHelper<TestPreset, ReadFileResult>( + static auto const helper = JSONHelperBuilder::Vector<TestPreset>( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper); diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 1b11f20..abec968 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -432,7 +432,7 @@ static int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs, lffArgs.emplace_back(args[i], cmListFileArgument::Quoted, 0); } - cmListFileFunction lff{ name, 0, std::move(lffArgs) }; + cmListFileFunction lff{ name, 0, 0, std::move(lffArgs) }; cmExecutionStatus status(*mf); return mf->ExecuteCommand(lff, status); } diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index a1e920e..710b4d7 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2036,6 +2036,13 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, "Invalid value for '--test-output-size-failed': " << args[i] << "\n"); } + } else if (this->CheckArgument(arg, "--test-output-truncation"_s) && + i < args.size() - 1) { + i++; + if (!this->Impl->TestHandler.SetTestOutputTruncation(args[i])) { + errormsg = "Invalid value for '--test-output-truncation': " + args[i]; + return false; + } } else if (this->CheckArgument(arg, "-N"_s, "--show-only")) { this->Impl->ShowOnly = true; } else if (cmHasLiteralPrefix(arg, "--show-only=")) { @@ -2464,6 +2471,11 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, *expandedPreset->Output->MaxFailedTestOutputSize); } + if (expandedPreset->Output->TestOutputTruncation) { + this->Impl->TestHandler.TestOutputTruncation = + *expandedPreset->Output->TestOutputTruncation; + } + if (expandedPreset->Output->MaxTestNameWidth) { this->Impl->MaxTestNameWidth = *expandedPreset->Output->MaxTestNameWidth; } diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h index 72ab045..33c91bc 100644 --- a/Source/cmCommandLineArgument.h +++ b/Source/cmCommandLineArgument.h @@ -201,7 +201,57 @@ struct cmCommandLineArgument return (parseState == ParseMode::Valid); } + template <typename... Values> + static std::function<FunctionSignature> setToTrue(Values&&... values) + { + return ArgumentLambdaHelper<FunctionSignature>::generateSetToTrue( + std::forward<Values>(values)...); + } + + template <typename... Values> + static std::function<FunctionSignature> setToValue(Values&&... values) + { + return ArgumentLambdaHelper<FunctionSignature>::generateSetToValue( + std::forward<Values>(values)...); + } + private: + template <typename T> + class ArgumentLambdaHelper; + + template <typename... CallState> + class ArgumentLambdaHelper<bool(const std::string&, CallState...)> + { + public: + static std::function<bool(const std::string&, CallState...)> + generateSetToTrue(bool& value1) + { + return [&value1](const std::string&, CallState&&...) -> bool { + value1 = true; + return true; + }; + } + + static std::function<bool(const std::string&, CallState...)> + generateSetToTrue(bool& value1, bool& value2) + { + return [&value1, &value2](const std::string&, CallState&&...) -> bool { + value1 = true; + value2 = true; + return true; + }; + } + + static std::function<bool(const std::string&, CallState...)> + generateSetToValue(std::string& value1) + { + return [&value1](const std::string& arg, CallState&&...) -> bool { + value1 = arg; + return true; + }; + } + }; + std::string extract_single_value(std::string const& input, ParseMode& parseState) const { diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 129ef4b..b172c20 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCommonTargetGenerator.h" -#include <set> +#include <algorithm> #include <sstream> #include <utility> @@ -13,9 +13,11 @@ #include "cmLocalCommonGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmRange.h" #include "cmSourceFile.h" +#include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" @@ -321,3 +323,29 @@ std::string cmCommonTargetGenerator::GetLinkerLauncher( } return std::string(); } + +bool cmCommonTargetGenerator::HaveRequiredLanguages( + const std::vector<cmSourceFile const*>& sources, + std::set<std::string>& languagesNeeded) const +{ + for (cmSourceFile const* sf : sources) { + languagesNeeded.insert(sf->GetLanguage()); + } + + auto* makefile = this->Makefile; + auto* state = makefile->GetState(); + auto unary = [&state, &makefile](const std::string& lang) -> bool { + const bool valid = state->GetLanguageEnabled(lang); + if (!valid) { + makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The language ", lang, + " was requested for compilation but was not enabled." + " To enable a language it needs to be specified in a" + " 'project' or 'enable_language' command in the root" + " CMakeLists.txt")); + } + return valid; + }; + return std::all_of(languagesNeeded.cbegin(), languagesNeeded.cend(), unary); +} diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 5aba1c6..1b804b4 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> +#include <set> #include <string> #include <vector> @@ -74,6 +75,9 @@ protected: std::string GetLinkerLauncher(const std::string& config); + bool HaveRequiredLanguages(const std::vector<cmSourceFile const*>& sources, + std::set<std::string>& languagesNeeded) const; + private: using ByLanguageMap = std::map<std::string, std::string>; struct ByConfig diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 370ddff..8cbdcaa 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -11,13 +11,18 @@ #include <utility> #include <cm/memory> +#include <cm/string_view> +#include <cmext/string_view> #include "cmComputeComponentGraph.h" +#include "cmGeneratorExpression.h" +#include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmRange.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -174,8 +179,62 @@ items that we know the linker will re-use automatically (shared libs). */ +namespace { +// LINK_LIBRARY helpers +const auto LL_BEGIN = "<LINK_LIBRARY:"_s; +const auto LL_END = "</LINK_LIBRARY:"_s; + +inline std::string ExtractFeature(std::string const& item) +{ + return item.substr(LL_BEGIN.length(), + item.find('>', LL_BEGIN.length()) - LL_BEGIN.length()); +} + +bool IsFeatureSupported(cmMakefile* makefile, std::string const& linkLanguage, + std::string const& feature) +{ + auto featureSupported = cmStrCat( + "CMAKE_", linkLanguage, "_LINK_LIBRARY_USING_", feature, "_SUPPORTED"); + if (makefile->GetDefinition(featureSupported).IsOn()) { + return true; + } + + featureSupported = + cmStrCat("CMAKE_LINK_LIBRARY_USING_", feature, "_SUPPORTED"); + return makefile->GetDefinition(featureSupported).IsOn(); +} + +// LINK_GROUP helpers +const auto LG_BEGIN = "<LINK_GROUP:"_s; +const auto LG_END = "</LINK_GROUP:"_s; + +inline std::string ExtractGroupFeature(std::string const& item) +{ + return item.substr(LG_BEGIN.length(), + item.find(':', LG_BEGIN.length()) - LG_BEGIN.length()); +} + +bool IsGroupFeatureSupported(cmMakefile* makefile, + std::string const& linkLanguage, + std::string const& feature) +{ + auto featureSupported = cmStrCat( + "CMAKE_", linkLanguage, "_LINK_GROUP_USING_", feature, "_SUPPORTED"); + if (makefile->GetDefinition(featureSupported).IsOn()) { + return true; + } + + featureSupported = + cmStrCat("CMAKE_LINK_GROUP_USING_", feature, "_SUPPORTED"); + return makefile->GetDefinition(featureSupported).IsOn(); +} +} + +const std::string cmComputeLinkDepends::LinkEntry::DEFAULT = "DEFAULT"; + cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target, - const std::string& config) + const std::string& config, + const std::string& linkLanguage) { // Store context information. this->Target = target; @@ -183,6 +242,50 @@ cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target, this->GlobalGenerator = this->Target->GetLocalGenerator()->GetGlobalGenerator(); this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance(); + this->LinkLanguage = linkLanguage; + + // target oriented feature override property takes precedence over + // global override property + cm::string_view lloPrefix = "LINK_LIBRARY_OVERRIDE_"_s; + auto const& keys = this->Target->GetPropertyKeys(); + std::for_each( + keys.cbegin(), keys.cend(), + [this, &lloPrefix, &config, &linkLanguage](std::string const& key) { + if (cmHasPrefix(key, lloPrefix)) { + if (cmValue feature = this->Target->GetProperty(key)) { + if (!feature->empty() && key.length() > lloPrefix.length()) { + auto item = key.substr(lloPrefix.length()); + cmGeneratorExpressionDAGChecker dag{ this->Target->GetBacktrace(), + this->Target, + "LINK_LIBRARY_OVERRIDE", + nullptr, nullptr }; + auto overrideFeature = cmGeneratorExpression::Evaluate( + feature, this->Target->GetLocalGenerator(), config, this->Target, + &dag, this->Target, linkLanguage); + this->LinkLibraryOverride.emplace(item, overrideFeature); + } + } + } + }); + // global override property + if (cmValue linkLibraryOverride = + this->Target->GetProperty("LINK_LIBRARY_OVERRIDE")) { + cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, + "LINK_LIBRARY_OVERRIDE", nullptr, + nullptr }; + auto overrideValue = cmGeneratorExpression::Evaluate( + linkLibraryOverride, target->GetLocalGenerator(), config, target, &dag, + target, linkLanguage); + + auto overrideList = cmTokenize(overrideValue, ","_s); + if (overrideList.size() >= 2) { + auto const& feature = overrideList.front(); + for_each(overrideList.cbegin() + 1, overrideList.cend(), + [this, &feature](std::string const& item) { + this->LinkLibraryOverride.emplace(item, feature); + }); + } + } // The configuration being linked. this->HasConfig = !config.empty(); @@ -234,6 +337,11 @@ cmComputeLinkDepends::Compute() // Infer dependencies of targets for which they were not known. this->InferDependencies(); + // finalize groups dependencies + // All dependencies which are raw items must be replaced by the group + // it belongs to, if any. + this->UpdateGroupDependencies(); + // Cleanup the constraint graph. this->CleanConstraintGraph(); @@ -248,8 +356,21 @@ cmComputeLinkDepends::Compute() this->DisplayConstraintGraph(); } + // Compute the DAG of strongly connected components. The algorithm + // used by cmComputeComponentGraph should identify the components in + // the same order in which the items were originally discovered in + // the BFS. This should preserve the original order when no + // constraints disallow it. + this->CCG = + cm::make_unique<cmComputeComponentGraph>(this->EntryConstraintGraph); + this->CCG->Compute(); + + if (!this->CheckCircularDependencies()) { + return this->FinalLinkEntries; + } + // Compute the final ordering. - this->OrderLinkEntires(); + this->OrderLinkEntries(); // Compute the final set of link entries. // Iterate in reverse order so we can keep only the last occurrence @@ -273,6 +394,29 @@ cmComputeLinkDepends::Compute() // Reverse the resulting order since we iterated in reverse. std::reverse(this->FinalLinkEntries.begin(), this->FinalLinkEntries.end()); + // Expand group items + if (!this->GroupItems.empty()) { + for (const auto& group : this->GroupItems) { + const LinkEntry& groupEntry = this->EntryList[group.first]; + auto it = this->FinalLinkEntries.begin(); + while (true) { + it = std::find_if(it, this->FinalLinkEntries.end(), + [&groupEntry](const LinkEntry& entry) -> bool { + return groupEntry.Item == entry.Item; + }); + if (it == this->FinalLinkEntries.end()) { + break; + } + it->Item.Value = "</LINK_GROUP>"; + for (auto i = group.second.rbegin(); i != group.second.rend(); ++i) { + it = this->FinalLinkEntries.insert(it, this->EntryList[*i]); + } + it = this->FinalLinkEntries.insert(it, groupEntry); + it->Item.Value = "<LINK_GROUP>"; + } + } + } + // Display the final set. if (this->DebugMode) { this->DisplayFinalEntries(); @@ -281,76 +425,91 @@ cmComputeLinkDepends::Compute() return this->FinalLinkEntries; } -std::map<cmLinkItem, int>::iterator cmComputeLinkDepends::AllocateLinkEntry( - cmLinkItem const& item) +std::string const& cmComputeLinkDepends::GetCurrentFeature( + std::string const& item, std::string const& defaultFeature) const +{ + auto it = this->LinkLibraryOverride.find(item); + return it == this->LinkLibraryOverride.end() ? defaultFeature : it->second; +} + +std::pair<std::map<cmLinkItem, int>::iterator, bool> +cmComputeLinkDepends::AllocateLinkEntry(cmLinkItem const& item) { std::map<cmLinkItem, int>::value_type index_entry( item, static_cast<int>(this->EntryList.size())); - auto lei = this->LinkEntryIndex.insert(index_entry).first; - this->EntryList.emplace_back(); - this->InferredDependSets.emplace_back(); - this->EntryConstraintGraph.emplace_back(); + auto lei = this->LinkEntryIndex.insert(index_entry); + if (lei.second) { + this->EntryList.emplace_back(); + this->InferredDependSets.emplace_back(); + this->EntryConstraintGraph.emplace_back(); + } return lei; } -int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) +std::pair<int, bool> cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item, + int groupIndex) { + // Allocate a spot for the item entry. + auto lei = this->AllocateLinkEntry(item); + // Check if the item entry has already been added. - auto lei = this->LinkEntryIndex.find(item); - if (lei != this->LinkEntryIndex.end()) { + if (!lei.second) { // Yes. We do not need to follow the item's dependencies again. - return lei->second; + return { lei.first->second, false }; } - // Allocate a spot for the item entry. - lei = this->AllocateLinkEntry(item); - // Initialize the item entry. - int index = lei->second; + int index = lei.first->second; LinkEntry& entry = this->EntryList[index]; entry.Item = BT<std::string>(item.AsStr(), item.Backtrace); entry.Target = item.Target; - entry.IsFlag = (!entry.Target && entry.Item.Value[0] == '-' && - entry.Item.Value[1] != 'l' && - entry.Item.Value.substr(0, 10) != "-framework"); + if (!entry.Target && entry.Item.Value[0] == '-' && + entry.Item.Value[1] != 'l' && + entry.Item.Value.substr(0, 10) != "-framework") { + entry.Kind = LinkEntry::Flag; + } else if (cmHasPrefix(entry.Item.Value, LG_BEGIN) && + cmHasSuffix(entry.Item.Value, '>')) { + entry.Kind = LinkEntry::Group; + } - // If the item has dependencies queue it to follow them. - if (entry.Target) { - // Target dependencies are always known. Follow them. - BFSEntry qe = { index, nullptr }; - this->BFSQueue.push(qe); - } else { - // Look for an old-style <item>_LIB_DEPENDS variable. - std::string var = cmStrCat(entry.Item.Value, "_LIB_DEPENDS"); - if (cmValue val = this->Makefile->GetDefinition(var)) { - // The item dependencies are known. Follow them. - BFSEntry qe = { index, val->c_str() }; + if (entry.Kind != LinkEntry::Group) { + // If the item has dependencies queue it to follow them. + if (entry.Target) { + // Target dependencies are always known. Follow them. + BFSEntry qe = { index, groupIndex, nullptr }; this->BFSQueue.push(qe); - } else if (!entry.IsFlag) { - // The item dependencies are not known. We need to infer them. - this->InferredDependSets[index].Initialized = true; + } else { + // Look for an old-style <item>_LIB_DEPENDS variable. + std::string var = cmStrCat(entry.Item.Value, "_LIB_DEPENDS"); + if (cmValue val = this->Makefile->GetDefinition(var)) { + // The item dependencies are known. Follow them. + BFSEntry qe = { index, groupIndex, val->c_str() }; + this->BFSQueue.push(qe); + } else if (entry.Kind != LinkEntry::Flag) { + // The item dependencies are not known. We need to infer them. + this->InferredDependSets[index].Initialized = true; + } } } - return index; + return { index, true }; } void cmComputeLinkDepends::AddLinkObject(cmLinkItem const& item) { + // Allocate a spot for the item entry. + auto lei = this->AllocateLinkEntry(item); + // Check if the item entry has already been added. - auto lei = this->LinkEntryIndex.find(item); - if (lei != this->LinkEntryIndex.end()) { + if (!lei.second) { return; } - // Allocate a spot for the item entry. - lei = this->AllocateLinkEntry(item); - // Initialize the item entry. - int index = lei->second; + int index = lei.first->second; LinkEntry& entry = this->EntryList[index]; entry.Item = BT<std::string>(item.AsStr(), item.Backtrace); - entry.IsObject = true; + entry.Kind = LinkEntry::Object; // Record explicitly linked object files separately. this->ObjectEntries.emplace_back(index); @@ -359,8 +518,8 @@ void cmComputeLinkDepends::AddLinkObject(cmLinkItem const& item) void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe) { // Get this entry representation. - int depender_index = qe.Index; - LinkEntry const& entry = this->EntryList[depender_index]; + int depender_index = qe.GroupIndex == -1 ? qe.Index : qe.GroupIndex; + LinkEntry const& entry = this->EntryList[qe.Index]; // Follow the item's dependencies. if (entry.Target) { @@ -423,25 +582,24 @@ void cmComputeLinkDepends::QueueSharedDependencies( void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) { - // Check if the target already has an entry. - auto lei = this->LinkEntryIndex.find(dep.Item); - if (lei == this->LinkEntryIndex.end()) { - // Allocate a spot for the item entry. - lei = this->AllocateLinkEntry(dep.Item); + // Allocate a spot for the item entry. + auto lei = this->AllocateLinkEntry(dep.Item); + int index = lei.first->second; + // Check if the target does not already has an entry. + if (lei.second) { // Initialize the item entry. - LinkEntry& entry = this->EntryList[lei->second]; + LinkEntry& entry = this->EntryList[index]; entry.Item = BT<std::string>(dep.Item.AsStr(), dep.Item.Backtrace); entry.Target = dep.Item.Target; // This item was added specifically because it is a dependent // shared library. It may get special treatment // in cmComputeLinkInformation. - entry.IsSharedDep = true; + entry.Kind = LinkEntry::SharedDep; } // Get the link entry for this target. - int index = lei->second; LinkEntry& entry = this->EntryList[index]; // This shared library dependency must follow the item that listed @@ -519,8 +677,8 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, void cmComputeLinkDepends::AddDirectLinkEntries() { // Add direct link dependencies in this configuration. - cmLinkImplementation const* impl = - this->Target->GetLinkImplementation(this->Config); + cmLinkImplementation const* impl = this->Target->GetLinkImplementation( + this->Config, cmGeneratorTarget::LinkInterfaceFor::Link); this->AddLinkEntries(-1, impl->Libraries); this->AddLinkObjects(impl->Objects); @@ -541,6 +699,11 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, { // Track inferred dependency sets implied by this list. std::map<int, DependSet> dependSets; + std::string feature = LinkEntry::DEFAULT; + + bool inGroup = false; + std::pair<int, bool> groupIndex{ -1, false }; + std::vector<int> groupItems; // Loop over the libraries linked directly by the depender. for (T const& l : libs) { @@ -551,35 +714,233 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, continue; } + if (cmHasPrefix(item.AsStr(), LL_BEGIN) && + cmHasSuffix(item.AsStr(), '>')) { + feature = ExtractFeature(item.AsStr()); + // emit a warning if an undefined feature is used as part of + // an imported target + if (depender_index >= 0) { + const auto& depender = this->EntryList[depender_index]; + if (depender.Target != nullptr && depender.Target->IsImported() && + !IsFeatureSupported(this->Makefile, this->LinkLanguage, feature)) { + this->CMakeInstance->IssueMessage( + MessageType::AUTHOR_ERROR, + cmStrCat("The 'IMPORTED' target '", depender.Target->GetName(), + "' uses the generator-expression '$<LINK_LIBRARY>' with " + "the feature '", + feature, + "', which is undefined or unsupported.\nDid you miss to " + "define it by setting variables \"CMAKE_", + this->LinkLanguage, "_LINK_LIBRARY_USING_", feature, + "\" and \"CMAKE_", this->LinkLanguage, + "_LINK_LIBRARY_USING_", feature, "_SUPPORTED\"?"), + this->Target->GetBacktrace()); + } + } + continue; + } + if (cmHasPrefix(item.AsStr(), LL_END) && cmHasSuffix(item.AsStr(), '>')) { + feature = LinkEntry::DEFAULT; + continue; + } + + if (cmHasPrefix(item.AsStr(), LG_BEGIN) && + cmHasSuffix(item.AsStr(), '>')) { + groupIndex = this->AddLinkEntry(item); + if (groupIndex.second) { + LinkEntry& entry = this->EntryList[groupIndex.first]; + entry.Feature = ExtractGroupFeature(item.AsStr()); + } + inGroup = true; + if (depender_index >= 0) { + this->EntryConstraintGraph[depender_index].emplace_back( + groupIndex.first, false, false, cmListFileBacktrace()); + } else { + // This is a direct dependency of the target being linked. + this->OriginalEntries.push_back(groupIndex.first); + } + continue; + } + + int dependee_index; + + if (cmHasPrefix(item.AsStr(), LG_END) && cmHasSuffix(item.AsStr(), '>')) { + dependee_index = groupIndex.first; + if (groupIndex.second) { + this->GroupItems.emplace(groupIndex.first, groupItems); + } + inGroup = false; + groupIndex = std::make_pair(-1, false); + groupItems.clear(); + continue; + } + + if (depender_index >= 0 && inGroup) { + const auto& depender = this->EntryList[depender_index]; + const auto& groupFeature = this->EntryList[groupIndex.first].Feature; + if (depender.Target != nullptr && depender.Target->IsImported() && + !IsGroupFeatureSupported(this->Makefile, this->LinkLanguage, + groupFeature)) { + this->CMakeInstance->IssueMessage( + MessageType::AUTHOR_ERROR, + cmStrCat("The 'IMPORTED' target '", depender.Target->GetName(), + "' uses the generator-expression '$<LINK_GROUP>' with " + "the feature '", + groupFeature, + "', which is undefined or unsupported.\nDid you miss to " + "define it by setting variables \"CMAKE_", + this->LinkLanguage, "_LINK_GROUP_USING_", groupFeature, + "\" and \"CMAKE_", this->LinkLanguage, "_LINK_GROUP_USING_", + groupFeature, "_SUPPORTED\"?"), + this->Target->GetBacktrace()); + } + } + // Add a link entry for this item. - int dependee_index = this->AddLinkEntry(l); + auto ale = this->AddLinkEntry(item, groupIndex.first); + dependee_index = ale.first; + LinkEntry& entry = this->EntryList[dependee_index]; + auto const& itemFeature = + this->GetCurrentFeature(entry.Item.Value, feature); + if (inGroup && ale.second && entry.Target != nullptr && + (entry.Target->GetType() == cmStateEnums::TargetType::OBJECT_LIBRARY || + entry.Target->GetType() == + cmStateEnums::TargetType::INTERFACE_LIBRARY)) { + const auto& groupFeature = this->EntryList[groupIndex.first].Feature; + this->CMakeInstance->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat( + "The feature '", groupFeature, + "', specified as part of a generator-expression " + "'$", + LG_BEGIN, groupFeature, ">', will not be applied to the ", + (entry.Target->GetType() == cmStateEnums::TargetType::OBJECT_LIBRARY + ? "OBJECT" + : "INTERFACE"), + " library '", entry.Item.Value, "'."), + this->Target->GetBacktrace()); + } + if (itemFeature != LinkEntry::DEFAULT) { + if (ale.second) { + // current item not yet defined + if (entry.Target != nullptr && + (entry.Target->GetType() == + cmStateEnums::TargetType::OBJECT_LIBRARY || + entry.Target->GetType() == + cmStateEnums::TargetType::INTERFACE_LIBRARY)) { + this->CMakeInstance->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat("The feature '", feature, + "', specified as part of a generator-expression " + "'$", + LL_BEGIN, feature, ">', will not be applied to the ", + (entry.Target->GetType() == + cmStateEnums::TargetType::OBJECT_LIBRARY + ? "OBJECT" + : "INTERFACE"), + " library '", entry.Item.Value, "'."), + this->Target->GetBacktrace()); + } else { + entry.Feature = itemFeature; + } + } + } - // The dependee must come after the depender. - if (depender_index >= 0) { - this->EntryConstraintGraph[depender_index].emplace_back( - dependee_index, false, false, cmListFileBacktrace()); - } else { - // This is a direct dependency of the target being linked. - this->OriginalEntries.push_back(dependee_index); - } - - // Update the inferred dependencies for earlier items. - for (auto& dependSet : dependSets) { - // Add this item to the inferred dependencies of other items. - // Target items are never inferred dependees because unknown - // items are outside libraries that should not be depending on - // targets. - if (!this->EntryList[dependee_index].Target && - !this->EntryList[dependee_index].IsFlag && - dependee_index != dependSet.first) { - dependSet.second.insert(dependee_index); + bool supportedItem = entry.Target == nullptr || + (entry.Target->GetType() != cmStateEnums::TargetType::OBJECT_LIBRARY && + entry.Target->GetType() != cmStateEnums::TargetType::INTERFACE_LIBRARY); + + if (supportedItem) { + if (inGroup) { + const auto& currentFeature = this->EntryList[groupIndex.first].Feature; + for (const auto& g : this->GroupItems) { + const auto& groupFeature = this->EntryList[g.first].Feature; + if (groupFeature == currentFeature) { + continue; + } + if (std::find(g.second.cbegin(), g.second.cend(), dependee_index) != + g.second.cend()) { + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Impossible to link target '", this->Target->GetName(), + "' because the link item '", entry.Item.Value, + "', specified with the group feature '", currentFeature, + '\'', ", has already occurred with the feature '", + groupFeature, '\'', ", which is not allowed."), + this->Target->GetBacktrace()); + continue; + } + } + } + if (entry.Feature != itemFeature) { + // incompatibles features occurred + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Impossible to link target '", this->Target->GetName(), + "' because the link item '", entry.Item.Value, + "', specified ", + (itemFeature == LinkEntry::DEFAULT + ? "without any feature or 'DEFAULT' feature" + : cmStrCat("with the feature '", itemFeature, '\'')), + ", has already occurred ", + (entry.Feature == LinkEntry::DEFAULT + ? "without any feature or 'DEFAULT' feature" + : cmStrCat("with the feature '", entry.Feature, '\'')), + ", which is not allowed."), + this->Target->GetBacktrace()); } } - // If this item needs to have dependencies inferred, do so. - if (this->InferredDependSets[dependee_index].Initialized) { - // Make sure an entry exists to hold the set for the item. - dependSets[dependee_index]; + if (inGroup) { + // store item index for dependencies handling + groupItems.push_back(dependee_index); + } else { + std::vector<int> indexes; + bool entryHandled = false; + // search any occurrence of the library in already defined groups + for (const auto& group : this->GroupItems) { + for (auto index : group.second) { + if (entry.Item.Value == this->EntryList[index].Item.Value) { + indexes.push_back(group.first); + entryHandled = true; + break; + } + } + } + if (!entryHandled) { + indexes.push_back(dependee_index); + } + + for (auto index : indexes) { + // The dependee must come after the depender. + if (depender_index >= 0) { + this->EntryConstraintGraph[depender_index].emplace_back( + index, false, false, cmListFileBacktrace()); + } else { + // This is a direct dependency of the target being linked. + this->OriginalEntries.push_back(index); + } + + // Update the inferred dependencies for earlier items. + for (auto& dependSet : dependSets) { + // Add this item to the inferred dependencies of other items. + // Target items are never inferred dependees because unknown + // items are outside libraries that should not be depending on + // targets. + if (!this->EntryList[index].Target && + this->EntryList[index].Kind != LinkEntry::Flag && + this->EntryList[index].Kind != LinkEntry::Group && + dependee_index != dependSet.first) { + dependSet.second.insert(index); + } + } + + // If this item needs to have dependencies inferred, do so. + if (this->InferredDependSets[index].Initialized) { + // Make sure an entry exists to hold the set for the item. + dependSets[index]; + } + } } } @@ -642,6 +1003,36 @@ void cmComputeLinkDepends::InferDependencies() } } +void cmComputeLinkDepends::UpdateGroupDependencies() +{ + if (this->GroupItems.empty()) { + return; + } + + // Walks through all entries of the constraint graph to replace dependencies + // over raw items by the group it belongs to, if any. + for (auto& edgeList : this->EntryConstraintGraph) { + for (auto& edge : edgeList) { + int index = edge; + if (this->EntryList[index].Kind == LinkEntry::Group || + this->EntryList[index].Kind == LinkEntry::Flag || + this->EntryList[index].Kind == LinkEntry::Object) { + continue; + } + // search the item in the defined groups + for (const auto& groupItems : this->GroupItems) { + auto pos = std::find(groupItems.second.cbegin(), + groupItems.second.cend(), index); + if (pos != groupItems.second.cend()) { + // replace lib dependency by the group it belongs to + edge = cmGraphEdge{ groupItems.first, false, false, + cmListFileBacktrace() }; + } + } + } + } +} + void cmComputeLinkDepends::CleanConstraintGraph() { for (cmGraphEdgeList& edgeList : this->EntryConstraintGraph) { @@ -655,6 +1046,76 @@ void cmComputeLinkDepends::CleanConstraintGraph() } } +bool cmComputeLinkDepends::CheckCircularDependencies() const +{ + std::vector<NodeList> const& components = this->CCG->GetComponents(); + int nc = static_cast<int>(components.size()); + for (int c = 0; c < nc; ++c) { + // Get the current component. + NodeList const& nl = components[c]; + + // Skip trivial components. + if (nl.size() < 2) { + continue; + } + + // no group must be evolved + bool cycleDetected = false; + for (int ni : nl) { + if (this->EntryList[ni].Kind == LinkEntry::Group) { + cycleDetected = true; + break; + } + } + if (!cycleDetected) { + continue; + } + + // Construct the error message. + auto formatItem = [](LinkEntry const& entry) -> std::string { + if (entry.Kind == LinkEntry::Group) { + auto items = + entry.Item.Value.substr(entry.Item.Value.find(':', 12) + 1); + items.pop_back(); + std::replace(items.begin(), items.end(), '|', ','); + return cmStrCat("group \"", ExtractGroupFeature(entry.Item.Value), + ":{", items, "}\""); + } + return cmStrCat('"', entry.Item.Value, '"'); + }; + + std::ostringstream e; + e << "The inter-target dependency graph, for the target \"" + << this->Target->GetName() + << "\", contains the following strongly connected component " + "(cycle):\n"; + std::vector<int> const& cmap = this->CCG->GetComponentMap(); + for (int i : nl) { + // Get the depender. + LinkEntry const& depender = this->EntryList[i]; + + // Describe the depender. + e << " " << formatItem(depender) << "\n"; + + // List its dependencies that are inside the component. + EdgeList const& el = this->EntryConstraintGraph[i]; + for (cmGraphEdge const& ni : el) { + int j = ni; + if (cmap[j] == c) { + LinkEntry const& dependee = this->EntryList[j]; + e << " depends on " << formatItem(dependee) << "\n"; + } + } + } + this->CMakeInstance->IssueMessage(MessageType::FATAL_ERROR, e.str(), + this->Target->GetBacktrace()); + + return false; + } + + return true; +} + void cmComputeLinkDepends::DisplayConstraintGraph() { // Display the graph nodes and their edges. @@ -667,17 +1128,8 @@ void cmComputeLinkDepends::DisplayConstraintGraph() fprintf(stderr, "%s\n", e.str().c_str()); } -void cmComputeLinkDepends::OrderLinkEntires() +void cmComputeLinkDepends::OrderLinkEntries() { - // Compute the DAG of strongly connected components. The algorithm - // used by cmComputeComponentGraph should identify the components in - // the same order in which the items were originally discovered in - // the BFS. This should preserve the original order when no - // constraints disallow it. - this->CCG = - cm::make_unique<cmComputeComponentGraph>(this->EntryConstraintGraph); - this->CCG->Compute(); - // The component graph is guaranteed to be acyclic. Start a DFS // from every entry to compute a topological order for the // components. @@ -867,12 +1319,23 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl) void cmComputeLinkDepends::DisplayFinalEntries() { fprintf(stderr, "target [%s] links to:\n", this->Target->GetName().c_str()); + char space[] = " "; + int count = 2; for (LinkEntry const& lei : this->FinalLinkEntries) { - if (lei.Target) { - fprintf(stderr, " target [%s]\n", lei.Target->GetName().c_str()); + if (lei.Kind == LinkEntry::Group) { + fprintf(stderr, " %s group", + lei.Item.Value == "<LINK_GROUP>" ? "start" : "end"); + count = lei.Item.Value == "<LINK_GROUP>" ? 4 : 2; + } else if (lei.Target) { + fprintf(stderr, "%*starget [%s]", count, space, + lei.Target->GetName().c_str()); } else { - fprintf(stderr, " item [%s]\n", lei.Item.Value.c_str()); + fprintf(stderr, "%*sitem [%s]", count, space, lei.Item.Value.c_str()); + } + if (lei.Feature != LinkEntry::DEFAULT) { + fprintf(stderr, ", feature [%s]", lei.Feature.c_str()); } + fprintf(stderr, "\n"); } fprintf(stderr, "\n"); } diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 72316f1..8cc916a 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -9,6 +9,7 @@ #include <queue> #include <set> #include <string> +#include <utility> #include <vector> #include "cmGraphAdjacencyList.h" @@ -29,7 +30,8 @@ class cmComputeLinkDepends { public: cmComputeLinkDepends(cmGeneratorTarget const* target, - const std::string& config); + const std::string& config, + const std::string& linkLanguage); ~cmComputeLinkDepends(); cmComputeLinkDepends(const cmComputeLinkDepends&) = delete; @@ -38,11 +40,32 @@ public: // Basic information about each link item. struct LinkEntry { + LinkEntry() = default; + LinkEntry(BT<std::string> item, cmGeneratorTarget const* target = nullptr) + : Item(std::move(item)) + , Target(target) + { + } + + static const std::string DEFAULT; + + enum EntryKind + { + Library, + Object, + SharedDep, + Flag, + // The following member is for the management of items specified + // through genex $<LINK_GROUP:...> + Group + }; + BT<std::string> Item; cmGeneratorTarget const* Target = nullptr; - bool IsSharedDep = false; - bool IsFlag = false; - bool IsObject = false; + EntryKind Kind = Library; + // The following member is for the management of items specified + // through genex $<LINK_LIBRARY:...> + std::string Feature = std::string(DEFAULT); }; using EntryVector = std::vector<LinkEntry>; @@ -60,12 +83,18 @@ private: cmMakefile* Makefile; cmGlobalGenerator const* GlobalGenerator; cmake* CMakeInstance; + std::string LinkLanguage; std::string Config; EntryVector FinalLinkEntries; + std::map<std::string, std::string> LinkLibraryOverride; + + std::string const& GetCurrentFeature( + std::string const& item, std::string const& defaultFeature) const; - std::map<cmLinkItem, int>::iterator AllocateLinkEntry( + std::pair<std::map<cmLinkItem, int>::iterator, bool> AllocateLinkEntry( cmLinkItem const& item); - int AddLinkEntry(cmLinkItem const& item); + std::pair<int, bool> AddLinkEntry(cmLinkItem const& item, + int groupIndex = -1); void AddLinkObject(cmLinkItem const& item); void AddVarLinkEntries(int depender_index, const char* value); void AddDirectLinkEntries(); @@ -78,10 +107,14 @@ private: std::vector<LinkEntry> EntryList; std::map<cmLinkItem, int> LinkEntryIndex; + // map storing, for each group, the list of items + std::map<int, std::vector<int>> GroupItems; + // BFS of initial dependencies. struct BFSEntry { int Index; + int GroupIndex; const char* LibDepends; }; std::queue<BFSEntry> BFSQueue; @@ -114,16 +147,20 @@ private: std::vector<DependSetList> InferredDependSets; void InferDependencies(); + // To finalize dependencies over groups in place of raw items + void UpdateGroupDependencies(); + // Ordering constraint graph adjacency list. using NodeList = cmGraphNodeList; using EdgeList = cmGraphEdgeList; using Graph = cmGraphAdjacencyList; Graph EntryConstraintGraph; void CleanConstraintGraph(); + bool CheckCircularDependencies() const; void DisplayConstraintGraph(); // Ordering algorithm. - void OrderLinkEntires(); + void OrderLinkEntries(); std::vector<char> ComponentVisited; std::vector<int> ComponentOrder; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 2ff91fe..e156e3d 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -8,7 +8,9 @@ #include <utility> #include <cm/memory> +#include <cm/optional> #include <cmext/algorithm> +#include <cmext/string_view> #include "cmComputeLinkDepends.h" #include "cmGeneratorTarget.h" @@ -18,7 +20,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmOrderDirectories.h" -#include "cmOutputConverter.h" +#include "cmPlaceholderExpander.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" @@ -344,6 +346,29 @@ cmComputeLinkInformation::cmComputeLinkInformation( this->LinkWithRuntimePath = this->Makefile->IsOn(var); } + // Define some Feature descriptors to handle standard library and object link + if (!this->GetLibLinkFileFlag().empty()) { + this->LibraryFeatureDescriptors.emplace( + "__CMAKE_LINK_LIBRARY", + LibraryFeatureDescriptor{ + "__CMAKE_LINK_LIBRARY", + cmStrCat(this->GetLibLinkFileFlag(), "<LIBRARY>") }); + } + if (!this->GetObjLinkFileFlag().empty()) { + this->LibraryFeatureDescriptors.emplace( + "__CMAKE_LINK_OBJECT", + LibraryFeatureDescriptor{ + "__CMAKE_LINK_OBJECT", + cmStrCat(this->GetObjLinkFileFlag(), "<LIBRARY>") }); + } + if (!this->LoaderFlag->empty()) { + // Define a Feature descriptor for the link of an executable with exports + this->LibraryFeatureDescriptors.emplace( + "__CMAKE_LINK_EXECUTABLE", + LibraryFeatureDescriptor{ "__CMAKE_LINK_EXECUTABLE", + cmStrCat(this->LoaderFlag, "<LIBRARY>") }); + } + // Check the platform policy for missing soname case. this->NoSONameUsesPath = this->Makefile->IsOn("CMAKE_PLATFORM_USES_PATH_WHEN_NO_SONAME"); @@ -409,6 +434,10 @@ cmComputeLinkInformation::cmComputeLinkInformation( cmComputeLinkInformation::~cmComputeLinkInformation() = default; +namespace { +const std::string& DEFAULT = cmComputeLinkDepends::LinkEntry::DEFAULT; +} + void cmComputeLinkInformation::AppendValues( std::string& result, std::vector<BT<std::string>>& values) { @@ -510,17 +539,67 @@ bool cmComputeLinkInformation::Compute() } // Compute the ordered link line items. - cmComputeLinkDepends cld(this->Target, this->Config); + cmComputeLinkDepends cld(this->Target, this->Config, this->LinkLanguage); cld.SetOldLinkDirMode(this->OldLinkDirMode); cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute(); + FeatureDescriptor const* currentFeature = nullptr; // Add the link line items. for (cmComputeLinkDepends::LinkEntry const& linkEntry : linkEntries) { - if (linkEntry.IsSharedDep) { - this->AddSharedDepItem(linkEntry.Item, linkEntry.Target); + if (linkEntry.Kind == cmComputeLinkDepends::LinkEntry::Group) { + const auto& groupFeature = this->GetGroupFeature(linkEntry.Feature); + if (groupFeature.Supported) { + this->Items.emplace_back( + BT<std::string>{ linkEntry.Item.Value == "<LINK_GROUP>" + ? groupFeature.Prefix + : groupFeature.Suffix, + linkEntry.Item.Backtrace }, + ItemIsPath::No); + } + continue; + } + + if (currentFeature != nullptr && + linkEntry.Feature != currentFeature->Name) { + // emit feature suffix, if any + if (!currentFeature->Suffix.empty()) { + this->Items.emplace_back( + BT<std::string>{ currentFeature->Suffix, + this->Items.back().Value.Backtrace }, + ItemIsPath::No); + } + currentFeature = nullptr; + } + + if (linkEntry.Feature != DEFAULT && + (currentFeature == nullptr || + linkEntry.Feature != currentFeature->Name)) { + if (!this->AddLibraryFeature(linkEntry.Feature)) { + continue; + } + currentFeature = this->FindLibraryFeature(linkEntry.Feature); + // emit feature prefix, if any + if (!currentFeature->Prefix.empty()) { + this->Items.emplace_back( + BT<std::string>{ currentFeature->Prefix, linkEntry.Item.Backtrace }, + ItemIsPath::No); + } + } + + if (linkEntry.Kind == cmComputeLinkDepends::LinkEntry::SharedDep) { + this->AddSharedDepItem(linkEntry); } else { - this->AddItem(linkEntry.Item, linkEntry.Target, - linkEntry.IsObject ? ItemIsObject::Yes : ItemIsObject::No); + this->AddItem(linkEntry); + } + } + + if (currentFeature != nullptr) { + // emit feature suffix, if any + if (!currentFeature->Suffix.empty()) { + this->Items.emplace_back( + BT<std::string>{ currentFeature->Suffix, + this->Items.back().Value.Backtrace }, + ItemIsPath::No); } } @@ -576,6 +655,377 @@ bool cmComputeLinkInformation::Compute() return true; } +namespace { +void FinalizeFeatureFormat(std::string& format, const std::string& activeTag, + const std::string& otherTag) +{ + auto pos = format.find(otherTag); + if (pos != std::string::npos) { + format.erase(pos, format.find('}', pos) - pos + 1); + } + pos = format.find(activeTag); + if (pos != std::string::npos) { + format.erase(pos, activeTag.length()); + pos = format.find('}', pos); + if (pos != std::string::npos) { + format.erase(pos, 1); + } + } +} + +bool IsValidFeatureFormat(const std::string& format) +{ + return format.find("<LIBRARY>") != std::string::npos || + format.find("<LIB_ITEM>") != std::string::npos || + format.find("<LINK_ITEM>") != std::string::npos; +} + +class FeaturePlaceHolderExpander : public cmPlaceholderExpander +{ +public: + FeaturePlaceHolderExpander(const std::string* library, + const std::string* libItem = nullptr, + const std::string* linkItem = nullptr) + : Library(library) + , LibItem(libItem) + , LinkItem(linkItem) + { + } + +private: + std::string ExpandVariable(std::string const& variable) override + { + if (this->Library != nullptr && variable == "LIBRARY") { + return *this->Library; + } + if (this->LibItem != nullptr && variable == "LIB_ITEM") { + return *this->LibItem; + } + if (this->LinkItem != nullptr && variable == "LINK_ITEM") { + return *this->LinkItem; + } + + return variable; + } + + const std::string* Library = nullptr; + const std::string* LibItem = nullptr; + const std::string* LinkItem = nullptr; +}; +} + +cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( + std::string name, std::string itemFormat) + : Name(std::move(name)) + , Supported(true) + , ItemPathFormat(std::move(itemFormat)) + , ItemNameFormat(this->ItemPathFormat) +{ +} +cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( + std::string name, std::string itemPathFormat, std::string itemNameFormat) + : Name(std::move(name)) + , Supported(true) + , ItemPathFormat(std::move(itemPathFormat)) + , ItemNameFormat(std::move(itemNameFormat)) +{ +} +cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( + std::string name, std::string prefix, std::string itemPathFormat, + std::string itemNameFormat, std::string suffix) + : Name(std::move(name)) + , Supported(true) + , Prefix(std::move(prefix)) + , Suffix(std::move(suffix)) + , ItemPathFormat(std::move(itemPathFormat)) + , ItemNameFormat(std::move(itemNameFormat)) +{ +} +cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( + std::string name, std::string prefix, std::string suffix, bool) + : Name(std::move(name)) + , Supported(true) + , Prefix(std::move(prefix)) + , Suffix(std::move(suffix)) +{ +} + +std::string cmComputeLinkInformation::FeatureDescriptor::GetDecoratedItem( + std::string const& library, ItemIsPath isPath) const +{ + auto format = + isPath == ItemIsPath::Yes ? this->ItemPathFormat : this->ItemNameFormat; + + // replace <LIBRARY>, <LIB_ITEM> and <LINK_ITEM> patterns with library path + FeaturePlaceHolderExpander expander(&library, &library, &library); + return expander.ExpandVariables(format); +} +std::string cmComputeLinkInformation::FeatureDescriptor::GetDecoratedItem( + std::string const& library, std::string const& libItem, + std::string const& linkItem, ItemIsPath isPath) const +{ + auto format = + isPath == ItemIsPath::Yes ? this->ItemPathFormat : this->ItemNameFormat; + + // replace <LIBRARY>, <LIB_ITEM> and <LINK_ITEM> patterns + FeaturePlaceHolderExpander expander(&library, &libItem, &linkItem); + return expander.ExpandVariables(format); +} + +cmComputeLinkInformation::LibraryFeatureDescriptor::LibraryFeatureDescriptor( + std::string name, std::string itemFormat) + : FeatureDescriptor(std::move(name), std::move(itemFormat)) +{ +} +cmComputeLinkInformation::LibraryFeatureDescriptor::LibraryFeatureDescriptor( + std::string name, std::string itemPathFormat, std::string itemNameFormat) + : FeatureDescriptor(std::move(name), std::move(itemPathFormat), + std::move(itemNameFormat)) +{ +} +cmComputeLinkInformation::LibraryFeatureDescriptor::LibraryFeatureDescriptor( + std::string name, std::string prefix, std::string itemPathFormat, + std::string itemNameFormat, std::string suffix) + : FeatureDescriptor(std::move(name), std::move(prefix), + std::move(itemPathFormat), std::move(itemNameFormat), + std::move(suffix)) +{ +} + +bool cmComputeLinkInformation::AddLibraryFeature(std::string const& feature) +{ + auto it = this->LibraryFeatureDescriptors.find(feature); + if (it != this->LibraryFeatureDescriptors.end()) { + return it->second.Supported; + } + + auto featureName = + cmStrCat("CMAKE_", this->LinkLanguage, "_LINK_LIBRARY_USING_", feature); + cmValue featureSupported = + this->Makefile->GetDefinition(cmStrCat(featureName, "_SUPPORTED")); + if (!featureSupported) { + // language specific variable is not defined, fallback to the more generic + // one + featureName = cmStrCat("CMAKE_LINK_LIBRARY_USING_", feature); + featureSupported = + this->Makefile->GetDefinition(cmStrCat(featureName, "_SUPPORTED")); + } + if (!featureSupported.IsOn()) { + this->LibraryFeatureDescriptors.emplace(feature, FeatureDescriptor{}); + + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Feature '", feature, + "', specified through generator-expression '$<LINK_LIBRARY>' to " + "link target '", + this->Target->GetName(), "', is not supported for the '", + this->LinkLanguage, "' link language."), + this->Target->GetBacktrace()); + + return false; + } + + cmValue langFeature = this->Makefile->GetDefinition(featureName); + if (!langFeature) { + this->LibraryFeatureDescriptors.emplace(feature, FeatureDescriptor{}); + + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Feature '", feature, + "', specified through generator-expression '$<LINK_LIBRARY>' to " + "link target '", + this->Target->GetName(), "', is not defined for the '", + this->LinkLanguage, "' link language."), + this->Target->GetBacktrace()); + + return false; + } + + auto items = + cmExpandListWithBacktrace(langFeature, this->Target->GetBacktrace(), true); + + if ((items.size() == 1 && !IsValidFeatureFormat(items.front().Value)) || + (items.size() == 3 && !IsValidFeatureFormat(items[1].Value))) { + this->LibraryFeatureDescriptors.emplace(feature, FeatureDescriptor{}); + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Feature '", feature, "', specified by variable '", featureName, + "', is malformed (\"<LIBRARY>\", \"<LIB_ITEM>\", or " + "\"<LINK_ITEM>\" patterns " + "are missing) and cannot be used to link target '", + this->Target->GetName(), "'."), + this->Target->GetBacktrace()); + + return false; + } + + // now, handle possible "PATH{}" and "NAME{}" patterns + if (items.size() == 1) { + items.push_back(items.front()); + FinalizeFeatureFormat(items[0].Value, "PATH{", "NAME{"); + FinalizeFeatureFormat(items[1].Value, "NAME{", "PATH{"); + } else if (items.size() == 3) { + items.insert(items.begin() + 1, items[1]); + FinalizeFeatureFormat(items[1].Value, "PATH{", "NAME{"); + FinalizeFeatureFormat(items[2].Value, "NAME{", "PATH{"); + } else { + this->LibraryFeatureDescriptors.emplace(feature, FeatureDescriptor{}); + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Feature '", feature, "', specified by variable '", featureName, + "', is malformed (wrong number of elements) and cannot be used " + "to link target '", + this->Target->GetName(), "'."), + this->Target->GetBacktrace()); + + return false; + } + if ((items.size() == 2 && !IsValidFeatureFormat(items[0].Value)) || + (items.size() == 4 && !IsValidFeatureFormat(items[1].Value))) { + // PATH{} has wrong format + this->LibraryFeatureDescriptors.emplace(feature, FeatureDescriptor{}); + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Feature '", feature, "', specified by variable '", featureName, + "', is malformed (\"<LIBRARY>\", \"<LIB_ITEM>\", or " + "\"<LINK_ITEM>\" patterns " + "are missing for \"PATH{}\" alternative) and cannot be used to " + "link target '", + this->Target->GetName(), "'."), + this->Target->GetBacktrace()); + + return false; + } + if ((items.size() == 2 && !IsValidFeatureFormat(items[1].Value)) || + (items.size() == 4 && !IsValidFeatureFormat(items[2].Value))) { + // NAME{} has wrong format + this->LibraryFeatureDescriptors.emplace(feature, FeatureDescriptor{}); + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Feature '", feature, "', specified by variable '", featureName, + "', is malformed (\"<LIBRARY>\", \"<LIB_ITEM>\", or " + "\"<LINK_ITEM>\" patterns " + "are missing for \"NAME{}\" alternative) and cannot be used to " + "link target '", + this->Target->GetName(), "'."), + this->Target->GetBacktrace()); + + return false; + } + + // replace LINKER: pattern + this->Target->ResolveLinkerWrapper(items, this->LinkLanguage, true); + + if (items.size() == 2) { + this->LibraryFeatureDescriptors.emplace( + feature, + LibraryFeatureDescriptor{ feature, items[0].Value, items[1].Value }); + } else { + this->LibraryFeatureDescriptors.emplace( + feature, + LibraryFeatureDescriptor{ feature, items[0].Value, items[1].Value, + items[2].Value, items[3].Value }); + } + + return true; +} + +cmComputeLinkInformation::FeatureDescriptor const& +cmComputeLinkInformation::GetLibraryFeature(std::string const& feature) const +{ + return this->LibraryFeatureDescriptors.find(feature)->second; +} +cmComputeLinkInformation::FeatureDescriptor const* +cmComputeLinkInformation::FindLibraryFeature(std::string const& feature) const +{ + auto it = this->LibraryFeatureDescriptors.find(feature); + if (it == this->LibraryFeatureDescriptors.end()) { + return nullptr; + } + + return &it->second; +} + +cmComputeLinkInformation::GroupFeatureDescriptor::GroupFeatureDescriptor( + std::string name, std::string prefix, std::string suffix) + : FeatureDescriptor(std::move(name), std::move(prefix), std::move(suffix), + true) +{ +} + +cmComputeLinkInformation::FeatureDescriptor const& +cmComputeLinkInformation::GetGroupFeature(std::string const& feature) +{ + auto it = this->GroupFeatureDescriptors.find(feature); + if (it != this->GroupFeatureDescriptors.end()) { + return it->second; + } + + auto featureName = + cmStrCat("CMAKE_", this->LinkLanguage, "_LINK_GROUP_USING_", feature); + cmValue featureSupported = + this->Makefile->GetDefinition(cmStrCat(featureName, "_SUPPORTED")); + if (!featureSupported) { + // language specific variable is not defined, fallback to the more generic + // one + featureName = cmStrCat("CMAKE_LINK_GROUP_USING_", feature); + featureSupported = + this->Makefile->GetDefinition(cmStrCat(featureName, "_SUPPORTED")); + } + if (!featureSupported.IsOn()) { + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Feature '", feature, + "', specified through generator-expression '$<LINK_GROUP>' to " + "link target '", + this->Target->GetName(), "', is not supported for the '", + this->LinkLanguage, "' link language."), + this->Target->GetBacktrace()); + return this->GroupFeatureDescriptors.emplace(feature, FeatureDescriptor{}) + .first->second; + } + + cmValue langFeature = this->Makefile->GetDefinition(featureName); + if (!langFeature) { + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Feature '", feature, + "', specified through generator-expression '$<LINK_GROUP>' to " + "link target '", + this->Target->GetName(), "', is not defined for the '", + this->LinkLanguage, "' link language."), + this->Target->GetBacktrace()); + return this->GroupFeatureDescriptors.emplace(feature, FeatureDescriptor{}) + .first->second; + } + + auto items = + cmExpandListWithBacktrace(langFeature, this->Target->GetBacktrace(), true); + + // replace LINKER: pattern + this->Target->ResolveLinkerWrapper(items, this->LinkLanguage, true); + + if (items.size() == 2) { + return this->GroupFeatureDescriptors + .emplace( + feature, + GroupFeatureDescriptor{ feature, items[0].Value, items[1].Value }) + .first->second; + } + + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Feature '", feature, "', specified by variable '", featureName, + "', is malformed (wrong number of elements) and cannot be used " + "to link target '", + this->Target->GetName(), "'."), + this->Target->GetBacktrace()); + return this->GroupFeatureDescriptors.emplace(feature, FeatureDescriptor{}) + .first->second; +} + void cmComputeLinkInformation::AddImplicitLinkInfo() { // The link closure lists all languages whose implicit info is needed. @@ -610,7 +1060,7 @@ void cmComputeLinkInformation::AddRuntimeLinkLibrary(std::string const& lang) std::vector<std::string> libsVec = cmExpandedList(*runtimeLinkOptions); for (std::string const& i : libsVec) { if (!cm::contains(this->ImplicitLinkLibs, i)) { - this->AddItem(i, nullptr); + this->AddItem({ i }); } } } @@ -625,7 +1075,7 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) std::vector<std::string> libsVec = cmExpandedList(*libs); for (std::string const& i : libsVec) { if (!cm::contains(this->ImplicitLinkLibs, i)) { - this->AddItem(i, nullptr); + this->AddItem({ i }); } } } @@ -639,10 +1089,11 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) } } -void cmComputeLinkInformation::AddItem(BT<std::string> const& item, - cmGeneratorTarget const* tgt, - ItemIsObject isObject) +void cmComputeLinkInformation::AddItem(LinkEntry const& entry) { + cmGeneratorTarget const* tgt = entry.Target; + BT<std::string> const& item = entry.Item; + // Compute the proper name to use to link this library. const std::string& config = this->Config; bool impexe = (tgt && tgt->IsExecutableWithExports()); @@ -657,28 +1108,27 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item, if (impexe && this->LoaderFlag) { // This link item is an executable that may provide symbols // used by this target. A special flag is needed on this - // platform. Add it now. - std::string linkItem = this->LoaderFlag; + // platform. Add it now using a special feature. cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config) ? cmStateEnums::ImportLibraryArtifact : cmStateEnums::RuntimeBinaryArtifact; - std::string exe = tgt->GetFullPath(config, artifact, true); - linkItem += exe; - this->Items.emplace_back(BT<std::string>(linkItem, item.Backtrace), - ItemIsPath::Yes, ItemIsObject::No, tgt); + this->Items.emplace_back( + BT<std::string>(exe, item.Backtrace), ItemIsPath::Yes, tgt, + this->FindLibraryFeature(entry.Feature == DEFAULT + ? "__CMAKE_LINK_EXECUTABLE" + : entry.Feature)); this->Depends.push_back(std::move(exe)); } else if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { // Add the interface library as an item so it can be considered as part // of COMPATIBLE_INTERFACE_ enforcement. The generators will ignore // this for the actual link line. - this->Items.emplace_back(std::string(), ItemIsPath::No, ItemIsObject::No, - tgt); + this->Items.emplace_back(std::string(), ItemIsPath::No, tgt); // Also add the item the interface specifies to be used in its place. std::string const& libName = tgt->GetImportedLibName(config); if (!libName.empty()) { - this->AddItem(BT<std::string>(libName, item.Backtrace), nullptr); + this->AddItem(BT<std::string>(libName, item.Backtrace)); } } else if (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) { // Ignore object library! @@ -706,7 +1156,9 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item, this->Depends.push_back(lib.Value); } - this->AddTargetItem(lib, tgt); + LinkEntry libEntry{ entry }; + libEntry.Item = lib; + this->AddTargetItem(libEntry); this->AddLibraryRuntimeInfo(lib.Value, tgt); if (tgt && tgt->GetType() == cmStateEnums::SHARED_LIBRARY && this->Target->IsDLLPlatform()) { @@ -715,30 +1167,34 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item, } } else { // This is not a CMake target. Use the name given. - if (cmSystemTools::FileIsFullPath(item.Value)) { - if (cmSystemTools::IsPathToFramework(item.Value) && - this->Makefile->IsOn("APPLE")) { - // This is a framework. - this->AddFrameworkItem(item.Value); - } else if (cmSystemTools::FileIsDirectory(item.Value)) { + if (cmHasSuffix(entry.Feature, "FRAMEWORK"_s) || + (entry.Feature == DEFAULT && + cmSystemTools::IsPathToFramework(item.Value) && + this->Makefile->IsOn("APPLE"))) { + // This is a framework. + this->AddFrameworkItem(entry); + } else if (cmSystemTools::FileIsFullPath(item.Value)) { + if (cmSystemTools::FileIsDirectory(item.Value)) { // This is a directory. this->DropDirectoryItem(item); } else { // Use the full path given to the library file. this->Depends.push_back(item.Value); - this->AddFullItem(item, isObject); + this->AddFullItem(entry); this->AddLibraryRuntimeInfo(item.Value); } } else { // This is a library or option specified by the user. - this->AddUserItem(item, true); + this->AddUserItem(entry, true); } } } -void cmComputeLinkInformation::AddSharedDepItem(BT<std::string> const& item, - const cmGeneratorTarget* tgt) +void cmComputeLinkInformation::AddSharedDepItem(LinkEntry const& entry) { + BT<std::string> const& item = entry.Item; + const cmGeneratorTarget* tgt = entry.Target; + // Record dependencies on DLLs. if (tgt && tgt->GetType() == cmStateEnums::SHARED_LIBRARY && this->Target->IsDLLPlatform() && @@ -776,7 +1232,7 @@ void cmComputeLinkInformation::AddSharedDepItem(BT<std::string> const& item, // If in linking mode, just link to the shared library. if (this->SharedDependencyMode == SharedDepModeLink) { - this->AddItem(item, tgt); + this->AddItem(entry); return; } @@ -1058,8 +1514,7 @@ void cmComputeLinkInformation::SetCurrentLinkType(LinkType lt) } } -void cmComputeLinkInformation::AddTargetItem(BT<std::string> const& item, - cmGeneratorTarget const* target) +void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry) { // This is called to handle a link item that is a full path to a target. // If the target is not a static library make sure the link type is @@ -1067,6 +1522,9 @@ void cmComputeLinkInformation::AddTargetItem(BT<std::string> const& item, // shared and static libraries but static-mode can handle only // static libraries. If a previous user item changed the link type // to static we need to make sure it is back to shared. + BT<std::string> const& item = entry.Item; + cmGeneratorTarget const* target = entry.Target; + if (target->GetType() != cmStateEnums::STATIC_LIBRARY) { this->SetCurrentLinkType(LinkShared); } @@ -1079,7 +1537,7 @@ void cmComputeLinkInformation::AddTargetItem(BT<std::string> const& item, // Handle case of an imported shared library with no soname. if (this->NoSONameUsesPath && target->IsImportedSharedLibWithoutSOName(this->Config)) { - this->AddSharedLibNoSOName(item.Value); + this->AddSharedLibNoSOName(entry); return; } @@ -1091,20 +1549,60 @@ void cmComputeLinkInformation::AddTargetItem(BT<std::string> const& item, this->OldLinkDirItems.push_back(item.Value); } - // Now add the full path to the library. - this->Items.emplace_back(item, ItemIsPath::Yes, ItemIsObject::No, target); + if (target->IsFrameworkOnApple() && this->GlobalGenerator->IsXcode() && + entry.Feature == DEFAULT) { + // ensure FRAMEWORK feature is loaded + this->AddLibraryFeature("FRAMEWORK"); + } + + if (target->IsFrameworkOnApple() && !this->GlobalGenerator->IsXcode()) { + // Add the framework directory and the framework item itself + auto fwItems = this->GlobalGenerator->SplitFrameworkPath(item.Value, true); + if (!fwItems) { + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Could not parse framework path \"", item.Value, + "\" linked by target ", this->Target->GetName(), '.'), + item.Backtrace); + return; + } + if (!fwItems->first.empty()) { + // Add the directory portion to the framework search path. + this->AddFrameworkPath(fwItems->first); + } + if (cmHasSuffix(entry.Feature, "FRAMEWORK"_s)) { + this->Items.emplace_back(fwItems->second, ItemIsPath::Yes, target, + this->FindLibraryFeature(entry.Feature)); + } else { + this->Items.emplace_back( + item, ItemIsPath::Yes, target, + this->FindLibraryFeature( + entry.Feature == DEFAULT ? "__CMAKE_LINK_LIBRARY" : entry.Feature)); + } + } else { + // Now add the full path to the library. + this->Items.emplace_back( + item, ItemIsPath::Yes, target, + this->FindLibraryFeature( + entry.Feature == DEFAULT + ? (target->IsFrameworkOnApple() && this->GlobalGenerator->IsXcode() + ? "FRAMEWORK" + : "__CMAKE_LINK_LIBRARY") + : entry.Feature)); + } } -void cmComputeLinkInformation::AddFullItem(BT<std::string> const& item, - ItemIsObject isObject) +void cmComputeLinkInformation::AddFullItem(LinkEntry const& entry) { + BT<std::string> const& item = entry.Item; + // Check for the implicit link directory special case. - if (this->CheckImplicitDirItem(item.Value)) { + if (this->CheckImplicitDirItem(entry)) { return; } // Check for case of shared library with no builtin soname. - if (this->NoSONameUsesPath && this->CheckSharedLibNoSOName(item.Value)) { + if (this->NoSONameUsesPath && this->CheckSharedLibNoSOName(entry)) { return; } @@ -1116,7 +1614,7 @@ void cmComputeLinkInformation::AddFullItem(BT<std::string> const& item, generator.find("Xcode") != std::string::npos)) { std::string file = cmSystemTools::GetFilenameName(item.Value); if (!this->ExtractAnyLibraryName.find(file)) { - this->HandleBadFullItem(item.Value, file); + this->HandleBadFullItem(entry, file); return; } } @@ -1147,11 +1645,20 @@ void cmComputeLinkInformation::AddFullItem(BT<std::string> const& item, } // Now add the full path to the library. - this->Items.emplace_back(item, ItemIsPath::Yes, isObject); + this->Items.emplace_back( + item, ItemIsPath::Yes, nullptr, + this->FindLibraryFeature( + entry.Feature == DEFAULT + ? (entry.Kind == cmComputeLinkDepends::LinkEntry::Object + ? "__CMAKE_LINK_OBJECT" + : "__CMAKE_LINK_LIBRARY") + : entry.Feature)); } -bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) +bool cmComputeLinkInformation::CheckImplicitDirItem(LinkEntry const& entry) { + BT<std::string> const& item = entry.Item; + // We only switch to a pathless item if the link type may be // enforced. Fortunately only platforms that support link types // seem to have magic per-architecture implicit link directories. @@ -1160,7 +1667,7 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) } // Check if this item is in an implicit link directory. - std::string dir = cmSystemTools::GetFilenamePath(item); + std::string dir = cmSystemTools::GetFilenamePath(item.Value); if (!cm::contains(this->ImplicitLinkDirs, dir)) { // Only libraries in implicit link directories are converted to // pathless items. @@ -1169,7 +1676,7 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) // Only apply the policy below if the library file is one that can // be found by the linker. - std::string file = cmSystemTools::GetFilenameName(item); + std::string file = cmSystemTools::GetFilenameName(item.Value); if (!this->ExtractAnyLibraryName.find(file)) { return false; } @@ -1179,10 +1686,10 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) case cmPolicies::WARN: if (this->CMP0060Warn) { // Print the warning at most once for this item. - std::string const& wid = "CMP0060-WARNING-GIVEN-" + item; + std::string const& wid = "CMP0060-WARNING-GIVEN-" + item.Value; if (!this->CMakeInstance->GetPropertyAsBool(wid)) { this->CMakeInstance->SetProperty(wid, "1"); - this->CMP0060WarnItems.insert(item); + this->CMP0060WarnItems.insert(item.Value); } } CM_FALLTHROUGH; @@ -1200,15 +1707,17 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) // directory then just report the file name without the directory // portion. This will allow the system linker to locate the proper // library for the architecture at link time. - this->AddUserItem(file, false); + LinkEntry fileEntry{ entry }; + fileEntry.Item = file; + this->AddUserItem(fileEntry, false); // Make sure the link directory ordering will find the library. - this->OrderLinkerSearchPath->AddLinkLibrary(item); + this->OrderLinkerSearchPath->AddLinkLibrary(item.Value); return true; } -void cmComputeLinkInformation::AddUserItem(BT<std::string> const& item, +void cmComputeLinkInformation::AddUserItem(LinkEntry const& entry, bool pathNotKnown) { // This is called to handle a link item that does not match a CMake @@ -1219,8 +1728,10 @@ void cmComputeLinkInformation::AddUserItem(BT<std::string> const& item, // foo ==> -lfoo // libfoo.a ==> -Wl,-Bstatic -lfoo - // Pass flags through untouched. + BT<std::string> const& item = entry.Item; + if (item.Value[0] == '-' || item.Value[0] == '$' || item.Value[0] == '`') { + // Pass flags through untouched. // if this is a -l option then we might need to warn about // CMP0003 so put it in OldUserFlagItems, if it is not a -l // or -Wl,-l (-framework -pthread), then allow it without a @@ -1305,9 +1816,20 @@ void cmComputeLinkInformation::AddUserItem(BT<std::string> const& item, } // Create an option to ask the linker to search for the library. - std::string out = cmStrCat(this->LibLinkFlag, lib, this->LibLinkSuffix); - this->Items.emplace_back(BT<std::string>(out, item.Backtrace), - ItemIsPath::No); + auto out = cmStrCat(this->LibLinkFlag, lib, this->LibLinkSuffix); + + if (entry.Feature != DEFAULT) { + auto const& feature = this->GetLibraryFeature(entry.Feature); + this->Items.emplace_back( + BT<std::string>( + feature.GetDecoratedItem(cmStrCat(lib, this->LibLinkSuffix), + item.Value, out, ItemIsPath::No), + item.Backtrace), + ItemIsPath::No); + } else { + this->Items.emplace_back(BT<std::string>(out, item.Backtrace), + ItemIsPath::No); + } // Here we could try to find the library the linker will find and // add a runtime information entry for it. It would probably not be @@ -1315,10 +1837,14 @@ void cmComputeLinkInformation::AddUserItem(BT<std::string> const& item, // specification. } -void cmComputeLinkInformation::AddFrameworkItem(std::string const& item) +void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry) { + std::string const& item = entry.Item.Value; + // Try to separate the framework name and path. - if (!this->SplitFramework.find(item)) { + auto fwItems = + this->GlobalGenerator->SplitFrameworkPath(item, entry.Feature != DEFAULT); + if (!fwItems) { std::ostringstream e; e << "Could not parse framework path \"" << item << "\" " << "linked by target " << this->Target->GetName() << "."; @@ -1326,26 +1852,36 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item) return; } - std::string fw_path = this->SplitFramework.match(1); - std::string fw = this->SplitFramework.match(2); - std::string full_fw = cmStrCat(fw_path, '/', fw, ".framework/", fw); + std::string fw_path = std::move(fwItems->first); + std::string fw = std::move(fwItems->second); + std::string full_fw = cmStrCat(fw, ".framework/", fw); - // Add the directory portion to the framework search path. - this->AddFrameworkPath(fw_path); + if (!fw_path.empty()) { + full_fw = cmStrCat(fw_path, '/', full_fw); + // Add the directory portion to the framework search path. + this->AddFrameworkPath(fw_path); + } // add runtime information this->AddLibraryRuntimeInfo(full_fw); + if (entry.Feature == DEFAULT) { + // ensure FRAMEWORK feature is loaded + this->AddLibraryFeature("FRAMEWORK"); + } + if (this->GlobalGenerator->IsXcode()) { // Add framework path - it will be handled by Xcode after it's added to // "Link Binary With Libraries" build phase - this->Items.emplace_back(item, ItemIsPath::Yes); + this->Items.emplace_back(item, ItemIsPath::Yes, nullptr, + this->FindLibraryFeature(entry.Feature == DEFAULT + ? "FRAMEWORK" + : entry.Feature)); } else { - // Add the item using the -framework option. - this->Items.emplace_back(std::string("-framework"), ItemIsPath::No); - cmOutputConverter converter(this->Makefile->GetStateSnapshot()); - fw = converter.EscapeForShell(fw); - this->Items.emplace_back(fw, ItemIsPath::No); + this->Items.emplace_back(fw, ItemIsPath::Yes, nullptr, + this->FindLibraryFeature(entry.Feature == DEFAULT + ? "FRAMEWORK" + : entry.Feature)); } } @@ -1355,10 +1891,10 @@ void cmComputeLinkInformation::DropDirectoryItem(BT<std::string> const& item) // user. this->CMakeInstance->IssueMessage( MessageType::WARNING, - cmStrCat( - "Target \"", this->Target->GetName(), - "\" requests linking to directory \"", item.Value, - "\". Targets may link only to libraries. CMake is dropping the item."), + cmStrCat("Target \"", this->Target->GetName(), + "\" requests linking to directory \"", item.Value, + "\". Targets may link only to libraries. CMake is dropping " + "the item."), item.Backtrace); } @@ -1378,9 +1914,6 @@ void cmComputeLinkInformation::ComputeFrameworkInfo() this->FrameworkPathsEmitted.insert(implicitDirVec.begin(), implicitDirVec.end()); - - // Regular expression to extract a framework path and name. - this->SplitFramework.compile("(.*)/(.*)\\.framework$"); } void cmComputeLinkInformation::AddFrameworkPath(std::string const& p) @@ -1390,42 +1923,44 @@ void cmComputeLinkInformation::AddFrameworkPath(std::string const& p) } } -bool cmComputeLinkInformation::CheckSharedLibNoSOName(std::string const& item) +bool cmComputeLinkInformation::CheckSharedLibNoSOName(LinkEntry const& entry) { // This platform will use the path to a library as its soname if the // library is given via path and was not built with an soname. If // this is a shared library that might be the case. - std::string file = cmSystemTools::GetFilenameName(item); + std::string file = cmSystemTools::GetFilenameName(entry.Item.Value); if (this->ExtractSharedLibraryName.find(file)) { // If we can guess the soname fairly reliably then assume the // library has one. Otherwise assume the library has no builtin // soname. std::string soname; - if (!cmSystemTools::GuessLibrarySOName(item, soname)) { - this->AddSharedLibNoSOName(item); + if (!cmSystemTools::GuessLibrarySOName(entry.Item.Value, soname)) { + this->AddSharedLibNoSOName(entry); return true; } } return false; } -void cmComputeLinkInformation::AddSharedLibNoSOName(std::string const& item) +void cmComputeLinkInformation::AddSharedLibNoSOName(LinkEntry const& entry) { // We have a full path to a shared library with no soname. We need // to ask the linker to locate the item because otherwise the path // we give to it will be embedded in the target linked. Then at // runtime the dynamic linker will search for the library using the // path instead of just the name. - std::string file = cmSystemTools::GetFilenameName(item); - this->AddUserItem(file, false); + LinkEntry fileEntry{ entry }; + fileEntry.Item = cmSystemTools::GetFilenameName(entry.Item.Value); + this->AddUserItem(fileEntry, false); // Make sure the link directory ordering will find the library. - this->OrderLinkerSearchPath->AddLinkLibrary(item); + this->OrderLinkerSearchPath->AddLinkLibrary(entry.Item.Value); } -void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, +void cmComputeLinkInformation::HandleBadFullItem(LinkEntry const& entry, std::string const& file) { + std::string const& item = entry.Item.Value; // Do not depend on things that do not exist. auto i = std::find(this->Depends.begin(), this->Depends.end(), item); if (i != this->Depends.end()) { @@ -1435,7 +1970,9 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, // Tell the linker to search for the item and provide the proper // path for it. Do not contribute to any CMP0003 warning (do not // put in OldLinkDirItems or OldUserFlagItems). - this->AddUserItem(file, false); + LinkEntry fileEntry{ entry }; + fileEntry.Item = file; + this->AddUserItem(fileEntry, false); this->OrderLinkerSearchPath->AddLinkLibrary(item); // Produce any needed message. @@ -1781,8 +2318,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // Add directories explicitly specified by user std::string build_rpath; if (this->Target->GetBuildRPATH(this->Config, build_rpath)) { - // This will not resolve entries to use $ORIGIN, the user is expected to - // do that if necessary. + // This will not resolve entries to use $ORIGIN, the user is expected + // to do that if necessary. cmCLI_ExpandListUnique(build_rpath, runtimeDirs, emitted); } } diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 0315540..a4ada1f 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <map> #include <memory> #include <set> #include <string> @@ -13,6 +14,7 @@ #include "cmsys/RegularExpression.hxx" +#include "cmComputeLinkDepends.h" #include "cmListFileCache.h" #include "cmValue.h" @@ -27,6 +29,9 @@ class cmake; */ class cmComputeLinkInformation { +private: + class FeatureDescriptor; + public: cmComputeLinkInformation(cmGeneratorTarget const* target, const std::string& config); @@ -42,28 +47,38 @@ public: Yes, }; - enum class ItemIsObject - { - No, - Yes, - }; - struct Item { - Item() = default; Item(BT<std::string> v, ItemIsPath isPath, - ItemIsObject isObject = ItemIsObject::No, - cmGeneratorTarget const* target = nullptr) + cmGeneratorTarget const* target = nullptr, + FeatureDescriptor const* feature = nullptr) : Value(std::move(v)) , IsPath(isPath) - , IsObject(isObject) , Target(target) + , Feature(feature) { } BT<std::string> Value; - ItemIsPath IsPath = ItemIsPath::Yes; - ItemIsObject IsObject = ItemIsObject::No; + ItemIsPath IsPath = ItemIsPath::No; cmGeneratorTarget const* Target = nullptr; + + bool HasFeature() const { return this->Feature != nullptr; } + const std::string& GetFeatureName() const + { + return HasFeature() ? this->Feature->Name + : cmComputeLinkDepends::LinkEntry::DEFAULT; + } + + BT<std::string> GetFormattedItem(std::string const& path) const + { + return { (this->Feature != nullptr) + ? this->Feature->GetDecoratedItem(path, this->IsPath) + : path, + Value.Backtrace }; + } + + private: + FeatureDescriptor const* Feature = nullptr; }; using ItemVector = std::vector<Item>; void AppendValues(std::string& result, std::vector<BT<std::string>>& values); @@ -104,10 +119,10 @@ public: const cmGeneratorTarget* GetTarget() { return this->Target; } private: - void AddItem(BT<std::string> const& item, const cmGeneratorTarget* tgt, - ItemIsObject isObject = ItemIsObject::No); - void AddSharedDepItem(BT<std::string> const& item, - cmGeneratorTarget const* tgt); + using LinkEntry = cmComputeLinkDepends::LinkEntry; + + void AddItem(LinkEntry const& entry); + void AddSharedDepItem(LinkEntry const& entry); void AddRuntimeDLL(cmGeneratorTarget const* tgt); // Output information. @@ -181,22 +196,20 @@ private: std::string NoCaseExpression(std::string const& str); // Handling of link items. - void AddTargetItem(BT<std::string> const& item, - const cmGeneratorTarget* target); - void AddFullItem(BT<std::string> const& item, ItemIsObject isObject); - bool CheckImplicitDirItem(std::string const& item); - void AddUserItem(BT<std::string> const& item, bool pathNotKnown); - void AddFrameworkItem(std::string const& item); + void AddTargetItem(LinkEntry const& entry); + void AddFullItem(LinkEntry const& entry); + bool CheckImplicitDirItem(LinkEntry const& entry); + void AddUserItem(LinkEntry const& entry, bool pathNotKnown); + void AddFrameworkItem(LinkEntry const& entry); void DropDirectoryItem(BT<std::string> const& item); - bool CheckSharedLibNoSOName(std::string const& item); - void AddSharedLibNoSOName(std::string const& item); - void HandleBadFullItem(std::string const& item, std::string const& file); + bool CheckSharedLibNoSOName(LinkEntry const& entry); + void AddSharedLibNoSOName(LinkEntry const& entry); + void HandleBadFullItem(LinkEntry const& entry, std::string const& file); // Framework info. void ComputeFrameworkInfo(); void AddFrameworkPath(std::string const& p); std::set<std::string> FrameworkPathsEmitted; - cmsys::RegularExpression SplitFramework; // Linker search path computation. std::unique_ptr<cmOrderDirectories> OrderLinkerSearchPath; @@ -237,4 +250,61 @@ private: void AddLibraryRuntimeInfo(std::string const& fullPath, const cmGeneratorTarget* target); void AddLibraryRuntimeInfo(std::string const& fullPath); + + class FeatureDescriptor + { + public: + FeatureDescriptor() = default; + + const std::string Name; + const bool Supported = false; + const std::string Prefix; + const std::string Suffix; + std::string GetDecoratedItem(std::string const& library, + ItemIsPath isPath) const; + std::string GetDecoratedItem(std::string const& library, + std::string const& linkItem, + std::string const& defaultValue, + ItemIsPath isPath) const; + + protected: + FeatureDescriptor(std::string name, std::string itemFormat); + FeatureDescriptor(std::string name, std::string itemPathFormat, + std::string itemNameFormat); + FeatureDescriptor(std::string name, std::string prefix, + std::string itemPathFormat, std::string itemNameFormat, + std::string suffix); + + FeatureDescriptor(std::string name, std::string prefix, std::string suffix, + bool isGroup); + + private: + std::string ItemPathFormat; + std::string ItemNameFormat; + }; + + class LibraryFeatureDescriptor : public FeatureDescriptor + { + public: + LibraryFeatureDescriptor(std::string name, std::string itemFormat); + LibraryFeatureDescriptor(std::string name, std::string itemPathFormat, + std::string itemNameFormat); + LibraryFeatureDescriptor(std::string name, std::string prefix, + std::string itemPathFormat, + std::string itemNameFormat, std::string suffix); + }; + std::map<std::string, FeatureDescriptor> LibraryFeatureDescriptors; + bool AddLibraryFeature(std::string const& feature); + FeatureDescriptor const& GetLibraryFeature(std::string const& feature) const; + FeatureDescriptor const* FindLibraryFeature( + std::string const& feature) const; + + class GroupFeatureDescriptor : public FeatureDescriptor + { + public: + GroupFeatureDescriptor(std::string name, std::string prefix, + std::string suffix); + }; + std::map<std::string, FeatureDescriptor> GroupFeatureDescriptors; + FeatureDescriptor const& GetGroupFeature(std::string const& feature); }; diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index ef89c8b..3ff16a4 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -218,8 +218,8 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace())); emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace())); - if (cmLinkImplementation const* impl = - depender->GetLinkImplementation(it)) { + if (cmLinkImplementation const* impl = depender->GetLinkImplementation( + it, cmGeneratorTarget::LinkInterfaceFor::Link)) { for (cmLinkImplItem const& lib : impl->Libraries) { // Don't emit the same library twice for this target. if (emitted.insert(lib).second) { diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 0eab368..cdb66f8 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -10,12 +10,12 @@ #include <vector> #include "cmGraphAdjacencyList.h" -#include "cmListFileCache.h" class cmComputeComponentGraph; class cmGeneratorTarget; class cmGlobalGenerator; class cmLinkItem; +class cmListFileBacktrace; class cmSourceFile; class cmTargetDependSet; diff --git a/Source/cmConstStack.h b/Source/cmConstStack.h new file mode 100644 index 0000000..f0bca32 --- /dev/null +++ b/Source/cmConstStack.h @@ -0,0 +1,39 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <memory> + +/** Base class template for CRTP to represent a stack of constant values. + Provide value semantics, but use efficient reference-counting underneath + to avoid copies. */ +template <typename T, typename Stack> +class cmConstStack +{ + struct Entry; + std::shared_ptr<Entry const> TopEntry; + +public: + /** Default-construct an empty stack. */ + cmConstStack(); + + /** Get a stack with the given call context added to the top. */ + Stack Push(T value) const; + + /** Get a stack with the top level removed. + May not be called until after a matching Push. */ + Stack Pop() const; + + /** Get the value at the top of the stack. + This may be called only if Empty() would return false. */ + T const& Top() const; + + /** Return true if this stack is empty. */ + bool Empty() const; + +protected: + cmConstStack(std::shared_ptr<Entry const> parent, T value); + cmConstStack(std::shared_ptr<Entry const> top); +}; diff --git a/Source/cmConstStack.tcc b/Source/cmConstStack.tcc new file mode 100644 index 0000000..81918ee --- /dev/null +++ b/Source/cmConstStack.tcc @@ -0,0 +1,62 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include <cassert> +#include <memory> +#include <utility> + +template <typename T, typename Stack> +struct cmConstStack<T, Stack>::Entry +{ + Entry(std::shared_ptr<Entry const> parent, T value) + : Value(std::move(value)) + , Parent(std::move(parent)) + { + } + + T Value; + std::shared_ptr<Entry const> Parent; +}; + +template <typename T, typename Stack> +cmConstStack<T, Stack>::cmConstStack() = default; + +template <typename T, typename Stack> +Stack cmConstStack<T, Stack>::Push(T value) const +{ + return Stack(this->TopEntry, std::move(value)); +} + +template <typename T, typename Stack> +Stack cmConstStack<T, Stack>::Pop() const +{ + assert(this->TopEntry); + return Stack(this->TopEntry->Parent); +} + +template <typename T, typename Stack> +T const& cmConstStack<T, Stack>::Top() const +{ + assert(this->TopEntry); + return this->TopEntry->Value; +} + +template <typename T, typename Stack> +bool cmConstStack<T, Stack>::Empty() const +{ + return !this->TopEntry; +} + +template <typename T, typename Stack> +cmConstStack<T, Stack>::cmConstStack(std::shared_ptr<Entry const> parent, + T value) + : TopEntry( + std::make_shared<Entry const>(std::move(parent), std::move(value))) +{ +} + +template <typename T, typename Stack> +cmConstStack<T, Stack>::cmConstStack(std::shared_ptr<Entry const> top) + : TopEntry(std::move(top)) +{ +} diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 324ce87..caa413b 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -108,7 +108,7 @@ public: std::string value = makefile->GetSafeDefinition(var); if (warnCMP0067 && !value.empty()) { value.clear(); - warnCMP0067Variables.push_back(var); + warnCMP0067Variables.emplace_back(var); } return value; }; @@ -228,6 +228,8 @@ std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES = std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = "CMAKE_TRY_COMPILE_PLATFORM_VARIABLES"; std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED"; +std::string const kCMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT = + "CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT"; /* GHS Multi platform variables */ std::set<std::string> const ghs_platform_vars{ @@ -335,11 +337,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } else if (argv[i] == "__CMAKE_INTERNAL") { doing = DoingCMakeInternal; } else if (doing == DoingCMakeFlags) { - cmakeFlags.push_back(argv[i]); + cmakeFlags.emplace_back(argv[i]); } else if (doing == DoingCompileDefinitions) { cmExpandList(argv[i], compileDefs); } else if (doing == DoingLinkOptions) { - linkOptions.push_back(argv[i]); + linkOptions.emplace_back(argv[i]); } else if (doing == DoingLinkLibraries) { libsToLink += "\"" + cmTrimWhitespace(argv[i]) + "\" "; if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) { @@ -364,7 +366,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, return -1; } if (tgt->IsImported()) { - targets.push_back(argv[i]); + targets.emplace_back(argv[i]); } } } else if (doing == DoingOutputVariable) { @@ -377,7 +379,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, copyFileError = argv[i]; doing = DoingNone; } else if (doing == DoingSources) { - sources.push_back(argv[i]); + sources.emplace_back(argv[i]); } else if (doing == DoingCMakeInternal) { cmakeInternal = argv[i]; doing = DoingNone; @@ -488,7 +490,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, // Choose sources. if (!useSources) { - sources.push_back(argv[2]); + sources.emplace_back(argv[2]); } // Detect languages to enable. @@ -555,6 +557,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, !msvcRuntimeLibraryDefault->empty() ? "NEW" : "OLD"); } + /* Set Watcom runtime library policy to match our selection. */ + if (cmValue watcomRuntimeLibraryDefault = this->Makefile->GetDefinition( + kCMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT)) { + fprintf(fout, "cmake_policy(SET CMP0136 %s)\n", + !watcomRuntimeLibraryDefault->empty() ? "NEW" : "OLD"); + } + /* Set CUDA architectures policy to match outer project. */ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0104) != cmPolicies::NEW && @@ -720,103 +729,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, fname.c_str()); } - // Forward a set of variables to the inner project cache. - { - std::set<std::string> vars; - vars.insert(&c_properties[lang_property_start], - &c_properties[lang_property_start + lang_property_size]); - vars.insert(&cxx_properties[lang_property_start], - &cxx_properties[lang_property_start + lang_property_size]); - vars.insert(&cuda_properties[lang_property_start], - &cuda_properties[lang_property_start + lang_property_size]); - vars.insert( - &fortran_properties[lang_property_start], - &fortran_properties[lang_property_start + lang_property_size]); - vars.insert(&hip_properties[lang_property_start], - &hip_properties[lang_property_start + lang_property_size]); - vars.insert(&objc_properties[lang_property_start], - &objc_properties[lang_property_start + lang_property_size]); - vars.insert( - &objcxx_properties[lang_property_start], - &objcxx_properties[lang_property_start + lang_property_size]); - vars.insert(&ispc_properties[lang_property_start], - &ispc_properties[lang_property_start + lang_property_size]); - vars.insert(&swift_properties[lang_property_start], - &swift_properties[lang_property_start + lang_property_size]); - vars.insert(kCMAKE_CUDA_ARCHITECTURES); - vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY); - vars.insert(kCMAKE_ENABLE_EXPORTS); - vars.insert(kCMAKE_HIP_ARCHITECTURES); - vars.insert(kCMAKE_HIP_RUNTIME_LIBRARY); - vars.insert(kCMAKE_ISPC_INSTRUCTION_SETS); - vars.insert(kCMAKE_ISPC_HEADER_SUFFIX); - vars.insert(kCMAKE_LINK_SEARCH_END_STATIC); - vars.insert(kCMAKE_LINK_SEARCH_START_STATIC); - vars.insert(kCMAKE_OSX_ARCHITECTURES); - vars.insert(kCMAKE_OSX_DEPLOYMENT_TARGET); - vars.insert(kCMAKE_OSX_SYSROOT); - vars.insert(kCMAKE_APPLE_ARCH_SYSROOTS); - vars.insert(kCMAKE_POSITION_INDEPENDENT_CODE); - vars.insert(kCMAKE_SYSROOT); - vars.insert(kCMAKE_SYSROOT_COMPILE); - vars.insert(kCMAKE_SYSROOT_LINK); - vars.insert(kCMAKE_WARN_DEPRECATED); - vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s); - - if (cmValue varListStr = this->Makefile->GetDefinition( - kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) { - std::vector<std::string> varList = cmExpandedList(*varListStr); - 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(&c_properties[pie_property_start], - &c_properties[pie_property_start + pie_property_size]); - vars.insert(&cxx_properties[pie_property_start], - &cxx_properties[pie_property_start + pie_property_size]); - vars.insert(&cuda_properties[pie_property_start], - &cuda_properties[pie_property_start + pie_property_size]); - vars.insert( - &fortran_properties[pie_property_start], - &fortran_properties[pie_property_start + pie_property_size]); - vars.insert(&hip_properties[pie_property_start], - &hip_properties[pie_property_start + pie_property_size]); - vars.insert(&objc_properties[pie_property_start], - &objc_properties[pie_property_start + pie_property_size]); - vars.insert( - &objcxx_properties[pie_property_start], - &objcxx_properties[pie_property_start + pie_property_size]); - vars.insert(&ispc_properties[pie_property_start], - &ispc_properties[pie_property_start + pie_property_size]); - vars.insert(&swift_properties[pie_property_start], - &swift_properties[pie_property_start + pie_property_size]); - } - - /* for the TRY_COMPILEs we want to be able to specify the architecture. - 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 - have the tests run for each specific architecture. Since - cmLocalGenerator doesn't allow building for "the other" - architecture only via CMAKE_OSX_ARCHITECTURES. - */ - if (cmValue tcArchs = this->Makefile->GetDefinition( - kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) { - vars.erase(kCMAKE_OSX_ARCHITECTURES); - std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + *tcArchs; - cmakeFlags.push_back(std::move(flag)); - } - - for (std::string const& var : vars) { - if (cmValue val = this->Makefile->GetDefinition(var)) { - std::string flag = "-D" + var + "=" + *val; - cmakeFlags.push_back(std::move(flag)); - } - } - } - /* Set the appropriate policy information for ENABLE_EXPORTS */ fprintf(fout, "cmake_policy(SET CMP0065 %s)\n", this->Makefile->GetPolicyStatus(cmPolicies::CMP0065) == @@ -959,12 +871,109 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, projectName = "CMAKE_TRY_COMPILE"; } + // Forward a set of variables to the inner project cache. + if ((this->SrcFileSignature || + this->Makefile->GetPolicyStatus(cmPolicies::CMP0137) == + cmPolicies::NEW) && + !this->Makefile->IsOn("CMAKE_TRY_COMPILE_NO_PLATFORM_VARIABLES")) { + std::set<std::string> vars; + vars.insert(&c_properties[lang_property_start], + &c_properties[lang_property_start + lang_property_size]); + vars.insert(&cxx_properties[lang_property_start], + &cxx_properties[lang_property_start + lang_property_size]); + vars.insert(&cuda_properties[lang_property_start], + &cuda_properties[lang_property_start + lang_property_size]); + vars.insert(&fortran_properties[lang_property_start], + &fortran_properties[lang_property_start + lang_property_size]); + vars.insert(&hip_properties[lang_property_start], + &hip_properties[lang_property_start + lang_property_size]); + vars.insert(&objc_properties[lang_property_start], + &objc_properties[lang_property_start + lang_property_size]); + vars.insert(&objcxx_properties[lang_property_start], + &objcxx_properties[lang_property_start + lang_property_size]); + vars.insert(&ispc_properties[lang_property_start], + &ispc_properties[lang_property_start + lang_property_size]); + vars.insert(&swift_properties[lang_property_start], + &swift_properties[lang_property_start + lang_property_size]); + vars.insert(kCMAKE_CUDA_ARCHITECTURES); + vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY); + vars.insert(kCMAKE_ENABLE_EXPORTS); + vars.insert(kCMAKE_HIP_ARCHITECTURES); + vars.insert(kCMAKE_HIP_RUNTIME_LIBRARY); + vars.insert(kCMAKE_ISPC_INSTRUCTION_SETS); + vars.insert(kCMAKE_ISPC_HEADER_SUFFIX); + vars.insert(kCMAKE_LINK_SEARCH_END_STATIC); + vars.insert(kCMAKE_LINK_SEARCH_START_STATIC); + vars.insert(kCMAKE_OSX_ARCHITECTURES); + vars.insert(kCMAKE_OSX_DEPLOYMENT_TARGET); + vars.insert(kCMAKE_OSX_SYSROOT); + vars.insert(kCMAKE_APPLE_ARCH_SYSROOTS); + vars.insert(kCMAKE_POSITION_INDEPENDENT_CODE); + vars.insert(kCMAKE_SYSROOT); + vars.insert(kCMAKE_SYSROOT_COMPILE); + vars.insert(kCMAKE_SYSROOT_LINK); + vars.insert(kCMAKE_WARN_DEPRECATED); + vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s); + vars.emplace("CMAKE_WATCOM_RUNTIME_LIBRARY"_s); + + if (cmValue varListStr = this->Makefile->GetDefinition( + kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) { + std::vector<std::string> varList = cmExpandedList(*varListStr); + 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(&c_properties[pie_property_start], + &c_properties[pie_property_start + pie_property_size]); + vars.insert(&cxx_properties[pie_property_start], + &cxx_properties[pie_property_start + pie_property_size]); + vars.insert(&cuda_properties[pie_property_start], + &cuda_properties[pie_property_start + pie_property_size]); + vars.insert(&fortran_properties[pie_property_start], + &fortran_properties[pie_property_start + pie_property_size]); + vars.insert(&hip_properties[pie_property_start], + &hip_properties[pie_property_start + pie_property_size]); + vars.insert(&objc_properties[pie_property_start], + &objc_properties[pie_property_start + pie_property_size]); + vars.insert(&objcxx_properties[pie_property_start], + &objcxx_properties[pie_property_start + pie_property_size]); + vars.insert(&ispc_properties[pie_property_start], + &ispc_properties[pie_property_start + pie_property_size]); + vars.insert(&swift_properties[pie_property_start], + &swift_properties[pie_property_start + pie_property_size]); + } + + /* for the TRY_COMPILEs we want to be able to specify the architecture. + 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 + have the tests run for each specific architecture. Since + cmLocalGenerator doesn't allow building for "the other" + architecture only via CMAKE_OSX_ARCHITECTURES. + */ + if (cmValue tcArchs = this->Makefile->GetDefinition( + kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) { + vars.erase(kCMAKE_OSX_ARCHITECTURES); + std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + *tcArchs; + cmakeFlags.emplace_back(std::move(flag)); + } + + for (std::string const& var : vars) { + if (cmValue val = this->Makefile->GetDefinition(var)) { + std::string flag = "-D" + var + "=" + *val; + cmakeFlags.emplace_back(std::move(flag)); + } + } + } + if (this->Makefile->GetState()->UseGhsMultiIDE()) { // Forward the GHS variables to the inner project cache. for (std::string const& var : ghs_platform_vars) { if (cmValue val = this->Makefile->GetDefinition(var)) { std::string flag = "-D" + var + "=" + "'" + *val + "'"; - cmakeFlags.push_back(std::move(flag)); + cmakeFlags.emplace_back(std::move(flag)); } } } @@ -1109,18 +1118,18 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName, // if a config was specified try that first if (cmNonempty(config)) { std::string tmp = cmStrCat('/', *config); - searchDirs.push_back(std::move(tmp)); + searchDirs.emplace_back(std::move(tmp)); } searchDirs.emplace_back("/Debug"); #if defined(__APPLE__) std::string app = "/" + targetName + ".app"; if (cmNonempty(config)) { std::string tmp = cmStrCat('/', *config, app); - searchDirs.push_back(std::move(tmp)); + searchDirs.emplace_back(std::move(tmp)); } std::string tmp = "/Debug" + app; searchDirs.emplace_back(std::move(tmp)); - searchDirs.push_back(std::move(app)); + searchDirs.emplace_back(std::move(app)); #endif searchDirs.emplace_back("/Development"); diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx index a2fac73..2a52d1a 100644 --- a/Source/cmCreateTestSourceList.cxx +++ b/Source/cmCreateTestSourceList.cxx @@ -102,7 +102,6 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args, } std::string functionMapCode; - int numTests = 0; std::vector<std::string>::iterator j; for (i = testsBegin, j = tests_func_name.begin(); i != tests.end(); ++i, ++j) { @@ -121,7 +120,6 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args, functionMapCode += *j; functionMapCode += "\n" " },\n"; - numTests++; } if (!extraInclude.empty()) { mf.AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES", extraInclude); diff --git a/Source/cmEnableTestingCommand.h b/Source/cmEnableTestingCommand.h index 1722511..a1374f3 100644 --- a/Source/cmEnableTestingCommand.h +++ b/Source/cmEnableTestingCommand.h @@ -14,10 +14,10 @@ class cmExecutionStatus; * * Produce the output testfile. This produces a file in the build directory * called CMakeTestfile with a syntax similar to CMakeLists.txt. It contains - * the SUBDIRS() and ADD_TEST() commands from the source CMakeLists.txt + * the subdirs() and add_test() commands from the source CMakeLists.txt * file with CMake variables expanded. Only the subdirs and tests * within the valid control structures are replicated in Testfile - * (i.e. SUBDIRS() and ADD_TEST() commands within IF() commands that are + * (i.e. subdirs() and add_test() commands within IF() commands that are * not entered by CMake are not replicated in Testfile). * Note that CTest expects to find this file in the build directory root; * therefore, this command should be in the source directory root too. diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index bcd8c64..5d0b208 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -4,6 +4,7 @@ #include <sstream> #include <utility> +#include <vector> #include <cmext/algorithm> @@ -60,7 +61,7 @@ void cmExportBuildAndroidMKGenerator::GenerateImportPropertyCode( } void cmExportBuildAndroidMKGenerator::GenerateMissingTargetsCheckCode( - std::ostream&, const std::vector<std::string>&) + std::ostream&) { } @@ -168,7 +169,8 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( // Tell the NDK build system if prebuilt static libraries use C++. if (target->GetType() == cmStateEnums::STATIC_LIBRARY) { - cmLinkImplementation const* li = target->GetLinkImplementation(config); + cmLinkImplementation const* li = target->GetLinkImplementation( + config, cmGeneratorTarget::LinkInterfaceFor::Link); if (cm::contains(li->Languages, "CXX")) { os << "LOCAL_HAS_CPP := true\n"; } diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h index 250564f..1a9a626 100644 --- a/Source/cmExportBuildAndroidMKGenerator.h +++ b/Source/cmExportBuildAndroidMKGenerator.h @@ -6,7 +6,6 @@ #include <iosfwd> #include <string> -#include <vector> #include "cmExportBuildFileGenerator.h" #include "cmExportFileGenerator.h" @@ -21,7 +20,7 @@ class cmGeneratorTarget; * a build tree. This exports the targets to the Android ndk build tool * makefile format for prebuilt libraries. * - * This is used to implement the EXPORT() command. + * This is used to implement the export() command. */ class cmExportBuildAndroidMKGenerator : public cmExportBuildFileGenerator { @@ -56,8 +55,7 @@ protected: std::ostream& os, const std::string& config, cmGeneratorTarget const* target, ImportPropertyMap const& properties) override; - void GenerateMissingTargetsCheckCode( - std::ostream& os, const std::vector<std::string>& missingTargets) override; + void GenerateMissingTargetsCheckCode(std::ostream& os) override; void GenerateInterfaceProperties( cmGeneratorTarget const* target, std::ostream& os, const ImportPropertyMap& properties) override; diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 2773b3b..6ce0c98 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -76,8 +76,6 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateExpectedTargetsCode(os, expectedTargets); } - std::vector<std::string> missingTargets; - // Create all the imported targets. for (cmGeneratorTarget* gte : this->Exports) { this->GenerateImportTargetCode(os, gte, this->GetExportTargetType(gte)); @@ -88,34 +86,34 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", gte, cmGeneratorExpression::BuildInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_SOURCES", gte, cmGeneratorExpression::BuildInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", gte, cmGeneratorExpression::BuildInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gte, cmGeneratorExpression::BuildInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gte, cmGeneratorExpression::BuildInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gte, cmGeneratorExpression::BuildInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gte, cmGeneratorExpression::BuildInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gte, cmGeneratorExpression::BuildInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_LINK_DIRECTORIES", gte, cmGeneratorExpression::BuildInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_LINK_DEPENDS", gte, cmGeneratorExpression::BuildInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte, properties); @@ -132,8 +130,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) gte->GetPolicyStatusCMP0022() != cmPolicies::OLD; if (newCMP0022Behavior) { this->PopulateInterfaceLinkLibrariesProperty( - gte, cmGeneratorExpression::BuildInterface, properties, - missingTargets); + gte, cmGeneratorExpression::BuildInterface, properties); } this->PopulateCompatibleInterfaceProperties(gte, properties); @@ -144,17 +141,16 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) // Generate import file content for each configuration. for (std::string const& c : this->Configurations) { - this->GenerateImportConfig(os, c, missingTargets); + this->GenerateImportConfig(os, c); } - this->GenerateMissingTargetsCheckCode(os, missingTargets); + this->GenerateMissingTargetsCheckCode(os); return true; } void cmExportBuildFileGenerator::GenerateImportTargetsConfig( - std::ostream& os, const std::string& config, std::string const& suffix, - std::vector<std::string>& missingTargets) + std::ostream& os, const std::string& config, std::string const& suffix) { for (cmGeneratorTarget* target : this->Exports) { // Collect import properties for this target. @@ -167,11 +163,10 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig( // Get the rest of the target details. if (this->GetExportTargetType(target) != cmStateEnums::INTERFACE_LIBRARY) { - this->SetImportDetailProperties(config, suffix, target, properties, - missingTargets); + this->SetImportDetailProperties(config, suffix, target, properties); this->SetImportLinkInterface(config, suffix, cmGeneratorExpression::BuildInterface, - target, properties, missingTargets); + target, properties); } // TODO: PUBLIC_HEADER_LOCATION @@ -195,7 +190,7 @@ cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType( // to support transitive usage requirements on other targets that // use the object library. if (targetType == cmStateEnums::OBJECT_LIBRARY && - !this->LG->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) { + !target->Target->HasKnownObjectFileLocation(nullptr)) { targetType = cmStateEnums::INTERFACE_LIBRARY; } return targetType; @@ -259,8 +254,8 @@ void cmExportBuildFileGenerator::SetImportLocationProperty( } void cmExportBuildFileGenerator::HandleMissingTarget( - std::string& link_libs, std::vector<std::string>& missingTargets, - cmGeneratorTarget const* depender, cmGeneratorTarget* dependee) + std::string& link_libs, cmGeneratorTarget const* depender, + cmGeneratorTarget* dependee) { // The target is not in the export. if (!this->AppendMode) { @@ -275,7 +270,7 @@ void cmExportBuildFileGenerator::HandleMissingTarget( missingTarget += dependee->GetExportName(); link_libs += missingTarget; - missingTargets.push_back(std::move(missingTarget)); + this->MissingTargets.emplace_back(std::move(missingTarget)); return; } // We are not appending, so all exported targets should be diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index a7985c7..5681e8f 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -28,7 +28,7 @@ class cmTargetExport; * a build tree. A single file exports information for all * configurations built. * - * This is used to implement the EXPORT() command. + * This is used to implement the export() command. */ class cmExportBuildFileGenerator : public cmExportFileGenerator { @@ -55,13 +55,11 @@ public: protected: // Implement virtual methods from the superclass. bool GenerateMainFile(std::ostream& os) override; - void GenerateImportTargetsConfig( - std::ostream& os, const std::string& config, std::string const& suffix, - std::vector<std::string>& missingTargets) override; + void GenerateImportTargetsConfig(std::ostream& os, const std::string& config, + std::string const& suffix) override; cmStateEnums::TargetType GetExportTargetType( cmGeneratorTarget const* target) const; void HandleMissingTarget(std::string& link_libs, - std::vector<std::string>& missingTargets, cmGeneratorTarget const* depender, cmGeneratorTarget* dependee) override; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index ed1e4cb..452eb99 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExportFileGenerator.h" +#include <array> #include <cassert> #include <cstring> #include <sstream> @@ -15,7 +16,6 @@ #include "cmFileSet.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" -#include "cmGlobalGenerator.h" #include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -106,9 +106,8 @@ bool cmExportFileGenerator::GenerateImportFile() return result; } -void cmExportFileGenerator::GenerateImportConfig( - std::ostream& os, const std::string& config, - std::vector<std::string>& missingTargets) +void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, + const std::string& config) { // Construct the property configuration suffix. std::string suffix = "_"; @@ -119,7 +118,7 @@ void cmExportFileGenerator::GenerateImportConfig( } // Generate the per-config target information. - this->GenerateImportTargetsConfig(os, config, suffix, missingTargets); + this->GenerateImportTargetsConfig(os, config, suffix); } void cmExportFileGenerator::PopulateInterfaceProperty( @@ -136,7 +135,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty( const std::string& propName, const std::string& outputName, cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets) + ImportPropertyMap& properties) { cmValue input = target->GetProperty(propName); if (input) { @@ -149,8 +148,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty( std::string prepro = cmGeneratorExpression::Preprocess(*input, preprocessRule); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, target, - missingTargets); + this->ResolveTargetsInGeneratorExpressions(prepro, target); properties[outputName] = prepro; } } @@ -170,23 +168,29 @@ void cmExportFileGenerator::GenerateRequiredCMakeVersion( bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty( cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets) + ImportPropertyMap& properties) { if (!target->IsLinkable()) { return false; } - cmValue input = target->GetProperty("INTERFACE_LINK_LIBRARIES"); - if (input) { - std::string prepro = - cmGeneratorExpression::Preprocess(*input, preprocessRule); - if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions( - prepro, target, missingTargets, ReplaceFreeTargets); - properties["INTERFACE_LINK_LIBRARIES"] = prepro; - return true; + static const std::array<std::string, 3> linkIfaceProps = { + { "INTERFACE_LINK_LIBRARIES", "INTERFACE_LINK_LIBRARIES_DIRECT", + "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE" } + }; + bool hadINTERFACE_LINK_LIBRARIES = false; + for (std::string const& linkIfaceProp : linkIfaceProps) { + if (cmValue input = target->GetProperty(linkIfaceProp)) { + std::string prepro = + cmGeneratorExpression::Preprocess(*input, preprocessRule); + if (!prepro.empty()) { + this->ResolveTargetsInGeneratorExpressions(prepro, target, + ReplaceFreeTargets); + properties[linkIfaceProp] = prepro; + hadINTERFACE_LINK_LIBRARIES = true; + } } } - return false; + return hadINTERFACE_LINK_LIBRARIES; } static bool isSubDirectory(std::string const& a, std::string const& b) @@ -337,7 +341,7 @@ static void prefixItems(std::string& exportDirs) void cmExportFileGenerator::PopulateSourcesInterface( cmGeneratorTarget const* gt, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets) + ImportPropertyMap& properties) { assert(preprocessRule == cmGeneratorExpression::InstallInterface); @@ -356,7 +360,7 @@ void cmExportFileGenerator::PopulateSourcesInterface( std::string prepro = cmGeneratorExpression::Preprocess(*input, preprocessRule, true); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets); + this->ResolveTargetsInGeneratorExpressions(prepro, gt); if (!checkInterfaceDirs(prepro, gt, propName)) { return; @@ -368,8 +372,7 @@ void cmExportFileGenerator::PopulateSourcesInterface( void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets, - cmTargetExport const& te) + ImportPropertyMap& properties, cmTargetExport const& te) { assert(preprocessRule == cmGeneratorExpression::InstallInterface); @@ -416,7 +419,7 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( std::string prepro = cmGeneratorExpression::Preprocess(includes, preprocessRule, true); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, target, missingTargets); + this->ResolveTargetsInGeneratorExpressions(prepro, target); if (!checkInterfaceDirs(prepro, target, propName)) { return; @@ -428,7 +431,7 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( void cmExportFileGenerator::PopulateLinkDependsInterface( cmGeneratorTarget const* gt, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets) + ImportPropertyMap& properties) { assert(preprocessRule == cmGeneratorExpression::InstallInterface); @@ -447,7 +450,7 @@ void cmExportFileGenerator::PopulateLinkDependsInterface( std::string prepro = cmGeneratorExpression::Preprocess(*input, preprocessRule, true); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets); + this->ResolveTargetsInGeneratorExpressions(prepro, gt); if (!checkInterfaceDirs(prepro, gt, propName)) { return; @@ -459,7 +462,7 @@ void cmExportFileGenerator::PopulateLinkDependsInterface( void cmExportFileGenerator::PopulateLinkDirectoriesInterface( cmGeneratorTarget const* gt, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets) + ImportPropertyMap& properties) { assert(preprocessRule == cmGeneratorExpression::InstallInterface); @@ -478,7 +481,7 @@ void cmExportFileGenerator::PopulateLinkDirectoriesInterface( std::string prepro = cmGeneratorExpression::Preprocess(*input, preprocessRule, true); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets); + this->ResolveTargetsInGeneratorExpressions(prepro, gt); if (!checkInterfaceDirs(prepro, gt, propName)) { return; @@ -490,10 +493,10 @@ void cmExportFileGenerator::PopulateLinkDirectoriesInterface( void cmExportFileGenerator::PopulateInterfaceProperty( const std::string& propName, cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets) + ImportPropertyMap& properties) { this->PopulateInterfaceProperty(propName, propName, target, preprocessRule, - properties, missingTargets); + properties); } static void getPropertyContents(cmGeneratorTarget const* tgt, @@ -598,12 +601,12 @@ void cmExportFileGenerator::GenerateInterfaceProperties( } } -bool cmExportFileGenerator::AddTargetNamespace( - std::string& input, cmGeneratorTarget const* target, - std::vector<std::string>& missingTargets) +bool cmExportFileGenerator::AddTargetNamespace(std::string& input, + cmGeneratorTarget const* target, + cmLocalGenerator const* lg) { cmGeneratorTarget::TargetOrString resolved = - target->ResolveTargetReference(input); + target->ResolveTargetReference(input, lg); cmGeneratorTarget* tgt = resolved.Target; if (!tgt) { @@ -619,7 +622,7 @@ bool cmExportFileGenerator::AddTargetNamespace( input = this->Namespace + tgt->GetExportName(); } else { std::string namespacedTarget; - this->HandleMissingTarget(namespacedTarget, missingTargets, target, tgt); + this->HandleMissingTarget(namespacedTarget, target, tgt); if (!namespacedTarget.empty()) { input = namespacedTarget; } else { @@ -631,10 +634,11 @@ bool cmExportFileGenerator::AddTargetNamespace( void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( std::string& input, cmGeneratorTarget const* target, - std::vector<std::string>& missingTargets, FreeTargetsReplace replace) + FreeTargetsReplace replace) { + cmLocalGenerator const* lg = target->GetLocalGenerator(); if (replace == NoReplaceFreeTargets) { - this->ResolveTargetsInGeneratorExpression(input, target, missingTargets); + this->ResolveTargetsInGeneratorExpression(input, target, lg); return; } std::vector<std::string> parts; @@ -643,13 +647,13 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( std::string sep; input.clear(); for (std::string& li : parts) { - if (cmHasLiteralPrefix(li, CMAKE_DIRECTORY_ID_SEP)) { + if (target->IsLinkLookupScope(li, lg)) { continue; } if (cmGeneratorExpression::Find(li) == std::string::npos) { - this->AddTargetNamespace(li, target, missingTargets); + this->AddTargetNamespace(li, target, lg); } else { - this->ResolveTargetsInGeneratorExpression(li, target, missingTargets); + this->ResolveTargetsInGeneratorExpression(li, target, lg); } input += sep + li; sep = ";"; @@ -658,7 +662,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( std::string& input, cmGeneratorTarget const* target, - std::vector<std::string>& missingTargets) + cmLocalGenerator const* lg) { std::string::size_type pos = 0; std::string::size_type lastPos = pos; @@ -682,7 +686,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( std::string targetName = input.substr(nameStartPos, commaPos - nameStartPos); - if (this->AddTargetNamespace(targetName, target, missingTargets)) { + if (this->AddTargetNamespace(targetName, target, lg)) { input.replace(nameStartPos, commaPos - nameStartPos, targetName); } lastPos = nameStartPos + targetName.size() + 1; @@ -704,7 +708,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( "literal."; break; } - if (!this->AddTargetNamespace(targetName, target, missingTargets)) { + if (!this->AddTargetNamespace(targetName, target, lg)) { errorString = "$<TARGET_NAME:...> requires its parameter to be a " "reachable target."; break; @@ -725,7 +729,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( } std::string libName = input.substr(nameStartPos, endPos - nameStartPos); if (cmGeneratorExpression::IsValidTargetName(libName) && - this->AddTargetNamespace(libName, target, missingTargets)) { + this->AddTargetNamespace(libName, target, lg)) { input.replace(nameStartPos, endPos - nameStartPos, libName); } lastPos = nameStartPos + libName.size() + 1; @@ -747,8 +751,7 @@ void cmExportFileGenerator::ReplaceInstallPrefix(std::string& /*unused*/) void cmExportFileGenerator::SetImportLinkInterface( const std::string& config, std::string const& suffix, cmGeneratorExpression::PreprocessContext preprocessRule, - cmGeneratorTarget const* target, ImportPropertyMap& properties, - std::vector<std::string>& missingTargets) + cmGeneratorTarget const* target, ImportPropertyMap& properties) { // Add the transitive link dependencies for this configuration. cmLinkInterface const* iface = target->GetLinkInterface(config, target); @@ -760,7 +763,7 @@ void cmExportFileGenerator::SetImportLinkInterface( // Policy CMP0022 must not be NEW. this->SetImportLinkProperty( suffix, target, "IMPORTED_LINK_INTERFACE_LIBRARIES", iface->Libraries, - properties, missingTargets, ImportLinkPropertyTargetNames::Yes); + properties, ImportLinkPropertyTargetNames::Yes); return; } @@ -799,7 +802,7 @@ void cmExportFileGenerator::SetImportLinkInterface( std::string prepro = cmGeneratorExpression::Preprocess(*propContent, preprocessRule); if (!prepro.empty()) { - this->ResolveTargetsInGeneratorExpressions(prepro, target, missingTargets, + this->ResolveTargetsInGeneratorExpressions(prepro, target, ReplaceFreeTargets); properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro; } @@ -807,8 +810,7 @@ void cmExportFileGenerator::SetImportLinkInterface( void cmExportFileGenerator::SetImportDetailProperties( const std::string& config, std::string const& suffix, - cmGeneratorTarget* target, ImportPropertyMap& properties, - std::vector<std::string>& missingTargets) + cmGeneratorTarget* target, ImportPropertyMap& properties) { // Get the makefile in which to lookup target information. cmMakefile* mf = target->Makefile; @@ -839,12 +841,11 @@ void cmExportFileGenerator::SetImportDetailProperties( target->GetLinkInterface(config, target)) { this->SetImportLinkProperty( suffix, target, "IMPORTED_LINK_INTERFACE_LANGUAGES", iface->Languages, - properties, missingTargets, ImportLinkPropertyTargetNames::No); + properties, ImportLinkPropertyTargetNames::No); - std::vector<std::string> dummy; this->SetImportLinkProperty( suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps, - properties, dummy, ImportLinkPropertyTargetNames::Yes); + properties, ImportLinkPropertyTargetNames::Yes); if (iface->Multiplicity > 0) { std::string prop = cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix); @@ -885,14 +886,15 @@ template <typename T> void cmExportFileGenerator::SetImportLinkProperty( std::string const& suffix, cmGeneratorTarget const* target, const std::string& propName, std::vector<T> const& entries, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets, - ImportLinkPropertyTargetNames targetNames) + ImportPropertyMap& properties, ImportLinkPropertyTargetNames targetNames) { // Skip the property if there are no entries. if (entries.empty()) { return; } + cmLocalGenerator const* lg = target->GetLocalGenerator(); + // Construct the property value. std::string link_entries; const char* sep = ""; @@ -903,7 +905,7 @@ void cmExportFileGenerator::SetImportLinkProperty( if (targetNames == ImportLinkPropertyTargetNames::Yes) { std::string temp = asString(l); - this->AddTargetNamespace(temp, target, missingTargets); + this->AddTargetNamespace(temp, target, lg); link_entries += temp; } else { link_entries += asString(l); @@ -920,20 +922,23 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) // Protect that file against use with older CMake versions. /* clang-format off */ os << "# Generated by CMake\n\n"; - os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.6)\n" - << " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n" + os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.8)\n" + << " message(FATAL_ERROR \"CMake >= 2.8.0 required\")\n" + << "endif()\n" + << "if(CMAKE_VERSION VERSION_LESS \"2.8.3\")\n" + << " message(FATAL_ERROR \"CMake >= 2.8.3 required\")\n" << "endif()\n"; /* clang-format on */ // Isolate the file policy level. // Support CMake versions as far back as 2.6 but also support using NEW - // policy settings for up to CMake 3.21 (this upper limit may be reviewed + // policy settings for up to CMake 3.22 (this upper limit may be reviewed // and increased from time to time). This reduces the opportunity for CMake // warnings when an older export file is later used with newer CMake // versions. /* clang-format off */ os << "cmake_policy(PUSH)\n" - << "cmake_policy(VERSION 2.6...3.21)\n"; + << "cmake_policy(VERSION 2.8.3...3.22)\n"; /* clang-format on */ } @@ -980,34 +985,36 @@ void cmExportFileGenerator::GenerateExpectedTargetsCode( /* clang-format off */ os << "# Protect against multiple inclusion, which would fail when already " "imported targets are added once more.\n" - "set(_targetsDefined)\n" - "set(_targetsNotDefined)\n" - "set(_expectedTargets)\n" - "foreach(_expectedTarget " << expectedTargets << ")\n" - " list(APPEND _expectedTargets ${_expectedTarget})\n" - " if(NOT TARGET ${_expectedTarget})\n" - " list(APPEND _targetsNotDefined ${_expectedTarget})\n" - " endif()\n" - " if(TARGET ${_expectedTarget})\n" - " list(APPEND _targetsDefined ${_expectedTarget})\n" + "set(_cmake_targets_defined \"\")\n" + "set(_cmake_targets_not_defined \"\")\n" + "set(_cmake_expected_targets \"\")\n" + "foreach(_cmake_expected_target IN ITEMS " << expectedTargets << ")\n" + " list(APPEND _cmake_expected_targets \"${_cmake_expected_target}\")\n" + " if(TARGET \"${_cmake_expected_target}\")\n" + " list(APPEND _cmake_targets_defined \"${_cmake_expected_target}\")\n" + " else()\n" + " list(APPEND _cmake_targets_not_defined \"${_cmake_expected_target}\")\n" " endif()\n" "endforeach()\n" - "if(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n" - " unset(_targetsDefined)\n" - " unset(_targetsNotDefined)\n" - " unset(_expectedTargets)\n" - " set(CMAKE_IMPORT_FILE_VERSION)\n" + "unset(_cmake_expected_target)\n" + "if(_cmake_targets_defined STREQUAL _cmake_expected_targets)\n" + " unset(_cmake_targets_defined)\n" + " unset(_cmake_targets_not_defined)\n" + " unset(_cmake_expected_targets)\n" + " unset(CMAKE_IMPORT_FILE_VERSION)\n" " cmake_policy(POP)\n" " return()\n" "endif()\n" - "if(NOT \"${_targetsDefined}\" STREQUAL \"\")\n" + "if(NOT _cmake_targets_defined STREQUAL \"\")\n" + " string(REPLACE \";\" \", \" _cmake_targets_defined_text \"${_cmake_targets_defined}\")\n" + " string(REPLACE \";\" \", \" _cmake_targets_not_defined_text \"${_cmake_targets_not_defined}\")\n" " message(FATAL_ERROR \"Some (but not all) targets in this export " - "set were already defined.\\nTargets Defined: ${_targetsDefined}\\n" - "Targets not yet defined: ${_targetsNotDefined}\\n\")\n" + "set were already defined.\\nTargets Defined: ${_cmake_targets_defined_text}\\n" + "Targets not yet defined: ${_cmake_targets_not_defined_text}\\n\")\n" "endif()\n" - "unset(_targetsDefined)\n" - "unset(_targetsNotDefined)\n" - "unset(_expectedTargets)\n" + "unset(_cmake_targets_defined)\n" + "unset(_cmake_targets_not_defined)\n" + "unset(_cmake_expected_targets)\n" "\n\n"; /* clang-format on */ } @@ -1113,10 +1120,9 @@ void cmExportFileGenerator::GenerateImportPropertyCode( << "\n"; } -void cmExportFileGenerator::GenerateMissingTargetsCheckCode( - std::ostream& os, const std::vector<std::string>& missingTargets) +void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os) { - if (missingTargets.empty()) { + if (this->MissingTargets.empty()) { /* clang-format off */ os << "# This file does not depend on other imported targets which have\n" "# been exported from the same project but in a separate " @@ -1131,7 +1137,7 @@ void cmExportFileGenerator::GenerateMissingTargetsCheckCode( "foreach(_target "; /* clang-format on */ std::set<std::string> emitted; - for (std::string const& missingTarget : missingTargets) { + for (std::string const& missingTarget : this->MissingTargets) { if (emitted.insert(missingTarget).second) { os << "\"" << missingTarget << "\" "; } @@ -1174,12 +1180,12 @@ void cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os) // but the development package was not installed.). /* clang-format off */ os << "# Loop over all imported files and verify that they actually exist\n" - "foreach(target ${_IMPORT_CHECK_TARGETS} )\n" - " foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n" - " if(NOT EXISTS \"${file}\" )\n" - " message(FATAL_ERROR \"The imported target \\\"${target}\\\"" + "foreach(_cmake_target IN LISTS _cmake_import_check_targets)\n" + " foreach(_cmake_file IN LISTS \"_cmake_import_check_files_for_${_cmake_target}\")\n" + " if(NOT EXISTS \"${_cmake_file}\")\n" + " message(FATAL_ERROR \"The imported target \\\"${_cmake_target}\\\"" " references the file\n" - " \\\"${file}\\\"\n" + " \\\"${_cmake_file}\\\"\n" "but this file does not exist. Possible reasons include:\n" "* The file was deleted, renamed, or moved to another location.\n" "* An install or uninstall procedure did not complete successfully.\n" @@ -1189,9 +1195,11 @@ void cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os) "\")\n" " endif()\n" " endforeach()\n" - " unset(_IMPORT_CHECK_FILES_FOR_${target})\n" + " unset(_cmake_file)\n" + " unset(\"_cmake_import_check_files_for_${_cmake_target}\")\n" "endforeach()\n" - "unset(_IMPORT_CHECK_TARGETS)\n" + "unset(_cmake_target)\n" + "unset(_cmake_import_check_targets)\n" "\n"; /* clang-format on */ } @@ -1204,9 +1212,9 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode( // Construct the imported target name. std::string targetName = cmStrCat(this->Namespace, target->GetExportName()); - os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName + os << "list(APPEND _cmake_import_check_targets " << targetName << " )\n" - "list(APPEND _IMPORT_CHECK_FILES_FOR_" + "list(APPEND _cmake_import_check_files_for_" << targetName << " "; for (std::string const& li : importedLocations) { diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index d50f7e8..d27a555 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -17,6 +17,7 @@ class cmFileSet; class cmGeneratorTarget; +class cmLocalGenerator; class cmTargetExport; #define STRINGIFY_HELPER(X) #X @@ -65,8 +66,7 @@ protected: // Generate per-configuration target information to the given output // stream. - void GenerateImportConfig(std::ostream& os, const std::string& config, - std::vector<std::string>& missingTargets); + void GenerateImportConfig(std::ostream& os, const std::string& config); // Methods to implement export file code generation. virtual void GeneratePolicyHeaderCode(std::ostream& os); @@ -87,8 +87,7 @@ protected: ImportPropertyMap const& properties, const std::set<std::string>& importedLocations); virtual void GenerateImportedFileCheckLoop(std::ostream& os); - virtual void GenerateMissingTargetsCheckCode( - std::ostream& os, const std::vector<std::string>& missingTargets); + virtual void GenerateMissingTargetsCheckCode(std::ostream& os); virtual void GenerateExpectedTargetsCode(std::ostream& os, const std::string& expectedTargets); @@ -98,8 +97,7 @@ protected: void SetImportDetailProperties(const std::string& config, std::string const& suffix, cmGeneratorTarget* target, - ImportPropertyMap& properties, - std::vector<std::string>& missingTargets); + ImportPropertyMap& properties); enum class ImportLinkPropertyTargetNames { @@ -112,31 +110,28 @@ protected: const std::string& propName, std::vector<T> const& entries, ImportPropertyMap& properties, - std::vector<std::string>& missingTargets, ImportLinkPropertyTargetNames targetNames); /** Each subclass knows how to generate its kind of export file. */ virtual bool GenerateMainFile(std::ostream& os) = 0; /** Each subclass knows where the target files are located. */ - virtual void GenerateImportTargetsConfig( - std::ostream& os, const std::string& config, std::string const& suffix, - std::vector<std::string>& missingTargets) = 0; + virtual void GenerateImportTargetsConfig(std::ostream& os, + const std::string& config, + std::string const& suffix) = 0; /** Each subclass knows how to deal with a target that is missing from an * export set. */ virtual void HandleMissingTarget(std::string& link_libs, - std::vector<std::string>& missingTargets, cmGeneratorTarget const* depender, cmGeneratorTarget* dependee) = 0; void PopulateInterfaceProperty(const std::string&, cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext, - ImportPropertyMap& properties, - std::vector<std::string>& missingTargets); + ImportPropertyMap& properties); bool PopulateInterfaceLinkLibrariesProperty( cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets); + ImportPropertyMap& properties); void PopulateInterfaceProperty(const std::string& propName, cmGeneratorTarget const* target, ImportPropertyMap& properties); @@ -148,26 +143,24 @@ protected: void PopulateIncludeDirectoriesInterface( cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets, - cmTargetExport const& te); + ImportPropertyMap& properties, cmTargetExport const& te); void PopulateSourcesInterface( cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets); + ImportPropertyMap& properties); void PopulateLinkDirectoriesInterface( cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets); + ImportPropertyMap& properties); void PopulateLinkDependsInterface( cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets); + ImportPropertyMap& properties); void SetImportLinkInterface( const std::string& config, std::string const& suffix, cmGeneratorExpression::PreprocessContext preprocessRule, - cmGeneratorTarget const* target, ImportPropertyMap& properties, - std::vector<std::string>& missingTargets); + cmGeneratorTarget const* target, ImportPropertyMap& properties); enum FreeTargetsReplace { @@ -177,7 +170,6 @@ protected: void ResolveTargetsInGeneratorExpressions( std::string& input, cmGeneratorTarget const* target, - std::vector<std::string>& missingTargets, FreeTargetsReplace replace = NoReplaceFreeTargets); virtual void GenerateRequiredCMakeVersion(std::ostream& os, @@ -215,19 +207,20 @@ protected: // The set of targets included in the export. std::set<cmGeneratorTarget*> ExportedTargets; + std::vector<std::string> MissingTargets; + private: void PopulateInterfaceProperty(const std::string&, const std::string&, cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext, - ImportPropertyMap& properties, - std::vector<std::string>& missingTargets); + ImportPropertyMap& properties); bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target, - std::vector<std::string>& missingTargets); + cmLocalGenerator const* lg); - void ResolveTargetsInGeneratorExpression( - std::string& input, cmGeneratorTarget const* target, - std::vector<std::string>& missingTargets); + void ResolveTargetsInGeneratorExpression(std::string& input, + cmGeneratorTarget const* target, + cmLocalGenerator const* lg); virtual void ReplaceInstallPrefix(std::string& input); diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx index 80f776e..4e4f8a1 100644 --- a/Source/cmExportInstallAndroidMKGenerator.cxx +++ b/Source/cmExportInstallAndroidMKGenerator.cxx @@ -5,6 +5,7 @@ #include <cstddef> #include <memory> #include <ostream> +#include <vector> #include "cmExportBuildAndroidMKGenerator.h" #include "cmExportSet.h" @@ -86,7 +87,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportPropertyCode( } void cmExportInstallAndroidMKGenerator::GenerateMissingTargetsCheckCode( - std::ostream&, const std::vector<std::string>&) + std::ostream&) { } @@ -132,7 +133,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportedFileChecksCode( } bool cmExportInstallAndroidMKGenerator::GenerateImportFileConfig( - const std::string&, std::vector<std::string>&) + const std::string&) { return true; } diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h index 40978e0..c05751a 100644 --- a/Source/cmExportInstallAndroidMKGenerator.h +++ b/Source/cmExportInstallAndroidMKGenerator.h @@ -7,7 +7,6 @@ #include <iosfwd> #include <set> #include <string> -#include <vector> #include "cmExportFileGenerator.h" #include "cmExportInstallFileGenerator.h" @@ -50,8 +49,7 @@ protected: std::ostream& os, const std::string& config, cmGeneratorTarget const* target, ImportPropertyMap const& properties) override; - void GenerateMissingTargetsCheckCode( - std::ostream& os, const std::vector<std::string>& missingTargets) override; + void GenerateMissingTargetsCheckCode(std::ostream& os) override; void GenerateInterfaceProperties( cmGeneratorTarget const* target, std::ostream& os, const ImportPropertyMap& properties) override; @@ -65,6 +63,5 @@ protected: std::ostream& os, cmGeneratorTarget* target, ImportPropertyMap const& properties, const std::set<std::string>& importedLocations) override; - bool GenerateImportFileConfig(const std::string& config, - std::vector<std::string>&) override; + bool GenerateImportFileConfig(const std::string& config) override; }; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index f232440..adccdfe 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -71,8 +71,6 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) // Compute the relative import prefix for the file this->GenerateImportPrefix(os); - std::vector<std::string> missingTargets; - bool require2_8_12 = false; bool require3_0_0 = false; bool require3_1_0 = false; @@ -90,35 +88,34 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) ImportPropertyMap properties; this->PopulateIncludeDirectoriesInterface( - gt, cmGeneratorExpression::InstallInterface, properties, missingTargets, - *te); + gt, cmGeneratorExpression::InstallInterface, properties, *te); this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt, cmGeneratorExpression::InstallInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", gt, cmGeneratorExpression::InstallInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gt, cmGeneratorExpression::InstallInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gt, cmGeneratorExpression::InstallInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gt, cmGeneratorExpression::InstallInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gt, cmGeneratorExpression::InstallInterface, - properties, missingTargets); + properties); this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gt, cmGeneratorExpression::InstallInterface, - properties, missingTargets); + properties); this->PopulateLinkDirectoriesInterface( - gt, cmGeneratorExpression::InstallInterface, properties, missingTargets); + gt, cmGeneratorExpression::InstallInterface, properties); this->PopulateLinkDependsInterface( - gt, cmGeneratorExpression::InstallInterface, properties, missingTargets); + gt, cmGeneratorExpression::InstallInterface, properties); std::string errorMessage; if (!this->PopulateExportProperties(gt, properties, errorMessage)) { @@ -131,8 +128,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) gt->GetPolicyStatusCMP0022() != cmPolicies::OLD; if (newCMP0022Behavior) { if (this->PopulateInterfaceLinkLibrariesProperty( - gt, cmGeneratorExpression::InstallInterface, properties, - missingTargets) && + gt, cmGeneratorExpression::InstallInterface, properties) && !this->ExportOld) { require2_8_12 = true; } @@ -174,13 +170,13 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) // Don't do this if we only export INTERFACE_LIBRARY targets. if (requiresConfigFiles) { for (std::string const& c : this->Configurations) { - if (!this->GenerateImportFileConfig(c, missingTargets)) { + if (!this->GenerateImportFileConfig(c)) { result = false; } } } - this->GenerateMissingTargetsCheckCode(os, missingTargets); + this->GenerateMissingTargetsCheckCode(os); return result; } @@ -257,12 +253,13 @@ void cmExportInstallFileGenerator::LoadConfigFiles(std::ostream& os) // Now load per-configuration properties for them. /* clang-format off */ os << "# Load information for each installed configuration.\n" - << "get_filename_component(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n" - << "file(GLOB CONFIG_FILES \"${_DIR}/" + << "file(GLOB _cmake_config_files \"${CMAKE_CURRENT_LIST_DIR}/" << this->GetConfigImportFileGlob() << "\")\n" - << "foreach(f ${CONFIG_FILES})\n" - << " include(${f})\n" + << "foreach(_cmake_config_file IN LISTS _cmake_config_files)\n" + << " include(\"${_cmake_config_file}\")\n" << "endforeach()\n" + << "unset(_cmake_config_file)\n" + << "unset(_cmake_config_files)\n" << "\n"; /* clang-format on */ } @@ -273,7 +270,7 @@ void cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string& input) } bool cmExportInstallFileGenerator::GenerateImportFileConfig( - const std::string& config, std::vector<std::string>& missingTargets) + const std::string& config) { // Skip configurations not enabled for this export. if (!this->IEGen->InstallsForConfig(config)) { @@ -305,7 +302,7 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig( this->GenerateImportHeaderCode(os, config); // Generate the per-config target information. - this->GenerateImportConfig(os, config, missingTargets); + this->GenerateImportConfig(os, config); // End with the import file footer. this->GenerateImportFooterCode(os); @@ -317,8 +314,7 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig( } void cmExportInstallFileGenerator::GenerateImportTargetsConfig( - std::ostream& os, const std::string& config, std::string const& suffix, - std::vector<std::string>& missingTargets) + std::ostream& os, const std::string& config, std::string const& suffix) { // Add each target in the set to the export. for (std::unique_ptr<cmTargetExport> const& te : @@ -350,12 +346,11 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig( if (!properties.empty()) { // Get the rest of the target details. cmGeneratorTarget* gtgt = te->Target; - this->SetImportDetailProperties(config, suffix, gtgt, properties, - missingTargets); + this->SetImportDetailProperties(config, suffix, gtgt, properties); this->SetImportLinkInterface(config, suffix, cmGeneratorExpression::InstallInterface, - gtgt, properties, missingTargets); + gtgt, properties); // TODO: PUBLIC_HEADER_LOCATION // This should wait until the build feature propagation stuff @@ -454,8 +449,8 @@ cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType( } void cmExportInstallFileGenerator::HandleMissingTarget( - std::string& link_libs, std::vector<std::string>& missingTargets, - cmGeneratorTarget const* depender, cmGeneratorTarget* dependee) + std::string& link_libs, cmGeneratorTarget const* depender, + cmGeneratorTarget* dependee) { const std::string name = dependee->GetName(); cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator(); @@ -466,7 +461,7 @@ void cmExportInstallFileGenerator::HandleMissingTarget( missingTarget += dependee->GetExportName(); link_libs += missingTarget; - missingTargets.push_back(std::move(missingTarget)); + this->MissingTargets.emplace_back(std::move(missingTarget)); } else { // All exported targets should be known here and should be unique. // This is probably user-error. diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 9374c6b..86fb505 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -57,13 +57,11 @@ public: protected: // Implement virtual methods from the superclass. bool GenerateMainFile(std::ostream& os) override; - void GenerateImportTargetsConfig( - std::ostream& os, const std::string& config, std::string const& suffix, - std::vector<std::string>& missingTargets) override; + void GenerateImportTargetsConfig(std::ostream& os, const std::string& config, + std::string const& suffix) override; cmStateEnums::TargetType GetExportTargetType( cmTargetExport const* targetExport) const; void HandleMissingTarget(std::string& link_libs, - std::vector<std::string>& missingTargets, cmGeneratorTarget const* depender, cmGeneratorTarget* dependee) override; @@ -85,8 +83,7 @@ protected: virtual void CleanupTemporaryVariables(std::ostream&); /** Generate a per-configuration file for the targets. */ - virtual bool GenerateImportFileConfig( - const std::string& config, std::vector<std::string>& missingTargets); + virtual bool GenerateImportFileConfig(const std::string& config); /** Fill in properties indicating installed file locations. */ void SetImportLocationProperty(const std::string& config, diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index db9b05b..e98aa05 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -111,6 +111,8 @@ void cmExportTryCompileFileGenerator::PopulateProperties( std::vector<std::string> props = target->GetPropertyKeys(); // Include special properties that might be relevant here. props.emplace_back("INTERFACE_LINK_LIBRARIES"); + props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT"); + props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE"); for (std::string const& p : props) { cmValue v = target->GetProperty(p); if (!v) { diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index 8a1fd7e..1dd8a20 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -33,12 +33,10 @@ protected: bool GenerateMainFile(std::ostream& os) override; void GenerateImportTargetsConfig(std::ostream&, const std::string&, - std::string const&, - std::vector<std::string>&) override + std::string const&) override { } - void HandleMissingTarget(std::string&, std::vector<std::string>&, - cmGeneratorTarget const*, + void HandleMissingTarget(std::string&, cmGeneratorTarget const*, cmGeneratorTarget*) override { } diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index 80c069f..373a3cf 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -10,7 +10,6 @@ #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmExecutionStatus.h" -#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -20,6 +19,7 @@ #include "cmSystemTools.h" #include "cmake.h" +class cmListFileBacktrace; class cmTarget; static void FinalAction(cmMakefile& makefile, std::string const& name, diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 40e1d2e..dd0540c 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -1728,7 +1728,7 @@ Json::Value Target::DumpArtifacts() // Object libraries have only object files as artifacts. if (this->GT->GetType() == cmStateEnums::OBJECT_LIBRARY) { - if (!this->GT->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) { + if (!this->GT->Target->HasKnownObjectFileLocation(nullptr)) { return artifacts; } std::vector<cmSourceFile const*> objectSources; diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index da2f15f..e4728ac 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -15,6 +15,7 @@ #include <vector> #include <cm/memory> +#include <cm/optional> #include <cm/string_view> #include <cmext/algorithm> #include <cmext/string_view> @@ -1778,6 +1779,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, std::string userpwd; std::vector<std::string> curl_headers; + std::vector<std::pair<std::string, cm::optional<std::string>>> curl_ranges; while (i != args.end()) { if (*i == "TIMEOUT") { @@ -1890,6 +1892,27 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, return false; } curl_headers.push_back(*i); + } else if (*i == "RANGE_START") { + ++i; + if (i == args.end()) { + status.SetError("DOWNLOAD missing value for RANGE_START."); + return false; + } + curl_ranges.emplace_back(*i, cm::nullopt); + } else if (*i == "RANGE_END") { + ++i; + if (curl_ranges.empty()) { + curl_ranges.emplace_back("0", *i); + } else { + auto& last_range = curl_ranges.back(); + if (!last_range.second.has_value()) { + last_range.second = *i; + } else { + status.SetError("Multiple RANGE_END values is provided without " + "the corresponding RANGE_START."); + return false; + } + } } else if (file.empty()) { file = *i; } else { @@ -1899,6 +1922,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, } ++i; } + // Can't calculate hash if we don't save the file. // TODO Incrementally calculate hash in the write callback as the file is // being downloaded so this check can be relaxed. @@ -1984,6 +2008,13 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, check_curl_result(res, "DOWNLOAD cannot set TLS/SSL Verify off: "); } + for (const auto& range : curl_ranges) { + std::string curl_range = range.first + '-' + + (range.second.has_value() ? range.second.value() : ""); + res = ::curl_easy_setopt(curl, CURLOPT_RANGE, curl_range.c_str()); + check_curl_result(res, "DOWNLOAD cannot set range: "); + } + // check to see if a CAINFO file has been specified // command arg comes first std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo); @@ -3476,6 +3507,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args, bool ListOnly = false; std::string Destination; std::vector<std::string> Patterns; + bool Touch = false; }; static auto const parser = cmArgumentParser<Arguments>{} @@ -3483,7 +3515,8 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args, .Bind("VERBOSE"_s, &Arguments::Verbose) .Bind("LIST_ONLY"_s, &Arguments::ListOnly) .Bind("DESTINATION"_s, &Arguments::Destination) - .Bind("PATTERNS"_s, &Arguments::Patterns); + .Bind("PATTERNS"_s, &Arguments::Patterns) + .Bind("TOUCH"_s, &Arguments::Touch); std::vector<std::string> unrecognizedArguments; std::vector<std::string> keywordsMissingValues; @@ -3546,8 +3579,11 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args, return false; } - if (!cmSystemTools::ExtractTar(inFile, parsedArgs.Patterns, - parsedArgs.Verbose)) { + if (!cmSystemTools::ExtractTar( + inFile, parsedArgs.Patterns, + parsedArgs.Touch ? cmSystemTools::cmTarExtractTimestamps::No + : cmSystemTools::cmTarExtractTimestamps::Yes, + parsedArgs.Verbose)) { status.SetError(cmStrCat("failed to extract: ", inFile)); cmSystemTools::SetFatalErrorOccured(); return false; diff --git a/Source/cmFileSet.cxx b/Source/cmFileSet.cxx index 1d1d29e..d6665a2 100644 --- a/Source/cmFileSet.cxx +++ b/Source/cmFileSet.cxx @@ -45,9 +45,12 @@ cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name, if (name == "PRIVATE"_s) { return cmFileSetVisibility::Private; } - mf->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("File set visibility \"", name, "\" is not valid.")); + auto msg = cmStrCat("File set visibility \"", name, "\" is not valid."); + if (mf) { + mf->IssueMessage(MessageType::FATAL_ERROR, msg); + } else { + cmSystemTools::Error(msg); + } return cmFileSetVisibility::Private; } diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index efc4e3a..702d9fe 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -7,6 +7,7 @@ #include <map> #include <utility> +#include <cm/optional> #include <cmext/algorithm> #include "cmCMakePath.h" @@ -20,6 +21,7 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" +#include "cmWindowsRegistry.h" #include "cmake.h" class cmExecutionStatus; @@ -123,6 +125,19 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) doing = DoingNone; this->Required = true; newStyle = true; + } else if (args[j] == "REGISTRY_VIEW") { + if (++j == args.size()) { + this->SetError("missing required argument for \"REGISTRY_VIEW\""); + return false; + } + auto view = cmWindowsRegistry::ToView(args[j]); + if (view) { + this->RegistryView = *view; + } else { + this->SetError( + cmStrCat("given invalid value for \"REGISTRY_VIEW\": ", args[j])); + return false; + } } else if (this->CheckCommonArgument(args[j])) { doing = DoingNone; } else { @@ -267,8 +282,61 @@ void cmFindBase::FillCMakeSystemVariablePath() { cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem]; + const bool install_prefix_in_list = + !this->Makefile->IsOn("CMAKE_FIND_NO_INSTALL_PREFIX"); + const bool remove_install_prefix = this->NoCMakeInstallPath; + const bool add_install_prefix = !this->NoCMakeInstallPath && + this->Makefile->IsDefinitionSet("CMAKE_FIND_USE_INSTALL_PREFIX"); + + // We have 3 possible states for `CMAKE_SYSTEM_PREFIX_PATH` and + // `CMAKE_INSTALL_PREFIX`. + // Either we need to remove `CMAKE_INSTALL_PREFIX`, add + // `CMAKE_INSTALL_PREFIX`, or do nothing. + // + // When we need to remove `CMAKE_INSTALL_PREFIX` we remove the Nth occurrence + // of `CMAKE_INSTALL_PREFIX` from `CMAKE_SYSTEM_PREFIX_PATH`, where `N` is + // computed by `CMakeSystemSpecificInformation.cmake` while constructing + // `CMAKE_SYSTEM_PREFIX_PATH`. This ensures that if projects / toolchains + // have removed `CMAKE_INSTALL_PREFIX` from the list, we don't remove + // some other entry by mistake + long install_prefix_count = -1; + std::string install_path_to_remove; + if (cmValue to_skip = this->Makefile->GetDefinition( + "_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_COUNT")) { + cmStrToLong(to_skip, &install_prefix_count); + } + if (cmValue install_value = this->Makefile->GetDefinition( + "_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE")) { + install_path_to_remove = *install_value; + } + + if (remove_install_prefix && install_prefix_in_list && + install_prefix_count > 0 && !install_path_to_remove.empty()) { + cmValue prefix_paths = + this->Makefile->GetDefinition("CMAKE_SYSTEM_PREFIX_PATH"); + + // remove entry from CMAKE_SYSTEM_PREFIX_PATH + std::vector<std::string> expanded = cmExpandedList(*prefix_paths); + long index_to_remove = 0; + for (const auto& path : expanded) { + if (path == install_path_to_remove && --install_prefix_count == 0) { + break; + } + ++index_to_remove; + } + expanded.erase(expanded.begin() + index_to_remove); + paths.AddPrefixPaths(expanded, + this->Makefile->GetCurrentSourceDirectory().c_str()); + } else if (add_install_prefix && !install_prefix_in_list) { + + paths.AddCMakePrefixPath("CMAKE_INSTALL_PREFIX"); + paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH"); + } else { + // Otherwise the current setup of `CMAKE_SYSTEM_PREFIX_PATH` is correct + paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH"); + } + std::string var = cmStrCat("CMAKE_SYSTEM_", this->CMakePathName, "_PATH"); - paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH"); paths.AddCMakePath(var); if (this->CMakePathName == "PROGRAM") { @@ -496,7 +564,9 @@ cmFindBaseDebugState::~cmFindBaseDebugState() " CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: ", !this->FindCommand->NoSystemEnvironmentPath, "\n", " CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: ", - !this->FindCommand->NoCMakeSystemPath, "\n"); + !this->FindCommand->NoCMakeSystemPath, "\n", + " CMAKE_FIND_USE_INSTALL_PREFIX: ", + !this->FindCommand->NoCMakeInstallPath, "\n"); } buffer += diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 7106e4b..c3fb907 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -11,6 +11,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" @@ -39,6 +40,7 @@ cmFindCommon::cmFindCommon(cmExecutionStatus& status) this->NoCMakeEnvironmentPath = false; this->NoSystemEnvironmentPath = false; this->NoCMakeSystemPath = false; + this->NoCMakeInstallPath = false; // OS X Bundle and Framework search policy. The default is to // search frameworks first on apple. @@ -57,6 +59,17 @@ cmFindCommon::cmFindCommon(cmExecutionStatus& status) this->InitializeSearchPathGroups(); this->DebugMode = false; + + // Windows Registry views + // When policy CMP0134 is not NEW, rely on previous behavior: + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0134) != + cmPolicies::NEW) { + if (this->Makefile->GetDefinition("CMAKE_SIZEOF_VOID_P") == "8") { + this->RegistryView = cmWindowsRegistry::View::Reg64; + } else { + this->RegistryView = cmWindowsRegistry::View::Reg32; + } + } } void cmFindCommon::SetError(std::string const& e) @@ -179,14 +192,15 @@ void cmFindCommon::SelectDefaultMacMode() void cmFindCommon::SelectDefaultSearchModes() { - const std::array<std::pair<bool&, std::string>, 5> search_paths = { + const std::array<std::pair<bool&, std::string>, 6> search_paths = { { { this->NoPackageRootPath, "CMAKE_FIND_USE_PACKAGE_ROOT_PATH" }, { this->NoCMakePath, "CMAKE_FIND_USE_CMAKE_PATH" }, { this->NoCMakeEnvironmentPath, "CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH" }, { this->NoSystemEnvironmentPath, "CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH" }, - { this->NoCMakeSystemPath, "CMAKE_FIND_USE_CMAKE_SYSTEM_PATH" } } + { this->NoCMakeSystemPath, "CMAKE_FIND_USE_CMAKE_SYSTEM_PATH" }, + { this->NoCMakeInstallPath, "CMAKE_FIND_USE_INSTALL_PREFIX" } } }; for (auto const& path : search_paths) { @@ -348,6 +362,8 @@ bool cmFindCommon::CheckCommonArgument(std::string const& arg) this->NoSystemEnvironmentPath = true; } else if (arg == "NO_CMAKE_SYSTEM_PATH") { this->NoCMakeSystemPath = true; + } else if (arg == "NO_CMAKE_INSTALL_PREFIX") { + this->NoCMakeInstallPath = true; } else if (arg == "NO_CMAKE_FIND_ROOT_PATH") { this->FindRootPathMode = RootPathModeNever; } else if (arg == "ONLY_CMAKE_FIND_ROOT_PATH") { diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h index 5d9b3e1..41de797 100644 --- a/Source/cmFindCommon.h +++ b/Source/cmFindCommon.h @@ -11,6 +11,7 @@ #include "cmPathLabel.h" #include "cmSearchPath.h" +#include "cmWindowsRegistry.h" class cmExecutionStatus; class cmMakefile; @@ -130,6 +131,8 @@ protected: bool NoCMakeEnvironmentPath; bool NoSystemEnvironmentPath; bool NoCMakeSystemPath; + bool NoCMakeInstallPath; + cmWindowsRegistry::View RegistryView = cmWindowsRegistry::View::Target; std::vector<std::string> SearchPathSuffixes; diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index f55d838..6586c69 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -13,6 +13,7 @@ #include <utility> #include <cm/memory> +#include <cm/optional> #include <cmext/string_view> #include "cmsys/Directory.hxx" @@ -22,6 +23,7 @@ #include "cmsys/String.h" #include "cmAlgorithms.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -33,6 +35,7 @@ #include "cmSystemTools.h" #include "cmValue.h" #include "cmVersion.h" +#include "cmWindowsRegistry.h" #if defined(__HAIKU__) # include <FindDirectory.h> @@ -42,6 +45,8 @@ class cmExecutionStatus; class cmFileList; +cmFindPackageCommand::PathLabel + cmFindPackageCommand::PathLabel::PackageRedirect("PACKAGE_REDIRECT"); cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::UserRegistry( "PACKAGE_REGISTRY"); cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::Builds( @@ -109,8 +114,10 @@ void cmFindPackageCommand::AppendSearchPathGroups() { std::vector<cmFindCommon::PathLabel>* labels; - // Update the All group with new paths + // Update the All group with new paths. Note that package redirection must + // take precedence over everything else, so it has to be first in the array. labels = &this->PathGroupLabelMap[PathGroup::All]; + labels->insert(labels->begin(), PathLabel::PackageRedirect); labels->insert( std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem), PathLabel::UserRegistry); @@ -122,6 +129,8 @@ void cmFindPackageCommand::AppendSearchPathGroups() // Create the new path objects this->LabeledPaths.insert( + std::make_pair(PathLabel::PackageRedirect, cmSearchPath(this))); + this->LabeledPaths.insert( std::make_pair(PathLabel::UserRegistry, cmSearchPath(this))); this->LabeledPaths.insert( std::make_pair(PathLabel::Builds, cmSearchPath(this))); @@ -262,6 +271,9 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } else if (args[i] == "EXACT") { this->VersionExact = true; doing = DoingNone; + } else if (args[i] == "GLOBAL") { + this->GlobalScope = true; + doing = DoingNone; } else if (args[i] == "MODULE") { moduleArgs.insert(i); doing = DoingNone; @@ -314,6 +326,20 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) // Ignore legacy option. configArgs.insert(i); doing = DoingNone; + } else if (args[i] == "REGISTRY_VIEW") { + if (++i == args.size()) { + this->SetError("missing required argument for \"REGISTRY_VIEW\""); + return false; + } + auto view = cmWindowsRegistry::ToView(args[i]); + if (view) { + this->RegistryView = *view; + this->RegistryViewDefined = true; + } else { + this->SetError( + cmStrCat("given invalid value for \"REGISTRY_VIEW\": ", args[i])); + return false; + } } else if (this->CheckCommonArgument(args[i])) { configArgs.insert(i); doing = DoingNone; @@ -364,6 +390,12 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } } + if (!this->GlobalScope) { + cmValue value( + this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_TARGETS_GLOBAL")); + this->GlobalScope = value.IsOn(); + } + std::vector<std::string> doubledComponents; std::set_intersection(requiredComponents.begin(), requiredComponents.end(), optionalComponents.begin(), optionalComponents.end(), @@ -543,9 +575,62 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->SetModuleVariables(components); + // See if we have been told to delegate to FetchContent or some other + // redirected config package first. We have to check all names that + // find_package() may look for, but only need to invoke the override for the + // first one that matches. + auto overrideNames = this->Names; + if (overrideNames.empty()) { + overrideNames.push_back(this->Name); + } + bool forceConfigMode = false; + const auto redirectsDir = + this->Makefile->GetSafeDefinition("CMAKE_FIND_PACKAGE_REDIRECTS_DIR"); + for (const auto& overrideName : overrideNames) { + const auto nameLower = cmSystemTools::LowerCase(overrideName); + const auto delegatePropName = + cmStrCat("_FetchContent_", nameLower, "_override_find_package"); + const cmValue delegateToFetchContentProp = + this->Makefile->GetState()->GetGlobalProperty(delegatePropName); + if (delegateToFetchContentProp.IsOn()) { + // When this property is set, the FetchContent module has already been + // included at least once, so we know the FetchContent_MakeAvailable() + // command will be defined. Any future find_package() calls after this + // one for this package will by-pass this once-only delegation. + // The following call will typically create a <name>-config.cmake file + // in the redirectsDir, which we still want to process like any other + // config file to ensure we follow normal find_package() processing. + cmListFileFunction func( + "FetchContent_MakeAvailable", 0, 0, + { cmListFileArgument(overrideName, cmListFileArgument::Unquoted, 0) }); + if (!this->Makefile->ExecuteCommand(func, this->Status)) { + return false; + } + } + + if (cmSystemTools::FileExists( + cmStrCat(redirectsDir, '/', nameLower, "-config.cmake")) || + cmSystemTools::FileExists( + cmStrCat(redirectsDir, '/', overrideName, "Config.cmake"))) { + // Force the use of this redirected config package file, regardless of + // the type of find_package() call. Files in the redirectsDir must always + // take priority over everything else. + forceConfigMode = true; + this->UseConfigFiles = true; + this->UseFindModules = false; + this->Names.clear(); + this->Names.emplace_back(overrideName); // Force finding this one + this->Variable = cmStrCat(this->Name, "_DIR"); + this->SetConfigDirCacheVariable(redirectsDir); + break; + } + } + // See if there is a Find<PackageName>.cmake module. bool loadedPackage = false; - if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) { + if (forceConfigMode) { + loadedPackage = this->FindPackageUsingConfigMode(); + } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) { if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) { loadedPackage = true; } else { @@ -758,6 +843,11 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components) id = cmStrCat(this->Name, "_FIND_VERSION_RANGE_MAX"); this->AddFindDefinition(id, this->VersionRangeMax); } + + if (this->RegistryViewDefined) { + this->AddFindDefinition(cmStrCat(this->Name, "_FIND_REGISTRY_VIEW"), + cmWindowsRegistry::FromView(this->RegistryView)); + } } void cmFindPackageCommand::AddFindDefinition(const std::string& var, @@ -1155,19 +1245,24 @@ bool cmFindPackageCommand::FindConfig() } else { init = this->Variable + "-NOTFOUND"; } + // We force the value since we do not get here if it was already set. + this->SetConfigDirCacheVariable(init); + + return found; +} + +void cmFindPackageCommand::SetConfigDirCacheVariable(const std::string& value) +{ std::string help = cmStrCat("The directory containing a CMake configuration file for ", this->Name, '.'); - // We force the value since we do not get here if it was already set. - this->Makefile->AddCacheDefinition(this->Variable, init, help.c_str(), + this->Makefile->AddCacheDefinition(this->Variable, value, help.c_str(), cmStateEnums::PATH, true); if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == cmPolicies::NEW && this->Makefile->IsNormalDefinitionSet(this->Variable)) { - this->Makefile->AddDefinition(this->Variable, init); + this->Makefile->AddDefinition(this->Variable, value); } - - return found; } bool cmFindPackageCommand::FindPrefixedConfig() @@ -1200,6 +1295,11 @@ bool cmFindPackageCommand::ReadListFile(const std::string& f, PolicyScopeRule psr) { const bool noPolicyScope = !this->PolicyScope || psr == NoPolicyScope; + + using ITScope = cmMakefile::ImportedTargetScope; + ITScope scope = this->GlobalScope ? ITScope::Global : ITScope::Local; + cmMakefile::SetGlobalTargetImportScope globScope(this->Makefile, scope); + if (this->Makefile->ReadDependentFile(f, noPolicyScope)) { return true; } @@ -1313,6 +1413,8 @@ inline std::size_t collectPathsForDebug(std::string& buffer, void cmFindPackageCommand::ComputePrefixes() { + this->FillPrefixesPackageRedirect(); + if (!this->NoDefaultPath) { if (!this->NoPackageRootPath) { this->FillPrefixesPackageRoot(); @@ -1346,6 +1448,23 @@ void cmFindPackageCommand::ComputePrefixes() this->ComputeFinalPaths(IgnorePaths::No); } +void cmFindPackageCommand::FillPrefixesPackageRedirect() +{ + cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRedirect]; + + const auto redirectDir = + this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_REDIRECTS_DIR"); + if (redirectDir && !redirectDir->empty()) { + paths.AddPath(*redirectDir); + } + if (this->DebugMode) { + std::string debugBuffer = + "The internally managed CMAKE_FIND_PACKAGE_REDIRECTS_DIR.\n"; + collectPathsForDebug(debugBuffer, paths); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); + } +} + void cmFindPackageCommand::FillPrefixesPackageRoot() { cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot]; @@ -1668,7 +1787,57 @@ void cmFindPackageCommand::FillPrefixesCMakeSystemVariable() { cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem]; - paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH"); + const bool install_prefix_in_list = + !this->Makefile->IsOn("CMAKE_FIND_NO_INSTALL_PREFIX"); + const bool remove_install_prefix = this->NoCMakeInstallPath; + const bool add_install_prefix = !this->NoCMakeInstallPath && + this->Makefile->IsDefinitionSet("CMAKE_FIND_USE_INSTALL_PREFIX"); + + // We have 3 possible states for `CMAKE_SYSTEM_PREFIX_PATH` and + // `CMAKE_INSTALL_PREFIX`. + // Either we need to remove `CMAKE_INSTALL_PREFIX`, add + // `CMAKE_INSTALL_PREFIX`, or do nothing. + // + // When we need to remove `CMAKE_INSTALL_PREFIX` we remove the Nth occurrence + // of `CMAKE_INSTALL_PREFIX` from `CMAKE_SYSTEM_PREFIX_PATH`, where `N` is + // computed by `CMakeSystemSpecificInformation.cmake` while constructing + // `CMAKE_SYSTEM_PREFIX_PATH`. This ensures that if projects / toolchains + // have removed `CMAKE_INSTALL_PREFIX` from the list, we don't remove + // some other entry by mistake + long install_prefix_count = -1; + std::string install_path_to_remove; + if (cmValue to_skip = this->Makefile->GetDefinition( + "_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_COUNT")) { + cmStrToLong(to_skip, &install_prefix_count); + } + if (cmValue install_value = this->Makefile->GetDefinition( + "_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE")) { + install_path_to_remove = *install_value; + } + + if (remove_install_prefix && install_prefix_in_list && + install_prefix_count > 0 && !install_path_to_remove.empty()) { + + cmValue prefix_paths = + this->Makefile->GetDefinition("CMAKE_SYSTEM_PREFIX_PATH"); + // remove entry from CMAKE_SYSTEM_PREFIX_PATH + std::vector<std::string> expanded = cmExpandedList(*prefix_paths); + long count = 0; + for (const auto& path : expanded) { + bool to_add = + !(path == install_path_to_remove && ++count == install_prefix_count); + if (to_add) { + paths.AddPath(path); + } + } + } else if (add_install_prefix && !install_prefix_in_list) { + paths.AddCMakePath("CMAKE_INSTALL_PREFIX"); + paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH"); + } else { + // Otherwise the current setup of `CMAKE_SYSTEM_PREFIX_PATH` is correct + paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH"); + } + paths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); paths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH"); diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index f921bb0..902fa32 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -76,6 +76,7 @@ private: : cmFindCommon::PathLabel(label) { } + static PathLabel PackageRedirect; static PathLabel UserRegistry; static PathLabel Builds; static PathLabel SystemRegistry; @@ -119,8 +120,10 @@ private: }; bool ReadListFile(const std::string& f, PolicyScopeRule psr); void StoreVersionFound(); + void SetConfigDirCacheVariable(const std::string& value); void ComputePrefixes(); + void FillPrefixesPackageRedirect(); void FillPrefixesPackageRoot(); void FillPrefixesCMakeEnvironment(); void FillPrefixesCMakeVariable(); @@ -199,6 +202,8 @@ private: bool UseLibx32Paths = false; bool UseRealPath = false; bool PolicyScope = true; + bool GlobalScope = false; + bool RegistryViewDefined = false; std::string LibraryArchitecture; std::vector<std::string> Names; std::vector<std::string> Configs; diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 780b256..a64e0e4 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -12,6 +12,8 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" +#include "cmWindowsRegistry.h" class cmExecutionStatus; @@ -172,6 +174,18 @@ cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status) this->NamesPerDirAllowed = true; this->VariableDocumentation = "Path to a program."; this->VariableType = cmStateEnums::FILEPATH; + // Windows Registry views + // When policy CMP0134 is not NEW, rely on previous behavior: + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0134) != + cmPolicies::NEW) { + if (this->Makefile->GetDefinition("CMAKE_SIZEOF_VOID_P") == "8") { + this->RegistryView = cmWindowsRegistry::View::Reg64_32; + } else { + this->RegistryView = cmWindowsRegistry::View::Reg32_64; + } + } else { + this->RegistryView = cmWindowsRegistry::View::Both; + } } // cmFindProgramCommand diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 187db73..d35d428 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -167,7 +167,7 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression() const cm::string_view property(this->Top()->Property); return property == "LINK_DIRECTORIES"_s || property == "LINK_OPTIONS"_s || - property == "LINK_DEPENDS"_s; + property == "LINK_DEPENDS"_s || property == "LINK_LIBRARY_OVERRIDE"_s; } bool cmGeneratorExpressionDAGChecker::EvaluatingLinkOptionsExpression() const @@ -189,6 +189,8 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries( } return prop == "LINK_LIBRARIES"_s || prop == "INTERFACE_LINK_LIBRARIES"_s || + prop == "INTERFACE_LINK_LIBRARIES_DIRECT"_s || + prop == "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE"_s || prop == "LINK_INTERFACE_LIBRARIES"_s || prop == "IMPORTED_LINK_INTERFACE_LIBRARIES"_s || cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") || diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 396e9c9..26ffd4b 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1198,6 +1198,152 @@ static const struct LinkLanguageAndIdNode : public cmGeneratorExpressionNode } } linkLanguageAndIdNode; +static const struct LinkLibraryNode : public cmGeneratorExpressionNode +{ + LinkLibraryNode() {} // NOLINT(modernize-use-equals-default) + + int NumExpectedParameters() const override { return OneOrMoreParameters; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!context->HeadTarget || !dagChecker || + !dagChecker->EvaluatingLinkLibraries()) { + reportError(context, content->GetOriginalExpression(), + "$<LINK_LIBRARY:...> may only be used with binary targets " + "to specify link libraries."); + return std::string(); + } + + std::vector<std::string> list; + cmExpandLists(parameters.begin(), parameters.end(), list); + if (list.empty()) { + reportError( + context, content->GetOriginalExpression(), + "$<LINK_LIBRARY:...> expects a feature name as first argument."); + return std::string(); + } + if (list.size() == 1) { + // no libraries specified, ignore this genex + return std::string(); + } + + static cmsys::RegularExpression featureNameValidator("^[A-Za-z0-9_]+$"); + auto const& feature = list.front(); + if (!featureNameValidator.find(feature)) { + reportError(context, content->GetOriginalExpression(), + cmStrCat("The feature name '", feature, + "' contains invalid characters.")); + return std::string(); + } + + const auto LL_BEGIN = cmStrCat("<LINK_LIBRARY:", feature, '>'); + const auto LL_END = cmStrCat("</LINK_LIBRARY:", feature, '>'); + + // filter out $<LINK_LIBRARY:..> tags with same feature + // and raise an error for any different feature + cm::erase_if(list, [&](const std::string& item) -> bool { + return item == LL_BEGIN || item == LL_END; + }); + auto it = + std::find_if(list.cbegin() + 1, list.cend(), + [&feature](const std::string& item) -> bool { + return cmHasPrefix(item, "<LINK_LIBRARY:"_s) && + item.substr(14, item.find('>', 14) - 14) != feature; + }); + if (it != list.cend()) { + reportError( + context, content->GetOriginalExpression(), + "$<LINK_LIBRARY:...> with different features cannot be nested."); + return std::string(); + } + // $<LINK_GROUP:...> must not appear as part of $<LINK_LIBRARY:...> + it = std::find_if(list.cbegin() + 1, list.cend(), + [](const std::string& item) -> bool { + return cmHasPrefix(item, "<LINK_GROUP:"_s); + }); + if (it != list.cend()) { + reportError(context, content->GetOriginalExpression(), + "$<LINK_GROUP:...> cannot be nested inside a " + "$<LINK_LIBRARY:...> expression."); + return std::string(); + } + + list.front() = LL_BEGIN; + list.push_back(LL_END); + + return cmJoin(list, ";"_s); + } +} linkLibraryNode; + +static const struct LinkGroupNode : public cmGeneratorExpressionNode +{ + LinkGroupNode() {} // NOLINT(modernize-use-equals-default) + + int NumExpectedParameters() const override { return OneOrMoreParameters; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!context->HeadTarget || !dagChecker || + !dagChecker->EvaluatingLinkLibraries()) { + reportError(context, content->GetOriginalExpression(), + "$<LINK_GROUP:...> may only be used with binary targets " + "to specify group of link libraries."); + return std::string(); + } + + std::vector<std::string> list; + cmExpandLists(parameters.begin(), parameters.end(), list); + if (list.empty()) { + reportError( + context, content->GetOriginalExpression(), + "$<LINK_GROUP:...> expects a feature name as first argument."); + return std::string(); + } + // $<LINK_GROUP:..> cannot be nested + if (std::find_if(list.cbegin(), list.cend(), + [](const std::string& item) -> bool { + return cmHasPrefix(item, "<LINK_GROUP"_s); + }) != list.cend()) { + reportError(context, content->GetOriginalExpression(), + "$<LINK_GROUP:...> cannot be nested."); + return std::string(); + } + if (list.size() == 1) { + // no libraries specified, ignore this genex + return std::string(); + } + + static cmsys::RegularExpression featureNameValidator("^[A-Za-z0-9_]+$"); + auto const& feature = list.front(); + if (!featureNameValidator.find(feature)) { + reportError(context, content->GetOriginalExpression(), + cmStrCat("The feature name '", feature, + "' contains invalid characters.")); + return std::string(); + } + + const auto LG_BEGIN = cmStrCat( + "<LINK_GROUP:", feature, ':', + cmJoin(cmRange<decltype(list.cbegin())>(list.cbegin() + 1, list.cend()), + "|"_s), + '>'); + const auto LG_END = cmStrCat("</LINK_GROUP:", feature, '>'); + + list.front() = LG_BEGIN; + list.push_back(LG_END); + + return cmJoin(list, ";"_s); + } +} linkGroupNode; + static const struct HostLinkNode : public cmGeneratorExpressionNode { HostLinkNode() {} // NOLINT(modernize-use-equals-default) @@ -1269,7 +1415,8 @@ static std::string getLinkedTargetsContent( { std::string result; if (cmLinkImplementationLibraries const* impl = - target->GetLinkImplementationLibraries(context->Config)) { + target->GetLinkImplementationLibraries( + context->Config, cmGeneratorTarget::LinkInterfaceFor::Usage)) { for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target) { // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our @@ -1638,7 +1785,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode { std::string reason; if (!context->EvaluateForBuildsystem && - !gg->HasKnownObjectFileLocation(&reason)) { + !gt->Target->HasKnownObjectFileLocation(&reason)) { std::ostringstream e; e << "The evaluation of the TARGET_OBJECTS generator expression " "is only suitable for consumption by CMake (limited" @@ -1951,6 +2098,7 @@ class ArtifactPathTag; class ArtifactPdbTag; class ArtifactSonameTag; class ArtifactBundleDirTag; +class ArtifactBundleDirNameTag; class ArtifactBundleContentDirTag; template <typename ArtifactT, typename ComponentT> @@ -2011,6 +2159,12 @@ struct TargetFilesystemArtifactDependency<ArtifactBundleDirTag, { }; template <> +struct TargetFilesystemArtifactDependency<ArtifactBundleDirNameTag, + ArtifactPathTag> + : TargetFilesystemArtifactDependencyCMP0112 +{ +}; +template <> struct TargetFilesystemArtifactDependency<ArtifactBundleContentDirTag, ArtifactPathTag> : TargetFilesystemArtifactDependencyCMP0112 @@ -2138,6 +2292,31 @@ struct TargetFilesystemArtifactResultCreator<ArtifactBundleDirTag> }; template <> +struct TargetFilesystemArtifactResultCreator<ArtifactBundleDirNameTag> +{ + static std::string Create(cmGeneratorTarget* target, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content) + { + if (target->IsImported()) { + ::reportError( + context, content->GetOriginalExpression(), + "TARGET_BUNDLE_DIR_NAME not allowed for IMPORTED targets."); + return std::string(); + } + if (!target->IsBundleOnApple()) { + ::reportError( + context, content->GetOriginalExpression(), + "TARGET_BUNDLE_DIR_NAME is allowed only for Bundle targets."); + return std::string(); + } + + return target->GetAppBundleDirectory(context->Config, + cmGeneratorTarget::BundleDirLevel); + } +}; + +template <> struct TargetFilesystemArtifactResultCreator<ArtifactBundleContentDirTag> { static std::string Create(cmGeneratorTarget* target, @@ -2270,7 +2449,8 @@ struct TargetFilesystemArtifact : public TargetArtifactBase return std::string(); } // Not a dependent target if we are querying for ArtifactDirTag, - // ArtifactNameTag, ArtifactBundleDirTag, and ArtifactBundleContentDirTag + // ArtifactNameTag, ArtifactBundleDirTag, ArtifactBundleDirNameTag, + // and ArtifactBundleContentDirTag TargetFilesystemArtifactDependency<ArtifactT, ComponentT>::AddDependency( target, context); @@ -2311,6 +2491,10 @@ static const TargetFilesystemArtifactNodeGroup<ArtifactPdbTag> static const TargetFilesystemArtifact<ArtifactBundleDirTag, ArtifactPathTag> targetBundleDirNode; +static const TargetFilesystemArtifact<ArtifactBundleDirNameTag, + ArtifactNameTag> + targetBundleDirNameNode; + static const TargetFilesystemArtifact<ArtifactBundleContentDirTag, ArtifactPathTag> targetBundleContentDirNode; @@ -2636,6 +2820,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "TARGET_SONAME_FILE_DIR", &targetSoNameNodeGroup.FileDir }, { "TARGET_PDB_FILE_DIR", &targetPdbNodeGroup.FileDir }, { "TARGET_BUNDLE_DIR", &targetBundleDirNode }, + { "TARGET_BUNDLE_DIR_NAME", &targetBundleDirNameNode }, { "TARGET_BUNDLE_CONTENT_DIR", &targetBundleContentDirNode }, { "STREQUAL", &strEqualNode }, { "EQUAL", &equalNode }, @@ -2668,6 +2853,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "COMPILE_LANGUAGE", &languageNode }, { "LINK_LANG_AND_ID", &linkLanguageAndIdNode }, { "LINK_LANGUAGE", &linkLanguageNode }, + { "LINK_LIBRARY", &linkLibraryNode }, + { "LINK_GROUP", &linkGroupNode }, { "HOST_LINK", &hostLinkNode }, { "DEVICE_LINK", &deviceLinkNode }, { "SHELL_PATH", &shellPathNode } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index fec4679..d8a7c39 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -58,6 +58,10 @@ using LinkInterfaceFor = cmGeneratorTarget::LinkInterfaceFor; const cmsys::RegularExpression FrameworkRegularExpression( "^(.*/)?([^/]*)\\.framework/(.*)$"); const std::string kINTERFACE_LINK_LIBRARIES = "INTERFACE_LINK_LIBRARIES"; +const std::string kINTERFACE_LINK_LIBRARIES_DIRECT = + "INTERFACE_LINK_LIBRARIES_DIRECT"; +const std::string kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE = + "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE"; } template <> @@ -748,6 +752,7 @@ void cmGeneratorTarget::ClearSourcesCache() this->Objects.clear(); this->VisitedConfigsForObjects.clear(); this->LinkImplMap.clear(); + this->LinkImplUsageRequirementsOnlyMap.clear(); } void cmGeneratorTarget::ClearLinkInterfaceCache() @@ -1300,7 +1305,8 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory( &dagChecker, result, excludeImported, language); } - cmLinkImplementation const* impl = this->GetLinkImplementation(config); + cmLinkImplementation const* impl = + this->GetLinkImplementation(config, LinkInterfaceFor::Usage); if (impl != nullptr) { auto runtimeEntries = impl->LanguageRuntimeLibraries.find(language); if (runtimeEntries != impl->LanguageRuntimeLibraries.end()) { @@ -1517,7 +1523,8 @@ void AddLangSpecificImplicitIncludeDirectories( const std::string& config, const std::string& propertyName, IncludeDirectoryFallBack mode, EvaluatedTargetPropertyEntries& entries) { - if (const auto* libraries = target->GetLinkImplementationLibraries(config)) { + if (const auto* libraries = target->GetLinkImplementationLibraries( + config, LinkInterfaceFor::Usage)) { cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, propertyName, nullptr, nullptr }; @@ -1607,7 +1614,7 @@ void AddInterfaceEntries( { if (searchRuntime == IncludeRuntimeInterface::Yes) { if (cmLinkImplementation const* impl = - headTarget->GetLinkImplementation(config)) { + headTarget->GetLinkImplementation(config, interfaceFor)) { entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition; @@ -1621,7 +1628,7 @@ void AddInterfaceEntries( } } else { if (cmLinkImplementationLibraries const* impl = - headTarget->GetLinkImplementationLibraries(config)) { + headTarget->GetLinkImplementationLibraries(config, interfaceFor)) { entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition; addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries, @@ -1636,7 +1643,8 @@ void AddObjectEntries(cmGeneratorTarget const* headTarget, EvaluatedTargetPropertyEntries& entries) { if (cmLinkImplementationLibraries const* impl = - headTarget->GetLinkImplementationLibraries(config)) { + headTarget->GetLinkImplementationLibraries(config, + LinkInterfaceFor::Usage)) { entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition; for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target && @@ -2045,7 +2053,11 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, } else if (ext == "appxmanifest") { kind = SourceKindAppManifest; } else if (ext == "manifest") { - kind = SourceKindManifest; + if (sf->GetPropertyAsBool("VS_DEPLOYMENT_CONTENT")) { + kind = SourceKindExtra; + } else { + kind = SourceKindManifest; + } } else if (ext == "pfx") { kind = SourceKindCertificate; } else if (ext == "xaml") { @@ -2815,7 +2827,7 @@ bool cmGeneratorTarget::ComputeLinkClosure(const std::string& config, // Get languages built in this target. std::unordered_set<std::string> languages; cmLinkImplementation const* impl = - this->GetLinkImplementation(config, secondPass); + this->GetLinkImplementation(config, LinkInterfaceFor::Link, secondPass); assert(impl); languages.insert(impl->Languages.cbegin(), impl->Languages.cend()); @@ -3083,7 +3095,7 @@ cmGeneratorTarget::GetLinkImplementationClosure( std::set<cmGeneratorTarget const*> emitted; cmLinkImplementationLibraries const* impl = - this->GetLinkImplementationLibraries(config); + this->GetLinkImplementationLibraries(config, LinkInterfaceFor::Usage); assert(impl); for (cmLinkImplItem const& lib : impl->Libraries) { @@ -3461,6 +3473,23 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const property = *this->Makefile->GetDefinition("CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR"); } + } else if (property == "native") { + cmValue native = + this->Makefile->GetDefinition("CMAKE_CUDA_ARCHITECTURES_NATIVE"); + if (native.IsEmpty()) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "CUDA_ARCHITECTURES is set to \"native\", but no GPU was detected."); + } + if (compiler == "NVIDIA" && + cmSystemTools::VersionCompare( + cmSystemTools::OP_GREATER_EQUAL, + this->Makefile->GetDefinition("CMAKE_CUDA_COMPILER_VERSION"), + "11.6")) { + flags = cmStrCat(flags, " -arch=", property); + return; + } + property = *native; } struct CudaArchitecture @@ -3808,7 +3837,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( if (this->Makefile->IsOn("APPLE")) { if (cmLinkImplementationLibraries const* impl = - this->GetLinkImplementationLibraries(config)) { + this->GetLinkImplementationLibraries(config, + LinkInterfaceFor::Usage)) { for (cmLinkImplItem const& lib : impl->Libraries) { std::string libDir = cmSystemTools::CollapseFullPath( lib.AsStr(), this->Makefile->GetHomeOutputDirectory()); @@ -4621,7 +4651,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( } std::vector<BT<std::string>>& cmGeneratorTarget::ResolveLinkerWrapper( - std::vector<BT<std::string>>& result, const std::string& language) const + std::vector<BT<std::string>>& result, const std::string& language, + bool joinItems) const { // replace "LINKER:" prefixed elements by actual linker wrapper const std::string wrapper(this->Makefile->GetSafeDefinition( @@ -4680,7 +4711,14 @@ std::vector<BT<std::string>>& cmGeneratorTarget::ResolveLinkerWrapper( std::vector<BT<std::string>> options = wrapOptions( linkerOptions, bt, wrapperFlag, wrapperSep, concatFlagAndArgs); - result.insert(entry, options.begin(), options.end()); + if (joinItems) { + result.insert(entry, + cmJoin(cmRange<decltype(options.cbegin())>( + options.cbegin(), options.cend()), + " "_s)); + } else { + result.insert(entry, options.begin(), options.end()); + } } return result; } @@ -6327,7 +6365,8 @@ cm::string_view missingTargetPossibleReasons = bool cmGeneratorTarget::VerifyLinkItemColons(LinkItemRole role, cmLinkItem const& item) const { - if (item.Target || item.AsStr().find("::") == std::string::npos) { + if (item.Target || cmHasPrefix(item.AsStr(), "<LINK_GROUP:"_s) || + item.AsStr().find("::") == std::string::npos) { return true; } MessageType messageType = MessageType::FATAL_ERROR; @@ -6373,7 +6412,9 @@ bool cmGeneratorTarget::VerifyLinkItemIsTarget(LinkItemRole role, std::string const& str = item.AsStr(); if (!str.empty() && (str[0] == '-' || str[0] == '$' || str[0] == '`' || - str.find_first_of("/\\") != std::string::npos)) { + str.find_first_of("/\\") != std::string::npos || + cmHasPrefix(str, "<LINK_LIBRARY:"_s) || + cmHasPrefix(str, "<LINK_GROUP:"_s))) { return true; } @@ -6669,12 +6710,10 @@ cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem( return maybeItem; } -void cmGeneratorTarget::ExpandLinkItems(std::string const& prop, - cmBTStringRange entries, - std::string const& config, - cmGeneratorTarget const* headTarget, - LinkInterfaceFor interfaceFor, - cmLinkInterface& iface) const +void cmGeneratorTarget::ExpandLinkItems( + std::string const& prop, cmBTStringRange entries, std::string const& config, + cmGeneratorTarget const* headTarget, LinkInterfaceFor interfaceFor, + LinkInterfaceField field, cmLinkInterface& iface) const { if (entries.empty()) { return; @@ -6698,9 +6737,19 @@ void cmGeneratorTarget::ExpandLinkItems(std::string const& prop, this, headTarget->LinkerLanguage)); for (std::string const& lib : libs) { if (cm::optional<cmLinkItem> maybeItem = this->LookupLinkItem( - lib, cge->GetBacktrace(), &scope, LookupSelf::No)) { + lib, cge->GetBacktrace(), &scope, + field == LinkInterfaceField::Libraries ? LookupSelf::No + : LookupSelf::Yes)) { cmLinkItem item = std::move(*maybeItem); + if (field == LinkInterfaceField::HeadInclude) { + iface.HeadInclude.emplace_back(std::move(item)); + continue; + } + if (field == LinkInterfaceField::HeadExclude) { + iface.HeadExclude.emplace_back(std::move(item)); + continue; + } if (!item.Target) { // Report explicitly linked object files separately. std::string const& maybeObj = item.AsStr(); @@ -6803,8 +6852,8 @@ void cmGeneratorTarget::ComputeLinkInterface( emitted.insert(lib); } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - cmLinkImplementation const* impl = - this->GetLinkImplementation(config, secondPass); + cmLinkImplementation const* impl = this->GetLinkImplementation( + config, LinkInterfaceFor::Link, secondPass); for (cmLinkImplItem const& lib : impl->Libraries) { if (emitted.insert(lib).second) { if (lib.Target) { @@ -6826,15 +6875,16 @@ void cmGeneratorTarget::ComputeLinkInterface( this->GetPolicyStatusCMP0022() == cmPolicies::OLD) { // The link implementation is the default link interface. cmLinkImplementationLibraries const* impl = - this->GetLinkImplementationLibrariesInternal(config, headTarget); + this->GetLinkImplementationLibrariesInternal(config, headTarget, + LinkInterfaceFor::Link); iface.ImplementationIsInterface = true; iface.WrongConfigLibraries = impl->WrongConfigLibraries; } if (this->LinkLanguagePropagatesToDependents()) { // Targets using this archive need its language runtime libraries. - if (cmLinkImplementation const* impl = - this->GetLinkImplementation(config, secondPass)) { + if (cmLinkImplementation const* impl = this->GetLinkImplementation( + config, LinkInterfaceFor::Link, secondPass)) { iface.Languages = impl->Languages; } } @@ -7171,7 +7221,9 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( this->GetPolicyStatusCMP0022() != cmPolicies::WARN); if (cmp0022NEW) { // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES. - haveExplicitLibraries = !this->Target->GetLinkInterfaceEntries().empty(); + haveExplicitLibraries = !this->Target->GetLinkInterfaceEntries().empty() || + !this->Target->GetLinkInterfaceDirectEntries().empty() || + !this->Target->GetLinkInterfaceDirectExcludeEntries().empty(); } else { // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a // shared lib or executable. @@ -7236,15 +7288,24 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( if (cmp0022NEW) { // The interface libraries are specified by INTERFACE_LINK_LIBRARIES. // Use its special representation directly to get backtraces. - this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES, - this->Target->GetLinkInterfaceEntries(), config, - headTarget, interfaceFor, iface); + this->ExpandLinkItems( + kINTERFACE_LINK_LIBRARIES, this->Target->GetLinkInterfaceEntries(), + config, headTarget, interfaceFor, LinkInterfaceField::Libraries, iface); + this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT, + this->Target->GetLinkInterfaceDirectEntries(), + config, headTarget, interfaceFor, + LinkInterfaceField::HeadInclude, iface); + this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE, + this->Target->GetLinkInterfaceDirectExcludeEntries(), + config, headTarget, interfaceFor, + LinkInterfaceField::HeadExclude, iface); } else if (explicitLibrariesCMP0022OLD) { // The interface libraries have been explicitly set in pre-CMP0022 style. std::vector<BT<std::string>> entries; entries.emplace_back(*explicitLibrariesCMP0022OLD); this->ExpandLinkItems(linkIfacePropCMP0022OLD, cmMakeRange(entries), - config, headTarget, interfaceFor, iface); + config, headTarget, interfaceFor, + LinkInterfaceField::Libraries, iface); } // If the link interface is explicit, do not fall back to the link impl. @@ -7254,7 +7315,8 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // The link implementation is the default link interface. if (cmLinkImplementationLibraries const* impl = - this->GetLinkImplementationLibrariesInternal(config, headTarget)) { + this->GetLinkImplementationLibrariesInternal(config, headTarget, + interfaceFor)) { iface.Libraries.insert(iface.Libraries.end(), impl->Libraries.begin(), impl->Libraries.end()); if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN && @@ -7264,7 +7326,8 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( cmLinkInterface ifaceNew; this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES, this->Target->GetLinkInterfaceEntries(), config, - headTarget, interfaceFor, ifaceNew); + headTarget, interfaceFor, + LinkInterfaceField::Libraries, ifaceNew); if (ifaceNew.Libraries != iface.Libraries) { std::string oldLibraries = cmJoin(impl->Libraries, ";"); std::string newLibraries = cmJoin(ifaceNew.Libraries, ";"); @@ -7404,8 +7467,17 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( iface.LibrariesDone = true; iface.Multiplicity = info->Multiplicity; cmExpandList(info->Languages, iface.Languages); + this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT, + cmMakeRange(info->LibrariesHeadInclude), config, + headTarget, interfaceFor, + LinkInterfaceField::HeadInclude, iface); + this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE, + cmMakeRange(info->LibrariesHeadExclude), config, + headTarget, interfaceFor, + LinkInterfaceField::HeadExclude, iface); this->ExpandLinkItems(info->LibrariesProp, cmMakeRange(info->Libraries), - config, headTarget, interfaceFor, iface); + config, headTarget, interfaceFor, + LinkInterfaceField::Libraries, iface); std::vector<std::string> deps = cmExpandedList(info->SharedDeps); LookupLinkItemScope scope{ this->LocalGenerator }; for (std::string const& dep : deps) { @@ -7498,6 +7570,14 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, } } } + for (BT<std::string> const& entry : + this->Target->GetLinkInterfaceDirectEntries()) { + info.LibrariesHeadInclude.emplace_back(entry); + } + for (BT<std::string> const& entry : + this->Target->GetLinkInterfaceDirectExcludeEntries()) { + info.LibrariesHeadExclude.emplace_back(entry); + } if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { if (loc) { info.LibName = *loc; @@ -7615,27 +7695,30 @@ cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap( } const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation( - const std::string& config) const + const std::string& config, LinkInterfaceFor implFor) const { - return this->GetLinkImplementation(config, false); + return this->GetLinkImplementation(config, implFor, false); } const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation( - const std::string& config, bool secondPass) const + const std::string& config, LinkInterfaceFor implFor, bool secondPass) const { // There is no link implementation for targets that cannot compile sources. if (!this->CanCompileSources()) { return nullptr; } - cmOptionalLinkImplementation& impl = - this->LinkImplMap[cmSystemTools::UpperCase(config)][this]; + HeadToLinkImplementationMap& hm = + (implFor == LinkInterfaceFor::Usage + ? this->GetHeadToLinkImplementationUsageRequirementsMap(config) + : this->GetHeadToLinkImplementationMap(config)); + cmOptionalLinkImplementation& impl = hm[this]; if (secondPass) { impl = cmOptionalLinkImplementation(); } if (!impl.LibrariesDone) { impl.LibrariesDone = true; - this->ComputeLinkImplementationLibraries(config, impl, this); + this->ComputeLinkImplementationLibraries(config, impl, this, implFor); } if (!impl.LanguagesDone) { impl.LanguagesDone = true; @@ -7645,6 +7728,21 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation( return &impl; } +cmGeneratorTarget::HeadToLinkImplementationMap& +cmGeneratorTarget::GetHeadToLinkImplementationMap( + std::string const& config) const +{ + return this->LinkImplMap[cmSystemTools::UpperCase(config)]; +} + +cmGeneratorTarget::HeadToLinkImplementationMap& +cmGeneratorTarget::GetHeadToLinkImplementationUsageRequirementsMap( + std::string const& config) const +{ + return this + ->LinkImplUsageRequirementsOnlyMap[cmSystemTools::UpperCase(config)]; +} + bool cmGeneratorTarget::GetConfigCommonSourceFilesForXcode( std::vector<cmSourceFile*>& files) const { @@ -7885,7 +7983,7 @@ bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const return true; } if (cmLinkImplementationLibraries const* impl = - this->GetLinkImplementationLibraries(config)) { + this->GetLinkImplementationLibraries(config, LinkInterfaceFor::Link)) { return !impl->Libraries.empty(); } return false; @@ -7893,14 +7991,15 @@ bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const cmLinkImplementationLibraries const* cmGeneratorTarget::GetLinkImplementationLibraries( - const std::string& config) const + const std::string& config, LinkInterfaceFor implFor) const { - return this->GetLinkImplementationLibrariesInternal(config, this); + return this->GetLinkImplementationLibrariesInternal(config, this, implFor); } cmLinkImplementationLibraries const* cmGeneratorTarget::GetLinkImplementationLibrariesInternal( - const std::string& config, cmGeneratorTarget const* head) const + const std::string& config, cmGeneratorTarget const* head, + LinkInterfaceFor implFor) const { // There is no link implementation for targets that cannot compile sources. if (!this->CanCompileSources()) { @@ -7909,7 +8008,9 @@ cmGeneratorTarget::GetLinkImplementationLibrariesInternal( // Populate the link implementation libraries for this configuration. HeadToLinkImplementationMap& hm = - this->LinkImplMap[cmSystemTools::UpperCase(config)]; + (implFor == LinkInterfaceFor::Usage + ? this->GetHeadToLinkImplementationUsageRequirementsMap(config) + : this->GetHeadToLinkImplementationMap(config)); // If the link implementation does not depend on the head target // then re-use the one from the head we computed first. @@ -7920,7 +8021,7 @@ cmGeneratorTarget::GetLinkImplementationLibrariesInternal( cmOptionalLinkImplementation& impl = hm[head]; if (!impl.LibrariesDone) { impl.LibrariesDone = true; - this->ComputeLinkImplementationLibraries(config, impl, head); + this->ComputeLinkImplementationLibraries(config, impl, head, implFor); } return &impl; } @@ -7931,9 +8032,118 @@ bool cmGeneratorTarget::IsNullImpliedByLinkLibraries( return cm::contains(this->LinkImplicitNullProperties, p); } +namespace { +class TransitiveLinkImpl +{ + cmGeneratorTarget const* Self; + std::string const& Config; + LinkInterfaceFor ImplFor; + cmLinkImplementation& Impl; + + std::set<cmLinkItem> Emitted; + std::set<cmLinkItem> Excluded; + std::unordered_set<cmGeneratorTarget const*> Followed; + + void Follow(cmGeneratorTarget const* target); + +public: + TransitiveLinkImpl(cmGeneratorTarget const* self, std::string const& config, + LinkInterfaceFor implFor, cmLinkImplementation& impl) + : Self(self) + , Config(config) + , ImplFor(implFor) + , Impl(impl) + { + } + + void Compute(); +}; + +void TransitiveLinkImpl::Follow(cmGeneratorTarget const* target) +{ + if (!target || !this->Followed.insert(target).second || + target->GetPolicyStatusCMP0022() == cmPolicies::OLD || + target->GetPolicyStatusCMP0022() == cmPolicies::WARN) { + return; + } + + // Get this target's usage requirements. + cmLinkInterfaceLibraries const* iface = + target->GetLinkInterfaceLibraries(this->Config, this->Self, this->ImplFor); + if (!iface) { + return; + } + if (iface->HadContextSensitiveCondition) { + this->Impl.HadContextSensitiveCondition = true; + } + + // Process 'INTERFACE_LINK_LIBRARIES_DIRECT' usage requirements. + for (cmLinkItem const& item : iface->HeadInclude) { + // Inject direct dependencies from the item's usage requirements + // before the item itself. + this->Follow(item.Target); + + // Add the item itself, but at most once. + if (this->Emitted.insert(item).second) { + this->Impl.Libraries.emplace_back(item, /* checkCMP0027= */ false); + } + } + + // Follow transitive dependencies. + for (cmLinkItem const& item : iface->Libraries) { + this->Follow(item.Target); + } + + // Record exclusions from 'INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE' + // usage requirements. + for (cmLinkItem const& item : iface->HeadExclude) { + this->Excluded.insert(item); + } +} + +void TransitiveLinkImpl::Compute() +{ + // Save the original items and start with an empty list. + std::vector<cmLinkImplItem> original = std::move(this->Impl.Libraries); + + // Avoid injecting any original items as usage requirements. + // This gives LINK_LIBRARIES final control over the order + // if it explicitly lists everything. + this->Emitted.insert(original.cbegin(), original.cend()); + + // Process each original item. + for (cmLinkImplItem& item : original) { + // Inject direct dependencies listed in 'INTERFACE_LINK_LIBRARIES_DIRECT' + // usage requirements before the item itself. + this->Follow(item.Target); + + // Add the item itself. + this->Impl.Libraries.emplace_back(std::move(item)); + } + + // Remove items listed in 'INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE' + // usage requirements found through any dependency above. + this->Impl.Libraries.erase( + std::remove_if(this->Impl.Libraries.begin(), this->Impl.Libraries.end(), + [this](cmLinkImplItem const& item) { + return this->Excluded.find(item) != this->Excluded.end(); + }), + this->Impl.Libraries.end()); +} + +void ComputeLinkImplTransitive(cmGeneratorTarget const* self, + std::string const& config, + LinkInterfaceFor implFor, + cmLinkImplementation& impl) +{ + TransitiveLinkImpl transitiveLinkImpl(self, config, implFor, impl); + transitiveLinkImpl.Compute(); +} +} + void cmGeneratorTarget::ComputeLinkImplementationLibraries( const std::string& config, cmOptionalLinkImplementation& impl, - cmGeneratorTarget const* head) const + cmGeneratorTarget const* head, LinkInterfaceFor implFor) const { cmLocalGenerator const* lg = this->LocalGenerator; cmMakefile const* mf = lg->GetMakefile(); @@ -7944,6 +8154,20 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( // Keep this logic in sync with ExpandLinkItems. cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr, nullptr); + // The $<LINK_ONLY> expression may be used to specify link dependencies + // that are otherwise excluded from usage requirements. + if (implFor == LinkInterfaceFor::Usage) { + switch (this->GetPolicyStatusCMP0131()) { + case cmPolicies::WARN: + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + dagChecker.SetTransitivePropertiesOnly(); + break; + } + } cmGeneratorExpression ge(entry.Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(entry.Value); @@ -8037,6 +8261,11 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards); } + // Update the list of direct link dependencies from usage requirements. + if (head == this) { + ComputeLinkImplTransitive(this, config, implFor, impl); + } + // Get the list of configurations considered to be DEBUG. std::vector<std::string> debugConfigs = this->Makefile->GetCMakeInstance()->GetDebugConfigs(); @@ -8295,3 +8524,176 @@ cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType( // has to be set manually for C# targets. return this->IsCSharpOnly() ? ManagedType::Managed : ManagedType::Native; } + +bool cmGeneratorTarget::AddHeaderSetVerification() +{ + if (!this->GetPropertyAsBool("VERIFY_HEADER_SETS")) { + return true; + } + + if (this->GetType() != cmStateEnums::STATIC_LIBRARY && + this->GetType() != cmStateEnums::SHARED_LIBRARY && + this->GetType() != cmStateEnums::UNKNOWN_LIBRARY && + this->GetType() != cmStateEnums::OBJECT_LIBRARY && + this->GetType() != cmStateEnums::INTERFACE_LIBRARY && + !this->IsExecutableWithExports()) { + return true; + } + + cmTarget* verifyTarget = nullptr; + + auto interfaceFileSetEntries = this->Target->GetInterfaceHeaderSetsEntries(); + + std::set<cmFileSet*> fileSets; + auto const addFileSets = [&fileSets, this](const cmBTStringRange& entries) { + for (auto const& entry : entries) { + for (auto const& name : cmExpandedList(entry.Value)) { + fileSets.insert(this->Target->GetFileSet(name)); + } + } + }; + addFileSets(interfaceFileSetEntries); + + cm::optional<std::set<std::string>> languages; + for (auto* fileSet : fileSets) { + auto dirCges = fileSet->CompileDirectoryEntries(); + auto fileCges = fileSet->CompileFileEntries(); + + static auto const contextSensitive = + [](const std::unique_ptr<cmCompiledGeneratorExpression>& cge) { + return cge->GetHadContextSensitiveCondition(); + }; + bool dirCgesContextSensitive = false; + bool fileCgesContextSensitive = false; + + std::vector<std::string> dirs; + std::map<std::string, std::vector<std::string>> filesPerDir; + bool first = true; + for (auto const& config : this->Makefile->GetGeneratorConfigs( + cmMakefile::GeneratorConfigQuery::IncludeEmptyConfig)) { + if (first || dirCgesContextSensitive) { + dirs = fileSet->EvaluateDirectoryEntries(dirCges, this->LocalGenerator, + config, this); + dirCgesContextSensitive = + std::any_of(dirCges.begin(), dirCges.end(), contextSensitive); + } + if (first || fileCgesContextSensitive) { + filesPerDir.clear(); + for (auto const& fileCge : fileCges) { + fileSet->EvaluateFileEntry(dirs, filesPerDir, fileCge, + this->LocalGenerator, config, this); + if (fileCge->GetHadContextSensitiveCondition()) { + fileCgesContextSensitive = true; + } + } + } + + for (auto const& files : filesPerDir) { + for (auto const& file : files.second) { + std::string filename = this->GenerateHeaderSetVerificationFile( + *this->Makefile->GetOrCreateSource(file), files.first, languages); + if (filename.empty()) { + continue; + } + + if (!verifyTarget) { + { + cmMakefile::PolicyPushPop polScope(this->Makefile); + this->Makefile->SetPolicy(cmPolicies::CMP0119, cmPolicies::NEW); + verifyTarget = this->Makefile->AddLibrary( + cmStrCat(this->GetName(), "_verify_header_sets"), + cmStateEnums::OBJECT_LIBRARY, {}, true); + } + + verifyTarget->AddLinkLibrary( + *this->Makefile, this->GetName(), + cmTargetLinkLibraryType::GENERAL_LibraryType); + verifyTarget->SetProperty("AUTOMOC", "OFF"); + verifyTarget->SetProperty("AUTORCC", "OFF"); + verifyTarget->SetProperty("AUTOUIC", "OFF"); + verifyTarget->SetProperty("DISABLE_PRECOMPILE_HEADERS", "ON"); + verifyTarget->SetProperty("UNITY_BUILD", "OFF"); + } + + if (fileCgesContextSensitive) { + filename = cmStrCat("$<$<CONFIG:", config, ">:", filename, ">"); + } + verifyTarget->AddSource(filename); + } + } + + if (!dirCgesContextSensitive && !fileCgesContextSensitive) { + break; + } + first = false; + } + } + + if (verifyTarget) { + this->LocalGenerator->AddGeneratorTarget( + cm::make_unique<cmGeneratorTarget>(verifyTarget, this->LocalGenerator)); + } + + return true; +} + +std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile( + cmSourceFile& source, const std::string& dir, + cm::optional<std::set<std::string>>& languages) const +{ + std::string extension; + std::string language = source.GetOrDetermineLanguage(); + + if (language.empty()) { + if (!languages) { + languages.emplace(); + for (auto const& tgtSource : this->GetAllConfigSources()) { + auto const& tgtSourceLanguage = + tgtSource.Source->GetOrDetermineLanguage(); + if (tgtSourceLanguage == "CXX") { + languages->insert("CXX"); + break; // C++ overrides everything else, so we don't need to keep + // checking. + } + if (tgtSourceLanguage == "C") { + languages->insert("C"); + } + } + } + + if (languages->count("CXX")) { + language = "CXX"; + } else if (languages->count("C")) { + language = "C"; + } + } + + if (language == "C") { + extension = ".c"; + } else if (language == "CXX") { + extension = ".cxx"; + } else { + return ""; + } + + std::string headerFilename = dir; + if (!headerFilename.empty()) { + headerFilename += '/'; + } + headerFilename += source.GetLocation().GetName(); + + auto filename = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), + '/', this->GetName(), "_verify_header_sets/", + headerFilename, extension); + auto* verificationSource = this->Makefile->GetOrCreateSource(filename); + verificationSource->SetProperty("LANGUAGE", language); + + cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(filename)); + + cmGeneratedFileStream fout(filename); + fout.SetCopyIfDifferent(true); + fout << "#include <" << headerFilename << ">\n"; + fout.close(); + + return filename; +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 7cf1720..b927848 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -399,17 +399,18 @@ public: LinkClosure const* GetLinkClosure(const std::string& config) const; cmLinkImplementation const* GetLinkImplementation( - const std::string& config) const; + const std::string& config, LinkInterfaceFor implFor) const; void ComputeLinkImplementationLanguages( const std::string& config, cmOptionalLinkImplementation& impl) const; cmLinkImplementationLibraries const* GetLinkImplementationLibraries( - const std::string& config) const; + const std::string& config, LinkInterfaceFor implFor) const; void ComputeLinkImplementationLibraries(const std::string& config, cmOptionalLinkImplementation& impl, - const cmGeneratorTarget* head) const; + const cmGeneratorTarget* head, + LinkInterfaceFor implFor) const; struct TargetOrString { @@ -513,7 +514,8 @@ public: std::string const& config, std::string const& language) const; std::vector<BT<std::string>>& ResolveLinkerWrapper( - std::vector<BT<std::string>>& result, const std::string& language) const; + std::vector<BT<std::string>>& result, const std::string& language, + bool joinItems = false) const; void GetStaticLibraryLinkOptions(std::vector<std::string>& result, const std::string& config, @@ -854,6 +856,9 @@ public: std::string GetFortranModuleDirectory(std::string const& working_dir) const; bool IsFortranBuildingInstrinsicModules() const; + bool IsLinkLookupScope(std::string const& n, + cmLocalGenerator const*& lg) const; + cmValue GetSourcesProperty() const; void AddISPCGeneratedHeader(std::string const& header, @@ -866,6 +871,11 @@ public: std::vector<std::string> GetGeneratedISPCObjects( std::string const& config) const; + bool AddHeaderSetVerification(); + std::string GenerateHeaderSetVerificationFile( + cmSourceFile& source, const std::string& dir, + cm::optional<std::set<std::string>>& languages) const; + private: void AddSourceCommon(const std::string& src, bool before = false); @@ -983,6 +993,7 @@ private: const cmGeneratorTarget* head, bool secondPass) const; cmLinkImplementation const* GetLinkImplementation(const std::string& config, + LinkInterfaceFor implFor, bool secondPass) const; enum class LinkItemRole @@ -1006,6 +1017,8 @@ private: std::string Languages; std::string LibrariesProp; std::vector<BT<std::string>> Libraries; + std::vector<BT<std::string>> LibrariesHeadInclude; + std::vector<BT<std::string>> LibrariesHeadExclude; std::string SharedDeps; }; @@ -1063,13 +1076,16 @@ private: std::unordered_map<std::string, std::vector<std::string>> ISPCGeneratedObjects; - bool IsLinkLookupScope(std::string const& n, - cmLocalGenerator const*& lg) const; - + enum class LinkInterfaceField + { + Libraries, + HeadExclude, + HeadInclude, + }; void ExpandLinkItems(std::string const& prop, cmBTStringRange entries, std::string const& config, const cmGeneratorTarget* headTarget, - LinkInterfaceFor interfaceFor, + LinkInterfaceFor interfaceFor, LinkInterfaceField field, cmLinkInterface& iface) const; struct LookupLinkItemScope @@ -1099,9 +1115,16 @@ private: }; using LinkImplMapType = std::map<std::string, HeadToLinkImplementationMap>; mutable LinkImplMapType LinkImplMap; + mutable LinkImplMapType LinkImplUsageRequirementsOnlyMap; + + HeadToLinkImplementationMap& GetHeadToLinkImplementationMap( + std::string const& config) const; + HeadToLinkImplementationMap& GetHeadToLinkImplementationUsageRequirementsMap( + std::string const& config) const; cmLinkImplementationLibraries const* GetLinkImplementationLibrariesInternal( - const std::string& config, const cmGeneratorTarget* head) const; + const std::string& config, const cmGeneratorTarget* head, + LinkInterfaceFor implFor) const; bool ComputeOutputDir(const std::string& config, cmStateEnums::ArtifactType artifact, std::string& out) const; diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 47cefae..bf019c3 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -36,11 +36,6 @@ cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target) static_cast<cmLocalGhsMultiGenerator*>(target->GetLocalGenerator())) , Makefile(target->Target->GetMakefile()) , Name(target->GetName()) -#ifdef _WIN32 - , CmdWindowsShell(true) -#else - , CmdWindowsShell(false) -#endif { // Store the configuration name that is being used if (cmValue config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { @@ -112,12 +107,6 @@ void cmGhsMultiTargetGenerator::Generate() return; } - // Tell the global generator the name of the project file - this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", - this->Name); - this->GeneratorTarget->Target->SetProperty( - "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType)); - this->GenerateTarget(); } @@ -126,7 +115,14 @@ void cmGhsMultiTargetGenerator::GenerateTarget() // Open the target file in copy-if-different mode. std::string fproj = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', - this->Name, cmGlobalGhsMultiGenerator::FILE_EXTENSION); + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), + '/', this->Name, cmGlobalGhsMultiGenerator::FILE_EXTENSION); + + // Tell the global generator the name of the project file + this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", fproj); + this->GeneratorTarget->Target->SetProperty( + "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType)); + cmGeneratedFileStream fout(fproj); fout.SetCopyIfDifferent(true); @@ -160,10 +156,16 @@ void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout, { std::string outpath; + /* Determine paths from the target project file to where the output artifacts + * need to be located. + */ if (this->TagType != GhsMultiGpj::SUBPROJECT) { // set target binary file destination - outpath = this->GeneratorTarget->GetDirectory(config); - outpath = this->LocalGenerator->MaybeRelativeToCurBinDir(outpath); + std::string binpath = cmStrCat( + this->LocalGenerator->GetCurrentBinaryDirectory(), '/', + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget)); + outpath = cmSystemTools::RelativePath( + binpath, this->GeneratorTarget->GetDirectory(config)); /* clang-format off */ fout << " :binDirRelative=\"" << outpath << "\"\n" " -o \"" << this->TargetNameReal << "\"\n"; @@ -171,7 +173,7 @@ void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout, } // set target object file destination - outpath = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + outpath = "."; fout << " :outputDirRelative=\"" << outpath << "\"\n"; } @@ -187,6 +189,7 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, language, config); this->LocalGenerator->AddVisibilityPresetFlags( flags, this->GeneratorTarget, language); + this->LocalGenerator->AddColorDiagnosticsFlags(flags, language); // Append old-style preprocessor definition flags. if (this->Makefile->GetDefineFlags() != " ") { @@ -316,19 +319,37 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, void cmGhsMultiTargetGenerator::WriteBuildEvents(std::ostream& fout) { - this->WriteBuildEventsHelper( - fout, this->GeneratorTarget->GetPreBuildCommands(), - std::string("prebuild"), std::string("preexecShell")); + this->WriteBuildEventsHelper(fout, + this->GeneratorTarget->GetPreBuildCommands(), + std::string("prebuild"), +#ifdef _WIN32 + std::string("preexecShell") +#else + std::string("preexec") +#endif + ); if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) { - this->WriteBuildEventsHelper( - fout, this->GeneratorTarget->GetPreLinkCommands(), - std::string("prelink"), std::string("preexecShell")); + this->WriteBuildEventsHelper(fout, + this->GeneratorTarget->GetPreLinkCommands(), + std::string("prelink"), +#ifdef _WIN32 + std::string("preexecShell") +#else + std::string("preexec") +#endif + ); } - this->WriteBuildEventsHelper( - fout, this->GeneratorTarget->GetPostBuildCommands(), - std::string("postbuild"), std::string("postexecShell")); + this->WriteBuildEventsHelper(fout, + this->GeneratorTarget->GetPostBuildCommands(), + std::string("postbuild"), +#ifdef _WIN32 + std::string("postexecShell") +#else + std::string("postexec") +#endif + ); } void cmGhsMultiTargetGenerator::WriteBuildEventsHelper( @@ -336,6 +357,13 @@ void cmGhsMultiTargetGenerator::WriteBuildEventsHelper( std::string const& name, std::string const& cmd) { int cmdcount = 0; +#ifdef _WIN32 + std::string fext = ".bat"; + std::string shell; +#else + std::string fext = ".sh"; + std::string shell = "/bin/sh "; +#endif for (cmCustomCommand const& cc : ccv) { cmCustomCommandGenerator ccg(cc, this->ConfigName, this->LocalGenerator); @@ -343,14 +371,14 @@ void cmGhsMultiTargetGenerator::WriteBuildEventsHelper( std::string fname = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), - '/', this->Name, '_', name, cmdcount++, - this->CmdWindowsShell ? ".bat" : ".sh"); + '/', this->Name, '_', name, cmdcount++, fext); + cmGeneratedFileStream f(fname); f.SetCopyIfDifferent(true); this->WriteCustomCommandsHelper(f, ccg); f.Close(); if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) { - fout << " :" << cmd << "=\"" << fname << "\"\n"; + fout << " :" << cmd << "=\"" << shell << fname << "\"\n"; } else { fout << fname << "\n :outputName=\"" << fname << ".rule\"\n"; } @@ -409,15 +437,15 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( // bool useCall = false; - if (this->CmdWindowsShell) { - std::string suffix; - if (cmd.size() > 4) { - suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size() - 4)); - if (suffix == ".bat" || suffix == ".cmd") { - useCall = true; - } +#ifdef _WIN32 + std::string suffix; + if (cmd.size() > 4) { + suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size() - 4)); + if (suffix == ".bat" || suffix == ".cmd") { + useCall = true; } } +#endif cmSystemTools::ReplaceString(cmd, "/./", "/"); // Convert the command to a relative path only if the current @@ -555,11 +583,12 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) // Open the filestream in copy-if-different mode. std::string gname = sg; cmsys::SystemTools::ReplaceString(gname, "\\", "_"); - std::string lpath = cmStrCat( - this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/', - gname, cmGlobalGhsMultiGenerator::FILE_EXTENSION); + std::string lpath = + cmStrCat(gname, cmGlobalGhsMultiGenerator::FILE_EXTENSION); std::string fpath = cmStrCat( - this->LocalGenerator->GetCurrentBinaryDirectory(), '/', lpath); + this->LocalGenerator->GetCurrentBinaryDirectory(), '/', + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/', + lpath); cmGeneratedFileStream* f = new cmGeneratedFileStream(fpath); f->SetCopyIfDifferent(true); gfiles.push_back(f); @@ -605,13 +634,8 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) compile = false; } - *fout << comment << fname << '\n'; + *fout << comment << fname << WriteObjectLangOverride(si) << '\n'; if (compile) { - if ("ld" != si->GetExtension() && "int" != si->GetExtension() && - "bsp" != si->GetExtension()) { - WriteObjectLangOverride(*fout, si); - } - this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I"); this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D"); this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", ""); @@ -645,6 +669,11 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) } } int cmdcount = 0; +#ifdef _WIN32 + std::string fext = ".bat"; +#else + std::string fext = ".sh"; +#endif for (auto& sf : customCommands) { const cmCustomCommand* cc = sf->GetCustomCommand(); cmCustomCommandGenerator ccg(*cc, this->ConfigName, @@ -655,8 +684,8 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) this->LocalGenerator->GetCurrentBinaryDirectory(), '/', this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/', this->Name, "_cc", cmdcount++, '_', - (sf->GetLocation()).GetName(), - this->CmdWindowsShell ? ".bat" : ".sh"); + (sf->GetLocation()).GetName(), fext); + cmGeneratedFileStream f(fname); f.SetCopyIfDifferent(true); this->WriteCustomCommandsHelper(f, ccg); @@ -702,17 +731,16 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandLine( } } -void cmGhsMultiTargetGenerator::WriteObjectLangOverride( - std::ostream& fout, const cmSourceFile* sourceFile) +std::string cmGhsMultiTargetGenerator::WriteObjectLangOverride( + const cmSourceFile* sourceFile) { + std::string ret; cmValue rawLangProp = sourceFile->GetProperty("LANGUAGE"); if (rawLangProp) { - std::string sourceLangProp(*rawLangProp); - std::string const& extension = sourceFile->GetExtension(); - if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) { - fout << " -dotciscxx\n"; - } + ret = cmStrCat(" [", *rawLangProp, "]"); } + + return ret; } bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp() diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h index e9d7537..d3e80e6 100644 --- a/Source/cmGhsMultiTargetGenerator.h +++ b/Source/cmGhsMultiTargetGenerator.h @@ -65,8 +65,7 @@ private: void WriteSourceProperty(std::ostream& fout, const cmSourceFile* sf, std::string const& propName, std::string const& propFlag); - static void WriteObjectLangOverride(std::ostream& fout, - const cmSourceFile* sourceFile); + static std::string WriteObjectLangOverride(const cmSourceFile* sourceFile); bool DetermineIfIntegrityApp(); cmGeneratorTarget* GeneratorTarget; @@ -78,6 +77,5 @@ private: std::string TargetNameReal; GhsMultiGpj::Types TagType; std::string const Name; - std::string ConfigName; /* CMAKE_BUILD_TYPE */ - bool const CmdWindowsShell; /* custom commands run in cmd.exe or /bin/sh */ + std::string ConfigName; /* CMAKE_BUILD_TYPE */ }; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 156ecce..3831546 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -19,6 +19,7 @@ #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" #if defined(_WIN32) && !defined(__CYGWIN__) # include <windows.h> @@ -687,6 +688,33 @@ void cmGlobalGenerator::EnableLanguage( if (!this->FindMakeProgram(mf)) { return; } + + // One-time includes of user-provided project setup files + std::string includes = + mf->GetSafeDefinition("CMAKE_PROJECT_TOP_LEVEL_INCLUDES"); + std::vector<std::string> includesList = cmExpandedList(includes); + for (std::string const& setupFile : includesList) { + std::string absSetupFile = cmSystemTools::CollapseFullPath( + setupFile, mf->GetCurrentSourceDirectory()); + if (!cmSystemTools::FileExists(absSetupFile)) { + cmSystemTools::Error( + "CMAKE_PROJECT_TOP_LEVEL_INCLUDES file does not exist: " + + setupFile); + return; + } + if (cmSystemTools::FileIsDirectory(absSetupFile)) { + cmSystemTools::Error( + "CMAKE_PROJECT_TOP_LEVEL_INCLUDES file is a directory: " + + setupFile); + return; + } + if (!mf->ReadListFile(absSetupFile)) { + cmSystemTools::Error( + "Failed reading CMAKE_PROJECT_TOP_LEVEL_INCLUDES file: " + + setupFile); + return; + } + } } // Check that the languages are supported by the generator and its @@ -758,7 +786,9 @@ void cmGlobalGenerator::EnableLanguage( needTestLanguage[lang] = true; // Some generators like visual studio should not use the env variables // So the global generator can specify that in this variable - if (!mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV")) { + if ((mf->GetPolicyStatus(cmPolicies::CMP0132) == cmPolicies::OLD || + mf->GetPolicyStatus(cmPolicies::CMP0132) == cmPolicies::WARN) && + !mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV")) { // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER // into the environment, in case user scripts want to run // configure, or sub cmakes @@ -1498,6 +1528,11 @@ bool cmGlobalGenerator::Compute() return false; } + // Iterate through all targets and add verification targets for header sets + if (!this->AddHeaderSetVerification()) { + return false; + } + // Iterate through all targets and set up AUTOMOC, AUTOUIC and AUTORCC if (!this->QtAutoGen()) { return false; @@ -1719,6 +1754,27 @@ bool cmGlobalGenerator::QtAutoGen() #endif } +bool cmGlobalGenerator::AddHeaderSetVerification() +{ + for (auto const& gen : this->LocalGenerators) { + // Because AddHeaderSetVerification() adds generator targets, we need to + // cache the existing list of generator targets before starting. + std::vector<cmGeneratorTarget*> genTargets; + genTargets.reserve(gen->GetGeneratorTargets().size()); + for (auto const& tgt : gen->GetGeneratorTargets()) { + genTargets.push_back(tgt.get()); + } + + for (auto* tgt : genTargets) { + if (!tgt->AddHeaderSetVerification()) { + return false; + } + } + } + + return true; +} + bool cmGlobalGenerator::AddAutomaticSources() { for (const auto& lg : this->LocalGenerators) { @@ -1735,6 +1791,7 @@ bool cmGlobalGenerator::AddAutomaticSources() if (!gt->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) { lg->AddPchDependencies(gt.get()); } + lg->AddXCConfigSources(gt.get()); } } for (const auto& lg : this->LocalGenerators) { @@ -2522,6 +2579,47 @@ bool cmGlobalGenerator::NameResolvesToFramework( return false; } +// If the file has no extension it's either a raw executable or might +// be a direct reference to a binary within a framework (bad practice!). +// This is where we change the path to point to the framework directory. +// .tbd files also can be located in SDK frameworks (they are +// placeholders for actual libraries shipped with the OS) +cm::optional<std::pair<std::string, std::string>> +cmGlobalGenerator::SplitFrameworkPath(const std::string& path, + bool extendedFormat) const +{ + // Check for framework structure: + // (/path/to/)?FwName.framework + // or (/path/to/)?FwName.framework/FwName(.tbd)? + // or (/path/to/)?FwName.framework/Versions/*/FwName(.tbd)? + static cmsys::RegularExpression frameworkPath( + "((.+)/)?(.+)\\.framework(/Versions/[^/]+)?(/(.+))?$"); + + auto ext = cmSystemTools::GetFilenameLastExtension(path); + if ((ext.empty() || ext == ".tbd" || ext == ".framework") && + frameworkPath.find(path)) { + auto name = frameworkPath.match(3); + auto libname = + cmSystemTools::GetFilenameWithoutExtension(frameworkPath.match(6)); + if (!libname.empty() && name != libname) { + return cm::nullopt; + } + return std::pair<std::string, std::string>{ frameworkPath.match(2), name }; + } + + if (extendedFormat) { + // path format can be more flexible: (/path/to/)?fwName(.framework)? + auto fwDir = cmSystemTools::GetParentDirectory(path); + auto name = cmSystemTools::GetFilenameLastExtension(path) == ".framework" + ? cmSystemTools::GetFilenameWithoutExtension(path) + : cmSystemTools::GetFilenameName(path); + + return std::pair<std::string, std::string>{ fwDir, name }; + } + + return cm::nullopt; +} + bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName, std::string const& reason) const { diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index a43d4a6..dcef070 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -367,6 +367,13 @@ public: /** Determine if a name resolves to a framework on disk or a built target that is a framework. */ bool NameResolvesToFramework(const std::string& libname) const; + /** Split a framework path to the directory and name of the framework + * returns std::nullopt if the path does not match with framework format + * when extendedFormat is true, required format is relaxed (i.e. extension + * `.framework' is optional). Used when FRAMEWORK link feature is + * specified */ + cm::optional<std::pair<std::string, std::string>> SplitFrameworkPath( + const std::string& path, bool extendedFormat = false) const; cmMakefile* FindMakefile(const std::string& start_dir) const; cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const; @@ -452,10 +459,13 @@ public: virtual bool IsNinja() const { return false; } - /** Return true if we know the exact location of object files. - If false, store the reason in the given string. - This is meaningful only after EnableLanguage has been called. */ - virtual bool HasKnownObjectFileLocation(std::string*) const { return true; } + /** Return true if we know the exact location of object files for the given + cmTarget. If false, store the reason in the given string. This is + meaningful only after EnableLanguage has been called. */ + virtual bool HasKnownObjectFileLocation(cmTarget const&, std::string*) const + { + return true; + } virtual bool UseFolderProperty() const; @@ -566,6 +576,8 @@ protected: /// @return true on success bool QtAutoGen(); + bool AddHeaderSetVerification(); + bool AddAutomaticSources(); std::string SelectMakeProgram(const std::string& makeProgram, diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 5e51dd2..9c334a5 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -2,14 +2,19 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalGhsMultiGenerator.h" +#include <algorithm> +#include <functional> #include <map> -#include <ostream> +#include <sstream> #include <utility> #include <cm/memory> #include <cm/string> #include <cmext/algorithm> +#include <cmext/memory> +#include "cmCustomCommand.h" +#include "cmCustomCommandLines.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -18,10 +23,13 @@ #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" +#include "cmSourceFile.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTarget.h" #include "cmValue.h" #include "cmVersion.h" #include "cmake.h" @@ -32,6 +40,8 @@ const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild"; #elif defined(_WIN32) const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild.exe"; #endif +const char* cmGlobalGhsMultiGenerator::CHECK_BUILD_SYSTEM_TARGET = + "RERUN_CMAKE"; cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm) : cmGlobalGenerator(cm) @@ -279,7 +289,7 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout, { this->WriteFileHeader(fout); this->WriteMacros(fout, root); - this->WriteHighLevelDirectives(root, fout); + this->WriteHighLevelDirectives(fout, root); GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fout); fout << "# Top Level Project File\n"; @@ -308,9 +318,13 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout, } void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout, - std::string& all_target) + bool filterPredefined) { - fout << "CMakeFiles/" << all_target << " [Project]\n"; + std::set<std::string> predefinedTargets; + predefinedTargets.insert(this->GetInstallTargetName()); + predefinedTargets.insert(this->GetAllTargetName()); + predefinedTargets.insert(std::string(CHECK_BUILD_SYSTEM_TARGET)); + // All known targets for (cmGeneratorTarget const* target : this->ProjectTargets) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY || @@ -320,8 +334,13 @@ void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout, target->GetName() != this->GetInstallTargetName())) { continue; } - fout << "CMakeFiles/" << target->GetName() + ".tgt" + FILE_EXTENSION - << " [Project]\n"; + /* Check if the current target is a predefined CMake target */ + bool predefinedTarget = + predefinedTargets.find(target->GetName()) != predefinedTargets.end(); + if ((filterPredefined && predefinedTarget) || + (!filterPredefined && !predefinedTarget)) { + fout << target->GetName() + ".tgt" + FILE_EXTENSION << " [Project]\n"; + } } } @@ -329,36 +348,22 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine( std::ostream& fout, cmGeneratorTarget const* target, std::string& rootBinaryDir) { - cmValue projName = target->GetProperty("GENERATOR_FILE_NAME"); + cmValue projFile = target->GetProperty("GENERATOR_FILE_NAME"); cmValue projType = target->GetProperty("GENERATOR_FILE_NAME_EXT"); - if (projName && projType) { - cmLocalGenerator* lg = target->GetLocalGenerator(); - std::string dir = lg->GetCurrentBinaryDirectory(); - dir = cmSystemTools::ForceToRelativePath(rootBinaryDir, dir); - if (dir == ".") { - dir.clear(); - } else { - if (dir.back() != '/') { - dir += "/"; - } - } + /* If either value is not valid then this particular target is an + * unsupported target type and should be skipped. + */ + if (projFile && projType) { + std::string path = cmSystemTools::RelativePath(rootBinaryDir, projFile); - std::string projFile = dir + *projName + FILE_EXTENSION; - fout << projFile; + fout << path; fout << ' ' << *projType << '\n'; - } else { - /* Should never happen */ - std::string message = - "The project file for target [" + target->GetName() + "] is missing.\n"; - cmSystemTools::Error(message); - fout << "{comment} " << target->GetName() << " [missing project file]\n"; } } void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root) { - std::string rootBinaryDir = - cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles"); + std::string rootBinaryDir = root->GetCurrentBinaryDirectory(); // All known targets for (cmGeneratorTarget const* target : this->ProjectTargets) { @@ -391,62 +396,6 @@ void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root) } } -void cmGlobalGhsMultiGenerator::WriteAllTarget( - cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators, - std::string& all_target) -{ - this->ProjectTargets.clear(); - - // create target build file - all_target = root->GetProjectName() + "." + this->GetAllTargetName() + - ".tgt" + FILE_EXTENSION; - std::string fname = - root->GetCurrentBinaryDirectory() + "/CMakeFiles/" + all_target; - cmGeneratedFileStream fbld(fname); - fbld.SetCopyIfDifferent(true); - this->WriteFileHeader(fbld); - GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fbld); - - // 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 sortedProjectTargets(projectTargets, ""); - std::vector<cmGeneratorTarget const*> defaultTargets; - for (cmGeneratorTarget const* t : sortedProjectTargets) { - /* save list of all targets in sorted order */ - this->ProjectTargets.push_back(t); - } - for (cmGeneratorTarget const* t : sortedProjectTargets) { - if (!t->IsInBuildSystem()) { - continue; - } - if (!this->IsExcluded(t->GetLocalGenerator(), t)) { - defaultTargets.push_back(t); - } - } - std::vector<cmGeneratorTarget const*> build; - if (this->ComputeTargetBuildOrder(defaultTargets, build)) { - std::string message = "The inter-target dependency graph for project [" + - root->GetProjectName() + "] had a cycle.\n"; - cmSystemTools::Error(message); - } else { - // determine the targets for ALL target - std::string rootBinaryDir = - cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles"); - for (cmGeneratorTarget const* target : build) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY || - target->GetType() == cmStateEnums::MODULE_LIBRARY || - target->GetType() == cmStateEnums::SHARED_LIBRARY) { - continue; - } - this->WriteProjectLine(fbld, target, rootBinaryDir); - } - } - fbld.Close(); -} - void cmGlobalGhsMultiGenerator::Generate() { std::string fname; @@ -482,12 +431,23 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject( cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { std::string fname; - std::string all_target; if (generators.empty()) { return; } + // 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 sortedProjectTargets(projectTargets, ""); + this->ProjectTargets.clear(); + for (cmGeneratorTarget const* t : sortedProjectTargets) { + /* save list of all targets in sorted order */ + this->ProjectTargets.push_back(t); + } + /* 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. @@ -498,11 +458,9 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject( cmGeneratedFileStream top(fname); top.SetCopyIfDifferent(true); this->WriteTopLevelProject(top, root); - - this->WriteAllTarget(root, generators, all_target); this->WriteTargets(root); - - this->WriteSubProjects(top, all_target); + this->WriteSubProjects(top, true); + this->WriteSubProjects(top, false); top.Close(); } @@ -510,59 +468,62 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand> cmGlobalGhsMultiGenerator::GenerateBuildCommand( const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, std::vector<std::string> const& targetNames, - const std::string& /*config*/, int jobs, bool /*verbose*/, + const std::string& /*config*/, int jobs, bool verbose, const cmBuildOptions& /*buildOptions*/, std::vector<std::string> const& makeOptions) { - GeneratedMakeCommand makeCommand = {}; - std::string gbuild; - if (cmValue gbuildCached = - this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM")) { - gbuild = *gbuildCached; - } - makeCommand.Add(this->SelectMakeProgram(makeProgram, gbuild)); + GeneratedMakeCommand makeCommand; + + makeCommand.Add(this->SelectMakeProgram(makeProgram)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - makeCommand.Add("-parallel"); - if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.Add(std::to_string(jobs)); + if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { + makeCommand.Add("-parallel"); + } else { + makeCommand.Add(std::string("-parallel=") + std::to_string(jobs)); } } - makeCommand.Add(makeOptions.begin(), makeOptions.end()); - - /* determine which top-project file to use */ + /* determine the top-project file in the project directory */ std::string proj = projectName + ".top" + FILE_EXTENSION; std::vector<std::string> files; cmSystemTools::Glob(projectDir, ".*\\.top\\.gpj", files); if (!files.empty()) { - /* if multiple top-projects are found in build directory - * then prefer projectName top-project. - */ - if (!cm::contains(files, proj)) { - proj = files.at(0); - } + /* use the real top-level project in the directory */ + proj = files.at(0); } - makeCommand.Add("-top", proj); + + /* determine targets to build */ + bool build_all = false; if (!targetNames.empty()) { - if (cm::contains(targetNames, "clean")) { - makeCommand.Add("-clean"); - } else { - for (const auto& tname : targetNames) { - if (!tname.empty()) { + for (const auto& tname : targetNames) { + if (!tname.empty()) { + if (tname == "clean") { + makeCommand.Add("-clean"); + } else { makeCommand.Add(tname + ".tgt.gpj"); } + } else { + build_all = true; } } } else { + build_all = true; + } + + if (build_all) { /* transform name to default build */; - std::string all = proj; - all.replace(all.end() - 7, all.end(), - std::string(this->GetAllTargetName()) + ".tgt.gpj"); + std::string all = std::string(this->GetAllTargetName()) + ".tgt.gpj"; makeCommand.Add(all); } - return { makeCommand }; + + if (verbose) { + makeCommand.Add("-commands"); + } + makeCommand.Add(makeOptions.begin(), makeOptions.end()); + + return { std::move(makeCommand) }; } void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout, @@ -579,7 +540,7 @@ void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout, } void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives( - cmLocalGenerator* root, std::ostream& fout) + std::ostream& fout, cmLocalGenerator* root) { /* put primary target and customization files into project file */ cmValue const tgt = root->GetMakefile()->GetDefinition("GHS_PRIMARY_TARGET"); @@ -681,3 +642,153 @@ bool cmGlobalGhsMultiGenerator::VisitTarget( /* already complete */ return false; } + +bool cmGlobalGhsMultiGenerator::AddCheckTarget() +{ + // Skip the target if no regeneration is to be done. + if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { + return false; + } + + // Get the generators. + std::vector<std::unique_ptr<cmLocalGenerator>> const& generators = + this->LocalGenerators; + auto& lg = + cm::static_reference_cast<cmLocalGhsMultiGenerator>(generators[0]); + + // The name of the output file for the custom command. + this->StampFile = lg.GetBinaryDirectory() + std::string("/CMakeFiles/") + + CHECK_BUILD_SYSTEM_TARGET; + + // Add a custom rule to re-run CMake if any input files changed. + { + // Collect the input files used to generate all targets in this + // project. + std::vector<std::string> listFiles; + for (const auto& gen : generators) { + cm::append(listFiles, gen->GetMakefile()->GetListFiles()); + } + + // Add the cache file. + listFiles.push_back(cmStrCat( + this->GetCMakeInstance()->GetHomeOutputDirectory(), "/CMakeCache.txt")); + + // Print not implemented warning. + if (this->GetCMakeInstance()->DoWriteGlobVerifyTarget()) { + std::ostringstream msg; + msg << "Any pre-check scripts, such as those generated for file(GLOB " + "CONFIGURE_DEPENDS), will not be run by gbuild."; + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + msg.str()); + } + + // Sort the list of input files and remove duplicates. + std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>()); + auto newEnd = std::unique(listFiles.begin(), listFiles.end()); + listFiles.erase(newEnd, listFiles.end()); + + // Create a rule to re-run CMake and create output file. + cmCustomCommandLines commandLines; + commandLines.emplace_back( + cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", "rm", "-f", + this->StampFile })); + std::string argS = cmStrCat("-S", lg.GetSourceDirectory()); + std::string argB = cmStrCat("-B", lg.GetBinaryDirectory()); + commandLines.emplace_back( + cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), argS, argB })); + commandLines.emplace_back(cmMakeCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "touch", this->StampFile })); + + /* Create the target(Exclude from ALL_BUILD). + * + * The build tool, currently, does not support rereading the project files + * if they get updated. So do not run this target as part of ALL_BUILD. + */ + auto cc = cm::make_unique<cmCustomCommand>(); + cmTarget* tgt = + lg.AddUtilityCommand(CHECK_BUILD_SYSTEM_TARGET, true, std::move(cc)); + auto ptr = cm::make_unique<cmGeneratorTarget>(tgt, &lg); + auto* gt = ptr.get(); + lg.AddGeneratorTarget(std::move(ptr)); + + // Add the rule. + cc = cm::make_unique<cmCustomCommand>(); + cc->SetOutputs(this->StampFile); + cc->SetDepends(listFiles); + cc->SetCommandLines(commandLines); + cc->SetComment("Checking Build System"); + cc->SetCMP0116Status(cmPolicies::NEW); + cc->SetEscapeOldStyle(false); + cc->SetStdPipesUTF8(true); + + if (cmSourceFile* file = + lg.AddCustomCommandToOutput(std::move(cc), true)) { + gt->AddSource(file->ResolveFullPath()); + } else { + cmSystemTools::Error("Error adding rule for " + this->StampFile); + } + // Organize in the "predefined targets" folder: + if (this->UseFolderProperty()) { + tgt->SetProperty("FOLDER", this->GetPredefinedTargetsFolder()); + } + } + + return true; +} + +void cmGlobalGhsMultiGenerator::AddAllTarget() +{ + // Add a special target that depends on ALL projects for easy build + // of one configuration only. + for (auto const& it : this->ProjectMap) { + std::vector<cmLocalGenerator*> const& gen = it.second; + // add the ALL_BUILD to the first local generator of each project + if (!gen.empty()) { + // Use no actual command lines so that the target itself is not + // considered always out of date. + auto cc = cm::make_unique<cmCustomCommand>(); + cc->SetCMP0116Status(cmPolicies::NEW); + cc->SetEscapeOldStyle(false); + cc->SetComment("Build all projects"); + cmTarget* allBuild = gen[0]->AddUtilityCommand(this->GetAllTargetName(), + true, std::move(cc)); + + gen[0]->AddGeneratorTarget( + cm::make_unique<cmGeneratorTarget>(allBuild, gen[0])); + + // Organize in the "predefined targets" folder: + if (this->UseFolderProperty()) { + allBuild->SetProperty("FOLDER", this->GetPredefinedTargetsFolder()); + } + + // Now make all targets depend on the ALL_BUILD target + for (cmLocalGenerator const* i : gen) { + for (const auto& tgt : i->GetGeneratorTargets()) { + // Skip global or imported targets + if (tgt->GetType() == cmStateEnums::GLOBAL_TARGET || + tgt->IsImported()) { + continue; + } + // Skip Exclude From All Targets + if (!this->IsExcluded(gen[0], tgt.get())) { + allBuild->AddUtility(tgt->GetName(), false); + } + } + } + } + } +} + +void cmGlobalGhsMultiGenerator::AddExtraIDETargets() +{ + // Add a special target that depends on ALL projects. + this->AddAllTarget(); + + /* Add Custom Target to check if CMake needs to be rerun. + * + * The build tool, currently, does not support rereading the project files + * if they get updated. So do not make the other targets dependent on this + * check. + */ + this->AddCheckTarget(); +} diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index 26ea3c7..aa68d3b 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -81,8 +81,6 @@ public: // Write the common disclaimer text at the top of each build file. void WriteFileHeader(std::ostream& fout); - const char* GetInstallTargetName() const override { return "install"; } - protected: void Generate() override; std::vector<GeneratedMakeCommand> GenerateBuildCommand( @@ -92,6 +90,7 @@ protected: const cmBuildOptions& buildOptions = cmBuildOptions(), std::vector<std::string> const& makeOptions = std::vector<std::string>()) override; + void AddExtraIDETargets() override; private: void GetToolset(cmMakefile* mf, std::string& tsd, const std::string& ts); @@ -101,20 +100,21 @@ private: std::vector<cmLocalGenerator*>& generators); void WriteTopLevelProject(std::ostream& fout, cmLocalGenerator* root); void WriteMacros(std::ostream& fout, cmLocalGenerator* root); - void WriteHighLevelDirectives(cmLocalGenerator* root, std::ostream& fout); - void WriteSubProjects(std::ostream& fout, std::string& all_target); + void WriteHighLevelDirectives(std::ostream& fout, cmLocalGenerator* root); + void WriteSubProjects(std::ostream& fout, bool filterPredefined); void WriteTargets(cmLocalGenerator* root); void WriteProjectLine(std::ostream& fout, cmGeneratorTarget const* target, std::string& rootBinaryDir); void WriteCustomRuleBOD(std::ostream& fout); void WriteCustomTargetBOD(std::ostream& fout); - void WriteAllTarget(cmLocalGenerator* root, - std::vector<cmLocalGenerator*>& generators, - std::string& all_target); + bool AddCheckTarget(); + void AddAllTarget(); + std::string StampFile; static std::string TrimQuotes(std::string str); static const char* DEFAULT_BUILD_PROGRAM; + static const char* CHECK_BUILD_SYSTEM_TARGET; bool ComputeTargetBuildOrder(cmGeneratorTarget const* tgt, std::vector<cmGeneratorTarget const*>& build); diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 4245037..3726aa4 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2495,8 +2495,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( snapshot.GetDirectory().SetCurrentBinary(dir_cur_bld); auto mfd = cm::make_unique<cmMakefile>(this, snapshot); auto lgd = this->CreateLocalGenerator(mfd.get()); - lgd->SetRelativePathTopSource(dir_top_src); - lgd->SetRelativePathTopBinary(dir_top_bld); + lgd->SetRelativePathTop(dir_top_src, dir_top_bld); this->Makefiles.push_back(std::move(mfd)); this->LocalGenerators.push_back(std::move(lgd)); } @@ -2535,6 +2534,11 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( } } + const char* module_ext = ""; + if (arg_modmapfmt == "gcc") { + module_ext = ".gcm"; + } + // Extend the module map with those provided by this target. // We do this after loading the modules provided by linked targets // in case we have one of the same name that must be preferred. @@ -2551,7 +2555,9 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( } } else { // Assume the module file path matches the logical module name. - mod = cmStrCat(module_dir, p.LogicalName); + std::string safe_logical_name = p.LogicalName; + cmSystemTools::ReplaceString(safe_logical_name, ":", "-"); + mod = cmStrCat(module_dir, safe_logical_name, module_ext); } mod_files[p.LogicalName] = mod; tm[p.LogicalName] = mod; diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index db54b86..35448ee 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1286,6 +1286,14 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand( return makeCommands; } +bool cmGlobalVisualStudio10Generator::IsInSolution( + const cmGeneratorTarget* gt) const +{ + return gt->IsInBuildSystem() && + !(this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS16 && + gt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET); +} + bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf) { if (this->DefaultPlatformToolset == "v100") { diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 4977a84..2203f71 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -118,6 +118,8 @@ public: return this->WindowsTargetPlatformVersion; } + bool IsInSolution(const cmGeneratorTarget* gt) const override; + /** Return true if building for WindowsCE */ bool TargetsWindowsCE() const override { return this->SystemIsWindowsCE; } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 134937e..1c10fb3 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -359,7 +359,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( // loop over again and write out configurations for each target // in the solution for (cmGeneratorTarget const* target : projectTargets) { - if (!target->IsInBuildSystem()) { + if (!this->IsInSolution(target)) { continue; } cmValue expath = target->GetProperty("EXTERNAL_MSPROJECT"); @@ -396,7 +396,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( VisualStudioFolders.clear(); for (cmGeneratorTarget const* target : projectTargets) { - if (!target->IsInBuildSystem()) { + if (!this->IsInSolution(target)) { continue; } bool written = false; @@ -458,22 +458,6 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( } } -void cmGlobalVisualStudio7Generator::WriteTargetDepends( - std::ostream& fout, OrderedTargetDependSet const& projectTargets) -{ - for (cmGeneratorTarget const* target : projectTargets) { - if (!target->IsInBuildSystem()) { - continue; - } - cmValue vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); - if (vcprojName) { - std::string dir = - target->GetLocalGenerator()->GetCurrentSourceDirectory(); - this->WriteProjectDepends(fout, *vcprojName, dir, target); - } - } -} - void cmGlobalVisualStudio7Generator::WriteFolders(std::ostream& fout) { cm::string_view const prefix = "CMAKE_FOLDER_GUID_"; diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 33f1063..a55cf45 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -148,8 +148,6 @@ protected: virtual void WriteTargetsToSolution( std::ostream& fout, cmLocalGenerator* root, OrderedTargetDependSet const& projectTargets); - virtual void WriteTargetDepends( - std::ostream& fout, OrderedTargetDependSet const& projectTargets); virtual void WriteTargetConfigurations( std::ostream& fout, std::vector<std::string> const& configs, OrderedTargetDependSet const& projectTargets); diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index dbd2de9..323ee67 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -392,7 +392,7 @@ void cmGlobalVisualStudio8Generator::WriteProjectDepends( TargetDependSet const& unordered = this->GetTargetDirectDepends(gt); OrderedTargetDependSet depends(unordered, std::string()); for (cmTargetDepend const& i : depends) { - if (!i->IsInBuildSystem()) { + if (!this->IsInSolution(i)) { continue; } std::string guid = this->GetGUID(i->GetName()); diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 141b5eb..cddaaa4 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -837,6 +837,12 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly( return languages.size() == 1 && *languages.begin() == "Fortran"; } +bool cmGlobalVisualStudioGenerator::IsInSolution( + const cmGeneratorTarget* gt) const +{ + return gt->IsInBuildSystem(); +} + bool cmGlobalVisualStudioGenerator::TargetCompare::operator()( cmGeneratorTarget const* l, cmGeneratorTarget const* r) const { diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index cb1b14b..4f5f100 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -98,6 +98,9 @@ public: // return true if target is fortran only bool TargetIsFortranOnly(const cmGeneratorTarget* gt); + // return true if target should be included in solution. + virtual bool IsInSolution(const cmGeneratorTarget* gt) const; + /** Get the top-level registry key for this VS version. */ std::string GetRegistryBase(); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 203addd..d53c3d5 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -616,6 +616,16 @@ void cmGlobalXCodeGenerator::AddExtraTargets( cmTarget* allbuild = root->AddUtilityCommand("ALL_BUILD", true, std::move(cc)); + // Add xcconfig files to ALL_BUILD sources + for (auto& config : this->CurrentConfigurationTypes) { + auto xcconfig = cmGeneratorExpression::Evaluate( + this->CurrentMakefile->GetSafeDefinition("CMAKE_XCODE_XCCONFIG"), + this->CurrentLocalGenerator, config); + if (!xcconfig.empty()) { + allbuild->AddSource(xcconfig); + } + } + root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(allbuild, root)); // Add XCODE depend helper @@ -1142,6 +1152,9 @@ std::string GetSourcecodeValueFromFileExtension( } else if (ext == "xcassets") { keepLastKnownFileType = true; sourcecode = "folder.assetcatalog"; + } else if (ext == "xcconfig") { + keepLastKnownFileType = true; + sourcecode = "text.xcconfig"; } // else // { @@ -1154,47 +1167,39 @@ std::string GetSourcecodeValueFromFileExtension( return sourcecode; } -// If the file has no extension it's either a raw executable or might -// be a direct reference to a binary within a framework (bad practice!). -// This is where we change the path to point to the framework directory. -// .tbd files also can be located in SDK frameworks (they are -// placeholders for actual libraries shipped with the OS) -std::string GetLibraryOrFrameworkPath(const std::string& path) +template <class T> +std::string GetTargetObjectDirArch(T const& target, + const std::string& defaultVal) { - auto ext = cmSystemTools::GetFilenameLastExtension(path); - if (ext.empty() || ext == ".tbd") { - auto name = cmSystemTools::GetFilenameWithoutExtension(path); - // Check for iOS framework structure: - // FwName.framework/FwName (and also on macOS where FwName lib is a - // symlink) - auto parentDir = cmSystemTools::GetParentDirectory(path); - auto parentName = cmSystemTools::GetFilenameWithoutExtension(parentDir); - ext = cmSystemTools::GetFilenameLastExtension(parentDir); - if (ext == ".framework" && name == parentName) { - return parentDir; - } - // Check for macOS framework structure: - // FwName.framework/Versions/*/FwName - std::vector<std::string> components; - cmSystemTools::SplitPath(path, components); - if (components.size() > 3 && - components[components.size() - 3] == "Versions") { - ext = cmSystemTools::GetFilenameLastExtension( - components[components.size() - 4]); - parentName = cmSystemTools::GetFilenameWithoutExtension( - components[components.size() - 4]); - if (ext == ".framework" && name == parentName) { - components.erase(components.begin() + components.size() - 3, - components.end()); - return cmSystemTools::JoinPath(components); - } - } + auto archs = cmExpandedList(target.GetSafeProperty("OSX_ARCHITECTURES")); + if (archs.size() > 1) { + return "$(CURRENT_ARCH)"; + } else if (archs.size() == 1) { + return archs.front(); + } else { + return defaultVal; } - return path; } } // anonymous +// Extracts the framework directory, if path matches the framework syntax +// otherwise returns the path untouched +std::string cmGlobalXCodeGenerator::GetLibraryOrFrameworkPath( + const std::string& path) const +{ + auto fwItems = this->SplitFrameworkPath(path); + if (fwItems) { + if (fwItems->first.empty()) { + return cmStrCat(fwItems->second, ".framework"); + } else { + return cmStrCat(fwItems->first, '/', fwItems->second, ".framework"); + } + } + + return path; +} + cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( const std::string& fullpath, cmGeneratorTarget* target, const std::string& lang, cmSourceFile* sf) @@ -1217,7 +1222,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( ext = ext.substr(1); } if (fileType.empty()) { - path = GetLibraryOrFrameworkPath(path); + path = this->GetLibraryOrFrameworkPath(path); ext = cmSystemTools::GetFilenameLastExtension(path); if (!ext.empty()) { ext = ext.substr(1); @@ -1649,7 +1654,10 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt) // If the language is compiled as a source trust Xcode to link with it. for (auto const& Language : - gtgt->GetLinkImplementation("NOCONFIG")->Languages) { + gtgt + ->GetLinkImplementation("NOCONFIG", + cmGeneratorTarget::LinkInterfaceFor::Link) + ->Languages) { if (Language == llang) { return; } @@ -3064,6 +3072,8 @@ std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target, config->AddAttribute("name", this->CreateString(i)); config->SetComment(i); config->AddAttribute("buildSettings", buildSettings); + + this->CreateTargetXCConfigSettings(gtgt, config, i); } if (!configVector.empty()) { configlist->AddAttribute("defaultConfigurationName", @@ -3075,6 +3085,67 @@ std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target, return ""; } +void cmGlobalXCodeGenerator::CreateGlobalXCConfigSettings( + cmLocalGenerator* root, cmXCodeObject* config, const std::string& configName) +{ + auto xcconfig = cmGeneratorExpression::Evaluate( + this->CurrentMakefile->GetSafeDefinition("CMAKE_XCODE_XCCONFIG"), + this->CurrentLocalGenerator, configName); + if (xcconfig.empty()) { + return; + } + + auto sf = this->CurrentMakefile->GetSource(xcconfig); + if (!sf) { + cmSystemTools::Error( + cmStrCat("sources for ALL_BUILD do not contain xcconfig file: '", + xcconfig, "' (configuration: ", configName, ")")); + return; + } + + cmXCodeObject* fileRef = this->CreateXCodeFileReferenceFromPath( + sf->ResolveFullPath(), root->FindGeneratorTargetToUse("ALL_BUILD"), "", + sf); + + if (!fileRef) { + // error is already reported by CreateXCodeFileReferenceFromPath + return; + } + + config->AddAttribute("baseConfigurationReference", + this->CreateObjectReference(fileRef)); +} + +void cmGlobalXCodeGenerator::CreateTargetXCConfigSettings( + cmGeneratorTarget* target, cmXCodeObject* config, + const std::string& configName) +{ + auto xcconfig = + cmGeneratorExpression::Evaluate(target->GetSafeProperty("XCODE_XCCONFIG"), + this->CurrentLocalGenerator, configName); + if (xcconfig.empty()) { + return; + } + + auto sf = target->Makefile->GetSource(xcconfig); + if (!sf) { + cmSystemTools::Error(cmStrCat("target sources for target ", + target->Target->GetName(), + " do not contain xcconfig file: '", xcconfig, + "' (configuration: ", configName, ")")); + return; + } + + cmXCodeObject* fileRef = this->CreateXCodeFileReferenceFromPath( + sf->ResolveFullPath(), target, "", sf); + if (!fileRef) { + // error is already reported by CreateXCodeFileReferenceFromPath + return; + } + config->AddAttribute("baseConfigurationReference", + this->CreateObjectReference(fileRef)); +} + const char* cmGlobalXCodeGenerator::GetTargetLinkFlagsVar( cmGeneratorTarget const* target) const { @@ -3541,13 +3612,14 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) } else { linkDir = libItem->Value.Value; } - linkDir = GetLibraryOrFrameworkPath(linkDir); - bool isFramework = cmSystemTools::IsPathToFramework(linkDir); - linkDir = cmSystemTools::GetParentDirectory(linkDir); - if (isFramework) { - if (std::find(frameworkSearchPaths.begin(), frameworkSearchPaths.end(), - linkDir) == frameworkSearchPaths.end()) { - frameworkSearchPaths.push_back(linkDir); + if (cmHasSuffix(libItem->GetFeatureName(), "FRAMEWORK"_s)) { + auto fwItems = this->SplitFrameworkPath(linkDir, true); + if (fwItems && !fwItems->first.empty()) { + linkDir = std::move(fwItems->first); + if (std::find(frameworkSearchPaths.begin(), frameworkSearchPaths.end(), + linkDir) == frameworkSearchPaths.end()) { + frameworkSearchPaths.push_back(linkDir); + } } } else { if (std::find(linkSearchPaths.begin(), linkSearchPaths.end(), linkDir) == @@ -3555,7 +3627,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) linkSearchPaths.push_back(linkDir); } } - // Add target dependency + if (libItem->Target && !libItem->Target->IsImported()) { for (auto const& configName : this->CurrentConfigurationTypes) { target->AddDependTarget(configName, libItem->Target->GetName()); @@ -3729,22 +3801,27 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) if (cmSystemTools::FileIsFullPath(cleanPath)) { cleanPath = cmSystemTools::CollapseFullPath(cleanPath); } - const auto libPath = GetLibraryOrFrameworkPath(cleanPath); - if (cmSystemTools::StringEndsWith(libPath.c_str(), ".framework")) { - const auto fwName = - cmSystemTools::GetFilenameWithoutExtension(libPath); - const auto fwDir = cmSystemTools::GetParentDirectory(libPath); - if (emitted.insert(fwDir).second) { - // This is a search path we had not added before and it isn't an - // implicit search path, so we need it - libPaths.Add("-F " + this->XCodeEscapePath(fwDir)); + bool isFramework = + cmHasSuffix(libName.GetFeatureName(), "FRAMEWORK"_s); + if (isFramework) { + const auto fwItems = + this->SplitFrameworkPath(cleanPath, isFramework); + if (!fwItems->first.empty() && + emitted.insert(fwItems->first).second) { + // This is a search path we had not added before and it isn't + // an implicit search path, so we need it + libPaths.Add("-F " + this->XCodeEscapePath(fwItems->first)); } - libPaths.Add("-framework " + this->XCodeEscapePath(fwName)); + libPaths.Add( + libName.GetFormattedItem(this->XCodeEscapePath(fwItems->second)) + .Value); } else { - libPaths.Add(this->XCodeEscapePath(cleanPath)); + libPaths.Add( + libName.GetFormattedItem(this->XCodeEscapePath(cleanPath)) + .Value); } if ((!libName.Target || libName.Target->IsImported()) && - IsLinkPhaseLibraryExtension(libPath)) { + (isFramework || IsLinkPhaseLibraryExtension(cleanPath))) { // Create file reference for embedding auto it = this->ExternalLibRefs.find(cleanPath); if (it == this->ExternalLibRefs.end()) { @@ -3912,8 +3989,8 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) { static const auto dstSubfolderSpec = "10"; - // Despite the name, by default Xcode uses "Embed Frameworks" build phase for - // both frameworks and dynamic libraries + // Despite the name, by default Xcode uses "Embed Frameworks" build phase + // for both frameworks and dynamic libraries this->AddEmbeddedObjects(target, "Embed Frameworks", "XCODE_EMBED_FRAMEWORKS", dstSubfolderSpec, NoActionOnCopyByDefault); @@ -4258,6 +4335,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( } for (auto& config : configs) { + CreateGlobalXCConfigSettings(root, config.second, config.first); + cmXCodeObject* buildSettingsForCfg = this->CreateFlatClone(buildSettings); // Put this last so it can override existing settings @@ -4711,10 +4790,12 @@ std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake( std::string cmGlobalXCodeGenerator::RelativeToSource(const std::string& p) { - // We force conversion because Xcode breakpoints do not work unless - // they are in a file named relative to the source tree. - return cmSystemTools::ForceToRelativePath( - this->CurrentRootGenerator->GetCurrentSourceDirectory(), p); + std::string const& rootSrc = + this->CurrentRootGenerator->GetCurrentSourceDirectory(); + if (cmSystemTools::IsSubDirectory(p, rootSrc)) { + return cmSystemTools::ForceToRelativePath(rootSrc, p); + } + return p; } std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p) @@ -4857,9 +4938,11 @@ bool cmGlobalXCodeGenerator::IsMultiConfig() const } bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation( - std::string* reason) const + cmTarget const& target, std::string* reason) const { - if (this->ObjectDirArch.find('$') != std::string::npos) { + auto objectDirArch = GetTargetObjectDirArch(target, this->ObjectDirArch); + + if (objectDirArch.find('$') != std::string::npos) { if (reason != nullptr) { *reason = " under Xcode with multiple architectures"; } @@ -4890,10 +4973,12 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { std::string configName = this->GetCMakeCFGIntDir(); + auto objectDirArch = GetTargetObjectDirArch(*gt, this->ObjectDirArch); + std::string dir = cmStrCat(this->GetObjectsDirectory("$(PROJECT_NAME)", configName, gt, "$(OBJECT_FILE_DIR_normal:base)/"), - this->ObjectDirArch, '/'); + objectDirArch, '/'); gt->ObjectDirectory = dir; } diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index ff6ffe8..92e4528 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -107,7 +107,8 @@ public: bool IsXcode() const override { return true; } - bool HasKnownObjectFileLocation(std::string* reason) const override; + bool HasKnownObjectFileLocation(cmTarget const&, + std::string* reason) const override; bool IsIPOSupported() const override { return true; } @@ -224,6 +225,12 @@ private: void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target, cmXCodeObject* buildSettings, const std::string& configName); + void CreateGlobalXCConfigSettings(cmLocalGenerator* root, + cmXCodeObject* config, + const std::string& configName); + void CreateTargetXCConfigSettings(cmGeneratorTarget* target, + cmXCodeObject* config, + const std::string& configName); void CreateBuildSettings(cmGeneratorTarget* gtgt, cmXCodeObject* buildSettings, const std::string& buildType); @@ -330,6 +337,8 @@ private: { } + std::string GetLibraryOrFrameworkPath(const std::string& path) const; + std::string GetObjectsDirectory(const std::string& projName, const std::string& configName, const cmGeneratorTarget* t, diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 55f6453..9cd1943 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -73,11 +73,11 @@ bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, } // watch for our state change if (scopeDepth == 0 && func.LowerCaseName() == "else") { + cmListFileBacktrace elseBT = mf.GetBacktrace().Push( + cmListFileContext{ func.OriginalName(), + this->GetStartingContext().FilePath, func.Line() }); if (this->ElseSeen) { - cmListFileBacktrace elseBT = mf.GetBacktrace().Push(cmListFileContext{ - func.OriginalName(), this->GetStartingContext().FilePath, - func.Line() }); mf.GetCMakeInstance()->IssueMessage( MessageType::FATAL_ERROR, "A duplicate ELSE command was found inside an IF block.", elseBT); @@ -92,7 +92,8 @@ bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, // if trace is enabled, print a (trivially) evaluated "else" // statement if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) { - mf.PrintCommandTrace(func); + mf.PrintCommandTrace(func, elseBT, + cmMakefile::CommandMissingFromStack::Yes); } } else if (scopeDepth == 0 && func.LowerCaseName() == "elseif") { cmListFileBacktrace elseifBT = mf.GetBacktrace().Push( @@ -111,7 +112,8 @@ bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, } else { // if trace is enabled, print the evaluated "elseif" statement if (mf.GetCMakeInstance()->GetTrace()) { - mf.PrintCommandTrace(func); + mf.PrintCommandTrace(func, elseifBT, + cmMakefile::CommandMissingFromStack::Yes); } std::string errorString; diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index bb08215..7ca5b23 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -35,7 +35,6 @@ #include "cmInstallRuntimeDependencySetGenerator.h" #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" -#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -49,6 +48,8 @@ #include "cmTargetExport.h" #include "cmValue.h" +class cmListFileBacktrace; + namespace { struct RuntimeDependenciesArgs @@ -918,8 +919,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, if (!objectArgs.GetDestination().empty()) { // Verify that we know where the objects are to install them. std::string reason; - if (!helper.Makefile->GetGlobalGenerator() - ->HasKnownObjectFileLocation(&reason)) { + if (!target.HasKnownObjectFileLocation(&reason)) { status.SetError( cmStrCat("TARGETS given OBJECT library \"", target.GetName(), "\" whose objects may not be installed", reason, ".")); diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index 86362e4..8462b99 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -6,6 +6,7 @@ #include "cmGeneratorExpression.h" #include "cmInstallType.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h index 0f91a59..419fd8c 100644 --- a/Source/cmInstallDirectoryGenerator.h +++ b/Source/cmInstallDirectoryGenerator.h @@ -9,9 +9,9 @@ #include <vector> #include "cmInstallGenerator.h" -#include "cmListFileCache.h" #include "cmScriptGenerator.h" +class cmListFileBacktrace; class cmLocalGenerator; /** \class cmInstallDirectoryGenerator diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 820f24a..f1ac656 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallExportGenerator.h" -#include <algorithm> #include <map> #include <sstream> #include <utility> @@ -15,6 +14,7 @@ #include "cmExportInstallFileGenerator.h" #include "cmExportSet.h" #include "cmInstallType.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -53,73 +53,36 @@ bool cmInstallExportGenerator::Compute(cmLocalGenerator* lg) return true; } -void cmInstallExportGenerator::ComputeTempDir() +std::string cmInstallExportGenerator::TempDirCalculate() const { // Choose a temporary directory in which to generate the import // files to be installed. - this->TempDir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), - "/CMakeFiles/Export"); + std::string path = cmStrCat( + this->LocalGenerator->GetCurrentBinaryDirectory(), "/CMakeFiles/Export"); if (this->Destination.empty()) { - return; - } - this->TempDir += "/"; - - // Enforce a maximum length. - bool useMD5 = false; -#if defined(_WIN32) || defined(__CYGWIN__) - std::string::size_type const max_total_len = 250; -#else - std::string::size_type const max_total_len = 1000; -#endif - // Will generate files of the form "<temp-dir>/<base>-<config>.<ext>". - std::string::size_type const len = this->TempDir.size() + 1 + - this->FileName.size() + 1 + this->GetMaxConfigLength(); - if (len < max_total_len) { - // Keep the total path length below the limit. - std::string::size_type const max_len = max_total_len - len; - if (this->Destination.size() > max_len) { - useMD5 = true; - } - } else { - useMD5 = true; + return path; } - if (useMD5) { - // Replace the destination path with a hash to keep it short. + #ifndef CMAKE_BOOTSTRAP - this->TempDir += cmSystemTools::ComputeStringMD5(this->Destination); + path += '/'; + // Replace the destination path with a hash to keep it short. + path += cmSystemTools::ComputeStringMD5(this->Destination); #endif - } else { - std::string dest = this->Destination; - // Avoid unix full paths. - if (dest[0] == '/') { - dest[0] = '_'; - } - // Avoid windows full paths by removing colons. - std::replace(dest.begin(), dest.end(), ':', '_'); - // Avoid relative paths that go up the tree. - cmSystemTools::ReplaceString(dest, "../", "__/"); - // Avoid spaces. - std::replace(dest.begin(), dest.end(), ' ', '_'); - this->TempDir += dest; - } + + return path; } -size_t cmInstallExportGenerator::GetMaxConfigLength() const +void cmInstallExportGenerator::ComputeTempDir() { - // Always use at least 8 for "noconfig". - size_t len = 8; - if (this->ConfigurationTypes->empty()) { - if (this->ConfigurationName.size() > 8) { - len = this->ConfigurationName.size(); - } - } else { - for (std::string const& c : *this->ConfigurationTypes) { - if (c.size() > len) { - len = c.size(); - } - } + this->TempDir = this->TempDirCalculate(); +} + +std::string cmInstallExportGenerator::GetTempDir() const +{ + if (this->TempDir.empty()) { + return this->TempDirCalculate(); } - return len; + return this->TempDir; } void cmInstallExportGenerator::GenerateScript(std::ostream& os) @@ -194,18 +157,22 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os, Indent indentNN = indentN.Next(); Indent indentNNN = indentNN.Next(); /* clang-format off */ - os << indentN << "file(DIFFERENT EXPORT_FILE_CHANGED FILES\n" + os << indentN << "file(DIFFERENT _cmake_export_file_changed FILES\n" << indentN << " \"" << installedFile << "\"\n" << indentN << " \"" << this->MainImportFile << "\")\n"; - os << indentN << "if(EXPORT_FILE_CHANGED)\n"; - os << indentNN << "file(GLOB OLD_CONFIG_FILES \"" << installedDir + os << indentN << "if(_cmake_export_file_changed)\n"; + os << indentNN << "file(GLOB _cmake_old_config_files \"" << installedDir << this->EFGen->GetConfigImportFileGlob() << "\")\n"; - os << indentNN << "if(OLD_CONFIG_FILES)\n"; + os << indentNN << "if(_cmake_old_config_files)\n"; + os << indentNNN << "string(REPLACE \";\" \", \" _cmake_old_config_files_text \"${_cmake_old_config_files}\")\n"; os << indentNNN << R"(message(STATUS "Old export file \")" << installedFile - << "\\\" will be replaced. Removing files [${OLD_CONFIG_FILES}].\")\n"; - os << indentNNN << "file(REMOVE ${OLD_CONFIG_FILES})\n"; + << "\\\" will be replaced. Removing files [${_cmake_old_config_files_text}].\")\n"; + os << indentNNN << "unset(_cmake_old_config_files_text)\n"; + os << indentNNN << "file(REMOVE ${_cmake_old_config_files})\n"; os << indentNN << "endif()\n"; + os << indentNN << "unset(_cmake_old_config_files)\n"; os << indentN << "endif()\n"; + os << indentN << "unset(_cmake_export_file_changed)\n"; os << indent << "endif()\n"; /* clang-format on */ diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index efeae86..dc07d36 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -4,18 +4,17 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <cstddef> #include <iosfwd> #include <memory> #include <string> #include <vector> #include "cmInstallGenerator.h" -#include "cmListFileCache.h" #include "cmScriptGenerator.h" class cmExportInstallFileGenerator; class cmExportSet; +class cmListFileBacktrace; class cmLocalGenerator; /** \class cmInstallExportGenerator @@ -50,6 +49,7 @@ public: std::string const& GetDestination() const { return this->Destination; } std::string GetDestinationFile() const; std::string GetFileName() const { return this->FileName; } + std::string GetTempDir() const; protected: void GenerateScript(std::ostream& os) override; @@ -57,8 +57,8 @@ protected: void GenerateScriptActions(std::ostream& os, Indent indent) override; void GenerateImportFile(cmExportSet const* exportSet); void GenerateImportFile(const char* config, cmExportSet const* exportSet); + std::string TempDirCalculate() const; void ComputeTempDir(); - size_t GetMaxConfigLength() const; cmExportSet* const ExportSet; std::string const FilePermissions; diff --git a/Source/cmInstallFileSetGenerator.cxx b/Source/cmInstallFileSetGenerator.cxx index 7121ea3..8c37312 100644 --- a/Source/cmInstallFileSetGenerator.cxx +++ b/Source/cmInstallFileSetGenerator.cxx @@ -11,6 +11,7 @@ #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmInstallType.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmStringAlgorithms.h" diff --git a/Source/cmInstallFileSetGenerator.h b/Source/cmInstallFileSetGenerator.h index 8d067d9..56341d4 100644 --- a/Source/cmInstallFileSetGenerator.h +++ b/Source/cmInstallFileSetGenerator.h @@ -8,11 +8,11 @@ #include <vector> #include "cmInstallGenerator.h" -#include "cmListFileCache.h" #include "cmScriptGenerator.h" class cmGeneratorTarget; class cmFileSet; +class cmListFileBacktrace; class cmLocalGenerator; class cmInstallFileSetGenerator : public cmInstallGenerator diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index 04aaa29..378b9fc 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -6,6 +6,7 @@ #include "cmGeneratorExpression.h" #include "cmInstallType.h" +#include "cmListFileCache.h" #include "cmStringAlgorithms.h" class cmLocalGenerator; diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index af7f113..2276ab8 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -9,9 +9,9 @@ #include <vector> #include "cmInstallGenerator.h" -#include "cmListFileCache.h" #include "cmScriptGenerator.h" +class cmListFileBacktrace; class cmLocalGenerator; /** \class cmInstallFilesGenerator diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index 4cfeb47..93abd45 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -41,10 +41,10 @@ void cmInstallGenerator::CheckCMP0082(bool& haveSubdirectoryInstall, void cmInstallGenerator::AddInstallRule( std::ostream& os, std::string const& dest, cmInstallType type, std::vector<std::string> const& files, bool optional /* = false */, - const char* permissions_file /* = 0 */, - const char* permissions_dir /* = 0 */, const char* rename /* = 0 */, - const char* literal_args /* = 0 */, Indent indent, - const char* files_var /* = 0 */) + const char* permissions_file /* = nullptr */, + const char* permissions_dir /* = nullptr */, + const char* rename /* = nullptr */, const char* literal_args /* = nullptr */, + Indent indent, const char* files_var /* = nullptr */) { // Use the FILE command to install the file. std::string stype; @@ -91,21 +91,28 @@ void cmInstallGenerator::AddInstallRule( os << "\")\n"; } if (files_var) { - os << indent << "foreach(_f IN LISTS " << files_var << ")\n"; - os << indent.Next() << "get_filename_component(_fn \"${_f}\" NAME)\n"; + os << indent << "foreach(_cmake_abs_file IN LISTS " << files_var + << ")\n"; + os << indent.Next() + << "get_filename_component(_cmake_abs_file_name " + "\"${_cmake_abs_file}\" NAME)\n"; os << indent.Next() << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES \"" - << dest << "/${_fn}\")\n"; + << dest << "/${_cmake_abs_file_name}\")\n"; os << indent << "endforeach()\n"; + os << indent << "unset(_cmake_abs_file_name)\n"; + os << indent << "unset(_cmake_abs_file)\n"; } os << indent << "if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n"; - os << indent.Next() << "message(WARNING \"ABSOLUTE path INSTALL " - << "DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"; + os << indent.Next() + << "message(WARNING \"ABSOLUTE path INSTALL " + "DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"; os << indent << "endif()\n"; os << indent << "if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n"; - os << indent.Next() << "message(FATAL_ERROR \"ABSOLUTE path INSTALL " - << "DESTINATION forbidden (by caller): " - << "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"; + os << indent.Next() + << "message(FATAL_ERROR \"ABSOLUTE path INSTALL " + "DESTINATION forbidden (by caller): " + "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"; os << indent << "endif()\n"; } std::string absDest = ConvertToAbsoluteDestination(dest); @@ -158,14 +165,22 @@ void cmInstallGenerator::AddInstallRule( } std::string cmInstallGenerator::CreateComponentTest( - const std::string& component, bool exclude_from_all) + const std::string& component, bool exclude_from_all, bool all_components) { - std::string result = R"("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "x)"; + if (all_components) { + if (exclude_from_all) { + return "CMAKE_INSTALL_COMPONENT"; + } + return {}; + } + + std::string result = "CMAKE_INSTALL_COMPONENT STREQUAL \""; result += component; - result += "x\""; + result += "\""; if (!exclude_from_all) { result += " OR NOT CMAKE_INSTALL_COMPONENT"; } + return result; } @@ -174,10 +189,11 @@ void cmInstallGenerator::GenerateScript(std::ostream& os) // Track indentation. Indent indent; + std::string component_test = this->CreateComponentTest( + this->Component, this->ExcludeFromAll, this->AllComponents); + // Begin this block of installation. - if (!this->AllComponents) { - std::string component_test = - this->CreateComponentTest(this->Component, this->ExcludeFromAll); + if (!component_test.empty()) { os << indent << "if(" << component_test << ")\n"; } @@ -186,7 +202,7 @@ void cmInstallGenerator::GenerateScript(std::ostream& os) this->AllComponents ? indent : indent.Next()); // End this block of installation. - if (!this->AllComponents) { + if (!component_test.empty()) { os << indent << "endif()\n\n"; } } diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index d342c99..9fcd284 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -78,7 +78,8 @@ protected: void GenerateScript(std::ostream& os) override; std::string CreateComponentTest(const std::string& component, - bool exclude_from_all); + bool exclude_from_all, + bool all_components = false); using TweakMethod = std::function<void(std::ostream& os, Indent indent, diff --git a/Source/cmInstallGetRuntimeDependenciesGenerator.cxx b/Source/cmInstallGetRuntimeDependenciesGenerator.cxx index 4d585ce..3e493bc 100644 --- a/Source/cmInstallGetRuntimeDependenciesGenerator.cxx +++ b/Source/cmInstallGetRuntimeDependenciesGenerator.cxx @@ -15,6 +15,7 @@ #include "cmGeneratorExpression.h" #include "cmInstallRuntimeDependencySet.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" diff --git a/Source/cmInstallGetRuntimeDependenciesGenerator.h b/Source/cmInstallGetRuntimeDependenciesGenerator.h index 19f6cc6..a2d6593 100644 --- a/Source/cmInstallGetRuntimeDependenciesGenerator.h +++ b/Source/cmInstallGetRuntimeDependenciesGenerator.h @@ -7,9 +7,9 @@ #include <vector> #include "cmInstallGenerator.h" -#include "cmListFileCache.h" #include "cmScriptGenerator.h" +class cmListFileBacktrace; class cmLocalGenerator; class cmInstallRuntimeDependencySet; diff --git a/Source/cmInstallRuntimeDependencySetGenerator.h b/Source/cmInstallRuntimeDependencySetGenerator.h index 8e98b57..680361b 100644 --- a/Source/cmInstallRuntimeDependencySetGenerator.h +++ b/Source/cmInstallRuntimeDependencySetGenerator.h @@ -7,10 +7,10 @@ #include <vector> #include "cmInstallGenerator.h" -#include "cmListFileCache.h" #include "cmScriptGenerator.h" class cmInstallRuntimeDependencySet; +class cmListFileBacktrace; class cmLocalGenerator; class cmInstallRuntimeDependencySetGenerator : public cmInstallGenerator diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx index 0a8e065..dd71332 100644 --- a/Source/cmInstallSubdirectoryGenerator.cxx +++ b/Source/cmInstallSubdirectoryGenerator.cxx @@ -7,6 +7,7 @@ #include <utility> #include <vector> +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmPolicies.h" diff --git a/Source/cmInstallSubdirectoryGenerator.h b/Source/cmInstallSubdirectoryGenerator.h index f174d07..7a472ed 100644 --- a/Source/cmInstallSubdirectoryGenerator.h +++ b/Source/cmInstallSubdirectoryGenerator.h @@ -8,8 +8,8 @@ #include <string> #include "cmInstallGenerator.h" -#include "cmListFileCache.h" +class cmListFileBacktrace; class cmLocalGenerator; class cmMakefile; diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h index 6690aef..48decbc 100644 --- a/Source/cmJSONHelpers.h +++ b/Source/cmJSONHelpers.h @@ -14,146 +14,126 @@ #include <cm3p/json/value.h> -template <typename T, typename E> -using cmJSONHelper = std::function<E(T& out, const Json::Value* value)>; +template <typename T, typename E, typename... CallState> +using cmJSONHelper = + std::function<E(T& out, const Json::Value* value, CallState&&... state)>; -template <typename T, typename E> -class cmJSONObjectHelper +template <typename E, typename... CallState> +struct cmJSONHelperBuilder { -public: - cmJSONObjectHelper(E&& success, E&& fail, bool allowExtra = true); - - template <typename U, typename M, typename F> - cmJSONObjectHelper& Bind(const cm::string_view& name, M U::*member, F func, - bool required = true); - template <typename M, typename F> - cmJSONObjectHelper& Bind(const cm::string_view& name, std::nullptr_t, F func, - bool required = true); - template <typename F> - cmJSONObjectHelper& Bind(const cm::string_view& name, F func, - bool required = true); - - E operator()(T& out, const Json::Value* value) const; - -private: - // Not a true cmJSONHelper, it just happens to match the signature - using MemberFunction = std::function<E(T& out, const Json::Value* value)>; - struct Member + template <typename T> + class Object { - cm::string_view Name; - MemberFunction Function; - bool Required; - }; - std::vector<Member> Members; - bool AnyRequired = false; - E Success; - E Fail; - bool AllowExtra; - - cmJSONObjectHelper& BindPrivate(const cm::string_view& name, - MemberFunction&& func, bool required); -}; - -template <typename T, typename E> -cmJSONObjectHelper<T, E>::cmJSONObjectHelper(E&& success, E&& fail, - bool allowExtra) - : Success(std::move(success)) - , Fail(std::move(fail)) - , AllowExtra(allowExtra) -{ -} + public: + Object(E&& success, E&& fail, bool allowExtra = true) + : Success(std::move(success)) + , Fail(std::move(fail)) + , AllowExtra(allowExtra) + { + } -template <typename T, typename E> -template <typename U, typename M, typename F> -cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind( - const cm::string_view& name, M U::*member, F func, bool required) -{ - return this->BindPrivate( - name, - [func, member](T& out, const Json::Value* value) -> E { - return func(out.*member, value); - }, - required); -} + template <typename U, typename M, typename F> + Object& Bind(const cm::string_view& name, M U::*member, F func, + bool required = true) + { + return this->BindPrivate(name, + [func, member](T& out, const Json::Value* value, + CallState&&... state) -> E { + return func(out.*member, value, + std::forward(state)...); + }, + required); + } + template <typename M, typename F> + Object& Bind(const cm::string_view& name, std::nullptr_t, F func, + bool required = true) + { + return this->BindPrivate(name, + [func](T& /*out*/, const Json::Value* value, + CallState&&... state) -> E { + M dummy; + return func(dummy, value, + std::forward(state)...); + }, + required); + } + template <typename F> + Object& Bind(const cm::string_view& name, F func, bool required = true) + { + return this->BindPrivate(name, MemberFunction(func), required); + } -template <typename T, typename E> -template <typename M, typename F> -cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind( - const cm::string_view& name, std::nullptr_t, F func, bool required) -{ - return this->BindPrivate(name, - [func](T& /*out*/, const Json::Value* value) -> E { - M dummy; - return func(dummy, value); - }, - required); -} + E operator()(T& out, const Json::Value* value, CallState&&... state) const + { + if (!value && this->AnyRequired) { + return this->Fail; + } + if (value && !value->isObject()) { + return this->Fail; + } + Json::Value::Members extraFields; + if (value) { + extraFields = value->getMemberNames(); + } -template <typename T, typename E> -template <typename F> -cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind( - const cm::string_view& name, F func, bool required) -{ - return this->BindPrivate(name, MemberFunction(func), required); -} + for (auto const& m : this->Members) { + std::string name(m.Name.data(), m.Name.size()); + if (value && value->isMember(name)) { + E result = m.Function(out, &(*value)[name], std::forward(state)...); + if (result != this->Success) { + return result; + } + extraFields.erase( + std::find(extraFields.begin(), extraFields.end(), name)); + } else if (!m.Required) { + E result = m.Function(out, nullptr, std::forward(state)...); + if (result != this->Success) { + return result; + } + } else { + return this->Fail; + } + } -template <typename T, typename E> -cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::BindPrivate( - const cm::string_view& name, MemberFunction&& func, bool required) -{ - Member m; - m.Name = name; - m.Function = std::move(func); - m.Required = required; - this->Members.push_back(std::move(m)); - if (required) { - this->AnyRequired = true; - } - return *this; -} + return this->AllowExtra || extraFields.empty() ? this->Success + : this->Fail; + } -template <typename T, typename E> -E cmJSONObjectHelper<T, E>::operator()(T& out, const Json::Value* value) const -{ - if (!value && this->AnyRequired) { - return this->Fail; - } - if (value && !value->isObject()) { - return this->Fail; - } - Json::Value::Members extraFields; - if (value) { - extraFields = value->getMemberNames(); - } + private: + // Not a true cmJSONHelper, it just happens to match the signature + using MemberFunction = + std::function<E(T& out, const Json::Value* value, CallState&&... state)>; + struct Member + { + cm::string_view Name; + MemberFunction Function; + bool Required; + }; + std::vector<Member> Members; + bool AnyRequired = false; + E Success; + E Fail; + bool AllowExtra; - for (auto const& m : this->Members) { - std::string name(m.Name.data(), m.Name.size()); - if (value && value->isMember(name)) { - E result = m.Function(out, &(*value)[name]); - if (result != this->Success) { - return result; - } - extraFields.erase( - std::find(extraFields.begin(), extraFields.end(), name)); - } else if (!m.Required) { - E result = m.Function(out, nullptr); - if (result != this->Success) { - return result; + Object& BindPrivate(const cm::string_view& name, MemberFunction&& func, + bool required) + { + Member m; + m.Name = name; + m.Function = std::move(func); + m.Required = required; + this->Members.push_back(std::move(m)); + if (required) { + this->AnyRequired = true; } - } else { - return this->Fail; + return *this; } - } - - return this->AllowExtra || extraFields.empty() ? this->Success : this->Fail; -} - -template <typename E> -cmJSONHelper<std::string, E> cmJSONStringHelper(E success, E fail, - const std::string& defval = "") -{ - return - [success, fail, defval](std::string& out, const Json::Value* value) -> E { + }; + static cmJSONHelper<std::string, E, CallState...> String( + E success, E fail, const std::string& defval = "") + { + return [success, fail, defval](std::string& out, const Json::Value* value, + CallState&&... /*state*/) -> E { if (!value) { out = defval; return success; @@ -164,30 +144,30 @@ cmJSONHelper<std::string, E> cmJSONStringHelper(E success, E fail, out = value->asString(); return success; }; -} + } -template <typename E> -cmJSONHelper<int, E> cmJSONIntHelper(E success, E fail, int defval = 0) -{ - return [success, fail, defval](int& out, const Json::Value* value) -> E { - if (!value) { - out = defval; + static cmJSONHelper<int, E, CallState...> Int(E success, E fail, + int defval = 0) + { + return [success, fail, defval](int& out, const Json::Value* value, + CallState&&... /*state*/) -> E { + if (!value) { + out = defval; + return success; + } + if (!value->isInt()) { + return fail; + } + out = value->asInt(); return success; - } - if (!value->isInt()) { - return fail; - } - out = value->asInt(); - return success; - }; -} + }; + } -template <typename E> -cmJSONHelper<unsigned int, E> cmJSONUIntHelper(E success, E fail, - unsigned int defval = 0) -{ - return - [success, fail, defval](unsigned int& out, const Json::Value* value) -> E { + static cmJSONHelper<unsigned int, E, CallState...> UInt( + E success, E fail, unsigned int defval = 0) + { + return [success, fail, defval](unsigned int& out, const Json::Value* value, + CallState&&... /*state*/) -> E { if (!value) { out = defval; return success; @@ -198,118 +178,126 @@ cmJSONHelper<unsigned int, E> cmJSONUIntHelper(E success, E fail, out = value->asUInt(); return success; }; -} + } -template <typename E> -cmJSONHelper<bool, E> cmJSONBoolHelper(E success, E fail, bool defval = false) -{ - return [success, fail, defval](bool& out, const Json::Value* value) -> E { - if (!value) { - out = defval; + static cmJSONHelper<bool, E, CallState...> Bool(E success, E fail, + bool defval = false) + { + return [success, fail, defval](bool& out, const Json::Value* value, + CallState&&... /*state*/) -> E { + if (!value) { + out = defval; + return success; + } + if (!value->isBool()) { + return fail; + } + out = value->asBool(); return success; - } - if (!value->isBool()) { - return fail; - } - out = value->asBool(); - return success; - }; -} + }; + } -template <typename T, typename E, typename F, typename Filter> -cmJSONHelper<std::vector<T>, E> cmJSONVectorFilterHelper(E success, E fail, - F func, Filter filter) -{ - return [success, fail, func, filter](std::vector<T>& out, - const Json::Value* value) -> E { - if (!value) { - out.clear(); - return success; - } - if (!value->isArray()) { - return fail; - } - out.clear(); - for (auto const& item : *value) { - T t; - E result = func(t, &item); - if (result != success) { - return result; + template <typename T, typename F, typename Filter> + static cmJSONHelper<std::vector<T>, E, CallState...> VectorFilter( + E success, E fail, F func, Filter filter) + { + return [success, fail, func, filter](std::vector<T>& out, + const Json::Value* value, + CallState&&... state) -> E { + if (!value) { + out.clear(); + return success; } - if (!filter(t)) { - continue; + if (!value->isArray()) { + return fail; } - out.push_back(std::move(t)); - } - return success; - }; -} - -template <typename T, typename E, typename F> -cmJSONHelper<std::vector<T>, E> cmJSONVectorHelper(E success, E fail, F func) -{ - return cmJSONVectorFilterHelper<T, E, F>(success, fail, func, - [](const T&) { return true; }); -} - -template <typename T, typename E, typename F, typename Filter> -cmJSONHelper<std::map<std::string, T>, E> cmJSONMapFilterHelper(E success, - E fail, F func, - Filter filter) -{ - return [success, fail, func, filter](std::map<std::string, T>& out, - const Json::Value* value) -> E { - if (!value) { out.clear(); + for (auto const& item : *value) { + T t; + E result = func(t, &item, std::forward(state)...); + if (result != success) { + return result; + } + if (!filter(t)) { + continue; + } + out.push_back(std::move(t)); + } return success; - } - if (!value->isObject()) { - return fail; - } - out.clear(); - for (auto const& key : value->getMemberNames()) { - if (!filter(key)) { - continue; + }; + } + + template <typename T, typename F> + static cmJSONHelper<std::vector<T>, E, CallState...> Vector(E success, + E fail, F func) + { + return VectorFilter<T, F>(success, fail, func, + [](const T&) { return true; }); + } + + template <typename T, typename F, typename Filter> + static cmJSONHelper<std::map<std::string, T>, E, CallState...> MapFilter( + E success, E fail, F func, Filter filter) + { + return [success, fail, func, filter](std::map<std::string, T>& out, + const Json::Value* value, + CallState&&... state) -> E { + if (!value) { + out.clear(); + return success; } - T t; - E result = func(t, &(*value)[key]); - if (result != success) { - return result; + if (!value->isObject()) { + return fail; } - out[key] = std::move(t); - } - return success; - }; -} + out.clear(); + for (auto const& key : value->getMemberNames()) { + if (!filter(key)) { + continue; + } + T t; + E result = func(t, &(*value)[key], std::forward(state)...); + if (result != success) { + return result; + } + out[key] = std::move(t); + } + return success; + }; + } -template <typename T, typename E, typename F> -cmJSONHelper<std::map<std::string, T>, E> cmJSONMapHelper(E success, E fail, - F func) -{ - return cmJSONMapFilterHelper<T, E, F>( - success, fail, func, [](const std::string&) { return true; }); -} + template <typename T, typename F> + static cmJSONHelper<std::map<std::string, T>, E, CallState...> Map(E success, + E fail, + F func) + { + return MapFilter<T, F>(success, fail, func, + [](const std::string&) { return true; }); + } -template <typename T, typename E, typename F> -cmJSONHelper<cm::optional<T>, E> cmJSONOptionalHelper(E success, F func) -{ - return [success, func](cm::optional<T>& out, const Json::Value* value) -> E { - if (!value) { - out.reset(); - return success; - } - out.emplace(); - return func(*out, value); - }; -} + template <typename T, typename F> + static cmJSONHelper<cm::optional<T>, E, CallState...> Optional(E success, + F func) + { + return [success, func](cm::optional<T>& out, const Json::Value* value, + CallState&&... state) -> E { + if (!value) { + out.reset(); + return success; + } + out.emplace(); + return func(*out, value, std::forward(state)...); + }; + } -template <typename T, typename E, typename F> -cmJSONHelper<T, E> cmJSONRequiredHelper(E fail, F func) -{ - return [fail, func](T& out, const Json::Value* value) -> E { - if (!value) { - return fail; - } - return func(out, value); - }; -} + template <typename T, typename F> + static cmJSONHelper<T, E, CallState...> Required(E fail, F func) + { + return [fail, func](T& out, const Json::Value* value, + CallState&&... state) -> E { + if (!value) { + return fail; + } + return func(out, value, std::forward(state)...); + }; + } +}; diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index e715659..262728b 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -70,6 +70,12 @@ struct cmLinkInterfaceLibraries // Object files listed in the interface. std::vector<cmLinkItem> Objects; + // Items to be included as if directly linked by the head target. + std::vector<cmLinkItem> HeadInclude; + + // Items to be excluded from direct linking by the head target. + std::vector<cmLinkItem> HeadExclude; + // Whether the list depends on a genex referencing the head target. bool HadHeadSensitiveCondition = false; diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx index d87d183..0ad846b 100644 --- a/Source/cmLinkItemGraphVisitor.cxx +++ b/Source/cmLinkItemGraphVisitor.cxx @@ -98,8 +98,8 @@ void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target, std::string const& config, DependencyMap& dependencies) { - const auto* implementationLibraries = - target.GetLinkImplementationLibraries(config); + const auto* implementationLibraries = target.GetLinkImplementationLibraries( + config, cmGeneratorTarget::LinkInterfaceFor::Link); if (implementationLibraries != nullptr) { for (auto const& lib : implementationLibraries->Libraries) { auto const& name = lib.AsStr(); diff --git a/Source/cmLinkLibrariesCommand.cxx b/Source/cmLinkLibrariesCommand.cxx index 2b8f836..ed89e91 100644 --- a/Source/cmLinkLibrariesCommand.cxx +++ b/Source/cmLinkLibrariesCommand.cxx @@ -35,5 +35,7 @@ bool cmLinkLibrariesCommand(std::vector<std::string> const& args, mf.AppendProperty("LINK_LIBRARIES", *i); } + mf.CheckProperty("LINK_LIBRARIES"); + return true; } diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 5646368..290642b 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -75,14 +75,8 @@ void cmLinkLineComputer::ComputeLinkLibs( BT<std::string> linkLib; if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { - if (item.IsObject == cmComputeLinkInformation::ItemIsObject::Yes) { - linkLib.Value += cli.GetObjLinkFileFlag(); - } else { - linkLib.Value += cli.GetLibLinkFileFlag(); - } - linkLib.Value += this->ConvertToOutputFormat( - this->ConvertToLinkReference(item.Value.Value)); - linkLib.Backtrace = item.Value.Backtrace; + linkLib = item.GetFormattedItem(this->ConvertToOutputFormat( + this->ConvertToLinkReference(item.Value.Value))); } else { linkLib = item.Value; } diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 43f161b..43f1b8e 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -118,8 +118,10 @@ void cmLinkLineDeviceComputer::ComputeLinkLibraries( // can tolerate '.so' or '.dylib' it cannot tolerate '.so.1'. if (cmHasLiteralSuffix(item.Value.Value, ".a") || cmHasLiteralSuffix(item.Value.Value, ".lib")) { - linkLib.Value += this->ConvertToOutputFormat( - this->ConvertToLinkReference(item.Value.Value)); + linkLib.Value = item + .GetFormattedItem(this->ConvertToOutputFormat( + this->ConvertToLinkReference(item.Value.Value))) + .Value; } } else if (item.Value == "-framework") { // This is the first part of '-framework Name' where the framework @@ -127,14 +129,15 @@ void cmLinkLineDeviceComputer::ComputeLinkLibraries( skipItemAfterFramework = true; continue; } else if (cmLinkItemValidForDevice(item.Value.Value)) { - linkLib.Value += item.Value.Value; + linkLib.Value = item.Value.Value; } if (emitted.insert(linkLib.Value).second) { linkLib.Value += " "; const cmLinkImplementation* linkImpl = - cli.GetTarget()->GetLinkImplementation(cli.GetConfig()); + cli.GetTarget()->GetLinkImplementation( + cli.GetConfig(), cmGeneratorTarget::LinkInterfaceFor::Link); for (const cmLinkImplItem& iter : linkImpl->Libraries) { if (iter.Target != nullptr && diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 3da266d..5133521 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -1,8 +1,8 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ +#define cmListFileCache_cxx #include "cmListFileCache.h" -#include <cassert> #include <memory> #include <sstream> #include <utility> @@ -40,6 +40,7 @@ struct cmListFileParser cmListFileLexer* Lexer; std::string FunctionName; long FunctionLine; + long FunctionLineEnd; std::vector<cmListFileArgument> FunctionArguments; enum { @@ -146,7 +147,7 @@ bool cmListFileParser::Parse() if (this->ParseFunction(token->text, token->line)) { this->ListFile->Functions.emplace_back( std::move(this->FunctionName), this->FunctionLine, - std::move(this->FunctionArguments)); + this->FunctionLineEnd, std::move(this->FunctionArguments)); } else { return false; } @@ -259,6 +260,7 @@ bool cmListFileParser::ParseFunction(const char* name, long line) } } else if (token->type == cmListFileLexer_Token_ParenRight) { if (parenDepth == 0) { + this->FunctionLineEnd = token->line; return true; } parenDepth--; @@ -443,64 +445,8 @@ cm::optional<cmListFileContext> cmListFileParser::CheckNesting() const return cm::nullopt; } -// We hold a call/file context. -struct cmListFileBacktrace::Entry -{ - Entry(std::shared_ptr<Entry const> parent, cmListFileContext lfc) - : Context(std::move(lfc)) - , Parent(std::move(parent)) - { - } - - cmListFileContext Context; - std::shared_ptr<Entry const> Parent; -}; - -/* NOLINTNEXTLINE(performance-unnecessary-value-param) */ -cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> parent, - cmListFileContext const& lfc) - : TopEntry(std::make_shared<Entry const>(std::move(parent), lfc)) -{ -} - -cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> top) - : TopEntry(std::move(top)) -{ -} - -cmListFileBacktrace cmListFileBacktrace::Push(std::string const& file) const -{ - // We are entering a file-level scope but have not yet reached - // any specific line or command invocation within it. This context - // is useful to print when it is at the top but otherwise can be - // skipped during call stack printing. - cmListFileContext lfc; - lfc.FilePath = file; - return this->Push(lfc); -} - -cmListFileBacktrace cmListFileBacktrace::Push( - cmListFileContext const& lfc) const -{ - return cmListFileBacktrace(this->TopEntry, lfc); -} - -cmListFileBacktrace cmListFileBacktrace::Pop() const -{ - assert(this->TopEntry); - return cmListFileBacktrace(this->TopEntry->Parent); -} - -cmListFileContext const& cmListFileBacktrace::Top() const -{ - assert(this->TopEntry); - return this->TopEntry->Context; -} - -bool cmListFileBacktrace::Empty() const -{ - return !this->TopEntry; -} +#include "cmConstStack.tcc" +template class cmConstStack<cmListFileContext, cmListFileBacktrace>; std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc) { @@ -539,11 +485,11 @@ 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>> cmExpandListWithBacktrace( + std::string const& list, cmListFileBacktrace const& bt, bool emptyArgs) { std::vector<BT<std::string>> result; - std::vector<std::string> tmp = cmExpandedList(list); + std::vector<std::string> tmp = cmExpandedList(list, emptyArgs); result.reserve(tmp.size()); for (std::string& i : tmp) { result.emplace_back(std::move(i), bt); diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 5d45027..f7c2509 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -12,6 +12,7 @@ #include <cm/optional> +#include "cmConstStack.h" #include "cmSystemTools.h" /** \class cmListFileCache @@ -51,9 +52,9 @@ struct cmListFileArgument class cmListFileFunction { public: - cmListFileFunction(std::string name, long line, + cmListFileFunction(std::string name, long line, long lineEnd, std::vector<cmListFileArgument> args) - : Impl{ std::make_shared<Implementation>(std::move(name), line, + : Impl{ std::make_shared<Implementation>(std::move(name), line, lineEnd, std::move(args)) } { } @@ -69,6 +70,7 @@ public: } long Line() const noexcept { return this->Impl->Line; } + long LineEnd() const noexcept { return this->Impl->LineEnd; } std::vector<cmListFileArgument> const& Arguments() const noexcept { @@ -78,11 +80,12 @@ public: private: struct Implementation { - Implementation(std::string name, long line, + Implementation(std::string name, long line, long lineEnd, std::vector<cmListFileArgument> args) : OriginalName{ std::move(name) } , LowerCaseName{ cmSystemTools::LowerCase(this->OriginalName) } , Line{ line } + , LineEnd{ lineEnd } , Arguments{ std::move(args) } { } @@ -90,6 +93,7 @@ private: std::string OriginalName; std::string LowerCaseName; long Line = 0; + long LineEnd = 0; std::vector<cmListFileArgument> Arguments; }; @@ -125,6 +129,17 @@ public: { } + static cmListFileContext FromListFilePath(std::string const& filePath) + { + // We are entering a file-level scope but have not yet reached + // any specific line or command invocation within it. This context + // is useful to print when it is at the top but otherwise can be + // skipped during call stack printing. + cmListFileContext lfc; + lfc.FilePath = filePath; + return lfc; + } + static cmListFileContext FromListFileFunction( cmListFileFunction const& lff, std::string const& fileName, cm::optional<std::string> deferId = {}) @@ -143,38 +158,16 @@ bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs); bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs); bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs); -// Represent a backtrace (call stack). Provide value semantics -// but use efficient reference-counting underneath to avoid copies. +// Represent a backtrace (call stack) with efficient value semantics. class cmListFileBacktrace + : public cmConstStack<cmListFileContext, cmListFileBacktrace> { -public: - // Default-constructed backtrace is empty. - cmListFileBacktrace() = default; - - // Get a backtrace with the given file scope added to the top. - cmListFileBacktrace Push(std::string const& file) const; - - // Get a backtrace with the given call context added to the top. - cmListFileBacktrace Push(cmListFileContext const& lfc) const; - - // Get a backtrace with the top level removed. - // May not be called until after a matching Push. - cmListFileBacktrace Pop() const; - - // Get the context at the top of the backtrace. - // This may be called only if Empty() would return false. - cmListFileContext const& Top() const; - - // Return true if this backtrace is empty. - bool Empty() const; - -private: - struct Entry; - std::shared_ptr<Entry const> TopEntry; - cmListFileBacktrace(std::shared_ptr<Entry const> parent, - cmListFileContext const& lfc); - cmListFileBacktrace(std::shared_ptr<Entry const> top); + using cmConstStack::cmConstStack; + friend class cmConstStack<cmListFileContext, cmListFileBacktrace>; }; +#ifndef cmListFileCache_cxx +extern template class cmConstStack<cmListFileContext, cmListFileBacktrace>; +#endif // Wrap type T as a value with a backtrace. For purposes of // ordering and equality comparison, only the original value is @@ -230,9 +223,10 @@ public: friend bool operator==(T const& l, BTs<T> const& r) { return l == r.Value; } }; -std::vector<BT<std::string>> ExpandListWithBacktrace( +std::vector<BT<std::string>> cmExpandListWithBacktrace( std::string const& list, - cmListFileBacktrace const& bt = cmListFileBacktrace()); + cmListFileBacktrace const& bt = cmListFileBacktrace(), + bool emptyArgs = false); struct cmListFile { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index e39309c..e2bcea8 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1025,6 +1025,14 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, flags.emplace_back(std::move(compReqFlag)); } + // Add Warning as errors flags + const cmValue wError = target->GetProperty("COMPILE_WARNING_AS_ERROR"); + const cmValue wErrorFlag = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_WARNING_AS_ERROR")); + if (wError.IsOn() && wErrorFlag.IsSet()) { + flags.emplace_back(wErrorFlag); + } + // Add compile flag for the MSVC compiler only. cmMakefile* mf = this->GetMakefile(); if (cmValue jmc = @@ -1609,6 +1617,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetTargetCompileFlags( this->AddCMP0018Flags(compileFlags, target, lang, config); this->AddVisibilityPresetFlags(compileFlags, target, lang); + this->AddColorDiagnosticsFlags(compileFlags, lang); this->AppendFlags(compileFlags, mf->GetDefineFlags()); this->AppendFlags(compileFlags, this->GetFrameworkFlags(lang, config, target)); @@ -1918,6 +1927,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, std::string compilerSimulateId = this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_", lang, "_SIMULATE_ID")); + if (lang == "Swift") { if (cmValue v = target->GetProperty("Swift_LANGUAGE_VERSION")) { if (cmSystemTools::VersionCompare( @@ -1993,6 +2003,38 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, } } } + + // Add Watcom runtime library flags. This is activated by the presence + // of a default selection whether or not it is overridden by a property. + cmValue watcomRuntimeLibraryDefault = + this->Makefile->GetDefinition("CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT"); + if (cmNonempty(watcomRuntimeLibraryDefault)) { + cmValue watcomRuntimeLibraryValue = + target->GetProperty("WATCOM_RUNTIME_LIBRARY"); + if (!watcomRuntimeLibraryValue) { + watcomRuntimeLibraryValue = watcomRuntimeLibraryDefault; + } + std::string const watcomRuntimeLibrary = cmGeneratorExpression::Evaluate( + *watcomRuntimeLibraryValue, this, config, target); + if (!watcomRuntimeLibrary.empty()) { + if (cmValue watcomRuntimeLibraryOptions = this->Makefile->GetDefinition( + "CMAKE_" + lang + "_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_" + + watcomRuntimeLibrary)) { + this->AppendCompileOptions(flags, *watcomRuntimeLibraryOptions); + } else if ((this->Makefile->GetSafeDefinition( + "CMAKE_" + lang + "_COMPILER_ID") == "OpenWatcom" || + this->Makefile->GetSafeDefinition( + "CMAKE_" + lang + "_SIMULATE_ID") == "OpenWatcom") && + !cmSystemTools::GetErrorOccuredFlag()) { + // The compiler uses the Watcom ABI so it needs a known runtime + // library. + this->IssueMessage(MessageType::FATAL_ERROR, + "WATCOM_RUNTIME_LIBRARY value '" + + watcomRuntimeLibrary + "' not known for this " + + lang + " compiler."); + } + } + } } void cmLocalGenerator::AddLanguageFlagsForLinking( @@ -2354,6 +2396,29 @@ void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags, } } +void cmLocalGenerator::AddColorDiagnosticsFlags(std::string& flags, + const std::string& lang) +{ + cmValue diag = this->Makefile->GetDefinition("CMAKE_COLOR_DIAGNOSTICS"); + if (diag.IsSet()) { + std::string colorFlagName; + if (diag.IsOn()) { + colorFlagName = + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_COLOR_DIAGNOSTICS"); + } else { + colorFlagName = + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_COLOR_DIAGNOSTICS_OFF"); + } + + std::vector<std::string> options; + this->Makefile->GetDefExpandList(colorFlagName, options); + + for (std::string const& option : options) { + this->AppendFlagEscape(flags, option); + } + } +} + void cmLocalGenerator::AddConfigVariableFlags(std::string& flags, const std::string& var, const std::string& config) @@ -3201,7 +3266,7 @@ void cmLocalGenerator::AppendDefines(std::set<std::string>& defines, std::string const& defines_list) const { std::set<BT<std::string>> tmp; - this->AppendDefines(tmp, ExpandListWithBacktrace(defines_list)); + this->AppendDefines(tmp, cmExpandListWithBacktrace(defines_list)); for (BT<std::string> const& i : tmp) { defines.emplace(i.Value); } @@ -3216,7 +3281,7 @@ void cmLocalGenerator::AppendDefines(std::set<BT<std::string>>& defines, } // Expand the list of definitions. - this->AppendDefines(defines, ExpandListWithBacktrace(defines_list)); + this->AppendDefines(defines, cmExpandListWithBacktrace(defines_list)); } void cmLocalGenerator::AppendDefines( diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 115a54a..da3c9fd 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -159,6 +159,7 @@ public: cmGeneratorTarget const* target, const std::string& lang, const std::string& config); + void AddColorDiagnosticsFlags(std::string& flags, const std::string& lang); //! Append flags to a string. virtual void AppendFlags(std::string& flags, const std::string& newFlags) const; @@ -169,6 +170,7 @@ public: void AddISPCDependencies(cmGeneratorTarget* target); void AddPchDependencies(cmGeneratorTarget* target); void AddUnityBuild(cmGeneratorTarget* target); + virtual void AddXCConfigSources(cmGeneratorTarget* /* target */) {} void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, const std::string& config, const std::string& lang); diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 3118bb4..4d393d9 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -10,7 +10,6 @@ #include <string> #include <vector> -#include "cmListFileCache.h" #include "cmLocalCommonGenerator.h" #include "cmNinjaTypes.h" #include "cmOutputConverter.h" @@ -21,6 +20,7 @@ class cmGeneratedFileStream; class cmGeneratorTarget; class cmGlobalGenerator; class cmGlobalNinjaGenerator; +class cmListFileBacktrace; class cmMakefile; class cmRulePlaceholderExpander; class cmake; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 0f8cdca..97a275a 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -133,7 +133,11 @@ void cmLocalUnixMakefileGenerator3::Generate() // Record whether some options are enabled to avoid checking many // times later. if (!this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile()) { - this->ColorMakefile = this->Makefile->IsOn("CMAKE_COLOR_MAKEFILE"); + if (this->Makefile->IsSet("CMAKE_COLOR_MAKEFILE")) { + this->ColorMakefile = this->Makefile->IsOn("CMAKE_COLOR_MAKEFILE"); + } else { + this->ColorMakefile = this->Makefile->IsOn("CMAKE_COLOR_DIAGNOSTICS"); + } } this->SkipPreprocessedSourceRules = this->Makefile->IsOn("CMAKE_SKIP_PREPROCESSED_SOURCE_RULES"); @@ -1508,13 +1512,12 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( } // Setup relative path top directories. - if (cmValue relativePathTopSource = - mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE")) { - this->SetRelativePathTopSource(*relativePathTopSource); - } - if (cmValue relativePathTopBinary = - mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY")) { - this->SetRelativePathTopBinary(*relativePathTopBinary); + cmValue relativePathTopSource = + mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE"); + cmValue relativePathTopBinary = + mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY"); + if (relativePathTopSource && relativePathTopBinary) { + this->SetRelativePathTop(*relativePathTopSource, *relativePathTopBinary); } } else { cmSystemTools::Error("Directory Information file not found"); @@ -1849,7 +1852,7 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf, cmSystemTools::Touch(DepTimestamp.GenericString(), true); // clear the dependencies files generated by the compiler - std::vector<std::string> dependencies = cmExpandedList(depsFiles); + std::vector<std::string> dependencies = cmExpandedList(depsFiles, true); cmDependsCompiler depsManager; depsManager.SetVerbose(verbose); depsManager.ClearDependencies(dependencies); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index ed7e888..f65add1 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1294,7 +1294,9 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries( for (auto const& lib : libs) { if (lib.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { std::string rel = lg->MaybeRelativeToCurBinDir(lib.Value.Value); - fout << lg->ConvertToXMLOutputPath(rel) << " "; + rel = lg->ConvertToXMLOutputPath(rel); + fout << (lib.HasFeature() ? lib.GetFormattedItem(rel).Value : rel) + << " "; } else if (!lib.Target || lib.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { fout << lib.Value.Value << " "; diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 93f01ed..2703c7b 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -252,7 +252,7 @@ std::string cmLocalVisualStudioGenerator::FinishConstructScript( // Store the script in a string. std::string script; - if (useLocal && projectType == VsProjectType::csproj) { + if (useLocal && projectType != VsProjectType::vcxproj) { // This label is not provided by MSBuild for C# projects. script += newline; script += this->GetReportErrorLabel(); diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index dd064a1..e7a1f93 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -6,6 +6,7 @@ #include <ostream> #include <utility> +#include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalXCodeGenerator.h" #include "cmMakefile.h" @@ -134,3 +135,22 @@ void cmLocalXCodeGenerator::ComputeObjectFilenames( si.second = objectName; } } + +void cmLocalXCodeGenerator::AddXCConfigSources(cmGeneratorTarget* target) +{ + auto xcconfig = target->GetProperty("XCODE_XCCONFIG"); + if (!xcconfig) { + return; + } + auto configs = target->Makefile->GetGeneratorConfigs( + cmMakefile::IncludeEmptyConfig); + + for (auto& config : configs) { + auto file = cmGeneratorExpression::Evaluate( + xcconfig, + this, config); + if (!file.empty()) { + target->AddSource(file); + } + } +} diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h index ff6b356..b825161 100644 --- a/Source/cmLocalXCodeGenerator.h +++ b/Source/cmLocalXCodeGenerator.h @@ -38,5 +38,7 @@ public: std::map<cmSourceFile const*, std::string>& mapping, cmGeneratorTarget const* gt = nullptr) override; + void AddXCConfigSources(cmGeneratorTarget* target) override; + private: }; diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 154df63..ef12487 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -116,7 +116,7 @@ bool cmMacroHelperCommand::operator()( newLFFArgs.push_back(std::move(arg)); } cmListFileFunction newLFF{ func.OriginalName(), func.Line(), - std::move(newLFFArgs) }; + func.LineEnd(), std::move(newLFFArgs) }; cmExecutionStatus status(makefile); if (!makefile.ExecuteCommand(newLFF, status) || status.GetNestedError()) { // The error message should have already included the call stack diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 94d3be6..91d7ac5 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -241,14 +241,14 @@ cmListFileBacktrace cmMakefile::GetBacktrace() const return this->Backtrace; } -void cmMakefile::PrintCommandTrace( - cmListFileFunction const& lff, - cm::optional<std::string> const& deferId) const +void cmMakefile::PrintCommandTrace(cmListFileFunction const& lff, + cmListFileBacktrace const& bt, + CommandMissingFromStack missing) const { // Check if current file in the list of requested to trace... std::vector<std::string> const& trace_only_this_files = this->GetCMakeInstance()->GetTraceSources(); - std::string const& full_path = this->GetBacktrace().Top().FilePath; + std::string const& full_path = bt.Top().FilePath; std::string const& only_filename = cmSystemTools::GetFilenameName(full_path); bool trace = trace_only_this_files.empty(); if (!trace) { @@ -282,6 +282,7 @@ void cmMakefile::PrintCommandTrace( args.push_back(arg.Value); } } + cm::optional<std::string> const& deferId = bt.Top().DeferId; switch (this->GetCMakeInstance()->GetTraceFormat()) { case cmake::TraceFormat::TRACE_JSON_V1: { @@ -291,6 +292,9 @@ void cmMakefile::PrintCommandTrace( builder["indentation"] = ""; val["file"] = full_path; val["line"] = static_cast<Json::Value::Int64>(lff.Line()); + if (lff.Line() != lff.LineEnd()) { + val["line_end"] = static_cast<Json::Value::Int64>(lff.LineEnd()); + } if (deferId) { val["defer"] = *deferId; } @@ -300,8 +304,10 @@ void cmMakefile::PrintCommandTrace( val["args"].append(arg); } val["time"] = cmSystemTools::GetTime(); - val["frame"] = + val["frame"] = (missing == CommandMissingFromStack::Yes ? 1 : 0) + static_cast<Json::Value::UInt64>(this->ExecutionStatusStack.size()); + val["global_frame"] = (missing == CommandMissingFromStack::Yes ? 1 : 0) + + static_cast<Json::Value::UInt64>(this->RecursionDepth); msg << Json::writeString(builder, val); #endif break; @@ -422,7 +428,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, if (!cmSystemTools::GetFatalErrorOccured()) { // if trace is enabled, print out invoke information if (this->GetCMakeInstance()->GetTrace()) { - this->PrintCommandTrace(lff, this->Backtrace.Top().DeferId); + this->PrintCommandTrace(lff, this->Backtrace); } // Try invoking the command. bool invokeSucceeded = command(lff.Arguments(), status); @@ -453,6 +459,11 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, return result; } +bool cmMakefile::IsImportedTargetGlobalScope() const +{ + return this->CurrentImportedTargetScope == ImportedTargetScope::Global; +} + class cmMakefile::IncludeScope { public: @@ -480,7 +491,8 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf, , CheckCMP0011(false) , ReportError(true) { - this->Makefile->Backtrace = this->Makefile->Backtrace.Push(filenametoread); + this->Makefile->Backtrace = this->Makefile->Backtrace.Push( + cmListFileContext::FromListFilePath(filenametoread)); this->Makefile->PushFunctionBlockerBarrier(); @@ -613,7 +625,8 @@ public: : Makefile(mf) , ReportError(true) { - this->Makefile->Backtrace = this->Makefile->Backtrace.Push(filenametoread); + this->Makefile->Backtrace = this->Makefile->Backtrace.Push( + cmListFileContext::FromListFilePath(filenametoread)); this->Makefile->StateSnapshot = this->Makefile->GetState()->CreateInlineListFileSnapshot( @@ -1576,7 +1589,8 @@ void cmMakefile::Configure() // Add the bottom of all backtraces within this directory. // We will never pop this scope because it should be available // for messages during the generate step too. - this->Backtrace = this->Backtrace.Push(currentStart); + this->Backtrace = + this->Backtrace.Push(cmListFileContext::FromListFilePath(currentStart)); BuildsystemFileScope scope(this); @@ -1663,6 +1677,7 @@ void cmMakefile::Configure() this->Backtrace); cmListFileFunction project{ "project", 0, + 0, { { "Project", cmListFileArgument::Unquoted, 0 }, { "__CMAKE_INJECTED_PROJECT_COMMAND__", @@ -3976,6 +3991,31 @@ std::vector<std::string> cmMakefile::GetPropertyKeys() const return this->StateSnapshot.GetDirectory().GetPropertyKeys(); } +void cmMakefile::CheckProperty(const std::string& prop) const +{ + // Certain properties need checking. + if (prop == "LINK_LIBRARIES") { + if (cmValue value = this->GetProperty(prop)) { + // Look for <LINK_LIBRARY:> internal pattern + static cmsys::RegularExpression linkPattern( + "(^|;)(</?LINK_(LIBRARY|GROUP):[^;>]*>)(;|$)"); + if (!linkPattern.find(value)) { + return; + } + + // Report an error. + this->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Property ", prop, " contains the invalid item \"", + linkPattern.match(2), "\". The ", prop, + " property may contain the generator-expression \"$<LINK_", + linkPattern.match(3), + ":...>\" which may be used to specify how the libraries are " + "linked.")); + } + } +} + cmTarget* cmMakefile::FindLocalNonAliasTarget(const std::string& name) const { auto i = this->Targets.find(name); @@ -4395,12 +4435,14 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, } // Deprecate old policies. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0094 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0097 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. id == cmPolicies::CMP0065 || id == cmPolicies::CMP0083 || - id == cmPolicies::CMP0091))) { + id == cmPolicies::CMP0091)) && + (!this->IsSet("CMAKE_WARN_DEPRECATED") || + this->IsOn("CMAKE_WARN_DEPRECATED"))) { this->IssueMessage(MessageType::DEPRECATION_WARNING, cmPolicies::GetPolicyDeprecatedWarning(id)); } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index f425697..c8e1e83 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -674,11 +674,18 @@ public: bool copyonly, bool atOnly, bool escapeQuotes, mode_t permissions = 0, cmNewLineStyle = cmNewLineStyle()); + enum class CommandMissingFromStack + { + No, + Yes, + }; + /** * Print a command's invocation */ - void PrintCommandTrace(cmListFileFunction const& lff, - cm::optional<std::string> const& deferId = {}) const; + void PrintCommandTrace( + cmListFileFunction const& lff, cmListFileBacktrace const& bt, + CommandMissingFromStack missing = CommandMissingFromStack::No) const; /** * Set a callback that is invoked whenever ExecuteCommand is called. @@ -787,6 +794,7 @@ public: cmValue GetProperty(const std::string& prop, bool chain) const; bool GetPropertyAsBool(const std::string& prop) const; std::vector<std::string> GetPropertyKeys() const; + void CheckProperty(const std::string& prop) const; //! Initialize a makefile from its parent void InitializeFromParent(cmMakefile* parent); @@ -859,6 +867,44 @@ public: void PushLoopBlockBarrier(); void PopLoopBlockBarrier(); + bool IsImportedTargetGlobalScope() const; + + enum class ImportedTargetScope + { + Local, + Global, + }; + + /** Helper class to manage whether imported packages + * should be globally scoped based off the find package command + */ + class SetGlobalTargetImportScope + { + public: + SetGlobalTargetImportScope(cmMakefile* mk, ImportedTargetScope const scope) + : Makefile(mk) + { + if (scope == ImportedTargetScope::Global && + !this->Makefile->IsImportedTargetGlobalScope()) { + this->Makefile->CurrentImportedTargetScope = scope; + this->Set = true; + } else { + this->Set = false; + } + } + ~SetGlobalTargetImportScope() + { + if (this->Set) { + this->Makefile->CurrentImportedTargetScope = + ImportedTargetScope::Local; + } + } + + private: + cmMakefile* Makefile; + bool Set; + }; + /** Helper class to push and pop scopes automatically. */ class ScopePushPop { @@ -1123,4 +1169,5 @@ private: std::set<std::string> WarnedCMP0074; bool IsSourceFileTryCompile; mutable bool SuppressSideEffects; + ImportedTargetScope CurrentImportedTargetScope = ImportedTargetScope::Local; }; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 1c92c7f..aec6577 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -305,9 +305,14 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() std::vector<cmSourceFile const*> objectSources; this->GeneratorTarget->GetObjectSources(objectSources, this->GetConfigName()); - for (cmSourceFile const* sf : objectSources) { - // Generate this object file's rule file. - this->WriteObjectRuleFiles(*sf); + + // validate that all languages requested are enabled. + std::set<std::string> requiredLangs; + if (this->HaveRequiredLanguages(objectSources, requiredLangs)) { + for (cmSourceFile const* sf : objectSources) { + // Generate this object file's rule file. + this->WriteObjectRuleFiles(*sf); + } } } @@ -532,8 +537,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmSourceFile const& source) { // Identify the language of the source file. - const std::string& lang = - this->LocalGenerator->GetSourceFileLanguage(source); + const std::string& lang = source.GetLanguage(); if (lang.empty()) { // don't know anything about this file so skip it return; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 1c5bac8..4f6da0e 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -126,15 +126,11 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules( std::set<std::string> languages; std::vector<cmSourceFile const*> sourceFiles; this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config); - for (cmSourceFile const* sf : sourceFiles) { - std::string const lang = sf->GetLanguage(); - if (!lang.empty()) { - languages.insert(lang); + if (this->HaveRequiredLanguages(sourceFiles, languages)) { + for (std::string const& language : languages) { + this->WriteLanguageRules(language, config); } } - for (std::string const& language : languages) { - this->WriteLanguageRules(language, config); - } } const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index e61b4b6..3fac7f5 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -21,6 +21,7 @@ #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" +#include "cmFileSet.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -28,6 +29,7 @@ #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmNinjaNormalTargetGenerator.h" #include "cmNinjaUtilityTargetGenerator.h" #include "cmOutputConverter.h" @@ -39,6 +41,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTarget.h" #include "cmValue.h" #include "cmake.h" @@ -252,6 +255,55 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( flags, genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS)); } + if (this->NeedCxxModuleSupport(language, config)) { + auto const& path = source->GetFullPath(); + auto const* tgt = this->GeneratorTarget->Target; + + std::string file_set_type; + + for (auto const& name : tgt->GetAllFileSetNames()) { + auto const* file_set = tgt->GetFileSet(name); + if (!file_set) { + this->GetMakefile()->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("Target `", tgt->GetName(), + "` is tracked to have file set `", name, + "`, but it was not found.")); + continue; + } + + auto fileEntries = file_set->CompileFileEntries(); + auto directoryEntries = file_set->CompileDirectoryEntries(); + auto directories = file_set->EvaluateDirectoryEntries( + directoryEntries, this->LocalGenerator, config, this->GeneratorTarget); + + std::map<std::string, std::vector<std::string>> files; + for (auto const& entry : fileEntries) { + file_set->EvaluateFileEntry(directories, files, entry, + this->LocalGenerator, config, + this->GeneratorTarget); + } + + for (auto const& it : files) { + for (auto const& filename : it.second) { + if (filename == path) { + file_set_type = file_set->GetType(); + break; + } + } + } + + if (!file_set_type.empty()) { + std::string source_type_var = cmStrCat( + "CMAKE_EXPERIMENTAL_CXX_MODULE_SOURCE_TYPE_FLAG_", file_set_type); + cmMakefile* mf = this->GetMakefile(); + if (cmValue source_type_flag = mf->GetDefinition(source_type_var)) { + this->LocalGenerator->AppendFlags(flags, *source_type_flag); + } + } + } + } + return flags; } @@ -534,6 +586,7 @@ std::string GetScanCommand(const std::string& cmakeCmd, const std::string& tdi, // not perform explicit preprocessing too. cmNinjaRule GetScanRule( std::string const& ruleName, std::string const& ppFileName, + std::string const& deptype, cmRulePlaceholderExpander::RuleVariables const& vars, const std::string& responseFlag, const std::string& flags, cmRulePlaceholderExpander* const rulePlaceholderExpander, @@ -542,8 +595,13 @@ cmNinjaRule GetScanRule( { cmNinjaRule rule(ruleName); // Scanning always uses a depfile for preprocessor dependencies. - rule.DepType = ""; // no deps= for multiple outputs - rule.DepFile = "$DEP_FILE"; + if (deptype == "msvc"_s) { + rule.DepType = deptype; + rule.DepFile = ""; + } else { + rule.DepType = ""; // no deps= for multiple outputs + rule.DepFile = "$DEP_FILE"; + } cmRulePlaceholderExpander::RuleVariables scanVars; scanVars.CMTargetName = vars.CMTargetName; @@ -647,6 +705,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); if (needDyndep) { + const auto& scanDepType = this->GetMakefile()->GetSafeDefinition( + cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_SCANDEP_DEPFILE_FORMAT")); + // Rule to scan dependencies of sources that need preprocessing. { std::vector<std::string> scanCommands; @@ -674,10 +735,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, "$DYNDEP_INTERMEDIATE_FILE")); } - auto scanRule = - GetScanRule(scanRuleName, ppFileName, vars, responseFlag, flags, - rulePlaceholderExpander.get(), this->GetLocalGenerator(), - std::move(scanCommands), config); + auto scanRule = GetScanRule( + scanRuleName, ppFileName, scanDepType, vars, responseFlag, flags, + rulePlaceholderExpander.get(), this->GetLocalGenerator(), + std::move(scanCommands), config); scanRule.Comment = cmStrCat("Rule for generating ", lang, " dependencies."); @@ -705,9 +766,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, scanCommands.emplace_back( GetScanCommand(cmakeCmd, tdi, lang, "$in", "$out")); - auto scanRule = GetScanRule( - scanRuleName, "", vars, "", flags, rulePlaceholderExpander.get(), - this->GetLocalGenerator(), std::move(scanCommands), config); + auto scanRule = + GetScanRule(scanRuleName, "", scanDepType, vars, "", flags, + rulePlaceholderExpander.get(), this->GetLocalGenerator(), + std::move(scanCommands), config); // Write the rule for generating dependencies for the given language. scanRule.Comment = cmStrCat("Rule for generating ", lang, @@ -1197,7 +1259,8 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName, scanBuild.Variables["PREPROCESSED_OUTPUT_FILE"] = ppFileName; } - // Scanning always uses a depfile for preprocessor dependencies. + // Scanning always provides a depfile for preprocessor dependencies. This + // variable is unused in `msvc`-deptype scanners. std::string const& depFileName = cmStrCat(scanBuild.Outputs.front(), ".d"); scanBuild.Variables["DEP_FILE"] = lg->ConvertToOutputFormat(depFileName, cmOutputConverter::SHELL); diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index b143170..e62e0cd 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -34,6 +34,7 @@ cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot) assert(this->StateSnapshot.IsValid()); this->ComputeRelativePathTopSource(); this->ComputeRelativePathTopBinary(); + this->ComputeRelativePathTopRelation(); } void cmOutputConverter::ComputeRelativePathTopSource() @@ -69,6 +70,22 @@ void cmOutputConverter::ComputeRelativePathTopBinary() this->RelativePathTopBinary = snapshot.GetDirectory().GetCurrentBinary(); } +void cmOutputConverter::ComputeRelativePathTopRelation() +{ + if (cmSystemTools::ComparePath(this->RelativePathTopSource, + this->RelativePathTopBinary)) { + this->RelativePathTopRelation = TopRelation::InSource; + } else if (cmSystemTools::IsSubDirectory(this->RelativePathTopBinary, + this->RelativePathTopSource)) { + this->RelativePathTopRelation = TopRelation::BinInSrc; + } else if (cmSystemTools::IsSubDirectory(this->RelativePathTopSource, + this->RelativePathTopBinary)) { + this->RelativePathTopRelation = TopRelation::SrcInBin; + } else { + this->RelativePathTopRelation = TopRelation::Separate; + } +} + std::string const& cmOutputConverter::GetRelativePathTopSource() const { return this->RelativePathTopSource; @@ -79,27 +96,45 @@ std::string const& cmOutputConverter::GetRelativePathTopBinary() const return this->RelativePathTopBinary; } -void cmOutputConverter::SetRelativePathTopSource(std::string const& top) -{ - this->RelativePathTopSource = top; -} - -void cmOutputConverter::SetRelativePathTopBinary(std::string const& top) +void cmOutputConverter::SetRelativePathTop(std::string const& topSource, + std::string const& topBinary) { - this->RelativePathTopBinary = top; + this->RelativePathTopSource = topSource; + this->RelativePathTopBinary = topBinary; + this->ComputeRelativePathTopRelation(); } std::string cmOutputConverter::MaybeRelativeTo( std::string const& local_path, std::string const& remote_path) const { - bool bothInBinary = - PathEqOrSubDir(local_path, this->RelativePathTopBinary) && + bool localInBinary = PathEqOrSubDir(local_path, this->RelativePathTopBinary); + bool remoteInBinary = PathEqOrSubDir(remote_path, this->RelativePathTopBinary); - bool bothInSource = - PathEqOrSubDir(local_path, this->RelativePathTopSource) && + bool localInSource = PathEqOrSubDir(local_path, this->RelativePathTopSource); + bool remoteInSource = PathEqOrSubDir(remote_path, this->RelativePathTopSource); + switch (this->RelativePathTopRelation) { + case TopRelation::Separate: + // Checks are independent. + break; + case TopRelation::BinInSrc: + localInSource = localInSource && !localInBinary; + remoteInSource = remoteInSource && !remoteInBinary; + break; + case TopRelation::SrcInBin: + localInBinary = localInBinary && !localInSource; + remoteInBinary = remoteInBinary && !remoteInSource; + break; + case TopRelation::InSource: + // Checks are identical. + break; + }; + + bool const bothInBinary = localInBinary && remoteInBinary; + bool const bothInSource = localInSource && remoteInSource; + if (bothInBinary || bothInSource) { return cmSystemTools::ForceToRelativePath(local_path, remote_path); } diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index 335442d..d19bccc 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -29,8 +29,8 @@ public: std::string const& GetRelativePathTopSource() const; std::string const& GetRelativePathTopBinary() const; - void SetRelativePathTopSource(std::string const& top); - void SetRelativePathTopBinary(std::string const& top); + void SetRelativePathTop(std::string const& topSource, + std::string const& topBinary); enum OutputFormat { @@ -147,8 +147,17 @@ private: // safely by the build tools. std::string RelativePathTopSource; std::string RelativePathTopBinary; + enum class TopRelation + { + Separate, + BinInSrc, + SrcInBin, + InSource, + }; + TopRelation RelativePathTopRelation = TopRelation::Separate; void ComputeRelativePathTopSource(); void ComputeRelativePathTopBinary(); + void ComputeRelativePathTopRelation(); std::string MaybeRelativeTo(std::string const& local_path, std::string const& remote_path) const; }; diff --git a/Source/cmPlaceholderExpander.cxx b/Source/cmPlaceholderExpander.cxx new file mode 100644 index 0000000..118017e --- /dev/null +++ b/Source/cmPlaceholderExpander.cxx @@ -0,0 +1,54 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmPlaceholderExpander.h" + +#include <cctype> + +std::string& cmPlaceholderExpander::ExpandVariables(std::string& s) +{ + std::string::size_type start = s.find('<'); + // no variables to expand + if (start == std::string::npos) { + return s; + } + std::string::size_type pos = 0; + std::string expandedInput; + while (start != std::string::npos && start < s.size() - 2) { + std::string::size_type end = s.find('>', start); + // if we find a < with no > we are done + if (end == std::string::npos) { + s = expandedInput; + return s; + } + char c = s[start + 1]; + // if the next char after the < is not A-Za-z then + // skip it and try to find the next < in the string + if (!isalpha(c)) { + start = s.find('<', start + 1); + } else { + // extract the var + std::string var = s.substr(start + 1, end - start - 1); + std::string replace = this->ExpandVariable(var); + expandedInput += s.substr(pos, start - pos); + + // Prevent consecutive whitespace in the output if the rule variable + // expands to an empty string. + bool consecutive = replace.empty() && start > 0 && s[start - 1] == ' ' && + end + 1 < s.size() && s[end + 1] == ' '; + if (consecutive) { + expandedInput.pop_back(); + } + + expandedInput += replace; + + // move to next one + start = s.find('<', start + var.size() + 2); + pos = end + 1; + } + } + // add the rest of the input + expandedInput += s.substr(pos, s.size() - pos); + s = expandedInput; + + return s; +} diff --git a/Source/cmPlaceholderExpander.h b/Source/cmPlaceholderExpander.h new file mode 100644 index 0000000..24225cc --- /dev/null +++ b/Source/cmPlaceholderExpander.h @@ -0,0 +1,19 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <string> + +class cmPlaceholderExpander +{ +public: + virtual ~cmPlaceholderExpander() = default; + + std::string& ExpandVariables(std::string& string); + +protected: + virtual std::string ExpandVariable(std::string const& variable) = 0; +}; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 99e2eb6..c8b037e 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -388,6 +388,32 @@ class cmMakefile; 22, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0129, \ "Compiler id for MCST LCC compilers is now LCC, not GNU.", 3, 23, 0, \ + cmPolicies::WARN) \ + SELECT(POLICY, CMP0130, "while() diagnoses condition evaluation errors.", \ + 3, 24, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0131, \ + "LINK_LIBRARIES supports the LINK_ONLY generator expression.", 3, \ + 24, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0132, \ + "Do not set compiler environment variables on first run", 3, 24, 0, \ + cmPolicies::WARN) \ + SELECT(POLICY, CMP0133, \ + "The CPack module disables SLA by default in the CPack DragNDrop " \ + "Generator.", \ + 3, 24, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0134, \ + "Fallback to \"HOST\" Windows registry view when \"TARGET\" view " \ + "is not usable.", \ + 3, 24, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0135, \ + "ExternalProject ignores timestamps in archives by default for the " \ + "URL download method", \ + 3, 24, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0136, \ + "Watcom runtime library flags are selected by an abstraction.", 3, \ + 24, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0137, \ + "try_compile() passes platform variables in project mode", 3, 24, 0, \ cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) @@ -424,7 +450,8 @@ class cmMakefile; F(CMP0108) \ F(CMP0112) \ F(CMP0113) \ - F(CMP0119) + F(CMP0119) \ + F(CMP0131) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 0a394b5..adbdba8 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -76,6 +76,13 @@ static void MergeOptions(std::vector<std::string>& baseOpts, unsigned int const cmQtAutoGen::ParallelMax = 64; +#ifdef _WIN32 +// Actually 32767 (see +// https://devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553) but we +// allow for a small margin +size_t const cmQtAutoGen::CommandLineLengthMax = 32000; +#endif + cm::string_view cmQtAutoGen::GeneratorName(GenT genType) { switch (genType) { diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index 5a23ae9..d111422 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -64,6 +64,11 @@ public: /// @brief Maximum number of parallel threads/processes in a generator static unsigned int const ParallelMax; +#ifdef _WIN32 + /// @brief Maximum number of characters on command line + static size_t const CommandLineLengthMax; +#endif + /// @brief Returns the generator name static cm::string_view GeneratorName(GenT genType); /// @brief Returns the generator name in upper case diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index a01e6ae..a47b3c0 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -114,7 +114,8 @@ bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin, } // Collect all static_library dependencies from the test target cmLinkImplementationLibraries const* libs = - testTarget->GetLinkImplementationLibraries(config); + testTarget->GetLinkImplementationLibraries( + config, cmGeneratorTarget::LinkInterfaceFor::Link); if (libs) { for (cmLinkItem const& item : libs->Libraries) { cmGeneratorTarget const* depTarget = item.Target; @@ -1266,7 +1267,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() std::map<cmGeneratorTarget const*, std::size_t> commonTargets; for (std::string const& config : this->ConfigsList) { cmLinkImplementationLibraries const* libs = - this->GenTarget->GetLinkImplementationLibraries(config); + this->GenTarget->GetLinkImplementationLibraries( + config, cmGeneratorTarget::LinkInterfaceFor::Link); if (libs) { for (cmLinkItem const& item : libs->Libraries) { cmGeneratorTarget const* libTarget = item.Target; diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 4ed728e..0d38dfb 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -497,6 +497,10 @@ public: protected: ParseCacheT::FileHandleT CacheEntry; + + private: + void MaybeWriteMocResponseFile(std::string const& outputFile, + std::vector<std::string>& cmd) const; }; /** uic compiles a file. */ @@ -2025,6 +2029,8 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() cmd.push_back(outputFile); // Add source file cmd.push_back(sourceFile); + + MaybeWriteMocResponseFile(outputFile, cmd); } // Execute moc command @@ -2070,6 +2076,51 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() } } +/* + * Check if command line exceeds maximum length supported by OS + * (if on Windows) and switch to using a response file instead. + */ +void cmQtAutoMocUicT::JobCompileMocT::MaybeWriteMocResponseFile( + std::string const& outputFile, std::vector<std::string>& cmd) const +{ +#ifdef _WIN32 + // Ensure cmd is less than CommandLineLengthMax characters + size_t commandLineLength = cmd.size(); // account for separating spaces + for (std::string const& str : cmd) { + commandLineLength += str.length(); + } + if (commandLineLength >= CommandLineLengthMax) { + // Command line exceeds maximum size allowed by OS + // => create response file + std::string const responseFile = cmStrCat(outputFile, ".rsp"); + + cmsys::ofstream fout(responseFile.c_str()); + if (!fout) { + this->LogError( + GenT::MOC, + cmStrCat("AUTOMOC was unable to create a response file at\n ", + this->MessagePath(responseFile))); + return; + } + + auto it = cmd.begin(); + while (++it != cmd.end()) { + fout << *it << "\n"; + } + fout.close(); + + // Keep all but executable + cmd.resize(1); + + // Specify response file + cmd.push_back(cmStrCat('@', responseFile)); + } +#else + static_cast<void>(outputFile); + static_cast<void>(cmd); +#endif +} + void cmQtAutoMocUicT::JobCompileUicT::Process() { std::string const& sourceFile = this->Mapping->SourceFile->FileName; diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx index 4cee09d..b63d11c 100644 --- a/Source/cmRulePlaceholderExpander.cxx +++ b/Source/cmRulePlaceholderExpander.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmRulePlaceholderExpander.h" -#include <cctype> #include <utility> #include "cmOutputConverter.h" @@ -20,195 +19,194 @@ cmRulePlaceholderExpander::cmRulePlaceholderExpander( { } -std::string cmRulePlaceholderExpander::ExpandRuleVariable( - cmOutputConverter* outputConverter, std::string const& variable, - const RuleVariables& replaceValues) +std::string cmRulePlaceholderExpander::ExpandVariable( + std::string const& variable) { - if (replaceValues.LinkFlags) { + if (this->ReplaceValues->LinkFlags) { if (variable == "LINK_FLAGS") { - return replaceValues.LinkFlags; + return this->ReplaceValues->LinkFlags; } } - if (replaceValues.Manifests) { + if (this->ReplaceValues->Manifests) { if (variable == "MANIFESTS") { - return replaceValues.Manifests; + return this->ReplaceValues->Manifests; } } - if (replaceValues.Flags) { + if (this->ReplaceValues->Flags) { if (variable == "FLAGS") { - return replaceValues.Flags; + return this->ReplaceValues->Flags; } } - if (replaceValues.Source) { + if (this->ReplaceValues->Source) { if (variable == "SOURCE") { - return replaceValues.Source; + return this->ReplaceValues->Source; } } - if (replaceValues.DynDepFile) { + if (this->ReplaceValues->DynDepFile) { if (variable == "DYNDEP_FILE") { - return replaceValues.DynDepFile; + return this->ReplaceValues->DynDepFile; } } - if (replaceValues.PreprocessedSource) { + if (this->ReplaceValues->PreprocessedSource) { if (variable == "PREPROCESSED_SOURCE") { - return replaceValues.PreprocessedSource; + return this->ReplaceValues->PreprocessedSource; } } - if (replaceValues.AssemblySource) { + if (this->ReplaceValues->AssemblySource) { if (variable == "ASSEMBLY_SOURCE") { - return replaceValues.AssemblySource; + return this->ReplaceValues->AssemblySource; } } - if (replaceValues.Object) { + if (this->ReplaceValues->Object) { if (variable == "OBJECT") { - return replaceValues.Object; + return this->ReplaceValues->Object; } } - if (replaceValues.ObjectDir) { + if (this->ReplaceValues->ObjectDir) { if (variable == "OBJECT_DIR") { - return replaceValues.ObjectDir; + return this->ReplaceValues->ObjectDir; } } - if (replaceValues.ObjectFileDir) { + if (this->ReplaceValues->ObjectFileDir) { if (variable == "OBJECT_FILE_DIR") { - return replaceValues.ObjectFileDir; + return this->ReplaceValues->ObjectFileDir; } } - if (replaceValues.Objects) { + if (this->ReplaceValues->Objects) { if (variable == "OBJECTS") { - return replaceValues.Objects; + return this->ReplaceValues->Objects; } } - if (replaceValues.ObjectsQuoted) { + if (this->ReplaceValues->ObjectsQuoted) { if (variable == "OBJECTS_QUOTED") { - return replaceValues.ObjectsQuoted; + return this->ReplaceValues->ObjectsQuoted; } } - if (replaceValues.CudaCompileMode) { + if (this->ReplaceValues->CudaCompileMode) { if (variable == "CUDA_COMPILE_MODE") { - return replaceValues.CudaCompileMode; + return this->ReplaceValues->CudaCompileMode; } } - if (replaceValues.AIXExports) { + if (this->ReplaceValues->AIXExports) { if (variable == "AIX_EXPORTS") { - return replaceValues.AIXExports; + return this->ReplaceValues->AIXExports; } } - if (replaceValues.ISPCHeader) { + if (this->ReplaceValues->ISPCHeader) { if (variable == "ISPC_HEADER") { - return replaceValues.ISPCHeader; + return this->ReplaceValues->ISPCHeader; } } - if (replaceValues.Defines && variable == "DEFINES") { - return replaceValues.Defines; + if (this->ReplaceValues->Defines && variable == "DEFINES") { + return this->ReplaceValues->Defines; } - if (replaceValues.Includes && variable == "INCLUDES") { - return replaceValues.Includes; + if (this->ReplaceValues->Includes && variable == "INCLUDES") { + return this->ReplaceValues->Includes; } - if (replaceValues.SwiftLibraryName) { + if (this->ReplaceValues->SwiftLibraryName) { if (variable == "SWIFT_LIBRARY_NAME") { - return replaceValues.SwiftLibraryName; + return this->ReplaceValues->SwiftLibraryName; } } - if (replaceValues.SwiftModule) { + if (this->ReplaceValues->SwiftModule) { if (variable == "SWIFT_MODULE") { - return replaceValues.SwiftModule; + return this->ReplaceValues->SwiftModule; } } - if (replaceValues.SwiftModuleName) { + if (this->ReplaceValues->SwiftModuleName) { if (variable == "SWIFT_MODULE_NAME") { - return replaceValues.SwiftModuleName; + return this->ReplaceValues->SwiftModuleName; } } - if (replaceValues.SwiftOutputFileMap) { + if (this->ReplaceValues->SwiftOutputFileMap) { if (variable == "SWIFT_OUTPUT_FILE_MAP") { - return replaceValues.SwiftOutputFileMap; + return this->ReplaceValues->SwiftOutputFileMap; } } - if (replaceValues.SwiftSources) { + if (this->ReplaceValues->SwiftSources) { if (variable == "SWIFT_SOURCES") { - return replaceValues.SwiftSources; + return this->ReplaceValues->SwiftSources; } } - if (replaceValues.TargetPDB) { + if (this->ReplaceValues->TargetPDB) { if (variable == "TARGET_PDB") { - return replaceValues.TargetPDB; + return this->ReplaceValues->TargetPDB; } } - if (replaceValues.TargetCompilePDB) { + if (this->ReplaceValues->TargetCompilePDB) { if (variable == "TARGET_COMPILE_PDB") { - return replaceValues.TargetCompilePDB; + return this->ReplaceValues->TargetCompilePDB; } } - if (replaceValues.DependencyFile) { + if (this->ReplaceValues->DependencyFile) { if (variable == "DEP_FILE") { - return replaceValues.DependencyFile; + return this->ReplaceValues->DependencyFile; } } - if (replaceValues.DependencyTarget) { + if (this->ReplaceValues->DependencyTarget) { if (variable == "DEP_TARGET") { - return replaceValues.DependencyTarget; + return this->ReplaceValues->DependencyTarget; } } - if (replaceValues.Fatbinary) { + if (this->ReplaceValues->Fatbinary) { if (variable == "FATBINARY") { - return replaceValues.Fatbinary; + return this->ReplaceValues->Fatbinary; } } - if (replaceValues.RegisterFile) { + if (this->ReplaceValues->RegisterFile) { if (variable == "REGISTER_FILE") { - return replaceValues.RegisterFile; + return this->ReplaceValues->RegisterFile; } } - if (replaceValues.Target) { + if (this->ReplaceValues->Target) { if (variable == "TARGET_QUOTED") { - std::string targetQuoted = replaceValues.Target; + std::string targetQuoted = this->ReplaceValues->Target; if (!targetQuoted.empty() && targetQuoted.front() != '\"') { targetQuoted = '\"'; - targetQuoted += replaceValues.Target; + targetQuoted += this->ReplaceValues->Target; targetQuoted += '\"'; } return targetQuoted; } if (variable == "TARGET_UNQUOTED") { - std::string unquoted = replaceValues.Target; + std::string unquoted = this->ReplaceValues->Target; std::string::size_type sz = unquoted.size(); if (sz > 2 && unquoted.front() == '\"' && unquoted.back() == '\"') { unquoted = unquoted.substr(1, sz - 2); } return unquoted; } - if (replaceValues.LanguageCompileFlags) { + if (this->ReplaceValues->LanguageCompileFlags) { if (variable == "LANGUAGE_COMPILE_FLAGS") { - return replaceValues.LanguageCompileFlags; + return this->ReplaceValues->LanguageCompileFlags; } } - if (replaceValues.Target) { + if (this->ReplaceValues->Target) { if (variable == "TARGET") { - return replaceValues.Target; + return this->ReplaceValues->Target; } } if (variable == "TARGET_IMPLIB") { return this->TargetImpLib; } if (variable == "TARGET_VERSION_MAJOR") { - if (replaceValues.TargetVersionMajor) { - return replaceValues.TargetVersionMajor; + if (this->ReplaceValues->TargetVersionMajor) { + return this->ReplaceValues->TargetVersionMajor; } return "0"; } if (variable == "TARGET_VERSION_MINOR") { - if (replaceValues.TargetVersionMinor) { - return replaceValues.TargetVersionMinor; + if (this->ReplaceValues->TargetVersionMinor) { + return this->ReplaceValues->TargetVersionMinor; } return "0"; } - if (replaceValues.Target) { + if (this->ReplaceValues->Target) { if (variable == "TARGET_BASE") { // Strip the last extension off the target name. - std::string targetBase = replaceValues.Target; + std::string targetBase = this->ReplaceValues->Target; std::string::size_type pos = targetBase.rfind('.'); if (pos != std::string::npos) { return targetBase.substr(0, pos); @@ -220,54 +218,54 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( if (variable == "TARGET_SONAME" || variable == "SONAME_FLAG" || variable == "TARGET_INSTALLNAME_DIR") { // All these variables depend on TargetSOName - if (replaceValues.TargetSOName) { + if (this->ReplaceValues->TargetSOName) { if (variable == "TARGET_SONAME") { - return replaceValues.TargetSOName; + return this->ReplaceValues->TargetSOName; } - if (variable == "SONAME_FLAG" && replaceValues.SONameFlag) { - return replaceValues.SONameFlag; + if (variable == "SONAME_FLAG" && this->ReplaceValues->SONameFlag) { + return this->ReplaceValues->SONameFlag; } - if (replaceValues.TargetInstallNameDir && + if (this->ReplaceValues->TargetInstallNameDir && variable == "TARGET_INSTALLNAME_DIR") { - return replaceValues.TargetInstallNameDir; + return this->ReplaceValues->TargetInstallNameDir; } } return ""; } - if (replaceValues.LinkLibraries) { + if (this->ReplaceValues->LinkLibraries) { if (variable == "LINK_LIBRARIES") { - return replaceValues.LinkLibraries; + return this->ReplaceValues->LinkLibraries; } } - if (replaceValues.Language) { + if (this->ReplaceValues->Language) { if (variable == "LANGUAGE") { - return replaceValues.Language; + return this->ReplaceValues->Language; } } - if (replaceValues.CMTargetName) { + if (this->ReplaceValues->CMTargetName) { if (variable == "TARGET_NAME") { - return replaceValues.CMTargetName; + return this->ReplaceValues->CMTargetName; } } - if (replaceValues.CMTargetType) { + if (this->ReplaceValues->CMTargetType) { if (variable == "TARGET_TYPE") { - return replaceValues.CMTargetType; + return this->ReplaceValues->CMTargetType; } } - if (replaceValues.Output) { + if (this->ReplaceValues->Output) { if (variable == "OUTPUT") { - return replaceValues.Output; + return this->ReplaceValues->Output; } } if (variable == "CMAKE_COMMAND") { - return outputConverter->ConvertToOutputFormat( + return this->OutputConverter->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); } auto compIt = this->Compilers.find(variable); if (compIt != this->Compilers.end()) { - std::string ret = outputConverter->ConvertToOutputForExisting( + std::string ret = this->OutputConverter->ConvertToOutputForExisting( this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER"]); std::string const& compilerArg1 = this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER_ARG1"]; @@ -286,11 +284,12 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( this->VariableMappings["CMAKE_" + compIt->second + "_COMPILE_OPTIONS_SYSROOT"]; - if (compIt->second == replaceValues.Language && replaceValues.Launcher) { + if (compIt->second == this->ReplaceValues->Language && + this->ReplaceValues->Launcher) { // Add launcher as part of expansion so that it always appears // immediately before the command itself, regardless of whether the // overall rule template contains other content at the front. - ret = cmStrCat(replaceValues.Launcher, " ", ret); + ret = cmStrCat(this->ReplaceValues->Launcher, " ", ret); } // if there are required arguments to the compiler add it @@ -308,13 +307,14 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( !compilerOptionExternalToolchain.empty()) { ret += " "; ret += compilerOptionExternalToolchain; - ret += outputConverter->EscapeForShell(compilerExternalToolchain, true); + ret += + this->OutputConverter->EscapeForShell(compilerExternalToolchain, true); } std::string sysroot; // Some platforms may use separate sysroots for compiling and linking. // If we detect link flags, then we pass the link sysroot instead. // FIXME: Use a more robust way to detect link line expansion. - if (replaceValues.LinkFlags) { + if (this->ReplaceValues->LinkFlags) { sysroot = this->LinkerSysroot; } else { sysroot = this->CompilerSysroot; @@ -322,7 +322,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( if (!sysroot.empty() && !compilerOptionSysroot.empty()) { ret += " "; ret += compilerOptionSysroot; - ret += outputConverter->EscapeForShell(sysroot, true); + ret += this->OutputConverter->EscapeForShell(sysroot, true); } return ret; } @@ -331,13 +331,13 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( if (mapIt != this->VariableMappings.end()) { if (variable.find("_FLAG") == std::string::npos) { std::string ret = - outputConverter->ConvertToOutputForExisting(mapIt->second); + this->OutputConverter->ConvertToOutputForExisting(mapIt->second); - if (replaceValues.Launcher && variable == "CMAKE_LINKER") { + if (this->ReplaceValues->Launcher && variable == "CMAKE_LINKER") { // Add launcher as part of expansion so that it always appears // immediately before the command itself, regardless of whether the // overall rule template contains other content at the front. - ret = cmStrCat(replaceValues.Launcher, " ", ret); + ret = cmStrCat(this->ReplaceValues->Launcher, " ", ret); } return ret; @@ -351,47 +351,8 @@ void cmRulePlaceholderExpander::ExpandRuleVariables( cmOutputConverter* outputConverter, std::string& s, const RuleVariables& replaceValues) { - std::string::size_type start = s.find('<'); - // no variables to expand - if (start == std::string::npos) { - return; - } - std::string::size_type pos = 0; - std::string expandedInput; - while (start != std::string::npos && start < s.size() - 2) { - std::string::size_type end = s.find('>', start); - // if we find a < with no > we are done - if (end == std::string::npos) { - return; - } - char c = s[start + 1]; - // if the next char after the < is not A-Za-z then - // skip it and try to find the next < in the string - if (!isalpha(c)) { - start = s.find('<', start + 1); - } else { - // extract the var - std::string var = s.substr(start + 1, end - start - 1); - std::string replace = - this->ExpandRuleVariable(outputConverter, var, replaceValues); - expandedInput += s.substr(pos, start - pos); - - // Prevent consecutive whitespace in the output if the rule variable - // expands to an empty string. - bool consecutive = replace.empty() && start > 0 && s[start - 1] == ' ' && - end + 1 < s.size() && s[end + 1] == ' '; - if (consecutive) { - expandedInput.pop_back(); - } + this->OutputConverter = outputConverter; + this->ReplaceValues = &replaceValues; - expandedInput += replace; - - // move to next one - start = s.find('<', start + var.size() + 2); - pos = end + 1; - } - } - // add the rest of the input - expandedInput += s.substr(pos, s.size() - pos); - s = expandedInput; + this->ExpandVariables(s); } diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h index 852954f..23ec405 100644 --- a/Source/cmRulePlaceholderExpander.h +++ b/Source/cmRulePlaceholderExpander.h @@ -8,9 +8,11 @@ #include <map> #include <string> +#include "cmPlaceholderExpander.h" + class cmOutputConverter; -class cmRulePlaceholderExpander +class cmRulePlaceholderExpander : public cmPlaceholderExpander { public: cmRulePlaceholderExpander( @@ -76,16 +78,16 @@ public: std::string& string, const RuleVariables& replaceValues); - // Expand rule variables in a single string - std::string ExpandRuleVariable(cmOutputConverter* outputConverter, - std::string const& variable, - const RuleVariables& replaceValues); - private: + std::string ExpandVariable(std::string const& variable) override; + std::string TargetImpLib; std::map<std::string, std::string> Compilers; std::map<std::string, std::string> VariableMappings; std::string CompilerSysroot; std::string LinkerSysroot; + + cmOutputConverter* OutputConverter = nullptr; + RuleVariables const* ReplaceValues = nullptr; }; diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx index 5ac7be9..437b938 100644 --- a/Source/cmScriptGenerator.cxx +++ b/Source/cmScriptGenerator.cxx @@ -52,8 +52,7 @@ static void cmScriptGeneratorEncodeConfig(const std::string& config, std::string cmScriptGenerator::CreateConfigTest(const std::string& config) { - std::string result = - cmStrCat("\"${", this->RuntimeConfigVariable, "}\" MATCHES \"^("); + std::string result = cmStrCat(this->RuntimeConfigVariable, " MATCHES \"^("); if (!config.empty()) { cmScriptGeneratorEncodeConfig(config, result); } @@ -64,8 +63,7 @@ std::string cmScriptGenerator::CreateConfigTest(const std::string& config) std::string cmScriptGenerator::CreateConfigTest( std::vector<std::string> const& configs) { - std::string result = - cmStrCat("\"${", this->RuntimeConfigVariable, "}\" MATCHES \"^("); + std::string result = cmStrCat(this->RuntimeConfigVariable, " MATCHES \"^("); const char* sep = ""; for (std::string const& config : configs) { result += sep; diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index bfee64c..6c53b85 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -6,11 +6,14 @@ #include <cassert> #include <utility> +#include <cm/optional> + #include "cmFindCommon.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" +#include "cmWindowsRegistry.h" cmSearchPath::cmSearchPath(cmFindCommon* findCmd) : FC(findCmd) @@ -46,26 +49,13 @@ void cmSearchPath::AddUserPath(const std::string& path) std::vector<std::string> outPaths; - // We should view the registry as the target application would view - // it. - cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32; - cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64; - if (this->FC->Makefile->PlatformIs64Bit()) { - view = cmSystemTools::KeyWOW64_64; - other_view = cmSystemTools::KeyWOW64_32; - } - - // Expand using the view of the target application. - std::string expanded = path; - cmSystemTools::ExpandRegistryValues(expanded, view); - cmSystemTools::GlobDirs(expanded, outPaths); - - // Executables can be either 32-bit or 64-bit, so expand using the - // alternative view. - if (expanded != path && this->FC->CMakePathName == "PROGRAM") { - expanded = path; - cmSystemTools::ExpandRegistryValues(expanded, other_view); - cmSystemTools::GlobDirs(expanded, outPaths); + cmWindowsRegistry registry(*this->FC->Makefile, + cmWindowsRegistry::SimpleTypes); + auto expandedPaths = registry.ExpandExpression(path, this->FC->RegistryView); + if (expandedPaths) { + for (const auto& expandedPath : expandedPaths.value()) { + cmSystemTools::GlobDirs(expandedPath, outPaths); + } } // Process them all from the current directory diff --git a/Source/cmState.h b/Source/cmState.h index 4f2b7df..ee133fc 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -14,7 +14,6 @@ #include "cmDefinitions.h" #include "cmLinkedTree.h" -#include "cmListFileCache.h" #include "cmPolicies.h" #include "cmProperty.h" #include "cmPropertyDefinition.h" @@ -30,6 +29,11 @@ class cmMakefile; class cmStateSnapshot; class cmMessenger; class cmExecutionStatus; +class cmListFileBacktrace; +struct cmListFileArgument; + +template <typename T> +class BT; class cmState { diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index b42e5c3..20e4604 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -13,6 +13,7 @@ #include <cmext/string_view> #include "cmAlgorithms.h" +#include "cmListFileCache.h" #include "cmProperty.h" #include "cmPropertyMap.h" #include "cmRange.h" diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index 6429f32..8c6b09d 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -10,11 +10,14 @@ #include "cmAlgorithms.h" #include "cmLinkedTree.h" -#include "cmListFileCache.h" #include "cmStatePrivate.h" #include "cmStateSnapshot.h" #include "cmValue.h" +class cmListFileBacktrace; +template <typename T> +class BT; + class cmStateDirectory { cmStateDirectory( diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index e5935b8..c3ee695 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -55,7 +55,6 @@ bool joinImpl(std::vector<std::string> const& args, std::string const& glue, bool HandleHashCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { -#if !defined(CMAKE_BOOTSTRAP) if (args.size() != 3) { status.SetError( cmStrCat(args[0], " requires an output variable and an input string")); @@ -69,10 +68,6 @@ bool HandleHashCommand(std::vector<std::string> const& args, return true; } return false; -#else - status.SetError(cmStrCat(args[0], " not available during bootstrap")); - return false; -#endif } bool HandleToUpperLowerCommand(std::vector<std::string> const& args, @@ -1106,8 +1101,8 @@ bool HandleJSONCommand(std::vector<std::string> const& arguments, mode != "EQUAL"_s) { throw json_error( { "got an invalid mode '"_s, mode, - "', expected one of GET, GET_ARRAY, TYPE, MEMBER, MEMBERS," - " LENGTH, REMOVE, SET, EQUAL"_s }); + "', expected one of GET, TYPE, MEMBER, LENGTH, REMOVE, SET, " + " EQUAL"_s }); } const auto& jsonstr = args.PopFront("missing json string argument"_s); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index effb837..527175d 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1821,6 +1821,7 @@ bool copy_data(struct archive* ar, struct archive* aw) bool extract_tar(const std::string& outFileName, const std::vector<std::string>& files, bool verbose, + cmSystemTools::cmTarExtractTimestamps extractTimestamps, bool extract) { cmLocaleRAII localeRAII; @@ -1879,10 +1880,12 @@ bool extract_tar(const std::string& outFileName, cmSystemTools::Stdout("\n"); } if (extract) { - r = archive_write_disk_set_options(ext, ARCHIVE_EXTRACT_TIME); - if (r != ARCHIVE_OK) { - ArchiveError("Problem with archive_write_disk_set_options(): ", ext); - break; + if (extractTimestamps == cmSystemTools::cmTarExtractTimestamps::Yes) { + r = archive_write_disk_set_options(ext, ARCHIVE_EXTRACT_TIME); + if (r != ARCHIVE_OK) { + ArchiveError("Problem with archive_write_disk_set_options(): ", ext); + break; + } } r = archive_write_header(ext, entry); @@ -1942,13 +1945,15 @@ bool extract_tar(const std::string& outFileName, bool cmSystemTools::ExtractTar(const std::string& outFileName, const std::vector<std::string>& files, + cmTarExtractTimestamps extractTimestamps, bool verbose) { #if !defined(CMAKE_BOOTSTRAP) - return extract_tar(outFileName, files, verbose, true); + return extract_tar(outFileName, files, verbose, extractTimestamps, true); #else (void)outFileName; (void)files; + (void)extractTimestamps; (void)verbose; return false; #endif @@ -1959,7 +1964,8 @@ bool cmSystemTools::ListTar(const std::string& outFileName, bool verbose) { #if !defined(CMAKE_BOOTSTRAP) - return extract_tar(outFileName, files, verbose, false); + return extract_tar(outFileName, files, verbose, cmTarExtractTimestamps::Yes, + false); #else (void)outFileName; (void)files; @@ -3314,12 +3320,22 @@ cmsys::Status cmSystemTools::CreateSymlink(std::string const& origName, uv_fs_t req; int flags = 0; #if defined(_WIN32) - if (cmsys::SystemTools::FileIsDirectory(origName)) { - flags |= UV_FS_SYMLINK_DIR; + bool const isDir = cmsys::SystemTools::FileIsDirectory(origName); + if (isDir) { + flags |= UV_FS_SYMLINK_JUNCTION; } #endif int err = uv_fs_symlink(nullptr, &req, origName.c_str(), newName.c_str(), flags, nullptr); +#if defined(_WIN32) + if (err && uv_fs_get_system_error(&req) == ERROR_NOT_SUPPORTED && isDir) { + // Try fallback to symlink for network (requires additional permissions). + flags ^= UV_FS_SYMLINK_JUNCTION | UV_FS_SYMLINK_DIR; + err = uv_fs_symlink(nullptr, &req, origName.c_str(), newName.c_str(), + flags, nullptr); + } +#endif + cmsys::Status status; if (err) { #if defined(_WIN32) @@ -3413,3 +3429,12 @@ cm::string_view cmSystemTools::GetSystemName() return ""; #endif } + +char cmSystemTools::GetSystemPathlistSeparator() +{ +#if defined(_WIN32) + return ';'; +#else + return ':'; +#endif +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 19dabe8..4865a4b 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -417,6 +417,12 @@ public: TarCompressNone }; + enum class cmTarExtractTimestamps + { + Yes, + No + }; + static bool ListTar(const std::string& outFileName, const std::vector<std::string>& files, bool verbose); static bool CreateTar(const std::string& outFileName, @@ -426,7 +432,9 @@ public: std::string const& format = std::string(), int compressionLevel = 0); static bool ExtractTar(const std::string& inFileName, - const std::vector<std::string>& files, bool verbose); + const std::vector<std::string>& files, + cmTarExtractTimestamps extractTimestamps, + bool verbose); // This should be called first thing in main // it will keep child processes from inheriting the // stdin and stdout of this process. This is important @@ -527,6 +535,9 @@ public: /** Get the system name. */ static cm::string_view GetSystemName(); + /** Get the system path separator character */ + static char GetSystemPathlistSeparator(); + private: static bool s_ForceUnixPaths; static bool s_RunCommandHideConsole; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 57e31b9..80d1940 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -13,6 +13,7 @@ #include <unordered_set> #include <cm/memory> +#include <cm/string_view> #include <cmext/algorithm> #include <cmext/string_view> @@ -164,6 +165,66 @@ cmValue cmTargetPropertyComputer::GetSources<cmTarget>(cmTarget const* tgt, return cmValue(srcs); } +namespace { +struct FileSetEntries +{ + FileSetEntries(cm::static_string_view propertyName) + : PropertyName(propertyName) + { + } + + cm::static_string_view const PropertyName; + std::vector<BT<std::string>> Entries; +}; + +struct FileSetType +{ + FileSetType(cm::static_string_view typeName, + cm::static_string_view defaultDirectoryProperty, + cm::static_string_view defaultPathProperty, + cm::static_string_view directoryPrefix, + cm::static_string_view pathPrefix, + cm::static_string_view typeDescription, + cm::static_string_view defaultDescription, + cm::static_string_view arbitraryDescription, + FileSetEntries selfEntries, FileSetEntries interfaceEntries) + : TypeName(typeName) + , DefaultDirectoryProperty(defaultDirectoryProperty) + , DefaultPathProperty(defaultPathProperty) + , DirectoryPrefix(directoryPrefix) + , PathPrefix(pathPrefix) + , TypeDescription(typeDescription) + , DefaultDescription(defaultDescription) + , ArbitraryDescription(arbitraryDescription) + , SelfEntries(std::move(selfEntries)) + , InterfaceEntries(std::move(interfaceEntries)) + { + } + + cm::static_string_view const TypeName; + cm::static_string_view const DefaultDirectoryProperty; + cm::static_string_view const DefaultPathProperty; + cm::static_string_view const DirectoryPrefix; + cm::static_string_view const PathPrefix; + cm::static_string_view const TypeDescription; + cm::static_string_view const DefaultDescription; + cm::static_string_view const ArbitraryDescription; + + FileSetEntries SelfEntries; + FileSetEntries InterfaceEntries; + + template <typename ValueType> + bool WriteProperties(cmTarget* tgt, cmTargetInternals* impl, + const std::string& prop, ValueType value, bool clear); + std::pair<bool, cmValue> ReadProperties(cmTarget const* tgt, + cmTargetInternals const* impl, + const std::string& prop) const; + + void AddFileSet(const std::string& name, cmFileSetVisibility vis, + cmListFileBacktrace bt); +}; +} + class cmTargetInternals { public: @@ -203,19 +264,154 @@ public: std::vector<BT<std::string>> LinkDirectoriesEntries; std::vector<BT<std::string>> LinkImplementationPropertyEntries; std::vector<BT<std::string>> LinkInterfacePropertyEntries; - std::vector<BT<std::string>> HeaderSetsEntries; - std::vector<BT<std::string>> InterfaceHeaderSetsEntries; + std::vector<BT<std::string>> LinkInterfaceDirectPropertyEntries; + std::vector<BT<std::string>> LinkInterfaceDirectExcludePropertyEntries; std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>> TLLCommands; std::map<std::string, cmFileSet> FileSets; cmListFileBacktrace Backtrace; + FileSetType HeadersFileSets; + + cmTargetInternals(); + bool CheckImportedLibName(std::string const& prop, std::string const& value) const; std::string ProcessSourceItemCMP0049(const std::string& s) const; + + template <typename ValueType> + void AddDirectoryToFileSet(cmTarget* self, std::string const& fileSetName, + ValueType value, cm::string_view fileSetType, + cm::string_view description, bool clear); + template <typename ValueType> + void AddPathToFileSet(cmTarget* self, std::string const& fileSetName, + ValueType value, cm::string_view fileSetType, + cm::string_view description, bool clear); + cmValue GetFileSetDirectories(cmTarget const* self, + std::string const& fileSetName, + cm::string_view fileSetType) const; + cmValue GetFileSetPaths(cmTarget const* self, std::string const& fileSetName, + cm::string_view fileSetType) const; }; +cmTargetInternals::cmTargetInternals() + : HeadersFileSets("HEADERS"_s, "HEADER_DIRS"_s, "HEADER_SET"_s, + "HEADER_DIRS_"_s, "HEADER_SET_"_s, "Header"_s, + "The default header set"_s, "Header set"_s, + FileSetEntries("HEADER_SETS"_s), + FileSetEntries("INTERFACE_HEADER_SETS"_s)) +{ +} + +template <typename ValueType> +bool FileSetType::WriteProperties(cmTarget* tgt, cmTargetInternals* impl, + const std::string& prop, ValueType value, + bool clear) +{ + if (prop == this->DefaultDirectoryProperty) { + impl->AddDirectoryToFileSet(tgt, std::string(this->TypeName), value, + this->TypeName, this->DefaultDescription, + clear); + return true; + } + if (prop == this->DefaultPathProperty) { + impl->AddPathToFileSet(tgt, std::string(this->TypeName), value, + this->TypeName, this->DefaultDescription, clear); + return true; + } + if (cmHasPrefix(prop, this->DirectoryPrefix)) { + auto fileSetName = prop.substr(this->DirectoryPrefix.size()); + if (fileSetName.empty()) { + impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(this->ArbitraryDescription, " name cannot be empty.")); + } else { + impl->AddDirectoryToFileSet( + tgt, fileSetName, value, this->TypeName, + cmStrCat(this->ArbitraryDescription, " \"", fileSetName, "\""), clear); + } + return true; + } + if (cmHasPrefix(prop, this->PathPrefix)) { + auto fileSetName = prop.substr(this->PathPrefix.size()); + if (fileSetName.empty()) { + impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(this->ArbitraryDescription, " name cannot be empty.")); + } else { + impl->AddPathToFileSet( + tgt, fileSetName, value, this->TypeName, + cmStrCat(this->ArbitraryDescription, " \"", fileSetName, "\""), clear); + } + return true; + } + if (prop == this->SelfEntries.PropertyName) { + impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(this->SelfEntries.PropertyName, " property is read-only\n")); + return true; + } + if (prop == this->InterfaceEntries.PropertyName) { + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat(this->InterfaceEntries.PropertyName, + " property is read-only\n")); + return true; + } + return false; +} + +std::pair<bool, cmValue> FileSetType::ReadProperties( + cmTarget const* tgt, cmTargetInternals const* impl, + const std::string& prop) const +{ + bool did_read = false; + cmValue value = nullptr; + if (prop == this->DefaultDirectoryProperty) { + value = impl->GetFileSetDirectories(tgt, std::string(this->TypeName), + this->TypeName); + did_read = true; + } else if (prop == this->DefaultPathProperty) { + value = + impl->GetFileSetPaths(tgt, std::string(this->TypeName), this->TypeName); + did_read = true; + } else if (prop == this->SelfEntries.PropertyName) { + static std::string output; + output = cmJoin(this->SelfEntries.Entries, ";"_s); + value = cmValue(output); + did_read = true; + } else if (prop == this->InterfaceEntries.PropertyName) { + static std::string output; + output = cmJoin(this->InterfaceEntries.Entries, ";"_s); + value = cmValue(output); + did_read = true; + } else if (cmHasPrefix(prop, this->DirectoryPrefix)) { + std::string fileSetName = prop.substr(this->DirectoryPrefix.size()); + if (!fileSetName.empty()) { + value = impl->GetFileSetDirectories(tgt, fileSetName, this->TypeName); + } + did_read = true; + } else if (cmHasPrefix(prop, this->PathPrefix)) { + std::string fileSetName = prop.substr(this->PathPrefix.size()); + if (!fileSetName.empty()) { + value = impl->GetFileSetPaths(tgt, fileSetName, this->TypeName); + } + did_read = true; + } + return { did_read, value }; +} + +void FileSetType::AddFileSet(const std::string& name, cmFileSetVisibility vis, + cmListFileBacktrace bt) +{ + if (cmFileSetVisibilityIsForSelf(vis)) { + this->SelfEntries.Entries.emplace_back(name, bt); + } + if (cmFileSetVisibilityIsForInterface(vis)) { + this->InterfaceEntries.Entries.emplace_back(name, std::move(bt)); + } +} + namespace { #define SETUP_COMMON_LANGUAGE_PROPERTIES(lang) \ initProp(#lang "_COMPILER_LAUNCHER"); \ @@ -347,6 +543,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("LINK_DEPENDS_NO_SHARED"); initProp("LINK_INTERFACE_LIBRARIES"); initProp("MSVC_RUNTIME_LIBRARY"); + initProp("WATCOM_RUNTIME_LIBRARY"); initProp("WIN32_EXECUTABLE"); initProp("MACOSX_BUNDLE"); initProp("MACOSX_RPATH"); @@ -391,6 +588,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("UNITY_BUILD_UNIQUE_ID"); initProp("OPTIMIZE_DEPENDENCIES"); initProp("EXPORT_COMPILE_COMMANDS"); + initProp("COMPILE_WARNING_AS_ERROR"); initPropValue("UNITY_BUILD_BATCH_SIZE", "8"); initPropValue("UNITY_BUILD_MODE", "BATCH"); initPropValue("PCH_WARN_INVALID", "ON"); @@ -423,6 +621,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, } initProp("FOLDER"); + initProp("VERIFY_HEADER_SETS"); if (this->GetGlobalGenerator()->IsXcode()) { initProp("XCODE_GENERATE_SCHEME"); @@ -688,6 +887,11 @@ bool cmTarget::IsAndroidGuiExecutable() const this->impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")); } +bool cmTarget::HasKnownObjectFileLocation(std::string* reason) const +{ + return this->GetGlobalGenerator()->HasKnownObjectFileLocation(*this, reason); +} + std::vector<cmCustomCommand> const& cmTarget::GetPreBuildCommands() const { return this->impl->PreBuildCommands; @@ -1089,7 +1293,12 @@ void cmTarget::AddInstallIncludeDirectories(cmTargetExport const& te, cmStringRange cmTarget::GetInstallIncludeDirectoriesEntries( cmTargetExport const& te) const { - return cmMakeRange(this->impl->InstallIncludeDirectoriesEntries[&te]); + auto i = this->impl->InstallIncludeDirectoriesEntries.find(&te); + if (i == this->impl->InstallIncludeDirectoriesEntries.end()) { + decltype(i->second) empty; + return cmMakeRange(empty); + } + return cmMakeRange(i->second); } cmBTStringRange cmTarget::GetIncludeDirectoriesEntries() const @@ -1142,14 +1351,24 @@ cmBTStringRange cmTarget::GetLinkInterfaceEntries() const return cmMakeRange(this->impl->LinkInterfacePropertyEntries); } +cmBTStringRange cmTarget::GetLinkInterfaceDirectEntries() const +{ + return cmMakeRange(this->impl->LinkInterfaceDirectPropertyEntries); +} + +cmBTStringRange cmTarget::GetLinkInterfaceDirectExcludeEntries() const +{ + return cmMakeRange(this->impl->LinkInterfaceDirectExcludePropertyEntries); +} + cmBTStringRange cmTarget::GetHeaderSetsEntries() const { - return cmMakeRange(this->impl->HeaderSetsEntries); + return cmMakeRange(this->impl->HeadersFileSets.SelfEntries.Entries); } cmBTStringRange cmTarget::GetInterfaceHeaderSetsEntries() const { - return cmMakeRange(this->impl->InterfaceHeaderSetsEntries); + return cmMakeRange(this->impl->HeadersFileSets.InterfaceEntries.Entries); } namespace { @@ -1181,11 +1400,9 @@ MAKE_PROP(BINARY_DIR); MAKE_PROP(SOURCE_DIR); MAKE_PROP(FALSE); MAKE_PROP(TRUE); -MAKE_PROP(HEADER_DIRS); -MAKE_PROP(HEADER_SET); -MAKE_PROP(HEADER_SETS); -MAKE_PROP(INTERFACE_HEADER_SETS); MAKE_PROP(INTERFACE_LINK_LIBRARIES); +MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT); +MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE); #undef MAKE_PROP } @@ -1207,19 +1424,25 @@ std::string ConvertToString<cmValue>(cmValue value) } template <typename ValueType> -bool StringIsEmpty(ValueType value); +bool StringIsEmpty(ValueType const& value); template <> -bool StringIsEmpty<const char*>(const char* value) +bool StringIsEmpty<const char*>(const char* const& value) { return cmValue::IsEmpty(value); } template <> -bool StringIsEmpty<cmValue>(cmValue value) +bool StringIsEmpty<cmValue>(cmValue const& value) { return value.IsEmpty(); } + +template <> +bool StringIsEmpty<std::string>(std::string const& value) +{ + return value.empty(); +} } template <typename ValueType> @@ -1317,6 +1540,19 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value) cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); this->impl->LinkInterfacePropertyEntries.emplace_back(value, lfbt); } + } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) { + this->impl->LinkInterfaceDirectPropertyEntries.clear(); + if (value) { + cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + this->impl->LinkInterfaceDirectPropertyEntries.emplace_back(value, lfbt); + } + } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) { + this->impl->LinkInterfaceDirectExcludePropertyEntries.clear(); + if (value) { + cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + this->impl->LinkInterfaceDirectExcludePropertyEntries.emplace_back(value, + lfbt); + } } else if (prop == propSOURCES) { this->impl->SourceEntries.clear(); if (value) { @@ -1338,7 +1574,9 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value) } } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") && !this->impl->CheckImportedLibName( - prop, value ? value : std::string{})) { + prop, + value ? value + : std::string{})) { // NOLINT(bugprone-branch-clone) /* error was reported by check method */ } else if (prop == propCUDA_PTX_COMPILATION && this->GetType() != cmStateEnums::OBJECT_LIBRARY) { @@ -1389,81 +1627,9 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value) } else { this->impl->LanguageStandardProperties.erase(prop); } - } else if (prop == propHEADER_DIRS) { - auto* fileSet = this->GetFileSet("HEADERS"); - if (!fileSet) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "The default header set has not yet been created."); - return; - } - fileSet->ClearDirectoryEntries(); - if (!StringIsEmpty(value)) { - fileSet->AddDirectoryEntry( - BT<std::string>(value, this->impl->Makefile->GetBacktrace())); - } - } else if (prop == propHEADER_SET) { - auto* fileSet = this->GetFileSet("HEADERS"); - if (!fileSet) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "The default header set has not yet been created."); - return; - } - fileSet->ClearFileEntries(); - if (!StringIsEmpty(value)) { - fileSet->AddFileEntry( - BT<std::string>(value, this->impl->Makefile->GetBacktrace())); - } - } else if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) { - auto fileSetName = prop.substr(cmStrLen("HEADER_DIRS_")); - if (fileSetName.empty()) { - this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "Header set name cannot be empty."); - return; - } - auto* fileSet = this->GetFileSet(fileSetName); - if (!fileSet) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Header set \"", fileSetName, - "\" has not yet been created.")); - return; - } - fileSet->ClearDirectoryEntries(); - if (!StringIsEmpty(value)) { - fileSet->AddDirectoryEntry( - BT<std::string>(value, this->impl->Makefile->GetBacktrace())); - } - } else if (cmHasLiteralPrefix(prop, "HEADER_SET_")) { - auto fileSetName = prop.substr(cmStrLen("HEADER_SET_")); - if (fileSetName.empty()) { - this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "Header set name cannot be empty."); - return; - } - auto* fileSet = this->GetFileSet(fileSetName); - if (!fileSet) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Header set \"", fileSetName, - "\" has not yet been created.")); - return; - } - fileSet->ClearFileEntries(); - if (!StringIsEmpty(value)) { - fileSet->AddFileEntry( - BT<std::string>(value, this->impl->Makefile->GetBacktrace())); - } - } else if (prop == propHEADER_SETS) { - this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "HEADER_SETS property is read-only\n"); - return; - } else if (prop == propINTERFACE_HEADER_SETS) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "INTERFACE_HEADER_SETS property is read-only\n"); - return; + } else if (this->impl->HeadersFileSets.WriteProperties( + this, this->impl.get(), prop, value, true)) { + /* Handled in the `if` condition. */ } else { this->impl->Properties.SetProperty(prop, value); } @@ -1552,6 +1718,17 @@ void cmTarget::AppendProperty(const std::string& prop, cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); this->impl->LinkInterfacePropertyEntries.emplace_back(value, lfbt); } + } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) { + if (!value.empty()) { + cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + this->impl->LinkInterfaceDirectPropertyEntries.emplace_back(value, lfbt); + } + } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) { + if (!value.empty()) { + cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + this->impl->LinkInterfaceDirectExcludePropertyEntries.emplace_back(value, + lfbt); + } } else if (prop == "SOURCES") { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); this->impl->SourceEntries.emplace_back(value, lfbt); @@ -1563,69 +1740,9 @@ void cmTarget::AppendProperty(const std::string& prop, prop == "OBJC_STANDARD" || prop == "OBJCXX_STANDARD") { this->impl->Makefile->IssueMessage( MessageType::FATAL_ERROR, prop + " property may not be appended."); - } else if (prop == "HEADER_DIRS") { - auto* fileSet = this->GetFileSet("HEADERS"); - if (!fileSet) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "The default header set has not yet been created."); - return; - } - fileSet->AddDirectoryEntry( - BT<std::string>(value, this->impl->Makefile->GetBacktrace())); - } else if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) { - auto fileSetName = prop.substr(cmStrLen("HEADER_DIRS_")); - if (fileSetName.empty()) { - this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "Header set name cannot be empty."); - return; - } - auto* fileSet = this->GetFileSet(fileSetName); - if (!fileSet) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Header set \"", fileSetName, - "\" has not yet been created.")); - return; - } - fileSet->AddDirectoryEntry( - BT<std::string>(value, this->impl->Makefile->GetBacktrace())); - } else if (prop == "HEADER_SET") { - auto* fileSet = this->GetFileSet("HEADERS"); - if (!fileSet) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "The default header set has not yet been created."); - return; - } - fileSet->AddFileEntry( - BT<std::string>(value, this->impl->Makefile->GetBacktrace())); - } else if (cmHasLiteralPrefix(prop, "HEADER_SET_")) { - auto fileSetName = prop.substr(cmStrLen("HEADER_SET_")); - if (fileSetName.empty()) { - this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "Header set name cannot be empty."); - return; - } - auto* fileSet = this->GetFileSet(fileSetName); - if (!fileSet) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Header set \"", fileSetName, - "\" has not yet been created.")); - return; - } - fileSet->AddFileEntry( - BT<std::string>(value, this->impl->Makefile->GetBacktrace())); - } else if (prop == "HEADER_SETS") { - this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "HEADER_SETS property is read-only\n"); - return; - } else if (prop == "INTERFACE_HEADER_SETS") { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "INTERFACE_HEADER_SETS property is read-only\n"); - return; + } else if (this->impl->HeadersFileSets.WriteProperties( + this, this->impl.get(), prop, value, false)) { + /* Handled in the `if` condition. */ } else { this->impl->Properties.AppendProperty(prop, value, asString); } @@ -1640,6 +1757,102 @@ void cmTarget::SetProperty(const std::string& prop, cmValue value) this->StoreProperty(prop, value); } +template <typename ValueType> +void cmTargetInternals::AddDirectoryToFileSet( + cmTarget* self, std::string const& fileSetName, ValueType value, + cm::string_view fileSetType, cm::string_view description, bool clear) +{ + auto* fileSet = self->GetFileSet(fileSetName); + if (!fileSet) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(description, "has not yet been created.")); + return; + } + if (fileSet->GetType() != fileSetType) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("File set \"", fileSetName, + "\" is not of type \"", fileSetType, + "\".")); + return; + } + if (clear) { + fileSet->ClearDirectoryEntries(); + } + if (!StringIsEmpty(value)) { + fileSet->AddDirectoryEntry( + BT<std::string>(value, this->Makefile->GetBacktrace())); + } +} + +template <typename ValueType> +void cmTargetInternals::AddPathToFileSet( + cmTarget* self, std::string const& fileSetName, ValueType value, + cm::string_view fileSetType, cm::string_view description, bool clear) +{ + auto* fileSet = self->GetFileSet(fileSetName); + if (!fileSet) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(description, "has not yet been created.")); + return; + } + if (fileSet->GetType() != fileSetType) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("File set \"", fileSetName, + "\" is not of type \"", fileSetType, + "\".")); + return; + } + if (clear) { + fileSet->ClearFileEntries(); + } + if (!StringIsEmpty(value)) { + fileSet->AddFileEntry( + BT<std::string>(value, this->Makefile->GetBacktrace())); + } +} + +cmValue cmTargetInternals::GetFileSetDirectories( + cmTarget const* self, std::string const& fileSetName, + cm::string_view fileSetType) const +{ + auto const* fileSet = self->GetFileSet(fileSetName); + if (!fileSet) { + return nullptr; + } + if (fileSet->GetType() != fileSetType) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("File set \"", fileSetName, + "\" is not of type \"", fileSetType, + "\".")); + return nullptr; + } + static std::string output; + output = cmJoin(fileSet->GetDirectoryEntries(), ";"_s); + return cmValue(output); +} + +cmValue cmTargetInternals::GetFileSetPaths(cmTarget const* self, + std::string const& fileSetName, + cm::string_view fileSetType) const +{ + auto const* fileSet = self->GetFileSet(fileSetName); + if (!fileSet) { + return nullptr; + } + if (fileSet->GetType() != fileSetType) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("File set \"", fileSetName, + "\" is not of type \"", fileSetType, + "\".")); + return nullptr; + } + static std::string output; + output = cmJoin(fileSet->GetFileEntries(), ";"_s); + return cmValue(output); +} + void cmTarget::AppendBuildInterfaceIncludes() { if (this->GetType() != cmStateEnums::SHARED_LIBRARY && @@ -1709,69 +1922,94 @@ void cmTarget::InsertPrecompileHeader(BT<std::string> const& entry) this->impl->PrecompileHeadersEntries.push_back(entry); } -static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop, - const std::string& value, - cmMakefile* context, - bool imported) +namespace { +void CheckLinkLibraryPattern(const std::string& property, + const std::string& value, cmMakefile* context) { - // Look for link-type keywords in the value. - static cmsys::RegularExpression keys("(^|;)(debug|optimized|general)(;|$)"); - if (!keys.find(value)) { + // Look for <LINK_LIBRARY:> and </LINK_LIBRARY:> internal tags + static cmsys::RegularExpression linkPattern( + "(^|;)(</?LINK_(LIBRARY|GROUP):[^;>]*>)(;|$)"); + if (!linkPattern.find(value)) { return; } + // Report an error. + context->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Property ", property, " contains the invalid item \"", + linkPattern.match(2), "\". The ", property, + " property may contain the generator-expression \"$<LINK_", + linkPattern.match(3), + ":...>\" which may be used to specify how the libraries are linked.")); +} + +void CheckLINK_INTERFACE_LIBRARIES(const std::string& prop, + const std::string& value, + cmMakefile* context, bool imported) +{ // Support imported and non-imported versions of the property. const char* base = (imported ? "IMPORTED_LINK_INTERFACE_LIBRARIES" : "LINK_INTERFACE_LIBRARIES"); - // Report an error. - std::ostringstream e; - e << "Property " << prop << " may not contain link-type keyword \"" - << keys.match(2) << "\". " - << "The " << base << " property has a per-configuration " - << "version called " << base << "_<CONFIG> which may be " - << "used to specify per-configuration rules."; - if (!imported) { - e << " " - << "Alternatively, an IMPORTED library may be created, configured " - << "with a per-configuration location, and then named in the " - << "property value. " - << "See the add_library command's IMPORTED mode for details." - << "\n" - << "If you have a list of libraries that already contains the " - << "keyword, use the target_link_libraries command with its " - << "LINK_INTERFACE_LIBRARIES mode to set the property. " - << "The command automatically recognizes link-type keywords and sets " - << "the LINK_INTERFACE_LIBRARIES and LINK_INTERFACE_LIBRARIES_DEBUG " - << "properties accordingly."; - } - context->IssueMessage(MessageType::FATAL_ERROR, e.str()); -} - -static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const std::string& value, - cmMakefile* context) -{ // Look for link-type keywords in the value. static cmsys::RegularExpression keys("(^|;)(debug|optimized|general)(;|$)"); - if (!keys.find(value)) { - return; + if (keys.find(value)) { + // Report an error. + std::ostringstream e; + e << "Property " << prop << " may not contain link-type keyword \"" + << keys.match(2) << "\". " + << "The " << base << " property has a per-configuration " + << "version called " << base << "_<CONFIG> which may be " + << "used to specify per-configuration rules."; + if (!imported) { + e << " " + << "Alternatively, an IMPORTED library may be created, configured " + << "with a per-configuration location, and then named in the " + << "property value. " + << "See the add_library command's IMPORTED mode for details." + << "\n" + << "If you have a list of libraries that already contains the " + << "keyword, use the target_link_libraries command with its " + << "LINK_INTERFACE_LIBRARIES mode to set the property. " + << "The command automatically recognizes link-type keywords and sets " + << "the LINK_INTERFACE_LIBRARIES and LINK_INTERFACE_LIBRARIES_DEBUG " + << "properties accordingly."; + } + context->IssueMessage(MessageType::FATAL_ERROR, e.str()); } - // Report an error. - std::ostringstream e; + CheckLinkLibraryPattern(base, value, context); +} + +void CheckLINK_LIBRARIES(const std::string& value, cmMakefile* context) +{ + CheckLinkLibraryPattern("LINK_LIBRARIES", value, context); +} + +void CheckINTERFACE_LINK_LIBRARIES(const std::string& value, + cmMakefile* context) +{ + // Look for link-type keywords in the value. + static cmsys::RegularExpression keys("(^|;)(debug|optimized|general)(;|$)"); + if (keys.find(value)) { + // Report an error. + std::ostringstream e; - e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type " - "keyword \"" - << keys.match(2) - << "\". The INTERFACE_LINK_LIBRARIES " - "property may contain configuration-sensitive generator-expressions " - "which may be used to specify per-configuration rules."; + e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type " + "keyword \"" + << keys.match(2) + << "\". The INTERFACE_LINK_LIBRARIES " + "property may contain configuration-sensitive generator-expressions " + "which may be used to specify per-configuration rules."; - context->IssueMessage(MessageType::FATAL_ERROR, e.str()); + context->IssueMessage(MessageType::FATAL_ERROR, e.str()); + } + + CheckLinkLibraryPattern("INTERFACE_LINK_LIBRARIES", value, context); } -static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target, - cmMakefile* context) +void CheckIMPORTED_GLOBAL(const cmTarget* target, cmMakefile* context) { const auto& targets = context->GetOwnedImportedTargets(); auto it = @@ -1787,6 +2025,7 @@ static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target, context->IssueMessage(MessageType::FATAL_ERROR, e.str()); } } +} void cmTarget::CheckProperty(const std::string& prop, cmMakefile* context) const @@ -1794,22 +2033,23 @@ void cmTarget::CheckProperty(const std::string& prop, // Certain properties need checking. if (cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES")) { if (cmValue value = this->GetProperty(prop)) { - cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, *value, context, false); + CheckLINK_INTERFACE_LIBRARIES(prop, *value, context, false); } - } - if (cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES")) { + } else if (cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES")) { if (cmValue value = this->GetProperty(prop)) { - cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, *value, context, true); + CheckLINK_INTERFACE_LIBRARIES(prop, *value, context, true); } - } - if (prop == "INTERFACE_LINK_LIBRARIES") { + } else if (prop == "LINK_LIBRARIES") { if (cmValue value = this->GetProperty(prop)) { - cmTargetCheckINTERFACE_LINK_LIBRARIES(*value, context); + CheckLINK_LIBRARIES(*value, context); } - } - if (prop == "IMPORTED_GLOBAL") { + } else if (prop == "INTERFACE_LINK_LIBRARIES") { + if (cmValue value = this->GetProperty(prop)) { + CheckINTERFACE_LINK_LIBRARIES(*value, context); + } + } else if (prop == "IMPORTED_GLOBAL") { if (this->IsImported()) { - cmTargetCheckIMPORTED_GLOBAL(this, context); + CheckIMPORTED_GLOBAL(this, context); } } } @@ -1844,11 +2084,9 @@ cmValue cmTarget::GetProperty(const std::string& prop) const propBINARY_DIR, propSOURCE_DIR, propSOURCES, - propHEADER_DIRS, - propHEADER_SET, - propHEADER_SETS, - propINTERFACE_HEADER_SETS, propINTERFACE_LINK_LIBRARIES, + propINTERFACE_LINK_LIBRARIES_DIRECT, + propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE, }; if (specialProps.count(prop)) { if (prop == propC_STANDARD || prop == propCXX_STANDARD || @@ -1878,6 +2116,25 @@ cmValue cmTarget::GetProperty(const std::string& prop) const output = cmJoin(this->impl->LinkInterfacePropertyEntries, ";"); return cmValue(output); } + if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) { + if (this->impl->LinkInterfaceDirectPropertyEntries.empty()) { + return nullptr; + } + + static std::string output; + output = cmJoin(this->impl->LinkInterfaceDirectPropertyEntries, ";"); + return cmValue(output); + } + if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) { + if (this->impl->LinkInterfaceDirectExcludePropertyEntries.empty()) { + return nullptr; + } + + static std::string output; + output = + cmJoin(this->impl->LinkInterfaceDirectExcludePropertyEntries, ";"); + return cmValue(output); + } // the type property returns what type the target is if (prop == propTYPE) { return cmValue(cmState::GetTargetTypeName(this->GetType())); @@ -1983,73 +2240,15 @@ cmValue cmTarget::GetProperty(const std::string& prop) const .GetDirectory() .GetCurrentSource()); } - if (prop == propHEADER_DIRS) { - auto const* fileSet = this->GetFileSet("HEADERS"); - if (!fileSet) { - return nullptr; - } - static std::string output; - output = cmJoin(fileSet->GetDirectoryEntries(), ";"_s); - return cmValue(output); - } - if (prop == propHEADER_SET) { - auto const* fileSet = this->GetFileSet("HEADERS"); - if (!fileSet) { - return nullptr; - } - static std::string output; - output = cmJoin(fileSet->GetFileEntries(), ";"_s); - return cmValue(output); - } - if (prop == propHEADER_SETS) { - std::vector<std::string> set_names; - for (auto const& file_set : this->impl->FileSets) { - if (cmFileSetVisibilityIsForSelf(file_set.second.GetVisibility())) { - set_names.push_back(file_set.second.GetName()); - } - } - static std::string output; - output = cmJoin(set_names, ";"_s); - return cmValue(output); - } - if (prop == propINTERFACE_HEADER_SETS) { - std::vector<std::string> set_names; - for (auto const& file_set : this->impl->FileSets) { - if (cmFileSetVisibilityIsForInterface( - file_set.second.GetVisibility())) { - set_names.push_back(file_set.second.GetName()); - } - } - static std::string output; - output = cmJoin(set_names, ";"_s); - return cmValue(output); - } - } - if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) { - std::string fileSetName = prop.substr(cmStrLen("HEADER_DIRS_")); - if (fileSetName.empty()) { - return nullptr; - } - auto const* fileSet = this->GetFileSet(fileSetName); - if (!fileSet) { - return nullptr; - } - static std::string output; - output = cmJoin(fileSet->GetDirectoryEntries(), ";"_s); - return cmValue(output); } - if (cmHasLiteralPrefix(prop, "HEADER_SET_")) { - std::string fileSetName = prop.substr(cmStrLen("HEADER_SET_")); - if (fileSetName.empty()) { - return nullptr; - } - auto const* fileSet = this->GetFileSet(fileSetName); - if (!fileSet) { - return nullptr; + + // Check fileset properties. + { + auto headers = + this->impl->HeadersFileSets.ReadProperties(this, this->impl.get(), prop); + if (headers.first) { + return headers.second; } - static std::string output; - output = cmJoin(fileSet->GetFileEntries(), ";"_s); - return cmValue(output); } cmValue retVal = this->impl->Properties.GetPropertyValue(prop); @@ -2324,13 +2523,9 @@ std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet( auto result = this->impl->FileSets.emplace( std::make_pair(name, cmFileSet(name, type, vis))); if (result.second) { - if (cmFileSetVisibilityIsForSelf(vis)) { - this->impl->HeaderSetsEntries.emplace_back( - name, this->impl->Makefile->GetBacktrace()); - } - if (cmFileSetVisibilityIsForInterface(vis)) { - this->impl->InterfaceHeaderSetsEntries.emplace_back( - name, this->impl->Makefile->GetBacktrace()); + auto bt = this->impl->Makefile->GetBacktrace(); + if (type == this->impl->HeadersFileSets.TypeName) { + this->impl->HeadersFileSets.AddFileSet(name, vis, std::move(bt)); } } return std::make_pair(&result.first->second, result.second); @@ -2352,6 +2547,17 @@ std::string cmTarget::GetInterfaceFileSetsPropertyName(const std::string& type) return ""; } +std::vector<std::string> cmTarget::GetAllFileSetNames() const +{ + std::vector<std::string> result; + + for (auto const& it : this->impl->FileSets) { + result.push_back(it.first); + } + + return result; +} + std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const { std::vector<std::string> result; @@ -2364,7 +2570,7 @@ std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const } }; - appendEntries(this->impl->InterfaceHeaderSetsEntries); + appendEntries(this->impl->HeadersFileSets.InterfaceEntries.Entries); return result; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 3623854..5ed018e 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -220,6 +220,8 @@ public: //! Return whether this target is a GUI executable on Android. bool IsAndroidGuiExecutable() const; + bool HasKnownObjectFileLocation(std::string* reason = nullptr) const; + //! Get a backtrace from the creation of the target. cmListFileBacktrace const& GetBacktrace() const; @@ -269,6 +271,8 @@ public: cmBTStringRange GetLinkImplementationEntries() const; cmBTStringRange GetLinkInterfaceEntries() const; + cmBTStringRange GetLinkInterfaceDirectEntries() const; + cmBTStringRange GetLinkInterfaceDirectExcludeEntries() const; cmBTStringRange GetHeaderSetsEntries() const; @@ -288,6 +292,7 @@ public: const std::string& type, cmFileSetVisibility vis); + std::vector<std::string> GetAllFileSetNames() const; std::vector<std::string> GetAllInterfaceFileSets() const; static std::string GetFileSetsPropertyName(const std::string& type); diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index e10d0b5..e1a6c78 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -379,6 +379,9 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, target->SetProperty("LINK_INTERFACE_LIBRARIES", ""); } + target->CheckProperty("LINK_LIBRARIES", &mf); + target->CheckProperty("INTERFACE_LINK_LIBRARIES", &mf); + return true; } diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx index 05b3f05..130c228 100644 --- a/Source/cmTryCompileCommand.cxx +++ b/Source/cmTryCompileCommand.cxx @@ -20,7 +20,7 @@ bool cmTryCompileCommand::InitialPass(std::vector<std::string> const& argv, cmake::FIND_PACKAGE_MODE) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, - "The TRY_COMPILE() command is not supported in --find-package mode."); + "The try_compile() command is not supported in --find-package mode."); return false; } diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index cd468b9..c82ac64 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -31,7 +31,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, cmake::FIND_PACKAGE_MODE) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, - "The TRY_RUN() command is not supported in --find-package mode."); + "The try_run() command is not supported in --find-package mode."); return false; } @@ -217,7 +217,7 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs, retStr = "FAILED_TO_RUN"; } this->Makefile->AddCacheDefinition(this->RunResultVariable, retStr, - "Result of TRY_RUN", + "Result of try_run()", cmStateEnums::INTERNAL); } @@ -230,7 +230,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, std::string* out) { // copy the executable out of the CMakeFiles/ directory, so it is not - // removed at the end of TRY_RUN and the user can run it manually + // removed at the end of try_run() and the user can run it manually // on the target platform. std::string copyDest = cmStrCat(this->Makefile->GetHomeOutputDirectory(), "/CMakeFiles/", @@ -252,7 +252,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, // if the variables doesn't exist, create it with a helpful error text // and mark it as advanced std::string comment = - cmStrCat("Run result of TRY_RUN(), indicates whether the executable " + cmStrCat("Run result of try_run(), indicates whether the executable " "would have been able to run on its target platform.\n", detailsString); this->Makefile->AddCacheDefinition(this->RunResultVariable, @@ -274,7 +274,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, // if the variables doesn't exist, create it with a helpful error text // and mark it as advanced std::string comment = cmStrCat( - "Output of TRY_RUN(), contains the text, which the executable " + "Output of try_run(), contains the text, which the executable " "would have printed on stdout and stderr on its target platform.\n", detailsString); @@ -299,7 +299,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, if (firstTryRun) { /* clang-format off */ file << "# This file was generated by CMake because it detected " - "TRY_RUN() commands\n" + "try_run() commands\n" "# in crosscompiling mode. It will be overwritten by the next " "CMake run.\n" "# Copy it to a safe location, set the variables to " @@ -332,7 +332,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, } comment += "The "; comment += this->CompileResultVariable; - comment += " variable holds the build result for this TRY_RUN().\n\n" + comment += " variable holds the build result for this try_run().\n\n" "Source file : "; comment += srcFile + "\n"; comment += "Executable : "; @@ -346,19 +346,19 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, file << "set( " << this->RunResultVariable << " \n \"" << this->Makefile->GetSafeDefinition(this->RunResultVariable) - << "\"\n CACHE STRING \"Result from TRY_RUN\" FORCE)\n\n"; + << "\"\n CACHE STRING \"Result from try_run\" FORCE)\n\n"; if (out) { file << "set( " << internalRunOutputName << " \n \"" << this->Makefile->GetSafeDefinition(internalRunOutputName) - << "\"\n CACHE STRING \"Output from TRY_RUN\" FORCE)\n\n"; + << "\"\n CACHE STRING \"Output from try_run\" FORCE)\n\n"; } file.close(); } firstTryRun = false; std::string errorMessage = - cmStrCat("TRY_RUN() invoked in cross-compiling mode, " + cmStrCat("try_run() invoked in cross-compiling mode, " "please set the following cache variables " "appropriately:\n ", this->RunResultVariable, " (advanced)\n"); diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index cbd241b..1a3e72e 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -4,6 +4,11 @@ #include <utility> +#if !defined(CMAKE_BOOTSTRAP) +# include <cm3p/json/reader.h> +# include <cm3p/json/value.h> +#endif + #include "cmsys/Encoding.hxx" #include "cmsys/FStream.hxx" @@ -295,6 +300,87 @@ bool cmVSSetupAPIHelper::IsEWDKEnabled() return false; } +bool cmVSSetupAPIHelper::EnumerateVSInstancesWithVswhere( + std::vector<VSInstanceInfo>& VSInstances) +{ +#if !defined(CMAKE_BOOTSTRAP) + // Construct vswhere command to get installed VS instances in JSON format + std::string vswhereExe = getenv("ProgramFiles(x86)") + + std::string(R"(\Microsoft Visual Studio\Installer\vswhere.exe)"); + std::vector<std::string> vswhereCmd = { vswhereExe, "-format", "json" }; + + // Execute vswhere command and capture JSON output + std::string json_output; + int retVal = 1; + if (!cmSystemTools::RunSingleCommand(vswhereCmd, &json_output, &json_output, + &retVal, nullptr, + cmSystemTools::OUTPUT_NONE)) { + return false; + } + + // Parse JSON output and iterate over elements + Json::CharReaderBuilder builder; + auto jsonReader = std::unique_ptr<Json::CharReader>(builder.newCharReader()); + Json::Value json; + std::string error; + + if (!jsonReader->parse(json_output.data(), + json_output.data() + json_output.size(), &json, + &error)) { + return false; + } + + for (const auto& item : json) { + VSInstanceInfo instance; + instance.Version = item["installationVersion"].asString(); + instance.VSInstallLocation = item["installationPath"].asString(); + instance.IsWin10SDKInstalled = true; + instance.IsWin81SDKInstalled = false; + cmSystemTools::ConvertToUnixSlashes(instance.VSInstallLocation); + if (LoadVSInstanceVCToolsetVersion(instance)) { + VSInstances.push_back(instance); + } + } + return true; +#else + static_cast<void>(VSInstances); + return false; +#endif +} + +bool cmVSSetupAPIHelper::EnumerateVSInstancesWithCOM( + std::vector<VSInstanceInfo>& VSInstances) +{ + if (initializationFailure || setupConfig == NULL || setupConfig2 == NULL || + setupHelper == NULL) + return false; + + SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL; + if (FAILED( + setupConfig2->EnumInstances((IEnumSetupInstances**)&enumInstances)) || + !enumInstances) { + return false; + } + + SmartCOMPtr<ISetupInstance> instance; + while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { + SmartCOMPtr<ISetupInstance2> instance2 = NULL; + if (FAILED( + instance->QueryInterface(IID_ISetupInstance2, (void**)&instance2)) || + !instance2) { + instance = NULL; + continue; + } + + VSInstanceInfo instanceInfo; + bool isInstalled = GetVSInstanceInfo(instance2, instanceInfo); + instance = instance2 = NULL; + if (isInstalled) + VSInstances.push_back(instanceInfo); + } + return true; +} + bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() { bool isVSInstanceExists = false; @@ -321,10 +407,6 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() 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"; @@ -334,72 +416,60 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir); } - std::vector<VSInstanceInfo> vecVSInstances; - SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL; - if (FAILED( - setupConfig2->EnumInstances((IEnumSetupInstances**)&enumInstances)) || - !enumInstances) { - return false; - } - std::string const wantVersion = std::to_string(this->Version) + '.'; bool specifiedLocationNotSpecifiedVersion = false; SmartCOMPtr<ISetupInstance> instance; - while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) { - SmartCOMPtr<ISetupInstance2> instance2 = NULL; - if (FAILED( - instance->QueryInterface(IID_ISetupInstance2, (void**)&instance2)) || - !instance2) { - instance = NULL; + + std::vector<VSInstanceInfo> vecVSInstancesAll; + + // Enumerate VS instances with either COM interface or Vswhere + if (!EnumerateVSInstancesWithCOM(vecVSInstancesAll) && + !EnumerateVSInstancesWithVswhere(vecVSInstancesAll)) { + return false; + } + + std::vector<VSInstanceInfo> vecVSInstances; + for (const auto& instanceInfo : vecVSInstancesAll) { + // We are looking for a specific major version. + if (instanceInfo.Version.size() < wantVersion.size() || + instanceInfo.Version.substr(0, wantVersion.size()) != wantVersion) { continue; } - VSInstanceInfo instanceInfo; - bool isInstalled = GetVSInstanceInfo(instance2, instanceInfo); - instance = instance2 = NULL; - - if (isInstalled) { - // We are looking for a specific major version. - if (instanceInfo.Version.size() < wantVersion.size() || - instanceInfo.Version.substr(0, wantVersion.size()) != wantVersion) { - continue; + if (!this->SpecifiedVSInstallLocation.empty()) { + // We are looking for a specific instance. + std::string currentVSLocation = instanceInfo.GetInstallLocation(); + if (cmSystemTools::ComparePath(currentVSLocation, + this->SpecifiedVSInstallLocation)) { + if (this->SpecifiedVSInstallVersion.empty() || + instanceInfo.Version == this->SpecifiedVSInstallVersion) { + chosenInstanceInfo = instanceInfo; + return true; + } + specifiedLocationNotSpecifiedVersion = true; } - - if (!this->SpecifiedVSInstallLocation.empty()) { - // We are looking for a specific instance. - std::string currentVSLocation = instanceInfo.GetInstallLocation(); + } else if (!this->SpecifiedVSInstallVersion.empty()) { + // We are looking for a specific version. + if (instanceInfo.Version == this->SpecifiedVSInstallVersion) { + chosenInstanceInfo = instanceInfo; + return true; + } + } else { + // We are not looking for a specific instance. + // If we've been given a hint then use it. + if (!envVSCommonToolsDir.empty()) { + std::string currentVSLocation = + cmStrCat(instanceInfo.GetInstallLocation(), "/Common7/Tools"); if (cmSystemTools::ComparePath(currentVSLocation, - this->SpecifiedVSInstallLocation)) { - if (this->SpecifiedVSInstallVersion.empty() || - instanceInfo.Version == this->SpecifiedVSInstallVersion) { - chosenInstanceInfo = instanceInfo; - return true; - } - specifiedLocationNotSpecifiedVersion = true; - } - } else if (!this->SpecifiedVSInstallVersion.empty()) { - // We are looking for a specific version. - if (instanceInfo.Version == this->SpecifiedVSInstallVersion) { + envVSCommonToolsDir)) { chosenInstanceInfo = instanceInfo; return true; } - } else { - // We are not looking for a specific instance. - // If we've been given a hint then use it. - if (!envVSCommonToolsDir.empty()) { - std::string currentVSLocation = - cmStrCat(instanceInfo.GetInstallLocation(), "/Common7/Tools"); - if (cmSystemTools::ComparePath(currentVSLocation, - envVSCommonToolsDir)) { - chosenInstanceInfo = instanceInfo; - return true; - } - } - // Otherwise, add this to the list of candidates. - vecVSInstances.push_back(instanceInfo); } + // Otherwise, add this to the list of candidates. + vecVSInstances.push_back(instanceInfo); } } diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index 44c883b..a16f00b 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -118,6 +118,9 @@ private: int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances); bool EnumerateAndChooseVSInstance(); bool LoadSpecifiedVSInstanceFromDisk(); + bool EnumerateVSInstancesWithVswhere( + std::vector<VSInstanceInfo>& VSInstances); + bool EnumerateVSInstancesWithCOM(std::vector<VSInstanceInfo>& VSInstances); unsigned int Version; diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index fd5402c..24394d9 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -58,7 +58,7 @@ void cmVariableWatchCommandVariableAccessed(const std::string& variable, { stack, cmListFileArgument::Quoted, fakeLineNo } }; - cmListFileFunction newLFF{ data->Command, fakeLineNo, + cmListFileFunction newLFF{ data->Command, fakeLineNo, fakeLineNo, std::move(newLFFArgs) }; cmExecutionStatus status(*makefile); if (!makefile->ExecuteCommand(newLFF, status)) { diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 8ffb664..1739b5a 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -50,6 +50,24 @@ #include "cmValue.h" #include "cmVisualStudioGeneratorOptions.h" +namespace { +std::string getProjectFileExtension(VsProjectType projectType) +{ + switch (projectType) { + case VsProjectType::csproj: + return ".csproj"; + case VsProjectType::proj: + return ".proj"; + case VsProjectType::vcxproj: + return ".vcxproj"; + // Valid inputs shouldn't reach here. This default is needed so that all + // paths return value (C4715). + default: + return ""; + } +} +} + struct cmIDEFlagTable; static void ConvertToWindowsSlash(std::string& s); @@ -235,29 +253,6 @@ static bool cmVS10IsTargetsFile(std::string const& path) return cmSystemTools::Strucmp(ext.c_str(), ".targets") == 0; } -static VsProjectType computeProjectType(cmGeneratorTarget const* t) -{ - if (t->IsCSharpOnly()) { - return VsProjectType::csproj; - } - return VsProjectType::vcxproj; -} - -static std::string computeProjectFileExtension(VsProjectType projectType) -{ - switch (projectType) { - case VsProjectType::csproj: - return ".csproj"; - default: - return ".vcxproj"; - } -} - -static std::string computeProjectFileExtension(cmGeneratorTarget const* t) -{ - return computeProjectFileExtension(computeProjectType(t)); -} - cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator( cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg) : GeneratorTarget(target) @@ -352,10 +347,10 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString( void cmVisualStudio10TargetGenerator::Generate() { - this->ProjectType = computeProjectType(this->GeneratorTarget); + this->ProjectType = this->ComputeProjectType(this->GeneratorTarget); this->Managed = this->ProjectType == VsProjectType::csproj; const std::string ProjectFileExtension = - computeProjectFileExtension(this->ProjectType); + getProjectFileExtension(this->ProjectType); if (this->ProjectType == VsProjectType::csproj && this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) { @@ -416,10 +411,12 @@ void cmVisualStudio10TargetGenerator::Generate() char magic[] = { char(0xEF), char(0xBB), char(0xBF) }; BuildFileStream.write(magic, 3); - if (this->ProjectType == VsProjectType::csproj && - this->GeneratorTarget->IsDotNetSdkTarget() && - this->GlobalGenerator->GetVersion() >= - cmGlobalVisualStudioGenerator::VSVersion::VS16) { + if (this->ProjectType == VsProjectType::proj) { + this->WriteZeroCheckProj(BuildFileStream); + } else if (this->ProjectType == VsProjectType::csproj && + this->GeneratorTarget->IsDotNetSdkTarget() && + this->GlobalGenerator->GetVersion() >= + cmGlobalVisualStudioGenerator::VSVersion::VS16) { this->WriteSdkStyleProjectFile(BuildFileStream); } else { this->WriteClassicMsBuildProjectFile(BuildFileStream); @@ -667,6 +664,14 @@ void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile( } } + cmValue startupObject = + this->GeneratorTarget->GetProperty("VS_DOTNET_STARTUP_OBJECT"); + + if (startupObject && this->Managed) { + Elem e1(e0, "PropertyGroup"); + e1.Element("StartupObject", *startupObject); + } + switch (this->ProjectType) { case VsProjectType::vcxproj: { std::string const& props = @@ -681,6 +686,8 @@ void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile( .Attribute("Project", VS10_CSharp_DEFAULT_PROPS) .Attribute("Condition", "Exists('" VS10_CSharp_DEFAULT_PROPS "')"); break; + default: + break; } this->WriteProjectConfigurationValues(e0); @@ -737,6 +744,8 @@ void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile( case VsProjectType::csproj: props = VS10_CSharp_USER_PROPS; break; + default: + break; } if (cmValue p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) { props = *p; @@ -779,6 +788,8 @@ void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile( Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS); } break; + default: + break; } this->WriteTargetSpecificReferences(e0); @@ -924,6 +935,12 @@ void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile( break; } e1.Element("OutputType", outputType); + + cmValue startupObject = + this->GeneratorTarget->GetProperty("VS_DOTNET_STARTUP_OBJECT"); + if (startupObject) { + e1.Element("StartupObject", *startupObject); + } } for (const std::string& config : this->Configurations) { @@ -944,6 +961,45 @@ void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile( this->WriteProjectReferences(e0); } +void cmVisualStudio10TargetGenerator::WriteZeroCheckProj( + cmGeneratedFileStream& BuildFileStream) +{ + // ZERO_CHECK.proj is an XML file without any imports or targets. This is a + // ProjectReference for other targets and therefore, it needs to follow the + // ProjectReference protocol as documented here: + // https://github.com/dotnet/msbuild/blob/main/documentation/ProjectReference-Protocol.md + // + // We implement MSBuild target Build from WriteCustomCommand which calls + // WriteZeroCheckBuildTarget after setting up the command generator. MSBuild + // target Clean is a no-op as we do all the work for ZERO_CHECK on Build. + // MSBuild target GetTargetPath is needed and is no-op. + // MSBuild targets GetNativeManifest and GetCopyToOutputDirectoryItems are + // needed for MSBuild versions below 15.7 and are no-op. MSBuild target + // BeforeBuild is needed for supporting GLOBs. + BuildFileStream << "<?xml version=\"1.0\" encoding=\"" + << this->GlobalGenerator->Encoding() << "\"?>"; + { + Elem e0(BuildFileStream, "Project"); + e0.Attribute("DefaultTargets", "Build"); + e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion()); + e0.Attribute("xmlns", + "http://schemas.microsoft.com/developer/msbuild/2003"); + + this->WriteCustomCommands(e0); + + for (const char* targetName : + { "Clean", "GetTargetPath", "GetNativeManifest", + "GetCopyToOutputDirectoryItems" }) { + { + Elem e1(e0, "Target"); + e1.Attribute("Name", targetName); + } + } + + this->WriteZeroCheckBeforeBuildTarget(e0); + } +} + void cmVisualStudio10TargetGenerator::WriteCommonPropertyGroupGlobals(Elem& e1) { e1.Attribute("Label", "Globals"); @@ -1659,11 +1715,16 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( } } } + if (this->ProjectType == VsProjectType::proj) { + this->WriteZeroCheckBuildTarget(e0, command, source); + return; + } + cmLocalVisualStudio7Generator* lg = this->LocalGenerator; std::unique_ptr<Elem> spe1; std::unique_ptr<Elem> spe2; - if (this->ProjectType != VsProjectType::csproj) { + if (this->ProjectType == VsProjectType::vcxproj) { spe1 = cm::make_unique<Elem>(e0, "ItemGroup"); spe2 = cm::make_unique<Elem>(*spe1, "CustomBuild"); this->WriteSource(*spe2, source); @@ -1861,7 +1922,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() // Write out group file std::string path = cmStrCat( this->LocalGenerator->GetCurrentBinaryDirectory(), '/', this->Name, - computeProjectFileExtension(this->GeneratorTarget), ".filters"); + this->ComputeProjectFileExtension(this->GeneratorTarget), ".filters"); cmGeneratedFileStream fout(path); fout.SetCopyIfDifferent(true); char magic[] = { char(0xEF), char(0xBB), char(0xBF) }; @@ -3016,6 +3077,134 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental( } } +void cmVisualStudio10TargetGenerator::WriteZeroCheckBuildTarget( + cmVisualStudio10TargetGenerator::Elem& e0, const cmCustomCommand& command, + const cmSourceFile* source) +{ + cmLocalVisualStudio7Generator* lg = this->LocalGenerator; + + Elem e1(e0, "Target"); + e1.Attribute("Name", "Build"); + + std::string noConfig{}; + cmCustomCommandGenerator ccg{ command, noConfig, lg, true }; + std::string comment = lg->ConstructComment(ccg); + comment = cmVS10EscapeComment(comment); + std::string script = lg->ConstructScript(ccg); + bool symbolic = false; + // input files for custom command + std::stringstream additional_inputs; + { + const char* sep = ""; + if (this->ProjectType == VsProjectType::proj) { + // List explicitly the path to primary input. + std::string sourceFullPath = source->GetFullPath(); + ConvertToWindowsSlash(sourceFullPath); + additional_inputs << sourceFullPath; + sep = ";"; + } + + // Avoid listing an input more than once. + std::set<std::string> unique_inputs; + // The source is either implicitly an input or has been added above. + unique_inputs.insert(source->GetFullPath()); + + for (std::string const& d : ccg.GetDepends()) { + std::string dep; + if (lg->GetRealDependency(d, noConfig, dep)) { + if (!unique_inputs.insert(dep).second) { + // already listed + continue; + } + ConvertToWindowsSlash(dep); + additional_inputs << sep << dep; + sep = ";"; + if (!symbolic) { + if (cmSourceFile* sf = this->Makefile->GetSource( + dep, cmSourceFileLocationKind::Known)) { + symbolic = sf->GetPropertyAsBool("SYMBOLIC"); + } + } + } + } + } + // output files for custom command + std::stringstream outputs; + { + const char* sep = ""; + for (std::string const& o : ccg.GetOutputs()) { + std::string out = o; + ConvertToWindowsSlash(out); + outputs << sep << out; + sep = ";"; + if (!symbolic) { + if (cmSourceFile* sf = + this->Makefile->GetSource(o, cmSourceFileLocationKind::Known)) { + symbolic = sf->GetPropertyAsBool("SYMBOLIC"); + } + } + } + } + script += lg->FinishConstructScript(this->ProjectType); + + e1.Attribute("Inputs", cmVS10EscapeAttr(additional_inputs.str())); + e1.Attribute("Outputs", cmVS10EscapeAttr(outputs.str())); + + e1.SetHasElements(); + + if (!comment.empty()) { + Elem(e1, "Message").Attribute("Text", comment); + } + Elem(e1, "Exec").Attribute("Command", script); +} + +void cmVisualStudio10TargetGenerator::WriteZeroCheckBeforeBuildTarget( + cmVisualStudio10TargetGenerator::Elem& e0) +{ + const auto& commands = this->GeneratorTarget->GetPreBuildCommands(); + if (commands.empty()) { + return; + } + + { + Elem e1(e0, "Target"); + e1.Attribute("Name", "BeforeBuild"); + e1.Attribute("BeforeTargets", "Build"); + + cmLocalVisualStudio7Generator* lg = this->LocalGenerator; + std::string script; + const char* pre = ""; + std::string comment; + for (cmCustomCommand const& cc : commands) { + cmCustomCommandGenerator ccg(cc, std::string{}, lg); + if (!ccg.HasOnlyEmptyCommandLines()) { + comment += pre; + comment += lg->ConstructComment(ccg); + script += pre; + pre = "\n"; + script += lg->ConstructScript(ccg); + } + } + + if (script.empty()) { + return; + } + + script += lg->FinishConstructScript(this->ProjectType); + comment = cmVS10EscapeComment(comment); + std::string strippedComment = comment; + strippedComment.erase( + std::remove(strippedComment.begin(), strippedComment.end(), '\t'), + strippedComment.end()); + + e1.SetHasElements(); + if (!comment.empty() && !strippedComment.empty()) { + Elem(e1, "Message").Attribute("Text", comment); + } + Elem(e1, "Exec").Attribute("Command", script); + } +} + std::vector<std::string> cmVisualStudio10TargetGenerator::GetIncludes( std::string const& config, std::string const& lang) const { @@ -3057,6 +3246,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( cm::make_unique<Options>(this->LocalGenerator, Options::CSharpCompiler, gg->GetCSharpFlagTable()); break; + default: + break; } Options& clOptions = *pOptions; @@ -3182,6 +3373,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( return def.find('=') != std::string::npos; }); break; + default: + break; } clOptions.AddDefines(targetDefines); @@ -3309,7 +3502,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( } else if (this->MSTools) { cmsys::RegularExpression clangToolset("v[0-9]+_clang_.*"); const char* toolset = this->GlobalGenerator->GetPlatformToolset(); - if (toolset && clangToolset.find(toolset)) { + cmValue noCompileBatching = + this->GeneratorTarget->GetProperty("VS_NO_COMPILE_BATCHING"); + if (noCompileBatching.IsOn() || (toolset && clangToolset.find(toolset))) { e2.Element("ObjectFileName", "$(IntDir)%(filename).obj"); } else { e2.Element("ObjectFileName", "$(IntDir)"); @@ -3637,62 +3832,15 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( return false; } - // Would like to use: - // cmLinkLineDeviceComputer computer(this->LocalGenerator, - // this->LocalGenerator->GetStateSnapshot().GetDirectory()); - // std::string computed_libs = computer.ComputeLinkLibraries(cli, - // std::string{}); but it outputs in "<libA> <libB>" format instead of - // "<libA>;<libB>" - // Note: - // Any modification of this algorithm should be reflected also in - // cmLinkLineDeviceComputer cmComputeLinkInformation& cli = *pcli; + cmLinkLineDeviceComputer computer( + this->LocalGenerator, + this->LocalGenerator->GetStateSnapshot().GetDirectory()); + std::vector<BT<std::string>> btLibVec; + computer.ComputeLinkLibraries(cli, std::string{}, btLibVec); std::vector<std::string> libVec; - const auto& libs = cli.GetItems(); - for (cmComputeLinkInformation::Item const& l : libs) { - - if (l.Target) { - auto managedType = l.Target->GetManagedType(configName); - // Do not allow C# targets to be added to the LIB listing. LIB files - // are used for linking C++ dependencies. C# libraries do not have lib - // files. Instead, they compile down to C# reference libraries (DLL - // files). The - // `<ProjectReference>` elements added to the vcxproj are enough for - // the IDE to deduce the DLL file required by other C# projects that - // need its reference library. - if (managedType == cmGeneratorTarget::ManagedType::Managed) { - continue; - } - const auto type = l.Target->GetType(); - - bool skip = false; - switch (type) { - case cmStateEnums::SHARED_LIBRARY: - case cmStateEnums::MODULE_LIBRARY: - case cmStateEnums::INTERFACE_LIBRARY: - skip = true; - break; - case cmStateEnums::STATIC_LIBRARY: - skip = l.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS"); - break; - default: - break; - } - if (skip) { - continue; - } - } - - if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { - std::string path = - this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value); - ConvertToWindowsSlash(path); - if (!cmVS10IsTargetsFile(l.Value.Value)) { - libVec.push_back(path); - } - } else { - libVec.push_back(l.Value.Value); - } + for (auto const& item : btLibVec) { + libVec.emplace_back(item.Value); } cudaLinkOptions.AddFlag("AdditionalDependencies", libVec); @@ -4305,6 +4453,9 @@ void cmVisualStudio10TargetGenerator::AddLibraries( this->AdditionalUsingDirectories[config].insert( cmSystemTools::GetFilenamePath(location)); break; + default: + // In .proj files, we wouldn't be referencing libraries. + break; } } } @@ -4326,7 +4477,8 @@ void cmVisualStudio10TargetGenerator::AddLibraries( if (cmVS10IsTargetsFile(l.Value.Value)) { vsTargetVec.push_back(path); } else { - libVec.push_back(path); + libVec.push_back(l.HasFeature() ? l.GetFormattedItem(path).Value + : path); } } else if (!l.Target || l.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { @@ -4533,7 +4685,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) path = *p; } else { path = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', dt->GetName(), - computeProjectFileExtension(dt)); + this->ComputeProjectFileExtension(dt)); } ConvertToWindowsSlash(path); Elem e2(e1, "ProjectReference"); @@ -5387,6 +5539,26 @@ std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath( return path; } +std::string cmVisualStudio10TargetGenerator::ComputeProjectFileExtension( + cmGeneratorTarget const* t) const +{ + return getProjectFileExtension(this->ComputeProjectType(t)); +} + +VsProjectType cmVisualStudio10TargetGenerator::ComputeProjectType( + cmGeneratorTarget const* t) const +{ + if (this->GlobalGenerator->GetVersion() >= + cmGlobalVisualStudioGenerator::VSVersion::VS16 && + t->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) { + return VsProjectType::proj; + } + if (t->IsCSharpOnly()) { + return VsProjectType::csproj; + } + return VsProjectType::vcxproj; +} + void cmVisualStudio10TargetGenerator::WriteStdOutEncodingUtf8(Elem& e1) { if (this->GlobalGenerator->IsUtf8EncodingSupported()) { diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 8d777a3..7a0b8da 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -264,6 +264,13 @@ private: void WriteClassicMsBuildProjectFile(cmGeneratedFileStream& BuildFileStream); void WriteSdkStyleProjectFile(cmGeneratedFileStream& BuildFileStream); + void WriteZeroCheckProj(cmGeneratedFileStream& BuildFileStream); + void WriteZeroCheckBuildTarget(cmVisualStudio10TargetGenerator::Elem& e0, + const cmCustomCommand& command, + const cmSourceFile* source); + void WriteZeroCheckBeforeBuildTarget( + cmVisualStudio10TargetGenerator::Elem& e0); + void WriteCommonPropertyGroupGlobals( cmVisualStudio10TargetGenerator::Elem& e1); @@ -275,4 +282,7 @@ private: void ParseSettingsProperty(const std::string& settingsPropertyValue, ConfigToSettings& toolSettings); std::string GetCMakeFilePath(const char* name) const; + + std::string ComputeProjectFileExtension(cmGeneratorTarget const* t) const; + VsProjectType ComputeProjectType(cmGeneratorTarget const* t) const; }; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 0b27dfb..00c65ed 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -183,7 +183,8 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() // First entries for the -arch=<arch> [-code=<code>,...] pair. if (!arch.empty()) { std::string arch_name = arch[0]; - if (arch_name == "all" || arch_name == "all-major") { + if (arch_name == "all" || arch_name == "all-major" || + arch_name == "native") { AppendFlagString("AdditionalOptions", "-arch=" + arch_name); return; } diff --git a/Source/cmVsProjectType.h b/Source/cmVsProjectType.h index 8899267..04053a0 100644 --- a/Source/cmVsProjectType.h +++ b/Source/cmVsProjectType.h @@ -7,5 +7,6 @@ enum class VsProjectType { vcxproj, - csproj + csproj, + proj, }; diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index a93a81f..68d5a9a 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -17,6 +17,8 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmOutputConverter.h" +#include "cmPolicies.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -79,9 +81,8 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, return out; }; - // FIXME(#23296): For compatibility with older versions of CMake, we - // tolerate condition errors that evaluate to false. We should add - // a policy to enforce such errors. + // For compatibility with projects that do not set CMP0130 to NEW, + // we tolerate condition errors that evaluate to false. bool enforceError = true; std::string errorString; MessageType messageType; @@ -110,14 +111,38 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, } } + if (!errorString.empty() && !enforceError) { + // This error should only be enforced if CMP0130 is NEW. + switch (mf.GetPolicyStatus(cmPolicies::CMP0130)) { + case cmPolicies::WARN: + // Convert the error to a warning and enforce it. + messageType = MessageType::AUTHOR_WARNING; + enforceError = true; + break; + case cmPolicies::OLD: + // OLD behavior is to silently ignore the error. + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + // NEW behavior is to enforce the error. + enforceError = true; + break; + } + } + if (!errorString.empty() && enforceError) { - std::string err = "had incorrect arguments:\n "; + std::string err = "while() given incorrect arguments:\n "; for (auto const& i : expandedArguments) { err += " "; err += cmOutputConverter::EscapeForCMake(i.GetValue()); } err += "\n"; err += errorString; + if (mf.GetPolicyStatus(cmPolicies::CMP0130) == cmPolicies::WARN) { + err = + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0130), '\n', err); + } mf.GetCMakeInstance()->IssueMessage(messageType, err, whileBT); if (messageType == MessageType::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); diff --git a/Source/cmWindowsRegistry.cxx b/Source/cmWindowsRegistry.cxx new file mode 100644 index 0000000..6dba863 --- /dev/null +++ b/Source/cmWindowsRegistry.cxx @@ -0,0 +1,770 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmWindowsRegistry.h" + +#include <cctype> +#include <cstddef> +#include <functional> +#include <type_traits> +#include <unordered_map> +#include <utility> + +#include <cmext/string_view> + +#include "cmsys/RegularExpression.hxx" + +#if defined(_WIN32) && !defined(__CYGWIN__) +# include <algorithm> +# include <cstring> +# include <exception> +# include <iterator> +# include <vector> + +# include <cm/memory> + +# include <windows.h> + +# include "cmMakefile.h" +# include "cmStringAlgorithms.h" +# include "cmValue.h" +#endif + +namespace { +// Case-independent string comparison +int Strucmp(cm::string_view l, cm::string_view r) +{ + if (l.empty() && r.empty()) { + return 0; + } + if (l.empty() || r.empty()) { + return static_cast<int>(l.size() - r.size()); + } + + int lc; + int rc; + cm::string_view::size_type li = 0; + cm::string_view::size_type ri = 0; + + do { + lc = std::tolower(l[li++]); + rc = std::tolower(r[ri++]); + } while (lc == rc && li < l.size() && ri < r.size()); + + return lc == rc ? static_cast<int>(l.size() - r.size()) : lc - rc; +} + +#if defined(_WIN32) && !defined(__CYGWIN__) +bool Is64BitWindows() +{ +# if defined(_WIN64) + // 64-bit programs run only on Win64 + return true; +# else + // 32-bit programs run on both 32-bit and 64-bit Windows, so we must check. + BOOL isWow64 = false; + return IsWow64Process(GetCurrentProcess(), &isWow64) && isWow64; +# endif +} + +// Helper to translate Windows registry value type to enum ValueType +cm::optional<cmWindowsRegistry::ValueType> ToValueType(DWORD type) +{ + using ValueType = cmWindowsRegistry::ValueType; + + static std::unordered_map<DWORD, ValueType> ValueTypes{ + { REG_SZ, ValueType::Reg_SZ }, + { REG_EXPAND_SZ, ValueType::Reg_EXPAND_SZ }, + { REG_MULTI_SZ, ValueType::Reg_MULTI_SZ }, + { REG_DWORD, ValueType::Reg_DWORD }, + { REG_QWORD, ValueType::Reg_QWORD } + }; + + auto it = ValueTypes.find(type); + + return it == ValueTypes.end() + ? cm::nullopt + : cm::optional<cmWindowsRegistry::ValueType>{ it->second }; +} + +// class registry_exception +class registry_error : public std::exception +{ +public: + registry_error(std::string msg) + : What(std::move(msg)) + { + } + ~registry_error() override = default; + + const char* what() const noexcept override { return What.c_str(); } + +private: + std::string What; +}; + +// Class KeyHandler +class KeyHandler +{ +public: + using View = cmWindowsRegistry::View; + using ValueTypeSet = cmWindowsRegistry::ValueTypeSet; + + KeyHandler(HKEY hkey) + : Handler(hkey) + { + } + ~KeyHandler() { RegCloseKey(this->Handler); } + + static KeyHandler OpenKey(cm::string_view rootKey, cm::string_view subKey, + View view); + static KeyHandler OpenKey(cm::string_view key, View view); + + std::string ReadValue( + cm::string_view name, + ValueTypeSet supportedTypes = cmWindowsRegistry::AllTypes, + cm::string_view separator = "\0"_s); + + std::vector<std::string> GetValueNames(); + std::vector<std::string> GetSubKeys(); + +private: + static std::string FormatSystemError(LSTATUS status); + static std::wstring ToWide(cm::string_view str); + static std::string ToNarrow(const wchar_t* str, int size = -1); + + HKEY Handler; +}; + +KeyHandler KeyHandler::OpenKey(cm::string_view rootKey, cm::string_view subKey, + View view) +{ + if (view == View::Reg64 && !Is64BitWindows()) { + throw registry_error("No 64bit registry on Windows32."); + } + + HKEY hRootKey; + if (rootKey == "HKCU"_s || rootKey == "HKEY_CURRENT_USER"_s) { + hRootKey = HKEY_CURRENT_USER; + } else if (rootKey == "HKLM"_s || rootKey == "HKEY_LOCAL_MACHINE"_s) { + hRootKey = HKEY_LOCAL_MACHINE; + } else if (rootKey == "HKCR"_s || rootKey == "HKEY_CLASSES_ROOT"_s) { + hRootKey = HKEY_CLASSES_ROOT; + } else if (rootKey == "HKCC"_s || rootKey == "HKEY_CURRENT_CONFIG"_s) { + hRootKey = HKEY_CURRENT_CONFIG; + } else if (rootKey == "HKU"_s || rootKey == "HKEY_USERS"_s) { + hRootKey = HKEY_USERS; + } else { + throw registry_error(cmStrCat(rootKey, ": invalid root key.")); + } + // Update path format + auto key = ToWide(subKey); + std::replace(key.begin(), key.end(), L'/', L'\\'); + + REGSAM options = KEY_READ; + if (Is64BitWindows()) { + options |= view == View::Reg64 ? KEY_WOW64_64KEY : KEY_WOW64_32KEY; + } + + HKEY hKey; + LSTATUS status; + if ((status = RegOpenKeyExW(hRootKey, key.c_str(), 0, options, &hKey)) != + ERROR_SUCCESS) { + throw registry_error(FormatSystemError(status)); + } + + return KeyHandler(hKey); +} + +KeyHandler KeyHandler::OpenKey(cm::string_view key, View view) +{ + auto start = key.find_first_of("\\/"_s); + + return OpenKey(key.substr(0, start), + start == cm::string_view::npos ? cm::string_view{ ""_s } + : key.substr(start + 1), + view); +} + +std::string KeyHandler::FormatSystemError(LSTATUS status) +{ + std::string formattedMessage{ "Windows Registry: unexpected error." }; + LPWSTR message = nullptr; + DWORD size = 1024; + if (FormatMessageW( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, nullptr, + status, 0, reinterpret_cast<LPWSTR>(&message), size, nullptr) != 0) { + try { + formattedMessage = cmTrimWhitespace(ToNarrow(message)); + } catch (...) { + // ignore any exception because this method can be called + // as part of the raise of an exception + } + } + LocalFree(message); + + return formattedMessage; +} + +std::wstring KeyHandler::ToWide(cm::string_view str) +{ + std::wstring wstr; + + if (str.empty()) { + return wstr; + } + + const auto wlength = + MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(), + int(str.size()), nullptr, 0); + if (wlength > 0) { + auto wdata = cm::make_unique<wchar_t[]>(wlength); + const auto r = + MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(), + int(str.size()), wdata.get(), wlength); + if (r > 0) { + wstr = std::wstring(wdata.get(), wlength); + } else { + throw registry_error(FormatSystemError(GetLastError())); + } + } else { + throw registry_error(FormatSystemError(GetLastError())); + } + + return wstr; +} + +std::string KeyHandler::ToNarrow(const wchar_t* wstr, int size) +{ + std::string str; + + if (size == 0 || (size == -1 && wstr[0] == L'\0')) { + return str; + } + + const auto length = + WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, wstr, size, + nullptr, 0, nullptr, nullptr); + if (length > 0) { + auto data = cm::make_unique<char[]>(length); + const auto r = + WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, wstr, size, + data.get(), length, nullptr, nullptr); + if (r > 0) { + if (size == -1) { + str = std::string(data.get()); + } else { + str = std::string(data.get(), length); + } + } else { + throw registry_error(FormatSystemError(GetLastError())); + } + } else { + throw registry_error(FormatSystemError(GetLastError())); + } + + return str; +} + +std::string KeyHandler::ReadValue(cm::string_view name, + ValueTypeSet supportedTypes, + cm::string_view separator) +{ + LSTATUS status; + DWORD size; + // pick-up maximum size for value + if ((status = RegQueryInfoKeyW(this->Handler, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, + &size, nullptr, nullptr)) != ERROR_SUCCESS) { + throw registry_error(this->FormatSystemError(status)); + } + auto data = cm::make_unique<BYTE[]>(size); + DWORD type; + auto valueName = this->ToWide(name); + if ((status = RegQueryValueExW(this->Handler, valueName.c_str(), nullptr, + &type, data.get(), &size)) != ERROR_SUCCESS) { + throw registry_error(this->FormatSystemError(status)); + } + + auto valueType = ToValueType(type); + if (!valueType || !supportedTypes.contains(*valueType)) { + throw registry_error(cmStrCat(type, ": unsupported type.")); + } + + switch (type) { + case REG_SZ: + return this->ToNarrow(reinterpret_cast<wchar_t*>(data.get())); + break; + case REG_EXPAND_SZ: { + auto expandSize = ExpandEnvironmentStringsW( + reinterpret_cast<wchar_t*>(data.get()), nullptr, 0); + auto expandData = cm::make_unique<wchar_t[]>(expandSize + 1); + if (ExpandEnvironmentStringsW(reinterpret_cast<wchar_t*>(data.get()), + expandData.get(), expandSize + 1) == 0) { + throw registry_error(this->FormatSystemError(GetLastError())); + } else { + return this->ToNarrow(expandData.get()); + } + } break; + case REG_DWORD: + return std::to_string(*reinterpret_cast<std::uint32_t*>(data.get())); + break; + case REG_QWORD: + return std::to_string(*reinterpret_cast<std::uint64_t*>(data.get())); + break; + case REG_MULTI_SZ: { + // replace separator with semicolon + auto sep = this->ToWide(separator)[0]; + std::replace(reinterpret_cast<wchar_t*>(data.get()), + reinterpret_cast<wchar_t*>(data.get()) + + (size / sizeof(wchar_t)) - 1, + sep, L';'); + return this->ToNarrow(reinterpret_cast<wchar_t*>(data.get())); + } break; + default: + throw registry_error(cmStrCat(type, ": unsupported type.")); + } +} + +std::vector<std::string> KeyHandler::GetValueNames() +{ + LSTATUS status; + DWORD maxSize; + // pick-up maximum size for value names + if ((status = RegQueryInfoKeyW( + this->Handler, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, &maxSize, nullptr, nullptr, nullptr)) != ERROR_SUCCESS) { + throw registry_error(this->FormatSystemError(status)); + } + // increment size for final null + auto data = cm::make_unique<wchar_t[]>(++maxSize); + DWORD index = 0; + DWORD size = maxSize; + + std::vector<std::string> valueNames; + + while ((status = RegEnumValueW(this->Handler, index, data.get(), &size, + nullptr, nullptr, nullptr, nullptr)) == + ERROR_SUCCESS) { + auto name = this->ToNarrow(data.get()); + valueNames.push_back(name.empty() ? "(default)" : name); + size = maxSize; + ++index; + } + + if (status != ERROR_NO_MORE_ITEMS) { + throw registry_error(this->FormatSystemError(status)); + } + + return valueNames; +} + +std::vector<std::string> KeyHandler::GetSubKeys() +{ + LSTATUS status; + DWORD size; + // pick-up maximum size for subkeys + if ((status = RegQueryInfoKeyW( + this->Handler, nullptr, nullptr, nullptr, nullptr, &size, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr)) != ERROR_SUCCESS) { + throw registry_error(this->FormatSystemError(status)); + } + // increment size for final null + auto data = cm::make_unique<wchar_t[]>(++size); + DWORD index = 0; + std::vector<std::string> subKeys; + + while ((status = RegEnumKeyW(this->Handler, index, data.get(), size)) == + ERROR_SUCCESS) { + subKeys.push_back(this->ToNarrow(data.get())); + ++index; + } + if (status != ERROR_NO_MORE_ITEMS) { + throw registry_error(this->FormatSystemError(status)); + } + + return subKeys; +} +#endif + +// ExpressionParser: Helper to parse expression holding multiple +// registry specifications +class ExpressionParser +{ +public: + ExpressionParser(cm::string_view expression) + : Expression(expression) + , Separator(";"_s) + , RegistryFormat{ + "\\[({.+})?(HKCU|HKEY_CURRENT_USER|HKLM|HKEY_LOCAL_MACHINE|HKCR|HKEY_" + "CLASSES_" + "ROOT|HKCC|HKEY_CURRENT_CONFIG|HKU|HKEY_USERS)[/\\]?([^]]*)\\]" + } + { + } + + bool Find() + { + // reset result members + this->RootKey = cm::string_view{}; + this->SubKey = cm::string_view{}; + this->ValueName = cm::string_view{}; + + auto result = this->RegistryFormat.find(this->Expression); + + if (result) { + auto separator = cm::string_view{ + this->Expression.data() + this->RegistryFormat.start(1), + this->RegistryFormat.end(1) - this->RegistryFormat.start(1) + }; + if (separator.empty()) { + separator = this->Separator; + } else { + separator = separator.substr(1, separator.length() - 2); + } + + this->RootKey = cm::string_view{ + this->Expression.data() + this->RegistryFormat.start(2), + this->RegistryFormat.end(2) - this->RegistryFormat.start(2) + }; + this->SubKey = cm::string_view{ + this->Expression.data() + this->RegistryFormat.start(3), + this->RegistryFormat.end(3) - this->RegistryFormat.start(3) + }; + + auto pos = this->SubKey.find(separator); + if (pos != cm::string_view::npos) { + // split in ValueName and SubKey + this->ValueName = this->SubKey.substr(pos + separator.size()); + if (Strucmp(this->ValueName, "(default)") == 0) { + // handle magic name for default value + this->ValueName = ""_s; + } + this->SubKey = this->SubKey.substr(0, pos); + } else { + this->ValueName = ""_s; + } + } + return result; + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + void Replace(const std::string& value) + { + this->Expression.replace( + this->RegistryFormat.start(), + this->RegistryFormat.end() - this->RegistryFormat.start(), value); + } + + cm::string_view GetRootKey() const { return this->RootKey; } + + cm::string_view GetSubKey() const { return this->SubKey; } + cm::string_view GetValueName() const { return this->ValueName; } + + const std::string& GetExpression() const { return this->Expression; } +#endif + +private: + std::string Expression; + cm::string_view Separator; + cmsys::RegularExpression RegistryFormat; + cm::string_view RootKey; + cm::string_view SubKey; + cm::string_view ValueName; +}; +} + +// class cmWindowsRegistry +const cmWindowsRegistry::ValueTypeSet cmWindowsRegistry::SimpleTypes = + cmWindowsRegistry::ValueTypeSet{ cmWindowsRegistry::ValueType::Reg_SZ, + cmWindowsRegistry::ValueType::Reg_EXPAND_SZ, + cmWindowsRegistry::ValueType::Reg_DWORD, + cmWindowsRegistry::ValueType::Reg_QWORD }; +const cmWindowsRegistry::ValueTypeSet cmWindowsRegistry::AllTypes = + cmWindowsRegistry::SimpleTypes + cmWindowsRegistry::ValueType::Reg_MULTI_SZ; + +cmWindowsRegistry::cmWindowsRegistry(cmMakefile& makefile, + const ValueTypeSet& supportedTypes) +#if defined(_WIN32) && !defined(__CYGWIN__) + : SupportedTypes(supportedTypes) +#else + : LastError("No Registry on this platform.") +#endif +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + if (cmValue targetSize = makefile.GetDefinition("CMAKE_SIZEOF_VOID_P")) { + this->TargetSize = targetSize == "8" ? 64 : 32; + } +#else + (void)makefile; + (void)supportedTypes; +#endif +} + +cm::optional<cmWindowsRegistry::View> cmWindowsRegistry::ToView( + cm::string_view name) +{ + static std::unordered_map<cm::string_view, cmWindowsRegistry::View> + ViewDefinitions{ + { "BOTH"_s, View::Both }, { "HOST"_s, View::Host }, + { "TARGET"_s, View::Target }, { "32"_s, View::Reg32 }, + { "64"_s, View::Reg64 }, { "32_64"_s, View::Reg32_64 }, + { "64_32"_s, View::Reg64_32 } + }; + + auto it = ViewDefinitions.find(name); + + return it == ViewDefinitions.end() + ? cm::nullopt + : cm::optional<cmWindowsRegistry::View>{ it->second }; +} + +// define hash structure required by std::unordered_map +namespace std { +template <> +struct hash<cmWindowsRegistry::View> +{ + size_t operator()(cmWindowsRegistry::View const& v) const noexcept + { + return static_cast< + typename underlying_type<cmWindowsRegistry::View>::type>(v); + } +}; +} + +cm::string_view cmWindowsRegistry::FromView(View view) +{ + static std::unordered_map<cmWindowsRegistry::View, cm::string_view> + ViewDefinitions{ + { View::Both, "BOTH"_s }, { View::Host, "HOST"_s }, + { View::Target, "TARGET"_s }, { View::Reg32, "32"_s }, + { View::Reg64, "64"_s }, { View::Reg32_64, "32_64"_s }, + { View::Reg64_32, "64_32"_s } + }; + + auto it = ViewDefinitions.find(view); + + return it == ViewDefinitions.end() ? ""_s : it->second; +} + +cm::string_view cmWindowsRegistry::GetLastError() const +{ + return this->LastError; +} + +#if defined(_WIN32) && !defined(__CYGWIN__) +std::vector<cmWindowsRegistry::View> cmWindowsRegistry::ComputeViews(View view) +{ + switch (view) { + case View::Both: + switch (this->TargetSize) { + case 64: + return std::vector<View>{ View::Reg64, View::Reg32 }; + break; + case 32: + return Is64BitWindows() + ? std::vector<View>{ View::Reg32, View::Reg64 } + : std::vector<View>{ View::Reg32 }; + break; + default: + // No language specified, fallback to host architecture + return Is64BitWindows() + ? std::vector<View>{ View::Reg64, View::Reg32 } + : std::vector<View>{ View::Reg32 }; + break; + } + break; + case View::Target: + switch (this->TargetSize) { + case 64: + return std::vector<View>{ View::Reg64 }; + break; + case 32: + return std::vector<View>{ View::Reg32 }; + break; + default: + break; + } + CM_FALLTHROUGH; + case View::Host: + return std::vector<View>{ Is64BitWindows() ? View::Reg64 : View::Reg32 }; + break; + case View::Reg64_32: + return Is64BitWindows() ? std::vector<View>{ View::Reg64, View::Reg32 } + : std::vector<View>{ View::Reg32 }; + break; + case View::Reg32_64: + return Is64BitWindows() ? std::vector<View>{ View::Reg32, View::Reg64 } + : std::vector<View>{ View::Reg32 }; + break; + default: + return std::vector<View>{ view }; + break; + } +} +#endif + +cm::optional<std::string> cmWindowsRegistry::ReadValue( + cm::string_view key, cm::string_view name, View view, + cm::string_view separator) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + // compute list of registry views + auto views = this->ComputeViews(view); + + if (Strucmp(name, "(default)") == 0) { + // handle magic name for default value + name = ""_s; + } + if (separator.empty()) { + separator = "\0"_s; + } + + for (auto v : views) { + try { + this->LastError.clear(); + auto handler = KeyHandler::OpenKey(key, v); + return handler.ReadValue(name, this->SupportedTypes, separator); + } catch (const registry_error& e) { + this->LastError = e.what(); + continue; + } + } +#else + (void)key; + (void)name; + (void)view; + (void)separator; +#endif + return cm::nullopt; +} + +cm::optional<std::vector<std::string>> cmWindowsRegistry::GetValueNames( + cm::string_view key, View view) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + this->LastError.clear(); + // compute list of registry views + auto views = this->ComputeViews(view); + std::vector<std::string> valueNames; + bool querySuccessful = false; + + for (auto v : views) { + try { + auto handler = KeyHandler::OpenKey(key, v); + auto list = handler.GetValueNames(); + std::move(list.begin(), list.end(), std::back_inserter(valueNames)); + querySuccessful = true; + } catch (const registry_error& e) { + this->LastError = e.what(); + continue; + } + } + if (!valueNames.empty()) { + // value names must be unique and sorted + std::sort(valueNames.begin(), valueNames.end()); + valueNames.erase(std::unique(valueNames.begin(), valueNames.end()), + valueNames.end()); + } + + if (querySuccessful) { + // At least one query was successful, so clean-up any error message + this->LastError.clear(); + return valueNames; + } +#else + (void)key; + (void)view; +#endif + return cm::nullopt; +} + +cm::optional<std::vector<std::string>> cmWindowsRegistry::GetSubKeys( + cm::string_view key, View view) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + this->LastError.clear(); + // compute list of registry views + auto views = this->ComputeViews(view); + std::vector<std::string> subKeys; + bool querySuccessful = false; + + for (auto v : views) { + try { + auto handler = KeyHandler::OpenKey(key, v); + auto list = handler.GetSubKeys(); + std::move(list.begin(), list.end(), std::back_inserter(subKeys)); + querySuccessful = true; + } catch (const registry_error& e) { + this->LastError = e.what(); + continue; + } + } + if (!subKeys.empty()) { + // keys must be unique and sorted + std::sort(subKeys.begin(), subKeys.end()); + subKeys.erase(std::unique(subKeys.begin(), subKeys.end()), subKeys.end()); + } + + if (querySuccessful) { + // At least one query was successful, so clean-up any error message + this->LastError.clear(); + return subKeys; + } +#else + (void)key; + (void)view; +#endif + return cm::nullopt; +} + +cm::optional<std::vector<std::string>> cmWindowsRegistry::ExpandExpression( + cm::string_view expression, View view, cm::string_view separator) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + static std::string NOTFOUND{ "/REGISTRY-NOTFOUND" }; + + this->LastError.clear(); + + // compute list of registry views + auto views = this->ComputeViews(view); + std::vector<std::string> result; + + for (auto v : views) { + ExpressionParser parser(expression); + + while (parser.Find()) { + try { + auto handler = + KeyHandler::OpenKey(parser.GetRootKey(), parser.GetSubKey(), v); + auto data = handler.ReadValue(parser.GetValueName(), + this->SupportedTypes, separator); + parser.Replace(data); + } catch (const registry_error& e) { + this->LastError = e.what(); + parser.Replace(NOTFOUND); + continue; + } + } + result.emplace_back(parser.GetExpression()); + if (expression == parser.GetExpression()) { + // there no substitutions, so can ignore other views + break; + } + } + + return result; +#else + (void)view; + (void)separator; + + ExpressionParser parser(expression); + if (parser.Find()) { + // expression holds unsupported registry access + // so the expression cannot be used on this platform + return cm::nullopt; + } + return std::vector<std::string>{ std::string{ expression } }; +#endif +} diff --git a/Source/cmWindowsRegistry.h b/Source/cmWindowsRegistry.h new file mode 100644 index 0000000..bb9090e --- /dev/null +++ b/Source/cmWindowsRegistry.h @@ -0,0 +1,85 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include <string> +#include <vector> + +#include <cm/optional> +#include <cm/string_view> +#include <cmext/enum_set> +#include <cmext/string_view> + +class cmMakefile; + +class cmWindowsRegistry +{ +public: + enum class View + { + Both, + Target, + Host, + Reg64_32, + Reg32_64, + Reg32, + Reg64 + }; + + // Registry supported types + enum class ValueType : std::uint8_t + { + Reg_SZ, + Reg_EXPAND_SZ, + Reg_MULTI_SZ, + Reg_DWORD, + Reg_QWORD + }; + using ValueTypeSet = cm::enum_set<ValueType>; + + // All types as defined by enum ValueType + static const ValueTypeSet AllTypes; + // same as AllTYpes but without type REG_MULTI_SZ + static const ValueTypeSet SimpleTypes; + + cmWindowsRegistry(cmMakefile&, + const ValueTypeSet& supportedTypes = AllTypes); + + // Helper routine to convert string to enum value + static cm::optional<View> ToView(cm::string_view name); + // Helper routine to convert enum to string + static cm::string_view FromView(View view); + + cm::optional<std::string> ReadValue(cm::string_view key, + View view = View::Both, + cm::string_view separator = "\0"_s) + { + return this->ReadValue(key, ""_s, view, separator); + } + cm::optional<std::string> ReadValue(cm::string_view key, + cm::string_view name, + View view = View::Both, + cm::string_view separator = "\0"_s); + + cm::optional<std::vector<std::string>> GetValueNames(cm::string_view key, + View view = View::Both); + cm::optional<std::vector<std::string>> GetSubKeys(cm::string_view key, + View view = View::Both); + + // Expand an expression which may contains multiple references + // to registry keys. + // Depending of the view specified, one or two expansions can be done. + cm::optional<std::vector<std::string>> ExpandExpression( + cm::string_view expression, View view, cm::string_view separator = "\0"_s); + + cm::string_view GetLastError() const; + +private: +#if defined(_WIN32) && !defined(__CYGWIN__) + std::vector<View> ComputeViews(View view); + + int TargetSize = 0; + ValueTypeSet SupportedTypes = AllTypes; +#endif + std::string LastError; +}; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 7de488b..a8dc963 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -565,10 +565,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) "No install directory specified for --install-prefix", CommandArgument::Values::One, PrefixLambda }, CommandArgument{ "--find-package", CommandArgument::Values::Zero, - [&](std::string const&, cmake*) -> bool { - findPackageMode = true; - return true; - } }, + CommandArgument::setToTrue(findPackageMode) }, }; for (decltype(args.size()) i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; @@ -868,13 +865,15 @@ void cmake::SetArgs(const std::vector<std::string>& args) CommandArgument{ "-B", "No build directory specified for -B", CommandArgument::Values::One, CommandArgument::RequiresSeparator::No, BuildArgLambda }, + CommandArgument{ "--fresh", CommandArgument::Values::Zero, + [](std::string const&, cmake* cm) -> bool { + cm->FreshCache = true; + return true; + } }, CommandArgument{ "-P", "-P must be followed by a file name.", CommandArgument::Values::One, CommandArgument::RequiresSeparator::No, - [&](std::string const&, cmake*) -> bool { - scriptMode = true; - return true; - } }, + CommandArgument::setToTrue(scriptMode) }, CommandArgument{ "-D", "-D must be followed with VAR=VALUE.", CommandArgument::Values::One, CommandArgument::RequiresSeparator::No, @@ -1158,6 +1157,12 @@ void cmake::SetArgs(const std::vector<std::string>& args) // iterate each argument std::string const& arg = args[i]; + if (scriptMode && arg == "--") { + // Stop processing CMake args and avoid possible errors + // when arbitrary args are given to CMake script. + break; + } + // Generator flag has special handling for when to print help // so it becomes the exception if (generatorCommand.matches(arg)) { @@ -1455,7 +1460,7 @@ void cmake::PrintTraceFormatVersion() Json::StreamWriterBuilder builder; builder["indentation"] = ""; version["major"] = 1; - version["minor"] = 1; + version["minor"] = 2; val["version"] = version; msg = Json::writeString(builder, val); #endif @@ -2098,6 +2103,21 @@ int cmake::ActualConfigure() cmStateEnums::INTERNAL); } + // We want to create the package redirects directory as early as possible, + // but not before pre-configure checks have passed. This ensures we get + // errors about inappropriate source/binary directories first. + const auto redirectsDir = + cmStrCat(this->GetHomeOutputDirectory(), "/CMakeFiles/pkgRedirects"); + cmSystemTools::RemoveADirectory(redirectsDir); + if (!cmSystemTools::MakeDirectory(redirectsDir)) { + cmSystemTools::Error( + "Unable to (re)create the private pkgRedirects directory:\n" + + redirectsDir); + return -1; + } + this->AddCacheEntry("CMAKE_FIND_PACKAGE_REDIRECTS_DIR", redirectsDir, + "Value Computed by CMake.", cmStateEnums::STATIC); + // no generator specified on the command line if (!this->GlobalGenerator) { cmValue genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR"); @@ -2398,12 +2418,19 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) } if (this->GetWorkingMode() == NORMAL_MODE) { + if (this->FreshCache) { + this->DeleteCache(this->GetHomeOutputDirectory()); + } // load the cache if (this->LoadCache() < 0) { cmSystemTools::Error("Error executing cmake::LoadCache(). Aborting.\n"); return -1; } } else { + if (this->FreshCache) { + cmSystemTools::Error("--fresh allowed only when configuring a project"); + return -1; + } this->AddCMakePaths(); } diff --git a/Source/cmake.h b/Source/cmake.h index 3c2a36c..c2bbff7 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -703,6 +703,7 @@ private: FileExtensions HipFileExtensions; bool ClearBuildSystem = false; bool DebugTryCompile = false; + bool FreshCache = false; bool RegenerateDuringBuild = false; std::unique_ptr<cmFileTimeCache> FileTimeCache; std::string GraphVizFile; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 76055b4..41c6c12 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -9,6 +9,7 @@ #include <climits> #include <cstdio> #include <cstring> +#include <functional> #include <iostream> #include <sstream> #include <string> @@ -73,6 +74,8 @@ const char* cmDocumentationOptions[][2] = { { "--list-presets", "List available presets." }, { "-E", "CMake command mode." }, { "-L[A][H]", "List non-advanced cached variables." }, + { "--fresh", + "Configure a fresh build tree, removing any existing cache file." }, { "--build <dir>", "Build a CMake-generated project binary tree." }, { "--install <dir>", "Install a CMake-generated project binary tree." }, { "--open <dir>", "Open generated project in the associated application." }, @@ -260,37 +263,17 @@ int do_cmake(int ac, char const* const* av) return true; } }, CommandArgument{ "--system-information", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { - sysinfo = true; - return true; - } }, + CommandArgument::setToTrue(sysinfo) }, CommandArgument{ "-N", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { - view_only = true; - return true; - } }, + CommandArgument::setToTrue(view_only) }, CommandArgument{ "-LAH", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { - list_all_cached = true; - list_help = true; - return true; - } }, + CommandArgument::setToTrue(list_all_cached, list_help) }, CommandArgument{ "-LA", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { - list_all_cached = true; - return true; - } }, + CommandArgument::setToTrue(list_all_cached) }, CommandArgument{ "-LH", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { - list_cached = true; - list_help = true; - return true; - } }, + CommandArgument::setToTrue(list_cached, list_help) }, CommandArgument{ "-L", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { - list_cached = true; - return true; - } }, + CommandArgument::setToTrue(list_cached) }, CommandArgument{ "-P", "No script specified for argument -P", CommandArgument::Values::One, CommandArgument::RequiresSeparator::No, @@ -508,15 +491,9 @@ int do_build(int ac, char const* const* av) std::vector<CommandArgument> arguments = { CommandArgument{ "--preset", CommandArgument::Values::One, - [&](std::string const& value) -> bool { - presetName = value; - return true; - } }, + CommandArgument::setToValue(presetName) }, CommandArgument{ "--list-presets", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { - listPresets = true; - return true; - } }, + CommandArgument::setToTrue(listPresets) }, CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne, CommandArgument::RequiresSeparator::No, jLambda }, CommandArgument{ "--parallel", CommandArgument::Values::ZeroOrOne, @@ -525,15 +502,9 @@ int do_build(int ac, char const* const* av) CommandArgument{ "--target", CommandArgument::Values::OneOrMore, targetLambda }, CommandArgument{ "--config", CommandArgument::Values::One, - [&](std::string const& value) -> bool { - config = value; - return true; - } }, + CommandArgument::setToValue(config) }, CommandArgument{ "--clean-first", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { - cleanFirst = true; - return true; - } }, + CommandArgument::setToTrue(cleanFirst) }, CommandArgument{ "--resolve-package-references", CommandArgument::Values::One, resolvePackagesLambda }, CommandArgument{ "-v", CommandArgument::Values::Zero, verboseLambda }, @@ -543,10 +514,7 @@ int do_build(int ac, char const* const* av) CommandArgument{ "--use-stderr", CommandArgument::Values::Zero, [](std::string const&) -> bool { return true; } }, CommandArgument{ "--", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { - nativeOptionsPassed = true; - return true; - } }, + CommandArgument::setToTrue(nativeOptionsPassed) }, }; if (ac >= 3) { @@ -829,31 +797,16 @@ int do_install(int ac, char const* const* av) std::vector<CommandArgument> arguments = { CommandArgument{ "--config", CommandArgument::Values::One, - [&](std::string const& value) -> bool { - config = value; - return true; - } }, + CommandArgument::setToValue(config) }, CommandArgument{ "--component", CommandArgument::Values::One, - [&](std::string const& value) -> bool { - component = value; - return true; - } }, - CommandArgument{ "--default-directory-permissions", - CommandArgument::Values::One, - [&](std::string const& value) -> bool { - defaultDirectoryPermissions = value; - return true; - } }, + CommandArgument::setToValue(component) }, + CommandArgument{ + "--default-directory-permissions", CommandArgument::Values::One, + CommandArgument::setToValue(defaultDirectoryPermissions) }, CommandArgument{ "--prefix", CommandArgument::Values::One, - [&](std::string const& value) -> bool { - prefix = value; - return true; - } }, + CommandArgument::setToValue(prefix) }, CommandArgument{ "--strip", CommandArgument::Values::Zero, - [&](std::string const&) -> bool { - strip = true; - return true; - } }, + CommandArgument::setToTrue(strip) }, CommandArgument{ "-v", CommandArgument::Values::Zero, verboseLambda }, CommandArgument{ "--verbose", CommandArgument::Values::Zero, verboseLambda } diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 32c01e5..df740c9 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -97,7 +97,8 @@ void CMakeCommandUsage(std::string const& program) << "Available commands: \n" << " capabilities - Report capabilities built into cmake " "in JSON format\n" - << " cat <files>... - concat the files and print them to the standard output\n" + << " cat [--] <files>... - concat the files and print them to the " + "standard output\n" << " chdir dir cmd [args...] - run command in a given directory\n" << " compare_files [--ignore-eol] file1 file2\n" << " - check if file1 is same as file2\n" @@ -110,7 +111,7 @@ void CMakeCommandUsage(std::string const& program) << " echo [<string>...] - displays arguments as text\n" << " echo_append [<string>...] - displays arguments as text but no new " "line\n" - << " env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]...\n" + << " env [--unset=NAME ...] [NAME=VALUE ...] [--] <command> [<arg>...]\n" << " - run command in a modified environment\n" << " environment - display the current environment\n" << " make_directory <dir>... - create parent and <dir> directories\n" @@ -125,8 +126,9 @@ void CMakeCommandUsage(std::string const& program) << " remove_directory <dir>... - remove directories and their contents (deprecated: use rm instead)\n" << " rename oldname newname - rename a file or directory " "(on one volume)\n" - << " rm [-rRf] <file/dir>... - remove files or directories, use -f to " - "force it, r or R to remove directories and their contents recursively\n" + << " rm [-rRf] [--] <file/dir>... - remove files or directories, use -f " + "to force it, r or R to remove directories and their contents " + "recursively\n" << " sleep <number>... - sleep for given number of seconds\n" << " tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]\n" << " - create or extract a tar or zip archive\n" @@ -793,6 +795,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, auto ae = args.cend(); for (; ai != ae; ++ai) { std::string const& a = *ai; + if (a == "--") { + // Stop parsing options/environment variables; the next argument + // should be the command. + ++ai; + break; + } if (cmHasLiteralPrefix(a, "--unset=")) { // Unset environment variable. cmSystemTools::UnPutEnv(a.substr(8)); @@ -1051,9 +1059,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, // Command to concat files into one if (args[1] == "cat" && args.size() >= 3) { int return_value = 0; + bool doing_options = true; for (auto const& arg : cmMakeRange(args).advance(2)) { - if (cmHasLiteralPrefix(arg, "-")) { - if (arg != "--") { + if (doing_options && cmHasLiteralPrefix(arg, "-")) { + if (arg == "--") { + doing_options = false; + } else { cmSystemTools::Error(arg + ": option not handled"); return_value = 1; } @@ -1275,8 +1286,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, // FIXME: With advanced add_subdirectory usage, these are // not necessarily the same as the generator originally used. // We should pass all these directories through an info file. - lgd->SetRelativePathTopSource(homeDir); - lgd->SetRelativePathTopBinary(homeOutDir); + lgd->SetRelativePathTop(homeDir, homeOutDir); // Actually scan dependencies. return lgd->UpdateDependencies(depInfo, verbose, color) ? 0 : 2; @@ -1358,6 +1368,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, std::vector<std::string> files; std::string mtime; std::string format; + cmSystemTools::cmTarExtractTimestamps extractTimestamps = + cmSystemTools::cmTarExtractTimestamps::Yes; cmSystemTools::cmTarCompression compress = cmSystemTools::TarCompressNone; int nCompress = 0; @@ -1383,6 +1395,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, format); return 1; } + } else if (arg == "--touch") { + extractTimestamps = cmSystemTools::cmTarExtractTimestamps::No; } else { cmSystemTools::Error("Unknown option to -E tar: " + arg); return 1; @@ -1454,7 +1468,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, return 1; } } else if (action == cmSystemTools::TarActionExtract) { - if (!cmSystemTools::ExtractTar(outFile, files, verbose)) { + if (!cmSystemTools::ExtractTar(outFile, files, extractTimestamps, + verbose)) { cmSystemTools::Error("Problem extracting tar: " + outFile); return 1; } @@ -1558,8 +1573,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, // FIXME: With advanced add_subdirectory usage, these are // not necessarily the same as the generator originally used. // We should pass all these directories through an info file. - lgd->SetRelativePathTopSource(homeDir); - lgd->SetRelativePathTopBinary(homeOutDir); + lgd->SetRelativePathTop(homeDir, homeOutDir); return cmTransformDepfile(format, *lgd, args[8], args[9]) ? 0 : 2; } diff --git a/Source/ctest.cxx b/Source/ctest.cxx index cad27fa..363f473 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -44,6 +44,9 @@ static const char* cmDocumentationOptions[][2] = { { "--test-output-size-failed <size>", "Limit the output for failed tests " "to <size> bytes" }, + { "--test-output-truncation <mode>", + "Truncate 'tail' (default), 'middle' or 'head' of test output once " + "maximum output size is reached" }, { "-F", "Enable failover." }, { "-j <jobs>, --parallel <jobs>", "Run the tests in parallel using the " diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 19bf982..22cbf06 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -1906,7 +1906,7 @@ static void kwsysProcessDestroy(kwsysProcess* cp) (errno == EINTR)) { } if (result > 0) { - /* This child has termianted. */ + /* This child has terminated. */ cp->ForkPIDs[i] = 0; if (--cp->CommandsLeft == 0) { /* All children have terminated. Close the signal pipe diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index e97973e..17e1507 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -2119,7 +2119,7 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code, KWSYSPE_CASE(Fault, "In-page error"); break; case STATUS_INVALID_HANDLE: - KWSYSPE_CASE(Fault, "Invalid hanlde"); + KWSYSPE_CASE(Fault, "Invalid handle"); break; case STATUS_NONCONTINUABLE_EXCEPTION: KWSYSPE_CASE(Fault, "Noncontinuable exception"); |