diff options
Diffstat (limited to 'Source')
292 files changed, 9787 insertions, 5185 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index ddcdd7e..95b07cb 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 @@ -197,6 +199,7 @@ set(SRCS    cmCustomCommandTypes.h    cmDefinitions.cxx    cmDefinitions.h +  cmDependencyProvider.h    cmDepends.cxx    cmDepends.h    cmDependsC.cxx @@ -358,6 +361,8 @@ set(SRCS    cmLocalCommonGenerator.h    cmLocalGenerator.cxx    cmLocalGenerator.h +  cmPlaceholderExpander.cxx +  cmPlaceholderExpander.h    cmRulePlaceholderExpander.cxx    cmRulePlaceholderExpander.h    cmLocalUnixMakefileGenerator3.cxx @@ -456,6 +461,8 @@ set(SRCS    cmVariableWatch.h    cmVersion.cxx    cmVersion.h +  cmWindowsRegistry.cxx +  cmWindowsRegistry.h    cmWorkerPool.cxx    cmWorkerPool.h    cmWorkingDirectory.cxx @@ -728,7 +735,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 +1122,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 e28fc38..2d5e295 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 4) +set(CMake_VERSION_MINOR 24) +set(CMake_VERSION_PATCH 2)  #set(CMake_VERSION_RC 0)  set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index 9ca7a69..9dd8fe3 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -468,7 +468,7 @@ std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix(    const std::string suffix = "/data";    if (this->componentPackageMethod == this->ONE_PACKAGE) { -    return std::string(prefix + this->GetRootPackageName() + suffix); +    return cmStrCat(prefix, this->GetRootPackageName(), suffix);    }    return prefix + diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx index f25d2d2..46fc57f 100644 --- a/Source/CPack/IFW/cmCPackIFWRepository.cxx +++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx @@ -116,13 +116,12 @@ public:    cmCPackeIFWUpdatesPatcher(cmCPackIFWRepository* r, cmXMLWriter& x)      : repository(r)      , xout(x) -    , patched(false)    {    }    cmCPackIFWRepository* repository;    cmXMLWriter& xout; -  bool patched; +  bool patched = false;  protected:    void StartElement(const std::string& name, const char** atts) override diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 6a0095b..5dae966 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) { @@ -140,7 +151,7 @@ bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles)  int cmCPackWIXGenerator::PackageFiles()  { -  if (!PackageFilesImpl() || cmSystemTools::GetErrorOccuredFlag()) { +  if (!PackageFilesImpl() || cmSystemTools::GetErrorOccurredFlag()) {      cmCPackLogger(cmCPackLog::LOG_ERROR,                    "Fatal WiX Generator Error" << std::endl);      return false; diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 8e5e637..a3b9434 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -707,7 +707,7 @@ bool cmCPackDebGenerator::createDebPackages()                            &cmCPackDebGenerator::createDbgsymDDeb) &&        retval;    } -  return int(retval); +  return static_cast<int>(retval);  }  bool cmCPackDebGenerator::createDeb() diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx index 157ee1d..edd8490 100644 --- a/Source/CPack/cmCPackExternalGenerator.cxx +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -73,7 +73,7 @@ int cmCPackExternalGenerator::PackageFiles()      bool res = this->MakefileMap->ReadListFile(packageScript); -    if (cmSystemTools::GetErrorOccuredFlag() || !res) { +    if (cmSystemTools::GetErrorOccurredFlag() || !res) {        return 0;      } diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index b5d41fc..607d797 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -290,7 +290,7 @@ void cmCPackFreeBSDGenerator::write_manifest_fields(      cmExpandedList(var_lookup("CPACK_FREEBSD_PACKAGE_LICENSE"));    std::string licenselogic("single");    if (licenses.empty()) { -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();    } else if (licenses.size() > 1) {      licenselogic = var_lookup("CPACK_FREEBSD_PACKAGE_LICENSE_LOGIC");    } diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 7ddb103..90d15f8 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -525,7 +525,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript(        this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR",                                tempInstallDirectory);        bool res = this->MakefileMap->ReadListFile(installScript); -      if (cmSystemTools::GetErrorOccuredFlag() || !res) { +      if (cmSystemTools::GetErrorOccurredFlag() || !res) {          return 0;        }      } @@ -973,7 +973,7 @@ int cmCPackGenerator::InstallCMakeProject(        }      }    } -  if (cmSystemTools::GetErrorOccuredFlag() || !res) { +  if (cmSystemTools::GetErrorOccurredFlag() || !res) {      return 0;    }    return 1; @@ -985,7 +985,7 @@ bool cmCPackGenerator::ReadListFile(const char* moduleName)    std::string fullPath = this->MakefileMap->GetModulesFile(moduleName);    retval = this->MakefileMap->ReadListFile(fullPath);    // include FATAL_ERROR and ERROR in the return status -  retval = retval && (!cmSystemTools::GetErrorOccuredFlag()); +  retval = retval && (!cmSystemTools::GetErrorOccurredFlag());    return retval;  } @@ -1117,7 +1117,7 @@ int cmCPackGenerator::DoPackage()      this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion(),                                          std::string()); -    if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) { +    if (!this->PackageFiles() || cmSystemTools::GetErrorOccurredFlag()) {        cmCPackLogger(cmCPackLog::LOG_ERROR,                      "Problem compressing the directory" << std::endl);        return 0; @@ -1214,7 +1214,7 @@ int cmCPackGenerator::Initialize(const std::string& name, cmMakefile* mf)      mf->ReadListFile(config);    }    int result = this->InitializeInternal(); -  if (cmSystemTools::GetErrorOccuredFlag()) { +  if (cmSystemTools::GetErrorOccurredFlag()) {      return 0;    } 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/cmCPackLog.cxx b/Source/CPack/cmCPackLog.cxx index 49e4113..d37531b 100644 --- a/Source/CPack/cmCPackLog.cxx +++ b/Source/CPack/cmCPackLog.cxx @@ -159,6 +159,6 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg,    }    if (error) { -    cmSystemTools::SetErrorOccured(); +    cmSystemTools::SetErrorOccurred();    }  } 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..221f7dd 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"); @@ -466,7 +473,7 @@ int main(int argc, char const* const* argv)      return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;    } -  if (cmSystemTools::GetErrorOccuredFlag()) { +  if (cmSystemTools::GetErrorOccurredFlag()) {      return 1;    } diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index 0fe4ff4..81a866a 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -88,7 +88,6 @@ class cmCTestBZR::InfoParser : public cmCTestVC::LineParser  public:    InfoParser(cmCTestBZR* bzr, const char* prefix)      : BZR(bzr) -    , CheckOutFound(false)    {      this->SetLog(&bzr->Log, prefix);      this->RegexCheckOut.compile("checkout of branch: *([^\t\r\n]+)$"); @@ -97,7 +96,7 @@ public:  private:    cmCTestBZR* BZR; -  bool CheckOutFound; +  bool CheckOutFound = false;    cmsys::RegularExpression RegexCheckOut;    cmsys::RegularExpression RegexParent;    bool ProcessLine() override @@ -255,26 +254,26 @@ private:        this->BZR->DoRevision(this->Rev, this->Changes);      } else if (!this->CData.empty() &&                 (name == "file" || name == "directory")) { -      this->CurChange.Path.assign(&this->CData[0], this->CData.size()); +      this->CurChange.Path.assign(this->CData.data(), this->CData.size());        cmSystemTools::ConvertToUnixSlashes(this->CurChange.Path);        this->Changes.push_back(this->CurChange);      } else if (!this->CData.empty() && name == "symlink") {        // symlinks have an arobase at the end in the log -      this->CurChange.Path.assign(&this->CData[0], this->CData.size() - 1); +      this->CurChange.Path.assign(this->CData.data(), this->CData.size() - 1);        cmSystemTools::ConvertToUnixSlashes(this->CurChange.Path);        this->Changes.push_back(this->CurChange);      } else if (!this->CData.empty() && name == "committer") { -      this->Rev.Author.assign(&this->CData[0], this->CData.size()); +      this->Rev.Author.assign(this->CData.data(), this->CData.size());        if (this->EmailRegex.find(this->Rev.Author)) {          this->Rev.Author = this->EmailRegex.match(1);          this->Rev.EMail = this->EmailRegex.match(2);        }      } else if (!this->CData.empty() && name == "timestamp") { -      this->Rev.Date.assign(&this->CData[0], this->CData.size()); +      this->Rev.Date.assign(this->CData.data(), this->CData.size());      } else if (!this->CData.empty() && name == "message") { -      this->Rev.Log.assign(&this->CData[0], this->CData.size()); +      this->Rev.Log.assign(this->CData.data(), this->CData.size());      } else if (!this->CData.empty() && name == "revno") { -      this->Rev.Rev.assign(&this->CData[0], this->CData.size()); +      this->Rev.Rev.assign(this->CData.data(), this->CData.size());      }      this->CData.clear();    } @@ -389,7 +388,7 @@ bool cmCTestBZR::UpdateImpl()    // For some reason bzr uses stderr to display the update status.    OutputLogger out(this->Log, "pull-out> ");    UpdateParser err(this, "pull-err> "); -  return this->RunUpdateCommand(&bzr_update[0], &out, &err); +  return this->RunUpdateCommand(bzr_update.data(), &out, &err);  }  bool cmCTestBZR::LoadRevisions() diff --git a/Source/CTest/cmCTestBinPacker.cxx b/Source/CTest/cmCTestBinPacker.cxx index e21b14d..6eb45fa 100644 --- a/Source/CTest/cmCTestBinPacker.cxx +++ b/Source/CTest/cmCTestBinPacker.cxx @@ -34,7 +34,7 @@ namespace {   * more combinations can be tried.   */  template <typename AllocationStrategy> -static bool AllocateCTestResources( +bool AllocateCTestResources(    const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,    const std::vector<std::string>& resourcesSorted, std::size_t currentIndex,    std::vector<cmCTestBinPackerAllocation*>& allocations) @@ -82,7 +82,7 @@ static bool AllocateCTestResources(  }  template <typename AllocationStrategy> -static bool AllocateCTestResources( +bool AllocateCTestResources(    const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,    std::vector<cmCTestBinPackerAllocation>& allocations)  { @@ -108,7 +108,7 @@ static bool AllocateCTestResources(    // Do the actual allocation    return AllocateCTestResources<AllocationStrategy>( -    resources, resourcesSorted, std::size_t(0), allocationsPtr); +    resources, resourcesSorted, static_cast<std::size_t>(0), allocationsPtr);  }  class RoundRobinAllocationStrategy diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index e09b4dd..a39c52f 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -44,9 +44,9 @@ int cmCTestBuildAndTestHandler::ProcessHandler()  {    this->Output.clear();    std::string output; -  cmSystemTools::ResetErrorOccuredFlag(); +  cmSystemTools::ResetErrorOccurredFlag();    int retv = this->RunCMakeAndTest(&this->Output); -  cmSystemTools::ResetErrorOccuredFlag(); +  cmSystemTools::ResetErrorOccurredFlag();    return retv;  } diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 6e7c9e1..71787ea 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -84,7 +84,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()            std::string e = cmStrCat("could not create generator named \"",                                     *cmakeGeneratorName, '"');            this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); -          cmSystemTools::SetFatalErrorOccured(); +          cmSystemTools::SetFatalErrorOccurred();            return nullptr;          }        } diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 2aba79d..66c30c0 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -893,16 +893,31 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command,          // If there was an error running command, report that on the          // dashboard.          if (this->UseCTestLaunch) { -          cmCTestLaunchReporter reporter; -          reporter.RealArgs = args; -          reporter.ComputeFileNames(); -          reporter.ExitCode = *retVal; -          reporter.Process = cp; -          // Use temporary BuildLog file to populate this error for CDash. -          ofs.flush(); -          reporter.LogOut = this->LogFileNames["Build"]; -          reporter.LogOut += ".tmp"; -          reporter.WriteXML(); +          // For launchers, do not record this top-level error if other +          // more granular build errors have already been captured. +          bool launcherXMLFound = false; +          cmsys::Directory launchDir; +          launchDir.Load(this->CTestLaunchDir); +          unsigned long n = launchDir.GetNumberOfFiles(); +          for (unsigned long i = 0; i < n; ++i) { +            const char* fname = launchDir.GetFile(i); +            if (cmHasLiteralSuffix(fname, ".xml")) { +              launcherXMLFound = true; +              break; +            } +          } +          if (!launcherXMLFound) { +            cmCTestLaunchReporter reporter; +            reporter.RealArgs = args; +            reporter.ComputeFileNames(); +            reporter.ExitCode = *retVal; +            reporter.Process = cp; +            // Use temporary BuildLog file to populate this error for CDash. +            ofs.flush(); +            reporter.LogOut = this->LogFileNames["Build"]; +            reporter.LogOut += ".tmp"; +            reporter.WriteXML(); +          }          } else {            cmCTestBuildErrorWarning errorwarning;            errorwarning.LineNumber = 0; diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx index 1209e06..87ab762 100644 --- a/Source/CTest/cmCTestCVS.cxx +++ b/Source/CTest/cmCTestCVS.cxx @@ -101,7 +101,7 @@ bool cmCTestCVS::UpdateImpl()    UpdateParser out(this, "up-out> ");    UpdateParser err(this, "up-err> "); -  return this->RunUpdateCommand(&cvs_update[0], &out, &err); +  return this->RunUpdateCommand(cvs_update.data(), &out, &err);  }  class cmCTestCVS::LogParser : public cmCTestVC::LineParser @@ -111,7 +111,6 @@ public:    LogParser(cmCTestCVS* cvs, const char* prefix, std::vector<Revision>& revs)      : CVS(cvs)      , Revisions(revs) -    , Section(SectionHeader)    {      this->SetLog(&cvs->Log, prefix);      this->RegexRevision.compile("^revision +([^ ]*) *$"); @@ -131,7 +130,7 @@ private:      SectionRevisions,      SectionEnd    }; -  SectionType Section; +  SectionType Section = SectionHeader;    Revision Rev;    bool ProcessLine() override @@ -259,7 +258,7 @@ void cmCTestCVS::WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,      revisions.resize(2, this->Unknown);      // Write the entry for this file with these revisions. -    File f(fi.second, &revisions[0], &revisions[1]); +    File f(fi.second, revisions.data(), revisions.data() + 1);      this->WriteXMLEntry(xml, path, fi.first, full, f);    }    xml.EndElement(); // Directory diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 1b2f769..f7c6a9c 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; @@ -2216,7 +2210,7 @@ int cmCTestCoverageHandler::GetLabelId(std::string const& label)  {    auto i = this->LabelIdMap.find(label);    if (i == this->LabelIdMap.end()) { -    int n = int(this->Labels.size()); +    int n = static_cast<int>(this->Labels.size());      this->Labels.push_back(label);      LabelIdMapType::value_type entry(label, n);      i = this->LabelIdMap.insert(entry).first; diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 56f805c..b2fb069 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -176,7 +176,7 @@ bool cmCTestGIT::UpdateByFetchAndReset()    // Fetch upstream refs.    OutputLogger fetch_out(this->Log, "fetch-out> ");    OutputLogger fetch_err(this->Log, "fetch-err> "); -  if (!this->RunUpdateCommand(&git_fetch[0], &fetch_out, &fetch_err)) { +  if (!this->RunUpdateCommand(git_fetch.data(), &fetch_out, &fetch_err)) {      return false;    } @@ -225,7 +225,7 @@ bool cmCTestGIT::UpdateByCustom(std::string const& custom)    OutputLogger custom_out(this->Log, "custom-out> ");    OutputLogger custom_err(this->Log, "custom-err> "); -  return this->RunUpdateCommand(&git_custom[0], &custom_out, &custom_err); +  return this->RunUpdateCommand(git_custom.data(), &custom_out, &custom_err);  }  bool cmCTestGIT::UpdateInternal() @@ -332,7 +332,6 @@ public:    DiffParser(cmCTestGIT* git, const char* prefix)      : LineParser('\0', false)      , GIT(git) -    , DiffField(DiffFieldNone)    {      this->SetLog(&git->Log, prefix);    } @@ -349,7 +348,7 @@ protected:      DiffFieldSrc,      DiffFieldDst    }; -  DiffFieldType DiffField; +  DiffFieldType DiffField = DiffFieldNone;    Change CurChange;    void DiffReset() @@ -454,7 +453,6 @@ class cmCTestGIT::CommitParser : public cmCTestGIT::DiffParser  public:    CommitParser(cmCTestGIT* git, const char* prefix)      : DiffParser(git, prefix) -    , Section(SectionHeader)    {      this->Separator = SectionSep[this->Section];    } @@ -469,7 +467,7 @@ private:      SectionCount    };    static char const SectionSep[SectionCount]; -  SectionType Section; +  SectionType Section = SectionHeader;    Revision Rev;    struct Person @@ -537,7 +535,8 @@ private:    void NextSection()    { -    this->Section = SectionType((this->Section + 1) % SectionCount); +    this->Section = +      static_cast<SectionType>((this->Section + 1) % SectionCount);      this->Separator = SectionSep[this->Section];      if (this->Section == SectionHeader) {        this->GIT->DoRevision(this->Rev, this->Changes); diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 9800192..1c292c7 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -137,7 +137,7 @@ bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part,                 "maybe you forgot to call ctest_start() before calling "                 "ctest_configure()."                   << std::endl); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    if (!this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(), ostr.str(), diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx index 5f4581e..97b01ba 100644 --- a/Source/CTest/cmCTestHG.cxx +++ b/Source/CTest/cmCTestHG.cxx @@ -157,7 +157,7 @@ bool cmCTestHG::UpdateImpl()    OutputLogger out(this->Log, "update-out> ");    OutputLogger err(this->Log, "update-err> "); -  return this->RunUpdateCommand(&hg_update[0], &out, &err); +  return this->RunUpdateCommand(hg_update.data(), &out, &err);  }  class cmCTestHG::LogParser @@ -213,13 +213,13 @@ private:      if (name == "logentry") {        this->HG->DoRevision(this->Rev, this->Changes);      } else if (!this->CData.empty() && name == "author") { -      this->Rev.Author.assign(&this->CData[0], this->CData.size()); +      this->Rev.Author.assign(this->CData.data(), this->CData.size());      } else if (!this->CData.empty() && name == "email") { -      this->Rev.EMail.assign(&this->CData[0], this->CData.size()); +      this->Rev.EMail.assign(this->CData.data(), this->CData.size());      } else if (!this->CData.empty() && name == "date") { -      this->Rev.Date.assign(&this->CData[0], this->CData.size()); +      this->Rev.Date.assign(this->CData.data(), this->CData.size());      } else if (!this->CData.empty() && name == "msg") { -      this->Rev.Log.assign(&this->CData[0], this->CData.size()); +      this->Rev.Log.assign(this->CData.data(), this->CData.size());      } else if (!this->CData.empty() && name == "files") {        std::vector<std::string> paths = this->SplitCData();        for (std::string const& path : paths) { diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index ea8feaa..5494d20 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -29,8 +29,8 @@ class SaveRestoreErrorState  public:    SaveRestoreErrorState()    { -    this->InitialErrorState = cmSystemTools::GetErrorOccuredFlag(); -    cmSystemTools::ResetErrorOccuredFlag(); // rest the error state +    this->InitialErrorState = cmSystemTools::GetErrorOccurredFlag(); +    cmSystemTools::ResetErrorOccurredFlag(); // rest the error state      this->CaptureCMakeErrorValue = false;    }    // if the function has a CAPTURE_CMAKE_ERROR then we should restore @@ -44,21 +44,21 @@ public:      // otherwise leave it be what it is      if (!this->CaptureCMakeErrorValue) {        if (this->InitialErrorState) { -        cmSystemTools::SetErrorOccured(); +        cmSystemTools::SetErrorOccurred();        }        return;      }      // if we have saved the error in a return variable      // then put things back exactly like they were -    bool currentState = cmSystemTools::GetErrorOccuredFlag(); +    bool currentState = cmSystemTools::GetErrorOccurredFlag();      // if the state changed during this command we need      // to handle it, if not then nothing needs to be done      if (currentState != this->InitialErrorState) {        // restore the initial error state        if (this->InitialErrorState) { -        cmSystemTools::SetErrorOccured(); +        cmSystemTools::SetErrorOccurred();        } else { -        cmSystemTools::ResetErrorOccuredFlag(); +        cmSystemTools::ResetErrorOccurredFlag();        }      }    } @@ -212,7 +212,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,    // log the error message if there was an error    if (captureCMakeError) {      const char* returnString = "0"; -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        returnString = "-1";        std::string const& err = status.GetError();        // print out the error if it is not "unknown error" which means diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 6bb8e79..788845b 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; @@ -1206,7 +1207,8 @@ bool cmCTestMemCheckHandler::ProcessMemCheckCudaOutput(        if (failure >= 0) {          ostr << "<b>" << this->ResultStrings[failure] << "</b> "; -        if (results.empty() || unsigned(failure) > results.size() - 1) { +        if (results.empty() || +            static_cast<unsigned>(failure) > results.size() - 1) {            results.push_back(1);          } else {            results[failure]++; 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/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index 50c9c16..0e67c41 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -118,7 +118,6 @@ class cmCTestP4::DiffParser : public cmCTestVC::LineParser  public:    DiffParser(cmCTestP4* p4, const char* prefix)      : P4(p4) -    , AlreadyNotified(false)    {      this->SetLog(&this->P4->Log, prefix);      this->RegexDiff.compile("^==== (.*)#[0-9]+ - (.*)"); @@ -126,7 +125,7 @@ public:  private:    cmCTestP4* P4; -  bool AlreadyNotified; +  bool AlreadyNotified = false;    std::string CurrentPath;    cmsys::RegularExpression RegexDiff; @@ -161,7 +160,7 @@ cmCTestP4::User cmCTestP4::GetUserData(const std::string& username)      UserParser out(this, "users-out> ");      OutputLogger err(this->Log, "users-err> "); -    this->RunChild(&p4_users[0], &out, &err); +    this->RunChild(p4_users.data(), &out, &err);      // The user should now be added to the map. Search again.      it = this->Users.find(username); @@ -193,7 +192,6 @@ public:    DescribeParser(cmCTestP4* p4, const char* prefix)      : LineParser('\n', false)      , P4(p4) -    , Section(SectionHeader)    {      this->SetLog(&this->P4->Log, prefix);      this->RegexHeader.compile("^Change ([0-9]+) by (.+)@(.+) on (.*)$"); @@ -216,7 +214,7 @@ private:      SectionDiff,      SectionCount    }; -  SectionType Section; +  SectionType Section = SectionHeader;    Revision Rev;    bool ProcessLine() override @@ -250,7 +248,8 @@ private:        this->Rev = Revision();      } -    this->Section = SectionType((this->Section + 1) % SectionCount); +    this->Section = +      static_cast<SectionType>((this->Section + 1) % SectionCount);    }    void DoHeaderLine() @@ -354,7 +353,7 @@ std::string cmCTestP4::GetWorkingRevision()    IdentifyParser out(this, "p4_changes-out> ", rev);    OutputLogger err(this->Log, "p4_changes-err> "); -  bool result = this->RunChild(&p4_identify[0], &out, &err); +  bool result = this->RunChild(p4_identify.data(), &out, &err);    // If there was a problem contacting the server return "<unknown>"    if (!result) { @@ -418,7 +417,7 @@ bool cmCTestP4::LoadRevisions()    OutputLogger err(this->Log, "p4_changes-err> ");    this->ChangeLists.clear(); -  this->RunChild(&p4_changes[0], &out, &err); +  this->RunChild(p4_changes.data(), &out, &err);    if (this->ChangeLists.empty()) {      return true; @@ -435,7 +434,7 @@ bool cmCTestP4::LoadRevisions()      DescribeParser outDescribe(this, "p4_describe-out> ");      OutputLogger errDescribe(this->Log, "p4_describe-err> "); -    this->RunChild(&p4_describe[0], &outDescribe, &errDescribe); +    this->RunChild(p4_describe.data(), &outDescribe, &errDescribe);    }    return true;  } @@ -455,7 +454,7 @@ bool cmCTestP4::LoadModifications()    DiffParser out(this, "p4_diff-out> ");    OutputLogger err(this->Log, "p4_diff-err> "); -  this->RunChild(&p4_diff[0], &out, &err); +  this->RunChild(p4_diff.data(), &out, &err);    return true;  } @@ -473,7 +472,7 @@ bool cmCTestP4::UpdateCustom(const std::string& custom)    OutputLogger custom_out(this->Log, "p4_customsync-out> ");    OutputLogger custom_err(this->Log, "p4_customsync-err> "); -  return this->RunUpdateCommand(&p4_custom[0], &custom_out, &custom_err); +  return this->RunUpdateCommand(p4_custom.data(), &custom_out, &custom_err);  }  bool cmCTestP4::UpdateImpl() @@ -523,5 +522,5 @@ bool cmCTestP4::UpdateImpl()    OutputLogger out(this->Log, "p4_sync-out> ");    OutputLogger err(this->Log, "p4_sync-err> "); -  return this->RunUpdateCommand(&p4_sync[0], &out, &err); +  return this->RunUpdateCommand(p4_sync.data(), &out, &err);  } 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/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 4692dbd..4c98fdf 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -286,9 +286,9 @@ bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters,    args.push_back(nullptr);    if (strcmp(parameters[0], "update") == 0) { -    return this->RunUpdateCommand(&args[0], out, err); +    return this->RunUpdateCommand(args.data(), out, err);    } -  return this->RunChild(&args[0], out, err); +  return this->RunChild(args.data(), out, err);  }  class cmCTestSVN::LogParser @@ -353,16 +353,16 @@ private:      if (name == "logentry") {        this->SVN->DoRevisionSVN(this->Rev, this->Changes);      } else if (!this->CData.empty() && name == "path") { -      std::string orig_path(&this->CData[0], this->CData.size()); +      std::string orig_path(this->CData.data(), this->CData.size());        std::string new_path = this->SVNRepo.BuildLocalPath(orig_path);        this->CurChange.Path.assign(new_path);        this->Changes.push_back(this->CurChange);      } else if (!this->CData.empty() && name == "author") { -      this->Rev.Author.assign(&this->CData[0], this->CData.size()); +      this->Rev.Author.assign(this->CData.data(), this->CData.size());      } else if (!this->CData.empty() && name == "date") { -      this->Rev.Date.assign(&this->CData[0], this->CData.size()); +      this->Rev.Date.assign(this->CData.data(), this->CData.size());      } else if (!this->CData.empty() && name == "msg") { -      this->Rev.Log.assign(&this->CData[0], this->CData.size()); +      this->Rev.Log.assign(this->CData.data(), this->CData.size());      }      this->CData.clear();    } diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 16c0a0e..5a66f82 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -277,7 +277,7 @@ void cmCTestScriptHandler::CreateCMake()  int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)  {    // Reset the error flag so that the script is read in no matter what -  cmSystemTools::ResetErrorOccuredFlag(); +  cmSystemTools::ResetErrorOccurredFlag();    // if the argument has a , in it then it needs to be broken into the fist    // argument (which is the script) and the second argument which will be @@ -341,7 +341,7 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)    std::string systemFile =      this->Makefile->GetModulesFile("CTestScriptMode.cmake");    if (!this->Makefile->ReadListFile(systemFile) || -      cmSystemTools::GetErrorOccuredFlag()) { +      cmSystemTools::GetErrorOccurredFlag()) {      cmCTestLog(this->CTest, ERROR_MESSAGE,                 "Error in read:" << systemFile << "\n");      return 2; @@ -356,10 +356,10 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)    // finally read in the script    if (!this->Makefile->ReadListFile(script) || -      cmSystemTools::GetErrorOccuredFlag()) { +      cmSystemTools::GetErrorOccurredFlag()) {      // Reset the error flag so that it can run more than      // one script with an error when you use ctest_run_script. -    cmSystemTools::ResetErrorOccuredFlag(); +    cmSystemTools::ResetErrorOccurredFlag();      return 2;    } diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index fae5e30..da085a6 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -56,7 +56,7 @@ private:    {      std::string val;      if (!this->CurrentValue.empty()) { -      val.assign(&this->CurrentValue[0], this->CurrentValue.size()); +      val.assign(this->CurrentValue.data(), this->CurrentValue.size());      }      return val;    } @@ -124,7 +124,7 @@ void cmCTestSubmitHandler::Initialize()  {    // We submit all available parts by default.    for (cmCTest::Part p = cmCTest::PartStart; p != cmCTest::PartCount; -       p = cmCTest::Part(p + 1)) { +       p = static_cast<cmCTest::Part>(p + 1)) {      this->SubmitPart[p] = true;    }    this->HasWarnings = false; @@ -730,15 +730,15 @@ int cmCTestSubmitHandler::ProcessHandler()      return -1;    } -  if (getenv("HTTP_PROXY")) { +  if (char const* proxy = getenv("HTTP_PROXY")) {      this->HTTPProxyType = 1; -    this->HTTPProxy = getenv("HTTP_PROXY"); +    this->HTTPProxy = proxy;      if (getenv("HTTP_PROXY_PORT")) {        this->HTTPProxy += ":";        this->HTTPProxy += getenv("HTTP_PROXY_PORT");      } -    if (getenv("HTTP_PROXY_TYPE")) { -      std::string type = getenv("HTTP_PROXY_TYPE"); +    if (char const* proxy_type = getenv("HTTP_PROXY_TYPE")) { +      std::string type = proxy_type;        // HTTP/SOCKS4/SOCKS5        if (type == "HTTP") {          this->HTTPProxyType = 1; @@ -810,7 +810,7 @@ int cmCTestSubmitHandler::ProcessHandler()    // Query parts for files to submit.    for (cmCTest::Part p = cmCTest::PartStart; p != cmCTest::PartCount; -       p = cmCTest::Part(p + 1)) { +       p = static_cast<cmCTest::Part>(p + 1)) {      // Skip parts we are not submitting.      if (!this->SubmitPart[p]) {        continue; @@ -894,9 +894,8 @@ void cmCTestSubmitHandler::SelectParts(std::set<cmCTest::Part> const& parts)  {    // Check whether each part is selected.    for (cmCTest::Part p = cmCTest::PartStart; p != cmCTest::PartCount; -       p = cmCTest::Part(p + 1)) { -    this->SubmitPart[p] = -      (std::set<cmCTest::Part>::const_iterator(parts.find(p)) != parts.end()); +       p = static_cast<cmCTest::Part>(p + 1)) { +    this->SubmitPart[p] = parts.find(p) != parts.end();    }  } diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 5a3a8d0..daaf5fd 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,15 @@ 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) { +    if (!this->SetTestOutputTruncation(dval)) { +      cmCTestLog(this->CTest, ERROR_MESSAGE, +                 "Invalid value for CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION: " +                   << dval << std::endl); +    } +  }  }  int cmCTestTestHandler::PreProcessHandler() @@ -579,7 +590,8 @@ void cmCTestTestHandler::LogTestSummary(const std::vector<std::string>& passed,  {    std::size_t total = passed.size() + failed.size(); -  float percent = float(passed.size()) * 100.0f / float(total); +  float percent = +    static_cast<float>(passed.size()) * 100.0f / static_cast<float>(total);    if (!failed.empty() && percent > 99) {      percent = 99;    } @@ -1810,7 +1822,7 @@ bool cmCTestTestHandler::GetListOfTests()    if (!mf.ReadListFile(testFilename)) {      return false;    } -  if (cmSystemTools::GetErrorOccuredFlag()) { +  if (cmSystemTools::GetErrorOccurredFlag()) {      // SEND_ERROR or FATAL_ERROR in CTestTestfile or TEST_INCLUDE_FILES      return false;    } @@ -2076,6 +2088,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 +2120,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; +  }; + +  // 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(); -  // 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(); +  // 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 +2491,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/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index d5711c5..609ccba 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -66,7 +66,7 @@ bool cmCTestVC::InitialCheckout(const std::string& command)    this->Log << "--- Begin Initial Checkout ---\n";    OutputLogger out(this->Log, "co-out> ");    OutputLogger err(this->Log, "co-err> "); -  bool result = this->RunChild(&vc_co[0], &out, &err, parent.c_str()); +  bool result = this->RunChild(vc_co.data(), &out, &err, parent.c_str());    this->Log << "--- End Initial Checkout ---\n";    if (!result) {      cmCTestLog(this->CTest, ERROR_MESSAGE, diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake index f20572e..c88f5a3 100644 --- a/Source/Checks/cm_cxx_features.cmake +++ b/Source/Checks/cm_cxx_features.cmake @@ -48,7 +48,7 @@ function(cm_check_cxx_feature name)      # Filter out libhugetlbfs warnings.      string(REGEX REPLACE "[^\n]*libhugetlbfs [^\n]*: WARNING[^\n]*" "" check_output "${check_output}")      # Filter out xcodebuild warnings. -    string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\] warning: [^\n]*" "" check_output "${check_output}") +    string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\][^\n]*[Ww]arning: [^\n]*" "" check_output "${check_output}")      # Filter out icpc warnings      string(REGEX REPLACE "[^\n]*icpc: command line warning #10121: overriding [^\n]*" "" check_output "${check_output}")      # Filter out ld warnings. diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index 9b3a649..b14a751 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -43,7 +43,8 @@ void cmCursesLongMessageForm::UpdateContent(std::string const& output,    if (!output.empty() && this->Messages.size() < MAX_CONTENT_SIZE) {      this->Messages.push_back('\n');      this->Messages.append(output); -    form_driver(this->Form, REQ_NEW_LINE); +    form_driver(this->Form, REQ_NEXT_LINE); +    form_driver(this->Form, REQ_BEG_LINE);      this->DrawMessage(output.c_str());    } @@ -152,7 +153,8 @@ void cmCursesLongMessageForm::DrawMessage(const char* msg) const    int i = 0;    while (msg[i] != '\0' && i < MAX_CONTENT_SIZE) {      if (msg[i] == '\n' && msg[i + 1] != '\0') { -      form_driver(this->Form, REQ_NEW_LINE); +      form_driver(this->Form, REQ_NEXT_LINE); +      form_driver(this->Form, REQ_BEG_LINE);      } else {        form_driver(this->Form, msg[i]);      } @@ -191,9 +193,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/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 8381e86..a1b2149 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -494,21 +494,21 @@ int cmCursesMainForm::Configure(int noconfigure)    if (retVal != 0 || this->HasNonStatusOutputs) {      // see if there was an error -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        this->OkToGenerate = false;      }      int xx;      int yy;      getmaxyx(stdscr, yy, xx);      const char* title = "Configure produced the following output"; -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        title = "Configure failed with the following output";      }      cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(        this->Outputs, title,        cmCursesLongMessageForm::ScrollBehavior::ScrollDown);      // reset error condition -    cmSystemTools::ResetErrorOccuredFlag(); +    cmSystemTools::ResetErrorOccurredFlag();      CurrentForm = msgs;      msgs->Render(1, 1, xx, yy);      msgs->HandleInput(); @@ -547,16 +547,16 @@ int cmCursesMainForm::Generate()    if (retVal != 0 || this->HasNonStatusOutputs) {      // see if there was an error -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        this->OkToGenerate = false;      }      // reset error condition -    cmSystemTools::ResetErrorOccuredFlag(); +    cmSystemTools::ResetErrorOccurredFlag();      int xx;      int yy;      getmaxyx(stdscr, yy, xx);      const char* title = "Generate produced the following output"; -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        title = "Generate failed with the following output";      }      cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( @@ -617,7 +617,7 @@ void cmCursesMainForm::FillCacheManagerFromUI()      cmValue existingValue =        this->CMakeInstance->GetState()->GetCacheEntryValue(cacheKey);      if (existingValue) { -      std::string oldValue = *existingValue; +      std::string const& oldValue = *existingValue;        std::string newValue = entry.Entry->GetValue();        std::string fixedOldValue;        std::string fixedNewValue; @@ -973,7 +973,7 @@ void cmCursesMainForm::JumpToCacheEntry(const char* astr)          }        }      } -    if (size_t(findex) >= 3 * this->NumberOfVisibleEntries - 1) { +    if (static_cast<size_t>(findex) >= 3 * this->NumberOfVisibleEntries - 1) {        set_current_field(this->Form, this->Fields[2]);      } else if (new_page(this->Fields[findex + 1])) {        form_driver(this->Form, REQ_NEXT_PAGE); 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/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index c556049..fb12b7d 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -10,15 +10,6 @@  #include <QTranslator>  #include <QtPlugin> -// FIXME(#23565): Qt6 has QTextCodec in Core5Compat, but using its -// `setCodecForLocale` does not make cmake-gui support non-ASCII chars -// on Windows.  For now we only support them with Qt5.  How do we support -// them with Qt6, preferably without Core5Compat? -#if defined(Q_OS_WIN) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) -#  include <QTextCodec> -#  define CMAKE_HAVE_QTEXTCODEC -#endif -  #include "cmsys/CommandLineArguments.hxx"  #include "cmsys/Encoding.hxx"  #include "cmsys/SystemTools.hxx" @@ -133,11 +124,6 @@ int main(int argc, char** argv)    setlocale(LC_NUMERIC, "C"); -#ifdef CMAKE_HAVE_QTEXTCODEC -  QTextCodec* utf8_codec = QTextCodec::codecForName("UTF-8"); -  QTextCodec::setCodecForLocale(utf8_codec); -#endif -    // tell the cmake library where cmake is    QDir cmExecDir(QApplication::applicationDirPath());  #if defined(Q_OS_MAC) @@ -146,7 +132,7 @@ int main(int argc, char** argv)    // pick up translation files if they exists in the data directory    QDir translationsDir = cmExecDir; -  translationsDir.cd(QString::fromLocal8Bit(".." CMAKE_DATA_DIR)); +  translationsDir.cd(".." CMAKE_DATA_DIR);    translationsDir.cd("i18n");    QTranslator translator;    if (translator.load(QLocale(), "cmake", "_", translationsDir.path())) { @@ -185,8 +171,7 @@ int main(int argc, char** argv)          }        } -      sourceDirectory = -        cmSystemTools::CollapseFullPath(path.toLocal8Bit().data()); +      sourceDirectory = cmSystemTools::CollapseFullPath(path.toStdString());        cmSystemTools::ConvertToUnixSlashes(sourceDirectory);      } else if (arg.startsWith("-B")) {        QString path = arg.mid(2); @@ -203,8 +188,7 @@ int main(int argc, char** argv)          }        } -      binaryDirectory = -        cmSystemTools::CollapseFullPath(path.toLocal8Bit().data()); +      binaryDirectory = cmSystemTools::CollapseFullPath(path.toStdString());        cmSystemTools::ConvertToUnixSlashes(binaryDirectory);      } else if (arg.startsWith("--preset=")) {        QString preset = arg.mid(cmStrLen("--preset=")); @@ -212,7 +196,7 @@ int main(int argc, char** argv)          std::cerr << "No preset specified for --preset" << std::endl;          return 1;        } -      presetName = preset.toLocal8Bit().data(); +      presetName = preset.toStdString();      } else if (arg == "--browse-manual") {        OpenReferenceManual();        return 0; @@ -220,21 +204,20 @@ int main(int argc, char** argv)    }    if (!sourceDirectory.empty() &&        (!binaryDirectory.empty() || !presetName.empty())) { -    dialog.setSourceDirectory(QString::fromLocal8Bit(sourceDirectory.c_str())); +    dialog.setSourceDirectory(QString::fromStdString(sourceDirectory));      if (!binaryDirectory.empty()) { -      dialog.setBinaryDirectory( -        QString::fromLocal8Bit(binaryDirectory.c_str())); +      dialog.setBinaryDirectory(QString::fromStdString(binaryDirectory));        if (!presetName.empty()) {          dialog.setStartupBinaryDirectory(true);        }      }      if (!presetName.empty()) { -      dialog.setDeferredPreset(QString::fromLocal8Bit(presetName.c_str())); +      dialog.setDeferredPreset(QString::fromStdString(presetName));      }    } else {      if (args.count() == 2) {        std::string filePath = -        cmSystemTools::CollapseFullPath(args[1].toLocal8Bit().data()); +        cmSystemTools::CollapseFullPath(args[1].toStdString());        // check if argument is a directory containing CMakeCache.txt        std::string buildFilePath = cmStrCat(filePath, "/CMakeCache.txt"); @@ -249,12 +232,12 @@ int main(int argc, char** argv)        std::string srcFilePath = cmStrCat(filePath, "/CMakeLists.txt");        if (cmSystemTools::FileExists(buildFilePath.c_str())) { -        dialog.setBinaryDirectory(QString::fromLocal8Bit( -          cmSystemTools::GetFilenamePath(buildFilePath).c_str())); +        dialog.setBinaryDirectory(QString::fromStdString( +          cmSystemTools::GetFilenamePath(buildFilePath)));        } else if (cmSystemTools::FileExists(srcFilePath.c_str())) { -        dialog.setSourceDirectory(QString::fromLocal8Bit(filePath.c_str())); -        dialog.setBinaryDirectory(QString::fromLocal8Bit( -          cmSystemTools::CollapseFullPath(".").c_str())); +        dialog.setSourceDirectory(QString::fromStdString(filePath)); +        dialog.setBinaryDirectory( +          QString::fromStdString(cmSystemTools::CollapseFullPath(".")));        }      }    } diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index f90b781..01fa7bb 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -50,7 +50,7 @@ void OpenReferenceManual()    if (!cmSystemTools::GetHTMLDoc().empty()) {      url = QUrl::fromLocalFile( -      QDir(QString::fromLocal8Bit(cmSystemTools::GetHTMLDoc().data())) +      QDir(QString::fromStdString(cmSystemTools::GetHTMLDoc()))          .filePath("index.html"));    } @@ -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)); @@ -734,7 +735,7 @@ void CMakeSetupDialog::showPresetLoadError(  {    QMessageBox::warning(      this, "Error Reading CMake Presets", -    QString::fromLocal8Bit("Could not read presets from %1: %2") +    QString("Could not read presets from %1: %2")        .arg(dir, cmCMakePresetsGraph::ResultToString(result)));  } diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx index 10360bb..f3c4a8b 100644 --- a/Source/QtDialog/FirstConfigure.cxx +++ b/Source/QtDialog/FirstConfigure.cxx @@ -107,22 +107,21 @@ void StartCompilerSetup::setGenerators(    QStringList generator_list;    for (cmake::GeneratorInfo const& gen : gens) { -    generator_list.append(QString::fromLocal8Bit(gen.name.c_str())); +    generator_list.append(QString::fromStdString(gen.name));      if (gen.supportsPlatform) {        this->GeneratorsSupportingPlatform.append( -        QString::fromLocal8Bit(gen.name.c_str())); +        QString::fromStdString(gen.name)); -      this -        ->GeneratorDefaultPlatform[QString::fromLocal8Bit(gen.name.c_str())] = -        QString::fromLocal8Bit(gen.defaultPlatform.c_str()); +      this->GeneratorDefaultPlatform[QString::fromStdString(gen.name)] = +        QString::fromStdString(gen.defaultPlatform);        auto platformIt = gen.supportedPlatforms.cbegin();        while (platformIt != gen.supportedPlatforms.cend()) {          this->GeneratorSupportedPlatforms.insert( -          QString::fromLocal8Bit(gen.name.c_str()), -          QString::fromLocal8Bit((*platformIt).c_str())); +          QString::fromStdString(gen.name), +          QString::fromStdString((*platformIt)));          platformIt++;        } @@ -130,7 +129,7 @@ void StartCompilerSetup::setGenerators(      if (gen.supportsToolset) {        this->GeneratorsSupportingToolset.append( -        QString::fromLocal8Bit(gen.name.c_str())); +        QString::fromStdString(gen.name));      }    } diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index ffb6157..6b3cb9f 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -70,7 +70,7 @@ QCMake::QCMake(QObject* p)      this->loadPresets();      if (!this->PresetName.isEmpty() &&          this->CMakePresetsGraph.ConfigurePresets.find( -          std::string(this->PresetName.toLocal8Bit())) == +          std::string(this->PresetName.toStdString())) ==            this->CMakePresetsGraph.ConfigurePresets.end()) {        this->setPreset(QString{});      } @@ -87,8 +87,8 @@ void QCMake::loadCache(const QString& dir)  void QCMake::setSourceDirectory(const QString& _dir)  { -  QString dir = QString::fromLocal8Bit( -    cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str()); +  QString dir = QString::fromStdString( +    cmSystemTools::GetActualCaseForPath(_dir.toStdString()));    if (this->SourceDirectory != dir) {      this->SourceDirectory = QDir::fromNativeSeparators(dir);      emit this->sourceDirChanged(this->SourceDirectory); @@ -99,8 +99,8 @@ void QCMake::setSourceDirectory(const QString& _dir)  void QCMake::setBinaryDirectory(const QString& _dir)  { -  QString dir = QString::fromLocal8Bit( -    cmSystemTools::GetActualCaseForPath(_dir.toLocal8Bit().data()).c_str()); +  QString dir = QString::fromStdString( +    cmSystemTools::GetActualCaseForPath(_dir.toStdString()));    if (this->BinaryDirectory != dir) {      this->BinaryDirectory = QDir::fromNativeSeparators(dir);      emit this->binaryDirChanged(this->BinaryDirectory); @@ -108,8 +108,7 @@ void QCMake::setBinaryDirectory(const QString& _dir)      this->setGenerator(QString());      this->setToolset(QString());      this->setPlatform(QString()); -    if (!this->CMakeInstance->LoadCache( -          this->BinaryDirectory.toLocal8Bit().data())) { +    if (!this->CMakeInstance->LoadCache(this->BinaryDirectory.toStdString())) {        QDir testDir(this->BinaryDirectory);        if (testDir.exists("CMakeCache.txt")) {          cmSystemTools::Error( @@ -124,7 +123,7 @@ void QCMake::setBinaryDirectory(const QString& _dir)      emit this->propertiesChanged(props);      cmValue homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");      if (homeDir) { -      setSourceDirectory(QString::fromLocal8Bit(homeDir->c_str())); +      setSourceDirectory(QString(homeDir->c_str()));      }      cmValue gen = state->GetCacheEntryValue("CMAKE_GENERATOR");      if (gen) { @@ -133,17 +132,17 @@ void QCMake::setBinaryDirectory(const QString& _dir)        std::string curGen =          cmExternalMakefileProjectGenerator::CreateFullGeneratorName(*gen,                                                                      *extraGen); -      this->setGenerator(QString::fromLocal8Bit(curGen.c_str())); +      this->setGenerator(QString::fromStdString(curGen));      }      cmValue platform = state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM");      if (platform) { -      this->setPlatform(QString::fromLocal8Bit(platform->c_str())); +      this->setPlatform(QString(platform->c_str()));      }      cmValue toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");      if (toolset) { -      this->setToolset(QString::fromLocal8Bit(toolset->c_str())); +      this->setToolset(QString(toolset->c_str()));      }      checkOpenPossible(); @@ -157,13 +156,13 @@ void QCMake::setPreset(const QString& name, bool setBinary)      emit this->presetChanged(this->PresetName);      if (!name.isNull()) { -      std::string presetName(name.toLocal8Bit()); +      std::string presetName(name.toStdString());        auto const& expandedPreset =          this->CMakePresetsGraph.ConfigurePresets[presetName].Expanded;        if (expandedPreset) {          if (setBinary && !expandedPreset->BinaryDir.empty()) {            QString binaryDir = -            QString::fromLocal8Bit(expandedPreset->BinaryDir.data()); +            QString::fromStdString(expandedPreset->BinaryDir);            this->setBinaryDirectory(binaryDir);          }          if (expandedPreset->WarnDev) { @@ -190,8 +189,8 @@ void QCMake::setPreset(const QString& name, bool setBinary)          this->Environment = this->StartEnvironment;          for (auto const& v : expandedPreset->Environment) {            if (v.second) { -            this->Environment.insert(QString::fromLocal8Bit(v.first.data()), -                                     QString::fromLocal8Bit(v.second->data())); +            this->Environment.insert(QString::fromStdString(v.first), +                                     QString::fromStdString(v.second.value()));            }          }        } @@ -240,23 +239,20 @@ void QCMake::configure()      UINT lastErrorMode = SetErrorMode(0);  #endif -    this->CMakeInstance->SetHomeDirectory( -      this->SourceDirectory.toLocal8Bit().data()); +    this->CMakeInstance->SetHomeDirectory(this->SourceDirectory.toStdString());      this->CMakeInstance->SetHomeOutputDirectory( -      this->BinaryDirectory.toLocal8Bit().data()); +      this->BinaryDirectory.toStdString());      this->CMakeInstance->SetGlobalGenerator(        this->CMakeInstance->CreateGlobalGenerator( -        this->Generator.toLocal8Bit().data())); -    this->CMakeInstance->SetGeneratorPlatform( -      this->Platform.toLocal8Bit().data()); -    this->CMakeInstance->SetGeneratorToolset( -      this->Toolset.toLocal8Bit().data()); +        this->Generator.toStdString())); +    this->CMakeInstance->SetGeneratorPlatform(this->Platform.toStdString()); +    this->CMakeInstance->SetGeneratorToolset(this->Toolset.toStdString());      this->CMakeInstance->LoadCache();      this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode);      this->CMakeInstance->PreLoadCMakeFiles();      InterruptFlag = 0; -    cmSystemTools::ResetErrorOccuredFlag(); +    cmSystemTools::ResetErrorOccurredFlag();      err = this->CMakeInstance->Configure(); @@ -281,7 +277,7 @@ void QCMake::generate()  #endif      InterruptFlag = 0; -    cmSystemTools::ResetErrorOccuredFlag(); +    cmSystemTools::ResetErrorOccurredFlag();      err = this->CMakeInstance->Generate(); @@ -301,10 +297,10 @@ void QCMake::open()  #endif    InterruptFlag = 0; -  cmSystemTools::ResetErrorOccuredFlag(); +  cmSystemTools::ResetErrorOccurredFlag(); -  auto successful = this->CMakeInstance->Open( -    this->BinaryDirectory.toLocal8Bit().data(), false); +  auto successful = +    this->CMakeInstance->Open(this->BinaryDirectory.toStdString(), false);  #ifdef Q_OS_WIN    SetErrorMode(lastErrorMode); @@ -329,10 +325,10 @@ void QCMake::setProperties(const QCMakePropertyList& newProps)      }      QCMakeProperty prop; -    prop.Key = QString::fromLocal8Bit(key.c_str()); +    prop.Key = QString::fromStdString(key);      int idx = props.indexOf(prop);      if (idx == -1) { -      toremove.append(QString::fromLocal8Bit(key.c_str())); +      toremove.append(QString::fromStdString(key));      } else {        prop = props[idx];  #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) @@ -343,8 +339,7 @@ void QCMake::setProperties(const QCMakePropertyList& newProps)        if (isBool) {          state->SetCacheEntryValue(key, prop.Value.toBool() ? "ON" : "OFF");        } else { -        state->SetCacheEntryValue(key, -                                  prop.Value.toString().toLocal8Bit().data()); +        state->SetCacheEntryValue(key, prop.Value.toString().toStdString());        }        props.removeAt(idx);      } @@ -352,35 +347,35 @@ void QCMake::setProperties(const QCMakePropertyList& newProps)    // remove some properties    foreach (QString const& s, toremove) { -    this->CMakeInstance->UnwatchUnusedCli(s.toLocal8Bit().data()); +    this->CMakeInstance->UnwatchUnusedCli(s.toStdString()); -    state->RemoveCacheEntry(s.toLocal8Bit().data()); +    state->RemoveCacheEntry(s.toStdString());    }    // add some new properties    foreach (QCMakeProperty const& s, props) { -    this->CMakeInstance->WatchUnusedCli(s.Key.toLocal8Bit().data()); +    this->CMakeInstance->WatchUnusedCli(s.Key.toStdString());      if (s.Type == QCMakeProperty::BOOL) {        this->CMakeInstance->AddCacheEntry( -        s.Key.toLocal8Bit().data(), s.Value.toBool() ? "ON" : "OFF", -        s.Help.toLocal8Bit().data(), cmStateEnums::BOOL); +        s.Key.toStdString(), s.Value.toBool() ? "ON" : "OFF", +        s.Help.toStdString().c_str(), cmStateEnums::BOOL);      } else if (s.Type == QCMakeProperty::STRING) {        this->CMakeInstance->AddCacheEntry( -        s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(), -        s.Help.toLocal8Bit().data(), cmStateEnums::STRING); +        s.Key.toStdString(), s.Value.toString().toStdString(), +        s.Help.toStdString().c_str(), cmStateEnums::STRING);      } else if (s.Type == QCMakeProperty::PATH) {        this->CMakeInstance->AddCacheEntry( -        s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(), -        s.Help.toLocal8Bit().data(), cmStateEnums::PATH); +        s.Key.toStdString(), s.Value.toString().toStdString(), +        s.Help.toStdString().c_str(), cmStateEnums::PATH);      } else if (s.Type == QCMakeProperty::FILEPATH) {        this->CMakeInstance->AddCacheEntry( -        s.Key.toLocal8Bit().data(), s.Value.toString().toLocal8Bit().data(), -        s.Help.toLocal8Bit().data(), cmStateEnums::FILEPATH); +        s.Key.toStdString(), s.Value.toString().toStdString(), +        s.Help.toStdString().c_str(), cmStateEnums::FILEPATH);      }    } -  this->CMakeInstance->SaveCache(this->BinaryDirectory.toLocal8Bit().data()); +  this->CMakeInstance->SaveCache(this->BinaryDirectory.toStdString());  }  QCMakePropertyList QCMake::properties() const @@ -399,11 +394,11 @@ QCMakePropertyList QCMake::properties() const      cmValue cachedValue = state->GetCacheEntryValue(key);      QCMakeProperty prop; -    prop.Key = QString::fromLocal8Bit(key.c_str()); +    prop.Key = QString::fromStdString(key);      if (cmValue hs = state->GetCacheEntryProperty(key, "HELPSTRING")) { -      prop.Help = QString::fromLocal8Bit(hs->c_str()); +      prop.Help = QString(hs->c_str());      } -    prop.Value = QString::fromLocal8Bit(cachedValue->c_str()); +    prop.Value = QString(cachedValue->c_str());      prop.Advanced = state->GetCacheEntryPropertyAsBool(key, "ADVANCED");      if (t == cmStateEnums::BOOL) {        prop.Type = QCMakeProperty::BOOL; @@ -416,8 +411,7 @@ QCMakePropertyList QCMake::properties() const        prop.Type = QCMakeProperty::STRING;        cmValue stringsProperty = state->GetCacheEntryProperty(key, "STRINGS");        if (stringsProperty) { -        prop.Strings = -          QString::fromLocal8Bit(stringsProperty->c_str()).split(";"); +        prop.Strings = QString(stringsProperty->c_str()).split(";");        }      } @@ -425,7 +419,7 @@ QCMakePropertyList QCMake::properties() const    }    if (!this->PresetName.isNull()) { -    std::string presetName(this->PresetName.toLocal8Bit()); +    std::string presetName(this->PresetName.toStdString());      auto const& p =        this->CMakePresetsGraph.ConfigurePresets.at(presetName).Expanded;      if (p) { @@ -434,8 +428,8 @@ QCMakePropertyList QCMake::properties() const            continue;          }          QCMakeProperty prop; -        prop.Key = QString::fromLocal8Bit(v.first.data()); -        prop.Value = QString::fromLocal8Bit(v.second->Value.data()); +        prop.Key = QString::fromStdString(v.first); +        prop.Value = QString::fromStdString(v.second->Value);          prop.Type = QCMakeProperty::STRING;          if (!v.second->Type.empty()) {            auto type = cmState::StringToCacheEntryType(v.second->Type); @@ -523,18 +517,18 @@ void QCMake::setUpEnvironment() const  {    auto env = QProcessEnvironment::systemEnvironment();    for (auto const& key : env.keys()) { -    cmSystemTools::UnsetEnv(key.toLocal8Bit().data()); +    cmSystemTools::UnsetEnv(key.toStdString().c_str());    }    for (auto const& var : this->Environment.toStringList()) { -    cmSystemTools::PutEnv(var.toLocal8Bit().data()); +    cmSystemTools::PutEnv(var.toStdString());    }  }  void QCMake::loadPresets()  {    auto result = this->CMakePresetsGraph.ReadProjectPresets( -    this->SourceDirectory.toLocal8Bit().data(), true); +    this->SourceDirectory.toStdString(), true);    if (result != this->LastLoadPresetsResult &&        result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {      emit this->presetLoadError(this->SourceDirectory, result); @@ -550,14 +544,14 @@ void QCMake::loadPresets()      }      QCMakePreset preset; -    preset.name = QString::fromLocal8Bit(p.Name.data()); -    preset.displayName = QString::fromLocal8Bit(p.DisplayName.data()); -    preset.description = QString::fromLocal8Bit(p.Description.data()); -    preset.generator = QString::fromLocal8Bit(p.Generator.data()); -    preset.architecture = QString::fromLocal8Bit(p.Architecture.data()); +    preset.name = QString::fromStdString(p.Name); +    preset.displayName = QString::fromStdString(p.DisplayName); +    preset.description = QString::fromStdString(p.Description); +    preset.generator = QString::fromStdString(p.Generator); +    preset.architecture = QString::fromStdString(p.Architecture);      preset.setArchitecture = !p.ArchitectureStrategy ||        p.ArchitectureStrategy == cmCMakePresetsGraph::ArchToolsetStrategy::Set; -    preset.toolset = QString::fromLocal8Bit(p.Toolset.data()); +    preset.toolset = QString::fromStdString(p.Toolset);      preset.setToolset = !p.ToolsetStrategy ||        p.ToolsetStrategy == cmCMakePresetsGraph::ArchToolsetStrategy::Set;      preset.enabled = it.Expanded && it.Expanded->ConditionResult && @@ -599,9 +593,9 @@ std::vector<cmake::GeneratorInfo> const& QCMake::availableGenerators() const  void QCMake::deleteCache()  {    // delete cache -  this->CMakeInstance->DeleteCache(this->BinaryDirectory.toLocal8Bit().data()); +  this->CMakeInstance->DeleteCache(this->BinaryDirectory.toStdString());    // reload to make our cache empty -  this->CMakeInstance->LoadCache(this->BinaryDirectory.toLocal8Bit().data()); +  this->CMakeInstance->LoadCache(this->BinaryDirectory.toStdString());    // emit no generator and no properties    this->setGenerator(QString());    this->setToolset(QString()); @@ -615,7 +609,7 @@ void QCMake::reloadCache()    QCMakePropertyList props;    emit this->propertiesChanged(props);    // reload -  this->CMakeInstance->LoadCache(this->BinaryDirectory.toLocal8Bit().data()); +  this->CMakeInstance->LoadCache(this->BinaryDirectory.toStdString());    // emit new cache properties    props = this->properties();    emit this->propertiesChanged(props); @@ -681,7 +675,7 @@ void QCMake::setWarnUninitializedMode(bool value)  void QCMake::checkOpenPossible()  { -  std::string data = this->BinaryDirectory.toLocal8Bit().data(); +  std::string data = this->BinaryDirectory.toStdString();    auto possible = this->CMakeInstance->Open(data, true);    emit openPossible(possible);  } diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx index 994df78..f79d6fc 100644 --- a/Source/QtDialog/QCMakeCacheView.cxx +++ b/Source/QtDialog/QCMakeCacheView.cxx @@ -66,7 +66,6 @@ class QCMakeAdvancedFilter : public QSortFilterProxyModel  public:    QCMakeAdvancedFilter(QObject* o)      : QSortFilterProxyModel(o) -    , ShowAdvanced(false)    {    } @@ -78,7 +77,7 @@ public:    bool showAdvanced() const { return this->ShowAdvanced; }  protected: -  bool ShowAdvanced; +  bool ShowAdvanced = false;    bool filterAcceptsRow(int row, const QModelIndex& p) const override    { @@ -304,7 +303,7 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)        int num = props2.size();        for (int i = 0; i < num; i++) { -        QCMakeProperty prop = props2[i]; +        QCMakeProperty const& prop = props2[i];          QList<QStandardItem*> items;          items.append(new QStandardItem());          items.append(new QStandardItem()); @@ -326,7 +325,7 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)        int num = props2.size();        for (int i = 0; i < num; i++) { -        QCMakeProperty prop = props2[i]; +        QCMakeProperty const& prop = props2[i];          QList<QStandardItem*> items;          items.append(new QStandardItem());          items.append(new QStandardItem()); diff --git a/Source/QtDialog/QCMakePresetItemModel.cxx b/Source/QtDialog/QCMakePresetItemModel.cxx index 00a4e18..7ada2a5 100644 --- a/Source/QtDialog/QCMakePresetItemModel.cxx +++ b/Source/QtDialog/QCMakePresetItemModel.cxx @@ -17,12 +17,12 @@ QVariant QCMakePresetItemModel::data(const QModelIndex& index, int role) const        // AccessibleDescriptionRole. This was determined by looking at        // QComboBoxDelegate::isSeparator() (located in qcombobox_p.h.)        if (index.internalId() == SEPARATOR_INDEX) { -        return QString::fromLocal8Bit("separator"); +        return QString("separator");        }        return QString{};      case Qt::DisplayRole: {        if (index.internalId() == CUSTOM_INDEX) { -        return QString::fromLocal8Bit("<custom>"); +        return QString("<custom>");        }        if (index.internalId() == SEPARATOR_INDEX) {          return QVariant{}; @@ -32,7 +32,7 @@ QVariant QCMakePresetItemModel::data(const QModelIndex& index, int role) const      }      case Qt::ToolTipRole:        if (index.internalId() == CUSTOM_INDEX) { -        return QString::fromLocal8Bit("Specify all settings manually"); +        return QString("Specify all settings manually");        }        if (index.internalId() == SEPARATOR_INDEX) {          return QVariant{}; 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..f29983c 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -92,9 +92,21 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,    : Stream(os)    , Archive(archive_write_new())    , Disk(archive_read_disk_new()) -  , 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 +162,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 +187,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/cmArchiveWrite.h b/Source/cmArchiveWrite.h index 260bd20..b9fa3d7 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -156,7 +156,7 @@ private:    std::ostream& Stream;    struct archive* Archive;    struct archive* Disk; -  bool Verbose; +  bool Verbose = false;    std::string Format;    std::string Error;    std::string MTime; diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 3922c56..0750eea 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" @@ -335,7 +338,7 @@ std::map<std::string, std::string> GetOSReleaseVariables(      // include FATAL_ERROR and ERROR in the return status      if (!makefile.ReadListFile(script) || -        cmSystemTools::GetErrorOccuredFlag()) { +        cmSystemTools::GetErrorOccurredFlag()) {        // Ok, no worries... go try the next script.        continue;      } @@ -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..a2aaa2a 100644 --- a/Source/cmCMakeLanguageCommand.cxx +++ b/Source/cmCMakeLanguageCommand.cxx @@ -13,11 +13,14 @@  #include <cm/string_view>  #include <cmext/string_view> +#include "cmArgumentParser.h" +#include "cmDependencyProvider.h"  #include "cmExecutionStatus.h"  #include "cmGlobalGenerator.h"  #include "cmListFileCache.h"  #include "cmMakefile.h"  #include "cmRange.h" +#include "cmState.h"  #include "cmStringAlgorithms.h"  #include "cmSystemTools.h" @@ -26,7 +29,7 @@ namespace {  bool FatalError(cmExecutionStatus& status, std::string const& error)  {    status.SetError(error); -  cmSystemTools::SetFatalErrorOccured(); +  cmSystemTools::SetFatalErrorOccurred();    return false;  } @@ -84,7 +87,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()) { @@ -214,6 +218,91 @@ bool cmCMakeLanguageCommandEVAL(std::vector<cmListFileArgument> const& args,    return makefile.ReadListFileAsString(      code, cmStrCat(context.FilePath, ":", context.Line, ":EVAL"));  } + +bool cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER( +  std::vector<std::string> const& args, cmExecutionStatus& status) +{ +  cmState* state = status.GetMakefile().GetState(); +  if (!state->InTopLevelIncludes()) { +    return FatalError( +      status, +      "Dependency providers can only be set as part of the first call to " +      "project(). More specifically, cmake_language(SET_DEPENDENCY_PROVIDER) " +      "can only be called while the first project() command processes files " +      "listed in CMAKE_PROJECT_TOP_LEVEL_INCLUDES."); +  } + +  struct SetProviderArgs +  { +    std::string Command; +    std::vector<std::string> Methods; +  }; + +  auto const ArgsParser = +    cmArgumentParser<SetProviderArgs>() +      .Bind("SET_DEPENDENCY_PROVIDER"_s, &SetProviderArgs::Command) +      .Bind("SUPPORTED_METHODS"_s, &SetProviderArgs::Methods); + +  std::vector<std::string> unparsed; +  auto parsedArgs = ArgsParser.Parse(args, &unparsed); + +  if (!unparsed.empty()) { +    return FatalError( +      status, cmStrCat("Unrecognized keyword: \"", unparsed.front(), "\"")); +  } + +  // We store the command that FetchContent_MakeAvailable() can call in a +  // global (but considered internal) property. If the provider doesn't +  // support this method, we set this property to an empty string instead. +  // This simplifies the logic in FetchContent_MakeAvailable() and doesn't +  // require us to define a new internal command or sub-command. +  std::string fcmasProperty = "__FETCHCONTENT_MAKEAVAILABLE_SERIAL_PROVIDER"; + +  if (parsedArgs.Command.empty()) { +    if (!parsedArgs.Methods.empty()) { +      return FatalError(status, +                        "Must specify a non-empty command name when provider " +                        "methods are given"); +    } +    state->ClearDependencyProvider(); +    state->SetGlobalProperty(fcmasProperty, ""); +    return true; +  } + +  cmState::Command command = state->GetCommand(parsedArgs.Command); +  if (!command) { +    return FatalError(status, +                      cmStrCat("Command \"", parsedArgs.Command, +                               "\" is not a defined command")); +  } + +  if (parsedArgs.Methods.empty()) { +    return FatalError(status, "Must specify at least one provider method"); +  } + +  bool supportsFetchContentMakeAvailableSerial = false; +  std::vector<cmDependencyProvider::Method> methods; +  for (auto const& method : parsedArgs.Methods) { +    if (method == "FIND_PACKAGE") { +      methods.emplace_back(cmDependencyProvider::Method::FindPackage); +    } else if (method == "FETCHCONTENT_MAKEAVAILABLE_SERIAL") { +      supportsFetchContentMakeAvailableSerial = true; +      methods.emplace_back( +        cmDependencyProvider::Method::FetchContentMakeAvailableSerial); +    } else { +      return FatalError( +        status, +        cmStrCat("Unknown dependency provider method \"", method, "\"")); +    } +  } + +  state->SetDependencyProvider({ parsedArgs.Command, methods }); +  state->SetGlobalProperty( +    fcmasProperty, +    supportsFetchContentMakeAvailableSerial ? parsedArgs.Command.c_str() : ""); + +  return true; +}  }  bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args, @@ -245,6 +334,11 @@ bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,      return FatalError(status, "called with incorrect number of arguments");    } +  if (expArgs[expArg] == "SET_DEPENDENCY_PROVIDER"_s) { +    finishArgs(); +    return cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER(expArgs, status); +  } +    cm::optional<Defer> maybeDefer;    if (expArgs[expArg] == "DEFER"_s) {      ++expArg; // Consume "DEFER". diff --git a/Source/cmCMakeMinimumRequired.cxx b/Source/cmCMakeMinimumRequired.cxx index 1b03873..c6a0c9a 100644 --- a/Source/cmCMakeMinimumRequired.cxx +++ b/Source/cmCMakeMinimumRequired.cxx @@ -103,7 +103,7 @@ bool cmCMakeMinimumRequired(std::vector<std::string> const& args,        << " or higher is required.  You are running version "        << cmVersion::GetCMakeVersion();      status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return true;    } 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..66507a7 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -322,7 +322,7 @@ std::string cmCTest::DecodeURL(const std::string& in)    for (const char* c = in.c_str(); *c; ++c) {      if (*c == '%' && isxdigit(*(c + 1)) && isxdigit(*(c + 2))) {        char buf[3] = { *(c + 1), *(c + 2), 0 }; -      out.append(1, char(strtoul(buf, nullptr, 16))); +      out.append(1, static_cast<char>(strtoul(buf, nullptr, 16)));        c += 2;      } else {        out.append(1, *c); @@ -357,7 +357,7 @@ cmCTest::cmCTest()    this->Impl->Parts[PartDone].SetName("Done");    // Fill the part name-to-id map. -  for (Part p = PartStart; p != PartCount; p = Part(p + 1)) { +  for (Part p = PartStart; p != PartCount; p = static_cast<Part>(p + 1)) {      this->Impl        ->PartMap[cmSystemTools::LowerCase(this->Impl->Parts[p].GetName())] = p;    } @@ -643,7 +643,7 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)    std::string src_dir = this->GetCTestConfiguration("SourceDirectory");    std::string bld_dir = this->GetCTestConfiguration("BuildDirectory");    this->Impl->BuildID = ""; -  for (Part p = PartStart; p != PartCount; p = Part(p + 1)) { +  for (Part p = PartStart; p != PartCount; p = static_cast<Part>(p + 1)) {      this->Impl->Parts[p].SubmitFiles.clear();    } @@ -797,7 +797,7 @@ int cmCTest::GetTestModel() const  bool cmCTest::SetTest(const std::string& ttype, bool report)  {    if (cmSystemTools::LowerCase(ttype) == "all") { -    for (Part p = PartStart; p != PartCount; p = Part(p + 1)) { +    for (Part p = PartStart; p != PartCount; p = static_cast<Part>(p + 1)) {        this->Impl->Parts[p].Enable();      }      return true; @@ -935,7 +935,8 @@ int cmCTest::ProcessSteps()    bool notest = true;    int update_count = 0; -  for (Part p = PartStart; notest && p != PartCount; p = Part(p + 1)) { +  for (Part p = PartStart; notest && p != PartCount; +       p = static_cast<Part>(p + 1)) {      notest = !this->Impl->Parts[p];    }    if (this->Impl->Parts[PartUpdate] && @@ -1390,7 +1391,7 @@ void cmCTest::StartXML(cmXMLWriter& xml, bool append)                 "Current Tag empty, this may mean"                 " NightlStartTime was not set correctly."                   << std::endl); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();    }    // find out about the system @@ -1672,16 +1673,16 @@ std::string cmCTest::Base64EncodeFile(std::string const& file)  #endif    );    std::vector<char> file_buffer(len + 1); -  ifs.read(&file_buffer[0], len); +  ifs.read(file_buffer.data(), len);    ifs.close();    std::vector<char> encoded_buffer((len * 3) / 2 + 5);    size_t const rlen = cmsysBase64_Encode( -    reinterpret_cast<unsigned char*>(&file_buffer[0]), len, -    reinterpret_cast<unsigned char*>(&encoded_buffer[0]), 1); +    reinterpret_cast<unsigned char*>(file_buffer.data()), len, +    reinterpret_cast<unsigned char*>(encoded_buffer.data()), 1); -  return std::string(&encoded_buffer[0], rlen); +  return std::string(encoded_buffer.data(), rlen);  }  bool cmCTest::SubmitExtraFiles(std::vector<std::string> const& files) @@ -2019,7 +2020,8 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,      i++;      long outputSize;      if (cmStrToLong(args[i], &outputSize)) { -      this->Impl->TestHandler.SetTestOutputSizePassed(int(outputSize)); +      this->Impl->TestHandler.SetTestOutputSizePassed( +        static_cast<int>(outputSize));      } else {        cmCTestLog(this, WARNING,                   "Invalid value for '--test-output-size-passed': " << args[i] @@ -2030,12 +2032,20 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,      i++;      long outputSize;      if (cmStrToLong(args[i], &outputSize)) { -      this->Impl->TestHandler.SetTestOutputSizeFailed(int(outputSize)); +      this->Impl->TestHandler.SetTestOutputSizeFailed( +        static_cast<int>(outputSize));      } else {        cmCTestLog(this, WARNING,                   "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 +2474,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;      } @@ -2789,7 +2804,7 @@ bool cmCTest::HandleTestActionArgument(const char* ctestExec, size_t& i,                                         const std::vector<std::string>& args)  {    bool success = true; -  std::string arg = args[i]; +  std::string const& arg = args[i];    if (this->CheckArgument(arg, "-T"_s, "--test-action") &&        (i < args.size() - 1)) {      this->Impl->ProduceXML = true; @@ -2821,7 +2836,7 @@ bool cmCTest::HandleTestModelArgument(const char* ctestExec, size_t& i,                                        const std::vector<std::string>& args)  {    bool success = true; -  std::string arg = args[i]; +  std::string const& arg = args[i];    if (this->CheckArgument(arg, "-M"_s, "--test-model") &&        (i < args.size() - 1)) {      i++; @@ -3007,17 +3022,17 @@ int cmCTest::ReadCustomConfigurationFileTree(const std::string& dir,      cmCTestLog(this, DEBUG,                 "* Read custom CTest configuration file: " << fname                                                            << std::endl); -    bool erroroc = cmSystemTools::GetErrorOccuredFlag(); -    cmSystemTools::ResetErrorOccuredFlag(); +    bool erroroc = cmSystemTools::GetErrorOccurredFlag(); +    cmSystemTools::ResetErrorOccurredFlag(); -    if (!mf->ReadListFile(fname) || cmSystemTools::GetErrorOccuredFlag()) { +    if (!mf->ReadListFile(fname) || cmSystemTools::GetErrorOccurredFlag()) {        cmCTestLog(this, ERROR_MESSAGE,                   "Problem reading custom configuration: " << fname                                                            << std::endl);      }      found = true;      if (erroroc) { -      cmSystemTools::SetErrorOccured(); +      cmSystemTools::SetErrorOccurred();      }    } @@ -3032,7 +3047,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const std::string& dir,        cmCTestLog(this, DEBUG,                   "* Read custom CTest configuration file: " << file                                                              << std::endl); -      if (!mf->ReadListFile(file) || cmSystemTools::GetErrorOccuredFlag()) { +      if (!mf->ReadListFile(file) || cmSystemTools::GetErrorOccurredFlag()) {          cmCTestLog(this, ERROR_MESSAGE,                     "Problem reading custom configuration: " << file                                                              << std::endl); @@ -3646,7 +3661,7 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg,          cmCTestLogOutputFileLine(err);          err << msg;          err.flush(); -        cmSystemTools::SetErrorOccured(); +        cmSystemTools::SetErrorOccurred();          break;        default:          cmCTestLogOutputFileLine(out); @@ -3717,7 +3732,7 @@ bool cmCTest::CompressString(std::string& str)    strm.avail_in = static_cast<uInt>(str.size());    strm.next_in = in;    strm.avail_out = outSize; -  strm.next_out = &out[0]; +  strm.next_out = out.data();    ret = deflate(&strm, Z_FINISH);    if (ret != Z_STREAM_END) { @@ -3731,10 +3746,10 @@ bool cmCTest::CompressString(std::string& str)    // Now base64 encode the resulting binary string    std::vector<unsigned char> base64EncodedBuffer((outSize * 3) / 2); -  size_t rlen = -    cmsysBase64_Encode(&out[0], strm.total_out, &base64EncodedBuffer[0], 1); +  size_t rlen = cmsysBase64_Encode(out.data(), strm.total_out, +                                   base64EncodedBuffer.data(), 1); -  str.assign(reinterpret_cast<char*>(&base64EncodedBuffer[0]), rlen); +  str.assign(reinterpret_cast<char*>(base64EncodedBuffer.data()), rlen);    return true;  } 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..ba95168 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -2,20 +2,21 @@     file Copyright.txt or https://cmake.org/licensing for details.  */  #include "cmCommonTargetGenerator.h" -#include <set> +#include <algorithm>  #include <sstream>  #include <utility>  #include "cmComputeLinkInformation.h"  #include "cmGeneratorTarget.h"  #include "cmGlobalCommonGenerator.h" -#include "cmLinkLineComputer.h"  #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" @@ -45,33 +46,6 @@ cmValue cmCommonTargetGenerator::GetFeature(const std::string& feature,    return this->GeneratorTarget->GetFeature(feature, config);  } -void cmCommonTargetGenerator::AddModuleDefinitionFlag( -  cmLinkLineComputer* linkLineComputer, std::string& flags, -  const std::string& config) -{ -  cmGeneratorTarget::ModuleDefinitionInfo const* mdi = -    this->GeneratorTarget->GetModuleDefinitionInfo(config); -  if (!mdi || mdi->DefFile.empty()) { -    return; -  } - -  // TODO: Create a per-language flag variable. -  cmValue defFileFlag = -    this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG"); -  if (!defFileFlag) { -    return; -  } - -  // Append the flag and value.  Use ConvertToLinkReference to help -  // vs6's "cl -link" pass it to the linker. -  std::string flag = -    cmStrCat(*defFileFlag, -             this->LocalCommonGenerator->ConvertToOutputFormat( -               linkLineComputer->ConvertToLinkReference(mdi->DefFile), -               cmOutputConverter::SHELL)); -  this->LocalCommonGenerator->AppendFlags(flags, flag); -} -  void cmCommonTargetGenerator::AppendFortranFormatFlags(    std::string& flags, cmSourceFile const& source)  { @@ -321,3 +295,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..e8c5a19 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> @@ -12,7 +13,6 @@  class cmGeneratorTarget;  class cmGlobalCommonGenerator; -class cmLinkLineComputer;  class cmLocalCommonGenerator;  class cmMakefile;  class cmSourceFile; @@ -32,10 +32,6 @@ protected:    // Feature query methods.    cmValue GetFeature(const std::string& feature, const std::string& config); -  // Helper to add flag for windows .def file. -  void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer, -                               std::string& flags, const std::string& config); -    cmGeneratorTarget* GeneratorTarget;    cmMakefile* Makefile;    cmLocalCommonGenerator* LocalCommonGenerator; @@ -74,6 +70,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..cda70fc 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,33 @@ 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>") }); +  } +  // To link framewortk using a full path +  this->LibraryFeatureDescriptors.emplace( +    "__CMAKE_LINK_FRAMEWORK", +    LibraryFeatureDescriptor{ "__CMAKE_LINK_FRAMEWORK", "<LIBRARY>" }); +    // Check the platform policy for missing soname case.    this->NoSONameUsesPath =      this->Makefile->IsOn("CMAKE_PLATFORM_USES_PATH_WHEN_NO_SONAME"); @@ -409,6 +438,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 +543,78 @@ 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) { +        if (linkEntry.Item.Value == "</LINK_GROUP>" && +            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); +          } +          currentFeature = nullptr; +        } +        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 +670,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 +1075,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 +1090,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 +1104,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 +1123,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 +1171,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 +1182,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 +1247,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 +1529,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 +1537,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 +1552,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 +1564,54 @@ 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()) { +    // 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() +               ? "__CMAKE_LINK_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 +1623,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 +1654,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 +1676,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 +1685,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 +1695,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 +1716,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 +1737,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 +1825,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 +1846,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 +1861,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 +1900,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 +1923,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 +1932,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 +1979,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 +2327,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/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 8e479c5..5de012a 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -16,6 +16,7 @@  #include "cmsys/RegularExpression.hxx" +#include "cmCMakePath.h"  #include "cmExpandedCommandArgument.h"  #include "cmMakefile.h"  #include "cmMessageType.h" @@ -58,6 +59,7 @@ auto const keyVERSION_GREATER = "VERSION_GREATER"_s;  auto const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"_s;  auto const keyVERSION_LESS = "VERSION_LESS"_s;  auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s; +auto const keyPATH_EQUAL = "PATH_EQUAL"_s;  cmSystemTools::CompareOp const MATCH2CMPOP[5] = {    cmSystemTools::OP_LESS, cmSystemTools::OP_LESS_EQUAL, @@ -95,7 +97,8 @@ struct cmRt2CtSelector<Comp>  std::string bool2string(bool const value)  { -  return std::string(std::size_t(1), static_cast<char>('0' + int(value))); +  return std::string(static_cast<std::size_t>(1), +                     static_cast<char>('0' + static_cast<int>(value)));  }  bool looksLikeSpecialVariable(const std::string& var, @@ -141,15 +144,17 @@ public:      {        this->current = std::next(this->current);        this->next = -        std::next(this->current, difference_type(this->current != args.end())); +        std::next(this->current, +                  static_cast<difference_type>(this->current != args.end()));        return *this;      }    private:      CurrentAndNextIter(base_t& args)        : current(args.begin()) -      , next(std::next(this->current, -                       difference_type(this->current != args.end()))) +      , next( +          std::next(this->current, +                    static_cast<difference_type>(this->current != args.end())))      {      }    }; @@ -167,19 +172,21 @@ public:      {        this->current = std::next(this->current);        this->next = -        std::next(this->current, difference_type(this->current != args.end())); -      this->nextnext = -        std::next(this->next, difference_type(this->next != args.end())); +        std::next(this->current, +                  static_cast<difference_type>(this->current != args.end())); +      this->nextnext = std::next( +        this->next, static_cast<difference_type>(this->next != args.end()));        return *this;      }    private:      CurrentAndTwoMoreIter(base_t& args)        : current(args.begin()) -      , next(std::next(this->current, -                       difference_type(this->current != args.end()))) -      , nextnext( -          std::next(this->next, difference_type(this->next != args.end()))) +      , next( +          std::next(this->current, +                    static_cast<difference_type>(this->current != args.end()))) +      , nextnext(std::next( +          this->next, static_cast<difference_type>(this->next != args.end())))      {      }    }; @@ -212,6 +219,7 @@ cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile,    , Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054))    , Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057))    , Policy64Status(makefile.GetPolicyStatus(cmPolicies::CMP0064)) +  , Policy139Status(makefile.GetPolicyStatus(cmPolicies::CMP0139))  {  } @@ -526,9 +534,6 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,  bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,                                          MessageType&)  { -  const auto policy64IsOld = this->Policy64Status == cmPolicies::OLD || -    this->Policy64Status == cmPolicies::WARN; -    for (auto args = newArgs.make2ArgsIterator(); args.current != newArgs.end();         args.advance(newArgs)) { @@ -580,7 +585,8 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,      // does a command exist      else if (this->IsKeyword(keyCOMMAND, *args.current)) {        newArgs.ReduceOneArg( -        bool(this->Makefile.GetState()->GetCommand(args.next->GetValue())), +        static_cast<bool>( +          this->Makefile.GetState()->GetCommand(args.next->GetValue())),          args);      }      // does a policy exist @@ -591,8 +597,9 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,      }      // does a target exist      else if (this->IsKeyword(keyTARGET, *args.current)) { -      newArgs.ReduceOneArg( -        bool(this->Makefile.FindTargetToUse(args.next->GetValue())), args); +      newArgs.ReduceOneArg(static_cast<bool>(this->Makefile.FindTargetToUse( +                             args.next->GetValue())), +                           args);      }      // is a variable defined      else if (this->IsKeyword(keyDEFINED, *args.current)) { @@ -607,7 +614,8 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,        else if (looksLikeSpecialVariable(var, "CACHE"_s, varNameLen)) {          const auto cache = args.next->GetValue().substr(6, varNameLen - 7); -        result = bool(this->Makefile.GetState()->GetCacheEntryValue(cache)); +        result = static_cast<bool>( +          this->Makefile.GetState()->GetCacheEntryValue(cache));        }        else { @@ -617,11 +625,13 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,      }      // does a test exist      else if (this->IsKeyword(keyTEST, *args.current)) { -      if (policy64IsOld) { +      if (this->Policy64Status == cmPolicies::OLD || +          this->Policy64Status == cmPolicies::WARN) {          continue;        } -      newArgs.ReduceOneArg(bool(this->Makefile.GetTest(args.next->GetValue())), -                           args); +      newArgs.ReduceOneArg( +        static_cast<bool>(this->Makefile.GetTest(args.next->GetValue())), +        args);      }    }    return true; @@ -768,6 +778,29 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,          this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());        }      } + +    else if (this->IsKeyword(keyPATH_EQUAL, *args.next)) { + +      if (this->Policy139Status != cmPolicies::OLD && +          this->Policy139Status != cmPolicies::WARN) { + +        cmValue lhs = this->GetVariableOrString(*args.current); +        cmValue rhs = this->GetVariableOrString(*args.nextnext); +        const auto result = cmCMakePath{ *lhs } == cmCMakePath{ *rhs }; +        newArgs.ReduceTwoArgs(result, args); +      } + +      else if (this->Policy139Status == cmPolicies::WARN) { +        std::ostringstream e; +        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0139) +          << "\n" +             "PATH_EQUAL will be interpreted as an operator " +             "when the policy is set to NEW.  " +             "Since the policy is not set the OLD behavior will be used."; + +        this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); +      } +    }    }    return true;  } diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index 37b7825..9486b16 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -79,4 +79,5 @@ private:    cmPolicies::PolicyStatus Policy54Status;    cmPolicies::PolicyStatus Policy57Status;    cmPolicies::PolicyStatus Policy64Status; +  cmPolicies::PolicyStatus Policy139Status;  }; diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx index 12b2925..bf83b38 100644 --- a/Source/cmConfigureFileCommand.cxx +++ b/Source/cmConfigureFileCommand.cxx @@ -53,7 +53,7 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,      std::string e = "attempted to configure a file: " + outputFile +        " into a source directory.";      status.SetError(e); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    std::string errorMessage; 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/cmContinueCommand.cxx b/Source/cmContinueCommand.cxx index bb63dff..c6cecbe 100644 --- a/Source/cmContinueCommand.cxx +++ b/Source/cmContinueCommand.cxx @@ -16,7 +16,7 @@ bool cmContinueCommand(std::vector<std::string> const& args,        MessageType::FATAL_ERROR,        "A CONTINUE command was found outside of a "        "proper FOREACH or WHILE loop scope."); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return true;    } @@ -27,7 +27,7 @@ bool cmContinueCommand(std::vector<std::string> const& args,        MessageType::FATAL_ERROR,        "The CONTINUE command does not accept any "        "arguments."); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return true;    } diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 324ce87..5418e7c 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -32,11 +32,7 @@ class LanguageStandardState  {  public:    LanguageStandardState(std::string&& lang) -    : IsEnabled(false) -    , DidStandard(false) -    , DidStandardRequired(false) -    , DidExtensions(false) -    , StandardFlag(lang + "_STANDARD") +    : StandardFlag(lang + "_STANDARD")      , RequiredFlag(lang + "_STANDARD_REQUIRED")      , ExtensionFlag(lang + "_EXTENSIONS")    { @@ -108,7 +104,7 @@ public:        std::string value = makefile->GetSafeDefinition(var);        if (warnCMP0067 && !value.empty()) {          value.clear(); -        warnCMP0067Variables.push_back(var); +        warnCMP0067Variables.emplace_back(var);        }        return value;      }; @@ -154,10 +150,10 @@ public:    }  private: -  bool IsEnabled; -  bool DidStandard; -  bool DidStandardRequired; -  bool DidExtensions; +  bool IsEnabled = false; +  bool DidStandard = false; +  bool DidStandardRequired = false; +  bool DidExtensions = false;    std::string StandardFlag;    std::string RequiredFlag; @@ -228,6 +224,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 +333,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 +362,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 +375,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 +486,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 +553,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 +725,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,18 +867,115 @@ 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));        }      }    } -  bool erroroc = cmSystemTools::GetErrorOccuredFlag(); -  cmSystemTools::ResetErrorOccuredFlag(); +  bool erroroc = cmSystemTools::GetErrorOccurredFlag(); +  cmSystemTools::ResetErrorOccurredFlag();    std::string output;    // actually do the try compile now that everything is setup    int res = this->Makefile->TryCompile( @@ -978,7 +983,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,      this->SrcFileSignature, cmake::NO_BUILD_PARALLEL_LEVEL, &cmakeFlags,      output);    if (erroroc) { -    cmSystemTools::SetErrorOccured(); +    cmSystemTools::SetErrorOccurred();    }    // set the result var to the return value to indicate success or failure @@ -1109,18 +1114,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/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index b331862..ff9ab0f 100644 --- a/Source/cmCryptoHash.cxx +++ b/Source/cmCryptoHash.cxx @@ -83,15 +83,15 @@ std::unique_ptr<cmCryptoHash> cmCryptoHash::New(cm::string_view algo)  bool cmCryptoHash::IntFromHexDigit(char input, char& output)  {    if (input >= '0' && input <= '9') { -    output = char(input - '0'); +    output = static_cast<char>(input - '0');      return true;    }    if (input >= 'a' && input <= 'f') { -    output = char(input - 'a' + 0xA); +    output = static_cast<char>(input - 'a' + 0xA);      return true;    }    if (input >= 'A' && input <= 'F') { -    output = char(input - 'A' + 0xA); +    output = static_cast<char>(input - 'A' + 0xA);      return true;    }    return false; @@ -182,7 +182,7 @@ void cmCryptoHash::Append(cm::string_view input)  std::vector<unsigned char> cmCryptoHash::Finalize()  {    std::vector<unsigned char> hash(rhash_get_digest_size(this->Id), 0); -  rhash_final(this->CTX, &hash[0]); +  rhash_final(this->CTX, hash.data());    return hash;  } diff --git a/Source/cmDependencyProvider.h b/Source/cmDependencyProvider.h new file mode 100644 index 0000000..a6670b4 --- /dev/null +++ b/Source/cmDependencyProvider.h @@ -0,0 +1,38 @@ +/* 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 <algorithm> +#include <string> +#include <utility> +#include <vector> + +class cmDependencyProvider +{ +public: +  enum class Method +  { +    FindPackage, +    FetchContentMakeAvailableSerial, +  }; + +  cmDependencyProvider(std::string command, std::vector<Method> methods) +    : Command(std::move(command)) +    , Methods(std::move(methods)) +  { +  } + +  std::string const& GetCommand() const { return this->Command; } +  std::vector<Method> const& GetMethods() const { return this->Methods; } +  bool SupportsMethod(Method method) const +  { +    return std::find(this->Methods.begin(), this->Methods.end(), method) != +      this->Methods.end(); +  } + +private: +  std::string Command; +  std::vector<Method> Methods; +}; diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index d5e54ae..ac93c90 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -478,7 +478,7 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)    // when the interface described in the module does not.    std::string mod = args[2]; -  std::string stamp = args[3]; +  std::string const& stamp = args[3];    std::string compilerId;    if (args.size() >= 5) {      compilerId = args[4]; diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 66f1733..8aea753 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -83,7 +83,6 @@ public:      : External(external)      , Stream(std::move(fin))      , ByteOrder(order) -    , ELFType(cmELF::FileTypeInvalid)    {  // In most cases the processor-specific byte order will match that  // of the target execution environment.  If we choose wrong here @@ -150,7 +149,7 @@ protected:    ByteOrderType ByteOrder;    // The ELF file type. -  cmELF::FileType ELFType; +  cmELF::FileType ELFType = cmELF::FileTypeInvalid;    // The ELF architecture.    std::uint16_t Machine; 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/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 3b990cc..222ea80 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -113,7 +113,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,    if (!status.GetMakefile().CanIWriteThisFile(arguments.OutputFile)) {      status.SetError("attempted to output into a file: " +                      arguments.OutputFile + " into a source directory."); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -438,7 +438,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,      }      if (!ret) { -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    } @@ -470,7 +470,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,          break;      }      if (!ret) { -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    } 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..5a33349 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,18 @@ 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; +    // Export IMPORTED_LINK_DEPENDENT_LIBRARIES to help consuming linkers +    // find private dependencies of shared libraries. +    std::size_t oldMissingTargetsSize = this->MissingTargets.size();      this->SetImportLinkProperty(        suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps, -      properties, dummy, ImportLinkPropertyTargetNames::Yes); +      properties, ImportLinkPropertyTargetNames::Yes); +    // Avoid enforcing shared library private dependencies as public package +    // dependencies by ignoring missing targets added for them. +    this->MissingTargets.resize(oldMissingTargetsSize); +      if (iface->Multiplicity > 0) {        std::string prop =          cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix); @@ -885,14 +893,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 +912,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 +929,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 +992,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 +1127,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 +1144,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 +1187,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 +1202,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 +1219,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/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index d9d5a4b..ba4b326 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -737,7 +737,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const      // exclude source directory from output search path      // - only if not named the same as an output directory      if (!cmSystemTools::FileIsDirectory( -          std::string(this->HomeOutputDirectory + "/" + p))) { +          cmStrCat(this->HomeOutputDirectory, '/', p))) {        excludeFromOut += p + "/|";      }    } 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/cmFileAPI.cxx b/Source/cmFileAPI.cxx index c1df992..7f8374d 100644 --- a/Source/cmFileAPI.cxx +++ b/Source/cmFileAPI.cxx @@ -417,7 +417,7 @@ const char* cmFileAPI::ObjectKindName(ObjectKind kind)      "toolchains", //      "__test"      //    }; -  return objectKindNames[size_t(kind)]; +  return objectKindNames[static_cast<size_t>(kind)];  }  std::string cmFileAPI::ObjectName(Object const& o) 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 fb15a1b..3c234a6 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> @@ -86,7 +87,7 @@ bool HandleWriteImpl(std::vector<std::string> const& args, bool append,      std::string e =        "attempted to write a file: " + fileName + " into a source directory.";      status.SetError(e); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    std::string dir = cmSystemTools::GetFilenamePath(fileName); @@ -290,7 +291,7 @@ bool HandleStringsCommand(std::vector<std::string> const& args,    }    // Get the variable in which to store the results. -  std::string outVar = args[2]; +  std::string const& outVar = args[2];    // Parse the options.    enum @@ -840,7 +841,7 @@ bool HandleMakeDirectoryCommand(std::vector<std::string> const& args,        std::string e = "attempted to create a directory: " + *cdir +          " into a source directory.";        status.SetError(e); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }      if (!cmSystemTools::MakeDirectory(*cdir)) { @@ -870,7 +871,7 @@ bool HandleTouchImpl(std::vector<std::string> const& args, bool create,        std::string e =          "attempted to touch a file: " + tfile + " in a source directory.";        status.SetError(e); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }      if (!cmSystemTools::Touch(tfile, create)) { @@ -1615,8 +1616,8 @@ size_t cmWriteToMemoryCallback(void* ptr, size_t size, size_t nmemb,    return realsize;  } -size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr, -                                      size_t size, void* data) +int cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr, +                                   size_t size, void* data)  {    cmFileCommandVectorOfChar& vec =      *static_cast<cmFileCommandVectorOfChar*>(data); @@ -1784,6 +1785,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") { @@ -1874,7 +1876,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,        }        std::string algo = i->substr(0, pos);        expectedHash = cmSystemTools::LowerCase(i->substr(pos + 1)); -      hash = std::unique_ptr<cmCryptoHash>(cmCryptoHash::New(algo)); +      hash = cmCryptoHash::New(algo);        if (!hash) {          std::string err =            cmStrCat("DOWNLOAD EXPECTED_HASH given unknown ALGO: ", algo); @@ -1896,6 +1898,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 { @@ -1905,6 +1928,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. @@ -1990,6 +2014,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); @@ -2737,7 +2768,7 @@ bool HandleLockCommand(std::vector<std::string> const& args,        MessageType::FATAL_ERROR,        cmStrCat("directory\n  \"", parentDir,                 "\"\ncreation failed (check permissions).")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    FILE* file = cmsys::SystemTools::Fopen(path, "w"); @@ -2746,7 +2777,7 @@ bool HandleLockCommand(std::vector<std::string> const& args,        MessageType::FATAL_ERROR,        cmStrCat("file\n  \"", path,                 "\"\ncreation failed (check permissions).")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    fclose(file); @@ -2770,7 +2801,7 @@ bool HandleLockCommand(std::vector<std::string> const& args,          fileLockResult = lockPool.LockProcessScope(path, timeout);          break;        default: -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          return false;      }    } @@ -2781,7 +2812,7 @@ bool HandleLockCommand(std::vector<std::string> const& args,      status.GetMakefile().IssueMessage(        MessageType::FATAL_ERROR,        cmStrCat("error locking file\n  \"", path, "\"\n", result, ".")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3016,7 +3047,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,      status.SetError(        cmStrCat("GET_RUNTIME_DEPENDENCIES is not supported on system \"",                 platform, "\"")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3084,7 +3115,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,    auto argIt = unrecognizedArguments.begin();    if (argIt != unrecognizedArguments.end()) {      status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3106,7 +3137,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,    if (kwend != kwbegin) {      status.SetError(cmStrCat("Keywords missing values:\n  ",                               cmJoin(cmMakeRange(kwbegin, kwend), "\n  "))); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3118,13 +3149,13 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,      std::move(parsedArgs.PostExcludeFiles),      std::move(parsedArgs.PostExcludeFilesStrict));    if (!archive.Prepare()) { -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    if (!archive.GetRuntimeDependencies(          parsedArgs.Executables, parsedArgs.Libraries, parsedArgs.Modules)) { -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3165,7 +3196,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,          e << "\n  " << path;        }        status.SetError(e.str()); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    } @@ -3181,7 +3212,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,          e << "\n  " << path;        }        status.SetError(e.str()); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    } @@ -3235,7 +3266,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,    if (argIt != unrecognizedArguments.end()) {      status.SetError(        cmStrCat("CONFIGURE Unrecognized argument: \"", *argIt, "\"")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3247,7 +3278,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,                  e) != keywordsMissingArguments.end();      if (optionHasNoValue) {        status.SetError(cmStrCat("CONFIGURE ", e, " option needs a value.")); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    } @@ -3258,7 +3289,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,        parsedKeywords.end();      if (!optionGiven) {        status.SetError(cmStrCat("CONFIGURE ", e, " option is mandatory.")); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    } @@ -3373,7 +3404,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,    auto argIt = unrecognizedArguments.begin();    if (argIt != unrecognizedArguments.end()) {      status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3385,7 +3416,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,    if (kwend != kwbegin) {      status.SetError(cmStrCat("Keywords missing values:\n  ",                               cmJoin(cmMakeRange(kwbegin, kwend), "\n  "))); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3397,7 +3428,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,        !cm::contains(knownFormats, parsedArgs.Format)) {      status.SetError(        cmStrCat("archive format ", parsedArgs.Format, " not supported")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3406,7 +3437,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,        cm::contains(zipFileFormats, parsedArgs.Format)) {      status.SetError(cmStrCat("archive format ", parsedArgs.Format,                               " does not support COMPRESSION arguments")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3424,7 +3455,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,    } else if (!parsedArgs.Compression.empty()) {      status.SetError(cmStrCat("compression type ", parsedArgs.Compression,                               " is not supported")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3435,7 +3466,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,        status.SetError(cmStrCat("compression level ",                                 parsedArgs.CompressionLevel,                                 " should be in range 0 to 9")); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }      compressionLevel = std::stoi(parsedArgs.CompressionLevel); @@ -3443,21 +3474,21 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,        status.SetError(cmStrCat("compression level ",                                 parsedArgs.CompressionLevel,                                 " should be in range 0 to 9")); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }      if (compress == cmSystemTools::TarCompressNone) {        status.SetError(cmStrCat("compression level is not supported for "                                 "compression \"None\"",                                 parsedArgs.Compression)); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    }    if (parsedArgs.Paths.empty()) {      status.SetError("ARCHIVE_CREATE requires a non-empty list of PATHS"); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3465,7 +3496,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,                                  parsedArgs.Verbose, parsedArgs.MTime,                                  parsedArgs.Format, compressionLevel)) {      status.SetError(cmStrCat("failed to compress: ", parsedArgs.Output)); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3482,6 +3513,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>{} @@ -3489,7 +3521,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; @@ -3499,7 +3532,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,    auto argIt = unrecognizedArguments.begin();    if (argIt != unrecognizedArguments.end()) {      status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3510,7 +3543,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,    if (kwend != kwbegin) {      status.SetError(cmStrCat("Keywords missing values:\n  ",                               cmJoin(cmMakeRange(kwbegin, kwend), "\n  "))); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3520,7 +3553,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,      if (!cmSystemTools::ListTar(inFile, parsedArgs.Patterns,                                  parsedArgs.Verbose)) {        status.SetError(cmStrCat("failed to list: ", inFile)); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    } else { @@ -3534,7 +3567,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,        if (!cmSystemTools::MakeDirectory(destDir)) {          status.SetError(cmStrCat("failed to create directory: ", destDir)); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          return false;        } @@ -3548,14 +3581,17 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,      if (workdir.Failed()) {        status.SetError(          cmStrCat("failed to change working directory to: ", destDir)); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        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(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    } @@ -3569,7 +3605,7 @@ bool ValidateAndConvertPermissions(const std::vector<std::string>& permissions,    for (const auto& i : permissions) {      if (!cmFSPermissions::stringToModeT(i, perms)) {        status.SetError(i + " is an invalid permission specifier"); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    } @@ -3581,7 +3617,7 @@ bool SetPermissions(const std::string& filename, const mode_t& perms,  {    if (!cmSystemTools::SetPermissions(filename, perms)) {      status.SetError("Failed to set permissions for " + filename); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    return true; @@ -3621,7 +3657,7 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,        parsedArgs.DirectoryPermissions.empty()) // no permissions given    {      status.SetError("No permissions given"); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -3630,14 +3666,14 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,    {      status.SetError("Remove either PERMISSIONS or FILE_PERMISSIONS or "                      "DIRECTORY_PERMISSIONS from the invocation"); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    if (!keywordsMissingValues.empty()) {      for (const auto& i : keywordsMissingValues) {        status.SetError(i + " is not given any arguments"); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();      }      return false;    } @@ -3676,7 +3712,7 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,    for (const auto& i : allPathEntries) {      if (!(cmSystemTools::FileExists(i) || cmSystemTools::FileIsDirectory(i))) {        status.SetError(cmStrCat("does not exist:\n  ", i)); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      } diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx index 63a4274..1667807 100644 --- a/Source/cmFileCopier.cxx +++ b/Source/cmFileCopier.cxx @@ -27,16 +27,6 @@ cmFileCopier::cmFileCopier(cmExecutionStatus& status, const char* name)    : Status(status)    , Makefile(&status.GetMakefile())    , Name(name) -  , Always(false) -  , MatchlessFiles(true) -  , FilePermissions(0) -  , DirPermissions(0) -  , CurrentMatchRule(nullptr) -  , UseGivenPermissionsFile(false) -  , UseGivenPermissionsDir(false) -  , UseSourcePermissions(true) -  , FollowSymlinkChain(false) -  , Doing(DoingNone)  {  } diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h index ee9872d..1fd2062 100644 --- a/Source/cmFileCopier.h +++ b/Source/cmFileCopier.h @@ -28,15 +28,15 @@ protected:    cmExecutionStatus& Status;    cmMakefile* Makefile;    const char* Name; -  bool Always; +  bool Always = false;    cmFileTimeCache FileTimes;    // Whether to install a file not matching any expression. -  bool MatchlessFiles; +  bool MatchlessFiles = true;    // Permissions for files and directories installed by this object. -  mode_t FilePermissions; -  mode_t DirPermissions; +  mode_t FilePermissions = 0; +  mode_t DirPermissions = 0;    // Properties set by pattern and regex match rules.    struct MatchProperties @@ -85,17 +85,15 @@ protected:    virtual void ReportCopy(const std::string&, Type, bool) {}    virtual bool ReportMissing(const std::string& fromFile); -  MatchRule* CurrentMatchRule; -  bool UseGivenPermissionsFile; -  bool UseGivenPermissionsDir; -  bool UseSourcePermissions; -  bool FollowSymlinkChain; +  MatchRule* CurrentMatchRule = nullptr; +  bool UseGivenPermissionsFile = false; +  bool UseGivenPermissionsDir = false; +  bool UseSourcePermissions = true; +  bool FollowSymlinkChain = false;    std::string Destination;    std::string FilesFromDir;    std::vector<std::string> Files; -  int Doing; -  virtual bool Parse(std::vector<std::string> const& args);    enum    {      DoingNone, @@ -110,6 +108,9 @@ protected:      DoingPermissionsMatch,      DoingLast1    }; +  int Doing = DoingNone; + +  virtual bool Parse(std::vector<std::string> const& args);    virtual bool CheckKeyword(std::string const& arg);    virtual bool CheckValue(std::string const& arg); diff --git a/Source/cmFileInstaller.cxx b/Source/cmFileInstaller.cxx index 9bfbd13..5cfb2cf 100644 --- a/Source/cmFileInstaller.cxx +++ b/Source/cmFileInstaller.cxx @@ -23,13 +23,6 @@ using namespace cmFSPermissions;  cmFileInstaller::cmFileInstaller(cmExecutionStatus& status)    : cmFileCopier(status, "INSTALL") -  , InstallType(cmInstallType_FILES) -  , InstallMode(cmInstallMode::COPY) -  , Optional(false) -  , MessageAlways(false) -  , MessageLazy(false) -  , MessageNever(false) -  , DestDirLength(0)  {    // Installation does not use source permissions by default.    this->UseSourcePermissions = false; @@ -440,7 +433,7 @@ bool cmFileInstaller::HandleInstallDestination()        }      }      destination = sdestdir + destination.substr(skip); -    this->DestDirLength = int(sdestdir.size()); +    this->DestDirLength = static_cast<int>(sdestdir.size());    }    // check if default dir creation permissions were set diff --git a/Source/cmFileInstaller.h b/Source/cmFileInstaller.h index 3f6bd45..0b6f15d 100644 --- a/Source/cmFileInstaller.h +++ b/Source/cmFileInstaller.h @@ -19,13 +19,13 @@ struct cmFileInstaller : public cmFileCopier    ~cmFileInstaller() override;  protected: -  cmInstallType InstallType; -  cmInstallMode InstallMode; -  bool Optional; -  bool MessageAlways; -  bool MessageLazy; -  bool MessageNever; -  int DestDirLength; +  cmInstallType InstallType = cmInstallType_FILES; +  cmInstallMode InstallMode = cmInstallMode::COPY; +  bool Optional = false; +  bool MessageAlways = false; +  bool MessageLazy = false; +  bool MessageNever = false; +  int DestDirLength = 0;    std::string Rename;    std::string Manifest; 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..1da995a 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 { @@ -263,12 +278,89 @@ void cmFindBase::FillSystemEnvironmentPath()    paths.AddSuffixes(this->SearchPathSuffixes);  } +namespace { +struct entry_to_remove +{ +  entry_to_remove(std::string const& name, cmMakefile* makefile) +    : value() +  { +    if (cmValue to_skip = makefile->GetDefinition( +          cmStrCat("_CMAKE_SYSTEM_PREFIX_PATH_", name, "_PREFIX_COUNT"))) { +      cmStrToLong(to_skip, &count); +    } +    if (cmValue prefix_value = makefile->GetDefinition( +          cmStrCat("_CMAKE_SYSTEM_PREFIX_PATH_", name, "_PREFIX_VALUE"))) { +      value = *prefix_value; +    } +  } +  bool valid() const { return count > 0 && !value.empty(); } + +  void remove_self(std::vector<std::string>& entries) const +  { +    if (this->valid()) { +      long to_skip = this->count; +      long index_to_remove = 0; +      for (const auto& path : entries) { +        if (path == this->value && --to_skip == 0) { +          break; +        } +        ++index_to_remove; +      } +      entries.erase(entries.begin() + index_to_remove); +    } +  } + +  long count = -1; +  std::string value; +}; +} +  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 ( likewise for `CMAKE_STAGING_PREFIX` ) +  entry_to_remove install_entry("INSTALL", this->Makefile); +  entry_to_remove staging_entry("STAGING", this->Makefile); + +  if (remove_install_prefix && install_prefix_in_list && +      (install_entry.valid() || staging_entry.valid())) { +    cmValue prefix_paths = +      this->Makefile->GetDefinition("CMAKE_SYSTEM_PREFIX_PATH"); + +    // remove entries from CMAKE_SYSTEM_PREFIX_PATH +    std::vector<std::string> expanded = cmExpandedList(*prefix_paths); +    install_entry.remove_self(expanded); +    staging_entry.remove_self(expanded); + +    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_STAGING_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") { @@ -448,7 +540,7 @@ void cmFindBase::StoreFindResult(const std::string& value)                    ? "files"                    : "names"),                 ": ", cmJoin(this->Names, ", "))); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();    }  } @@ -496,7 +588,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..8c6a0aa 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,8 @@  #include "cmsys/String.h"  #include "cmAlgorithms.h" +#include "cmDependencyProvider.h" +#include "cmListFileCache.h"  #include "cmMakefile.h"  #include "cmMessageType.h"  #include "cmPolicies.h" @@ -33,6 +36,7 @@  #include "cmSystemTools.h"  #include "cmValue.h"  #include "cmVersion.h" +#include "cmWindowsRegistry.h"  #if defined(__HAIKU__)  #  include <FindDirectory.h> @@ -42,6 +46,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 +115,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 +130,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))); @@ -229,6 +239,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)    const char* components_sep = "";    std::set<std::string> requiredComponents;    std::set<std::string> optionalComponents; +  std::vector<std::pair<std::string, const char*>> componentVarDefs; +  bool bypassProvider = false;    // Always search directly in a generated path.    this->SearchPathSuffixes.emplace_back(); @@ -259,9 +271,15 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)      if (args[i] == "QUIET") {        this->Quiet = true;        doing = DoingNone; +    } else if (args[i] == "BYPASS_PROVIDER") { +      bypassProvider = true; +      doing = DoingNone;      } 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 +332,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; @@ -330,7 +362,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)        }        std::string req_var = this->Name + "_FIND_REQUIRED_" + args[i]; -      this->AddFindDefinition(req_var, isRequired); +      componentVarDefs.emplace_back(req_var, isRequired);        // Append to the list of required components.        components += components_sep; @@ -364,6 +396,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(), @@ -376,7 +414,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)      return false;    } -  // Maybe choose one mode exclusively. +  // Check and eliminate search modes not allowed by the args provided    this->UseFindModules = configArgs.empty();    this->UseConfigFiles = moduleArgs.empty();    if (!this->UseFindModules && !this->UseConfigFiles) { @@ -511,6 +549,48 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)      return true;    } +  // Now choose what method(s) we will use to satisfy the request. Note that +  // we still want all the above checking of arguments, etc. regardless of the +  // method used. This will ensure ill-formed arguments are caught earlier, +  // before things like dependency providers need to deal with them. + +  // A dependency provider (if set) gets first look before other methods. +  // We do this before modifying the package root path stack because a +  // provider might use methods that ignore that. +  cmState* state = this->Makefile->GetState(); +  cmState::Command providerCommand = state->GetDependencyProviderCommand( +    cmDependencyProvider::Method::FindPackage); +  if (bypassProvider) { +    if (this->DebugMode && providerCommand) { +      this->DebugMessage( +        "BYPASS_PROVIDER given, skipping dependency provider"); +    } +  } else if (providerCommand) { +    if (this->DebugMode) { +      this->DebugMessage(cmStrCat("Trying dependency provider command: ", +                                  state->GetDependencyProvider()->GetCommand(), +                                  "()")); +    } +    std::vector<cmListFileArgument> listFileArgs(args.size() + 1); +    listFileArgs[0] = +      cmListFileArgument("FIND_PACKAGE", cmListFileArgument::Unquoted, 0); +    std::transform(args.begin(), args.end(), listFileArgs.begin() + 1, +                   [](const std::string& arg) { +                     return cmListFileArgument(arg, +                                               cmListFileArgument::Bracket, 0); +                   }); +    if (!providerCommand(listFileArgs, this->Status)) { +      return false; +    } +    if (this->Makefile->IsOn(cmStrCat(this->Name, "_FOUND"))) { +      if (this->DebugMode) { +        this->DebugMessage("Package was found by the dependency provider"); +      } +      this->AppendSuccessInformation(); +      return true; +    } +  } +    {      // Allocate a PACKAGE_ROOT_PATH for the current find_package call.      this->Makefile->FindPackageRootPathStack.emplace_back(); @@ -541,11 +621,64 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)      }    } -  this->SetModuleVariables(components); +  this->SetModuleVariables(components, componentVarDefs); + +  // 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 { @@ -612,6 +745,12 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)    this->AppendSuccessInformation(); +  // Restore original state of "_FIND_" variables set in SetModuleVariables() +  this->RestoreFindDefinitions(); + +  // Pop the package stack +  this->Makefile->FindPackageRootPathStack.pop_back(); +    if (!this->DebugBuffer.empty()) {      this->DebugMessage(this->DebugBuffer);    } @@ -693,13 +832,18 @@ void cmFindPackageCommand::SetVersionVariables(    addDefinition(prefix + "_COUNT", buf);  } -void cmFindPackageCommand::SetModuleVariables(const std::string& components) +void cmFindPackageCommand::SetModuleVariables( +  const std::string& components, +  const std::vector<std::pair<std::string, const char*>>& componentVarDefs)  {    this->AddFindDefinition("CMAKE_FIND_PACKAGE_NAME", this->Name); -  // Store the list of components. +  // Store the list of components and associated variable definitions    std::string components_var = this->Name + "_FIND_COMPONENTS";    this->AddFindDefinition(components_var, components); +  for (const auto& varDef : componentVarDefs) { +    this->AddFindDefinition(varDef.first, varDef.second); +  }    if (this->Quiet) {      // Tell the module that is about to be read that it should find @@ -758,6 +902,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, @@ -1048,7 +1197,7 @@ bool cmFindPackageCommand::HandlePackageMode(                                                    : MessageType::WARNING,                                     e.str());        if (this->Required) { -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();        }        if (!aw.str().empty()) { @@ -1155,19 +1304,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 +1354,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;    } @@ -1288,12 +1447,6 @@ void cmFindPackageCommand::AppendSuccessInformation()      this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName,                                                    "REQUIRED");    } - -  // Restore original state of "_FIND_" variables we set. -  this->RestoreFindDefinitions(); - -  // Pop the package stack -  this->Makefile->FindPackageRootPathStack.pop_back();  }  inline std::size_t collectPathsForDebug(std::string& buffer, @@ -1313,6 +1466,8 @@ inline std::size_t collectPathsForDebug(std::string& buffer,  void cmFindPackageCommand::ComputePrefixes()  { +  this->FillPrefixesPackageRedirect(); +    if (!this->NoDefaultPath) {      if (!this->NoPackageRootPath) {        this->FillPrefixesPackageRoot(); @@ -1346,6 +1501,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 +1840,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..80fd8f8 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -9,6 +9,7 @@  #include <map>  #include <set>  #include <string> +#include <utility>  #include <vector>  #include <cm/string_view> @@ -76,6 +77,7 @@ private:        : cmFindCommon::PathLabel(label)      {      } +    static PathLabel PackageRedirect;      static PathLabel UserRegistry;      static PathLabel Builds;      static PathLabel SystemRegistry; @@ -96,7 +98,9 @@ private:      const std::string& prefix, const std::string& version, unsigned int count,      unsigned int major, unsigned int minor, unsigned int patch,      unsigned int tweak); -  void SetModuleVariables(const std::string& components); +  void SetModuleVariables( +    const std::string& components, +    const std::vector<std::pair<std::string, const char*>>& componentVarDefs);    bool FindModule(bool& found);    void AddFindDefinition(const std::string& var, cm::string_view value);    void RestoreFindDefinitions(); @@ -119,8 +123,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 +205,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/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index dcb3626..b9400c9 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -271,7 +271,7 @@ auto cmForEachFunctionBlocker::invoke(      if (status.GetContinueInvoked()) {        break;      } -    if (cmSystemTools::GetFatalErrorOccured()) { +    if (cmSystemTools::GetFatalErrorOccurred()) {        result.Restore = false;        result.Break = true;        break; @@ -382,13 +382,13 @@ bool TryParseInteger(cmExecutionStatus& status, const std::string& str, int& i)      std::ostringstream e;      e << "Invalid integer: '" << str << "'";      status.SetError(e.str()); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } catch (std::out_of_range&) {      std::ostringstream e;      e << "Integer out of range: '" << str << "'";      status.SetError(e.str()); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -452,7 +452,7 @@ bool cmForEachCommand(std::vector<std::string> const& args,          status.SetError(            cmStrCat("called with incorrect range specification: start ", start,                     ", stop ", stop, ", step ", step)); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          return false;        } @@ -460,8 +460,8 @@ bool cmForEachCommand(std::vector<std::string> const& args,        // in the `fb->Args` vector. The first item is the iteration variable        // name...        const std::size_t iter_cnt = 2u + -        int(start < stop) * (stop - start) / std::abs(step) + -        int(start > stop) * (start - stop) / std::abs(step); +        static_cast<int>(start < stop) * (stop - start) / std::abs(step) + +        static_cast<int>(start > stop) * (start - stop) / std::abs(step);        fb->Args.resize(iter_cnt);        fb->Args.front() = args.front();        auto cc = start; diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h index 70fe537..542b98c 100644 --- a/Source/cmFortranParser.h +++ b/Source/cmFortranParser.h @@ -123,13 +123,12 @@ struct cmFortranFile      : File(file)      , Buffer(buffer)      , Directory(std::move(dir)) -    , LastCharWasNewline(false)    {    }    FILE* File;    YY_BUFFER_STATE Buffer;    std::string Directory; -  bool LastCharWasNewline; +  bool LastCharWasNewline = false;  };  struct cmFortranCompiler diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index a52e66a..b529b8f 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -44,7 +44,8 @@ cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name,  #endif    if (encoding == codecvt::UTF8_WITH_BOM) {      // Write the BOM encoding header into the file -    char magic[] = { char(0xEF), char(0xBB), char(0xBF) }; +    char magic[] = { static_cast<char>(0xEF), static_cast<char>(0xBB), +                     static_cast<char>(0xBF) };      this->write(magic, 3);    }  } diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 840f511..f988e54 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -100,11 +100,6 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(    cmListFileBacktrace backtrace, std::string input)    : Backtrace(std::move(backtrace))    , Input(std::move(input)) -  , EvaluateForBuildsystem(false) -  , Quiet(false) -  , HadContextSensitiveCondition(false) -  , HadHeadSensitiveCondition(false) -  , HadLinkLanguageSensitiveCondition(false)  {    cmGeneratorExpressionLexer l;    std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(this->Input); diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 03be782..188993f 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -161,8 +161,8 @@ private:    std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>> Evaluators;    const std::string Input;    bool NeedsEvaluation; -  bool EvaluateForBuildsystem; -  bool Quiet; +  bool EvaluateForBuildsystem = false; +  bool Quiet = false;    mutable std::set<cmGeneratorTarget*> DependTargets;    mutable std::set<cmGeneratorTarget const*> AllTargetsSeen; @@ -171,9 +171,9 @@ private:                     std::map<std::string, std::string>>      MaxLanguageStandard;    mutable std::string Output; -  mutable bool HadContextSensitiveCondition; -  mutable bool HadHeadSensitiveCondition; -  mutable bool HadLinkLanguageSensitiveCondition; +  mutable bool HadContextSensitiveCondition = false; +  mutable bool HadHeadSensitiveCondition = false; +  mutable bool HadLinkLanguageSensitiveCondition = false;    mutable std::set<cmGeneratorTarget const*> SourceSensitiveTargets;  }; diff --git a/Source/cmGeneratorExpressionContext.cxx b/Source/cmGeneratorExpressionContext.cxx index 42cbe2a..8076887 100644 --- a/Source/cmGeneratorExpressionContext.cxx +++ b/Source/cmGeneratorExpressionContext.cxx @@ -16,10 +16,6 @@ cmGeneratorExpressionContext::cmGeneratorExpressionContext(    , HeadTarget(headTarget)    , CurrentTarget(currentTarget)    , Quiet(quiet) -  , HadError(false) -  , HadContextSensitiveCondition(false) -  , HadHeadSensitiveCondition(false) -  , HadLinkLanguageSensitiveCondition(false)    , EvaluateForBuildsystem(evaluateForBuildsystem)  {  } diff --git a/Source/cmGeneratorExpressionContext.h b/Source/cmGeneratorExpressionContext.h index 22e7463..21e3961 100644 --- a/Source/cmGeneratorExpressionContext.h +++ b/Source/cmGeneratorExpressionContext.h @@ -36,9 +36,9 @@ struct cmGeneratorExpressionContext    // directly or indirectly in the property.    cmGeneratorTarget const* CurrentTarget;    bool Quiet; -  bool HadError; -  bool HadContextSensitiveCondition; -  bool HadHeadSensitiveCondition; -  bool HadLinkLanguageSensitiveCondition; +  bool HadError = false; +  bool HadContextSensitiveCondition = false; +  bool HadHeadSensitiveCondition = false; +  bool HadLinkLanguageSensitiveCondition = false;    bool EvaluateForBuildsystem;  }; diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 187db73..6be5153 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 @@ -178,7 +178,7 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkOptionsExpression() const  }  bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries( -  cmGeneratorTarget const* tgt) const +  cmGeneratorTarget const* tgt, ForGenex genex) const  {    const auto* top = this->Top(); @@ -188,11 +188,17 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(      return top->Target == tgt && prop == "LINK_LIBRARIES"_s;    } -  return prop == "LINK_LIBRARIES"_s || prop == "INTERFACE_LINK_LIBRARIES"_s || +  auto result = prop == "LINK_LIBRARIES"_s || +    prop == "INTERFACE_LINK_LIBRARIES"_s || +    prop == "INTERFACE_LINK_LIBRARIES_DIRECT"_s ||      prop == "LINK_INTERFACE_LIBRARIES"_s ||      prop == "IMPORTED_LINK_INTERFACE_LIBRARIES"_s ||      cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") ||      cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_"); + +  return genex == ForGenex::LINK_LIBRARY || genex == ForGenex::LINK_GROUP +    ? result +    : (result || prop == "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE"_s);  }  cmGeneratorExpressionDAGChecker const* cmGeneratorExpressionDAGChecker::Top() diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index 93b44db..55d131f 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -71,7 +71,14 @@ struct cmGeneratorExpressionDAGChecker    bool EvaluatingLinkExpression() const;    bool EvaluatingLinkOptionsExpression() const; -  bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr) const; +  enum class ForGenex +  { +    ANY, +    LINK_LIBRARY, +    LINK_GROUP +  }; +  bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr, +                               ForGenex genex = ForGenex::ANY) const;  #define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const; diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index 9fae15a..8f3ed4d 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -182,7 +182,7 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)      for (std::string const& li : allConfigs) {        this->Generate(lg, li, le, inputExpression.get(), outputFiles,                       this->Permissions); -      if (cmSystemTools::GetFatalErrorOccured()) { +      if (cmSystemTools::GetFatalErrorOccurred()) {          return;        }      } diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 396e9c9..45d5a83 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -7,10 +7,12 @@  #include <cerrno>  #include <cstdlib>  #include <cstring> +#include <functional>  #include <map>  #include <memory>  #include <set>  #include <sstream> +#include <unordered_map>  #include <utility>  #include <cm/iterator> @@ -24,6 +26,7 @@  #include "cmsys/String.h"  #include "cmAlgorithms.h" +#include "cmCMakePath.h"  #include "cmComputeLinkInformation.h"  #include "cmGeneratorExpression.h"  #include "cmGeneratorExpressionContext.h" @@ -413,7 +416,7 @@ static const struct TargetExistsNode : public cmGeneratorExpressionNode        return std::string();      } -    std::string targetName = parameters.front(); +    std::string const& targetName = parameters.front();      if (targetName.empty() ||          !cmGeneratorExpression::IsValidTargetName(targetName)) {        reportError(context, content->GetOriginalExpression(), @@ -445,7 +448,7 @@ static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode        return std::string();      } -    std::string targetName = parameters.front(); +    std::string const& targetName = parameters.front();      if (targetName.empty() ||          !cmGeneratorExpression::IsValidTargetName(targetName)) {        reportError(context, content->GetOriginalExpression(), @@ -599,6 +602,455 @@ static const struct UpperCaseNode : public cmGeneratorExpressionNode    }  } upperCaseNode; +namespace { +template <typename Container> +class Range : public cmRange<typename Container::const_iterator> +{ +private: +  using Base = cmRange<typename Container::const_iterator>; + +public: +  using const_iterator = typename Container::const_iterator; +  using value_type = typename Container::value_type; +  using size_type = typename Container::size_type; +  using difference_type = typename Container::difference_type; +  using const_reference = typename Container::const_reference; + +  Range(const Container& container) +    : Base(container.begin(), container.end()) +  { +  } + +  const_reference operator[](size_type pos) const +  { +    return *(this->begin() + pos); +  } + +  const_reference front() const { return *this->begin(); } +  const_reference back() const { return *std::prev(this->end()); } + +  Range& advance(difference_type amount) & +  { +    Base::advance(amount); +    return *this; +  } +  Range advance(difference_type amount) && +  { +    Base::advance(amount); +    return std::move(*this); +  } +}; + +using Arguments = Range<std::vector<std::string>>; + +bool CheckPathParametersEx(cmGeneratorExpressionContext* ctx, +                           const GeneratorExpressionContent* cnt, +                           cm::string_view option, std::size_t count, +                           int required = 1, bool exactly = true) +{ +  if (static_cast<int>(count) < required || +      (exactly && static_cast<int>(count) > required)) { +    reportError(ctx, cnt->GetOriginalExpression(), +                cmStrCat("$<PATH:", option, "> expression requires ", +                         (exactly ? "exactly" : "at least"), ' ', +                         (required == 1 ? "one parameter" : "two parameters"), +                         '.')); +    return false; +  } +  return true; +}; +bool CheckPathParameters(cmGeneratorExpressionContext* ctx, +                         const GeneratorExpressionContent* cnt, +                         cm::string_view option, const Arguments& args, +                         int required = 1) +{ +  return CheckPathParametersEx(ctx, cnt, option, args.size(), required); +}; +std::string ToString(bool isTrue) +{ +  return isTrue ? "1" : "0"; +}; +} + +static const struct PathNode : public cmGeneratorExpressionNode +{ +  PathNode() {} // NOLINT(modernize-use-equals-default) + +  int NumExpectedParameters() const override { return TwoOrMoreParameters; } + +  bool AcceptsArbitraryContentParameter() const override { return true; } + +  std::string Evaluate( +    const std::vector<std::string>& parameters, +    cmGeneratorExpressionContext* context, +    const GeneratorExpressionContent* content, +    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override +  { +    static std::unordered_map< +      cm::string_view, +      std::function<std::string(cmGeneratorExpressionContext*, +                                const GeneratorExpressionContent*, +                                Arguments&)>> +      pathCommands{ +        { "GET_ROOT_NAME"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "GET_ROOT_NAME"_s, args) && +                !args.front().empty() +              ? cmCMakePath{ args.front() }.GetRootName().String() +              : std::string{}; +          } }, +        { "GET_ROOT_DIRECTORY"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "GET_ROOT_DIRECTORY"_s, +                                       args) && +                !args.front().empty() +              ? cmCMakePath{ args.front() }.GetRootDirectory().String() +              : std::string{}; +          } }, +        { "GET_ROOT_PATH"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "GET_ROOT_PATH"_s, args) && +                !args.front().empty() +              ? cmCMakePath{ args.front() }.GetRootPath().String() +              : std::string{}; +          } }, +        { "GET_FILENAME"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "GET_FILENAME"_s, args) && +                !args.front().empty() +              ? cmCMakePath{ args.front() }.GetFileName().String() +              : std::string{}; +          } }, +        { "GET_EXTENSION"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            bool lastOnly = args.front() == "LAST_ONLY"_s; +            if (lastOnly) { +              args.advance(1); +            } +            if (CheckPathParametersEx(ctx, cnt, +                                      lastOnly ? "GET_EXTENSION,LAST_ONLY"_s +                                               : "GET_EXTENSION"_s, +                                      args.size())) { +              if (args.front().empty()) { +                return std::string{}; +              } +              return lastOnly +                ? cmCMakePath{ args.front() }.GetExtension().String() +                : cmCMakePath{ args.front() }.GetWideExtension().String(); +            } +            return std::string{}; +          } }, +        { "GET_STEM"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            bool lastOnly = args.front() == "LAST_ONLY"_s; +            if (lastOnly) { +              args.advance(1); +            } +            if (CheckPathParametersEx( +                  ctx, cnt, lastOnly ? "GET_STEM,LAST_ONLY"_s : "GET_STEM"_s, +                  args.size())) { +              if (args.front().empty()) { +                return std::string{}; +              } +              return lastOnly +                ? cmCMakePath{ args.front() }.GetStem().String() +                : cmCMakePath{ args.front() }.GetNarrowStem().String(); +            } +            return std::string{}; +          } }, +        { "GET_RELATIVE_PART"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "GET_RELATIVE_PART"_s, +                                       args) && +                !args.front().empty() +              ? cmCMakePath{ args.front() }.GetRelativePath().String() +              : std::string{}; +          } }, +        { "GET_PARENT_PATH"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "GET_PARENT_PATH"_s, args) +              ? cmCMakePath{ args.front() }.GetParentPath().String() +              : std::string{}; +          } }, +        { "HAS_ROOT_NAME"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "HAS_ROOT_NAME"_s, args) +              ? ToString(cmCMakePath{ args.front() }.HasRootName()) +              : std::string{ "0" }; +          } }, +        { "HAS_ROOT_DIRECTORY"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "HAS_ROOT_DIRECTORY"_s, args) +              ? ToString(cmCMakePath{ args.front() }.HasRootDirectory()) +              : std::string{ "0" }; +          } }, +        { "HAS_ROOT_PATH"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "HAS_ROOT_PATH"_s, args) +              ? ToString(cmCMakePath{ args.front() }.HasRootPath()) +              : std::string{ "0" }; +          } }, +        { "HAS_FILENAME"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "HAS_FILENAME"_s, args) +              ? ToString(cmCMakePath{ args.front() }.HasFileName()) +              : std::string{ "0" }; +          } }, +        { "HAS_EXTENSION"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "HAS_EXTENSION"_s, args) && +                !args.front().empty() +              ? ToString(cmCMakePath{ args.front() }.HasExtension()) +              : std::string{ "0" }; +          } }, +        { "HAS_STEM"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "HAS_STEM"_s, args) +              ? ToString(cmCMakePath{ args.front() }.HasStem()) +              : std::string{ "0" }; +          } }, +        { "HAS_RELATIVE_PART"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "HAS_RELATIVE_PART"_s, args) +              ? ToString(cmCMakePath{ args.front() }.HasRelativePath()) +              : std::string{ "0" }; +          } }, +        { "HAS_PARENT_PATH"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "HAS_PARENT_PATH"_s, args) +              ? ToString(cmCMakePath{ args.front() }.HasParentPath()) +              : std::string{ "0" }; +          } }, +        { "IS_ABSOLUTE"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "IS_ABSOLUTE"_s, args) +              ? ToString(cmCMakePath{ args.front() }.IsAbsolute()) +              : std::string{ "0" }; +          } }, +        { "IS_RELATIVE"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "IS_RELATIVE"_s, args) +              ? ToString(cmCMakePath{ args.front() }.IsRelative()) +              : std::string{ "0" }; +          } }, +        { "IS_PREFIX"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            bool normalize = args.front() == "NORMALIZE"_s; +            if (normalize) { +              args.advance(1); +            } +            if (CheckPathParametersEx(ctx, cnt, +                                      normalize ? "IS_PREFIX,NORMALIZE"_s +                                                : "IS_PREFIX"_s, +                                      args.size(), 2)) { +              if (normalize) { +                return ToString(cmCMakePath{ args[0] }.Normal().IsPrefix( +                  cmCMakePath{ args[1] }.Normal())); +              } +              return ToString( +                cmCMakePath{ args[0] }.IsPrefix(cmCMakePath{ args[1] })); +            } +            return std::string{}; +          } }, +        { "CMAKE_PATH"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            bool normalize = args.front() == "NORMALIZE"_s; +            if (normalize) { +              args.advance(1); +            } +            if (CheckPathParametersEx(ctx, cnt, +                                      normalize ? "CMAKE_PATH,NORMALIZE"_s +                                                : "CMAKE_PATH"_s, +                                      args.size(), 1)) { +              auto path = +                cmCMakePath{ args.front(), cmCMakePath::auto_format }; +              return normalize ? path.Normal().GenericString() +                               : path.GenericString(); +            } +            return std::string{}; +          } }, +        { "APPEND"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            if (CheckPathParametersEx(ctx, cnt, "APPEND"_s, args.size(), 1, +                                      false)) { +              cmCMakePath path; +              for (const auto& p : args) { +                path /= p; +              } +              return path.String(); +            } +            return std::string{}; +          } }, +        { "REMOVE_FILENAME"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "REMOVE_FILENAME"_s, args) && +                !args.front().empty() +              ? cmCMakePath{ args.front() }.RemoveFileName().String() +              : std::string{}; +          } }, +        { "REPLACE_FILENAME"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "REPLACE_FILENAME"_s, args, 2) +              ? cmCMakePath{ args[0] } +                  .ReplaceFileName(cmCMakePath{ args[1] }) +                  .String() +              : std::string{}; +          } }, +        { "REMOVE_EXTENSION"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            bool lastOnly = args.front() == "LAST_ONLY"_s; +            if (lastOnly) { +              args.advance(1); +            } +            if (CheckPathParametersEx(ctx, cnt, +                                      lastOnly ? "REMOVE_EXTENSION,LAST_ONLY"_s +                                               : "REMOVE_EXTENSION"_s, +                                      args.size())) { +              if (args.front().empty()) { +                return std::string{}; +              } +              return lastOnly +                ? cmCMakePath{ args.front() }.RemoveExtension().String() +                : cmCMakePath{ args.front() }.RemoveWideExtension().String(); +            } +            return std::string{}; +          } }, +        { "REPLACE_EXTENSION"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            bool lastOnly = args.front() == "LAST_ONLY"_s; +            if (lastOnly) { +              args.advance(1); +            } +            if (CheckPathParametersEx(ctx, cnt, +                                      lastOnly +                                        ? "REPLACE_EXTENSION,LAST_ONLY"_s +                                        : "REPLACE_EXTENSION"_s, +                                      args.size(), 2)) { +              if (lastOnly) { +                return cmCMakePath{ args[0] } +                  .ReplaceExtension(cmCMakePath{ args[1] }) +                  .String(); +              } +              return cmCMakePath{ args[0] } +                .ReplaceWideExtension(cmCMakePath{ args[1] }) +                .String(); +            } +            return std::string{}; +          } }, +        { "NORMAL_PATH"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "NORMAL_PATH"_s, args) && +                !args.front().empty() +              ? cmCMakePath{ args.front() }.Normal().String() +              : std::string{}; +          } }, +        { "RELATIVE_PATH"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            return CheckPathParameters(ctx, cnt, "RELATIVE_PATH"_s, args, 2) +              ? cmCMakePath{ args[0] }.Relative(args[1]).String() +              : std::string{}; +          } }, +        { "ABSOLUTE_PATH"_s, +          [](cmGeneratorExpressionContext* ctx, +             const GeneratorExpressionContent* cnt, +             Arguments& args) -> std::string { +            bool normalize = args.front() == "NORMALIZE"_s; +            if (normalize) { +              args.advance(1); +            } +            if (CheckPathParametersEx(ctx, cnt, +                                      normalize ? "ABSOLUTE_PATH,NORMALIZE"_s +                                                : "ABSOLUTE_PATH"_s, +                                      args.size(), 2)) { +              auto path = cmCMakePath{ args[0] }.Absolute(args[1]); +              return normalize ? path.Normal().String() : path.String(); +            } +            return std::string{}; +          } } +      }; + +    if (cm::contains(pathCommands, parameters.front())) { +      auto args = Arguments{ parameters }.advance(1); +      return pathCommands[parameters.front()](context, content, args); +    } + +    reportError(context, content->GetOriginalExpression(), +                cmStrCat(parameters.front(), ": invalid option.")); +    return std::string{}; +  } +} pathNode; + +static const struct PathEqualNode : public cmGeneratorExpressionNode +{ +  PathEqualNode() {} // NOLINT(modernize-use-equals-default) + +  int NumExpectedParameters() const override { return 2; } + +  std::string Evaluate( +    const std::vector<std::string>& parameters, +    cmGeneratorExpressionContext* /*context*/, +    const GeneratorExpressionContent* /*content*/, +    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override +  { +    return cmCMakePath{ parameters[0] } == cmCMakePath{ parameters[1] } ? "1" +                                                                        : "0"; +  } +} pathEqualNode; +  static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode  {    MakeCIdentifierNode() {} // NOLINT(modernize-use-equals-default) @@ -1198,6 +1650,162 @@ 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 +  { +    using ForGenex = cmGeneratorExpressionDAGChecker::ForGenex; + +    if (!context->HeadTarget || !dagChecker || +        !dagChecker->EvaluatingLinkLibraries(nullptr, +                                             ForGenex::LINK_LIBRARY)) { +      reportError(context, content->GetOriginalExpression(), +                  "$<LINK_LIBRARY:...> may only be used with binary targets " +                  "to specify link libraries through 'LINK_LIBRARIES', " +                  "'INTERFACE_LINK_LIBRARIES', and " +                  "'INTERFACE_LINK_LIBRARIES_DIRECT' properties."); +      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 +  { +    using ForGenex = cmGeneratorExpressionDAGChecker::ForGenex; + +    if (!context->HeadTarget || !dagChecker || +        !dagChecker->EvaluatingLinkLibraries(nullptr, ForGenex::LINK_GROUP)) { +      reportError( +        context, content->GetOriginalExpression(), +        "$<LINK_GROUP:...> may only be used with binary targets " +        "to specify group of link libraries through 'LINK_LIBRARIES', " +        "'INTERFACE_LINK_LIBRARIES', and " +        "'INTERFACE_LINK_LIBRARIES_DIRECT' properties."); +      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 +1877,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 @@ -1612,7 +2221,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode      const GeneratorExpressionContent* content,      cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override    { -    std::string tgtName = parameters.front(); +    std::string const& tgtName = parameters.front();      cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);      if (!gt) {        std::ostringstream e; @@ -1638,7 +2247,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" @@ -1700,7 +2309,7 @@ static const struct TargetRuntimeDllsNode : public cmGeneratorExpressionNode      const GeneratorExpressionContent* content,      cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override    { -    std::string tgtName = parameters.front(); +    std::string const& tgtName = parameters.front();      cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);      if (!gt) {        std::ostringstream e; @@ -1951,6 +2560,7 @@ class ArtifactPathTag;  class ArtifactPdbTag;  class ArtifactSonameTag;  class ArtifactBundleDirTag; +class ArtifactBundleDirNameTag;  class ArtifactBundleContentDirTag;  template <typename ArtifactT, typename ComponentT> @@ -2011,6 +2621,12 @@ struct TargetFilesystemArtifactDependency<ArtifactBundleDirTag,  {  };  template <> +struct TargetFilesystemArtifactDependency<ArtifactBundleDirNameTag, +                                          ArtifactPathTag> +  : TargetFilesystemArtifactDependencyCMP0112 +{ +}; +template <>  struct TargetFilesystemArtifactDependency<ArtifactBundleContentDirTag,                                            ArtifactPathTag>    : TargetFilesystemArtifactDependencyCMP0112 @@ -2138,6 +2754,41 @@ 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(); +    } + +    auto level = cmGeneratorTarget::BundleDirLevel; +    auto config = context->Config; +    if (target->IsAppBundleOnApple()) { +      return target->GetAppBundleDirectory(config, level); +    } +    if (target->IsFrameworkOnApple()) { +      return target->GetFrameworkDirectory(config, level); +    } +    if (target->IsCFBundleOnApple()) { +      return target->GetCFBundleDirectory(config, level); +    } +    return std::string(); +  } +}; + +template <>  struct TargetFilesystemArtifactResultCreator<ArtifactBundleContentDirTag>  {    static std::string Create(cmGeneratorTarget* target, @@ -2217,7 +2868,7 @@ protected:      cmGeneratorExpressionDAGChecker* dagChecker) const    {      // Lookup the referenced target. -    std::string name = parameters.front(); +    std::string const& name = parameters.front();      if (!cmGeneratorExpression::IsValidTargetName(name)) {        ::reportError(context, content->GetOriginalExpression(), @@ -2270,7 +2921,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 +2963,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 +3292,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 }, @@ -2644,6 +3301,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(      { "REMOVE_DUPLICATES", &removeDuplicatesNode },      { "LOWER_CASE", &lowerCaseNode },      { "UPPER_CASE", &upperCaseNode }, +    { "PATH", &pathNode }, +    { "PATH_EQUAL", &pathEqualNode },      { "MAKE_C_IDENTIFIER", &makeCIdentifierNode },      { "BOOL", &boolNode },      { "IF", &ifNode }, @@ -2668,6 +3327,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/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx index 794c1a1..bbee4d5 100644 --- a/Source/cmGeneratorExpressionParser.cxx +++ b/Source/cmGeneratorExpressionParser.cxx @@ -15,7 +15,6 @@  cmGeneratorExpressionParser::cmGeneratorExpressionParser(    std::vector<cmGeneratorExpressionToken> tokens)    : Tokens(std::move(tokens)) -  , NestingLevel(0)  {  } diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h index efaef3e..63273e4 100644 --- a/Source/cmGeneratorExpressionParser.h +++ b/Source/cmGeneratorExpressionParser.h @@ -26,5 +26,5 @@ private:    std::vector<cmGeneratorExpressionToken>::const_iterator it;    const std::vector<cmGeneratorExpressionToken> Tokens; -  unsigned int NestingLevel; +  unsigned int NestingLevel = 0;  }; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index fec4679..6235a2a 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -16,6 +16,7 @@  #include <utility>  #include <cm/memory> +#include <cm/optional>  #include <cm/string_view>  #include <cmext/algorithm>  #include <cmext/string_view> @@ -58,6 +59,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 <> @@ -331,20 +336,6 @@ EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(  cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)    : Target(t) -  , FortranModuleDirectoryCreated(false) -  , SourceFileFlagsConstructed(false) -  , PolicyWarnedCMP0022(false) -  , PolicyReportedCMP0069(false) -  , DebugIncludesDone(false) -  , DebugCompileOptionsDone(false) -  , DebugCompileFeaturesDone(false) -  , DebugCompileDefinitionsDone(false) -  , DebugLinkOptionsDone(false) -  , DebugLinkDirectoriesDone(false) -  , DebugPrecompileHeadersDone(false) -  , DebugSourcesDone(false) -  , UtilityItemsDone(false) -  , SourcesAreContextDependent(Tribool::Indeterminate)  {    this->Makefile = this->Target->GetMakefile();    this->LocalGenerator = lg; @@ -443,7 +434,7 @@ cmValue cmGeneratorTarget::GetProperty(const std::string& prop) const          cmTargetPropertyComputer::GetProperty(this, prop, *this->Makefile)) {      return result;    } -  if (cmSystemTools::GetFatalErrorOccured()) { +  if (cmSystemTools::GetFatalErrorOccurred()) {      return nullptr;    }    return this->Target->GetProperty(prop); @@ -748,6 +739,7 @@ void cmGeneratorTarget::ClearSourcesCache()    this->Objects.clear();    this->VisitedConfigsForObjects.clear();    this->LinkImplMap.clear(); +  this->LinkImplUsageRequirementsOnlyMap.clear();  }  void cmGeneratorTarget::ClearLinkInterfaceCache() @@ -1300,7 +1292,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 +1510,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 +1601,7 @@ void AddInterfaceEntries(  {    if (searchRuntime == IncludeRuntimeInterface::Yes) {      if (cmLinkImplementation const* impl = -          headTarget->GetLinkImplementation(config)) { +          headTarget->GetLinkImplementation(config, interfaceFor)) {        entries.HadContextSensitiveCondition =          impl->HadContextSensitiveCondition; @@ -1621,7 +1615,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 +1630,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 && @@ -1707,7 +1702,7 @@ void addFileSetEntry(cmGeneratorTarget const* headTarget,        }        bool found = false;        for (auto const& sg : headTarget->Makefile->GetSourceGroups()) { -        if (sg.MatchesFiles(path)) { +        if (sg.MatchChildrenFiles(path)) {            found = true;            break;          } @@ -2045,7 +2040,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") { @@ -2763,15 +2762,14 @@ cmGeneratorTarget::LinkClosure const* cmGeneratorTarget::GetLinkClosure(  class cmTargetSelectLinker  { -  int Preference; +  int Preference = 0;    cmGeneratorTarget const* Target;    cmGlobalGenerator* GG;    std::set<std::string> Preferred;  public:    cmTargetSelectLinker(cmGeneratorTarget const* target) -    : Preference(0) -    , Target(target) +    : Target(target)    {      this->GG = this->Target->GetLocalGenerator()->GetGlobalGenerator();    } @@ -2815,7 +2813,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 +3081,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 +3459,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 +3823,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 +4637,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 +4697,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;  } @@ -5675,7 +5699,7 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender,      if (emitted.insert(p).second) {        getLinkInterfaceDependentProperty<PropertyType>(depender, p, config, t,                                                        nullptr); -      if (cmSystemTools::GetErrorOccuredFlag()) { +      if (cmSystemTools::GetErrorOccurredFlag()) {          return;        }      } @@ -5754,25 +5778,25 @@ void cmGeneratorTarget::CheckPropertyCompatibility(      checkPropertyConsistency<bool>(this, dep.Target, strBool, emittedBools,                                     config, BoolType, nullptr); -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        return;      }      checkPropertyConsistency<const char*>(this, dep.Target, strString,                                            emittedStrings, config, StringType,                                            nullptr); -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        return;      }      checkPropertyConsistency<const char*>(this, dep.Target, strNumMin,                                            emittedMinNumbers, config,                                            NumberMinType, nullptr); -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        return;      }      checkPropertyConsistency<const char*>(this, dep.Target, strNumMax,                                            emittedMaxNumbers, config,                                            NumberMaxType, nullptr); -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        return;      }    } @@ -6327,7 +6351,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 +6398,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 +6696,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 +6723,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 +6838,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 +6861,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 +7207,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 +7274,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 +7301,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 +7312,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 +7453,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 +7556,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 +7681,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 +7714,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 +7969,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 +7977,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 +7994,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 +8007,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 +8018,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 +8140,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 +8247,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 +8510,217 @@ 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_INTERFACE_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; +  } + +  auto verifyValue = this->GetProperty("INTERFACE_HEADER_SETS_TO_VERIFY"); +  const bool all = verifyValue.IsEmpty(); +  std::set<std::string> verifySet; +  if (!all) { +    auto verifyList = cmExpandedList(verifyValue); +    verifySet.insert(verifyList.begin(), verifyList.end()); +  } + +  cmTarget* verifyTarget = nullptr; +  cmTarget* allVerifyTarget = +    this->GlobalGenerator->GetMakefiles().front()->FindTargetToUse( +      "all_verify_interface_header_sets", true); + +  auto interfaceFileSetEntries = this->Target->GetInterfaceHeaderSetsEntries(); + +  std::set<cmFileSet*> fileSets; +  for (auto const& entry : interfaceFileSetEntries) { +    for (auto const& name : cmExpandedList(entry.Value)) { +      if (all || verifySet.count(name)) { +        fileSets.insert(this->Target->GetFileSet(name)); +        verifySet.erase(name); +      } +    } +  } +  if (!verifySet.empty()) { +    this->Makefile->IssueMessage( +      MessageType::FATAL_ERROR, +      cmStrCat("Property INTERFACE_HEADER_SETS_TO_VERIFY of target \"", +               this->GetName(), +               "\" contained the following header sets that are nonexistent " +               "or not INTERFACE:\n  ", +               cmJoin(verifySet, "\n  "))); +    return false; +  } + +  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_interface_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"); +            cm::optional<std::map<std::string, cmValue>> +              perConfigCompileDefinitions; +            verifyTarget->FinalizeTargetConfiguration( +              this->Makefile->GetCompileDefinitionsEntries(), +              perConfigCompileDefinitions); + +            if (!allVerifyTarget) { +              allVerifyTarget = this->GlobalGenerator->GetMakefiles() +                                  .front() +                                  ->AddNewUtilityTarget( +                                    "all_verify_interface_header_sets", true); +            } + +            allVerifyTarget->AddUtility(verifyTarget->GetName(), false); +          } + +          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->empty()) { +        std::vector<std::string> languagesVector; +        this->GlobalGenerator->GetEnabledLanguages(languagesVector); +        languages->insert(languagesVector.begin(), languagesVector.end()); +      } +    } + +    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_interface_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..6bce7d2 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,12 +871,17 @@ 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);    std::string CreateFortranModuleDirectory(      std::string const& working_dir) const; -  mutable bool FortranModuleDirectoryCreated; +  mutable bool FortranModuleDirectoryCreated = false;    mutable std::string FortranModuleDirectory;    friend class cmTargetTraceDependencies; @@ -896,7 +906,7 @@ private:    mutable std::string ExportMacro;    void ConstructSourceFileFlags() const; -  mutable bool SourceFileFlagsConstructed; +  mutable bool SourceFileFlagsConstructed = false;    mutable std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;    mutable std::map<std::string, bool> DebugCompatiblePropertiesDone; @@ -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; @@ -1120,24 +1143,24 @@ private:    mutable OutputNameMapType OutputNameMap;    mutable std::set<cmLinkItem> UtilityItems;    cmPolicies::PolicyMap PolicyMap; -  mutable bool PolicyWarnedCMP0022; -  mutable bool PolicyReportedCMP0069; -  mutable bool DebugIncludesDone; -  mutable bool DebugCompileOptionsDone; -  mutable bool DebugCompileFeaturesDone; -  mutable bool DebugCompileDefinitionsDone; -  mutable bool DebugLinkOptionsDone; -  mutable bool DebugLinkDirectoriesDone; -  mutable bool DebugPrecompileHeadersDone; -  mutable bool DebugSourcesDone; -  mutable bool UtilityItemsDone; +  mutable bool PolicyWarnedCMP0022 = false; +  mutable bool PolicyReportedCMP0069 = false; +  mutable bool DebugIncludesDone = false; +  mutable bool DebugCompileOptionsDone = false; +  mutable bool DebugCompileFeaturesDone = false; +  mutable bool DebugCompileDefinitionsDone = false; +  mutable bool DebugLinkOptionsDone = false; +  mutable bool DebugLinkDirectoriesDone = false; +  mutable bool DebugPrecompileHeadersDone = false; +  mutable bool DebugSourcesDone = false; +  mutable bool UtilityItemsDone = false;    enum class Tribool    {      False = 0x0,      True = 0x1,      Indeterminate = 0x2    }; -  mutable Tribool SourcesAreContextDependent; +  mutable Tribool SourcesAreContextDependent = Tribool::Indeterminate;    bool ComputePDBOutputDir(const std::string& kind, const std::string& config,                             std::string& out) const; diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index abe7d32..1815c4d 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -15,7 +15,7 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,  {    if (args.size() < 3) {      status.SetError("called with incorrect number of arguments"); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -116,7 +116,7 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,    } else {      std::string err = "unknown component " + args[2];      status.SetError(err); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 4a25311..943ce1d 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -71,7 +71,7 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,    }    // The cmake variable in which to store the result. -  const std::string variable = args[0]; +  std::string const& variable = args[0];    std::string name;    std::string propertyName; 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 c75198d..0fe55f0 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -14,11 +14,13 @@  #include <utility>  #include <cm/memory> +#include <cm/optional>  #include <cmext/algorithm>  #include <cmext/string_view>  #include "cmsys/Directory.hxx"  #include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx"  #if defined(_WIN32) && !defined(__CYGWIN__)  #  include <windows.h> @@ -48,6 +50,8 @@  #include "cmState.h"  #include "cmStateDirectory.h"  #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h"  #include "cmValue.h"  #include "cmVersion.h"  #include "cmWorkingDirectory.h" @@ -61,10 +65,6 @@  #  include "cmQtAutoGenGlobalInitializer.h"  #endif -#if defined(_MSC_VER) && _MSC_VER >= 1800 -#  define KWSYS_WINDOWS_DEPRECATED_GetVersionEx -#endif -  const std::string kCMAKE_PLATFORM_INFO_INITIALIZED =    "CMAKE_PLATFORM_INFO_INITIALIZED"; @@ -440,7 +440,7 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)          << this->GetName() << "\".  CMAKE_MAKE_PROGRAM is not set.  You "          << "probably need to select a different build tool.";      cmSystemTools::Error(err.str()); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); @@ -530,7 +530,7 @@ void cmGlobalGenerator::EnableLanguage(    if (languages.empty()) {      cmSystemTools::Error("EnableLanguage must have a lang specified!"); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return;    } @@ -542,7 +542,7 @@ void cmGlobalGenerator::EnableLanguage(          << "' is currently being enabled.  "             "Recursive call not allowed.";        mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return;      }    } @@ -559,7 +559,7 @@ void cmGlobalGenerator::EnableLanguage(              << " which is not enabled.";            this->TryCompileOuterMakefile->IssueMessage(MessageType::FATAL_ERROR,                                                        e.str()); -          cmSystemTools::SetFatalErrorOccured(); +          cmSystemTools::SetFatalErrorOccurred();            return;          }        } @@ -615,34 +615,12 @@ void cmGlobalGenerator::EnableLanguage(    // what platform we are running on    if (!mf->GetDefinition("CMAKE_SYSTEM")) {  #if defined(_WIN32) && !defined(__CYGWIN__) -    /* Windows version number data.  */ -    OSVERSIONINFOEXW osviex; -    ZeroMemory(&osviex, sizeof(osviex)); -    osviex.dwOSVersionInfoSize = sizeof(osviex); - -#  ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx -#    pragma warning(push) -#    ifdef __INTEL_COMPILER -#      pragma warning(disable : 1478) -#    elif defined __clang__ -#      pragma clang diagnostic push -#      pragma clang diagnostic ignored "-Wdeprecated-declarations" -#    else -#      pragma warning(disable : 4996) -#    endif -#  endif -    GetVersionExW((OSVERSIONINFOW*)&osviex); -#  ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx -#    ifdef __clang__ -#      pragma clang diagnostic pop -#    else -#      pragma warning(pop) -#    endif -#  endif +    cmSystemTools::WindowsVersion windowsVersion = +      cmSystemTools::GetWindowsVersion();      std::ostringstream windowsVersionString; -    windowsVersionString << osviex.dwMajorVersion << "." -                         << osviex.dwMinorVersion << "." -                         << osviex.dwBuildNumber; +    windowsVersionString << windowsVersion.dwMajorVersion << "." +                         << windowsVersion.dwMinorVersion << "." +                         << windowsVersion.dwBuildNumber;      mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION", windowsVersionString.str());  #endif      // Read the DetermineSystem file @@ -658,28 +636,28 @@ void cmGlobalGenerator::EnableLanguage(      // Tell the generator about the instance, if any.      std::string instance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");      if (!this->SetGeneratorInstance(instance, mf)) { -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return;      }      // Tell the generator about the target system.      std::string system = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");      if (!this->SetSystemName(system, mf)) { -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return;      }      // Tell the generator about the platform, if any.      std::string platform = mf->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM");      if (!this->SetGeneratorPlatform(platform, mf)) { -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return;      }      // Tell the generator about the toolset, if any.      std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET");      if (!this->SetGeneratorToolset(toolset, false, mf)) { -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return;      } @@ -687,7 +665,39 @@ void cmGlobalGenerator::EnableLanguage(      if (!this->FindMakeProgram(mf)) {        return;      } + +    // One-time includes of user-provided project setup files +    mf->GetState()->SetInTopLevelIncludes(true); +    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); +        mf->GetState()->SetInTopLevelIncludes(false); +        return; +      } +      if (cmSystemTools::FileIsDirectory(absSetupFile)) { +        cmSystemTools::Error( +          "CMAKE_PROJECT_TOP_LEVEL_INCLUDES file is a directory: " + +          setupFile); +        mf->GetState()->SetInTopLevelIncludes(false); +        return; +      } +      if (!mf->ReadListFile(absSetupFile)) { +        cmSystemTools::Error( +          "Failed reading CMAKE_PROJECT_TOP_LEVEL_INCLUDES file: " + +          setupFile); +        mf->GetState()->SetInTopLevelIncludes(false); +        return; +      } +    }    } +  mf->GetState()->SetInTopLevelIncludes(false);    // Check that the languages are supported by the generator and its    // native build tool found above. @@ -752,13 +762,15 @@ void cmGlobalGenerator::EnableLanguage(          cmSystemTools::Error("Could not find cmake module file: " +                               determineCompiler);        } -      if (cmSystemTools::GetFatalErrorOccured()) { +      if (cmSystemTools::GetFatalErrorOccurred()) {          return;        }        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 @@ -919,7 +931,7 @@ void cmGlobalGenerator::EnableLanguage(    }    if (fatalError) { -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();    }    for (std::string const& lang : cur_languages) { @@ -1122,7 +1134,10 @@ std::string cmGlobalGenerator::GetLanguageFromExtension(const char* ext) const  {    // if there is an extension and it starts with . then move past the    // . because the extensions are not stored with a .  in the map -  if (ext && *ext == '.') { +  if (!ext) { +    return ""; +  } +  if (*ext == '.') {      ++ext;    }    auto const it = this->ExtensionToLanguage.find(ext); @@ -1336,7 +1351,7 @@ void cmGlobalGenerator::Configure()    if (this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE) {      std::ostringstream msg; -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        msg << "Configuring incomplete, errors occurred!";        const char* logs[] = { "CMakeOutput.log", "CMakeError.log", nullptr };        for (const char** log = logs; *log; ++log) { @@ -1487,7 +1502,7 @@ bool cmGlobalGenerator::Compute()    if (!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS()) {      return false;    } -  this->FinalizeTargetCompileInfo(); +  this->FinalizeTargetConfiguration();    this->CreateGenerationObjects(); @@ -1500,6 +1515,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; @@ -1604,7 +1624,7 @@ void cmGlobalGenerator::Generate()    for (auto& buildExpSet : this->BuildExportSets) {      if (!buildExpSet.second->GenerateImportFile()) { -      if (!cmSystemTools::GetErrorOccuredFlag()) { +      if (!cmSystemTools::GetErrorOccurredFlag()) {          this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,                                                 "Could not write export file.");        } @@ -1721,6 +1741,35 @@ 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; +      } +    } +  } + +  cmTarget* allVerifyTarget = this->Makefiles.front()->FindTargetToUse( +    "all_verify_interface_header_sets", true); +  if (allVerifyTarget) { +    this->LocalGenerators.front()->AddGeneratorTarget( +      cm::make_unique<cmGeneratorTarget>(allVerifyTarget, +                                         this->LocalGenerators.front().get())); +  } + +  return true; +} +  bool cmGlobalGenerator::AddAutomaticSources()  {    for (const auto& lg : this->LocalGenerators) { @@ -1737,6 +1786,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) { @@ -1776,46 +1826,21 @@ cmGlobalGenerator::CreateMSVC60LinkLineComputer(      cm::make_unique<cmMSVC60LinkLineComputer>(outputConverter, stateDir));  } -void cmGlobalGenerator::FinalizeTargetCompileInfo() +void cmGlobalGenerator::FinalizeTargetConfiguration()  {    std::vector<std::string> const langs =      this->CMakeInstance->GetState()->GetEnabledLanguages();    // Construct per-target generator information.    for (const auto& mf : this->Makefiles) { -    const cmBTStringRange noconfig_compile_definitions = +    const cmBTStringRange noConfigCompileDefinitions =        mf->GetCompileDefinitionsEntries(); +    cm::optional<std::map<std::string, cmValue>> perConfigCompileDefinitions;      for (auto& target : mf->GetTargets()) {        cmTarget* t = &target.second; -      if (t->GetType() == cmStateEnums::GLOBAL_TARGET) { -        continue; -      } - -      t->AppendBuildInterfaceIncludes(); - -      if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) { -        continue; -      } - -      for (auto const& def : noconfig_compile_definitions) { -        t->InsertCompileDefinition(def); -      } - -      cmPolicies::PolicyStatus polSt = -        mf->GetPolicyStatus(cmPolicies::CMP0043); -      if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) { -        std::vector<std::string> configs = -          mf->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); - -        for (std::string const& c : configs) { -          std::string defPropName = -            cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c)); -          if (cmValue val = mf->GetProperty(defPropName)) { -            t->AppendProperty(defPropName, *val); -          } -        } -      } +      t->FinalizeTargetConfiguration(noConfigCompileDefinitions, +                                     perConfigCompileDefinitions);      }      // The standard include directories for each language @@ -2524,6 +2549,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() && !cmHasPrefix(libname, name)) { +      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..6e3072b 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, @@ -682,7 +694,7 @@ private:    void WriteSummary();    void WriteSummary(cmGeneratorTarget* target); -  void FinalizeTargetCompileInfo(); +  void FinalizeTargetConfiguration();    virtual void ForceLinkerLanguages(); 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/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx index c8520b8..d4ff1e0 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.cxx +++ b/Source/cmGlobalMSYSMakefileGenerator.cxx @@ -42,34 +42,7 @@ std::string cmGlobalMSYSMakefileGenerator::FindMinGW(  void cmGlobalMSYSMakefileGenerator::EnableLanguage(    std::vector<std::string> const& l, cmMakefile* mf, bool optional)  { -  this->FindMakeProgram(mf); -  const std::string& makeProgram = -    mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); -  std::vector<std::string> locations; -  std::string makeloc = cmSystemTools::GetProgramPath(makeProgram); -  locations.push_back(this->FindMinGW(makeloc)); -  locations.push_back(makeloc); -  locations.push_back("/mingw/bin"); -  locations.push_back("c:/mingw/bin"); -  std::string tgcc = cmSystemTools::FindProgram("gcc", locations); -  std::string gcc = "gcc.exe"; -  if (!tgcc.empty()) { -    gcc = tgcc; -  } -  std::string tgxx = cmSystemTools::FindProgram("g++", locations); -  std::string gxx = "g++.exe"; -  if (!tgxx.empty()) { -    gxx = tgxx; -  } -  std::string trc = cmSystemTools::FindProgram("windres", locations); -  std::string rc = "windres.exe"; -  if (!trc.empty()) { -    rc = trc; -  }    mf->AddDefinition("MSYS", "1"); -  mf->AddDefinition("CMAKE_GENERATOR_CC", gcc); -  mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx); -  mf->AddDefinition("CMAKE_GENERATOR_RC", rc);    this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);    if (!mf->IsSet("CMAKE_AR") && !this->CMakeInstance->GetIsInTryCompile() && diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx index 54d048d..5a7edae 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.cxx +++ b/Source/cmGlobalMinGWMakefileGenerator.cxx @@ -19,37 +19,6 @@ cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator(cmake* cm)    cm->GetState()->SetMinGWMake(true);  } -void cmGlobalMinGWMakefileGenerator::EnableLanguage( -  std::vector<std::string> const& l, cmMakefile* mf, bool optional) -{ -  this->FindMakeProgram(mf); -  const std::string& makeProgram = -    mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); -  std::vector<std::string> locations; -  locations.push_back(cmSystemTools::GetProgramPath(makeProgram)); -  locations.push_back("/mingw/bin"); -  locations.push_back("c:/mingw/bin"); -  std::string tgcc = cmSystemTools::FindProgram("gcc", locations); -  std::string gcc = "gcc.exe"; -  if (!tgcc.empty()) { -    gcc = tgcc; -  } -  std::string tgxx = cmSystemTools::FindProgram("g++", locations); -  std::string gxx = "g++.exe"; -  if (!tgxx.empty()) { -    gxx = tgxx; -  } -  std::string trc = cmSystemTools::FindProgram("windres", locations); -  std::string rc = "windres.exe"; -  if (!trc.empty()) { -    rc = trc; -  } -  mf->AddDefinition("CMAKE_GENERATOR_CC", gcc); -  mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx); -  mf->AddDefinition("CMAKE_GENERATOR_RC", rc); -  this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); -} -  void cmGlobalMinGWMakefileGenerator::GetDocumentation(    cmDocumentationEntry& entry)  { diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h index 1574faf..92d495c 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.h +++ b/Source/cmGlobalMinGWMakefileGenerator.h @@ -36,11 +36,4 @@ public:    /** Get the documentation entry for this generator.  */    static void GetDocumentation(cmDocumentationEntry& entry); - -  /** -   * Try to determine system information such as shared library -   * extension, pthreads, byte order etc. -   */ -  virtual void EnableLanguage(std::vector<std::string> const& languages, -                              cmMakefile*, bool optional);  }; diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index 55748cf..eabacf6 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -61,7 +61,7 @@ bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf)                                  "'\n"                                  "failed with:\n ",                                  err)); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }      cmsys::RegularExpression regex( diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 4245037..acaed36 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -604,7 +604,7 @@ void cmGlobalNinjaGenerator::Generate()    this->WriteUnknownExplicitDependencies(*this->GetCommonFileStream());    this->WriteBuiltinTargets(*this->GetCommonFileStream()); -  if (cmSystemTools::GetErrorOccuredFlag()) { +  if (cmSystemTools::GetErrorOccurredFlag()) {      this->RulesFileStream->setstate(std::ios::failbit);      for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs(             cmMakefile::IncludeEmptyConfig)) { @@ -651,7 +651,7 @@ void cmGlobalNinjaGenerator::CleanMetaData()                                                        "'\n"                                                        "failed with:\n ",                                                        error)); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();      }    }; @@ -710,7 +710,7 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf)                                  "'\n"                                  "failed with:\n ",                                  error)); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }      this->NinjaVersion = cmTrimWhitespace(version); @@ -790,7 +790,7 @@ void cmGlobalNinjaGenerator::CheckNinjaCodePage()                                                      "'\n"                                                      "failed with:\n ",                                                      error)); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();    } else if (result == 0) {      std::istringstream outputStream(output);      std::string line; @@ -837,7 +837,7 @@ bool cmGlobalNinjaGenerator::CheckLanguages(        mf->IssueMessage(MessageType::FATAL_ERROR,                         "multiple values for CMAKE_OSX_ARCHITECTURES not "                         "supported with Swift"); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return false;      }    } @@ -870,7 +870,7 @@ bool cmGlobalNinjaGenerator::CheckCxxModuleSupport()        ;      /* clang-format on */      this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str()); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();    }    return false;  } @@ -891,7 +891,7 @@ bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const      ;    /* clang-format on */    mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); -  cmSystemTools::SetFatalErrorOccured(); +  cmSystemTools::SetFatalErrorOccurred();    return false;  } @@ -912,7 +912,7 @@ bool cmGlobalNinjaGenerator::CheckISPC(cmMakefile* mf) const      ;    /* clang-format on */    mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); -  cmSystemTools::SetFatalErrorOccured(); +  cmSystemTools::SetFatalErrorOccurred();    return false;  } @@ -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/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index ab9ca50..21aa89c 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -181,12 +181,12 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()      return;    } -  // get a local generator for some useful methods -  auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>( +  // The global dependency graph is expressed via the root local generator. +  auto& rootLG = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(      this->LocalGenerators[0]);    // Write the do not edit header. -  lg.WriteDisclaimer(makefileStream); +  rootLG.WriteDisclaimer(makefileStream);    // Write the main entry point target.  This must be the VERY first    // target so that make with no arguments will run it. @@ -196,10 +196,10 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()    depends.emplace_back("all");    // Write the rule. -  lg.WriteMakeRule(makefileStream, -                   "Default target executed when no arguments are " -                   "given to make.", -                   "default_target", depends, no_commands, true); +  rootLG.WriteMakeRule(makefileStream, +                       "Default target executed when no arguments are " +                       "given to make.", +                       "default_target", depends, no_commands, true);    depends.clear(); @@ -210,22 +210,22 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()    }    // Write out the "special" stuff -  lg.WriteSpecialTargetsTop(makefileStream); +  rootLG.WriteSpecialTargetsTop(makefileStream);    // Write the directory level rules.    for (auto const& it : this->ComputeDirectoryTargets()) { -    this->WriteDirectoryRules2(makefileStream, it.second); +    this->WriteDirectoryRules2(makefileStream, rootLG, it.second);    }    // Write the target convenience rules    for (const auto& localGen : this->LocalGenerators) {      this->WriteConvenienceRules2( -      makefileStream, +      makefileStream, rootLG,        cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen));    }    // Write special bottom targets -  lg.WriteSpecialTargetsBottom(makefileStream); +  rootLG.WriteSpecialTargetsBottom(makefileStream);  }  void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() @@ -359,8 +359,9 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(  }  void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2( -  std::ostream& ruleFileStream, DirectoryTarget const& dt, const char* pass, -  bool check_all, bool check_relink, std::vector<std::string> const& commands) +  std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3& rootLG, +  DirectoryTarget const& dt, const char* pass, bool check_all, +  bool check_relink, std::vector<std::string> const& commands)  {    auto* lg = static_cast<cmLocalUnixMakefileGenerator3*>(dt.LG);    std::string makeTarget = @@ -406,19 +407,21 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(    } else {      doc = cmStrCat("Recursive \"", pass, "\" directory target.");    } -  lg->WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends, commands, -                    true); + +  rootLG.WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends, +                       commands, true);  }  void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2( -  std::ostream& ruleFileStream, DirectoryTarget const& dt) +  std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3& rootLG, +  DirectoryTarget const& dt)  {    auto* lg = static_cast<cmLocalUnixMakefileGenerator3*>(dt.LG);    // Begin the directory-level rules section.    {      std::string dir = cmSystemTools::ConvertToOutputPath( -      lg->MaybeRelativeToTopBinDir(lg->GetCurrentBinaryDirectory())); -    lg->WriteDivider(ruleFileStream); +      rootLG.MaybeRelativeToTopBinDir(lg->GetCurrentBinaryDirectory())); +    rootLG.WriteDivider(ruleFileStream);      if (lg->IsRootMakefile()) {        ruleFileStream << "# Directory level rules for the build root directory";      } else { @@ -428,16 +431,18 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(    }    // Write directory-level rules for "all". -  this->WriteDirectoryRule2(ruleFileStream, dt, "all", true, false); +  this->WriteDirectoryRule2(ruleFileStream, rootLG, dt, "all", true, false);    // Write directory-level rules for "preinstall". -  this->WriteDirectoryRule2(ruleFileStream, dt, "preinstall", true, true); +  this->WriteDirectoryRule2(ruleFileStream, rootLG, dt, "preinstall", true, +                            true);    // Write directory-level rules for "clean".    {      std::vector<std::string> cmds;      lg->AppendDirectoryCleanCommand(cmds); -    this->WriteDirectoryRule2(ruleFileStream, dt, "clean", false, false, cmds); +    this->WriteDirectoryRule2(ruleFileStream, rootLG, dt, "clean", false, +                              false, cmds);    }  } @@ -632,7 +637,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(  }  void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( -  std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3& lg) +  std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3& rootLG, +  cmLocalUnixMakefileGenerator3& lg)  {    std::vector<std::string> depends;    std::vector<std::string> commands; @@ -696,8 +702,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(        }        this->AppendGlobalTargetDepends(depends, gtarget.get()); -      lg.WriteMakeRule(ruleFileStream, "All Build rule for target.", localName, -                       depends, commands, true); +      rootLG.WriteMakeRule(ruleFileStream, "All Build rule for target.", +                           localName, depends, commands, true);        // Write the rule.        commands.clear(); @@ -731,16 +737,16 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(        }        localName =          cmStrCat(lg.GetRelativeTargetDirectory(gtarget.get()), "/rule"); -      lg.WriteMakeRule(ruleFileStream, -                       "Build rule for subdir invocation for target.", -                       localName, depends, commands, true); +      rootLG.WriteMakeRule(ruleFileStream, +                           "Build rule for subdir invocation for target.", +                           localName, depends, commands, true);        // Add a target with the canonical name (no prefix, suffix or path).        commands.clear();        depends.clear();        depends.push_back(localName); -      lg.WriteMakeRule(ruleFileStream, "Convenience name for target.", name, -                       depends, commands, true); +      rootLG.WriteMakeRule(ruleFileStream, "Convenience name for target.", +                           name, depends, commands, true);        // Add rules to prepare the target for installation.        if (gtarget->NeedRelinkBeforeInstall(lg.GetConfigName())) { @@ -749,8 +755,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(          depends.clear();          commands.clear();          commands.push_back(lg.GetRecursiveMakeCall(makefileName, localName)); -        lg.WriteMakeRule(ruleFileStream, "Pre-install relink rule for target.", -                         localName, depends, commands, true); +        rootLG.WriteMakeRule(ruleFileStream, +                             "Pre-install relink rule for target.", localName, +                             depends, commands, true);        }        // add the clean rule @@ -760,8 +767,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(        commands.clear();        commands.push_back(          lg.GetRecursiveMakeCall(makefileName, makeTargetName)); -      lg.WriteMakeRule(ruleFileStream, "clean rule for target.", -                       makeTargetName, depends, commands, true); +      rootLG.WriteMakeRule(ruleFileStream, "clean rule for target.", +                           makeTargetName, depends, commands, true);        commands.clear();      }    } diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 5157826..b9d333e 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -200,13 +200,16 @@ protected:    void WriteMainCMakefile();    void WriteConvenienceRules2(std::ostream& ruleFileStream, -                              cmLocalUnixMakefileGenerator3&); +                              cmLocalUnixMakefileGenerator3& rootLG, +                              cmLocalUnixMakefileGenerator3& lg);    void WriteDirectoryRule2(std::ostream& ruleFileStream, +                           cmLocalUnixMakefileGenerator3& rootLG,                             DirectoryTarget const& dt, const char* pass,                             bool check_all, bool check_relink,                             std::vector<std::string> const& commands = {});    void WriteDirectoryRules2(std::ostream& ruleFileStream, +                            cmLocalUnixMakefileGenerator3& rootLG,                              DirectoryTarget const& dt);    void AppendGlobalTargetDepends(std::vector<std::string>& depends, diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index db54b86..29eeb5a 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -254,7 +254,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(        "that is not an absolute path to an existing directory.";      /* clang-format on */      mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -955,7 +955,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)    if (!cmSystemTools::MakeDirectory(wd)) {      std::string e = "Failed to make directory:\n  " + wd;      mf->IssueMessage(MessageType::FATAL_ERROR, e); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -1086,7 +1086,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)        e << "Exit code: " << ret << "\n";      }      mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    this->VCTargetsPath = regex.match(1); @@ -1319,7 +1319,7 @@ bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)        << "  http://msdn.microsoft.com/en-us/windows/bb980924.aspx";      /* clang-format on */      mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str()); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }  } diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index 12ffa5b..600ee0a 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -138,7 +138,8 @@ bool cmGlobalVisualStudio12Generator::MatchesGeneratorName(  bool cmGlobalVisualStudio12Generator::ProcessGeneratorToolsetField(    std::string const& key, std::string const& value)  { -  if (key == "host" && (value == "x64" || value == "x86")) { +  if (key == "host" && +      (value == "x64" || value == "x86" || value == "ARM64")) {      this->GeneratorToolsetHostArchitecture = value;      return true;    } diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index ce943a2..758ce83 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -180,7 +180,7 @@ void cmGlobalVisualStudio71Generator::WriteExternalProject(      fout << "\tProjectSection(ProjectDependencies) = postProject\n";      for (BT<std::pair<std::string, bool>> const& it : depends) {        std::string const& dep = it.Value.first; -      if (!dep.empty()) { +      if (this->IsDepInSolution(dep)) {          fout << "\t\t{" << this->GetGUID(dep) << "} = {" << this->GetGUID(dep)               << "}\n";        } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 134937e..f7f7317 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -298,7 +298,7 @@ void cmGlobalVisualStudio7Generator::Generate()    this->OutputSLNFile();    // If any solution or project files changed during the generation,    // tell Visual Studio to reload them... -  if (!cmSystemTools::GetErrorOccuredFlag() && +  if (!cmSystemTools::GetErrorOccurredFlag() &&        !this->LocalGenerators.empty()) {      this->CallVisualStudioMacro(MacroReload,                                  GetSLNFile(this->LocalGenerators[0].get())); @@ -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..c6af20a 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -837,6 +837,18 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(    return languages.size() == 1 && *languages.begin() == "Fortran";  } +bool cmGlobalVisualStudioGenerator::IsInSolution( +  const cmGeneratorTarget* gt) const +{ +  return gt->IsInBuildSystem(); +} + +bool cmGlobalVisualStudioGenerator::IsDepInSolution( +  const std::string& targetName) const +{ +  return !targetName.empty(); +} +  bool cmGlobalVisualStudioGenerator::TargetCompare::operator()(    cmGeneratorTarget const* l, cmGeneratorTarget const* r) const  { diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index cb1b14b..f45b4d4 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -98,6 +98,12 @@ 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; + +  // return true if project dependency should be included in solution. +  virtual bool IsDepInSolution(const std::string& targetName) const; +    /** Get the top-level registry key for this VS version.  */    std::string GetRegistryBase(); diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index bc38335..7e36881 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -25,50 +25,100 @@  #include "cmVSSetupHelper.h"  #include "cmake.h" -#if defined(_M_ARM64) -#  define HOST_PLATFORM_NAME "ARM64" -#  define HOST_TOOLS_ARCH "" -#elif defined(_M_ARM) -#  define HOST_PLATFORM_NAME "ARM" -#  define HOST_TOOLS_ARCH "" -#elif defined(_M_IA64) -#  define HOST_PLATFORM_NAME "Itanium" -#  define HOST_TOOLS_ARCH "" -#elif defined(_WIN64) -#  define HOST_PLATFORM_NAME "x64" -#  define HOST_TOOLS_ARCH "x64" -#else +#ifndef IMAGE_FILE_MACHINE_ARM64 +#  define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian +#endif +  static bool VSIsWow64()  {    BOOL isWow64 = false;    return IsWow64Process(GetCurrentProcess(), &isWow64) && isWow64;  } + +static bool VSIsArm64Host() +{ +  typedef BOOL(WINAPI * CM_ISWOW64PROCESS2)( +    HANDLE hProcess, USHORT * pProcessMachine, USHORT * pNativeMachine); + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#  define CM_VS_GCC_DIAGNOSTIC_PUSHED +#  pragma GCC diagnostic push +#  pragma GCC diagnostic ignored "-Wcast-function-type"  #endif +  static const CM_ISWOW64PROCESS2 s_IsWow64Process2Impl = +    (CM_ISWOW64PROCESS2)GetProcAddress( +      GetModuleHandleW(L"api-ms-win-core-wow64-l1-1-1.dll"), +      "IsWow64Process2"); +#ifdef CM_VS_GCC_DIAGNOSTIC_PUSHED +#  pragma GCC diagnostic pop +#  undef CM_VS_GCC_DIAGNOSTIC_PUSHED +#endif + +  USHORT processMachine, nativeMachine; + +  return s_IsWow64Process2Impl != nullptr && +    s_IsWow64Process2Impl(GetCurrentProcess(), &processMachine, +                          &nativeMachine) && +    nativeMachine == IMAGE_FILE_MACHINE_ARM64; +} + +static bool VSHasDotNETFrameworkArm64() +{ +  std::string dotNetArm64; +  return cmSystemTools::ReadRegistryValue( +    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\.NETFramework;InstallRootArm64", +    dotNetArm64, cmSystemTools::KeyWOW64_64); +} + +static bool VSIsWindows11OrGreater() +{ +  cmSystemTools::WindowsVersion const windowsVersion = +    cmSystemTools::GetWindowsVersion(); +  return (windowsVersion.dwMajorVersion > 10 || +          (windowsVersion.dwMajorVersion == 10 && +           windowsVersion.dwMinorVersion > 0) || +          (windowsVersion.dwMajorVersion == 10 && +           windowsVersion.dwMinorVersion == 0 && +           windowsVersion.dwBuildNumber >= 22000)); +}  static std::string VSHostPlatformName()  { -#ifdef HOST_PLATFORM_NAME -  return HOST_PLATFORM_NAME; -#else -  if (VSIsWow64()) { +  if (VSIsArm64Host()) { +    return "ARM64"; +  } else if (VSIsWow64()) {      return "x64";    } else { +#if defined(_M_ARM) +    return "ARM"; +#elif defined(_M_IA64) +    return "Itanium"; +#elif defined(_WIN64) +    return "x64"; +#else      return "Win32"; -  }  #endif +  }  } -static std::string VSHostArchitecture() +static std::string VSHostArchitecture( +  cmGlobalVisualStudioGenerator::VSVersion v)  { -#ifdef HOST_TOOLS_ARCH -  return HOST_TOOLS_ARCH; -#else -  if (VSIsWow64()) { +  if (VSIsArm64Host()) { +    return v >= cmGlobalVisualStudioGenerator::VSVersion::VS17 ? "ARM64" : ""; +  } else if (VSIsWow64()) {      return "x64";    } else { +#if defined(_M_ARM) +    return ""; +#elif defined(_M_IA64) +    return ""; +#elif defined(_WIN64) +    return "x64"; +#else      return "x86"; -  }  #endif +  }  }  static unsigned int VSVersionToMajor( @@ -433,7 +483,8 @@ cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator(    this->DefaultLinkFlagTableName = VSVersionToToolset(this->Version);    if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS16) {      this->DefaultPlatformName = VSHostPlatformName(); -    this->DefaultPlatformToolsetHostArchitecture = VSHostArchitecture(); +    this->DefaultPlatformToolsetHostArchitecture = +      VSHostArchitecture(this->Version);    }    if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS17) {      // FIXME: Search for an existing framework?  Under '%ProgramFiles(x86)%', @@ -881,7 +932,7 @@ cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommandEarly(cmMakefile* mf)  {    std::string instance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");    if (!this->SetGeneratorInstance(instance, mf)) { -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return {};    }    return this->cmGlobalVisualStudio14Generator::FindMSBuildCommandEarly(mf); @@ -895,9 +946,24 @@ std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand()    std::string vs;    if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) {      if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS17) { -      msbuild = vs + "/MSBuild/Current/Bin/amd64/MSBuild.exe"; -      if (cmSystemTools::FileExists(msbuild)) { -        return msbuild; +      if (VSIsArm64Host()) { +        if (VSHasDotNETFrameworkArm64()) { +          msbuild = vs + "/MSBuild/Current/Bin/arm64/MSBuild.exe"; +          if (cmSystemTools::FileExists(msbuild)) { +            return msbuild; +          } +        } +        if (VSIsWindows11OrGreater()) { +          msbuild = vs + "/MSBuild/Current/Bin/amd64/MSBuild.exe"; +          if (cmSystemTools::FileExists(msbuild)) { +            return msbuild; +          } +        } +      } else { +        msbuild = vs + "/MSBuild/Current/Bin/amd64/MSBuild.exe"; +        if (cmSystemTools::FileExists(msbuild)) { +          return msbuild; +        }        }      }      msbuild = vs + "/MSBuild/Current/Bin/MSBuild.exe"; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 203addd..23c365a 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -556,7 +556,7 @@ void cmGlobalXCodeGenerator::AddExtraIDETargets()  void cmGlobalXCodeGenerator::Generate()  {    this->cmGlobalGenerator::Generate(); -  if (cmSystemTools::GetErrorOccuredFlag()) { +  if (cmSystemTools::GetErrorOccurredFlag()) {      return;    } @@ -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;      } @@ -2385,8 +2393,13 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,    // Add preprocessor definitions for this target and configuration.    BuildObjectListOrString ppDefs(this, true); -  this->AppendDefines( -    ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\""); +  if (languages.count("Swift")) { +    // FIXME: Xcode warns that Swift does not support definition values. +    // C/CXX sources mixed in Swift targets will not see CMAKE_INTDIR. +  } else { +    this->AppendDefines( +      ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\""); +  }    if (const std::string* exportMacro = gtgt->GetExportMacro()) {      // Add the export symbol definition for shared library objects.      this->AppendDefines(ppDefs, exportMacro->c_str()); @@ -3064,6 +3077,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 +3090,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,21 +3617,23 @@ 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 { +      linkDir = cmSystemTools::GetParentDirectory(linkDir);        if (std::find(linkSearchPaths.begin(), linkSearchPaths.end(), linkDir) ==            linkSearchPaths.end()) {          linkSearchPaths.push_back(linkDir);        }      } -    // Add target dependency +      if (libItem->Target && !libItem->Target->IsImported()) {        for (auto const& configName : this->CurrentConfigurationTypes) {          target->AddDependTarget(configName, libItem->Target->GetName()); @@ -3729,22 +3807,35 @@ 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)); +            } +            if (libName.GetFeatureName() == "__CMAKE_LINK_FRAMEWORK"_s) { +              // use the full path +              libPaths.Add( +                libName.GetFormattedItem(this->XCodeEscapePath(cleanPath)) +                  .Value); +            } else { +              libPaths.Add( +                libName +                  .GetFormattedItem(this->XCodeEscapePath(fwItems->second)) +                  .Value);              } -            libPaths.Add("-framework " + this->XCodeEscapePath(fwName));            } 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 +4003,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 +4349,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 +4804,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 +4952,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 +4987,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/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index ab18e2a..2bb438d 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -109,18 +109,6 @@ cmGraphVizWriter::cmGraphVizWriter(std::string const& fileName,    , GraphHeader("node [\n  fontsize = \"12\"\n];")    , GraphNodePrefix("node")    , GlobalGenerator(globalGenerator) -  , NextNodeId(0) -  , GenerateForExecutables(true) -  , GenerateForStaticLibs(true) -  , GenerateForSharedLibs(true) -  , GenerateForModuleLibs(true) -  , GenerateForInterfaceLibs(true) -  , GenerateForObjectLibs(true) -  , GenerateForUnknownLibs(true) -  , GenerateForCustomTargets(false) -  , GenerateForExternals(true) -  , GeneratePerTarget(true) -  , GenerateDependers(true)  {  } diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h index 0912fc8..24dbe52 100644 --- a/Source/cmGraphVizWriter.h +++ b/Source/cmGraphVizWriter.h @@ -119,19 +119,19 @@ private:    cmGlobalGenerator const* GlobalGenerator; -  int NextNodeId; +  int NextNodeId = 0;    // maps from the actual item names to node names in dot:    std::map<std::string, std::string> NodeNames; -  bool GenerateForExecutables; -  bool GenerateForStaticLibs; -  bool GenerateForSharedLibs; -  bool GenerateForModuleLibs; -  bool GenerateForInterfaceLibs; -  bool GenerateForObjectLibs; -  bool GenerateForUnknownLibs; -  bool GenerateForCustomTargets; -  bool GenerateForExternals; -  bool GeneratePerTarget; -  bool GenerateDependers; +  bool GenerateForExecutables = true; +  bool GenerateForStaticLibs = true; +  bool GenerateForSharedLibs = true; +  bool GenerateForModuleLibs = true; +  bool GenerateForInterfaceLibs = true; +  bool GenerateForObjectLibs = true; +  bool GenerateForUnknownLibs = true; +  bool GenerateForCustomTargets = false; +  bool GenerateForExternals = true; +  bool GeneratePerTarget = true; +  bool GenerateDependers = true;  }; diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 55f6453..0da72b1 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -73,15 +73,15 @@ 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); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          return true;        } @@ -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( @@ -102,7 +103,7 @@ bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,          mf.GetCMakeInstance()->IssueMessage(            MessageType::FATAL_ERROR,            "An ELSEIF command was found after an ELSE command.", elseifBT); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          return true;        } @@ -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; @@ -131,7 +133,7 @@ bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,              cmStrCat(cmIfCommandError(expandedArguments), errorString);            mf.GetCMakeInstance()->IssueMessage(messType, err, elseifBT);            if (messType == MessageType::FATAL_ERROR) { -            cmSystemTools::SetFatalErrorOccured(); +            cmSystemTools::SetFatalErrorOccurred();              return true;            }          } @@ -186,7 +188,7 @@ bool cmIfCommand(std::vector<cmListFileArgument> const& args,        cmStrCat("if ", cmIfCommandError(expandedArguments), errorString);      if (status == MessageType::FATAL_ERROR) {        makefile.IssueMessage(MessageType::FATAL_ERROR, err); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return true;      }      makefile.IssueMessage(status, err); diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx index 7b0320c..9242344 100644 --- a/Source/cmIncludeCommand.cxx +++ b/Source/cmIncludeCommand.cxx @@ -177,7 +177,7 @@ bool cmIncludeCommand(std::vector<std::string> const& args,        resultVarName, readit ? fname_abs.c_str() : "NOTFOUND");    } -  if (!optional && !readit && !cmSystemTools::GetFatalErrorOccured()) { +  if (!optional && !readit && !cmSystemTools::GetFatalErrorOccurred()) {      std::string m = cmStrCat("could not load requested file:\n  ", fname);      status.SetError(m);      return false; 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..d358763 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" @@ -19,7 +20,6 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(    bool optional, cmListFileBacktrace backtrace)    : cmInstallGenerator(dest, configurations, component, message,                         exclude_from_all, false, std::move(backtrace)) -  , LocalGenerator(nullptr)    , Directories(dirs)    , FilePermissions(std::move(file_permissions))    , DirPermissions(std::move(dir_permissions)) diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h index 0f91a59..7deb9ba 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 @@ -42,7 +42,7 @@ protected:    void AddDirectoryInstallRule(std::ostream& os, const std::string& config,                                 Indent indent,                                 std::vector<std::string> const& dirs); -  cmLocalGenerator* LocalGenerator; +  cmLocalGenerator* LocalGenerator = nullptr;    std::vector<std::string> const Directories;    std::string const FilePermissions;    std::string const DirPermissions; diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 9cb376d..b80437d 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" @@ -32,7 +32,6 @@ cmInstallExportGenerator::cmInstallExportGenerator(    , FileName(std::move(filename))    , Namespace(std::move(name_space))    , ExportOld(exportOld) -  , LocalGenerator(nullptr)  {    if (android) {  #ifndef CMAKE_BOOTSTRAP @@ -52,73 +51,36 @@ bool cmInstallExportGenerator::Compute(cmLocalGenerator* lg)    return this->ExportSet->Compute(lg);  } -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) @@ -193,18 +155,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..02fe1fa 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,15 +57,15 @@ 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;    std::string const FileName;    std::string const Namespace;    bool const ExportOld; -  cmLocalGenerator* LocalGenerator; +  cmLocalGenerator* LocalGenerator = nullptr;    std::string TempDir;    std::string MainImportFile; 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..18a852b 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; @@ -18,7 +19,6 @@ cmInstallFilesGenerator::cmInstallFilesGenerator(    bool optional, cmListFileBacktrace backtrace)    : cmInstallGenerator(dest, configurations, component, message,                         exclude_from_all, false, std::move(backtrace)) -  , LocalGenerator(nullptr)    , Files(files)    , FilePermissions(std::move(file_permissions))    , Rename(std::move(rename)) diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index af7f113..53076b3 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 @@ -44,7 +44,7 @@ protected:                             Indent indent,                             std::vector<std::string> const& files); -  cmLocalGenerator* LocalGenerator; +  cmLocalGenerator* LocalGenerator = nullptr;    std::vector<std::string> const Files;    std::string const FilePermissions;    std::string const Rename; 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/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx index bec98b6..a5625fe 100644 --- a/Source/cmInstallScriptGenerator.cxx +++ b/Source/cmInstallScriptGenerator.cxx @@ -20,7 +20,6 @@ cmInstallScriptGenerator::cmInstallScriptGenerator(                         std::move(backtrace))    , Script(std::move(script))    , Code(code) -  , AllowGenex(false)  {    // We need per-config actions if the script has generator expressions.    if (cmGeneratorExpression::Find(this->Script) != std::string::npos) { diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h index 2cf6a4b..c3a7058 100644 --- a/Source/cmInstallScriptGenerator.h +++ b/Source/cmInstallScriptGenerator.h @@ -41,5 +41,5 @@ protected:    std::string const Script;    bool const Code;    cmLocalGenerator* LocalGenerator; -  bool AllowGenex; +  bool AllowGenex = false;  }; 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/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index ae11afc..16c5002 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -50,7 +50,6 @@ cmInstallTargetGenerator::cmInstallTargetGenerator(    : cmInstallGenerator(dest, configurations, component, message,                         exclude_from_all, false, std::move(backtrace))    , TargetName(std::move(targetName)) -  , Target(nullptr)    , FilePermissions(std::move(file_permissions))    , ImportLibrary(implib)    , Optional(optional) diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 6173f2c..3fc4b59 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -118,7 +118,7 @@ protected:    void IssueCMP0095Warning(const std::string& unescapedRpath);    std::string const TargetName; -  cmGeneratorTarget* Target; +  cmGeneratorTarget* Target = nullptr;    std::string const FilePermissions;    NamelinkModeType NamelinkMode;    bool const ImportLibrary; 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/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 5646368..b1e9e56 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -18,10 +18,6 @@ cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,                                         cmStateDirectory const& stateDir)    : StateDir(stateDir)    , OutputConverter(outputConverter) -  , ForResponse(false) -  , UseWatcomQuote(false) -  , UseNinjaMulti(false) -  , Relink(false)  {  } @@ -75,14 +71,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/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h index a1dafc4..9fb222c 100644 --- a/Source/cmLinkLineComputer.h +++ b/Source/cmLinkLineComputer.h @@ -67,8 +67,8 @@ protected:    cmStateDirectory StateDir;    cmOutputConverter* OutputConverter; -  bool ForResponse; -  bool UseWatcomQuote; -  bool UseNinjaMulti; -  bool Relink; +  bool ForResponse = false; +  bool UseWatcomQuote = false; +  bool UseNinjaMulti = false; +  bool Relink = false;  }; 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/cmListCommand.cxx b/Source/cmListCommand.cxx index 56345df..d412534 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -229,7 +229,7 @@ bool HandleAppendCommand(std::vector<std::string> const& args,    // If `listString` or `args` is empty, no need to append `;`,    // then index is going to be `1` and points to the end-of-string ";"    auto const offset = -    std::string::size_type(listString.empty() || args.empty()); +    static_cast<std::string::size_type>(listString.empty() || args.empty());    listString += &";"[offset] + cmJoin(cmMakeRange(args).advance(2), ";");    makefile.AddDefinition(listName, listString); @@ -255,7 +255,7 @@ bool HandlePrependCommand(std::vector<std::string> const& args,    // If `listString` or `args` is empty, no need to append `;`,    // then `offset` is going to be `1` and points to the end-of-string ";"    auto const offset = -    std::string::size_type(listString.empty() || args.empty()); +    static_cast<std::string::size_type>(listString.empty() || args.empty());    listString.insert(0,                      cmJoin(cmMakeRange(args).advance(2), ";") + &";"[offset]); @@ -1199,7 +1199,7 @@ bool HandleSortCommand(std::vector<std::string> const& args,    const std::string messageHint = "sub-command SORT ";    while (argumentIndex < args.size()) { -    const std::string option = args[argumentIndex++]; +    std::string const& option = args[argumentIndex++];      if (option == "COMPARE") {        if (sortCompare != cmStringSorter::Compare::UNINITIALIZED) {          std::string error = cmStrCat(messageHint, "option \"", option, @@ -1208,7 +1208,7 @@ bool HandleSortCommand(std::vector<std::string> const& args,          return false;        }        if (argumentIndex < args.size()) { -        const std::string argument = args[argumentIndex++]; +        std::string const& argument = args[argumentIndex++];          if (argument == "STRING") {            sortCompare = cmStringSorter::Compare::STRING;          } else if (argument == "FILE_BASENAME") { @@ -1235,7 +1235,7 @@ bool HandleSortCommand(std::vector<std::string> const& args,          return false;        }        if (argumentIndex < args.size()) { -        const std::string argument = args[argumentIndex++]; +        std::string const& argument = args[argumentIndex++];          if (argument == "SENSITIVE") {            sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE;          } else if (argument == "INSENSITIVE") { @@ -1259,7 +1259,7 @@ bool HandleSortCommand(std::vector<std::string> const& args,          return false;        }        if (argumentIndex < args.size()) { -        const std::string argument = args[argumentIndex++]; +        std::string const& argument = args[argumentIndex++];          if (argument == "ASCENDING") {            sortOrder = cmStringSorter::Order::ASCENDING;          } else if (argument == "DESCENDING") { @@ -1346,7 +1346,7 @@ bool HandleSublistCommand(std::vector<std::string> const& args,    using size_type = decltype(varArgsExpanded)::size_type; -  if (start < 0 || size_type(start) >= varArgsExpanded.size()) { +  if (start < 0 || static_cast<size_type>(start) >= varArgsExpanded.size()) {      status.SetError(cmStrCat("begin index: ", start, " is out of range 0 - ",                               varArgsExpanded.size() - 1));      return false; @@ -1357,9 +1357,10 @@ bool HandleSublistCommand(std::vector<std::string> const& args,    }    const size_type end = -    (length == -1 || size_type(start + length) > varArgsExpanded.size()) +    (length == -1 || +     static_cast<size_type>(start + length) > varArgsExpanded.size())      ? varArgsExpanded.size() -    : size_type(start + length); +    : static_cast<size_type>(start + length);    std::vector<std::string> sublist(varArgsExpanded.begin() + start,                                     varArgsExpanded.begin() + end);    status.GetMakefile().AddDefinition(variableName, cmJoin(sublist, ";")); diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 3da266d..91157cb 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> @@ -36,10 +36,11 @@ struct cmListFileParser    cmListFile* ListFile;    cmListFileBacktrace Backtrace;    cmMessenger* Messenger; -  const char* FileName; +  const char* FileName = nullptr;    cmListFileLexer* Lexer;    std::string FunctionName;    long FunctionLine; +  long FunctionLineEnd;    std::vector<cmListFileArgument> FunctionArguments;    enum    { @@ -54,7 +55,6 @@ cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,    : ListFile(lf)    , Backtrace(std::move(lfbt))    , Messenger(messenger) -  , FileName(nullptr)    , Lexer(cmListFileLexer_New())  {  } @@ -78,7 +78,7 @@ void cmListFileParser::IssueError(const std::string& text) const    cmListFileBacktrace lfbt = this->Backtrace;    lfbt = lfbt.Push(lfc);    this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text, lfbt); -  cmSystemTools::SetFatalErrorOccured(); +  cmSystemTools::SetFatalErrorOccurred();  }  bool cmListFileParser::ParseFile(const char* filename) @@ -146,7 +146,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;          } @@ -174,7 +174,7 @@ bool cmListFileParser::Parse()        MessageType::FATAL_ERROR,        "Flow control statements are not properly nested.",        this->Backtrace.Push(*badNesting)); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -259,6 +259,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 +444,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 +484,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..0553989 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;    }; @@ -106,16 +110,22 @@ public:    cm::optional<std::string> DeferId;    cmListFileContext() = default; -  cmListFileContext(cmListFileContext&& /*other*/) = default; +  // This move constructor is marked `noexcept` yet `clang-tidy` 14 reports it +  // as being able to throw an exception. Suppress the warning as there doesn't +  // seem to be any way for this to happen given the member types. +  // NOLINTNEXTLINE(bugprone-exception-escape) +  cmListFileContext(cmListFileContext&& /*other*/) noexcept = default;    cmListFileContext(const cmListFileContext& /*other*/) = default;    cmListFileContext& operator=(const cmListFileContext& /*other*/) = default;  #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -  cmListFileContext& operator=(cmListFileContext&& /*other*/) = default; +  cmListFileContext& operator=(cmListFileContext&& /*other*/) noexcept = +    default;  #else    // The move assignment operators for several STL classes did not become    // noexcept until C++17, which causes some tools to warn about this move    // assignment operator throwing an exception when it shouldn't. -  cmListFileContext& operator=(cmListFileContext&& /*other*/) = delete; +  cmListFileContext& operator=(cmListFileContext&& /*other*/) noexcept = +    delete;  #endif    cmListFileContext(std::string name, std::string filePath, long line) @@ -125,6 +135,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 +164,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 +229,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/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx index d49e711..9981c05 100644 --- a/Source/cmLoadCacheCommand.cxx +++ b/Source/cmLoadCacheCommand.cxx @@ -106,7 +106,7 @@ static bool ReadWithPrefix(std::vector<std::string> const& args,    }    // Prepare the table of variables to read. -  std::string const prefix = args[2]; +  std::string const& prefix = args[2];    std::set<std::string> const variablesToRead(args.begin() + 3, args.end());    // Read the cache file. diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 2080b40..1f18ff2 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -91,7 +91,7 @@ struct LoadedCommandImpl : cmLoadedCommandInfo    {      if (this->Destructor) {        SignalHandlerGuard guard(this->Name); -#if defined(__NVCOMPILER) +#if defined(__NVCOMPILER) || defined(__LCC__)        static_cast<void>(guard); // convince compiler var is used  #endif        this->Destructor(this); @@ -107,7 +107,7 @@ struct LoadedCommandImpl : cmLoadedCommandInfo    int DoInitialPass(cmMakefile* mf, int argc, char* argv[])    {      SignalHandlerGuard guard(this->Name); -#if defined(__NVCOMPILER) +#if defined(__NVCOMPILER) || defined(__LCC__)      static_cast<void>(guard); // convince compiler var is used  #endif      return this->InitialPass(this, mf, argc, argv); @@ -116,7 +116,7 @@ struct LoadedCommandImpl : cmLoadedCommandInfo    void DoFinalPass(cmMakefile* mf)    {      SignalHandlerGuard guard(this->Name); -#if defined(__NVCOMPILER) +#if defined(__NVCOMPILER) || defined(__LCC__)      static_cast<void>(guard); // convince compiler var is used  #endif      this->FinalPass(this, mf); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index e39309c..99bd05f 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -399,7 +399,7 @@ void cmLocalGenerator::ProcessEvaluationFiles(  {    for (const auto& geef : this->Makefile->GetEvaluationFiles()) {      geef->Generate(this); -    if (cmSystemTools::GetFatalErrorOccured()) { +    if (cmSystemTools::GetFatalErrorOccurred()) {        return;      }      std::vector<std::string> files = geef->GetFiles(); @@ -1025,6 +1025,20 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,      flags.emplace_back(std::move(compReqFlag));    } +  // Add Warning as errors flags +  if (!this->GetCMakeInstance()->GetIgnoreWarningAsError()) { +    const cmValue wError = target->GetProperty("COMPILE_WARNING_AS_ERROR"); +    const cmValue wErrorOpts = this->Makefile->GetDefinition( +      cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_WARNING_AS_ERROR")); +    if (wError.IsOn() && wErrorOpts.IsSet()) { +      std::string wErrorFlags; +      this->AppendCompileOptions(wErrorFlags, *wErrorOpts); +      if (!wErrorFlags.empty()) { +        flags.emplace_back(std::move(wErrorFlags)); +      } +    } +  } +    // Add compile flag for the MSVC compiler only.    cmMakefile* mf = this->GetMakefile();    if (cmValue jmc = @@ -1438,22 +1452,6 @@ void cmLocalGenerator::GetTargetFlags(            sharedLibFlags += this->Makefile->GetSafeDefinition(build);            sharedLibFlags += " ";          } -        if (this->Makefile->IsOn("WIN32") && -            !(this->Makefile->IsOn("CYGWIN") || -              this->Makefile->IsOn("MINGW"))) { -          std::vector<cmSourceFile*> sources; -          target->GetSourceFiles(sources, config); -          std::string defFlag = -            this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); -          for (cmSourceFile* sf : sources) { -            if (sf->GetExtension() == "def") { -              sharedLibFlags += defFlag; -              sharedLibFlags += -                this->ConvertToOutputFormat(sf->ResolveFullPath(), SHELL); -              sharedLibFlags += " "; -            } -          } -        }        }        cmValue targetLinkFlags = target->GetProperty("LINK_FLAGS"); @@ -1567,6 +1565,8 @@ void cmLocalGenerator::GetTargetFlags(    this->AppendPositionIndependentLinkerFlags(extraLinkFlags, target, config,                                               linkLanguage);    this->AppendIPOLinkerFlags(extraLinkFlags, target, config, linkLanguage); +  this->AppendModuleDefinitionFlag(extraLinkFlags, target, linkLineComputer, +                                   config);    if (!extraLinkFlags.empty()) {      linkFlags.emplace_back(std::move(extraLinkFlags)); @@ -1609,6 +1609,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 +1919,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( @@ -1984,7 +1986,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,                      "CMAKE_" + lang + "_COMPILER_ID") == "MSVC" ||                    this->Makefile->GetSafeDefinition(                      "CMAKE_" + lang + "_SIMULATE_ID") == "MSVC") && -                 !cmSystemTools::GetErrorOccuredFlag()) { +                 !cmSystemTools::GetErrorOccurredFlag()) {          // The compiler uses the MSVC ABI so it needs a known runtime library.          this->IssueMessage(MessageType::FATAL_ERROR,                             "MSVC_RUNTIME_LIBRARY value '" + @@ -1993,6 +1995,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::GetErrorOccurredFlag()) { +        // 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 +2388,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) @@ -3070,6 +3127,32 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags(    }  } +void cmLocalGenerator::AppendModuleDefinitionFlag( +  std::string& flags, cmGeneratorTarget const* target, +  cmLinkLineComputer* linkLineComputer, std::string const& config) +{ +  cmGeneratorTarget::ModuleDefinitionInfo const* mdi = +    target->GetModuleDefinitionInfo(config); +  if (!mdi || mdi->DefFile.empty()) { +    return; +  } + +  cmValue defFileFlag = +    this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG"); +  if (!defFileFlag) { +    return; +  } + +  // Append the flag and value.  Use ConvertToLinkReference to help +  // vs6's "cl -link" pass it to the linker. +  std::string flag = +    cmStrCat(*defFileFlag, +             this->ConvertToOutputFormat( +               linkLineComputer->ConvertToLinkReference(mdi->DefFile), +               cmOutputConverter::SHELL)); +  this->AppendFlags(flags, flag); +} +  bool cmLocalGenerator::AppendLWYUFlags(std::string& flags,                                         const cmGeneratorTarget* target,                                         const std::string& lang) @@ -3201,7 +3284,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 +3299,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..7cae1fc 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); @@ -176,6 +178,10 @@ public:                                              cmGeneratorTarget* target,                                              const std::string& config,                                              const std::string& lang); +  void AppendModuleDefinitionFlag(std::string& flags, +                                  cmGeneratorTarget const* target, +                                  cmLinkLineComputer* linkLineComputer, +                                  std::string const& config);    bool AppendLWYUFlags(std::string& flags, const cmGeneratorTarget* target,                         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..e125470 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"); @@ -1328,7 +1332,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(  {    // read in the target info file    if (!this->Makefile->ReadListFile(tgtInfo) || -      cmSystemTools::GetErrorOccuredFlag()) { +      cmSystemTools::GetErrorOccurredFlag()) {      cmSystemTools::Error("Target DependInfo.cmake file not found");    } @@ -1493,7 +1497,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(        cmStrCat(this->GetCurrentBinaryDirectory(),                 "/CMakeFiles/CMakeDirectoryInformation.cmake");      if (mf->ReadListFile(dirInfoFile) && -        !cmSystemTools::GetErrorOccuredFlag()) { +        !cmSystemTools::GetErrorOccurredFlag()) {        haveDirectoryInfo = true;      }    } @@ -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/cmMakeDirectoryCommand.cxx b/Source/cmMakeDirectoryCommand.cxx index cdde6f9..ec8b826 100644 --- a/Source/cmMakeDirectoryCommand.cxx +++ b/Source/cmMakeDirectoryCommand.cxx @@ -18,7 +18,7 @@ bool cmMakeDirectoryCommand(std::vector<std::string> const& args,      std::string e = "attempted to create a directory: " + args[0] +        " into a source directory.";      status.SetError(e); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    }    cmSystemTools::MakeDirectory(args[0]); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 94d3be6..469eac3 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; @@ -411,7 +417,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,      std::ostringstream e;      e << "Maximum recursion depth of " << depth << " exceeded";      this->IssueMessage(MessageType::FATAL_ERROR, e.str()); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -419,10 +425,10 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,    if (cmState::Command command =          this->GetState()->GetCommandByExactName(lff.LowerCaseName())) {      // Decide whether to invoke the command. -    if (!cmSystemTools::GetFatalErrorOccured()) { +    if (!cmSystemTools::GetFatalErrorOccurred()) {        // 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); @@ -436,23 +442,28 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,          }          result = false;          if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) { -          cmSystemTools::SetFatalErrorOccured(); +          cmSystemTools::SetFatalErrorOccurred();          }        }      }    } else { -    if (!cmSystemTools::GetFatalErrorOccured()) { +    if (!cmSystemTools::GetFatalErrorOccurred()) {        std::string error =          cmStrCat("Unknown CMake command \"", lff.OriginalName(), "\".");        this->IssueMessage(MessageType::FATAL_ERROR, error);        result = false; -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();      }    }    return result;  } +bool cmMakefile::IsImportedTargetGlobalScope() const +{ +  return this->CurrentImportedTargetScope == ImportedTargetScope::Global; +} +  class cmMakefile::IncludeScope  {  public: @@ -467,8 +478,8 @@ public:  private:    cmMakefile* Makefile;    bool NoPolicyScope; -  bool CheckCMP0011; -  bool ReportError; +  bool CheckCMP0011 = false; +  bool ReportError = true;    void EnforceCMP0011();  }; @@ -477,10 +488,9 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf,                                         bool noPolicyScope)    : Makefile(mf)    , NoPolicyScope(noPolicyScope) -  , 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(); @@ -600,7 +610,7 @@ bool cmMakefile::ReadDependentFile(const std::string& filename,    }    this->RunListFile(listFile, filenametoread); -  if (cmSystemTools::GetFatalErrorOccured()) { +  if (cmSystemTools::GetFatalErrorOccurred()) {      incScope.Quiet();    }    return true; @@ -611,9 +621,9 @@ class cmMakefile::ListFileScope  public:    ListFileScope(cmMakefile* mf, std::string const& filenametoread)      : 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( @@ -637,7 +647,7 @@ public:  private:    cmMakefile* Makefile; -  bool ReportError; +  bool ReportError = true;  };  class cmMakefile::DeferScope @@ -701,7 +711,7 @@ bool cmMakefile::ReadListFile(const std::string& filename)    }    this->RunListFile(listFile, filenametoread); -  if (cmSystemTools::GetFatalErrorOccured()) { +  if (cmSystemTools::GetFatalErrorOccurred()) {      scope.Quiet();    }    return true; @@ -722,7 +732,7 @@ bool cmMakefile::ReadListFileAsString(const std::string& content,    }    this->RunListFile(listFile, filenametoread); -  if (cmSystemTools::GetFatalErrorOccured()) { +  if (cmSystemTools::GetFatalErrorOccurred()) {      scope.Quiet();    }    return true; @@ -752,7 +762,7 @@ void cmMakefile::RunListFile(cmListFile const& listFile,    for (size_t i = 0; i < numberFunctions; ++i) {      cmExecutionStatus status(*this);      this->ExecuteCommand(listFile.Functions[i], status); -    if (cmSystemTools::GetFatalErrorOccured()) { +    if (cmSystemTools::GetFatalErrorOccurred()) {        break;      }      if (status.GetReturnInvoked()) { @@ -782,7 +792,7 @@ void cmMakefile::RunListFile(cmListFile const& listFile,        cmExecutionStatus status(*this);        this->ExecuteCommand(d.Command, status, std::move(id)); -      if (cmSystemTools::GetFatalErrorOccured()) { +      if (cmSystemTools::GetFatalErrorOccurred()) {          break;        }      } @@ -828,7 +838,7 @@ void cmMakefile::EnforceDirectoryLevelRules() const          // NEW behavior is to issue an error.          this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,                                                 msg.str(), this->Backtrace); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          break;      }    } @@ -1523,7 +1533,6 @@ class cmMakefile::BuildsystemFileScope  public:    BuildsystemFileScope(cmMakefile* mf)      : Makefile(mf) -    , ReportError(true)    {      std::string currentStart =        cmStrCat(this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource(), @@ -1565,7 +1574,7 @@ private:    cmGlobalGenerator* GG;    cmMakefile* CurrentMakefile;    cmStateSnapshot Snapshot; -  bool ReportError; +  bool ReportError = true;  };  void cmMakefile::Configure() @@ -1576,7 +1585,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 +1673,7 @@ void cmMakefile::Configure()          this->Backtrace);        cmListFileFunction project{ "project",                                    0, +                                  0,                                    { { "Project", cmListFileArgument::Unquoted,                                        0 },                                      { "__CMAKE_INJECTED_PROJECT_COMMAND__", @@ -1674,7 +1685,7 @@ void cmMakefile::Configure()    this->Defer = cm::make_unique<DeferCommands>();    this->RunListFile(listFile, currentStart, this->Defer.get());    this->Defer.reset(); -  if (cmSystemTools::GetFatalErrorOccured()) { +  if (cmSystemTools::GetFatalErrorOccurred()) {      scope.Quiet();    } @@ -2607,7 +2618,7 @@ const std::string& cmMakefile::ExpandVariablesInString(    // If it's an error in either case, just report the error...    if (mtype != MessageType::LOG) {      if (mtype == MessageType::FATAL_ERROR) { -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();      }      this->IssueMessage(mtype, errorstr);    } @@ -3271,7 +3282,7 @@ bool cmMakefile::ExpandArguments(std::vector<cmListFileArgument> const& inArgs,        cmExpandList(value, outArgs);      }    } -  return !cmSystemTools::GetFatalErrorOccured(); +  return !cmSystemTools::GetFatalErrorOccurred();  }  bool cmMakefile::ExpandArguments( @@ -3303,7 +3314,7 @@ bool cmMakefile::ExpandArguments(        }      }    } -  return !cmSystemTools::GetFatalErrorOccured(); +  return !cmSystemTools::GetFatalErrorOccurred();  }  void cmMakefile::AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb) @@ -3498,7 +3509,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,      this->IssueMessage(MessageType::FATAL_ERROR,                         "Failed to set working directory to " + bindir + " : " +                           std::strerror(workdir.GetLastResult())); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      this->IsSourceFileTryCompile = false;      return 1;    } @@ -3514,7 +3525,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,                         "Global generator '" +                           this->GetGlobalGenerator()->GetName() +                           "' could not be created."); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      this->IsSourceFileTryCompile = false;      return 1;    } @@ -3586,7 +3597,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,    if (cm.Configure() != 0) {      this->IssueMessage(MessageType::FATAL_ERROR,                         "Failed to configure test project build system."); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      this->IsSourceFileTryCompile = false;      return 1;    } @@ -3594,7 +3605,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,    if (cm.Generate() != 0) {      this->IssueMessage(MessageType::FATAL_ERROR,                         "Failed to generate test project build system."); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      this->IsSourceFileTryCompile = false;      return 1;    } @@ -4395,12 +4406,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));    } @@ -4469,7 +4482,7 @@ void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm) const    /* Record the setting of every policy.  */    using PolicyID = cmPolicies::PolicyID;    for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT; -       pid = PolicyID(pid + 1)) { +       pid = static_cast<PolicyID>(pid + 1)) {      pm.Set(pid, this->GetPolicyStatus(pid));    }  } @@ -4496,7 +4509,6 @@ cmMakefile::FunctionPushPop::FunctionPushPop(cmMakefile* mf,                                               const std::string& fileName,                                               cmPolicies::PolicyMap const& pm)    : Makefile(mf) -  , ReportError(true)  {    this->Makefile->PushFunctionScope(fileName, pm);  } @@ -4510,7 +4522,6 @@ cmMakefile::MacroPushPop::MacroPushPop(cmMakefile* mf,                                         const std::string& fileName,                                         const cmPolicies::PolicyMap& pm)    : Makefile(mf) -  , ReportError(true)  {    this->Makefile->PushMacroScope(fileName, pm);  } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index f425697..27838b2 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. @@ -825,7 +832,7 @@ public:    private:      cmMakefile* Makefile; -    bool ReportError; +    bool ReportError = true;    };    class MacroPushPop @@ -842,7 +849,7 @@ public:    private:      cmMakefile* Makefile; -    bool ReportError; +    bool ReportError = true;    };    void PushFunctionScope(std::string const& fileName, @@ -859,6 +866,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 +1168,5 @@ private:    std::set<std::string> WarnedCMP0074;    bool IsSourceFileTryCompile;    mutable bool SuppressSideEffects; +  ImportedTargetScope CurrentImportedTargetScope = ImportedTargetScope::Local;  }; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 244f56e..3849c6f 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -407,8 +407,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)          this->LocalGenerator,          this->LocalGenerator->GetStateSnapshot().GetDirectory()); -    this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags, -                                  this->GetConfigName()); +    this->LocalGenerator->AppendModuleDefinitionFlag( +      linkFlags, this->GeneratorTarget, linkLineComputer.get(), +      this->GetConfigName());    }    this->LocalGenerator->AppendIPOLinkerFlags( diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 66031db..f30ec27 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -175,8 +175,9 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)        this->LocalGenerator,        this->LocalGenerator->GetStateSnapshot().GetDirectory()); -  this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, -                                this->GetConfigName()); +  this->LocalGenerator->AppendModuleDefinitionFlag( +    extraFlags, this->GeneratorTarget, linkLineComputer.get(), +    this->GetConfigName());    this->UseLWYU = this->LocalGenerator->AppendLWYUFlags(      extraFlags, this->GeneratorTarget, linkLanguage); @@ -209,8 +210,9 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)        this->LocalGenerator,        this->LocalGenerator->GetStateSnapshot().GetDirectory()); -  this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, -                                this->GetConfigName()); +  this->LocalGenerator->AppendModuleDefinitionFlag( +    extraFlags, this->GeneratorTarget, linkLineComputer.get(), +    this->GetConfigName());    this->WriteLibraryRules(linkRuleVar, extraFlags, relink);  } @@ -929,7 +931,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(    }    // Compute the list of outputs. -  std::vector<std::string> outputs(1, targetFullPathReal); +  std::vector<std::string> outputs; +  outputs.reserve(3); +  outputs.push_back(targetFullPathReal);    if (this->TargetNames.SharedObject != this->TargetNames.Real) {      outputs.push_back(targetFullPathSO);    } diff --git a/Source/cmMakefileProfilingData.cxx b/Source/cmMakefileProfilingData.cxx index 337f78b..1cd97c9 100644 --- a/Source/cmMakefileProfilingData.cxx +++ b/Source/cmMakefileProfilingData.cxx @@ -60,7 +60,7 @@ void cmMakefileProfilingData::StartEntry(const cmListFileFunction& lff,      v["ph"] = "B";      v["name"] = lff.LowerCaseName();      v["cat"] = "cmake"; -    v["ts"] = Json::Value::UInt64( +    v["ts"] = static_cast<Json::Value::UInt64>(        std::chrono::duration_cast<std::chrono::microseconds>(          std::chrono::steady_clock::now().time_since_epoch())          .count()); @@ -98,7 +98,7 @@ void cmMakefileProfilingData::StopEntry()      cmsys::SystemInformation info;      Json::Value v;      v["ph"] = "E"; -    v["ts"] = Json::Value::UInt64( +    v["ts"] = static_cast<Json::Value::UInt64>(        std::chrono::duration_cast<std::chrono::microseconds>(          std::chrono::steady_clock::now().time_since_epoch())          .count()); 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/cmMathCommand.cxx b/Source/cmMathCommand.cxx index df9ebcf..1c0ff13 100644 --- a/Source/cmMathCommand.cxx +++ b/Source/cmMathCommand.cxx @@ -57,10 +57,10 @@ bool HandleExprCommand(std::vector<std::string> const& args,    if (argumentIndex < args.size()) {      const std::string messageHint = "sub-command EXPR "; -    const std::string option = args[argumentIndex++]; +    std::string const& option = args[argumentIndex++];      if (option == "OUTPUT_FORMAT") {        if (argumentIndex < args.size()) { -        const std::string argument = args[argumentIndex++]; +        std::string const& argument = args[argumentIndex++];          if (argument == "DECIMAL") {            outputFormat = NumericFormat::DECIMAL;          } else if (argument == "HEXADECIMAL") { diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index c7bb9a7..cd57600 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -222,7 +222,7 @@ bool cmMessageCommand(std::vector<std::string> const& args,    }    if (fatal) { -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();    }    return true;  } diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index 6dd192e..333003b 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -143,7 +143,7 @@ static void displayMessage(MessageType t, std::ostringstream& msg)    md.desiredColor = getMessageColor(t);    if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||        t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) { -    cmSystemTools::SetErrorOccured(); +    cmSystemTools::SetErrorOccurred();      md.title = "Error";      cmSystemTools::Message(msg.str(), md);    } else { diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 1c5bac8..d4f1608 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 @@ -1168,9 +1164,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(    this->addPoolNinjaVariable("JOB_POOL_LINK", gt, vars); -  this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"], -                                config); -    this->UseLWYU = this->GetLocalGenerator()->AppendLWYUFlags(      vars["LINK_FLAGS"], this->GetGeneratorTarget(),      this->TargetLinkLanguage(config)); 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/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index 7eea4b2..674735b 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -18,7 +18,6 @@ cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target)    : GT(target)    , Makefile(target->Target->GetMakefile())    , LocalGenerator(target->GetLocalGenerator()) -  , MacContentFolders(nullptr)  {    if (this->MustSkip()) {      return; diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index a3b6f98..c33b087 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -65,5 +65,5 @@ private:    cmGeneratorTarget* GT;    cmMakefile* Makefile;    cmLocalGenerator* LocalGenerator; -  std::set<std::string>* MacContentFolders; +  std::set<std::string>* MacContentFolders = nullptr;  }; diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index b143170..6883535 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -29,11 +29,11 @@ bool PathEqOrSubDir(std::string const& a, std::string const& b)  cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot)    : StateSnapshot(snapshot) -  , LinkScriptShell(false)  {    assert(this->StateSnapshot.IsValid());    this->ComputeRelativePathTopSource();    this->ComputeRelativePathTopBinary(); +  this->ComputeRelativePathTopRelation();  }  void cmOutputConverter::ComputeRelativePathTopSource() @@ -69,6 +69,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 +95,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..6e1bfe3 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    { @@ -138,7 +138,7 @@ private:    static bool Shell_ArgumentNeedsQuotes(cm::string_view in, int flags);    static std::string Shell_GetArgument(cm::string_view in, int flags); -  bool LinkScriptShell; +  bool LinkScriptShell = false;    // The top-most directories for relative path conversion.  Both the    // source and destination location of a relative path conversion @@ -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/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index 9f3fd00..95f3e7e 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -127,7 +127,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args,        status.GetMakefile().IssueMessage(          MessageType::FATAL_ERROR,          "PARSE_ARGV must be called with exactly 6 arguments."); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return true;      }      parseFromArgV = true; @@ -136,7 +136,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args,        status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR,                                          "PARSE_ARGV index '" + *argIter +                                            "' is not an unsigned integer"); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return true;      }      argIter++; // move past N @@ -190,7 +190,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args,                                          "PARSE_ARGV called with ARGC='" +                                            argc +                                            "' that is not an unsigned integer"); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return true;      }      for (unsigned long i = argvStart; i < count; ++i) { @@ -201,7 +201,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args,          status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR,                                            "PARSE_ARGV called with " +                                              argName.str() + " not set"); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          return true;        }        list.emplace_back(*arg); 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.cxx b/Source/cmPolicies.cxx index e31de1c..da5f5e5 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -43,7 +43,7 @@ static bool stringToId(const char* input, cmPolicies::PolicyID& pid)    if (id >= cmPolicies::CMPCOUNT) {      return false;    } -  pid = cmPolicies::PolicyID(id); +  pid = static_cast<cmPolicies::PolicyID>(id);    return true;  } @@ -279,7 +279,7 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,    // now loop over all the policies and set them as appropriate    std::vector<cmPolicies::PolicyID> ancientPolicies;    for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT; -       pid = PolicyID(pid + 1)) { +       pid = static_cast<PolicyID>(pid + 1)) {      if (isPolicyNewerThan(pid, majorVer, minorVer, patchVer)) {        if (cmPolicies::GetPolicyStatus(pid) == cmPolicies::REQUIRED_ALWAYS) {          ancientPolicies.push_back(pid); @@ -314,7 +314,7 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,    // Make sure the project does not use any ancient policies.    if (!ancientPolicies.empty()) {      DiagnoseAncientPolicies(ancientPolicies, majorVer, minorVer, patchVer, mf); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 99e2eb6..cb7402c 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -388,7 +388,40 @@ 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) +         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)                                                    \ +  SELECT(POLICY, CMP0138,                                                     \ +         "CheckIPOSupported uses flags from calling project.", 3, 24, 0,      \ +         cmPolicies::WARN)                                                    \ +  SELECT(                                                                     \ +    POLICY, CMP0139,                                                          \ +    "The if() command supports path comparisons using PATH_EQUAL operator.",  \ +    3, 24, 0, cmPolicies::WARN)  #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)  #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \ @@ -424,7 +457,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/cmProcessTools.cxx b/Source/cmProcessTools.cxx index 9ebf5b7..9e7854b 100644 --- a/Source/cmProcessTools.cxx +++ b/Source/cmProcessTools.cxx @@ -21,12 +21,12 @@ void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out,           (p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) {      if (out && p == cmsysProcess_Pipe_STDOUT) {        processOutput.DecodeText(data, length, strdata, 1); -      if (!out->Process(strdata.c_str(), int(strdata.size()))) { +      if (!out->Process(strdata.c_str(), static_cast<int>(strdata.size()))) {          out = nullptr;        }      } else if (err && p == cmsysProcess_Pipe_STDERR) {        processOutput.DecodeText(data, length, strdata, 2); -      if (!err->Process(strdata.c_str(), int(strdata.size()))) { +      if (!err->Process(strdata.c_str(), static_cast<int>(strdata.size()))) {          err = nullptr;        }      } @@ -34,13 +34,13 @@ void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out,    if (out) {      processOutput.DecodeText(std::string(), strdata, 1);      if (!strdata.empty()) { -      out->Process(strdata.c_str(), int(strdata.size())); +      out->Process(strdata.c_str(), static_cast<int>(strdata.size()));      }    }    if (err) {      processOutput.DecodeText(std::string(), strdata, 2);      if (!strdata.empty()) { -      err->Process(strdata.c_str(), int(strdata.size())); +      err->Process(strdata.c_str(), static_cast<int>(strdata.size()));      }    }    cmsysProcess_WaitForExit(cp, nullptr); diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 04d99c9..249fe2d 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -102,7 +102,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,        if (haveLanguages) {          mf.IssueMessage(MessageType::FATAL_ERROR,                          "LANGUAGES may be specified at most once."); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          return true;        }        haveLanguages = true; @@ -121,7 +121,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,        if (haveVersion) {          mf.IssueMessage(MessageType::FATAL_ERROR,                          "VERSION may be specified at most once."); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          return true;        }        haveVersion = true; @@ -140,7 +140,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,        if (haveDescription) {          mf.IssueMessage(MessageType::FATAL_ERROR,                          "DESCRIPTION may be specified at most once."); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          return true;        }        haveDescription = true; @@ -159,7 +159,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,        if (haveHomepage) {          mf.IssueMessage(MessageType::FATAL_ERROR,                          "HOMEPAGE_URL may be specified at most once."); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          return true;        }        haveHomepage = true; @@ -200,7 +200,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,      mf.IssueMessage(MessageType::FATAL_ERROR,                      "project with VERSION, DESCRIPTION or HOMEPAGE_URL must "                      "use LANGUAGES before language names."); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return true;    }    if (haveLanguages && languages.empty()) { @@ -214,7 +214,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,      if (cmp0048 == cmPolicies::OLD || cmp0048 == cmPolicies::WARN) {        mf.IssueMessage(MessageType::FATAL_ERROR,                        "VERSION not allowed unless CMP0048 is set to NEW"); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return true;      } @@ -223,7 +223,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,      if (!vx.find(version)) {        std::string e = R"(VERSION ")" + version + R"(" format invalid.)";        mf.IssueMessage(MessageType::FATAL_ERROR, e); -      cmSystemTools::SetFatalErrorOccured(); +      cmSystemTools::SetFatalErrorOccurred();        return true;      } @@ -242,9 +242,9 @@ bool cmProjectCommand(std::vector<std::string> const& args,        const int vc = std::sscanf(version.c_str(), "%u.%u.%u.%u", &v[0], &v[1],                                   &v[2], &v[3]);        for (auto i = 0u; i < MAX_VERSION_COMPONENTS; ++i) { -        if (int(i) < vc) { +        if (static_cast<int>(i) < vc) {            std::snprintf(vb[i], maxIntLength, "%u", v[i]); -          version_string += &"."[std::size_t(i == 0)]; +          version_string += &"."[static_cast<std::size_t>(i == 0)];            version_string += vb[i];            version_components[i] = vb[i];          } else { @@ -380,7 +380,7 @@ static bool IncludeByVariable(cmExecutionStatus& status,      return true;    } -  if (cmSystemTools::GetFatalErrorOccured()) { +  if (cmSystemTools::GetFatalErrorOccurred()) {      return true;    } 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..40f3ab5 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; @@ -406,6 +407,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()    }    // Common directories +  std::string relativeBuildDir;    {      // Collapsed current binary directory      std::string const cbd = cmSystemTools::CollapseFullPath( @@ -423,6 +425,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()          cmStrCat(cbd, '/', this->GenTarget->GetName(), "_autogen");      }      cmSystemTools::ConvertToUnixSlashes(this->Dir.Build); +    this->Dir.RelativeBuild = +      cmSystemTools::RelativePath(cbd, this->Dir.Build);      // Cleanup build directory      this->AddCleanFile(this->Dir.Build); @@ -1266,7 +1270,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; @@ -1355,7 +1360,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()          cmStrCat(this->Dir.Build, "/", timestampFileName);        this->AutogenTarget.DepFile = cmStrCat(this->Dir.Build, "/deps");        this->AutogenTarget.DepFileRuleName = -        cmStrCat(this->GenTarget->GetName(), "_autogen/", timestampFileName); +        cmStrCat(this->Dir.RelativeBuild, "/", timestampFileName);        commandLines.push_back(cmMakeCommandLine(          { cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile })); diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 603c537..33749ba 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -178,6 +178,7 @@ private:    {      std::string Info;      std::string Build; +    std::string RelativeBuild;      std::string Work;      ConfigString Include;      std::string IncludeGenExp; diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 4ed728e..4753e61 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; @@ -2116,6 +2167,8 @@ void cmQtAutoMocUicT::JobCompileUicT::Process()  void cmQtAutoMocUicT::JobMocsCompilationT::Process()  { +  std::string const& compAbs = this->MocConst().CompFileAbs; +    // Compose mocs compilation file content    std::string content =      "// This file is autogenerated. Changes will be overwritten.\n"; @@ -2133,7 +2186,6 @@ void cmQtAutoMocUicT::JobMocsCompilationT::Process()      content += cmWrap(wrapFront, this->MocEval().CompFiles, wrapBack, "");    } -  std::string const& compAbs = this->MocConst().CompFileAbs;    if (cmQtAutoGenerator::FileDiffers(compAbs, content)) {      // Actually write mocs compilation file      if (this->Log().Verbose()) { @@ -2731,7 +2783,7 @@ void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap)  std::string cmQtAutoMocUicT::CollapseFullPathTS(std::string const& path) const  {    std::lock_guard<std::mutex> guard(this->CMakeLibMutex_); -#if defined(__NVCOMPILER) +#if defined(__NVCOMPILER) || defined(__LCC__)    static_cast<void>(guard); // convince compiler var is used  #endif    return cmSystemTools::CollapseFullPath(path, @@ -2973,7 +3025,7 @@ std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile(    const char* filePath)  {    std::lock_guard<std::mutex> guard(this->CMakeLibMutex_); -#if defined(__NVCOMPILER) +#if defined(__NVCOMPILER) || defined(__LCC__)    static_cast<void>(guard); // convince compiler var is used  #endif    auto const content = cmReadGccDepfile(filePath); diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx index 1e4dedd..fa9d4cc 100644 --- a/Source/cmRST.cxx +++ b/Source/cmRST.cxx @@ -19,11 +19,6 @@  cmRST::cmRST(std::ostream& os, std::string docroot)    : OS(os)    , DocRoot(std::move(docroot)) -  , IncludeDepth(0) -  , OutputLinePending(false) -  , LastLineEndedInColonColon(false) -  , Markup(MarkupNone) -  , Directive(DirectiveNone)    , CMakeDirective("^.. (cmake:)?("                     "command|envvar|genex|variable"                     ")::[ \t]+([^ \t\n]+)$") diff --git a/Source/cmRST.h b/Source/cmRST.h index 156b20a..ea4ef22 100644 --- a/Source/cmRST.h +++ b/Source/cmRST.h @@ -69,11 +69,11 @@ private:    std::ostream& OS;    std::string DocRoot; -  int IncludeDepth; -  bool OutputLinePending; -  bool LastLineEndedInColonColon; -  MarkupType Markup; -  DirectiveType Directive; +  int IncludeDepth = 0; +  bool OutputLinePending = false; +  bool LastLineEndedInColonColon = false; +  MarkupType Markup = MarkupNone; +  DirectiveType Directive = DirectiveNone;    cmsys::RegularExpression CMakeDirective;    cmsys::RegularExpression CMakeModuleDirective;    cmsys::RegularExpression ParsedLiteralDirective; 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..166ee56 100644 --- a/Source/cmScriptGenerator.cxx +++ b/Source/cmScriptGenerator.cxx @@ -12,8 +12,6 @@ cmScriptGenerator::cmScriptGenerator(std::string config_var,                                       std::vector<std::string> configurations)    : RuntimeConfigVariable(std::move(config_var))    , Configurations(std::move(configurations)) -  , ConfigurationTypes(nullptr) -  , ActionsPerConfig(false)  {  } @@ -52,8 +50,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 +61,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/cmScriptGenerator.h b/Source/cmScriptGenerator.h index 46d794c..3d7b350 100644 --- a/Source/cmScriptGenerator.h +++ b/Source/cmScriptGenerator.h @@ -78,12 +78,12 @@ protected:    // Information used during generation.    std::string ConfigurationName; -  std::vector<std::string> const* ConfigurationTypes; +  std::vector<std::string> const* ConfigurationTypes = nullptr;    // True if the subclass needs to generate an explicit rule for each    // configuration.  False if the subclass only generates one rule for    // all enabled configurations. -  bool ActionsPerConfig; +  bool ActionsPerConfig = false;  private:    void GenerateScriptActionsOnce(std::ostream& os, Indent indent); 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/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx index 155068cb..6019de1 100644 --- a/Source/cmSourceGroup.cxx +++ b/Source/cmSourceGroup.cxx @@ -124,6 +124,21 @@ cmSourceGroup* cmSourceGroup::MatchChildrenFiles(const std::string& name)    return nullptr;  } +const cmSourceGroup* cmSourceGroup::MatchChildrenFiles( +  const std::string& name) const +{ +  if (this->MatchesFiles(name)) { +    return this; +  } +  for (const cmSourceGroup& group : this->Internal->GroupChildren) { +    const cmSourceGroup* result = group.MatchChildrenFiles(name); +    if (result) { +      return result; +    } +  } +  return nullptr; +} +  cmSourceGroup* cmSourceGroup::MatchChildrenRegex(const std::string& name)  {    for (cmSourceGroup& group : this->Internal->GroupChildren) { diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h index 295240d..9ce71c7 100644 --- a/Source/cmSourceGroup.h +++ b/Source/cmSourceGroup.h @@ -80,6 +80,12 @@ public:    cmSourceGroup* MatchChildrenFiles(const std::string& name);    /** +   * Check if the given name matches this group's explicit file list +   * in children. +   */ +  const cmSourceGroup* MatchChildrenFiles(const std::string& name) const; + +  /**     * Check if the given name matches this group's regex in children.     */    cmSourceGroup* MatchChildrenRegex(const std::string& name); diff --git a/Source/cmState.cxx b/Source/cmState.cxx index f1144e1..3d38e73 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -503,7 +503,7 @@ bool cmState::AddScriptedCommand(std::string const& name, BT<Command> command,        cmStrCat("Built-in flow control command \"", sName,                 "\" cannot be overridden."),        command.Backtrace); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } @@ -1072,3 +1072,12 @@ bool cmState::ParseCacheEntry(const std::string& entry, std::string& var,    return flag;  } + +cmState::Command cmState::GetDependencyProviderCommand( +  cmDependencyProvider::Method method) const +{ +  return (this->DependencyProvider && +          this->DependencyProvider->SupportsMethod(method)) +    ? this->GetCommand(this->DependencyProvider->GetCommand()) +    : Command{}; +} diff --git a/Source/cmState.h b/Source/cmState.h index 4f2b7df..2d0c521 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -8,13 +8,17 @@  #include <memory>  #include <set>  #include <string> +#include <type_traits>  #include <unordered_map>  #include <unordered_set> +#include <utility>  #include <vector> +#include <cm/optional> +  #include "cmDefinitions.h" +#include "cmDependencyProvider.h"  #include "cmLinkedTree.h" -#include "cmListFileCache.h"  #include "cmPolicies.h"  #include "cmProperty.h"  #include "cmPropertyDefinition.h" @@ -30,6 +34,11 @@ class cmMakefile;  class cmStateSnapshot;  class cmMessenger;  class cmExecutionStatus; +class cmListFileBacktrace; +struct cmListFileArgument; + +template <typename T> +class BT;  class cmState  { @@ -223,6 +232,24 @@ public:    ProjectKind GetProjectKind() const; +  void ClearDependencyProvider() { this->DependencyProvider.reset(); } +  void SetDependencyProvider(cmDependencyProvider provider) +  { +    this->DependencyProvider = std::move(provider); +  } +  cm::optional<cmDependencyProvider> const& GetDependencyProvider() const +  { +    return this->DependencyProvider; +  } +  Command GetDependencyProviderCommand( +    cmDependencyProvider::Method method) const; + +  void SetInTopLevelIncludes(bool inTopLevelIncludes) +  { +    this->ProcessingTopLevelIncludes = inTopLevelIncludes; +  } +  bool InTopLevelIncludes() const { return this->ProcessingTopLevelIncludes; } +  private:    friend class cmake;    void AddCacheEntry(const std::string& key, const char* value, @@ -284,4 +311,6 @@ private:    bool NinjaMulti = false;    Mode StateMode = Unknown;    ProjectKind StateProjectKind = ProjectKind::Normal; +  cm::optional<cmDependencyProvider> DependencyProvider; +  bool ProcessingTopLevelIncludes = false;  }; 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..f077801 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -107,6 +107,10 @@  #  include <sys/utsname.h>  #endif +#if defined(_MSC_VER) && _MSC_VER >= 1800 +#  define CM_WINDOWS_DEPRECATED_GetVersionEx +#endif +  namespace {  cmSystemTools::InterruptCallback s_InterruptCallback; @@ -156,8 +160,8 @@ static int cm_archive_read_open_file(struct archive* a, const char* file,  bool cmSystemTools::s_RunCommandHideConsole = false;  bool cmSystemTools::s_DisableRunCommandOutput = false; -bool cmSystemTools::s_ErrorOccured = false; -bool cmSystemTools::s_FatalErrorOccured = false; +bool cmSystemTools::s_ErrorOccurred = false; +bool cmSystemTools::s_FatalErrorOccurred = false;  bool cmSystemTools::s_ForceUnixPaths = false;  // replace replace with with as many times as it shows up in source. @@ -212,7 +216,7 @@ std::string cmSystemTools::HelpFileName(cm::string_view str)  void cmSystemTools::Error(const std::string& m)  {    std::string message = "CMake Error: " + m; -  cmSystemTools::s_ErrorOccured = true; +  cmSystemTools::s_ErrorOccurred = true;    cmSystemTools::Message(message, "Error");  } @@ -904,6 +908,40 @@ cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsDirectoryRetry()      InitWindowsDirectoryRetry().Retry;    return retry;  } + +cmSystemTools::WindowsVersion cmSystemTools::GetWindowsVersion() +{ +  /* Windows version number data.  */ +  OSVERSIONINFOEXW osviex; +  ZeroMemory(&osviex, sizeof(osviex)); +  osviex.dwOSVersionInfoSize = sizeof(osviex); + +#  ifdef CM_WINDOWS_DEPRECATED_GetVersionEx +#    pragma warning(push) +#    ifdef __INTEL_COMPILER +#      pragma warning(disable : 1478) +#    elif defined __clang__ +#      pragma clang diagnostic push +#      pragma clang diagnostic ignored "-Wdeprecated-declarations" +#    else +#      pragma warning(disable : 4996) +#    endif +#  endif +  GetVersionExW((OSVERSIONINFOW*)&osviex); +#  ifdef CM_WINDOWS_DEPRECATED_GetVersionEx +#    ifdef __clang__ +#      pragma clang diagnostic pop +#    else +#      pragma warning(pop) +#    endif +#  endif + +  WindowsVersion result; +  result.dwMajorVersion = osviex.dwMajorVersion; +  result.dwMinorVersion = osviex.dwMinorVersion; +  result.dwBuildNumber = osviex.dwBuildNumber; +  return result; +}  #endif  std::string cmSystemTools::GetRealPathResolvingWindowsSubst( @@ -1821,6 +1859,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 +1918,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 +1983,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 +2002,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; @@ -1989,7 +2033,7 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,            --length;          }          if (length > 0) { -          line.append(&out[0], length); +          line.append(out.data(), length);          }          out.erase(out.begin(), outiter + 1);          return cmsysProcess_Pipe_STDOUT; @@ -2007,7 +2051,7 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,            --length;          }          if (length > 0) { -          line.append(&err[0], length); +          line.append(err.data(), length);          }          err.erase(err.begin(), erriter + 1);          return cmsysProcess_Pipe_STDERR; @@ -2051,12 +2095,12 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,          erriter = err.begin() + size;        }        if (!out.empty()) { -        line.append(&out[0], outiter - out.begin()); +        line.append(out.data(), outiter - out.begin());          out.erase(out.begin(), out.end());          return cmsysProcess_Pipe_STDOUT;        }        if (!err.empty()) { -        line.append(&err[0], erriter - err.begin()); +        line.append(err.data(), erriter - err.begin());          err.erase(err.begin(), err.end());          return cmsysProcess_Pipe_STDERR;        } @@ -3143,7 +3187,7 @@ static cm::optional<bool> RemoveRPathELF(std::string const& file,      }      return false;    } -  if (!f.write(&bytes[0], bytes.size())) { +  if (!f.write(bytes.data(), bytes.size())) {      if (emsg) {        *emsg = "Error replacing DYNAMIC table header.";      } @@ -3413,3 +3457,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..ec650f7 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -77,28 +77,28 @@ public:    static bool GetInterruptFlag();    //! Return true if there was an error at any point. -  static bool GetErrorOccuredFlag() +  static bool GetErrorOccurredFlag()    { -    return cmSystemTools::s_ErrorOccured || -      cmSystemTools::s_FatalErrorOccured || GetInterruptFlag(); +    return cmSystemTools::s_ErrorOccurred || +      cmSystemTools::s_FatalErrorOccurred || GetInterruptFlag();    }    //! If this is set to true, cmake stops processing commands. -  static void SetFatalErrorOccured() +  static void SetFatalErrorOccurred()    { -    cmSystemTools::s_FatalErrorOccured = true; +    cmSystemTools::s_FatalErrorOccurred = true;    } -  static void SetErrorOccured() { cmSystemTools::s_ErrorOccured = true; } +  static void SetErrorOccurred() { cmSystemTools::s_ErrorOccurred = true; }    //! Return true if there was an error at any point. -  static bool GetFatalErrorOccured() +  static bool GetFatalErrorOccurred()    { -    return cmSystemTools::s_FatalErrorOccured || GetInterruptFlag(); +    return cmSystemTools::s_FatalErrorOccurred || GetInterruptFlag();    }    //! Set the error occurred flag and fatal error back to false -  static void ResetErrorOccuredFlag() +  static void ResetErrorOccurredFlag()    { -    cmSystemTools::s_FatalErrorOccured = false; -    cmSystemTools::s_ErrorOccured = false; +    cmSystemTools::s_FatalErrorOccurred = false; +    cmSystemTools::s_ErrorOccurred = false;    }    //! Return true if the path is a framework @@ -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 @@ -501,6 +509,14 @@ public:    };    static WindowsFileRetry GetWindowsFileRetry();    static WindowsFileRetry GetWindowsDirectoryRetry(); + +  struct WindowsVersion +  { +    unsigned int dwMajorVersion; +    unsigned int dwMinorVersion; +    unsigned int dwBuildNumber; +  }; +  static WindowsVersion GetWindowsVersion();  #endif    /** Get the real path for a given path, removing all symlinks. @@ -527,10 +543,13 @@ 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; -  static bool s_ErrorOccured; -  static bool s_FatalErrorOccured; +  static bool s_ErrorOccurred; +  static bool s_FatalErrorOccurred;    static bool s_DisableRunCommandOutput;  }; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 57e31b9..cbe5d7d 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"); @@ -386,11 +583,13 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,      initProp("Swift_LANGUAGE_VERSION");      initProp("Swift_MODULE_DIRECTORY");      initProp("VS_JUST_MY_CODE_DEBUGGING"); +    initProp("VS_NO_COMPILE_BATCHING");      initProp("DISABLE_PRECOMPILE_HEADERS");      initProp("UNITY_BUILD");      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 +622,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,    }    initProp("FOLDER"); +  initProp("VERIFY_INTERFACE_HEADER_SETS");    if (this->GetGlobalGenerator()->IsXcode()) {      initProp("XCODE_GENERATE_SCHEME"); @@ -688,6 +888,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 +1294,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 +1352,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 +1401,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 +1425,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 +1541,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 +1575,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 +1628,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 +1719,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 +1741,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 +1758,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 && @@ -1667,6 +1881,97 @@ void cmTarget::AppendBuildInterfaceIncludes()    }  } +namespace { +bool CheckLinkLibraryPattern(cm::string_view property, +                             const std::vector<BT<std::string>>& value, +                             cmake* context) +{ +  // Look for <LINK_LIBRARY:> and </LINK_LIBRARY:> internal tags +  static cmsys::RegularExpression linkPattern( +    "(^|;)(</?LINK_(LIBRARY|GROUP):[^;>]*>)(;|$)"); + +  bool isValid = true; + +  for (const auto& item : value) { +    if (!linkPattern.find(item.Value)) { +      continue; +    } + +    isValid = false; + +    // 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."), +      item.Backtrace); +  } + +  return isValid; +} +} + +void cmTarget::FinalizeTargetConfiguration( +  const cmBTStringRange& noConfigCompileDefinitions, +  cm::optional<std::map<std::string, cmValue>>& perConfigCompileDefinitions) +{ +  if (this->GetType() == cmStateEnums::GLOBAL_TARGET) { +    return; +  } + +  if (!CheckLinkLibraryPattern("LINK_LIBRARIES"_s, +                               this->impl->LinkImplementationPropertyEntries, +                               this->GetMakefile()->GetCMakeInstance()) || +      !CheckLinkLibraryPattern("INTERFACE_LINK_LIBRARIES"_s, +                               this->impl->LinkInterfacePropertyEntries, +                               this->GetMakefile()->GetCMakeInstance()) || +      !CheckLinkLibraryPattern("INTERFACE_LINK_LIBRARIES_DIRECT"_s, +                               this->impl->LinkInterfaceDirectPropertyEntries, +                               this->GetMakefile()->GetCMakeInstance())) { +    return; +  } + +  this->AppendBuildInterfaceIncludes(); + +  if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { +    return; +  } + +  for (auto const& def : noConfigCompileDefinitions) { +    this->InsertCompileDefinition(def); +  } + +  auto* mf = this->GetMakefile(); +  cmPolicies::PolicyStatus polSt = mf->GetPolicyStatus(cmPolicies::CMP0043); +  if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) { +    if (perConfigCompileDefinitions) { +      for (auto const& it : *perConfigCompileDefinitions) { +        if (cmValue val = it.second) { +          this->AppendProperty(it.first, *val); +        } +      } +    } else { +      perConfigCompileDefinitions.emplace(); +      std::vector<std::string> configs = +        mf->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); + +      for (std::string const& c : configs) { +        std::string defPropName = +          cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c)); +        cmValue val = mf->GetProperty(defPropName); +        (*perConfigCompileDefinitions)[defPropName] = val; +        if (val) { +          this->AppendProperty(defPropName, *val); +        } +      } +    } +  } +} +  void cmTarget::InsertInclude(BT<std::string> const& entry, bool before)  {    auto position = before ? this->impl->IncludeDirectoriesEntries.begin() @@ -1709,69 +2014,64 @@ 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 CheckLINK_INTERFACE_LIBRARIES(const std::string& prop, +                                   const std::string& value, +                                   cmMakefile* context, bool imported)  { -  // Look for link-type keywords in the value. -  static cmsys::RegularExpression keys("(^|;)(debug|optimized|general)(;|$)"); -  if (!keys.find(value)) { -    return; -  } -    // 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; +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()); +  }  } -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 +2087,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 +2095,19 @@ 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 == "INTERFACE_LINK_LIBRARIES") {      if (cmValue value = this->GetProperty(prop)) { -      cmTargetCheckINTERFACE_LINK_LIBRARIES(*value, context); +      CheckINTERFACE_LINK_LIBRARIES(*value, context);      } -  } -  if (prop == "IMPORTED_GLOBAL") { +  } else if (prop == "IMPORTED_GLOBAL") {      if (this->IsImported()) { -      cmTargetCheckIMPORTED_GLOBAL(this, context); +      CheckIMPORTED_GLOBAL(this, context);      }    }  } @@ -1844,11 +2142,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 +2174,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 +2298,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 +2581,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 +2605,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 +2628,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..467c4da 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -5,12 +5,15 @@  #include "cmConfigure.h" // IWYU pragma: keep  #include <iosfwd> +#include <map>  #include <memory>  #include <set>  #include <string>  #include <utility>  #include <vector> +#include <cm/optional> +  #include "cmAlgorithms.h"  #include "cmFileSet.h"  #include "cmPolicies.h" @@ -220,6 +223,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; @@ -231,6 +236,9 @@ public:    void InsertPrecompileHeader(BT<std::string> const& entry);    void AppendBuildInterfaceIncludes(); +  void FinalizeTargetConfiguration( +    const cmBTStringRange& noConfigCompileDefinitions, +    cm::optional<std::map<std::string, cmValue>>& perConfigCompileDefinitions);    std::string GetDebugGeneratorExpressions(const std::string& value,                                             cmTargetLinkLibraryType llt) const; @@ -269,6 +277,8 @@ public:    cmBTStringRange GetLinkImplementationEntries() const;    cmBTStringRange GetLinkInterfaceEntries() const; +  cmBTStringRange GetLinkInterfaceDirectEntries() const; +  cmBTStringRange GetLinkInterfaceDirectExcludeEntries() const;    cmBTStringRange GetHeaderSetsEntries() const; @@ -288,6 +298,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/cmTargetDepend.h b/Source/cmTargetDepend.h index 9027409..4ff5eb4 100644 --- a/Source/cmTargetDepend.h +++ b/Source/cmTargetDepend.h @@ -18,17 +18,14 @@ class cmTargetDepend    // The set order depends only on the Target, so we use    // mutable members to achieve a map with set syntax. -  mutable bool Link; -  mutable bool Util; -  mutable bool Cross; +  mutable bool Link = false; +  mutable bool Util = false; +  mutable bool Cross = false;    mutable cmListFileBacktrace Backtrace;  public:    cmTargetDepend(cmGeneratorTarget const* t)      : Target(t) -    , Link(false) -    , Util(false) -    , Cross(false)    {    }    operator cmGeneratorTarget const*() const { return this->Target; } diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index f31501e..b4b4319 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -99,7 +99,7 @@ bool cmTargetIncludeDirectoriesCommand(std::vector<std::string> const& args,  {    return TargetIncludeDirectoriesImpl(status).HandleArguments(      args, "INCLUDE_DIRECTORIES", -    TargetIncludeDirectoriesImpl::ArgumentFlags( +    static_cast<TargetIncludeDirectoriesImpl::ArgumentFlags>(        TargetIncludeDirectoriesImpl::PROCESS_BEFORE |        TargetIncludeDirectoriesImpl::PROCESS_AFTER |        TargetIncludeDirectoriesImpl::PROCESS_SYSTEM)); diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index e10d0b5..af870da 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -130,7 +130,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,          break;        case MessageType::FATAL_ERROR:          mf.IssueMessage(MessageType::FATAL_ERROR, e.str()); -        cmSystemTools::SetFatalErrorOccured(); +        cmSystemTools::SetFatalErrorOccurred();          break;        default:          break; @@ -361,7 +361,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,      mf.IssueMessage(MessageType::FATAL_ERROR,                      cmStrCat("The \"", LinkLibraryTypeNames[llt],                               "\" argument must be followed by a library.")); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();    }    const cmPolicies::PolicyStatus policy22Status = diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h index 82c6355..a14a3f0 100644 --- a/Source/cmTargetPropertyComputer.h +++ b/Source/cmTargetPropertyComputer.h @@ -23,7 +23,7 @@ public:      if (cmValue loc = GetLocation(tgt, prop, mf)) {        return loc;      } -    if (cmSystemTools::GetFatalErrorOccured()) { +    if (cmSystemTools::GetFatalErrorOccurred()) {        return nullptr;      }      if (prop == "SOURCES") { diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index 7c0f9e7..e6ed01b 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -8,8 +8,7 @@  #include "cmValue.h"  cmTest::cmTest(cmMakefile* mf) -  : CommandExpandLists(false) -  , Backtrace(mf->GetBacktrace()) +  : Backtrace(mf->GetBacktrace())  {    this->Makefile = mf;    this->OldStyle = true; diff --git a/Source/cmTest.h b/Source/cmTest.h index 85978da..1c14310 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h @@ -64,7 +64,7 @@ private:    cmPropertyMap Properties;    std::string Name;    std::vector<std::string> Command; -  bool CommandExpandLists; +  bool CommandExpandLists = false;    bool OldStyle; diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index e2b6c20..677fdb6 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -50,7 +50,7 @@ std::string cmTimestamp::CurrentTime(const std::string& formatString,      // SOURCE_DATE_EPOCH has only a resolution in the seconds range      microseconds = 0;    } -  if (currentTimeT == time_t(-1)) { +  if (currentTimeT == static_cast<time_t>(-1)) {      return std::string();    } diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx index 81a6507..12c121f 100644 --- a/Source/cmTransformDepfile.cxx +++ b/Source/cmTransformDepfile.cxx @@ -89,7 +89,9 @@ void WriteMSBuildAdditionalInputs(cmsys::ofstream& fout,    }    // Write a UTF-8 BOM so MSBuild knows the encoding when reading the file. -  static const char utf8bom[] = { char(0xEF), char(0xBB), char(0xBF) }; +  static const char utf8bom[] = { static_cast<char>(0xEF), +                                  static_cast<char>(0xBB), +                                  static_cast<char>(0xBF) };    fout.write(utf8bom, sizeof(utf8bom));    // Write the format expected by MSBuild CustomBuild AdditionalInputs. 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/cmUuid.cxx b/Source/cmUuid.cxx index 2513303..6688668 100644 --- a/Source/cmUuid.cxx +++ b/Source/cmUuid.cxx @@ -17,10 +17,10 @@ std::string cmUuid::FromMd5(std::vector<unsigned char> const& uuidNamespace,    cmCryptoHash md5(cmCryptoHash::AlgoMD5);    md5.Initialize(); -  md5.Append(&hashInput[0], hashInput.size()); +  md5.Append(hashInput.data(), hashInput.size());    std::vector<unsigned char> digest = md5.Finalize(); -  return this->FromDigest(&digest[0], 3); +  return this->FromDigest(digest.data(), 3);  }  std::string cmUuid::FromSha1(std::vector<unsigned char> const& uuidNamespace, @@ -31,10 +31,10 @@ std::string cmUuid::FromSha1(std::vector<unsigned char> const& uuidNamespace,    cmCryptoHash sha1(cmCryptoHash::AlgoSHA1);    sha1.Initialize(); -  sha1.Append(&hashInput[0], hashInput.size()); +  sha1.Append(hashInput.data(), hashInput.size());    std::vector<unsigned char> digest = sha1.Finalize(); -  return this->FromDigest(&digest[0], 5); +  return this->FromDigest(digest.data(), 5);  }  void cmUuid::CreateHashInput(std::vector<unsigned char> const& uuidNamespace, @@ -46,7 +46,7 @@ void cmUuid::CreateHashInput(std::vector<unsigned char> const& uuidNamespace,    if (!name.empty()) {      output.resize(output.size() + name.size()); -    memcpy(&output[0] + uuidNamespace.size(), name.c_str(), name.size()); +    memcpy(output.data() + uuidNamespace.size(), name.c_str(), name.size());    }  } @@ -59,7 +59,7 @@ std::string cmUuid::FromDigest(const unsigned char* digest,    memcpy(uuid, digest, 16);    uuid[6] &= 0xF; -  uuid[6] |= byte_t(version << 4); +  uuid[6] |= static_cast<byte_t>(version << 4);    uuid[8] &= 0x3F;    uuid[8] |= 0x80; @@ -118,7 +118,8 @@ std::string cmUuid::ByteToHex(unsigned char byte) const    for (int i = 0; i < 2; ++i) {      unsigned char rest = byte % 16;      byte /= 16; -    char c = (rest < 0xA) ? char('0' + rest) : char('a' + (rest - 0xA)); +    char c = (rest < 0xA) ? static_cast<char>('0' + rest) +                          : static_cast<char>('a' + (rest - 0xA));      result.at(1 - i) = c;    } @@ -143,7 +144,7 @@ bool cmUuid::StringToBinaryImpl(std::string const& input,        return false;      } -    output.push_back(char(c1 << 4 | c2)); +    output.push_back(static_cast<char>(c1 << 4 | c2));    }    return true; @@ -152,15 +153,15 @@ bool cmUuid::StringToBinaryImpl(std::string const& input,  bool cmUuid::IntFromHexDigit(char input, char& output) const  {    if (input >= '0' && input <= '9') { -    output = char(input - '0'); +    output = static_cast<char>(input - '0');      return true;    }    if (input >= 'a' && input <= 'f') { -    output = char(input - 'a' + 0xA); +    output = static_cast<char>(input - 'a' + 0xA);      return true;    }    if (input >= 'A' && input <= 'F') { -    output = char(input - 'A' + 0xA); +    output = static_cast<char>(input - 'A' + 0xA);      return true;    }    return false; 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..9f3d620 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -248,6 +248,8 @@ static std::string computeProjectFileExtension(VsProjectType projectType)    switch (projectType) {      case VsProjectType::csproj:        return ".csproj"; +    case VsProjectType::proj: +      return ".proj";      default:        return ".vcxproj";    } @@ -667,6 +669,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 +691,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 +749,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 +793,8 @@ void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile(            Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS);          }          break; +      default: +        break;      }      this->WriteTargetSpecificReferences(e0); @@ -924,6 +940,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) { @@ -1583,6 +1605,10 @@ void cmVisualStudio10TargetGenerator::WriteAndroidConfigurationValues(        e1.Element("UseOfStl", *stlType);      }    } +  std::string const& apiLevel = gg->GetSystemVersion(); +  if (!apiLevel.empty()) { +    e1.Element("AndroidAPILevel", cmStrCat("android-", apiLevel)); +  }  }  void cmVisualStudio10TargetGenerator::WriteCustomCommands(Elem& e0) @@ -3057,6 +3083,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(          cm::make_unique<Options>(this->LocalGenerator, Options::CSharpCompiler,                                   gg->GetCSharpFlagTable());        break; +    default: +      break;    }    Options& clOptions = *pOptions; @@ -3165,6 +3193,43 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(      }    } +  // Get includes for this target +  if (!this->LangForClCompile.empty()) { +    auto includeList = this->GetIncludes(configName, this->LangForClCompile); + +    auto sysIncludeFlag = this->Makefile->GetDefinition( +      cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", this->LangForClCompile)); + +    if (sysIncludeFlag) { +      bool gotOneSys = false; +      for (auto i : includeList) { +        cmSystemTools::ConvertToUnixSlashes(i); +        if (this->GeneratorTarget->IsSystemIncludeDirectory( +              i, configName, this->LangForClCompile)) { +          auto flag = cmTrimWhitespace(*sysIncludeFlag); +          if (this->MSTools) { +            cmSystemTools::ReplaceString(flag, "-external:I", "/external:I"); +          } +          clOptions.AppendFlagString("AdditionalOptions", +                                     cmStrCat(flag, " \"", i, '"')); +          gotOneSys = true; +        } else { +          clOptions.AddInclude(i); +        } +      } + +      if (gotOneSys) { +        if (auto sysIncludeFlagWarning = this->Makefile->GetDefinition( +              cmStrCat("_CMAKE_INCLUDE_SYSTEM_FLAG_", this->LangForClCompile, +                       "_WARNING"))) { +          flags = cmStrCat(flags, ' ', *sysIncludeFlagWarning); +        } +      } +    } else { +      clOptions.AddIncludes(includeList); +    } +  } +    clOptions.Parse(flags);    clOptions.Parse(defineFlags);    std::vector<std::string> targetDefines; @@ -3182,6 +3247,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(          return def.find('=') != std::string::npos;        });        break; +    default: +      break;    }    clOptions.AddDefines(targetDefines); @@ -3189,12 +3256,6 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(      clOptions.AppendFlag("DefineConstants", targetDefines);    } -  // Get includes for this target -  if (!this->LangForClCompile.empty()) { -    clOptions.AddIncludes( -      this->GetIncludes(configName, this->LangForClCompile)); -  } -    if (this->MSTools) {      clOptions.SetVerboseMakefile(        this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); @@ -3309,7 +3370,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 +3700,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 +4321,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 +4345,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) { 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..fb94273 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; @@ -104,23 +105,47 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,        if (status.GetContinueInvoked()) {          break;        } -      if (cmSystemTools::GetFatalErrorOccured()) { +      if (cmSystemTools::GetFatalErrorOccurred()) {          return true;        }      }    } +  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(); +      cmSystemTools::SetFatalErrorOccurred();      }    } 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..2eed297 --- /dev/null +++ b/Source/cmWindowsRegistry.h @@ -0,0 +1,86 @@ +/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying +   file Copyright.txt or https://cmake.org/licensing for details.  */ +#pragma once + +#include <cstdint> // IWYU pragma: keep +#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/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx index 666ba87..8ed9ea7 100644 --- a/Source/cmWriteFileCommand.cxx +++ b/Source/cmWriteFileCommand.cxx @@ -38,7 +38,7 @@ bool cmWriteFileCommand(std::vector<std::string> const& args,      std::string e =        "attempted to write a file: " + fileName + " into a source directory.";      status.SetError(e); -    cmSystemTools::SetFatalErrorOccured(); +    cmSystemTools::SetFatalErrorOccurred();      return false;    } diff --git a/Source/cmXMLWriter.cxx b/Source/cmXMLWriter.cxx index 0811bd0..e4ad9b4 100644 --- a/Source/cmXMLWriter.cxx +++ b/Source/cmXMLWriter.cxx @@ -10,10 +10,6 @@ cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)    : Output(output)    , IndentationElement(1, '\t')    , Level(level) -  , Indent(0) -  , ElementOpen(false) -  , BreakAttrib(false) -  , IsContent(false)  {  } diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h index 6e8eeb7..49fc864 100644 --- a/Source/cmXMLWriter.h +++ b/Source/cmXMLWriter.h @@ -124,10 +124,10 @@ private:    std::stack<std::string, std::vector<std::string>> Elements;    std::string IndentationElement;    std::size_t Level; -  std::size_t Indent; -  bool ElementOpen; -  bool BreakAttrib; -  bool IsContent; +  std::size_t Indent = 0; +  bool ElementOpen = false; +  bool BreakAttrib = false; +  bool IsContent = false;  };  class cmXMLElement; // IWYU pragma: keep diff --git a/Source/cmake.cxx b/Source/cmake.cxx index b47155e..1c1cab3 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -861,6 +861,11 @@ 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, @@ -1077,6 +1082,14 @@ void cmake::SetArgs(const std::vector<std::string>& args)                    << "uninitialized variables.\n";          state->SetCheckSystemVars(true);          return true; +      } }, +    CommandArgument{ +      "--compile-no-warning-as-error", CommandArgument::Values::Zero, +      [](std::string const&, cmake* state) -> bool { +        std::cout << "Ignoring COMPILE_WARNING_AS_ERROR target property and " +                  << "CMAKE_COMPILE_WARNING_AS_ERROR variable.\n"; +        state->SetIgnoreWarningAsError(true); +        return true;        } }    }; @@ -1148,6 +1161,12 @@ void cmake::SetArgs(const std::vector<std::string>& args)      // iterate each argument      std::string const& arg = args[i]; +    if (this->GetWorkingMode() == SCRIPT_MODE && 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)) { @@ -1445,7 +1464,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 @@ -1980,7 +1999,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)    }    cmSystemTools::Message(warning.str());    // avoid reconfigure if there were errors -  if (!cmSystemTools::GetErrorOccuredFlag()) { +  if (!cmSystemTools::GetErrorOccurredFlag()) {      // re-run configure      return this->Configure();    } @@ -2089,6 +2108,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"); @@ -2250,7 +2284,7 @@ int cmake::ActualConfigure()    this->State->SaveVerificationScript(this->GetHomeOutputDirectory(),                                        this->Messenger.get());    this->SaveCache(this->GetHomeOutputDirectory()); -  if (cmSystemTools::GetErrorOccuredFlag()) { +  if (cmSystemTools::GetErrorOccurredFlag()) {      return -1;    }    return 0; @@ -2364,7 +2398,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)  {    // Process the arguments    this->SetArgs(args); -  if (cmSystemTools::GetErrorOccuredFlag()) { +  if (cmSystemTools::GetErrorOccurredFlag()) {      return -1;    }    if (this->GetWorkingMode() == HELP_MODE) { @@ -2389,12 +2423,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();    } @@ -2414,7 +2455,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)    // In script mode we terminate after running the script.    if (this->GetWorkingMode() != NORMAL_MODE) { -    if (cmSystemTools::GetErrorOccuredFlag()) { +    if (cmSystemTools::GetErrorOccurredFlag()) {        return -1;      }      return 0; @@ -2488,7 +2529,7 @@ int cmake::Generate()    if (this->WarnUnusedCli) {      this->RunCheckForUnusedVariables();    } -  if (cmSystemTools::GetErrorOccuredFlag()) { +  if (cmSystemTools::GetErrorOccurredFlag()) {      return -1;    }    // Save the cache again after a successful Generate so that any internal @@ -2507,7 +2548,7 @@ void cmake::AddCacheEntry(const std::string& key, cmValue value,                            const char* helpString, int type)  {    this->State->AddCacheEntry(key, value, helpString, -                             cmStateEnums::CacheEntryType(type)); +                             static_cast<cmStateEnums::CacheEntryType>(type));    this->UnwatchUnusedCli(key);    if (key == "CMAKE_WARN_DEPRECATED"_s) { @@ -2848,7 +2889,7 @@ int cmake::CheckBuildSystem()    cmGlobalGenerator gg(&cm);    cmMakefile mf(&gg, cm.GetCurrentSnapshot());    if (!mf.ReadListFile(this->CheckBuildSystemArgument) || -      cmSystemTools::GetErrorOccuredFlag()) { +      cmSystemTools::GetErrorOccurredFlag()) {      if (verbose) {        std::ostringstream msg;        msg << "Re-run cmake error reading : " << this->CheckBuildSystemArgument diff --git a/Source/cmake.h b/Source/cmake.h index 3c2a36c..3c6af17 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -534,6 +534,8 @@ public:    void SetWarnUnusedCli(bool b) { this->WarnUnusedCli = b; }    bool GetCheckSystemVars() const { return this->CheckSystemVars; }    void SetCheckSystemVars(bool b) { this->CheckSystemVars = b; } +  bool GetIgnoreWarningAsError() const { return this->IgnoreWarningAsError; } +  void SetIgnoreWarningAsError(bool b) { this->IgnoreWarningAsError = b; }    void MarkCliAsUsed(const std::string& variable); @@ -686,6 +688,7 @@ private:    bool WarnUninitialized = false;    bool WarnUnusedCli = true;    bool CheckSystemVars = false; +  bool IgnoreWarningAsError = false;    std::map<std::string, bool> UsedCliVariables;    std::string CMakeEditCommand;    std::string CXXEnvironment; @@ -703,6 +706,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..f931e9d 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." }, @@ -108,6 +111,9 @@ const char* cmDocumentationOptions[][2] = {    { "--check-system-vars",      "Find problems with variable usage in system "      "files." }, +  { "--compile-no-warning-as-error", +    "Ignore COMPILE_WARNING_AS_ERROR property and " +    "CMAKE_COMPILE_WARNING_AS_ERROR variable." },  #  if !defined(CMAKE_BOOTSTRAP)    { "--profiling-format=<fmt>",      "Output data for profiling CMake scripts. Supported formats: " @@ -201,7 +207,7 @@ int do_cmake(int ac, char const* const* av)  #ifndef CMAKE_BOOTSTRAP    cmDocumentation doc;    doc.addCMakeStandardDocSections(); -  if (doc.CheckOptions(ac, av)) { +  if (doc.CheckOptions(ac, av, "--")) {      // Construct and print requested documentation.      cmake hcm(cmake::RoleInternal, cmState::Unknown);      hcm.SetHomeDirectory(""); @@ -260,37 +266,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, @@ -423,7 +409,7 @@ int extract_job_number(std::string const& command,      } else if (numJobs > INT_MAX) {        std::cerr << "The <jobs> value is too large.\n\n";      } else { -      jobs = int(numJobs); +      jobs = static_cast<int>(numJobs);      }    } else {      std::cerr << "'" << command << "' invalid number '" << jobString @@ -508,15 +494,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 +505,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 +517,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) { @@ -623,7 +594,7 @@ int do_build(int ac, char const* const* av)                           "is too large.\n\n";              dir.clear();            } else { -            jobs = int(numJobs); +            jobs = static_cast<int>(numJobs);            }          } else {            std::cerr << "'CMAKE_BUILD_PARALLEL_LEVEL' environment variable\n" @@ -829,31 +800,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..9ab39f1 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;        } @@ -2055,8 +2069,8 @@ class cmVSLink  {    int Type;    bool Verbose; -  bool Incremental; -  bool LinkGeneratesManifest; +  bool Incremental = false; +  bool LinkGeneratesManifest = true;    std::vector<std::string> LinkCommand;    std::vector<std::string> UserManifests;    std::string LinkerManifestFile; @@ -2071,8 +2085,6 @@ public:    cmVSLink(int type, bool verbose)      : Type(type)      , Verbose(verbose) -    , Incremental(false) -    , LinkGeneratesManifest(true)    {    }    bool Parse(std::vector<std::string>::const_iterator argBeg, 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/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 2253a83..af02f7f 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -88,17 +88,7 @@  # any outside mailing list and no documentation of the change will be  # written. -cmake_minimum_required(VERSION 3.1 FATAL_ERROR) -foreach(p -    CMP0056 # CMake 3.2, Honor link flags in try_compile() source-file signature. -    CMP0063 # CMake 3.3, Honor visibility properties for all target types. -    CMP0067 # CMake 3.8, Honor language standard in try_compile source-file signature. -    CMP0069 # CMake 3.9, INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. -    ) -  if(POLICY ${p}) -    cmake_policy(SET ${p} NEW) -  endif() -endforeach() +cmake_minimum_required(VERSION 3.9...3.22 FATAL_ERROR)  # Some configure checks depend upon the deployment target. Clear checks when  # the deployment target changes. @@ -1111,7 +1101,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR)      # Some Apple compilers produce bad optimizations in this source.      if(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$")        set(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -O0") -    elseif(CMAKE_C_COMPILER_ID STREQUAL "XL") +    elseif(CMAKE_C_COMPILER_ID MATCHES "^(XL|XLClang)$")        # Tell IBM XL not to warn about our test infinite loop        if(CMAKE_SYSTEM MATCHES "Linux.*ppc64le"           AND CMAKE_C_COMPILER_VERSION VERSION_LESS "16.1.0" diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 19bf982..45a9e6f 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -1,5 +1,9 @@  /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying     file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */ +#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) +/* NOLINTNEXTLINE(bugprone-reserved-identifier) */ +#  define _XOPEN_SOURCE 600 +#endif  #include "kwsysPrivate.h"  #include KWSYS_HEADER(Process.h)  #include KWSYS_HEADER(System.h) @@ -1906,7 +1910,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"); diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index c38b456..5889a4b 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -94,6 +94,13 @@  #  include <linux/fs.h>  #endif +#if defined(__APPLE__) &&                                                     \ +  (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - 0 >= 101200) +#  define KWSYS_SYSTEMTOOLS_HAVE_MACOS_COPYFILE_CLONE +#  include <copyfile.h> +#  include <sys/stat.h> +#endif +  // Windows API.  #if defined(_WIN32)  #  include <windows.h> @@ -2474,6 +2481,26 @@ Status SystemTools::CloneFileContent(std::string const& source,    close(out);    return status; +#elif defined(__APPLE__) &&                                                   \ +  defined(KWSYS_SYSTEMTOOLS_HAVE_MACOS_COPYFILE_CLONE) +  // NOTE: we cannot use `clonefile` as the {a,c,m}time for the file needs to +  // be updated by `copy_file_if_different` and `copy_file`. +  if (copyfile(source.c_str(), destination.c_str(), nullptr, +               COPYFILE_METADATA | COPYFILE_CLONE) < 0) { +    return Status::POSIX_errno(); +  } +#  if KWSYS_CXX_HAS_UTIMENSAT +  // utimensat is only available on newer Unixes and macOS 10.13+ +  if (utimensat(AT_FDCWD, destination.c_str(), nullptr, 0) < 0) { +    return Status::POSIX_errno(); +  } +#  else +  // fall back to utimes +  if (utimes(destination.c_str(), nullptr) < 0) { +    return Status::POSIX_errno(); +  } +#  endif +  return Status::Success();  #else    (void)source;    (void)destination; diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c index 20bb5fe..39081a7 100644 --- a/Source/kwsys/Terminal.c +++ b/Source/kwsys/Terminal.c @@ -1,5 +1,9 @@  /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying     file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */ +#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) +/* NOLINTNEXTLINE(bugprone-reserved-identifier) */ +#  define _XOPEN_SOURCE 600 +#endif  #include "kwsysPrivate.h"  #include KWSYS_HEADER(Terminal.h) diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c index eed770c..fcc31da 100644 --- a/Source/kwsys/testProcess.c +++ b/Source/kwsys/testProcess.c @@ -1,5 +1,9 @@  /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying     file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */ +#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) +/* NOLINTNEXTLINE(bugprone-reserved-identifier) */ +#  define _XOPEN_SOURCE 600 +#endif  #include "kwsysPrivate.h"  #include KWSYS_HEADER(Process.h)  #include KWSYS_HEADER(Encoding.h) diff --git a/Source/kwsys/testSharedForward.c.in b/Source/kwsys/testSharedForward.c.in index b3eb413..e909458 100644 --- a/Source/kwsys/testSharedForward.c.in +++ b/Source/kwsys/testSharedForward.c.in @@ -1,5 +1,9 @@  /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying     file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */ +#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) +/* NOLINTNEXTLINE(bugprone-reserved-identifier) */ +#  define _XOPEN_SOURCE 600 +#endif  #if defined(CMAKE_INTDIR)  #  define CONFIG_DIR_PRE CMAKE_INTDIR "/"  #  define CONFIG_DIR_POST "/" CMAKE_INTDIR  | 
