diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-10-08 09:13:33 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-10-08 09:13:33 +0900 |
commit | 48d9a397fa3cf76397824122450a1450af712716 (patch) | |
tree | 37bb17e0bcabc1da17c5606716c713de5d7d0366 /Source | |
parent | 53666ee1cffac26c55edcbd9361dbd88a734cfa7 (diff) | |
download | cmake-48d9a397fa3cf76397824122450a1450af712716.tar.gz cmake-48d9a397fa3cf76397824122450a1450af712716.tar.bz2 cmake-48d9a397fa3cf76397824122450a1450af712716.zip |
Imported Upstream version 3.13.0upstream/3.13.0
Diffstat (limited to 'Source')
259 files changed, 9083 insertions, 5355 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 30bef744e..311f3f4e5 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -265,6 +265,7 @@ set(SRCS cmInstallDirectoryGenerator.h cmInstallDirectoryGenerator.cxx cmLinkedTree.h + cmLinkItem.cxx cmLinkItem.h cmLinkLineComputer.cxx cmLinkLineComputer.h @@ -379,6 +380,8 @@ set(SRCS cmAddCompileDefinitionsCommand.h cmAddCompileOptionsCommand.cxx cmAddCompileOptionsCommand.h + cmAddLinkOptionsCommand.cxx + cmAddLinkOptionsCommand.h cmAddCustomCommandCommand.cxx cmAddCustomCommandCommand.h cmAddCustomTargetCommand.cxx @@ -574,6 +577,10 @@ set(SRCS cmTargetCompileOptionsCommand.h cmTargetIncludeDirectoriesCommand.cxx cmTargetIncludeDirectoriesCommand.h + cmTargetLinkOptionsCommand.cxx + cmTargetLinkOptionsCommand.h + cmTargetLinkDirectoriesCommand.cxx + cmTargetLinkDirectoriesCommand.h cmTargetLinkLibrariesCommand.cxx cmTargetLinkLibrariesCommand.h cmTargetPropCommandBase.cxx @@ -882,6 +889,8 @@ include_directories( set(CPACK_SRCS CPack/cmCPackArchiveGenerator.cxx CPack/cmCPackComponentGroup.cxx + CPack/cmCPackDebGenerator.cxx + CPack/cmCPackExternalGenerator.cxx CPack/cmCPackGeneratorFactory.cxx CPack/cmCPackGenerator.cxx CPack/cmCPackLog.cxx @@ -894,7 +903,6 @@ set(CPACK_SRCS CPack/cmCPackTarCompressGenerator.cxx CPack/cmCPackZIPGenerator.cxx CPack/cmCPack7zGenerator.cxx - CPack/cmCPackDebGenerator.cxx ) # CPack IFW generator set(CPACK_SRCS ${CPACK_SRCS} @@ -1041,6 +1049,9 @@ target_link_libraries(cmake CMakeLib) add_library(CMakeServerLib cmConnection.h cmConnection.cxx cmFileMonitor.cxx cmFileMonitor.h + cmJsonObjectDictionary.h + cmJsonObjects.h + cmJsonObjects.cxx cmPipeConnection.cxx cmPipeConnection.h cmServer.cxx cmServer.h cmServerConnection.cxx cmServerConnection.h diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ff557e1b8..184308798 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) -set(CMake_VERSION_MINOR 12) -set(CMake_VERSION_PATCH 4) +set(CMake_VERSION_MINOR 13) +set(CMake_VERSION_PATCH 0) #set(CMake_VERSION_RC 0) diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index cf8334aef..180c92eed 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -90,7 +90,7 @@ int cmCPackIFWGenerator::PackageFiles() ifwCmd.c_str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose, cmDuration::zero()); if (!res || retVal) { - cmGeneratedFileStream ofs(ifwTmpFile.c_str()); + cmGeneratedFileStream ofs(ifwTmpFile); ofs << "# Run command: " << ifwCmd << std::endl << "# Output:" << std::endl << output << std::endl; @@ -203,7 +203,7 @@ int cmCPackIFWGenerator::PackageFiles() ifwCmd.c_str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose, cmDuration::zero()); if (!res || retVal) { - cmGeneratedFileStream ofs(ifwTmpFile.c_str()); + cmGeneratedFileStream ofs(ifwTmpFile); ofs << "# Run command: " << ifwCmd << std::endl << "# Output:" << std::endl << output << std::endl; diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index 36cf08cfc..8f492afde 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -306,7 +306,7 @@ void cmCPackIFWInstaller::GenerateInstallerFile() } // Output stream - cmGeneratedFileStream fout((this->Directory + "/config/config.xml").data()); + cmGeneratedFileStream fout(this->Directory + "/config/config.xml"); cmXMLWriter xout(fout); xout.StartDocument(); diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index f24ab6997..67e279c6b 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -528,7 +528,7 @@ void cmCPackIFWPackage::GeneratePackageFile() } // Output stream - cmGeneratedFileStream fout((this->Directory + "/meta/package.xml").data()); + cmGeneratedFileStream fout(this->Directory + "/meta/package.xml"); cmXMLWriter xout(fout); xout.StartDocument(); diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx index a01fc4ed3..987cad89e 100644 --- a/Source/CPack/IFW/cmCPackIFWRepository.cxx +++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx @@ -183,7 +183,7 @@ bool cmCPackIFWRepository::PatchUpdatesXml() this->Directory + "/repository/UpdatesPatch.xml"; // Output stream - cmGeneratedFileStream fout(updatesPatchXml.data()); + cmGeneratedFileStream fout(updatesPatchXml); cmXMLWriter xout(fout); xout.StartDocument(); diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index e06efdafd..398ebd399 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -100,6 +100,10 @@ bool cmCPackWIXGenerator::RunCandleCommand(std::string const& sourceFile, command << " -ext " << QuotePath(ext); } + if (sourceFile.rfind(this->CPackTopLevel, 0) != 0) { + command << " " << QuotePath("-I" + this->CPackTopLevel); + } + AddCustomFlags("CPACK_WIX_CANDLE_EXTRA_FLAGS", command); command << " " << QuotePath(sourceFile); @@ -148,7 +152,7 @@ int cmCPackWIXGenerator::PackageFiles() bool cmCPackWIXGenerator::InitializeWiXConfiguration() { - if (!ReadListFile("CPackWIX.cmake")) { + if (!ReadListFile("Internal/CPack/CPackWIX.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while executing CPackWIX.cmake" << std::endl); return false; diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index b734bb460..ee1070fe5 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -103,18 +103,18 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( */ #define DECLARE_AND_OPEN_ARCHIVE(filename, archive) \ cmGeneratedFileStream gf; \ - gf.Open((filename).c_str(), false, true); \ + gf.Open((filename), false, true); \ if (!GenerateHeader(&gf)) { \ cmCPackLogger(cmCPackLog::LOG_ERROR, \ - "Problem to generate Header for archive < " \ + "Problem to generate Header for archive <" \ << (filename) << ">." << std::endl); \ return 0; \ } \ cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat); \ if (!(archive)) { \ cmCPackLogger(cmCPackLog::LOG_ERROR, \ - "Problem to create archive < " \ - << (filename) << ">. ERROR =" << (archive).GetError() \ + "Problem to create archive <" \ + << (filename) << ">, ERROR = " << (archive).GetError() \ << std::endl); \ return 0; \ } @@ -262,9 +262,9 @@ int cmCPackArchiveGenerator::PackageFiles() archive.Add(rp, 0, nullptr, false); if (!archive) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem while adding file< " + "Problem while adding file <" << file << "> to archive <" << packageFileNames[0] - << "> .ERROR =" << archive.GetError() << std::endl); + << ">, ERROR = " << archive.GetError() << std::endl); return 0; } } diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h index f2907db20..bb980d77f 100644 --- a/Source/CPack/cmCPackComponentGroup.h +++ b/Source/CPack/cmCPackComponentGroup.h @@ -143,4 +143,29 @@ public: std::vector<cmCPackComponentGroup*> Subgroups; }; +/** \class cmCPackInstallCMakeProject + * \brief A single quadruplet from the CPACK_INSTALL_CMAKE_PROJECTS variable. + */ +class cmCPackInstallCMakeProject +{ +public: + /// The directory of the CMake project. + std::string Directory; + + /// The name of the CMake project. + std::string ProjectName; + + /// The name of the component (or component set) to install. + std::string Component; + + /// The subdirectory to install into. + std::string SubDirectory; + + /// The list of installation types. + std::vector<cmCPackInstallationType*> InstallationTypes; + + /// The list of components. + std::vector<cmCPackComponent*> Components; +}; + #endif diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 8a4c00427..ea0ee5815 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -12,11 +12,430 @@ #include "cm_sys_stat.h" #include "cmsys/Glob.hxx" +#include <map> #include <ostream> #include <set> #include <string.h> #include <utility> +namespace { + +class DebGenerator +{ +public: + DebGenerator(cmCPackLog* logger, std::string const& outputName, + std::string const& workDir, std::string const& topLevelDir, + std::string const& temporaryDir, + const char* debianCompressionType, + const char* debianArchiveType, + std::map<std::string, std::string> const& controlValues, + bool genShLibs, std::string const& shLibsFilename, + bool genPostInst, std::string const& postInst, bool genPostRm, + std::string const& postRm, const char* controlExtra, + bool permissionStrctPolicy, + std::vector<std::string> const& packageFiles); + + bool generate() const; + +private: + void generateDebianBinaryFile() const; + void generateControlFile() const; + bool generateDataTar() const; + std::string generateMD5File() const; + bool generateControlTar(std::string const& md5Filename) const; + bool generateDeb() const; + + cmCPackLog* Logger; + const std::string OutputName; + const std::string WorkDir; + std::string CompressionSuffix; + const std::string TopLevelDir; + const std::string TemporaryDir; + const char* DebianArchiveType; + const std::map<std::string, std::string> ControlValues; + const bool GenShLibs; + const std::string ShLibsFilename; + const bool GenPostInst; + const std::string PostInst; + const bool GenPostRm; + const std::string PostRm; + const char* ControlExtra; + const bool PermissionStrictPolicy; + const std::vector<std::string> PackageFiles; + cmArchiveWrite::Compress TarCompressionType; +}; + +DebGenerator::DebGenerator( + cmCPackLog* logger, std::string const& outputName, + std::string const& workDir, std::string const& topLevelDir, + std::string const& temporaryDir, const char* debianCompressionType, + const char* debianArchiveType, + std::map<std::string, std::string> const& controlValues, bool genShLibs, + std::string const& shLibsFilename, bool genPostInst, + std::string const& postInst, bool genPostRm, std::string const& postRm, + const char* controlExtra, bool permissionStrictPolicy, + std::vector<std::string> const& packageFiles) + : Logger(logger) + , OutputName(outputName) + , WorkDir(workDir) + , TopLevelDir(topLevelDir) + , TemporaryDir(temporaryDir) + , DebianArchiveType(debianArchiveType ? debianArchiveType : "paxr") + , ControlValues(controlValues) + , GenShLibs(genShLibs) + , ShLibsFilename(shLibsFilename) + , GenPostInst(genPostInst) + , PostInst(postInst) + , GenPostRm(genPostRm) + , PostRm(postRm) + , ControlExtra(controlExtra) + , PermissionStrictPolicy(permissionStrictPolicy) + , PackageFiles(packageFiles) +{ + if (!debianCompressionType) { + debianCompressionType = "gzip"; + } + + if (!strcmp(debianCompressionType, "lzma")) { + CompressionSuffix = ".lzma"; + TarCompressionType = cmArchiveWrite::CompressLZMA; + } else if (!strcmp(debianCompressionType, "xz")) { + CompressionSuffix = ".xz"; + TarCompressionType = cmArchiveWrite::CompressXZ; + } else if (!strcmp(debianCompressionType, "bzip2")) { + CompressionSuffix = ".bz2"; + TarCompressionType = cmArchiveWrite::CompressBZip2; + } else if (!strcmp(debianCompressionType, "gzip")) { + CompressionSuffix = ".gz"; + TarCompressionType = cmArchiveWrite::CompressGZip; + } else if (!strcmp(debianCompressionType, "none")) { + CompressionSuffix.clear(); + TarCompressionType = cmArchiveWrite::CompressNone; + } else { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error unrecognized compression type: " + << debianCompressionType << std::endl); + } +} + +bool DebGenerator::generate() const +{ + generateDebianBinaryFile(); + generateControlFile(); + if (!generateDataTar()) { + return false; + } + std::string md5Filename = generateMD5File(); + if (!generateControlTar(md5Filename)) { + return false; + } + return generateDeb(); +} + +void DebGenerator::generateDebianBinaryFile() const +{ + // debian-binary file + const std::string dbfilename = WorkDir + "/debian-binary"; + cmGeneratedFileStream out(dbfilename); + out << "2.0"; + out << std::endl; // required for valid debian package +} + +void DebGenerator::generateControlFile() const +{ + std::string ctlfilename = WorkDir + "/control"; + + cmGeneratedFileStream out(ctlfilename); + for (auto const& kv : ControlValues) { + out << kv.first << ": " << kv.second << "\n"; + } + + unsigned long totalSize = 0; + { + std::string dirName = TemporaryDir; + dirName += '/'; + for (std::string const& file : PackageFiles) { + totalSize += cmSystemTools::FileLength(file); + } + } + out << "Installed-Size: " << (totalSize + 1023) / 1024 << "\n"; + out << std::endl; +} + +bool DebGenerator::generateDataTar() const +{ + std::string filename_data_tar = WorkDir + "/data.tar" + CompressionSuffix; + cmGeneratedFileStream fileStream_data_tar; + fileStream_data_tar.Open(filename_data_tar, false, true); + if (!fileStream_data_tar) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error opening the file \"" + << filename_data_tar << "\" for writing" << std::endl); + return false; + } + cmArchiveWrite data_tar(fileStream_data_tar, TarCompressionType, + DebianArchiveType); + + // uid/gid should be the one of the root user, and this root user has + // always uid/gid equal to 0. + data_tar.SetUIDAndGID(0u, 0u); + data_tar.SetUNAMEAndGNAME("root", "root"); + + // now add all directories which have to be compressed + // collect all top level install dirs for that + // e.g. /opt/bin/foo, /usr/bin/bar and /usr/bin/baz would + // give /usr and /opt + size_t topLevelLength = WorkDir.length(); + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "WDIR: \"" << WorkDir << "\", length = " << topLevelLength + << std::endl); + std::set<std::string> orderedFiles; + + // we have to reconstruct the parent folders as well + + for (std::string currentPath : PackageFiles) { + while (currentPath != WorkDir) { + // the last one IS WorkDir, but we do not want this one: + // XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application + // should not add XXX/application + orderedFiles.insert(currentPath); + currentPath = cmSystemTools::CollapseCombinedPath(currentPath, ".."); + } + } + + for (std::string const& file : orderedFiles) { + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "FILEIT: \"" << file << "\"" << std::endl); + std::string::size_type slashPos = file.find('/', topLevelLength + 1); + std::string relativeDir = + file.substr(topLevelLength, slashPos - topLevelLength); + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "RELATIVEDIR: \"" << relativeDir << "\"" << std::endl); + +#ifdef WIN32 + std::string mode_t_adt_filename = file + ":cmake_mode_t"; + cmsys::ifstream permissionStream(mode_t_adt_filename.c_str()); + + mode_t permissions = 0; + + if (permissionStream) { + permissionStream >> std::oct >> permissions; + } + + if (permissions != 0) { + data_tar.SetPermissions(permissions); + } else if (cmSystemTools::FileIsDirectory(file)) { + data_tar.SetPermissions(0755); + } else { + data_tar.ClearPermissions(); + } +#endif + + // do not recurse because the loop will do it + if (!data_tar.Add(file, topLevelLength, ".", false)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem adding file to tar:" + << std::endl + << "#top level directory: " << WorkDir << std::endl + << "#file: " << file << std::endl + << "#error:" << data_tar.GetError() << std::endl); + return false; + } + } + return true; +} + +std::string DebGenerator::generateMD5File() const +{ + std::string md5filename = WorkDir + "/md5sums"; + + cmGeneratedFileStream out(md5filename); + + std::string topLevelWithTrailingSlash = TemporaryDir; + topLevelWithTrailingSlash += '/'; + for (std::string const& file : PackageFiles) { + // hash only regular files + if (cmSystemTools::FileIsDirectory(file) || + cmSystemTools::FileIsSymlink(file)) { + continue; + } + + std::string output = + cmSystemTools::ComputeFileHash(file, cmCryptoHash::AlgoMD5); + if (output.empty()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem computing the md5 of " << file << std::endl); + } + + output += " " + file + "\n"; + // debian md5sums entries are like this: + // 014f3604694729f3bf19263bac599765 usr/bin/ccmake + // thus strip the full path (with the trailing slash) + cmSystemTools::ReplaceString(output, topLevelWithTrailingSlash.c_str(), + ""); + out << output; + } + // each line contains a eol. + // Do not end the md5sum file with yet another (invalid) + return md5filename; +} + +bool DebGenerator::generateControlTar(std::string const& md5Filename) const +{ + std::string filename_control_tar = WorkDir + "/control.tar.gz"; + + cmGeneratedFileStream fileStream_control_tar; + fileStream_control_tar.Open(filename_control_tar, false, true); + if (!fileStream_control_tar) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error opening the file \"" + << filename_control_tar << "\" for writing" << std::endl); + return false; + } + cmArchiveWrite control_tar(fileStream_control_tar, + cmArchiveWrite::CompressGZip, DebianArchiveType); + + // sets permissions and uid/gid for the files + control_tar.SetUIDAndGID(0u, 0u); + control_tar.SetUNAMEAndGNAME("root", "root"); + + /* permissions are set according to + https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners + and + https://lintian.debian.org/tags/control-file-has-bad-permissions.html + */ + const mode_t permission644 = 0644; + const mode_t permissionExecute = 0111; + const mode_t permission755 = permission644 | permissionExecute; + + // for md5sum and control (that we have generated here), we use 644 + // (RW-R--R--) + // so that deb lintian doesn't warn about it + control_tar.SetPermissions(permission644); + + // adds control and md5sums + if (!control_tar.Add(md5Filename, WorkDir.length(), ".") || + !control_tar.Add(WorkDir + "/control", WorkDir.length(), ".")) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error adding file to tar:" + << std::endl + << "#top level directory: " << WorkDir << std::endl + << "#file: \"control\" or \"md5sums\"" << std::endl + << "#error:" << control_tar.GetError() << std::endl); + return false; + } + + // adds generated shlibs file + if (GenShLibs) { + if (!control_tar.Add(ShLibsFilename, WorkDir.length(), ".")) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error adding file to tar:" + << std::endl + << "#top level directory: " << WorkDir << std::endl + << "#file: \"shlibs\"" << std::endl + << "#error:" << control_tar.GetError() << std::endl); + return false; + } + } + + // adds LDCONFIG related files + if (GenPostInst) { + control_tar.SetPermissions(permission755); + if (!control_tar.Add(PostInst, WorkDir.length(), ".")) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error adding file to tar:" + << std::endl + << "#top level directory: " << WorkDir << std::endl + << "#file: \"postinst\"" << std::endl + << "#error:" << control_tar.GetError() << std::endl); + return false; + } + control_tar.SetPermissions(permission644); + } + + if (GenPostRm) { + control_tar.SetPermissions(permission755); + if (!control_tar.Add(PostRm, WorkDir.length(), ".")) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error adding file to tar:" + << std::endl + << "#top level directory: " << WorkDir << std::endl + << "#file: \"postinst\"" << std::endl + << "#error:" << control_tar.GetError() << std::endl); + return false; + } + control_tar.SetPermissions(permission644); + } + + // for the other files, we use + // -either the original permission on the files + // -either a permission strictly defined by the Debian policies + if (ControlExtra) { + // permissions are now controlled by the original file permissions + + static const char* strictFiles[] = { "config", "postinst", "postrm", + "preinst", "prerm" }; + std::set<std::string> setStrictFiles( + strictFiles, strictFiles + sizeof(strictFiles) / sizeof(strictFiles[0])); + + // default + control_tar.ClearPermissions(); + + std::vector<std::string> controlExtraList; + cmSystemTools::ExpandListArgument(ControlExtra, controlExtraList); + for (std::string const& i : controlExtraList) { + std::string filenamename = cmsys::SystemTools::GetFilenameName(i); + std::string localcopy = WorkDir + "/" + filenamename; + + if (PermissionStrictPolicy) { + control_tar.SetPermissions( + setStrictFiles.count(filenamename) ? permission755 : permission644); + } + + // if we can copy the file, it means it does exist, let's add it: + if (cmsys::SystemTools::CopyFileIfDifferent(i, localcopy)) { + control_tar.Add(localcopy, WorkDir.length(), "."); + } + } + } + + return true; +} + +bool DebGenerator::generateDeb() const +{ + // ar -r your-package-name.deb debian-binary control.tar.* data.tar.* + // A debian package .deb is simply an 'ar' archive. The only subtle + // difference is that debian uses the BSD ar style archive whereas most + // Linux distro have a GNU ar. + // See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=161593 for more info + std::string const outputPath = TopLevelDir + "/" + OutputName; + std::string const tlDir = WorkDir + "/"; + cmGeneratedFileStream debStream; + debStream.Open(outputPath, false, true); + cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd"); + + // uid/gid should be the one of the root user, and this root user has + // always uid/gid equal to 0. + deb.SetUIDAndGID(0u, 0u); + deb.SetUNAMEAndGNAME("root", "root"); + + if (!deb.Add(tlDir + "debian-binary", tlDir.length()) || + !deb.Add(tlDir + "control.tar.gz", tlDir.length()) || + !deb.Add(tlDir + "data.tar" + CompressionSuffix, tlDir.length())) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error creating debian package:" + << std::endl + << "#top level directory: " << TopLevelDir << std::endl + << "#file: " << OutputName << std::endl + << "#error:" << deb.GetError() << std::endl); + return false; + } + return true; +} + +} // end anonymous namespace + cmCPackDebGenerator::cmCPackDebGenerator() { } @@ -61,25 +480,27 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, component_path += packageName; this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", component_path.c_str()); - if (!this->ReadListFile("CPackDeb.cmake")) { + if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackDeb.cmake" << std::endl); retval = 0; return retval; } - cmsys::Glob gl; - std::string findExpr(this->GetOption("GEN_WDIR")); - findExpr += "/*"; - gl.RecurseOn(); - gl.SetRecurseListDirs(true); - if (!gl.FindFiles(findExpr)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find any files in the installed directory" - << std::endl); - return 0; + { // Isolate globbing of binaries vs. dbgsyms + cmsys::Glob gl; + std::string findExpr(this->GetOption("GEN_WDIR")); + findExpr += "/*"; + gl.RecurseOn(); + gl.SetRecurseListDirs(true); + if (!gl.FindFiles(findExpr)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot find any files in the installed directory" + << std::endl); + return 0; + } + packageFiles = gl.GetFiles(); } - packageFiles = gl.GetFiles(); int res = createDeb(); if (res != 1) { @@ -90,6 +511,32 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, packageFileName += "/"; packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"); packageFileNames.push_back(std::move(packageFileName)); + + if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE")) { + cmsys::Glob gl; + std::string findExpr(this->GetOption("GEN_DBGSYMDIR")); + findExpr += "/*"; + gl.RecurseOn(); + gl.SetRecurseListDirs(true); + if (!gl.FindFiles(findExpr)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot find any files in the installed directory" + << std::endl); + return 0; + } + packageFiles = gl.GetFiles(); + + res = createDbgsymDDeb(); + if (res != 1) { + retval = 0; + } + // add the generated package to package file names list + packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + packageFileName += "/"; + packageFileName += this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"); + packageFileNames.push_back(std::move(packageFileName)); + } + return retval; } @@ -179,7 +626,7 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", component_path.c_str()); } - if (!this->ReadListFile("CPackDeb.cmake")) { + if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackDeb.cmake" << std::endl); retval = 0; @@ -234,112 +681,81 @@ int cmCPackDebGenerator::PackageFiles() int cmCPackDebGenerator::createDeb() { - // debian-binary file - const std::string strGenWDIR(this->GetOption("GEN_WDIR")); - const std::string dbfilename = strGenWDIR + "/debian-binary"; - { // the scope is needed for cmGeneratedFileStream - cmGeneratedFileStream out(dbfilename.c_str()); - out << "2.0"; - out << std::endl; // required for valid debian package - } - - // control file - std::string ctlfilename = strGenWDIR + "/control"; + std::map<std::string, std::string> controlValues; // debian policy enforce lower case for package name - // mandatory entries: - std::string debian_pkg_name = cmsys::SystemTools::LowerCase( + controlValues["Package"] = cmsys::SystemTools::LowerCase( this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME")); - const char* debian_pkg_version = + controlValues["Version"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION"); - const char* debian_pkg_section = + controlValues["Section"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SECTION"); - const char* debian_pkg_priority = + controlValues["Priority"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PRIORITY"); - const char* debian_pkg_arch = + controlValues["Architecture"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE"); - const char* maintainer = + controlValues["Maintainer"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER"); - const char* desc = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION"); + controlValues["Description"] = + this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION"); - // optional entries + const char* debian_pkg_source = + this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); + if (debian_pkg_source && *debian_pkg_source) { + controlValues["Source"] = debian_pkg_source; + } const char* debian_pkg_dep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS"); + if (debian_pkg_dep && *debian_pkg_dep) { + controlValues["Depends"] = debian_pkg_dep; + } const char* debian_pkg_rec = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS"); + if (debian_pkg_rec && *debian_pkg_rec) { + controlValues["Recommends"] = debian_pkg_rec; + } const char* debian_pkg_sug = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS"); + if (debian_pkg_sug && *debian_pkg_sug) { + controlValues["Suggests"] = debian_pkg_sug; + } const char* debian_pkg_url = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE"); + if (debian_pkg_url && *debian_pkg_url) { + controlValues["Homepage"] = debian_pkg_url; + } const char* debian_pkg_predep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PREDEPENDS"); + if (debian_pkg_predep && *debian_pkg_predep) { + controlValues["Pre-Depends"] = debian_pkg_predep; + } const char* debian_pkg_enhances = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ENHANCES"); + if (debian_pkg_enhances && *debian_pkg_enhances) { + controlValues["Enhances"] = debian_pkg_enhances; + } const char* debian_pkg_breaks = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_BREAKS"); + if (debian_pkg_breaks && *debian_pkg_breaks) { + controlValues["Breaks"] = debian_pkg_breaks; + } const char* debian_pkg_conflicts = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONFLICTS"); + if (debian_pkg_conflicts && *debian_pkg_conflicts) { + controlValues["Conflicts"] = debian_pkg_conflicts; + } const char* debian_pkg_provides = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES"); + if (debian_pkg_provides && *debian_pkg_provides) { + controlValues["Provides"] = debian_pkg_provides; + } const char* debian_pkg_replaces = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_REPLACES"); - const char* debian_pkg_source = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); - - { // the scope is needed for cmGeneratedFileStream - cmGeneratedFileStream out(ctlfilename.c_str()); - out << "Package: " << debian_pkg_name << "\n"; - out << "Version: " << debian_pkg_version << "\n"; - out << "Section: " << debian_pkg_section << "\n"; - out << "Priority: " << debian_pkg_priority << "\n"; - out << "Architecture: " << debian_pkg_arch << "\n"; - if (debian_pkg_source && *debian_pkg_source) { - out << "Source: " << debian_pkg_source << "\n"; - } - if (debian_pkg_dep && *debian_pkg_dep) { - out << "Depends: " << debian_pkg_dep << "\n"; - } - if (debian_pkg_rec && *debian_pkg_rec) { - out << "Recommends: " << debian_pkg_rec << "\n"; - } - if (debian_pkg_sug && *debian_pkg_sug) { - out << "Suggests: " << debian_pkg_sug << "\n"; - } - if (debian_pkg_url && *debian_pkg_url) { - out << "Homepage: " << debian_pkg_url << "\n"; - } - if (debian_pkg_predep && *debian_pkg_predep) { - out << "Pre-Depends: " << debian_pkg_predep << "\n"; - } - if (debian_pkg_enhances && *debian_pkg_enhances) { - out << "Enhances: " << debian_pkg_enhances << "\n"; - } - if (debian_pkg_breaks && *debian_pkg_breaks) { - out << "Breaks: " << debian_pkg_breaks << "\n"; - } - if (debian_pkg_conflicts && *debian_pkg_conflicts) { - out << "Conflicts: " << debian_pkg_conflicts << "\n"; - } - if (debian_pkg_provides && *debian_pkg_provides) { - out << "Provides: " << debian_pkg_provides << "\n"; - } - if (debian_pkg_replaces && *debian_pkg_replaces) { - out << "Replaces: " << debian_pkg_replaces << "\n"; - } - unsigned long totalSize = 0; - { - std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - dirName += '/'; - for (std::string const& file : packageFiles) { - totalSize += cmSystemTools::FileLength(file); - } - } - out << "Installed-Size: " << (totalSize + 1023) / 1024 << "\n"; - out << "Maintainer: " << maintainer << "\n"; - out << "Description: " << desc << "\n"; - out << std::endl; + if (debian_pkg_replaces && *debian_pkg_replaces) { + controlValues["Replaces"] = debian_pkg_replaces; } + const std::string strGenWDIR(this->GetOption("GEN_WDIR")); const std::string shlibsfilename = strGenWDIR + "/shlibs"; const char* debian_pkg_shlibs = @@ -347,7 +763,7 @@ int cmCPackDebGenerator::createDeb() const bool gen_shibs = this->IsOn("CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS") && debian_pkg_shlibs && *debian_pkg_shlibs; if (gen_shibs) { - cmGeneratedFileStream out(shlibsfilename.c_str()); + cmGeneratedFileStream out(shlibsfilename); out << debian_pkg_shlibs; out << std::endl; } @@ -355,7 +771,7 @@ int cmCPackDebGenerator::createDeb() const std::string postinst = strGenWDIR + "/postinst"; const std::string postrm = strGenWDIR + "/postrm"; if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST")) { - cmGeneratedFileStream out(postinst.c_str()); + cmGeneratedFileStream out(postinst); out << "#!/bin/sh\n\n" "set -e\n\n" "if [ \"$1\" = \"configure\" ]; then\n" @@ -363,7 +779,7 @@ int cmCPackDebGenerator::createDeb() "fi\n"; } if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM")) { - cmGeneratedFileStream out(postrm.c_str()); + cmGeneratedFileStream out(postrm); out << "#!/bin/sh\n\n" "set -e\n\n" "if [ \"$1\" = \"remove\" ]; then\n" @@ -371,314 +787,74 @@ int cmCPackDebGenerator::createDeb() "fi\n"; } - cmArchiveWrite::Compress tar_compression_type = cmArchiveWrite::CompressGZip; - const char* debian_compression_type = - this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"); - if (!debian_compression_type) { - debian_compression_type = "gzip"; - } - - std::string compression_suffix; - if (!strcmp(debian_compression_type, "lzma")) { - compression_suffix = ".lzma"; - tar_compression_type = cmArchiveWrite::CompressLZMA; - } else if (!strcmp(debian_compression_type, "xz")) { - compression_suffix = ".xz"; - tar_compression_type = cmArchiveWrite::CompressXZ; - } else if (!strcmp(debian_compression_type, "bzip2")) { - compression_suffix = ".bz2"; - tar_compression_type = cmArchiveWrite::CompressBZip2; - } else if (!strcmp(debian_compression_type, "gzip")) { - compression_suffix = ".gz"; - tar_compression_type = cmArchiveWrite::CompressGZip; - } else if (!strcmp(debian_compression_type, "none")) { - compression_suffix.clear(); - tar_compression_type = cmArchiveWrite::CompressNone; - } else { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error unrecognized compression type: " - << debian_compression_type << std::endl); - } - - const char* debian_archive_type = - this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"); - if (!debian_archive_type) { - debian_archive_type = "paxr"; + DebGenerator gen( + Logger, this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"), strGenWDIR, + this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), + this->GetOption("CPACK_TEMPORARY_DIRECTORY"), + this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"), + this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"), controlValues, gen_shibs, + shlibsfilename, this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST"), postinst, + this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM"), postrm, + this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA"), + this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"), + packageFiles); + + if (!gen.generate()) { + return 0; } + return 1; +} - std::string filename_data_tar = - strGenWDIR + "/data.tar" + compression_suffix; - - // atomic file generation for data.tar - { - cmGeneratedFileStream fileStream_data_tar; - fileStream_data_tar.Open(filename_data_tar.c_str(), false, true); - if (!fileStream_data_tar) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error opening the file \"" - << filename_data_tar << "\" for writing" << std::endl); - return 0; - } - cmArchiveWrite data_tar(fileStream_data_tar, tar_compression_type, - debian_archive_type); - - // uid/gid should be the one of the root user, and this root user has - // always uid/gid equal to 0. - data_tar.SetUIDAndGID(0u, 0u); - data_tar.SetUNAMEAndGNAME("root", "root"); - - // now add all directories which have to be compressed - // collect all top level install dirs for that - // e.g. /opt/bin/foo, /usr/bin/bar and /usr/bin/baz would - // give /usr and /opt - size_t topLevelLength = strGenWDIR.length(); - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "WDIR: \"" << strGenWDIR << "\", length = " << topLevelLength - << std::endl); - std::set<std::string> orderedFiles; - - // we have to reconstruct the parent folders as well - - for (std::string currentPath : packageFiles) { - while (currentPath != strGenWDIR) { - // the last one IS strGenWDIR, but we do not want this one: - // XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application - // should not add XXX/application - orderedFiles.insert(currentPath); - currentPath = cmSystemTools::CollapseCombinedPath(currentPath, ".."); - } - } - - for (std::string const& file : orderedFiles) { - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "FILEIT: \"" << file << "\"" << std::endl); - std::string::size_type slashPos = file.find('/', topLevelLength + 1); - std::string relativeDir = - file.substr(topLevelLength, slashPos - topLevelLength); - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "RELATIVEDIR: \"" << relativeDir << "\"" << std::endl); - -#ifdef WIN32 - std::string mode_t_adt_filename = file + ":cmake_mode_t"; - cmsys::ifstream permissionStream(mode_t_adt_filename.c_str()); - - mode_t permissions = 0; - - if (permissionStream) { - permissionStream >> std::oct >> permissions; - } - - if (permissions != 0) { - data_tar.SetPermissions(permissions); - } else if (cmSystemTools::FileIsDirectory(file)) { - data_tar.SetPermissions(0755); - } else { - data_tar.ClearPermissions(); - } -#endif - - // do not recurse because the loop will do it - if (!data_tar.Add(file, topLevelLength, ".", false)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem adding file to tar:" - << std::endl - << "#top level directory: " << strGenWDIR << std::endl - << "#file: " << file << std::endl - << "#error:" << data_tar.GetError() << std::endl); - return 0; - } - } - } // scope for file generation +int cmCPackDebGenerator::createDbgsymDDeb() +{ + // Packages containing debug symbols follow the same structure as .debs + // but have different metadata and content. - std::string md5filename = strGenWDIR + "/md5sums"; - { - // the scope is needed for cmGeneratedFileStream - cmGeneratedFileStream out(md5filename.c_str()); - - std::string topLevelWithTrailingSlash = - this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - topLevelWithTrailingSlash += '/'; - for (std::string const& file : packageFiles) { - // hash only regular files - if (cmSystemTools::FileIsDirectory(file) || - cmSystemTools::FileIsSymlink(file)) { - continue; - } + std::map<std::string, std::string> controlValues; + // debian policy enforce lower case for package name + std::string packageNameLower = cmsys::SystemTools::LowerCase( + this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME")); + const char* debian_pkg_version = + this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION"); - std::string output = - cmSystemTools::ComputeFileHash(file, cmCryptoHash::AlgoMD5); - if (output.empty()) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem computing the md5 of " << file << std::endl); - } + controlValues["Package"] = packageNameLower + "-dbgsym"; + controlValues["Package-Type"] = "ddeb"; + controlValues["Version"] = debian_pkg_version; + controlValues["Auto-Built-Package"] = "debug-symbols"; + controlValues["Depends"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME") + + std::string(" (= ") + debian_pkg_version + ")"; + controlValues["Section"] = "debug"; + controlValues["Priority"] = "optional"; + controlValues["Architecture"] = + this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE"); + controlValues["Maintainer"] = + this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER"); + controlValues["Description"] = + std::string("debug symbols for ") + packageNameLower; - output += " " + file + "\n"; - // debian md5sums entries are like this: - // 014f3604694729f3bf19263bac599765 usr/bin/ccmake - // thus strip the full path (with the trailing slash) - cmSystemTools::ReplaceString(output, topLevelWithTrailingSlash.c_str(), - ""); - out << output; - } - // each line contains a eol. - // Do not end the md5sum file with yet another (invalid) + const char* debian_pkg_source = + this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); + if (debian_pkg_source && *debian_pkg_source) { + controlValues["Source"] = debian_pkg_source; } - - std::string filename_control_tar = strGenWDIR + "/control.tar.gz"; - // atomic file generation for control.tar - { - cmGeneratedFileStream fileStream_control_tar; - fileStream_control_tar.Open(filename_control_tar.c_str(), false, true); - if (!fileStream_control_tar) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error opening the file \"" << filename_control_tar - << "\" for writing" - << std::endl); - return 0; - } - cmArchiveWrite control_tar(fileStream_control_tar, - cmArchiveWrite::CompressGZip, - debian_archive_type); - - // sets permissions and uid/gid for the files - control_tar.SetUIDAndGID(0u, 0u); - control_tar.SetUNAMEAndGNAME("root", "root"); - - /* permissions are set according to - https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners - and - https://lintian.debian.org/tags/control-file-has-bad-permissions.html - */ - const mode_t permission644 = 0644; - const mode_t permissionExecute = 0111; - const mode_t permission755 = permission644 | permissionExecute; - - // for md5sum and control (that we have generated here), we use 644 - // (RW-R--R--) - // so that deb lintian doesn't warn about it - control_tar.SetPermissions(permission644); - - // adds control and md5sums - if (!control_tar.Add(md5filename, strGenWDIR.length(), ".") || - !control_tar.Add(strGenWDIR + "/control", strGenWDIR.length(), ".")) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error adding file to tar:" - << std::endl - << "#top level directory: " << strGenWDIR << std::endl - << "#file: \"control\" or \"md5sums\"" << std::endl - << "#error:" << control_tar.GetError() << std::endl); - return 0; - } - - // adds generated shlibs file - if (gen_shibs) { - if (!control_tar.Add(shlibsfilename, strGenWDIR.length(), ".")) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error adding file to tar:" - << std::endl - << "#top level directory: " << strGenWDIR << std::endl - << "#file: \"shlibs\"" << std::endl - << "#error:" << control_tar.GetError() << std::endl); - return 0; - } - } - - // adds LDCONFIG related files - if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST")) { - control_tar.SetPermissions(permission755); - if (!control_tar.Add(postinst, strGenWDIR.length(), ".")) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error adding file to tar:" - << std::endl - << "#top level directory: " << strGenWDIR << std::endl - << "#file: \"postinst\"" << std::endl - << "#error:" << control_tar.GetError() << std::endl); - return 0; - } - control_tar.SetPermissions(permission644); - } - - if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM")) { - control_tar.SetPermissions(permission755); - if (!control_tar.Add(postrm, strGenWDIR.length(), ".")) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error adding file to tar:" - << std::endl - << "#top level directory: " << strGenWDIR << std::endl - << "#file: \"postinst\"" << std::endl - << "#error:" << control_tar.GetError() << std::endl); - return 0; - } - control_tar.SetPermissions(permission644); - } - - // for the other files, we use - // -either the original permission on the files - // -either a permission strictly defined by the Debian policies - const char* controlExtra = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA"); - if (controlExtra) { - // permissions are now controlled by the original file permissions - - const bool permissionStrictPolicy = - this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"); - - static const char* strictFiles[] = { "config", "postinst", "postrm", - "preinst", "prerm" }; - std::set<std::string> setStrictFiles( - strictFiles, - strictFiles + sizeof(strictFiles) / sizeof(strictFiles[0])); - - // default - control_tar.ClearPermissions(); - - std::vector<std::string> controlExtraList; - cmSystemTools::ExpandListArgument(controlExtra, controlExtraList); - for (std::string const& i : controlExtraList) { - std::string filenamename = cmsys::SystemTools::GetFilenameName(i); - std::string localcopy = strGenWDIR + "/" + filenamename; - - if (permissionStrictPolicy) { - control_tar.SetPermissions(setStrictFiles.count(filenamename) - ? permission755 - : permission644); - } - - // if we can copy the file, it means it does exist, let's add it: - if (cmsys::SystemTools::CopyFileIfDifferent(i, localcopy)) { - control_tar.Add(localcopy, strGenWDIR.length(), "."); - } - } - } + const char* debian_build_ids = this->GetOption("GEN_BUILD_IDS"); + if (debian_build_ids && *debian_build_ids) { + controlValues["Build-Ids"] = debian_build_ids; } - // ar -r your-package-name.deb debian-binary control.tar.* data.tar.* - // A debian package .deb is simply an 'ar' archive. The only subtle - // difference is that debian uses the BSD ar style archive whereas most - // Linux distro have a GNU ar. - // See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=161593 for more info - std::string const outputDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - std::string const outputName = this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"); - std::string const outputPath = outputDir + "/" + outputName; - std::string const tlDir = strGenWDIR + "/"; - cmGeneratedFileStream debStream; - debStream.Open(outputPath.c_str(), false, true); - cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd"); + DebGenerator gen( + Logger, this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"), + this->GetOption("GEN_DBGSYMDIR"), - // uid/gid should be the one of the root user, and this root user has - // always uid/gid equal to 0. - deb.SetUIDAndGID(0u, 0u); - deb.SetUNAMEAndGNAME("root", "root"); + this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), + this->GetOption("CPACK_TEMPORARY_DIRECTORY"), + this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"), + this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"), controlValues, false, "", + false, "", false, "", nullptr, + this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"), + packageFiles); - if (!deb.Add(tlDir + "debian-binary", tlDir.length()) || - !deb.Add(tlDir + "control.tar.gz", tlDir.length()) || - !deb.Add(tlDir + "data.tar" + compression_suffix, tlDir.length())) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error creating debian package:" - << std::endl - << "#top level directory: " << outputDir << std::endl - << "#file: " << outputName << std::endl - << "#error:" << deb.GetError() << std::endl); + if (!gen.generate()) { return 0; } return 1; diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h index b4f0c7972..2244fe72e 100644 --- a/Source/CPack/cmCPackDebGenerator.h +++ b/Source/CPack/cmCPackDebGenerator.h @@ -65,6 +65,8 @@ protected: private: int createDeb(); + int createDbgsymDDeb(); + std::vector<std::string> packageFiles; }; diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx new file mode 100644 index 000000000..9f7b236a1 --- /dev/null +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -0,0 +1,322 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCPackExternalGenerator.h" + +#include "cmAlgorithms.h" +#include "cmCPackComponentGroup.h" +#include "cmCPackLog.h" +#include "cmMakefile.h" +#include "cmSystemTools.h" + +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" + +#include "cmsys/FStream.hxx" + +#include <utility> +#include <vector> + +int cmCPackExternalGenerator::InitializeInternal() +{ + this->SetOption("CPACK_EXTERNAL_KNOWN_VERSIONS", "1.0"); + + if (!this->ReadListFile("Internal/CPack/CPackExternal.cmake")) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error while executing CPackExternal.cmake" << std::endl); + return 0; + } + + std::string major = this->GetOption("CPACK_EXTERNAL_SELECTED_MAJOR"); + if (major == "1") { + this->Generator = cm::make_unique<cmCPackExternalVersion1Generator>(this); + } + + return this->Superclass::InitializeInternal(); +} + +int cmCPackExternalGenerator::PackageFiles() +{ + Json::StreamWriterBuilder builder; + builder["indentation"] = " "; + + std::string filename = "package.json"; + if (!this->packageFileNames.empty()) { + filename = this->packageFileNames[0]; + } + + cmsys::ofstream fout(filename.c_str()); + std::unique_ptr<Json::StreamWriter> jout(builder.newStreamWriter()); + + Json::Value root(Json::objectValue); + + if (!this->Generator->WriteToJSON(root)) { + return 0; + } + + if (jout->write(root, &fout)) { + return 0; + } + + const char* packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT"); + if (packageScript && *packageScript) { + if (!cmSystemTools::FileIsFullPath(packageScript)) { + cmCPackLogger( + cmCPackLog::LOG_ERROR, + "CPACK_EXTERNAL_PACKAGE_SCRIPT does not contain a full file path" + << std::endl); + return 0; + } + + int res = this->MakefileMap->ReadListFile(packageScript); + + if (cmSystemTools::GetErrorOccuredFlag() || !res) { + return 0; + } + } + + return 1; +} + +bool cmCPackExternalGenerator::SupportsComponentInstallation() const +{ + return true; +} + +int cmCPackExternalGenerator::InstallProjectViaInstallCommands( + bool setDestDir, const std::string& tempInstallDirectory) +{ + if (this->StagingEnabled()) { + return cmCPackGenerator::InstallProjectViaInstallCommands( + setDestDir, tempInstallDirectory); + } + + return 1; +} + +int cmCPackExternalGenerator::InstallProjectViaInstallScript( + bool setDestDir, const std::string& tempInstallDirectory) +{ + if (this->StagingEnabled()) { + return cmCPackGenerator::InstallProjectViaInstallScript( + setDestDir, tempInstallDirectory); + } + + return 1; +} + +int cmCPackExternalGenerator::InstallProjectViaInstalledDirectories( + bool setDestDir, const std::string& tempInstallDirectory, + const mode_t* default_dir_mode) +{ + if (this->StagingEnabled()) { + return cmCPackGenerator::InstallProjectViaInstalledDirectories( + setDestDir, tempInstallDirectory, default_dir_mode); + } + + return 1; +} + +int cmCPackExternalGenerator::RunPreinstallTarget( + const std::string& installProjectName, const std::string& installDirectory, + cmGlobalGenerator* globalGenerator, const std::string& buildConfig) +{ + if (this->StagingEnabled()) { + return cmCPackGenerator::RunPreinstallTarget( + installProjectName, installDirectory, globalGenerator, buildConfig); + } + + return 1; +} + +int cmCPackExternalGenerator::InstallCMakeProject( + bool setDestDir, const std::string& installDirectory, + const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode, + const std::string& component, bool componentInstall, + const std::string& installSubDirectory, const std::string& buildConfig, + std::string& absoluteDestFiles) +{ + if (this->StagingEnabled()) { + return cmCPackGenerator::InstallCMakeProject( + setDestDir, installDirectory, baseTempInstallDirectory, default_dir_mode, + component, componentInstall, installSubDirectory, buildConfig, + absoluteDestFiles); + } + + return 1; +} + +bool cmCPackExternalGenerator::StagingEnabled() const +{ + return !cmSystemTools::IsOff( + this->GetOption("CPACK_EXTERNAL_ENABLE_STAGING")); +} + +cmCPackExternalGenerator::cmCPackExternalVersionGenerator:: + cmCPackExternalVersionGenerator(cmCPackExternalGenerator* parent) + : Parent(parent) +{ +} + +int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteVersion( + Json::Value& root) +{ + root["formatVersionMajor"] = this->GetVersionMajor(); + root["formatVersionMinor"] = this->GetVersionMinor(); + + return 1; +} + +int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON( + Json::Value& root) +{ + if (!this->WriteVersion(root)) { + return 0; + } + + const char* packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME"); + if (packageName) { + root["packageName"] = packageName; + } + + const char* packageVersion = + this->Parent->GetOption("CPACK_PACKAGE_VERSION"); + if (packageVersion) { + root["packageVersion"] = packageVersion; + } + + const char* packageDescriptionFile = + this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); + if (packageDescriptionFile) { + root["packageDescriptionFile"] = packageDescriptionFile; + } + + const char* packageDescriptionSummary = + this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY"); + if (packageDescriptionSummary) { + root["packageDescriptionSummary"] = packageDescriptionSummary; + } + + const char* buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG"); + if (buildConfigCstr) { + root["buildConfig"] = buildConfigCstr; + } + + const char* defaultDirectoryPermissions = + this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); + if (defaultDirectoryPermissions && *defaultDirectoryPermissions) { + root["defaultDirectoryPermissions"] = defaultDirectoryPermissions; + } + if (cmSystemTools::IsInternallyOn( + this->Parent->GetOption("CPACK_SET_DESTDIR"))) { + root["setDestdir"] = true; + root["packagingInstallPrefix"] = + this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); + } else { + root["setDestdir"] = false; + } + + root["stripFiles"] = + !cmSystemTools::IsOff(this->Parent->GetOption("CPACK_STRIP_FILES")); + root["warnOnAbsoluteInstallDestination"] = + this->Parent->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION"); + root["errorOnAbsoluteInstallDestination"] = + this->Parent->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION"); + + Json::Value& projects = root["projects"] = Json::Value(Json::arrayValue); + for (auto& project : this->Parent->CMakeProjects) { + Json::Value jsonProject(Json::objectValue); + + jsonProject["projectName"] = project.ProjectName; + jsonProject["component"] = project.Component; + jsonProject["directory"] = project.Directory; + jsonProject["subDirectory"] = project.SubDirectory; + + Json::Value& installationTypes = jsonProject["installationTypes"] = + Json::Value(Json::arrayValue); + for (auto& installationType : project.InstallationTypes) { + installationTypes.append(installationType->Name); + } + + Json::Value& components = jsonProject["components"] = + Json::Value(Json::arrayValue); + for (auto& component : project.Components) { + components.append(component->Name); + } + + projects.append(jsonProject); + } + + Json::Value& installationTypes = root["installationTypes"] = + Json::Value(Json::objectValue); + for (auto& installationType : this->Parent->InstallationTypes) { + Json::Value& jsonInstallationType = + installationTypes[installationType.first] = + Json::Value(Json::objectValue); + + jsonInstallationType["name"] = installationType.second.Name; + jsonInstallationType["displayName"] = installationType.second.DisplayName; + jsonInstallationType["index"] = installationType.second.Index; + } + + Json::Value& components = root["components"] = + Json::Value(Json::objectValue); + for (auto& component : this->Parent->Components) { + Json::Value& jsonComponent = components[component.first] = + Json::Value(Json::objectValue); + + jsonComponent["name"] = component.second.Name; + jsonComponent["displayName"] = component.second.DisplayName; + if (component.second.Group) { + jsonComponent["group"] = component.second.Group->Name; + } + jsonComponent["isRequired"] = component.second.IsRequired; + jsonComponent["isHidden"] = component.second.IsHidden; + jsonComponent["isDisabledByDefault"] = + component.second.IsDisabledByDefault; + jsonComponent["isDownloaded"] = component.second.IsDownloaded; + jsonComponent["description"] = component.second.Description; + jsonComponent["archiveFile"] = component.second.ArchiveFile; + + Json::Value& cmpInstallationTypes = jsonComponent["installationTypes"] = + Json::Value(Json::arrayValue); + for (auto& installationType : component.second.InstallationTypes) { + cmpInstallationTypes.append(installationType->Name); + } + + Json::Value& dependencies = jsonComponent["dependencies"] = + Json::Value(Json::arrayValue); + for (auto& dep : component.second.Dependencies) { + dependencies.append(dep->Name); + } + } + + Json::Value& groups = root["componentGroups"] = + Json::Value(Json::objectValue); + for (auto& group : this->Parent->ComponentGroups) { + Json::Value& jsonGroup = groups[group.first] = + Json::Value(Json::objectValue); + + jsonGroup["name"] = group.second.Name; + jsonGroup["displayName"] = group.second.DisplayName; + jsonGroup["description"] = group.second.Description; + jsonGroup["isBold"] = group.second.IsBold; + jsonGroup["isExpandedByDefault"] = group.second.IsExpandedByDefault; + if (group.second.ParentGroup) { + jsonGroup["parentGroup"] = group.second.ParentGroup->Name; + } + + Json::Value& subgroups = jsonGroup["subgroups"] = + Json::Value(Json::arrayValue); + for (auto& subgroup : group.second.Subgroups) { + subgroups.append(subgroup->Name); + } + + Json::Value& groupComponents = jsonGroup["components"] = + Json::Value(Json::arrayValue); + for (auto& component : group.second.Components) { + groupComponents.append(component->Name); + } + } + + return 1; +} diff --git a/Source/CPack/cmCPackExternalGenerator.h b/Source/CPack/cmCPackExternalGenerator.h new file mode 100644 index 000000000..176d6a9d9 --- /dev/null +++ b/Source/CPack/cmCPackExternalGenerator.h @@ -0,0 +1,89 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCPackExternalGenerator_h +#define cmCPackExternalGenerator_h + +#include "cmCPackGenerator.h" +#include "cm_sys_stat.h" + +#include <memory> +#include <string> + +class cmGlobalGenerator; +namespace Json { +class Value; +} + +/** \class cmCPackExternalGenerator + * \brief A generator for CPack External packaging tools + */ +class cmCPackExternalGenerator : public cmCPackGenerator +{ +public: + cmCPackTypeMacro(cmCPackExternalGenerator, cmCPackGenerator); + + const char* GetOutputExtension() override { return ".json"; } + +protected: + int InitializeInternal() override; + + int PackageFiles() override; + + bool SupportsComponentInstallation() const override; + + int InstallProjectViaInstallCommands( + bool setDestDir, const std::string& tempInstallDirectory) override; + int InstallProjectViaInstallScript( + bool setDestDir, const std::string& tempInstallDirectory) override; + int InstallProjectViaInstalledDirectories( + bool setDestDir, const std::string& tempInstallDirectory, + const mode_t* default_dir_mode) override; + + int RunPreinstallTarget(const std::string& installProjectName, + const std::string& installDirectory, + cmGlobalGenerator* globalGenerator, + const std::string& buildConfig) override; + int InstallCMakeProject(bool setDestDir, const std::string& installDirectory, + const std::string& baseTempInstallDirectory, + const mode_t* default_dir_mode, + const std::string& component, bool componentInstall, + const std::string& installSubDirectory, + const std::string& buildConfig, + std::string& absoluteDestFiles) override; + +private: + bool StagingEnabled() const; + + class cmCPackExternalVersionGenerator + { + public: + cmCPackExternalVersionGenerator(cmCPackExternalGenerator* parent); + + virtual ~cmCPackExternalVersionGenerator() = default; + + virtual int WriteToJSON(Json::Value& root); + + protected: + virtual int GetVersionMajor() = 0; + virtual int GetVersionMinor() = 0; + + int WriteVersion(Json::Value& root); + + cmCPackExternalGenerator* Parent; + }; + + class cmCPackExternalVersion1Generator + : public cmCPackExternalVersionGenerator + { + public: + using cmCPackExternalVersionGenerator::cmCPackExternalVersionGenerator; + + protected: + int GetVersionMajor() override { return 1; } + int GetVersionMinor() override { return 0; } + }; + + std::unique_ptr<cmCPackExternalVersionGenerator> Generator; +}; + +#endif diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index 91ae1a23f..14334149e 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -298,7 +298,7 @@ static bool has_suffix(const std::string& str, const std::string& suffix) int cmCPackFreeBSDGenerator::PackageFiles() { - if (!this->ReadListFile("CPackFreeBSD.cmake")) { + if (!this->ReadListFile("Internal/CPack/CPackFreeBSD.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackFreeBSD.cmake" << std::endl); return 0; diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index f15445b1a..acd665095 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -288,7 +288,7 @@ int cmCPackGenerator::InstallProjectViaInstallCommands( if (!resB || retVal) { std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); tmpFile += "/InstallOutput.log"; - cmGeneratedFileStream ofs(tmpFile.c_str()); + cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << ic << std::endl << "# Output:" << std::endl << output << std::endl; @@ -360,8 +360,6 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( return 0; } files = gl.GetFiles(); - std::vector<std::string>::iterator gfit; - std::vector<cmsys::RegularExpression>::iterator regIt; for (std::string const& gf : files) { bool skip = false; std::string inFile = gf; @@ -369,7 +367,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( inFile += '/'; } for (cmsys::RegularExpression& reg : ignoreFilesRegex) { - if (reg.find(inFile.c_str())) { + if (reg.find(inFile)) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Ignore file: " << inFile << std::endl); skip = true; @@ -545,10 +543,13 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( ++it; std::string installProjectName = *it; ++it; - std::string installComponent = *it; + cmCPackInstallCMakeProject project; + + project.Directory = installDirectory; + project.ProjectName = installProjectName; + project.Component = *it; ++it; - std::string installSubDirectory = *it; - std::string installFile = installDirectory + "/cmake_install.cmake"; + project.SubDirectory = *it; std::vector<std::string> componentsVector; @@ -559,34 +560,36 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( * - the user did not request Monolithic install * (this works at CPack time too) */ - if (this->SupportsComponentInstallation() & + if (this->SupportsComponentInstallation() && !(this->IsOn("CPACK_MONOLITHIC_INSTALL"))) { // Determine the installation types for this project (if provided). std::string installTypesVar = "CPACK_" + - cmSystemTools::UpperCase(installComponent) + "_INSTALL_TYPES"; + cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES"; const char* installTypes = this->GetOption(installTypesVar); if (installTypes && *installTypes) { std::vector<std::string> installTypesVector; cmSystemTools::ExpandListArgument(installTypes, installTypesVector); for (std::string const& installType : installTypesVector) { - this->GetInstallationType(installProjectName, installType); + project.InstallationTypes.push_back( + this->GetInstallationType(project.ProjectName, installType)); } } // Determine the set of components that will be used in this project std::string componentsVar = - "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(installComponent); + "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component); const char* components = this->GetOption(componentsVar); if (components && *components) { cmSystemTools::ExpandListArgument(components, componentsVector); for (std::string const& comp : componentsVector) { - GetComponent(installProjectName, comp); + project.Components.push_back( + this->GetComponent(project.ProjectName, comp)); } componentInstall = true; } } if (componentsVector.empty()) { - componentsVector.push_back(installComponent); + componentsVector.push_back(project.Component); } const char* buildConfigCstr = this->GetOption("CPACK_BUILD_CONFIG"); @@ -606,297 +609,316 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // on windows. cmSystemTools::SetForceUnixPaths(globalGenerator->GetForceUnixPaths()); - // Does this generator require pre-install? - if (const char* preinstall = - globalGenerator->GetPreinstallTargetName()) { - std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand( - preinstall, buildConfig, "", false); - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "- Install command: " << buildCommand << std::endl); - cmCPackLogger(cmCPackLog::LOG_OUTPUT, - "- Run preinstall target for: " << installProjectName - << std::endl); - std::string output; - int retVal = 1; - bool resB = cmSystemTools::RunSingleCommand( - buildCommand.c_str(), &output, &output, &retVal, - installDirectory.c_str(), this->GeneratorVerbose, - cmDuration::zero()); - if (!resB || retVal) { - std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - tmpFile += "/PreinstallOutput.log"; - cmGeneratedFileStream ofs(tmpFile.c_str()); - ofs << "# Run command: " << buildCommand << std::endl - << "# Directory: " << installDirectory << std::endl - << "# Output:" << std::endl - << output << std::endl; - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem running install command: " - << buildCommand << std::endl - << "Please check " << tmpFile << " for errors" - << std::endl); - return 0; - } + if (!this->RunPreinstallTarget(project.ProjectName, project.Directory, + globalGenerator, buildConfig)) { + return 0; } + delete globalGenerator; cmCPackLogger(cmCPackLog::LOG_OUTPUT, - "- Install project: " << installProjectName << std::endl); + "- Install project: " << project.ProjectName << std::endl); // Run the installation for each component for (std::string const& component : componentsVector) { - std::string tempInstallDirectory = baseTempInstallDirectory; - installComponent = component; - if (componentInstall) { - cmCPackLogger(cmCPackLog::LOG_OUTPUT, - "- Install component: " << installComponent - << std::endl); + if (!this->InstallCMakeProject( + setDestDir, project.Directory, baseTempInstallDirectory, + default_dir_mode, component, componentInstall, + project.SubDirectory, buildConfig, absoluteDestFiles)) { + return 0; } + } - cmake cm(cmake::RoleScript); - cm.SetHomeDirectory(""); - cm.SetHomeOutputDirectory(""); - cm.GetCurrentSnapshot().SetDefaultDefinitions(); - cm.AddCMakePaths(); - cm.SetProgressCallback(cmCPackGeneratorProgress, this); - cm.SetTrace(this->Trace); - cm.SetTraceExpand(this->TraceExpand); - cmGlobalGenerator gg(&cm); - cmMakefile mf(&gg, cm.GetCurrentSnapshot()); - if (!installSubDirectory.empty() && installSubDirectory != "/" && - installSubDirectory != ".") { - tempInstallDirectory += installSubDirectory; - } - if (componentInstall) { - tempInstallDirectory += "/"; - // Some CPack generators would rather chose - // the local installation directory suffix. - // Some (e.g. RPM) use - // one install directory for each component **GROUP** - // instead of the default - // one install directory for each component. - tempInstallDirectory += - GetComponentInstallDirNameSuffix(installComponent); - if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { - tempInstallDirectory += "/"; - tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME"); - } - } + this->CMakeProjects.push_back(project); + } + } + this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES", + absoluteDestFiles.c_str()); + return 1; +} - const char* default_dir_inst_permissions = - this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); - if (default_dir_inst_permissions && *default_dir_inst_permissions) { - mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS", - default_dir_inst_permissions); - } +int cmCPackGenerator::RunPreinstallTarget( + const std::string& installProjectName, const std::string& installDirectory, + cmGlobalGenerator* globalGenerator, const std::string& buildConfig) +{ + // Does this generator require pre-install? + if (const char* preinstall = globalGenerator->GetPreinstallTargetName()) { + std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand( + preinstall, buildConfig, "", false); + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "- Install command: " << buildCommand << std::endl); + cmCPackLogger(cmCPackLog::LOG_OUTPUT, + "- Run preinstall target for: " << installProjectName + << std::endl); + std::string output; + int retVal = 1; + bool resB = cmSystemTools::RunSingleCommand( + buildCommand.c_str(), &output, &output, &retVal, + installDirectory.c_str(), this->GeneratorVerbose, cmDuration::zero()); + if (!resB || retVal) { + std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + tmpFile += "/PreinstallOutput.log"; + cmGeneratedFileStream ofs(tmpFile); + ofs << "# Run command: " << buildCommand << std::endl + << "# Directory: " << installDirectory << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem running install command: " + << buildCommand << std::endl + << "Please check " << tmpFile << " for errors" + << std::endl); + return 0; + } + } - if (!setDestDir) { - tempInstallDirectory += this->GetPackagingInstallPrefix(); - } + return 1; +} - if (setDestDir) { - // For DESTDIR based packaging, use the *project* - // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The - // value of the project's CMAKE_INSTALL_PREFIX is sent in here as - // the value of the CPACK_INSTALL_PREFIX variable. - // - // If DESTDIR has been 'internally set ON' this means that - // the underlying CPack specific generator did ask for that - // In this case we may override CPACK_INSTALL_PREFIX with - // CPACK_PACKAGING_INSTALL_PREFIX - // I know this is tricky and awkward but it's the price for - // CPACK_SET_DESTDIR backward compatibility. - if (cmSystemTools::IsInternallyOn( - this->GetOption("CPACK_SET_DESTDIR"))) { - this->SetOption("CPACK_INSTALL_PREFIX", - this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX")); - } - std::string dir; - if (this->GetOption("CPACK_INSTALL_PREFIX")) { - dir += this->GetOption("CPACK_INSTALL_PREFIX"); - } - mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir.c_str()); +int cmCPackGenerator::InstallCMakeProject( + bool setDestDir, const std::string& installDirectory, + const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode, + const std::string& component, bool componentInstall, + const std::string& installSubDirectory, const std::string& buildConfig, + std::string& absoluteDestFiles) +{ + std::string tempInstallDirectory = baseTempInstallDirectory; + std::string installFile = installDirectory + "/cmake_install.cmake"; - cmCPackLogger( - cmCPackLog::LOG_DEBUG, - "- Using DESTDIR + CPACK_INSTALL_PREFIX... (mf.AddDefinition)" - << std::endl); - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'" - << std::endl); - - // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory - // exists: - // - if (cmSystemTools::StringStartsWith(dir.c_str(), "/")) { - dir = tempInstallDirectory + dir; - } else { - dir = tempInstallDirectory + "/" + dir; - } - /* - * We must re-set DESTDIR for each component - * We must not add the CPACK_INSTALL_PREFIX part because - * it will be added using the override of CMAKE_INSTALL_PREFIX - * The main reason for this awkward trick is that - * are using DESTDIR for 2 different reasons: - * - Because it was asked by the CPack Generator or the user - * using CPACK_SET_DESTDIR - * - Because it was already used for component install - * in order to put things in subdirs... - */ - cmSystemTools::PutEnv(std::string("DESTDIR=") + - tempInstallDirectory); - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "- Creating directory: '" << dir << "'" << std::endl); + if (componentInstall) { + cmCPackLogger(cmCPackLog::LOG_OUTPUT, + "- Install component: " << component << std::endl); + } - if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) { - cmCPackLogger( - cmCPackLog::LOG_ERROR, - "Problem creating temporary directory: " << dir << std::endl); - return 0; - } - } else { - mf.AddDefinition("CMAKE_INSTALL_PREFIX", - tempInstallDirectory.c_str()); + cmake cm(cmake::RoleScript); + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); + cm.GetCurrentSnapshot().SetDefaultDefinitions(); + cm.AddCMakePaths(); + cm.SetProgressCallback(cmCPackGeneratorProgress, this); + cm.SetTrace(this->Trace); + cm.SetTraceExpand(this->TraceExpand); + cmGlobalGenerator gg(&cm); + cmMakefile mf(&gg, cm.GetCurrentSnapshot()); + if (!installSubDirectory.empty() && installSubDirectory != "/" && + installSubDirectory != ".") { + tempInstallDirectory += installSubDirectory; + } + if (componentInstall) { + tempInstallDirectory += "/"; + // Some CPack generators would rather chose + // the local installation directory suffix. + // Some (e.g. RPM) use + // one install directory for each component **GROUP** + // instead of the default + // one install directory for each component. + tempInstallDirectory += GetComponentInstallDirNameSuffix(component); + if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { + tempInstallDirectory += "/"; + tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME"); + } + } - if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory, - default_dir_mode)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem creating temporary directory: " - << tempInstallDirectory << std::endl); - return 0; - } + const char* default_dir_inst_permissions = + this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); + if (default_dir_inst_permissions && *default_dir_inst_permissions) { + mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS", + default_dir_inst_permissions); + } - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "- Using non-DESTDIR install... (mf.AddDefinition)" - << std::endl); - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "- Setting CMAKE_INSTALL_PREFIX to '" - << tempInstallDirectory << "'" << std::endl); - } + if (!setDestDir) { + tempInstallDirectory += this->GetPackagingInstallPrefix(); + } - if (!buildConfig.empty()) { - mf.AddDefinition("BUILD_TYPE", buildConfig.c_str()); - } - std::string installComponentLowerCase = - cmSystemTools::LowerCase(installComponent); - if (installComponentLowerCase != "all") { - mf.AddDefinition("CMAKE_INSTALL_COMPONENT", - installComponent.c_str()); - } + if (setDestDir) { + // For DESTDIR based packaging, use the *project* + // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The + // value of the project's CMAKE_INSTALL_PREFIX is sent in here as + // the value of the CPACK_INSTALL_PREFIX variable. + // + // If DESTDIR has been 'internally set ON' this means that + // the underlying CPack specific generator did ask for that + // In this case we may override CPACK_INSTALL_PREFIX with + // CPACK_PACKAGING_INSTALL_PREFIX + // I know this is tricky and awkward but it's the price for + // CPACK_SET_DESTDIR backward compatibility. + if (cmSystemTools::IsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"))) { + this->SetOption("CPACK_INSTALL_PREFIX", + this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX")); + } + std::string dir; + if (this->GetOption("CPACK_INSTALL_PREFIX")) { + dir += this->GetOption("CPACK_INSTALL_PREFIX"); + } + mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir.c_str()); - // strip on TRUE, ON, 1, one or several file names, but not on - // FALSE, OFF, 0 and an empty string - if (!cmSystemTools::IsOff(this->GetOption("CPACK_STRIP_FILES"))) { - mf.AddDefinition("CMAKE_INSTALL_DO_STRIP", "1"); - } - // Remember the list of files before installation - // of the current component (if we are in component install) - std::string const& InstallPrefix = tempInstallDirectory; - std::vector<std::string> filesBefore; - std::string findExpr = tempInstallDirectory; - if (componentInstall) { - cmsys::Glob glB; - findExpr += "/*"; - glB.RecurseOn(); - glB.SetRecurseListDirs(true); - glB.FindFiles(findExpr); - filesBefore = glB.GetFiles(); - std::sort(filesBefore.begin(), filesBefore.end()); - } + cmCPackLogger( + cmCPackLog::LOG_DEBUG, + "- Using DESTDIR + CPACK_INSTALL_PREFIX... (mf.AddDefinition)" + << std::endl); + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'" + << std::endl); + + // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory + // exists: + // + if (cmSystemTools::StringStartsWith(dir.c_str(), "/")) { + dir = tempInstallDirectory + dir; + } else { + dir = tempInstallDirectory + "/" + dir; + } + /* + * We must re-set DESTDIR for each component + * We must not add the CPACK_INSTALL_PREFIX part because + * it will be added using the override of CMAKE_INSTALL_PREFIX + * The main reason for this awkward trick is that + * are using DESTDIR for 2 different reasons: + * - Because it was asked by the CPack Generator or the user + * using CPACK_SET_DESTDIR + * - Because it was already used for component install + * in order to put things in subdirs... + */ + cmSystemTools::PutEnv(std::string("DESTDIR=") + tempInstallDirectory); + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "- Creating directory: '" << dir << "'" << std::endl); - // If CPack was asked to warn on ABSOLUTE INSTALL DESTINATION - // then forward request to cmake_install.cmake script - if (this->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")) { - mf.AddDefinition("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", "1"); - } - // If current CPack generator does support - // ABSOLUTE INSTALL DESTINATION or CPack has been asked for - // then ask cmake_install.cmake script to error out - // as soon as it occurs (before installing file) - if (!SupportsAbsoluteDestination() || - this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) { - mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1"); - } - // do installation - int res = mf.ReadListFile(installFile.c_str()); - // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES - // to CPack (may be used by generators like CPack RPM or DEB) - // in order to transparently handle ABSOLUTE PATH - if (mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) { - mf.AddDefinition( - "CPACK_ABSOLUTE_DESTINATION_FILES", - mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")); - } + if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem creating temporary directory: " << dir + << std::endl); + return 0; + } + } else { + mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str()); - // Now rebuild the list of files after installation - // of the current component (if we are in component install) - if (componentInstall) { - cmsys::Glob glA; - glA.RecurseOn(); - glA.SetRecurseListDirs(true); - glA.SetRecurseThroughSymlinks(false); - glA.FindFiles(findExpr); - std::vector<std::string> filesAfter = glA.GetFiles(); - std::sort(filesAfter.begin(), filesAfter.end()); - std::vector<std::string>::iterator diff; - std::vector<std::string> result(filesAfter.size()); - diff = std::set_difference(filesAfter.begin(), filesAfter.end(), - filesBefore.begin(), filesBefore.end(), - result.begin()); - - std::vector<std::string>::iterator fit; - std::string localFileName; - // Populate the File field of each component - for (fit = result.begin(); fit != diff; ++fit) { - localFileName = cmSystemTools::RelativePath(InstallPrefix, *fit); - localFileName = - localFileName.substr(localFileName.find_first_not_of('/')); - Components[installComponent].Files.push_back(localFileName); - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "Adding file <" - << localFileName << "> to component <" - << installComponent << ">" << std::endl); - } - } + if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory, + default_dir_mode)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem creating temporary directory: " + << tempInstallDirectory << std::endl); + return 0; + } - if (nullptr != mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) { - if (!absoluteDestFiles.empty()) { - absoluteDestFiles += ";"; - } - absoluteDestFiles += - mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"); - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "Got some ABSOLUTE DESTINATION FILES: " - << absoluteDestFiles << std::endl); - // define component specific var - if (componentInstall) { - std::string absoluteDestFileComponent = - std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + "_" + - GetComponentInstallDirNameSuffix(installComponent); - if (nullptr != this->GetOption(absoluteDestFileComponent)) { - std::string absoluteDestFilesListComponent = - this->GetOption(absoluteDestFileComponent); - absoluteDestFilesListComponent += ";"; - absoluteDestFilesListComponent += - mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"); - this->SetOption(absoluteDestFileComponent, - absoluteDestFilesListComponent.c_str()); - } else { - this->SetOption( - absoluteDestFileComponent, - mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")); - } - } - } - if (cmSystemTools::GetErrorOccuredFlag() || !res) { - return 0; - } + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "- Using non-DESTDIR install... (mf.AddDefinition)" + << std::endl); + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "- Setting CMAKE_INSTALL_PREFIX to '" << tempInstallDirectory + << "'" << std::endl); + } + + if (!buildConfig.empty()) { + mf.AddDefinition("BUILD_TYPE", buildConfig.c_str()); + } + std::string installComponentLowerCase = cmSystemTools::LowerCase(component); + if (installComponentLowerCase != "all") { + mf.AddDefinition("CMAKE_INSTALL_COMPONENT", component.c_str()); + } + + // strip on TRUE, ON, 1, one or several file names, but not on + // FALSE, OFF, 0 and an empty string + if (!cmSystemTools::IsOff(this->GetOption("CPACK_STRIP_FILES"))) { + mf.AddDefinition("CMAKE_INSTALL_DO_STRIP", "1"); + } + // Remember the list of files before installation + // of the current component (if we are in component install) + std::string const& InstallPrefix = tempInstallDirectory; + std::vector<std::string> filesBefore; + std::string findExpr = tempInstallDirectory; + if (componentInstall) { + cmsys::Glob glB; + findExpr += "/*"; + glB.RecurseOn(); + glB.SetRecurseListDirs(true); + glB.FindFiles(findExpr); + filesBefore = glB.GetFiles(); + std::sort(filesBefore.begin(), filesBefore.end()); + } + + // If CPack was asked to warn on ABSOLUTE INSTALL DESTINATION + // then forward request to cmake_install.cmake script + if (this->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")) { + mf.AddDefinition("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", "1"); + } + // If current CPack generator does support + // ABSOLUTE INSTALL DESTINATION or CPack has been asked for + // then ask cmake_install.cmake script to error out + // as soon as it occurs (before installing file) + if (!SupportsAbsoluteDestination() || + this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) { + mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1"); + } + // do installation + int res = mf.ReadListFile(installFile.c_str()); + // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES + // to CPack (may be used by generators like CPack RPM or DEB) + // in order to transparently handle ABSOLUTE PATH + if (mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) { + mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES", + mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")); + } + + // Now rebuild the list of files after installation + // of the current component (if we are in component install) + if (componentInstall) { + cmsys::Glob glA; + glA.RecurseOn(); + glA.SetRecurseListDirs(true); + glA.SetRecurseThroughSymlinks(false); + glA.FindFiles(findExpr); + std::vector<std::string> filesAfter = glA.GetFiles(); + std::sort(filesAfter.begin(), filesAfter.end()); + std::vector<std::string>::iterator diff; + std::vector<std::string> result(filesAfter.size()); + diff = std::set_difference(filesAfter.begin(), filesAfter.end(), + filesBefore.begin(), filesBefore.end(), + result.begin()); + + std::vector<std::string>::iterator fit; + std::string localFileName; + // Populate the File field of each component + for (fit = result.begin(); fit != diff; ++fit) { + localFileName = cmSystemTools::RelativePath(InstallPrefix, *fit); + localFileName = + localFileName.substr(localFileName.find_first_not_of('/')); + Components[component].Files.push_back(localFileName); + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "Adding file <" << localFileName << "> to component <" + << component << ">" << std::endl); + } + } + + if (nullptr != mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) { + if (!absoluteDestFiles.empty()) { + absoluteDestFiles += ";"; + } + absoluteDestFiles += mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"); + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "Got some ABSOLUTE DESTINATION FILES: " << absoluteDestFiles + << std::endl); + // define component specific var + if (componentInstall) { + std::string absoluteDestFileComponent = + std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + "_" + + GetComponentInstallDirNameSuffix(component); + if (nullptr != this->GetOption(absoluteDestFileComponent)) { + std::string absoluteDestFilesListComponent = + this->GetOption(absoluteDestFileComponent); + absoluteDestFilesListComponent += ";"; + absoluteDestFilesListComponent += + mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"); + this->SetOption(absoluteDestFileComponent, + absoluteDestFilesListComponent.c_str()); + } else { + this->SetOption(absoluteDestFileComponent, + mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")); } } } - this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES", - absoluteDestFiles.c_str()); + if (cmSystemTools::GetErrorOccuredFlag() || !res) { + return 0; + } return 1; } @@ -1475,7 +1497,6 @@ cmCPackComponent* cmCPackGenerator::GetComponent( if (installTypes && *installTypes) { std::vector<std::string> installTypesVector; cmSystemTools::ExpandListArgument(installTypes, installTypesVector); - std::vector<std::string>::iterator installTypesIt; for (std::string const& installType : installTypesVector) { component->InstallationTypes.push_back( this->GetInstallationType(projectName, installType)); @@ -1487,7 +1508,6 @@ cmCPackComponent* cmCPackGenerator::GetComponent( if (depends && *depends) { std::vector<std::string> dependsVector; cmSystemTools::ExpandListArgument(depends, dependsVector); - std::vector<std::string>::iterator dependIt; for (std::string const& depend : dependsVector) { cmCPackComponent* child = GetComponent(projectName, depend); component->Dependencies.push_back(child); diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index c22f36b3f..4755f942b 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -15,6 +15,7 @@ #include "cm_sys_stat.h" class cmCPackLog; +class cmGlobalGenerator; class cmInstalledFile; class cmMakefile; @@ -185,6 +186,17 @@ protected: bool setDestDir, const std::string& tempInstallDirectory, const mode_t* default_dir_mode); + virtual int RunPreinstallTarget(const std::string& installProjectName, + const std::string& installDirectory, + cmGlobalGenerator* globalGenerator, + const std::string& buildConfig); + virtual int InstallCMakeProject( + bool setDestDir, const std::string& installDirectory, + const std::string& baseTempInstallDirectory, + const mode_t* default_dir_mode, const std::string& component, + bool componentInstall, const std::string& installSubDirectory, + const std::string& buildConfig, std::string& absoluteDestFiles); + /** * The various level of support of * CPACK_SET_DESTDIR used by the generator. @@ -271,6 +283,7 @@ protected: */ std::vector<std::string> files; + std::vector<cmCPackInstallCMakeProject> CMakeProjects; std::map<std::string, cmCPackInstallationType> InstallationTypes; /** * The set of components. @@ -308,7 +321,6 @@ protected: bool Trace; bool TraceExpand; -private: cmMakefile* MakefileMap; }; diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index d47e5ed28..2c5ab4d78 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -12,6 +12,7 @@ # include "cmCPackFreeBSDGenerator.h" #endif #include "cmCPackDebGenerator.h" +#include "cmCPackExternalGenerator.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" #include "cmCPackNSISGenerator.h" @@ -110,6 +111,10 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("NuGet", "NuGet packages", cmCPackNuGetGenerator::CreateGenerator); } + if (cmCPackExternalGenerator::CanGenerate()) { + this->RegisterGenerator("External", "CPack External packages", + cmCPackExternalGenerator::CreateGenerator); + } #ifdef __APPLE__ if (cmCPackDragNDropGenerator::CanGenerate()) { this->RegisterGenerator("DragNDrop", "Mac OSX Drag And Drop", diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index a893a0f72..f75a750fe 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -305,7 +305,7 @@ int cmCPackNSISGenerator::PackageFiles() nsisCmd.c_str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose, cmDuration::zero()); if (!res || retVal) { - cmGeneratedFileStream ofs(tmpFile.c_str()); + cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << nsisCmd << std::endl << "# Output:" << std::endl << output << std::endl; @@ -416,7 +416,7 @@ int cmCPackNSISGenerator::InitializeInternal() const char* topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); std::string tmpFile = topDir ? topDir : "."; tmpFile += "/NSISOutput.log"; - cmGeneratedFileStream ofs(tmpFile.c_str()); + cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << nsisCmd << std::endl << "# Output:" << std::endl << output << std::endl; @@ -703,7 +703,7 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( // Find a ZIP program if (!this->IsSet("ZIP_EXECUTABLE")) { - this->ReadListFile("CPackZIP.cmake"); + this->ReadListFile("Internal/CPack/CPackZIP.cmake"); if (!this->IsSet("ZIP_EXECUTABLE")) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -726,7 +726,7 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( cmSystemTools::IsOn(this->GetOption("CPACK_ZIP_NEED_QUOTES")); unsigned long totalSize = 0; { // the scope is needed for cmGeneratedFileStream - cmGeneratedFileStream out(zipListFileName.c_str()); + cmGeneratedFileStream out(zipListFileName); for (std::string const& file : component->Files) { if (needQuotesInFile) { out << "\""; @@ -754,7 +754,7 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( if (!res || retVal) { std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); tmpFile += "/CompressZip.log"; - cmGeneratedFileStream ofs(tmpFile.c_str()); + cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << cmd << std::endl << "# Output:" << std::endl << output << std::endl; diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx index 2ae8cbac8..76f06992b 100644 --- a/Source/CPack/cmCPackNuGetGenerator.cxx +++ b/Source/CPack/cmCPackNuGetGenerator.cxx @@ -49,7 +49,7 @@ int cmCPackNuGetGenerator::PackageFiles() this->SetOption("CPACK_NUGET_ORDINAL_MONOLITIC", "TRUE"); } - auto retval = this->ReadListFile("CPackNuGet.cmake"); + auto retval = this->ReadListFile("Internal/CPack/CPackNuGet.cmake"); if (retval) { AddGeneratedPackageNames(); } else { diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index 4ca0fa82b..76b32753c 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -144,10 +144,10 @@ bool cmCPackProductBuildGenerator::RunProductBuild(const std::string& command) tmpFile += "/ProductBuildOutput.log"; cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl); - std::string output, error_output; + std::string output; int retVal = 1; bool res = cmSystemTools::RunSingleCommand( - command.c_str(), &output, &error_output, &retVal, nullptr, + command.c_str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose, cmDuration::zero()); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running command" << std::endl); if (!res || retVal) { diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index c38988403..5834829c6 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -89,7 +89,7 @@ int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel, component_path += packageName; this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH", component_path.c_str()); - if (!this->ReadListFile("CPackRPM.cmake")) { + if (!this->ReadListFile("Internal/CPack/CPackRPM.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake" << std::endl); retval = 0; @@ -385,7 +385,7 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne( component_path.c_str()); } - if (this->ReadListFile("CPackRPM.cmake")) { + if (this->ReadListFile("Internal/CPack/CPackRPM.cmake")) { AddGeneratedPackageNames(); } else { cmCPackLogger(cmCPackLog::LOG_ERROR, diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index fccbc9530..668a3871d 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -5,6 +5,7 @@ #include "cmCTest.h" #include "cmCTestTestHandler.h" #include "cmGlobalGenerator.h" +#include "cmMakefile.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" #include "cmake.h" @@ -210,9 +211,14 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) if (this->BuildNoCMake) { // Make the generator available for the Build call below. - cm.SetGlobalGenerator(cm.CreateGlobalGenerator(this->BuildGenerator)); - cm.SetGeneratorPlatform(this->BuildGeneratorPlatform); - cm.SetGeneratorToolset(this->BuildGeneratorToolset); + cmGlobalGenerator* gen = cm.CreateGlobalGenerator(this->BuildGenerator); + cm.SetGlobalGenerator(gen); + if (!this->BuildGeneratorPlatform.empty()) { + cmMakefile mf(gen, cm.GetCurrentSnapshot()); + if (!gen->SetGeneratorPlatform(this->BuildGeneratorPlatform, &mf)) { + return 1; + } + } // Load the cache to make CMAKE_MAKE_PROGRAM available. cm.LoadCache(this->BinaryDir); diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 8527d5497..a8309d94a 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -83,6 +83,7 @@ static const char* cmCTestErrorExceptions[] = { "instantiated from ", "candidates are:", ": warning", + ": WARNING", ": \\(Warning\\)", ": note", "Note:", @@ -326,7 +327,7 @@ int cmCTestBuildHandler::ProcessHandler() std::string const& useLaunchers = this->CTest->GetCTestConfiguration("UseLaunchers"); - this->UseCTestLaunch = cmSystemTools::IsOn(useLaunchers.c_str()); + this->UseCTestLaunch = cmSystemTools::IsOn(useLaunchers); // Create a last build log cmGeneratedFileStream ofs; @@ -589,7 +590,7 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml) for (cmCTestCompileErrorWarningRex& rit : this->ErrorWarningFileLineRegex) { cmsys::RegularExpression* re = &rit.RegularExpression; - if (re->find(cm->Text.c_str())) { + if (re->find(cm->Text)) { cm->SourceFile = re->match(rit.FileIndex); // At this point we need to make this->SourceFile relative to // the source root of the project, so cvs links will work @@ -742,7 +743,7 @@ void cmCTestBuildHandler::LaunchHelper::WriteLauncherConfig() // Give some testing configuration information to the launcher. std::string fname = this->Handler->CTestLaunchDir; fname += "/CTestLaunchConfig.cmake"; - cmGeneratedFileStream fout(fname.c_str()); + cmGeneratedFileStream fout(fname); std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory"); fout << "set(CTEST_SOURCE_DIRECTORY \"" << srcdir << "\")\n"; } @@ -757,7 +758,7 @@ void cmCTestBuildHandler::LaunchHelper::WriteScrapeMatchers( fname += "/Custom"; fname += purpose; fname += ".txt"; - cmGeneratedFileStream fout(fname.c_str()); + cmGeneratedFileStream fout(fname); for (std::string const& m : matchers) { fout << m << "\n"; } diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 43a2baec3..1d9a5f7e0 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -1075,7 +1075,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( if (line.empty()) { // Ignore empty line; probably style 2 - } else if (st1re1.find(line.c_str())) { + } else if (st1re1.find(line)) { if (gcovStyle == 0) { gcovStyle = 1; } @@ -1088,7 +1088,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( actualSourceFile.clear(); sourceFile = st1re1.match(2); - } else if (st1re2.find(line.c_str())) { + } else if (st1re2.find(line)) { if (gcovStyle == 0) { gcovStyle = 1; } @@ -1100,7 +1100,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( } gcovFile = st1re2.match(1); - } else if (st2re1.find(line.c_str())) { + } else if (st2re1.find(line)) { if (gcovStyle == 0) { gcovStyle = 2; } @@ -1113,7 +1113,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( actualSourceFile.clear(); sourceFile = st2re1.match(1); - } else if (st2re2.find(line.c_str())) { + } else if (st2re2.find(line)) { if (gcovStyle == 0) { gcovStyle = 2; } @@ -1123,7 +1123,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( cont->Error++; break; } - } else if (st2re3.find(line.c_str())) { + } else if (st2re3.find(line)) { if (gcovStyle == 0) { gcovStyle = 2; } @@ -1135,7 +1135,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( } gcovFile = st2re3.match(2); - } else if (st2re4.find(line.c_str())) { + } else if (st2re4.find(line)) { if (gcovStyle == 0) { gcovStyle = 2; } @@ -1150,7 +1150,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( "Warning: " << st2re4.match(1) << " had unexpected EOF" << std::endl, this->Quiet); - } else if (st2re5.find(line.c_str())) { + } else if (st2re5.find(line)) { if (gcovStyle == 0) { gcovStyle = 2; } @@ -1165,7 +1165,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( "Warning: Cannot open file: " << st2re5.match(1) << std::endl, this->Quiet); - } else if (st2re6.find(line.c_str())) { + } else if (st2re6.find(line)) { if (gcovStyle == 0) { gcovStyle = 2; } diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index b919c7934..71fcafb58 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -272,7 +272,7 @@ bool cmCTestGIT::UpdateImpl() std::string init_submodules = this->CTest->GetCTestConfiguration("GITInitSubmodules"); - if (cmSystemTools::IsOn(init_submodules.c_str())) { + if (cmSystemTools::IsOn(init_submodules)) { char const* git_submodule_init[] = { git, "submodule", "init", nullptr }; ret = this->RunChild(git_submodule_init, &submodule_out, &submodule_err, top_dir.c_str()); diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 8863dc847..667a8bad3 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -151,9 +151,9 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::CollapseFullPath(this->Values[ct_BUILD]).c_str(), this->Quiet); } else { - const char* bdir = + std::string const& bdir = this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY"); - if (bdir) { + if (!bdir.empty()) { this->CTest->SetCTestConfiguration( "BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(), this->Quiet); diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 0bffde3dc..6cd1c09c6 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -345,7 +345,7 @@ void cmCTestLaunch::WriteXML() logXML += ".xml"; // Use cmGeneratedFileStream to atomically create the report file. - cmGeneratedFileStream fxml(logXML.c_str()); + cmGeneratedFileStream fxml(logXML); cmXMLWriter xml(fxml, 2); cmXMLElement e2(xml, "Failure"); e2.Attribute("type", this->IsError() ? "Error" : "Warning"); @@ -584,7 +584,7 @@ bool cmCTestLaunch::Match(std::string const& line, std::vector<cmsys::RegularExpression>& regexps) { for (cmsys::RegularExpression& r : regexps) { - if (r.find(line.c_str())) { + if (r.find(line)) { return true; } } diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 04d1839ab..9c9532a08 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -1087,7 +1087,7 @@ void cmCTestMemCheckHandler::TestOutputFileNames( g.FindFiles(ofile); if (g.GetFiles().empty()) { std::string log = "Cannot find memory tester output file: " + ofile; - cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl); + cmCTestLog(this->CTest, WARNING, log << std::endl); ofile.clear(); } else { files = g.GetFiles(); @@ -1095,7 +1095,7 @@ void cmCTestMemCheckHandler::TestOutputFileNames( } } else if (!cmSystemTools::FileExists(ofile)) { std::string log = "Cannot find memory tester output file: " + ofile; - cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl); + cmCTestLog(this->CTest, WARNING, log << std::endl); ofile.clear(); } files.push_back(std::move(ofile)); diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 322da23d4..f0260018e 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -14,7 +14,6 @@ #include "cmUVSignalHackRAII.h" // IWYU pragma: keep #include "cmsys/FStream.hxx" -#include "cmsys/String.hxx" #include "cmsys/SystemInformation.hxx" #include <algorithm> @@ -57,7 +56,6 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler() this->RunningCount = 0; this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable(); this->HaveAffinity = this->ProcessorsAvailable.size(); - this->StopTimePassed = false; this->HasCycles = false; this->SerialTestRunning = false; } @@ -131,17 +129,6 @@ void cmCTestMultiProcessHandler::RunTests() bool cmCTestMultiProcessHandler::StartTestProcess(int test) { - std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime(); - if (stop_time != std::chrono::system_clock::time_point() && - stop_time <= std::chrono::system_clock::now()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "The stop time has been passed. " - "Stopping all tests." - << std::endl); - this->StopTimePassed = true; - return false; - } - if (this->HaveAffinity && this->Properties[test]->WantAffinity) { size_t needProcessors = this->GetProcessorsUsed(test); if (needProcessors > this->ProcessorsAvailable.size()) { @@ -191,7 +178,7 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) this->Properties[test]->Directory + " : " + std::strerror(workdir.GetLastResult())); } else { - if (testRun->StartTest(this->Total)) { + if (testRun->StartTest(this->Completed, this->Total)) { return true; } } @@ -200,6 +187,30 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) return false; } +bool cmCTestMultiProcessHandler::CheckStopTimePassed() +{ + if (!this->StopTimePassed) { + std::chrono::system_clock::time_point stop_time = + this->CTest->GetStopTime(); + if (stop_time != std::chrono::system_clock::time_point() && + stop_time <= std::chrono::system_clock::now()) { + this->SetStopTimePassed(); + } + } + return this->StopTimePassed; +} + +void cmCTestMultiProcessHandler::SetStopTimePassed() +{ + if (!this->StopTimePassed) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "The stop time has been passed. " + "Stopping all tests." + << std::endl); + this->StopTimePassed = true; + } +} + void cmCTestMultiProcessHandler::LockResources(int index) { this->LockedResources.insert( @@ -280,6 +291,10 @@ void cmCTestMultiProcessHandler::StartNextTests() return; } + if (this->CheckStopTimePassed()) { + return; + } + size_t numToStart = 0; if (this->RunningCount < this->ParallelLevel) { @@ -359,10 +374,6 @@ void cmCTestMultiProcessHandler::StartNextTests() } if (testLoadOk && processors <= numToStart && this->StartTest(test)) { - if (this->StopTimePassed) { - return; - } - numToStart -= processors; } else if (numToStart == 0) { break; @@ -425,8 +436,11 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, auto properties = runner->GetTestProperties(); bool testResult = runner->EndTest(this->Completed, this->Total, started); + if (runner->TimedOutForStopTime()) { + this->SetStopTimePassed(); + } if (started) { - if (runner->StartAgain()) { + if (!this->StopTimePassed && runner->StartAgain(this->Completed)) { this->Completed--; // remove the completed test because run again return; } @@ -477,7 +491,7 @@ void cmCTestMultiProcessHandler::UpdateCostData() if (line == "---") { break; } - std::vector<cmsys::String> parts = cmSystemTools::SplitString(line, ' '); + std::vector<std::string> parts = cmSystemTools::SplitString(line, ' '); // Format: <name> <previous_runs> <avg_cost> if (parts.size() < 3) { break; @@ -530,7 +544,7 @@ void cmCTestMultiProcessHandler::ReadCostData() break; } - std::vector<cmsys::String> parts = cmSystemTools::SplitString(line, ' '); + std::vector<std::string> parts = cmSystemTools::SplitString(line, ' '); // Probably an older version of the file, will be fixed next run if (parts.size() < 3) { diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 07a5fe78a..3927a8ab2 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -113,6 +113,9 @@ protected: inline size_t GetProcessorsUsed(int index); std::string GetName(int index); + bool CheckStopTimePassed(); + void SetStopTimePassed(); + void LockResources(int index); void UnlockResources(int index); // map from test number to set of depend tests @@ -125,7 +128,7 @@ protected: size_t RunningCount; std::set<size_t> ProcessorsAvailable; size_t HaveAffinity; - bool StopTimePassed; + bool StopTimePassed = false; // list of test properties (indices concurrent to the test map) PropertiesMap Properties; std::map<int, bool> TestRunningMap; diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 927797af0..7f081ef89 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -49,7 +49,7 @@ void cmCTestRunTest::CheckOutput(std::string const& line) // Check for TIMEOUT_AFTER_MATCH property. if (!this->TestProperties->TimeoutRegularExpressions.empty()) { for (auto& reg : this->TestProperties->TimeoutRegularExpressions) { - if (reg.first.find(this->ProcessOutput.c_str())) { + if (reg.first.find(this->ProcessOutput)) { cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex() << ": " @@ -140,6 +140,9 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) bool passed = true; cmProcess::State res = started ? this->TestProcess->GetProcessStatus() : cmProcess::State::Error; + if (res != cmProcess::State::Expired) { + this->TimeoutIsForStopTime = false; + } int retVal = this->TestProcess->GetExitValue(); bool forceFail = false; bool skipped = false; @@ -148,7 +151,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) this->FailedDependencies.empty()) { bool found = false; for (auto& pass : this->TestProperties->RequiredRegularExpressions) { - if (pass.first.find(this->ProcessOutput.c_str())) { + if (pass.first.find(this->ProcessOutput)) { found = true; reason = "Required regular expression found."; break; @@ -168,7 +171,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) if (!this->TestProperties->ErrorRegularExpressions.empty() && this->FailedDependencies.empty()) { for (auto& pass : this->TestProperties->ErrorRegularExpressions) { - if (pass.first.find(this->ProcessOutput.c_str())) { + if (pass.first.find(this->ProcessOutput)) { reason = "Error regular expression found in output."; reason += " Regex=["; reason += pass.second; @@ -178,6 +181,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) } } } + std::ostringstream outputStream; if (res == cmProcess::State::Exited) { bool success = !forceFail && (retVal == 0 || @@ -193,36 +197,36 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) } else if ((success && !this->TestProperties->WillFail) || (!success && this->TestProperties->WillFail)) { this->TestResult.Status = cmCTestTestHandler::COMPLETED; - cmCTestLog(this->CTest, HANDLER_OUTPUT, " Passed "); + outputStream << " Passed "; } else { this->TestResult.Status = cmCTestTestHandler::FAILED; - cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Failed " << reason); + outputStream << "***Failed " << reason; outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure; } } else if (res == cmProcess::State::Expired) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout "); + outputStream << "***Timeout "; this->TestResult.Status = cmCTestTestHandler::TIMEOUT; outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure; } else if (res == cmProcess::State::Exception) { outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure; - cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Exception: "); + outputStream << "***Exception: "; this->TestResult.ExceptionStatus = this->TestProcess->GetExitExceptionString(); switch (this->TestProcess->GetExitException()) { case cmProcess::Exception::Fault: - cmCTestLog(this->CTest, HANDLER_OUTPUT, "SegFault"); + outputStream << "SegFault"; this->TestResult.Status = cmCTestTestHandler::SEGFAULT; break; case cmProcess::Exception::Illegal: - cmCTestLog(this->CTest, HANDLER_OUTPUT, "Illegal"); + outputStream << "Illegal"; this->TestResult.Status = cmCTestTestHandler::ILLEGAL; break; case cmProcess::Exception::Interrupt: - cmCTestLog(this->CTest, HANDLER_OUTPUT, "Interrupt"); + outputStream << "Interrupt"; this->TestResult.Status = cmCTestTestHandler::INTERRUPT; break; case cmProcess::Exception::Numerical: - cmCTestLog(this->CTest, HANDLER_OUTPUT, "Numerical"); + outputStream << "Numerical"; this->TestResult.Status = cmCTestTestHandler::NUMERICAL; break; default: @@ -231,16 +235,41 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT; } } else if ("Disabled" == this->TestResult.CompletionStatus) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run (Disabled) "); + outputStream << "***Not Run (Disabled) "; } else // cmProcess::State::Error { - cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run "); + outputStream << "***Not Run "; } passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED; char buf[1024]; sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime().count()); - cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n"); + outputStream << buf << "\n"; + + if (this->CTest->GetTestProgressOutput()) { + if (!passed) { + // If the test did not pass, reprint test name and error + std::string output = GetTestPrefix(completed, total); + std::string testName = this->TestProperties->Name; + const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth(); + testName.resize(maxTestNameWidth + 4, '.'); + + output += testName; + output += outputStream.str(); + outputStream.str(""); + outputStream.clear(); + outputStream << output; + cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, "\n"); // flush + } + if (completed == total) { + std::string testName = + GetTestPrefix(completed, total) + this->TestProperties->Name + "\n"; + cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, testName); + } + } + if (!this->CTest->GetTestProgressOutput() || !passed) { + cmCTestLog(this->CTest, HANDLER_OUTPUT, outputStream.str()); + } if (outputTestErrorsToConsole) { cmCTestLog(this->CTest, HANDLER_OUTPUT, this->ProcessOutput << std::endl); @@ -328,7 +357,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) return passed || skipped; } -bool cmCTestRunTest::StartAgain() +bool cmCTestRunTest::StartAgain(size_t completed) { if (!this->RunAgain) { return false; @@ -343,7 +372,7 @@ bool cmCTestRunTest::StartAgain() return true; } - this->StartTest(this->TotalNumberOfTests); + this->StartTest(completed, this->TotalNumberOfTests); return true; } @@ -395,12 +424,14 @@ void cmCTestRunTest::StartFailure(std::string const& output) { // Still need to log the Start message so the test summary records our // attempt to start this test - cmCTestLog(this->CTest, HANDLER_OUTPUT, - std::setw(2 * getNumWidth(this->TotalNumberOfTests) + 8) - << "Start " - << std::setw(getNumWidth(this->TestHandler->GetMaxIndex())) - << this->TestProperties->Index << ": " - << this->TestProperties->Name << std::endl); + if (!this->CTest->GetTestProgressOutput()) { + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::setw(2 * getNumWidth(this->TotalNumberOfTests) + 8) + << "Start " + << std::setw(getNumWidth(this->TestHandler->GetMaxIndex())) + << this->TestProperties->Index << ": " + << this->TestProperties->Name << std::endl); + } this->ProcessOutput.clear(); if (!output.empty()) { @@ -422,16 +453,44 @@ void cmCTestRunTest::StartFailure(std::string const& output) this->TestProcess = cm::make_unique<cmProcess>(*this); } +std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const +{ + std::ostringstream outputStream; + outputStream << std::setw(getNumWidth(total)) << completed << "/"; + outputStream << std::setw(getNumWidth(total)) << total << " "; + + if (this->TestHandler->MemCheck) { + outputStream << "MemCheck"; + } else { + outputStream << "Test"; + } + + std::ostringstream indexStr; + indexStr << " #" << this->Index << ":"; + outputStream << std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex())) + << indexStr.str(); + outputStream << " "; + + return outputStream.str(); +} + // Starts the execution of a test. Returns once it has started -bool cmCTestRunTest::StartTest(size_t total) +bool cmCTestRunTest::StartTest(size_t completed, size_t total) { this->TotalNumberOfTests = total; // save for rerun case - cmCTestLog(this->CTest, HANDLER_OUTPUT, - std::setw(2 * getNumWidth(total) + 8) - << "Start " - << std::setw(getNumWidth(this->TestHandler->GetMaxIndex())) - << this->TestProperties->Index << ": " - << this->TestProperties->Name << std::endl); + if (!this->CTest->GetTestProgressOutput()) { + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::setw(2 * getNumWidth(total) + 8) + << "Start " + << std::setw(getNumWidth(this->TestHandler->GetMaxIndex())) + << this->TestProperties->Index << ": " + << this->TestProperties->Name << std::endl); + } else { + std::string testName = + GetTestPrefix(completed, total) + this->TestProperties->Name + "\n"; + cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, testName); + } + this->ProcessOutput.clear(); // Return immediately if test is disabled @@ -537,6 +596,7 @@ bool cmCTestRunTest::StartTest(size_t total) auto timeout = this->TestProperties->Timeout; + this->TimeoutIsForStopTime = false; std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime(); if (stop_time != std::chrono::system_clock::time_point()) { std::chrono::duration<double> stop_timeout = @@ -547,6 +607,7 @@ bool cmCTestRunTest::StartTest(size_t total) } if (timeout == std::chrono::duration<double>::zero() || stop_timeout < timeout) { + this->TimeoutIsForStopTime = true; timeout = stop_timeout; } } @@ -616,10 +677,10 @@ void cmCTestRunTest::DartProcessing() { if (!this->ProcessOutput.empty() && this->ProcessOutput.find("<DartMeasurement") != std::string::npos) { - if (this->TestHandler->DartStuff.find(this->ProcessOutput.c_str())) { + if (this->TestHandler->DartStuff.find(this->ProcessOutput)) { this->TestResult.DartString = this->TestHandler->DartStuff.match(1); // keep searching and replacing until none are left - while (this->TestHandler->DartStuff1.find(this->ProcessOutput.c_str())) { + while (this->TestHandler->DartStuff1.find(this->ProcessOutput)) { // replace the exact match for the string cmSystemTools::ReplaceString( this->ProcessOutput, this->TestHandler->DartStuff1.match(1).c_str(), @@ -684,44 +745,41 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) { - // if this is the last or only run of this test - // then print out completed / total + std::ostringstream outputStream; + + // If this is the last or only run of this test, or progress output is + // requested, then print out completed / total. // Only issue is if a test fails and we are running until fail // then it will never print out the completed / total, same would // got for run until pass. Trick is when this is called we don't // yet know if we are passing or failing. - if (this->NumberOfRunsLeft == 1) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, - std::setw(getNumWidth(total)) << completed << "/"); - cmCTestLog(this->CTest, HANDLER_OUTPUT, - std::setw(getNumWidth(total)) << total << " "); + if (this->NumberOfRunsLeft == 1 || this->CTest->GetTestProgressOutput()) { + outputStream << std::setw(getNumWidth(total)) << completed << "/"; + outputStream << std::setw(getNumWidth(total)) << total << " "; } // if this is one of several runs of a test just print blank space // to keep things neat else { - cmCTestLog(this->CTest, HANDLER_OUTPUT, - std::setw(getNumWidth(total)) << " " - << " "); - cmCTestLog(this->CTest, HANDLER_OUTPUT, - std::setw(getNumWidth(total)) << " " - << " "); + outputStream << std::setw(getNumWidth(total)) << " "; + outputStream << std::setw(getNumWidth(total)) << " "; } if (this->TestHandler->MemCheck) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, "MemCheck"); + outputStream << "MemCheck"; } else { - cmCTestLog(this->CTest, HANDLER_OUTPUT, "Test"); + outputStream << "Test"; } std::ostringstream indexStr; indexStr << " #" << this->Index << ":"; - cmCTestLog(this->CTest, HANDLER_OUTPUT, - std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex())) - << indexStr.str()); - cmCTestLog(this->CTest, HANDLER_OUTPUT, " "); + outputStream << std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex())) + << indexStr.str(); + outputStream << " "; + const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth(); std::string outname = this->TestProperties->Name + " "; outname.resize(maxTestNameWidth + 4, '.'); + outputStream << outname; *this->TestHandler->LogFile << this->TestProperties->Index << "/" << this->TestHandler->TotalNumberOfTests @@ -749,7 +807,10 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) *this->TestHandler->LogFile << this->ProcessOutput << "<end of output>" << std::endl; - cmCTestLog(this->CTest, HANDLER_OUTPUT, outname.c_str()); + if (!this->CTest->GetTestProgressOutput()) { + cmCTestLog(this->CTest, HANDLER_OUTPUT, outputStream.str()); + } + cmCTestLog(this->CTest, DEBUG, "Testing " << this->TestProperties->Name << " ... "); } diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 3b1d674da..10dceca9b 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -64,7 +64,7 @@ public: void CompressOutput(); // launch the test process, return whether it started correctly - bool StartTest(size_t total); + bool StartTest(size_t completed, size_t total); // capture and report the test results bool EndTest(size_t completed, size_t total, bool started); // Called by ctest -N to log the command string @@ -72,7 +72,7 @@ public: void ComputeWeightedCost(); - bool StartAgain(); + bool StartAgain(size_t completed); void StartFailure(std::string const& output); @@ -80,6 +80,8 @@ public: void FinalizeTest(); + bool TimedOutForStopTime() const { return this->TimeoutIsForStopTime; } + private: bool NeedsToRerun(); void DartProcessing(); @@ -91,7 +93,11 @@ private: // Run post processing of the process output for MemCheck void MemCheckPostProcess(); + // Returns "completed/total Test #Index: " + std::string GetTestPrefix(size_t completed, size_t total) const; + cmCTestTestHandler::cmCTestTestProperties* TestProperties; + bool TimeoutIsForStopTime = false; // Pointer back to the "parent"; the handler that invoked this test run cmCTestTestHandler* TestHandler; cmCTest* CTest; @@ -115,14 +121,12 @@ private: inline int getNumWidth(size_t n) { - int numWidth = 1; - if (n >= 10) { - numWidth = 2; - } - if (n >= 100) { - numWidth = 3; + int w = 1; + while (n >= 10) { + n /= 10; + ++w; } - return numWidth; + return w; } #endif diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 333c899be..a87473d33 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -563,7 +563,7 @@ int cmCTestScriptHandler::RunCurrentScript() // now that we have done most of the error checking finally run the // dashboard, we may be asked to repeatedly run this dashboard, such as - // for a continuous, do we ned to run it more than once? + // for a continuous, do we need to run it more than once? if (this->ContinuousDuration >= 0) { this->UpdateElapsedTime(); auto ending_time = @@ -792,7 +792,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard() cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Write CMake output to file: " << cmakeOutputFile << std::endl); - cmGeneratedFileStream fout(cmakeOutputFile.c_str()); + cmGeneratedFileStream fout(cmakeOutputFile); if (fout) { fout << output.c_str(); } else { @@ -856,7 +856,7 @@ bool cmCTestScriptHandler::WriteInitialCache(const char* directory, { std::string cacheFile = directory; cacheFile += "/CMakeCache.txt"; - cmGeneratedFileStream fout(cacheFile.c_str()); + cmGeneratedFileStream fout(cacheFile); if (!fout) { return false; } diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx index 3911540f6..47006c10f 100644 --- a/Source/CTest/cmCTestStartCommand.cxx +++ b/Source/CTest/cmCTestStartCommand.cxx @@ -121,7 +121,7 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, // Log startup actions. std::string startLogFile = binaryDir + "/Testing/Temporary/LastStart.log"; - cmGeneratedFileStream ofs(startLogFile.c_str()); + cmGeneratedFileStream ofs(startLogFile); if (!ofs) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create log file: LastStart.log" << std::endl); diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 4c2b75ee3..ecf309a80 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -392,8 +392,12 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); std::string local_file = file; + bool initialize_cdash_buildid = false; if (!cmSystemTools::FileExists(local_file)) { local_file = localprefix + "/" + file; + // If this file exists within the local Testing directory we assume + // that it will be associated with the current build in CDash. + initialize_cdash_buildid = true; } std::string remote_file = remoteprefix + cmSystemTools::GetFilenameName(file); @@ -425,6 +429,33 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, ((url.find('?') == std::string::npos) ? '?' : '&') + "FileName=" + ofile; + if (initialize_cdash_buildid) { + // Provide extra arguments to CDash so that it can initialize and + // return a buildid. + cmCTestCurl ctest_curl(this->CTest); + upload_as += "&build="; + upload_as += + ctest_curl.Escape(this->CTest->GetCTestConfiguration("BuildName")); + upload_as += "&site="; + upload_as += + ctest_curl.Escape(this->CTest->GetCTestConfiguration("Site")); + upload_as += "&stamp="; + upload_as += ctest_curl.Escape(this->CTest->GetCurrentTag()); + upload_as += "-"; + upload_as += ctest_curl.Escape(this->CTest->GetTestModelString()); + cmCTestScriptHandler* ch = static_cast<cmCTestScriptHandler*>( + this->CTest->GetHandler("script")); + cmake* cm = ch->GetCMake(); + if (cm) { + const char* subproject = + cm->GetState()->GetGlobalProperty("SubProject"); + if (subproject) { + upload_as += "&subproject="; + upload_as += ctest_curl.Escape(subproject); + } + } + } + upload_as += "&MD5="; if (cmSystemTools::IsOn(this->GetOption("InternalTest"))) { @@ -454,6 +485,10 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, // specify target ::curl_easy_setopt(curl, CURLOPT_URL, upload_as.c_str()); + // CURLAUTH_BASIC is default, and here we allow additional methods, + // including more secure ones + ::curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + // now specify which file to upload ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile); diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index d00513439..c936910f8 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -2127,10 +2127,10 @@ bool cmCTestTestHandler::SetTestsProperties( for (cmCTestTestProperties& rt : this->TestList) { if (t == rt.Name) { if (key == "WILL_FAIL") { - rt.WillFail = cmSystemTools::IsOn(val.c_str()); + rt.WillFail = cmSystemTools::IsOn(val); } if (key == "DISABLED") { - rt.Disabled = cmSystemTools::IsOn(val.c_str()); + rt.Disabled = cmSystemTools::IsOn(val); } if (key == "ATTACHED_FILES") { cmSystemTools::ExpandListArgument(val, rt.AttachedFiles); @@ -2173,7 +2173,7 @@ bool cmCTestTestHandler::SetTestsProperties( cmSystemTools::ExpandListArgument(val, rt.RequiredFiles); } if (key == "RUN_SERIAL") { - rt.RunSerial = cmSystemTools::IsOn(val.c_str()); + rt.RunSerial = cmSystemTools::IsOn(val); } if (key == "FAIL_REGULAR_EXPRESSION") { std::vector<std::string> lval; @@ -2189,7 +2189,7 @@ bool cmCTestTestHandler::SetTestsProperties( } } if (key == "PROCESSOR_AFFINITY") { - rt.WantAffinity = cmSystemTools::IsOn(val.c_str()); + rt.WantAffinity = cmSystemTools::IsOn(val); } if (key == "SKIP_RETURN_CODE") { rt.SkipReturnCode = atoi(val.c_str()); @@ -2311,7 +2311,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args) this->Quiet); if (this->UseExcludeRegExpFlag && this->UseExcludeRegExpFirst && - this->ExcludeTestsRegularExpression.find(testname.c_str())) { + this->ExcludeTestsRegularExpression.find(testname)) { return true; } if (this->MemCheck) { @@ -2366,10 +2366,10 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args) test.SkipReturnCode = -1; test.PreviousRuns = 0; if (this->UseIncludeRegExpFlag && - !this->IncludeTestsRegularExpression.find(testname.c_str())) { + !this->IncludeTestsRegularExpression.find(testname)) { test.IsInBasedOnREOptions = false; } else if (this->UseExcludeRegExpFlag && !this->UseExcludeRegExpFirst && - this->ExcludeTestsRegularExpression.find(testname.c_str())) { + this->ExcludeTestsRegularExpression.find(testname)) { test.IsInBasedOnREOptions = false; } this->TestList.push_back(test); diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index a59d671dd..21c888902 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -146,7 +146,7 @@ bool cmCTestVC::Update() // if update version only is on then do not actually update, // just note the current version and finish if (!cmSystemTools::IsOn( - this->CTest->GetCTestConfiguration("UpdateVersionOnly").c_str())) { + this->CTest->GetCTestConfiguration("UpdateVersionOnly"))) { result = this->NoteOldRevision() && result; this->Log << "--- Begin Update ---\n"; result = this->UpdateImpl() && result; diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx index 822363d2d..83dde3f75 100644 --- a/Source/CTest/cmParseGTMCoverage.cxx +++ b/Source/CTest/cmParseGTMCoverage.cxx @@ -160,7 +160,7 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line, { // this method parses lines from the .mcov file // each line has ^COVERAGE(...) in it, and there - // are several varients of coverage lines: + // are several variants of coverage lines: // // ^COVERAGE("DIC11","PR1",0)="2:0:0:0" // ( file , entry, line ) = "number_executed:timing_info" diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 39cea8795..c4cf046cf 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -127,7 +127,8 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) uv_pipe_open(pipe_writer, fds[1]); uv_stdio_container_t stdio[3]; - stdio[0].flags = UV_IGNORE; + stdio[0].flags = UV_INHERIT_FD; + stdio[0].data.fd = 0; stdio[1].flags = UV_INHERIT_STREAM; stdio[1].data.stream = pipe_writer; stdio[2] = stdio[1]; diff --git a/Source/Checks/cm_cxx14_check.cmake b/Source/Checks/cm_cxx14_check.cmake index a78ba35af..38606b9c9 100644 --- a/Source/Checks/cm_cxx14_check.cmake +++ b/Source/Checks/cm_cxx14_check.cmake @@ -1,5 +1,5 @@ set(CMake_CXX14_BROKEN 0) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI") if(NOT CMAKE_CXX14_STANDARD_COMPILE_OPTION) set(CMake_CXX14_WORKS 0) endif() diff --git a/Source/Checks/cm_cxx14_check.cpp b/Source/Checks/cm_cxx14_check.cpp index f5806a9c6..9369ba261 100644 --- a/Source/Checks/cm_cxx14_check.cpp +++ b/Source/Checks/cm_cxx14_check.cpp @@ -1,5 +1,8 @@ #include <cstdio> +#include <memory> + int main() { - return 0; + std::unique_ptr<int> u(new int(0)); + return *u; } diff --git a/Source/Checks/cm_cxx17_check.cmake b/Source/Checks/cm_cxx17_check.cmake index 83d397112..4da2fd7ca 100644 --- a/Source/Checks/cm_cxx17_check.cmake +++ b/Source/Checks/cm_cxx17_check.cmake @@ -1,5 +1,5 @@ set(CMake_CXX17_BROKEN 0) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI") if(NOT CMAKE_CXX17_STANDARD_COMPILE_OPTION) set(CMake_CXX17_WORKS 0) endif() diff --git a/Source/Checks/cm_cxx17_check.cpp b/Source/Checks/cm_cxx17_check.cpp index 2cbf1d5e9..4e8918454 100644 --- a/Source/Checks/cm_cxx17_check.cpp +++ b/Source/Checks/cm_cxx17_check.cpp @@ -1,7 +1,9 @@ #include <cstdio> +#include <memory> #include <unordered_map> int main() { - return 0; + std::unique_ptr<int> u(new int(0)); + return *u; } diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index 9bd1c11b5..a41d051b1 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -43,7 +43,7 @@ void cmCursesLongMessageForm::UpdateStatusBar() getmaxyx(stdscr, y, x); char bar[cmCursesMainForm::MAX_WIDTH]; - size_t size = strlen(this->Title.c_str()); + size_t size = this->Title.size(); if (size >= cmCursesMainForm::MAX_WIDTH) { size = cmCursesMainForm::MAX_WIDTH - 1; } diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 4a379c39d..931797a46 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -709,7 +709,7 @@ void cmCursesMainForm::FixValue(cmStateEnums::CacheEntryType type, cmSystemTools::ConvertToUnixSlashes(out); } if (type == cmStateEnums::BOOL) { - if (cmSystemTools::IsOff(out.c_str())) { + if (cmSystemTools::IsOff(out)) { out = "OFF"; } else { out = "ON"; diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx index aed0826c0..68b9e6c7e 100644 --- a/Source/LexerParser/cmCommandArgumentParser.cxx +++ b/Source/LexerParser/cmCommandArgumentParser.cxx @@ -126,8 +126,11 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4244) /* loss of precision */ # pragma warning (disable: 4702) /* unreachable code */ #endif +#if defined(__GNUC__) && __GNUC__ >= 8 +# pragma GCC diagnostic ignored "-Wconversion" +#endif -#line 131 "cmCommandArgumentParser.cxx" /* yacc.c:339 */ +#line 134 "cmCommandArgumentParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -200,7 +203,7 @@ int cmCommandArgument_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 204 "cmCommandArgumentParser.cxx" /* yacc.c:358 */ +#line 207 "cmCommandArgumentParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -498,9 +501,9 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 96, 96, 102, 105, 110, 113, 118, 121, 126, - 129, 132, 135, 138, 141, 146, 149, 152, 155, 160, - 163, 168, 171, 176, 179 + 0, 99, 99, 105, 108, 113, 116, 121, 124, 129, + 132, 135, 138, 141, 144, 149, 152, 155, 158, 163, + 166, 171, 174, 179, 182 }; #endif @@ -1297,192 +1300,192 @@ yyreduce: switch (yyn) { case 2: -#line 96 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 99 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = 0; yyGetParser->SetResult((yyvsp[0].str)); } -#line 1306 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1309 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 102 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1317 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 108 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1325 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 110 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = 0; } -#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1333 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 116 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1341 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 118 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1349 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 124 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1357 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 126 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1365 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1373 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1381 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1389 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1397 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 144 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1405 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 146 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1413 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1421 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); } -#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1429 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 158 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); } -#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1437 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 160 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1445 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 166 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[-1].str); } -#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1453 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 168 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = 0; } -#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1461 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 174 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1469 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 176 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1477 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 182 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1485 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; -#line 1486 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1489 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1712,7 +1715,7 @@ yyreturn: #endif return yyresult; } -#line 184 "cmCommandArgumentParser.y" /* yacc.c:1906 */ +#line 187 "cmCommandArgumentParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/LexerParser/cmCommandArgumentParser.y b/Source/LexerParser/cmCommandArgumentParser.y index 55a88dffa..0c6aad547 100644 --- a/Source/LexerParser/cmCommandArgumentParser.y +++ b/Source/LexerParser/cmCommandArgumentParser.y @@ -55,6 +55,9 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4244) /* loss of precision */ # pragma warning (disable: 4702) /* unreachable code */ #endif +#if defined(__GNUC__) && __GNUC__ >= 8 +# pragma GCC diagnostic ignored "-Wconversion" +#endif %} /* Generate a reentrant parser object. */ diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx index bc45d45e1..5400a10e7 100644 --- a/Source/LexerParser/cmDependsJavaParser.cxx +++ b/Source/LexerParser/cmDependsJavaParser.cxx @@ -115,8 +115,11 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4102) /* Unused goto label. */ # pragma warning (disable: 4065) /* Switch statement contains default but no case. */ #endif +#if defined(__GNUC__) && __GNUC__ >= 8 +# pragma GCC diagnostic ignored "-Wconversion" +#endif -#line 120 "cmDependsJavaParser.cxx" /* yacc.c:339 */ +#line 123 "cmDependsJavaParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -371,7 +374,7 @@ int cmDependsJava_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 375 "cmDependsJavaParser.cxx" /* yacc.c:358 */ +#line 378 "cmDependsJavaParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -679,42 +682,42 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 179, 179, 188, 196, 204, 212, 220, 228, 237, - 245, 254, 262, 271, 276, 281, 286, 291, 296, 301, - 306, 312, 320, 329, 339, 348, 357, 365, 375, 381, - 388, 395, 401, 408, 417, 427, 437, 446, 454, 463, - 472, 478, 487, 493, 502, 508, 517, 529, 537, 546, - 558, 571, 579, 587, 596, 604, 613, 613, 613, 614, - 615, 615, 615, 615, 615, 615, 616, 619, 629, 638, - 647, 656, 666, 672, 681, 690, 699, 707, 716, 725, - 731, 740, 748, 756, 764, 773, 781, 790, 796, 804, - 813, 821, 830, 839, 848, 856, 865, 873, 881, 890, - 899, 909, 916, 926, 936, 943, 950, 953, 959, 969, - 979, 989, 995, 1005, 1015, 1025, 1034, 1044, 1055, 1065, - 1072, 1082, 1091, 1101, 1110, 1120, 1126, 1136, 1145, 1155, - 1165, 1172, 1181, 1190, 1199, 1208, 1216, 1225, 1234, 1244, - 1254, 1263, 1273, 1283, 1290, 1299, 1309, 1318, 1328, 1337, - 1344, 1354, 1363, 1373, 1382, 1391, 1401, 1411, 1420, 1430, - 1439, 1448, 1457, 1466, 1475, 1485, 1494, 1503, 1512, 1521, - 1531, 1540, 1549, 1558, 1567, 1576, 1585, 1594, 1603, 1612, - 1621, 1630, 1640, 1650, 1661, 1671, 1681, 1690, 1699, 1708, - 1717, 1726, 1735, 1745, 1755, 1765, 1775, 1782, 1789, 1796, - 1806, 1813, 1823, 1833, 1842, 1852, 1861, 1871, 1878, 1885, - 1892, 1900, 1907, 1917, 1924, 1934, 1944, 1951, 1961, 1970, - 1980, 1990, 1999, 2009, 2018, 2028, 2039, 2046, 2053, 2064, - 2074, 2084, 2094, 2103, 2113, 2120, 2130, 2139, 2149, 2156, - 2166, 2175, 2185, 2194, 2200, 2209, 2218, 2227, 2236, 2246, - 2256, 2263, 2273, 2280, 2290, 2299, 2309, 2318, 2327, 2336, - 2346, 2353, 2363, 2372, 2382, 2392, 2398, 2405, 2415, 2425, - 2435, 2446, 2456, 2467, 2477, 2488, 2498, 2508, 2517, 2526, - 2535, 2544, 2554, 2564, 2574, 2583, 2592, 2601, 2610, 2620, - 2630, 2640, 2649, 2658, 2667, 2677, 2686, 2695, 2702, 2711, - 2720, 2729, 2739, 2748, 2757, 2767, 2776, 2785, 2794, 2804, - 2813, 2822, 2831, 2840, 2849, 2859, 2868, 2877, 2887, 2896, - 2906, 2915, 2925, 2934, 2944, 2953, 2963, 2972, 2982, 2991, - 3001, 3010, 3020, 3030, 3040, 3049, 3059, 3068, 3077, 3086, - 3095, 3104, 3113, 3122, 3131, 3140, 3149, 3158, 3168, 3178, - 3188, 3197 + 0, 182, 182, 191, 199, 207, 215, 223, 231, 240, + 248, 257, 265, 274, 279, 284, 289, 294, 299, 304, + 309, 315, 323, 332, 342, 351, 360, 368, 378, 384, + 391, 398, 404, 411, 420, 430, 440, 449, 457, 466, + 475, 481, 490, 496, 505, 511, 520, 532, 540, 549, + 561, 574, 582, 590, 599, 607, 616, 616, 616, 617, + 618, 618, 618, 618, 618, 618, 619, 622, 632, 641, + 650, 659, 669, 675, 684, 693, 702, 710, 719, 728, + 734, 743, 751, 759, 767, 776, 784, 793, 799, 807, + 816, 824, 833, 842, 851, 859, 868, 876, 884, 893, + 902, 912, 919, 929, 939, 946, 953, 956, 962, 972, + 982, 992, 998, 1008, 1018, 1028, 1037, 1047, 1058, 1068, + 1075, 1085, 1094, 1104, 1113, 1123, 1129, 1139, 1148, 1158, + 1168, 1175, 1184, 1193, 1202, 1211, 1219, 1228, 1237, 1247, + 1257, 1266, 1276, 1286, 1293, 1302, 1312, 1321, 1331, 1340, + 1347, 1357, 1366, 1376, 1385, 1394, 1404, 1414, 1423, 1433, + 1442, 1451, 1460, 1469, 1478, 1488, 1497, 1506, 1515, 1524, + 1534, 1543, 1552, 1561, 1570, 1579, 1588, 1597, 1606, 1615, + 1624, 1633, 1643, 1653, 1664, 1674, 1684, 1693, 1702, 1711, + 1720, 1729, 1738, 1748, 1758, 1768, 1778, 1785, 1792, 1799, + 1809, 1816, 1826, 1836, 1845, 1855, 1864, 1874, 1881, 1888, + 1895, 1903, 1910, 1920, 1927, 1937, 1947, 1954, 1964, 1973, + 1983, 1993, 2002, 2012, 2021, 2031, 2042, 2049, 2056, 2067, + 2077, 2087, 2097, 2106, 2116, 2123, 2133, 2142, 2152, 2159, + 2169, 2178, 2188, 2197, 2203, 2212, 2221, 2230, 2239, 2249, + 2259, 2266, 2276, 2283, 2293, 2302, 2312, 2321, 2330, 2339, + 2349, 2356, 2366, 2375, 2385, 2395, 2401, 2408, 2418, 2428, + 2438, 2449, 2459, 2470, 2480, 2491, 2501, 2511, 2520, 2529, + 2538, 2547, 2557, 2567, 2577, 2586, 2595, 2604, 2613, 2623, + 2633, 2643, 2652, 2661, 2670, 2680, 2689, 2698, 2705, 2714, + 2723, 2732, 2742, 2751, 2760, 2770, 2779, 2788, 2797, 2807, + 2816, 2825, 2834, 2843, 2852, 2862, 2871, 2880, 2890, 2899, + 2909, 2918, 2928, 2937, 2947, 2956, 2966, 2975, 2985, 2994, + 3004, 3013, 3023, 3033, 3043, 3052, 3062, 3071, 3080, 3089, + 3098, 3107, 3116, 3125, 3134, 3143, 3152, 3161, 3171, 3181, + 3191, 3200 }; #endif @@ -2282,214 +2285,214 @@ yyreduce: switch (yyn) { case 2: -#line 180 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 183 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2296 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 189 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 192 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2304 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2307 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 197 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 200 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2315 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2318 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 205 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 208 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2326 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 213 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 216 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2337 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2340 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 221 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 224 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2348 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2351 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 229 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 232 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2362 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 238 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 241 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2373 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 246 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 249 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2381 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2384 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 255 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 258 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2392 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2395 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 263 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 266 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2403 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2406 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 272 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 275 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2414 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 277 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 280 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2422 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 282 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 285 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2430 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 287 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 290 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2438 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 292 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 295 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2446 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 297 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 300 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2454 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 302 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 305 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2462 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 307 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 310 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2470 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 313 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 316 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2478 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2481 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 321 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 324 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2489 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2492 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 330 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 333 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpStoreClass((yyvsp[0].str)); @@ -2497,44 +2500,44 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2504 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 340 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 343 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2515 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 25: -#line 349 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 352 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2523 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2526 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 26: -#line 358 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 361 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2534 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2537 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 27: -#line 366 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 369 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpStoreClass((yyvsp[-1].str)); @@ -2542,56 +2545,56 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2546 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2549 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 28: -#line 376 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 379 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 29: -#line 382 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 385 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2564 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2567 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 30: -#line 389 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 392 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2573 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2576 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 31: -#line 396 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 399 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2582 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2585 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 32: -#line 402 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 405 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); (yyval.str) = (yyvsp[0].str); } -#line 2591 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2594 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 33: -#line 409 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 412 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->AddClassFound((yyvsp[-2].str)); @@ -2599,11 +2602,11 @@ yyreduce: yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); (yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine()); } -#line 2603 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2606 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 34: -#line 418 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 421 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2612,11 +2615,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2616 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2619 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 35: -#line 428 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 431 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2625,118 +2628,118 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2632 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 36: -#line 438 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 441 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2640 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2643 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 37: -#line 447 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 450 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2651 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2654 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 38: -#line 455 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 458 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 39: -#line 464 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 467 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2673 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2676 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 40: -#line 472 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 475 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 41: -#line 479 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 482 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2694 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2697 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 42: -#line 487 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 490 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2704 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2707 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 43: -#line 494 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 497 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2715 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2718 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 44: -#line 502 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 505 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2725 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2728 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 45: -#line 509 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 512 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2736 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2739 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 46: -#line 518 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 521 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->SetCurrentPackage((yyvsp[-1].str)); @@ -2746,33 +2749,33 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2750 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2753 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 47: -#line 530 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 533 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2761 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2764 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 48: -#line 538 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 541 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2772 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2775 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 49: -#line 547 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 550 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->AddPackagesImport((yyvsp[-1].str)); @@ -2782,11 +2785,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2786 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2789 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 50: -#line 559 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 562 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); std::string str = (yyvsp[-3].str); @@ -2797,77 +2800,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2801 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2804 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 51: -#line 572 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 575 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2815 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 52: -#line 580 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 583 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2823 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2826 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 53: -#line 588 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 591 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2834 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2837 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 54: -#line 597 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 600 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 55: -#line 605 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 608 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2856 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2859 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 67: -#line 620 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 623 "cmDependsJavaParser.y" /* yacc.c:1646 */ { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 2867 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2870 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 68: -#line 630 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 633 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -2875,11 +2878,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2879 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2882 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 69: -#line 639 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 642 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(2); @@ -2887,11 +2890,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2891 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2894 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 70: -#line 648 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 651 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -2899,11 +2902,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2903 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2906 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 71: -#line 657 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 660 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -2911,226 +2914,226 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2915 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2918 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 72: -#line 666 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 669 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2925 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2928 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 73: -#line 673 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 676 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2936 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2939 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 74: -#line 682 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 685 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 75: -#line 691 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 694 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2958 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2961 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 76: -#line 700 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 703 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2969 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2972 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 77: -#line 708 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 711 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2983 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 78: -#line 717 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 720 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2991 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2994 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 79: -#line 725 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 728 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3001 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3004 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 80: -#line 732 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 735 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3012 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3015 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 81: -#line 741 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 744 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 82: -#line 749 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 752 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3034 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3037 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 83: -#line 757 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 760 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3045 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3048 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 84: -#line 765 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 768 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3056 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3059 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 85: -#line 774 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 777 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3067 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3070 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 86: -#line 782 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 785 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3078 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3081 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 87: -#line 791 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 794 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); } -#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3089 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 88: -#line 797 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 800 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 89: -#line 805 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 808 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3108 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3111 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 90: -#line 814 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 817 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3122 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 91: -#line 822 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 825 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3130 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3133 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 92: -#line 831 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 834 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -3138,77 +3141,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3145 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 93: -#line 840 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 843 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3153 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3156 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 94: -#line 849 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 852 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 95: -#line 857 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 860 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3175 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3178 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 96: -#line 866 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 869 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3186 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3189 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 97: -#line 874 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 877 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3200 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 98: -#line 882 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 885 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3208 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3211 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 99: -#line 891 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 894 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3216,11 +3219,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3220 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3223 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 100: -#line 900 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 903 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3228,22 +3231,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3232 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3235 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 101: -#line 909 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 912 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3246 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 102: -#line 917 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 920 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3251,11 +3254,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3255 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3258 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 103: -#line 927 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 930 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3264,40 +3267,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3268 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3271 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 104: -#line 937 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 940 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); } -#line 3277 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3280 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 105: -#line 943 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 946 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3288 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3291 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 107: -#line 954 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 957 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } -#line 3297 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3300 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 108: -#line 960 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 963 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3305,11 +3308,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3309 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3312 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 109: -#line 970 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 973 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3317,11 +3320,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3321 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3324 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 110: -#line 980 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 983 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3329,20 +3332,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3333 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3336 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 111: -#line 990 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 993 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } -#line 3342 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3345 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 112: -#line 996 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 999 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3350,11 +3353,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3354 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3357 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 113: -#line 1006 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1009 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3362,11 +3365,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3366 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3369 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 114: -#line 1016 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1019 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3374,11 +3377,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3378 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3381 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 115: -#line 1026 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1029 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3386,11 +3389,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3390 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3393 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 116: -#line 1035 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1038 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -3398,11 +3401,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3402 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 117: -#line 1045 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1048 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3411,11 +3414,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3415 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3418 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 118: -#line 1056 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1059 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3423,22 +3426,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3430 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 119: -#line 1065 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1068 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3438 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3441 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 120: -#line 1073 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1076 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3446,11 +3449,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3450 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 121: -#line 1083 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1086 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -3458,11 +3461,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3462 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3465 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 122: -#line 1092 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1095 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -3470,22 +3473,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3477 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 123: -#line 1102 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1105 "cmDependsJavaParser.y" /* yacc.c:1646 */ { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3488 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 124: -#line 1111 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1114 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3493,21 +3496,21 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3500 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 125: -#line 1120 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1123 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3507 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3510 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 126: -#line 1127 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1130 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3515,11 +3518,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3519 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3522 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 127: -#line 1137 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1140 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3527,11 +3530,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3531 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3534 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 128: -#line 1146 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1149 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3539,11 +3542,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3543 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3546 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 129: -#line 1156 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1159 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3551,33 +3554,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 130: -#line 1165 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1168 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 131: -#line 1173 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1176 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3577 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3580 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 132: -#line 1182 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1185 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3585,11 +3588,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3589 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3592 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 133: -#line 1191 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1194 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3597,11 +3600,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3601 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3604 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 134: -#line 1200 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1203 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3609,22 +3612,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3613 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3616 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 135: -#line 1209 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1212 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3624 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3627 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 136: -#line 1217 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1220 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3632,22 +3635,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3636 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3639 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 137: -#line 1226 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1229 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3647 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3650 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 138: -#line 1235 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1238 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3655,11 +3658,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3659 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 139: -#line 1245 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1248 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3667,11 +3670,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3671 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3674 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 140: -#line 1255 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1258 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3679,11 +3682,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 141: -#line 1264 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1267 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3691,11 +3694,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3695 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 142: -#line 1274 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1277 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3703,22 +3706,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3707 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3710 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 143: -#line 1283 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1286 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3718 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3721 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 144: -#line 1291 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1294 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3726,11 +3729,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3730 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3733 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 145: -#line 1300 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1303 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3738,11 +3741,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3742 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3745 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 146: -#line 1310 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1313 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3750,11 +3753,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3754 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3757 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 147: -#line 1319 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1322 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3762,33 +3765,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3766 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3769 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 148: -#line 1329 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1332 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3777 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3780 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 149: -#line 1337 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1340 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3788 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3791 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 150: -#line 1345 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1348 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3796,11 +3799,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3800 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3803 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 151: -#line 1355 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1358 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3808,11 +3811,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3815 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 152: -#line 1364 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1367 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); @@ -3820,11 +3823,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3824 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3827 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 153: -#line 1374 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1377 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3832,11 +3835,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3836 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 154: -#line 1383 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1386 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3844,11 +3847,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3851 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 155: -#line 1392 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1395 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3856,11 +3859,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3860 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3863 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 156: -#line 1402 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1405 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); @@ -3868,11 +3871,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3872 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3875 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 157: -#line 1412 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1415 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(3); @@ -3880,11 +3883,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3887 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 158: -#line 1421 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1424 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); @@ -3892,11 +3895,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3899 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 159: -#line 1431 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1434 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3904,11 +3907,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3911 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 160: -#line 1440 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1443 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3916,11 +3919,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3923 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 161: -#line 1449 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1452 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3928,11 +3931,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3935 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 162: -#line 1458 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1461 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3940,11 +3943,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 163: -#line 1467 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1470 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3952,11 +3955,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3959 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 164: -#line 1476 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1479 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3964,11 +3967,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3968 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3971 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 165: -#line 1486 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1489 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3976,11 +3979,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3983 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 166: -#line 1495 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1498 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3988,11 +3991,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3992 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3995 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 167: -#line 1504 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1507 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4000,11 +4003,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4004 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4007 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 168: -#line 1513 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1516 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4012,11 +4015,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4016 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4019 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 169: -#line 1522 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1525 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4024,11 +4027,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4028 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4031 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 170: -#line 1532 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1535 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4036,11 +4039,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4040 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4043 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 171: -#line 1541 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1544 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4048,11 +4051,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4052 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4055 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 172: -#line 1550 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1553 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4060,11 +4063,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4064 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4067 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 173: -#line 1559 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1562 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4072,11 +4075,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4076 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4079 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 174: -#line 1568 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1571 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4084,11 +4087,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4088 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4091 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 175: -#line 1577 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1580 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4096,11 +4099,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4103 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 176: -#line 1586 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1589 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4108,11 +4111,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4112 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4115 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 177: -#line 1595 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1598 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4120,11 +4123,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4127 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 178: -#line 1604 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1607 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4132,11 +4135,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4139 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 179: -#line 1613 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1616 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4144,11 +4147,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4148 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4151 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 180: -#line 1622 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1625 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4156,11 +4159,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4160 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4163 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 181: -#line 1631 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1634 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4168,11 +4171,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4172 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4175 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 182: -#line 1641 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1644 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4180,11 +4183,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4187 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 183: -#line 1651 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1654 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); @@ -4193,11 +4196,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4200 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 184: -#line 1662 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1665 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4205,11 +4208,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4209 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4212 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 185: -#line 1672 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1675 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4217,11 +4220,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4221 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4224 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 186: -#line 1682 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1685 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4229,11 +4232,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4233 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4236 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 187: -#line 1691 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1694 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4241,11 +4244,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4245 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4248 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 188: -#line 1700 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1703 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4253,11 +4256,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4257 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4260 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 189: -#line 1709 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1712 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4265,11 +4268,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4272 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 190: -#line 1718 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1721 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4277,11 +4280,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4284 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 191: -#line 1727 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1730 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4289,11 +4292,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4296 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 192: -#line 1736 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1739 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4301,11 +4304,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4308 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 193: -#line 1746 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1749 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -4313,11 +4316,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4320 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 194: -#line 1756 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1759 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); jpCheckEmpty(7); @@ -4325,11 +4328,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4332 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 195: -#line 1766 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1769 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); jpCheckEmpty(7); @@ -4337,40 +4340,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4344 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 196: -#line 1776 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1779 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } -#line 4350 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 197: -#line 1783 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1786 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); } -#line 4359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4362 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 198: -#line 1789 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1792 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4373 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 199: -#line 1797 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1800 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4378,22 +4381,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4382 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4385 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 200: -#line 1806 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1809 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4393 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4396 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 201: -#line 1814 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1817 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4401,11 +4404,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4408 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 202: -#line 1824 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1827 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4413,11 +4416,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4417 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4420 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 203: -#line 1834 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1837 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4425,11 +4428,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4429 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4432 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 204: -#line 1843 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1846 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4437,11 +4440,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4441 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4444 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 205: -#line 1853 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1856 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4449,11 +4452,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4456 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 206: -#line 1862 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1865 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4461,58 +4464,58 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4465 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4468 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 207: -#line 1872 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1875 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } -#line 4474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4477 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 208: -#line 1879 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1882 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } -#line 4483 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4486 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 209: -#line 1886 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1889 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); } -#line 4492 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4495 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 210: -#line 1894 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1897 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(9); } -#line 4501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4504 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 211: -#line 1900 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1903 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4515 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 212: -#line 1908 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1911 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4520,22 +4523,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4527 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 213: -#line 1917 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1920 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4535 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4538 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 214: -#line 1925 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1928 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4543,33 +4546,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4547 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4550 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 215: -#line 1936 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1939 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(9); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4561 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 216: -#line 1944 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1947 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4572 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 217: -#line 1952 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1955 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4577,11 +4580,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4581 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4584 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 218: -#line 1962 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1965 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4589,11 +4592,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4593 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4596 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 219: -#line 1971 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1974 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4601,11 +4604,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4605 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4608 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 220: -#line 1981 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1984 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4613,11 +4616,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4617 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4620 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 221: -#line 1991 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1994 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4625,11 +4628,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4632 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 222: -#line 2000 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2003 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4637,11 +4640,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4644 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 223: -#line 2010 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2013 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4649,11 +4652,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4656 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 224: -#line 2019 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2022 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -4661,11 +4664,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4668 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 225: -#line 2029 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2032 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4674,31 +4677,31 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4678 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4681 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 226: -#line 2039 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2042 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4692 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 227: -#line 2047 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2050 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } -#line 4698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4701 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 228: -#line 2054 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2057 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4707,11 +4710,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4711 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4714 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 229: -#line 2065 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2068 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4719,11 +4722,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4723 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4726 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 230: -#line 2075 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2078 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4731,11 +4734,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4735 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4738 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 231: -#line 2085 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2088 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -4743,11 +4746,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4747 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4750 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 232: -#line 2095 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2098 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4755,11 +4758,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4759 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4762 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 233: -#line 2104 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2107 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -4767,22 +4770,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4771 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4774 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 234: -#line 2113 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2116 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4785 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 235: -#line 2121 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2124 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4790,11 +4793,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4797 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 236: -#line 2131 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2134 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4802,11 +4805,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4809 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 237: -#line 2140 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2143 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4814,20 +4817,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4821 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 238: -#line 2150 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2153 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } -#line 4827 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 239: -#line 2157 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2160 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4835,11 +4838,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 240: -#line 2167 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2170 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4847,11 +4850,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4851 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 241: -#line 2176 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2179 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4859,11 +4862,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4863 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 242: -#line 2186 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2189 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4871,20 +4874,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4875 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 243: -#line 2195 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2198 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } -#line 4884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4887 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 244: -#line 2201 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2204 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4892,11 +4895,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4899 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 245: -#line 2210 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2213 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4904,11 +4907,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4911 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 246: -#line 2219 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2222 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4916,11 +4919,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4923 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 247: -#line 2228 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2231 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4928,11 +4931,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4935 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 248: -#line 2237 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2240 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4940,11 +4943,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 249: -#line 2247 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2250 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); jpCheckEmpty(6); @@ -4952,22 +4955,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4959 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 250: -#line 2256 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2259 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4967 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4970 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 251: -#line 2264 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2267 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4975,22 +4978,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4979 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4982 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 252: -#line 2273 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2276 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4990 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4993 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 253: -#line 2281 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2284 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4998,11 +5001,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5002 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5005 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 254: -#line 2291 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2294 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5010,11 +5013,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5014 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5017 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 255: -#line 2300 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2303 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5022,11 +5025,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5029 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 256: -#line 2310 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2313 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5034,11 +5037,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5038 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5041 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 257: -#line 2319 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2322 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5046,11 +5049,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5053 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 258: -#line 2328 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2331 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5058,11 +5061,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5062 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5065 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 259: -#line 2337 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2340 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5070,22 +5073,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5074 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5077 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 260: -#line 2346 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2349 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 5085 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5088 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 261: -#line 2354 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2357 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5093,11 +5096,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 262: -#line 2364 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2367 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5105,11 +5108,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5109 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5112 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 263: -#line 2373 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2376 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5117,11 +5120,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5121 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 264: -#line 2383 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2386 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5129,29 +5132,29 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5133 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 265: -#line 2393 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2396 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); } -#line 5142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5145 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 266: -#line 2399 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2402 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); } -#line 5151 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5154 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 267: -#line 2406 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2409 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5160,11 +5163,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 268: -#line 2416 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2419 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5173,11 +5176,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5177 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 269: -#line 2426 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2429 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5186,11 +5189,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5190 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5193 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 270: -#line 2436 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2439 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5199,11 +5202,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5203 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5206 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 271: -#line 2447 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2450 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5212,11 +5215,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5216 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5219 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 272: -#line 2457 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2460 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-5].str))); @@ -5226,11 +5229,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5230 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5233 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 273: -#line 2468 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2471 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5239,11 +5242,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5246 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 274: -#line 2478 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2481 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5252,11 +5255,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5256 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5259 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 275: -#line 2489 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2492 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5265,11 +5268,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5272 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 276: -#line 2499 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2502 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5277,11 +5280,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5284 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 277: -#line 2509 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2512 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5289,11 +5292,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5296 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 278: -#line 2518 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2521 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5301,11 +5304,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5308 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 279: -#line 2527 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2530 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5313,11 +5316,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5320 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 280: -#line 2536 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2539 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5325,11 +5328,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5332 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 281: -#line 2545 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2548 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5337,11 +5340,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5344 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 282: -#line 2555 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2558 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5349,11 +5352,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5356 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 283: -#line 2565 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2568 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5361,11 +5364,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5365 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5368 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 284: -#line 2575 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2578 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5373,11 +5376,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5377 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5380 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 285: -#line 2584 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2587 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5385,11 +5388,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5389 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5392 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 286: -#line 2593 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2596 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5397,11 +5400,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5401 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5404 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 287: -#line 2602 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2605 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5409,11 +5412,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5413 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5416 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 288: -#line 2611 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2614 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5421,11 +5424,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5425 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5428 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 289: -#line 2621 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2624 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5433,11 +5436,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5437 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5440 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 290: -#line 2631 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2634 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5445,11 +5448,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5449 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5452 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 291: -#line 2641 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2644 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5457,11 +5460,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5461 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5464 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 292: -#line 2650 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2653 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5469,11 +5472,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5473 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5476 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 293: -#line 2659 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2662 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5481,11 +5484,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5488 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 294: -#line 2668 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2671 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5493,11 +5496,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5500 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 295: -#line 2678 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2681 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -5505,11 +5508,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5509 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 296: -#line 2687 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2690 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5517,20 +5520,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5521 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 297: -#line 2696 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2699 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } -#line 5530 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5533 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 298: -#line 2703 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2706 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5538,11 +5541,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5542 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5545 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 299: -#line 2712 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2715 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5550,11 +5553,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5554 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5557 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 300: -#line 2721 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2724 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5562,11 +5565,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 301: -#line 2730 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2733 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5574,11 +5577,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5578 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5581 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 302: -#line 2740 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2743 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5586,11 +5589,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5590 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5593 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 303: -#line 2749 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2752 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5598,11 +5601,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5602 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5605 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 304: -#line 2758 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2761 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5610,11 +5613,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5614 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5617 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 305: -#line 2768 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2771 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5622,11 +5625,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5626 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 306: -#line 2777 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2780 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5634,11 +5637,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5638 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 307: -#line 2786 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2789 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5646,11 +5649,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5650 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 308: -#line 2795 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2798 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5658,11 +5661,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 309: -#line 2805 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2808 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5670,11 +5673,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5674 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5677 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 310: -#line 2814 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2817 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5682,11 +5685,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 311: -#line 2823 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2826 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5694,11 +5697,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5701 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 312: -#line 2832 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2835 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5706,11 +5709,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5710 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5713 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 313: -#line 2841 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2844 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5718,11 +5721,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5722 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5725 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 314: -#line 2850 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2853 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5730,11 +5733,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5734 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5737 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 315: -#line 2860 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2863 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5742,11 +5745,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5746 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5749 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 316: -#line 2869 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2872 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5754,11 +5757,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5758 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5761 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 317: -#line 2878 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2881 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5766,11 +5769,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5770 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5773 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 318: -#line 2888 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2891 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5778,11 +5781,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5785 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 319: -#line 2897 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2900 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5790,11 +5793,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5797 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 320: -#line 2907 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2910 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5802,11 +5805,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5809 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 321: -#line 2916 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2919 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5814,11 +5817,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5821 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 322: -#line 2926 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2929 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5826,11 +5829,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5833 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 323: -#line 2935 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2938 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5838,11 +5841,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 324: -#line 2945 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2948 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5850,11 +5853,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5857 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 325: -#line 2954 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2957 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5862,11 +5865,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5869 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 326: -#line 2964 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2967 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5874,11 +5877,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5881 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 327: -#line 2973 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2976 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5886,11 +5889,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5890 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5893 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 328: -#line 2983 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2986 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5898,11 +5901,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5902 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5905 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 329: -#line 2992 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2995 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -5910,11 +5913,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5914 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5917 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 330: -#line 3002 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3005 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5922,11 +5925,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5926 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5929 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 331: -#line 3011 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3014 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5934,11 +5937,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5938 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5941 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 332: -#line 3021 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3024 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5946,11 +5949,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5953 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 333: -#line 3031 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3034 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5959,11 +5962,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5963 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5966 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 334: -#line 3041 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3044 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5971,11 +5974,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5975 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5978 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 335: -#line 3050 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3053 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5983,11 +5986,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5987 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5990 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 336: -#line 3060 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3063 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5995,11 +5998,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5999 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6002 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 337: -#line 3069 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3072 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6007,11 +6010,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6011 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6014 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 338: -#line 3078 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3081 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6019,11 +6022,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 339: -#line 3087 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3090 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6031,11 +6034,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6035 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6038 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 340: -#line 3096 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3099 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6043,11 +6046,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6047 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 341: -#line 3105 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3108 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6055,11 +6058,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6059 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6062 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 342: -#line 3114 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3117 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6067,11 +6070,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6071 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6074 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 343: -#line 3123 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3126 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6079,11 +6082,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6083 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6086 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 344: -#line 3132 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3135 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6091,11 +6094,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6095 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6098 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 345: -#line 3141 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3144 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6103,11 +6106,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6107 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6110 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 346: -#line 3150 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3153 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6115,11 +6118,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6122 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 347: -#line 3159 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3162 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6127,11 +6130,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6131 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6134 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 348: -#line 3169 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3172 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6139,11 +6142,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6143 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6146 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 349: -#line 3179 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3182 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6151,11 +6154,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6155 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6158 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 350: -#line 3189 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3192 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6163,11 +6166,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6170 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 351: -#line 3198 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3201 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -6176,11 +6179,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6183 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; -#line 6184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6187 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -6410,7 +6413,7 @@ yyreturn: #endif return yyresult; } -#line 3207 "cmDependsJavaParser.y" /* yacc.c:1906 */ +#line 3210 "cmDependsJavaParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/LexerParser/cmDependsJavaParser.y b/Source/LexerParser/cmDependsJavaParser.y index f7eb22818..a4e9c5d17 100644 --- a/Source/LexerParser/cmDependsJavaParser.y +++ b/Source/LexerParser/cmDependsJavaParser.y @@ -44,6 +44,9 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4102) /* Unused goto label. */ # pragma warning (disable: 4065) /* Switch statement contains default but no case. */ #endif +#if defined(__GNUC__) && __GNUC__ >= 8 +# pragma GCC diagnostic ignored "-Wconversion" +#endif %} /* Generate a reentrant parser object. */ diff --git a/Source/LexerParser/cmExprLexer.cxx b/Source/LexerParser/cmExprLexer.cxx index 81a1ec502..cb246873e 100644 --- a/Source/LexerParser/cmExprLexer.cxx +++ b/Source/LexerParser/cmExprLexer.cxx @@ -548,8 +548,8 @@ static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 15 -#define YY_END_OF_BUFFER 16 +#define YY_NUM_RULES 18 +#define YY_END_OF_BUFFER 19 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -557,29 +557,29 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static const flex_int16_t yy_accept[23] = +static const flex_int16_t yy_accept[29] = { 0, - 0, 0, 16, 15, 6, 8, 13, 14, 4, 2, - 3, 5, 1, 15, 15, 9, 7, 10, 1, 11, - 12, 0 + 0, 0, 19, 17, 1, 18, 8, 10, 15, 16, + 6, 4, 5, 7, 2, 2, 17, 17, 11, 9, + 12, 2, 0, 13, 14, 3, 3, 0 } ; static const YY_CHAR yy_ec[256] = { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 4, 5, 1, 6, + 7, 8, 9, 1, 10, 1, 11, 12, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 1, 1, 14, + 1, 15, 1, 1, 16, 16, 16, 16, 16, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 3, 1, 4, - 5, 6, 7, 1, 8, 1, 9, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 1, 1, 11, - 1, 12, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 13, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 17, 1, 1, + 1, 1, 1, 18, 1, 1, 16, 16, 16, 16, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 14, 1, 15, 1, 1, 1, 1, + 16, 16, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, + 1, 1, 1, 19, 1, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -596,40 +596,46 @@ static const YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1 } ; -static const YY_CHAR yy_meta[16] = +static const YY_CHAR yy_meta[21] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 + 1, 2, 2, 1, 1, 3, 4, 1, 1, 1 } ; -static const flex_int16_t yy_base[23] = +static const flex_int16_t yy_base[32] = { 0, - 0, 0, 20, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 9, 7, 5, 21, 21, 21, 6, 21, - 21, 21 + 0, 0, 34, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 16, 9, 18, 11, 35, 35, + 35, 11, 0, 35, 35, 0, 0, 35, 23, 26, + 28 } ; -static const flex_int16_t yy_def[23] = +static const flex_int16_t yy_def[32] = { 0, - 22, 1, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 0 + 28, 1, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 29, 28, 28, 28, 28, 28, + 28, 28, 30, 28, 28, 31, 31, 0, 28, 28, + 28 } ; -static const flex_int16_t yy_nxt[37] = +static const flex_int16_t yy_nxt[56] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 21, 20, 19, 22, - 3, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22 + 14, 15, 16, 17, 18, 4, 4, 19, 20, 21, + 22, 22, 22, 22, 22, 25, 22, 26, 26, 27, + 27, 24, 23, 28, 3, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28 } ; -static const flex_int16_t yy_chk[37] = +static const flex_int16_t yy_chk[56] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 19, 15, 14, 13, 3, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 16, 16, 22, 22, 29, 18, 29, 30, 30, 31, + 31, 17, 15, 3, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28 } ; /* The intent behind this definition is that it'll catch @@ -668,6 +674,8 @@ Modify cmExprLexer.cxx: /* Include the set of tokens from the parser. */ #include "cmExprParserTokens.h" +#include <string> + /*--------------------------------------------------------------------------*/ #define INITIAL 0 @@ -946,13 +954,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 23 ) + if ( yy_current_state >= 29 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 21 ); + while ( yy_base[yy_current_state] != 35 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -978,62 +986,74 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -{ yylvalp->Number = atoi(yytext); return exp_NUMBER; } +{} YY_BREAK case 2: YY_RULE_SETUP -{ return exp_PLUS; } +{ yylvalp->Number = std::stoll(yytext, nullptr, 10); return exp_NUMBER; } YY_BREAK case 3: YY_RULE_SETUP -{ return exp_MINUS; } +{ yylvalp->Number = std::stoll(yytext, nullptr, 16); return exp_NUMBER; } YY_BREAK case 4: YY_RULE_SETUP -{ return exp_TIMES; } +{ return exp_PLUS; } YY_BREAK case 5: YY_RULE_SETUP -{ return exp_DIVIDE; } +{ return exp_MINUS; } YY_BREAK case 6: YY_RULE_SETUP -{ return exp_MOD; } +{ return exp_TIMES; } YY_BREAK case 7: YY_RULE_SETUP -{ return exp_OR; } +{ return exp_DIVIDE; } YY_BREAK case 8: YY_RULE_SETUP -{ return exp_AND; } +{ return exp_MOD; } YY_BREAK case 9: YY_RULE_SETUP -{ return exp_XOR; } +{ return exp_OR; } YY_BREAK case 10: YY_RULE_SETUP -{ return exp_NOT; } +{ return exp_AND; } YY_BREAK case 11: YY_RULE_SETUP -{ return exp_SHIFTLEFT; } +{ return exp_XOR; } YY_BREAK case 12: YY_RULE_SETUP -{ return exp_SHIFTRIGHT; } +{ return exp_NOT; } YY_BREAK case 13: YY_RULE_SETUP -{ return exp_OPENPARENT; } +{ return exp_SHIFTLEFT; } YY_BREAK case 14: YY_RULE_SETUP -{ return exp_CLOSEPARENT; } +{ return exp_SHIFTRIGHT; } YY_BREAK case 15: YY_RULE_SETUP +{ return exp_OPENPARENT; } + YY_BREAK +case 16: +YY_RULE_SETUP +{ return exp_CLOSEPARENT; } + YY_BREAK +case 17: +YY_RULE_SETUP +{ yyextra->UnexpectedChar(yytext[0]); } + YY_BREAK +case 18: +YY_RULE_SETUP ECHO; YY_BREAK case YY_STATE_EOF(INITIAL): @@ -1334,7 +1354,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 23 ) + if ( yy_current_state >= 29 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; @@ -1363,11 +1383,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 23 ) + if ( yy_current_state >= 29 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 22); + yy_is_jam = (yy_current_state == 28); (void)yyg; return yy_is_jam ? 0 : yy_current_state; diff --git a/Source/LexerParser/cmExprLexer.in.l b/Source/LexerParser/cmExprLexer.in.l index e5f177a35..2197c2ae5 100644 --- a/Source/LexerParser/cmExprLexer.in.l +++ b/Source/LexerParser/cmExprLexer.in.l @@ -28,6 +28,8 @@ Modify cmExprLexer.cxx: /* Include the set of tokens from the parser. */ #include "cmExprParserTokens.h" +#include <string> + /*--------------------------------------------------------------------------*/ %} @@ -38,8 +40,10 @@ Modify cmExprLexer.cxx: %pointer %% +[ \t] {} -[0-9][0-9]* { yylvalp->Number = atoi(yytext); return exp_NUMBER; } +[0-9][0-9]* { yylvalp->Number = std::stoll(yytext, nullptr, 10); return exp_NUMBER; } +0[xX][0-9a-fA-F][0-9a-fA-F]* { yylvalp->Number = std::stoll(yytext, nullptr, 16); return exp_NUMBER; } "+" { return exp_PLUS; } "-" { return exp_MINUS; } @@ -54,5 +58,6 @@ Modify cmExprLexer.cxx: ">>" { return exp_SHIFTRIGHT; } "(" { return exp_OPENPARENT; } ")" { return exp_CLOSEPARENT; } +. { yyextra->UnexpectedChar(yytext[0]); } %% diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx index 67664a5f5..73ece2b4f 100644 --- a/Source/LexerParser/cmExprParser.cxx +++ b/Source/LexerParser/cmExprParser.cxx @@ -89,6 +89,7 @@ Modify cmExprParser.cxx: #include <stdlib.h> #include <string.h> +#include <stdexcept> /*-------------------------------------------------------------------------*/ #define YYDEBUG 1 @@ -107,8 +108,11 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4102) /* Unused goto label. */ # pragma warning (disable: 4065) /* Switch statement contains default but no case. */ #endif +#if defined(__GNUC__) && __GNUC__ >= 8 +# pragma GCC diagnostic ignored "-Wconversion" +#endif -#line 112 "cmExprParser.cxx" /* yacc.c:339 */ +#line 116 "cmExprParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -185,7 +189,7 @@ int cmExpr_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 189 "cmExprParser.cxx" /* yacc.c:358 */ +#line 193 "cmExprParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -484,9 +488,9 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 73, 73, 78, 81, 86, 89, 94, 97, 102, - 105, 108, 113, 116, 119, 124, 127, 130, 133, 138, - 141, 144, 149, 152 + 0, 77, 77, 82, 85, 90, 93, 98, 101, 106, + 109, 112, 117, 120, 123, 128, 131, 134, 140, 145, + 148, 151, 156, 159 }; #endif @@ -1281,183 +1285,186 @@ yyreduce: switch (yyn) { case 2: -#line 73 "cmExprParser.y" /* yacc.c:1646 */ +#line 77 "cmExprParser.y" /* yacc.c:1646 */ { cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number)); } -#line 1289 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1293 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 78 "cmExprParser.y" /* yacc.c:1646 */ +#line 82 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1297 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1301 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 81 "cmExprParser.y" /* yacc.c:1646 */ +#line 85 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number); } -#line 1305 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1309 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 86 "cmExprParser.y" /* yacc.c:1646 */ +#line 90 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1313 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1317 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 89 "cmExprParser.y" /* yacc.c:1646 */ +#line 93 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number); } -#line 1321 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1325 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 94 "cmExprParser.y" /* yacc.c:1646 */ +#line 98 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1329 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1333 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 97 "cmExprParser.y" /* yacc.c:1646 */ +#line 101 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number); } -#line 1337 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1341 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 102 "cmExprParser.y" /* yacc.c:1646 */ +#line 106 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1345 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1349 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 105 "cmExprParser.y" /* yacc.c:1646 */ +#line 109 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number); } -#line 1353 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1357 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 108 "cmExprParser.y" /* yacc.c:1646 */ +#line 112 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number); } -#line 1361 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1365 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 113 "cmExprParser.y" /* yacc.c:1646 */ +#line 117 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1369 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1373 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 116 "cmExprParser.y" /* yacc.c:1646 */ +#line 120 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number); } -#line 1377 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1381 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 119 "cmExprParser.y" /* yacc.c:1646 */ +#line 123 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number); } -#line 1385 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1389 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 124 "cmExprParser.y" /* yacc.c:1646 */ +#line 128 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1393 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1397 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 127 "cmExprParser.y" /* yacc.c:1646 */ +#line 131 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number); } -#line 1401 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1405 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 130 "cmExprParser.y" /* yacc.c:1646 */ +#line 134 "cmExprParser.y" /* yacc.c:1646 */ { + if (yyvsp[0].Number == 0) { + throw std::overflow_error("divide by zero"); + } (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number); } -#line 1409 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1416 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 133 "cmExprParser.y" /* yacc.c:1646 */ +#line 140 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number); } -#line 1417 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1424 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 138 "cmExprParser.y" /* yacc.c:1646 */ +#line 145 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1425 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1432 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 141 "cmExprParser.y" /* yacc.c:1646 */ +#line 148 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = + (yyvsp[0].Number); } -#line 1433 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1440 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 144 "cmExprParser.y" /* yacc.c:1646 */ +#line 151 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = - (yyvsp[0].Number); } -#line 1441 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1448 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 149 "cmExprParser.y" /* yacc.c:1646 */ +#line 156 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1449 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1456 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 152 "cmExprParser.y" /* yacc.c:1646 */ +#line 159 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-1].Number); } -#line 1457 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1464 "cmExprParser.cxx" /* yacc.c:1646 */ break; -#line 1461 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1468 "cmExprParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1687,7 +1694,7 @@ yyreturn: #endif return yyresult; } -#line 157 "cmExprParser.y" /* yacc.c:1906 */ +#line 164 "cmExprParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y index d1c3a97a7..213747340 100644 --- a/Source/LexerParser/cmExprParser.y +++ b/Source/LexerParser/cmExprParser.y @@ -18,6 +18,7 @@ Modify cmExprParser.cxx: #include <stdlib.h> #include <string.h> +#include <stdexcept> /*-------------------------------------------------------------------------*/ #define YYDEBUG 1 @@ -36,6 +37,9 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4102) /* Unused goto label. */ # pragma warning (disable: 4065) /* Switch statement contains default but no case. */ #endif +#if defined(__GNUC__) && __GNUC__ >= 8 +# pragma GCC diagnostic ignored "-Wconversion" +#endif %} /* Generate a reentrant parser object. */ @@ -128,6 +132,9 @@ term: $<Number>$ = $<Number>1 * $<Number>3; } | term exp_DIVIDE unary { + if (yyvsp[0].Number == 0) { + throw std::overflow_error("divide by zero"); + } $<Number>$ = $<Number>1 / $<Number>3; } | term exp_MOD unary { diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index 00c8a8afc..015cab9f9 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -127,8 +127,11 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # pragma warning (disable: 4127) /* Conditional expression is constant. */ # pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */ #endif +#if defined(__GNUC__) && __GNUC__ >= 8 +# pragma GCC diagnostic ignored "-Wconversion" +#endif -#line 132 "cmFortranParser.cxx" /* yacc.c:339 */ +#line 135 "cmFortranParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -248,11 +251,11 @@ extern int cmFortran_yydebug; union YYSTYPE { -#line 70 "cmFortranParser.y" /* yacc.c:355 */ +#line 73 "cmFortranParser.y" /* yacc.c:355 */ char* string; -#line 256 "cmFortranParser.cxx" /* yacc.c:355 */ +#line 259 "cmFortranParser.cxx" /* yacc.c:355 */ }; typedef union YYSTYPE YYSTYPE; @@ -268,7 +271,7 @@ int cmFortran_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 272 "cmFortranParser.cxx" /* yacc.c:358 */ +#line 275 "cmFortranParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -569,13 +572,13 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 98, 98, 98, 101, 105, 110, 119, 125, 132, - 137, 141, 146, 154, 159, 164, 169, 174, 179, 184, - 189, 194, 198, 202, 206, 210, 211, 216, 216, 216, - 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, - 222, 222, 223, 223, 224, 224, 225, 225, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243 + 0, 101, 101, 101, 104, 108, 113, 122, 128, 135, + 140, 144, 149, 157, 162, 167, 172, 177, 182, 187, + 192, 197, 201, 205, 209, 213, 214, 219, 219, 219, + 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, + 225, 225, 226, 226, 227, 227, 228, 228, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246 }; #endif @@ -1527,26 +1530,26 @@ yyreduce: switch (yyn) { case 4: -#line 101 "cmFortranParser.y" /* yacc.c:1646 */ +#line 104 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1536 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1539 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 105 "cmFortranParser.y" /* yacc.c:1646 */ +#line 108 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1546 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1549 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 110 "cmFortranParser.y" /* yacc.c:1646 */ +#line 113 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 && @@ -1556,22 +1559,22 @@ yyreduce: } free((yyvsp[-2].string)); } -#line 1560 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1563 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 119 "cmFortranParser.y" /* yacc.c:1646 */ +#line 122 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1571 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1574 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 125 "cmFortranParser.y" /* yacc.c:1646 */ +#line 128 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string)); @@ -1579,40 +1582,40 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1583 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1586 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 132 "cmFortranParser.y" /* yacc.c:1646 */ +#line 135 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1593 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1596 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 137 "cmFortranParser.y" /* yacc.c:1646 */ +#line 140 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1602 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1605 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 141 "cmFortranParser.y" /* yacc.c:1646 */ +#line 144 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1612 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1615 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 146 "cmFortranParser.y" /* yacc.c:1646 */ +#line 149 "cmFortranParser.y" /* yacc.c:1646 */ { if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); @@ -1621,139 +1624,139 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1625 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1628 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 154 "cmFortranParser.y" /* yacc.c:1646 */ +#line 157 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1635 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1638 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 159 "cmFortranParser.y" /* yacc.c:1646 */ +#line 162 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1645 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1648 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 164 "cmFortranParser.y" /* yacc.c:1646 */ +#line 167 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1655 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1658 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 169 "cmFortranParser.y" /* yacc.c:1646 */ +#line 172 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1665 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1668 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 174 "cmFortranParser.y" /* yacc.c:1646 */ +#line 177 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1675 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1678 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 179 "cmFortranParser.y" /* yacc.c:1646 */ +#line 182 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1685 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1688 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 184 "cmFortranParser.y" /* yacc.c:1646 */ +#line 187 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1695 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1698 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 189 "cmFortranParser.y" /* yacc.c:1646 */ +#line 192 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1705 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1708 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 194 "cmFortranParser.y" /* yacc.c:1646 */ +#line 197 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1714 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1717 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 198 "cmFortranParser.y" /* yacc.c:1646 */ +#line 201 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1723 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1726 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 202 "cmFortranParser.y" /* yacc.c:1646 */ +#line 205 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1732 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1735 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 206 "cmFortranParser.y" /* yacc.c:1646 */ +#line 209 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1741 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1744 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 48: -#line 228 "cmFortranParser.y" /* yacc.c:1646 */ +#line 231 "cmFortranParser.y" /* yacc.c:1646 */ { free ((yyvsp[0].string)); } -#line 1747 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1750 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 55: -#line 235 "cmFortranParser.y" /* yacc.c:1646 */ +#line 238 "cmFortranParser.y" /* yacc.c:1646 */ { free ((yyvsp[0].string)); } -#line 1753 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1756 "cmFortranParser.cxx" /* yacc.c:1646 */ break; -#line 1757 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1760 "cmFortranParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1983,6 +1986,6 @@ yyreturn: #endif return yyresult; } -#line 246 "cmFortranParser.y" /* yacc.c:1906 */ +#line 249 "cmFortranParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y index 5e0924872..87f3e0a16 100644 --- a/Source/LexerParser/cmFortranParser.y +++ b/Source/LexerParser/cmFortranParser.y @@ -56,6 +56,9 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # pragma warning (disable: 4127) /* Conditional expression is constant. */ # pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */ #endif +#if defined(__GNUC__) && __GNUC__ >= 8 +# pragma GCC diagnostic ignored "-Wconversion" +#endif %} /* Generate a reentrant parser object. */ diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h index 8d6a5fe5a..29c6d60a9 100644 --- a/Source/LexerParser/cmFortranParserTokens.h +++ b/Source/LexerParser/cmFortranParserTokens.h @@ -130,7 +130,7 @@ extern int cmFortran_yydebug; union YYSTYPE { -#line 70 "cmFortranParser.y" /* yacc.c:1909 */ +#line 73 "cmFortranParser.y" /* yacc.c:1909 */ char* string; diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 2646c9aac..7b980a01f 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -150,7 +150,7 @@ int main(int argc, char** argv) typedef cmsys::CommandLineArguments argT; arg.AddArgument("-B", argT::CONCAT_ARGUMENT, &binaryDirectory, "Binary Directory"); - arg.AddArgument("-H", argT::CONCAT_ARGUMENT, &sourceDirectory, + arg.AddArgument("-S", argT::CONCAT_ARGUMENT, &sourceDirectory, "Source Directory"); // do not complain about unknown options arg.StoreUnusedArguments(true); diff --git a/Source/QtDialog/CMakeSetup.icns b/Source/QtDialog/CMakeSetup.icns Binary files differindex 4a50c0416..e0bf8fdfa 100644 --- a/Source/QtDialog/CMakeSetup.icns +++ b/Source/QtDialog/CMakeSetup.icns diff --git a/Source/QtDialog/CMakeSetup.ico b/Source/QtDialog/CMakeSetup.ico Binary files differindex e13bb156f..1ac13c830 100644 --- a/Source/QtDialog/CMakeSetup.ico +++ b/Source/QtDialog/CMakeSetup.ico diff --git a/Source/QtDialog/CMakeSetup128.png b/Source/QtDialog/CMakeSetup128.png Binary files differindex 12f1d9a9a..728ef0269 100644 --- a/Source/QtDialog/CMakeSetup128.png +++ b/Source/QtDialog/CMakeSetup128.png diff --git a/Source/QtDialog/CMakeSetup32.png b/Source/QtDialog/CMakeSetup32.png Binary files differindex 7bbcee413..1c36b31d0 100644 --- a/Source/QtDialog/CMakeSetup32.png +++ b/Source/QtDialog/CMakeSetup32.png diff --git a/Source/QtDialog/CMakeSetup64.png b/Source/QtDialog/CMakeSetup64.png Binary files differindex 43a8cc6af..44eb17173 100644 --- a/Source/QtDialog/CMakeSetup64.png +++ b/Source/QtDialog/CMakeSetup64.png diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 5d589cc08..3761bd363 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -108,7 +108,7 @@ CMakeSetupDialog::CMakeSetupDialog() QMenu* ToolsMenu = this->menuBar()->addMenu(tr("&Tools")); this->ConfigureAction = ToolsMenu->addAction(tr("&Configure")); - // prevent merging with Preferences menu item on Mac OS X + // prevent merging with Preferences menu item on macOS this->ConfigureAction->setMenuRole(QAction::NoRole); QObject::connect(this->ConfigureAction, SIGNAL(triggered(bool)), this, SLOT(doConfigure())); diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui index 8d8e0cdc2..dc22a2989 100644 --- a/Source/QtDialog/CMakeSetupDialog.ui +++ b/Source/QtDialog/CMakeSetupDialog.ui @@ -57,6 +57,9 @@ <verstretch>0</verstretch> </sizepolicy> </property> + <property name="styleSheet"> + <string notr="true">padding-left: 0</string> + </property> <property name="editable"> <bool>true</bool> </property> diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 0e14a3f7d..0133b88b3 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -94,11 +94,11 @@ void QCMake::setBinaryDirectory(const QString& _dir) } const char* gen = state->GetCacheEntryValue("CMAKE_GENERATOR"); if (gen) { - const char* extraGen = + const std::string* extraGen = state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR"); std::string curGen = cmExternalMakefileProjectGenerator::CreateFullGeneratorName( - gen, extraGen ? extraGen : ""); + gen, extraGen ? *extraGen : ""); this->setGenerator(QString::fromLocal8Bit(curGen.c_str())); } diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx index 1b3fb1583..7d3aa57e6 100644 --- a/Source/QtDialog/QCMakeCacheView.cxx +++ b/Source/QtDialog/QCMakeCacheView.cxx @@ -614,7 +614,7 @@ bool QCMakeCacheModelDelegate::editorEvent(QEvent* e, // Can remove this function and FileDialogFlag when minimum Qt version is 4.5 bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* evt) { - // workaround for what looks like a bug in Qt on Mac OS X + // workaround for what looks like a bug in Qt on macOS // where it doesn't create a QWidget wrapper for the native file dialog // so the Qt library ends up assuming the focus was lost to something else diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 1e3faefa4..53f5593e4 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -318,12 +318,6 @@ bool cmAddCustomCommandCommand::InitialPass( return false; } - // Convert working directory to a full path. - if (!working.empty()) { - const char* build_dir = this->Makefile->GetCurrentBinaryDirectory(); - working = cmSystemTools::CollapseFullPath(working, build_dir); - } - // Choose which mode of the command to use. bool escapeOldStyle = !verbatim; if (source.empty() && output.empty()) { diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index 4655f5843..ddd9b7082 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -181,13 +181,6 @@ bool cmAddCustomTargetCommand::InitialPass( } } - // Convert working directory to a full path. - if (!working_directory.empty()) { - const char* build_dir = this->Makefile->GetCurrentBinaryDirectory(); - working_directory = - cmSystemTools::CollapseFullPath(working_directory, build_dir); - } - if (commandLines.empty() && !byproducts.empty()) { this->Makefile->IssueMessage( cmake::FATAL_ERROR, diff --git a/Source/cmAddLinkOptionsCommand.cxx b/Source/cmAddLinkOptionsCommand.cxx new file mode 100644 index 000000000..10ebd1284 --- /dev/null +++ b/Source/cmAddLinkOptionsCommand.cxx @@ -0,0 +1,20 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmAddLinkOptionsCommand.h" + +#include "cmMakefile.h" + +class cmExecutionStatus; + +bool cmAddLinkOptionsCommand::InitialPass(std::vector<std::string> const& args, + cmExecutionStatus&) +{ + if (args.empty()) { + return true; + } + + for (std::string const& i : args) { + this->Makefile->AddLinkOption(i); + } + return true; +} diff --git a/Source/cmAddLinkOptionsCommand.h b/Source/cmAddLinkOptionsCommand.h new file mode 100644 index 000000000..30fff0058 --- /dev/null +++ b/Source/cmAddLinkOptionsCommand.h @@ -0,0 +1,31 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmAddLinkOptionsCommand_h +#define cmAddLinkOptionsCommand_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <string> +#include <vector> + +#include "cmCommand.h" + +class cmExecutionStatus; + +class cmAddLinkOptionsCommand : public cmCommand +{ +public: + /** + * This is a virtual constructor for the command. + */ + cmCommand* Clone() override { return new cmAddLinkOptionsCommand; } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + bool InitialPass(std::vector<std::string> const& args, + cmExecutionStatus& status) override; +}; + +#endif diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx index f673c7265..75bd6fba4 100644 --- a/Source/cmAddSubDirectoryCommand.cxx +++ b/Source/cmAddSubDirectoryCommand.cxx @@ -80,17 +80,17 @@ bool cmAddSubDirectoryCommand::InitialPass( // Remove the CurrentDirectory from the srcPath and replace it // with the CurrentOutputDirectory. - const char* src = this->Makefile->GetCurrentSourceDirectory(); - const char* bin = this->Makefile->GetCurrentBinaryDirectory(); - size_t srcLen = strlen(src); - size_t binLen = strlen(bin); + const std::string& src = this->Makefile->GetCurrentSourceDirectory(); + const std::string& bin = this->Makefile->GetCurrentBinaryDirectory(); + size_t srcLen = src.length(); + size_t binLen = bin.length(); if (srcLen > 0 && src[srcLen - 1] == '/') { --srcLen; } if (binLen > 0 && bin[binLen - 1] == '/') { --binLen; } - binPath = std::string(bin, binLen) + srcPath.substr(srcLen); + binPath = bin.substr(0, binLen) + srcPath.substr(srcLen); } else { // Use the binary directory specified. // Interpret a relative path with respect to the current binary directory. diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 1dd773425..60317818b 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -10,6 +10,7 @@ #include "cmsys/Encoding.hxx" #include "cmsys/FStream.hxx" #include <iostream> +#include <sstream> #include <string.h> #include <time.h> @@ -94,13 +95,25 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, return; } break; - case CompressGZip: + case CompressGZip: { if (archive_write_add_filter_gzip(this->Archive) != ARCHIVE_OK) { this->Error = "archive_write_add_filter_gzip: "; this->Error += cm_archive_error_string(this->Archive); return; } - break; + std::string source_date_epoch; + cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch); + if (!source_date_epoch.empty()) { + // We're not able to specify an arbitrary timestamp for gzip. + // The next best thing is to omit the timestamp entirely. + if (archive_write_set_filter_option(this->Archive, "gzip", "timestamp", + nullptr) != ARCHIVE_OK) { + this->Error = "archive_write_set_filter_option: "; + this->Error += cm_archive_error_string(this->Archive); + return; + } + } + } break; case CompressBZip2: if (archive_write_add_filter_bzip2(this->Archive) != ARCHIVE_OK) { this->Error = "archive_write_add_filter_bzip2: "; @@ -243,6 +256,17 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix) return false; } archive_entry_set_mtime(e, t, 0); + } else { + std::string source_date_epoch; + cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch); + if (!source_date_epoch.empty()) { + std::istringstream iss(source_date_epoch); + time_t epochTime; + iss >> epochTime; + if (iss.eof() && !iss.fail()) { + archive_entry_set_mtime(e, epochTime, 0); + } + } } // manages the uid/guid of the entry (if any) diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index 5f54338c2..ddff68686 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -40,8 +40,8 @@ bool cmBuildNameCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::RunSingleCommand("uname -a", &buildname, &buildname); if (!buildname.empty()) { std::string RegExp = "([^ ]*) [^ ]* ([^ ]*) "; - cmsys::RegularExpression reg(RegExp.c_str()); - if (reg.find(buildname.c_str())) { + cmsys::RegularExpression reg(RegExp); + if (reg.find(buildname)) { buildname = reg.match(1) + "-" + reg.match(2); } } diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index be3d2f45e..22ae34033 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -118,22 +118,22 @@ const char* CCONV cmGetHomeOutputDirectory(void* arg) const char* CCONV cmGetStartDirectory(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); - return mf->GetCurrentSourceDirectory(); + return mf->GetCurrentSourceDirectory().c_str(); } const char* CCONV cmGetStartOutputDirectory(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); - return mf->GetCurrentBinaryDirectory(); + return mf->GetCurrentBinaryDirectory().c_str(); } const char* CCONV cmGetCurrentDirectory(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); - return mf->GetCurrentSourceDirectory(); + return mf->GetCurrentSourceDirectory().c_str(); } const char* CCONV cmGetCurrentOutputDirectory(void* arg) { cmMakefile* mf = static_cast<cmMakefile*>(arg); - return mf->GetCurrentBinaryDirectory(); + return mf->GetCurrentBinaryDirectory().c_str(); } const char* CCONV cmGetDefinition(void* arg, const char* def) { @@ -171,7 +171,7 @@ void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt, " for directory ", d); return; } - t->AddLinkDirectory(d); + t->InsertLinkDirectory(d, mf->GetBacktrace()); } void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs, diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index bcb754a94..908eea145 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -9,7 +9,6 @@ #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/Process.h" -#include "cmsys/String.hxx" #include "cmsys/SystemInformation.hxx" #include <algorithm> #include <chrono> @@ -25,6 +24,11 @@ #include <time.h> #include <utility> #include <vector> +#if defined(_WIN32) +# include <windows.h> // IWYU pragma: keep +#else +# include <unistd.h> // IWYU pragma: keep +#endif #include "cmAlgorithms.h" #include "cmCTestBuildAndTestHandler.h" @@ -264,6 +268,8 @@ cmCTest::cmCTest() this->Failover = false; this->ForceNewCTestProcess = false; this->TomorrowTag = false; + this->TestProgressOutput = false; + this->FlushTestProgressLine = false; this->Verbose = false; this->Debug = false; @@ -291,11 +297,16 @@ cmCTest::cmCTest() this->OutputTestOutputOnTestFailure = false; this->RepeatTests = 1; // default to run each test once this->RepeatUntilFail = false; - std::string outOnFail; - if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", outOnFail)) { - this->OutputTestOutputOnTestFailure = - !cmSystemTools::IsOff(outOnFail.c_str()); + + std::string envValue; + if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", envValue)) { + this->OutputTestOutputOnTestFailure = !cmSystemTools::IsOff(envValue); + } + envValue.clear(); + if (cmSystemTools::GetEnv("CTEST_PROGRESS_OUTPUT", envValue)) { + this->TestProgressOutput = !cmSystemTools::IsOff(envValue); } + this->InitStreams(); this->Parts[PartStart].SetName("Start"); @@ -750,8 +761,8 @@ bool cmCTest::UpdateCTestConfiguration() } } if (this->ProduceXML) { - this->CompressXMLFiles = cmSystemTools::IsOn( - this->GetCTestConfiguration("CompressSubmission").c_str()); + this->CompressXMLFiles = + cmSystemTools::IsOn(this->GetCTestConfiguration("CompressSubmission")); } return true; } @@ -821,7 +832,7 @@ bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name, } } std::string filename = testingDir + "/" + name; - stream.Open(filename.c_str()); + stream.Open(filename); if (!stream) { cmCTestLog(this, ERROR_MESSAGE, "Problem opening file: " << filename << std::endl); @@ -1493,7 +1504,7 @@ int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml, this->AddSiteProperties(xml); xml.StartElement("Notes"); - for (cmsys::String const& file : files) { + for (std::string const& file : files) { cmCTestLog(this, OUTPUT, "\tAdd file: " << file << std::endl); std::string note_time = this->CurrentTime(); xml.StartElement("Note"); @@ -1597,7 +1608,7 @@ std::string cmCTest::Base64EncodeFile(std::string const& file) bool cmCTest::SubmitExtraFiles(const VectorOfStrings& files) { - for (cmsys::String const& file : files) { + for (std::string const& file : files) { if (!cmSystemTools::FileExists(file)) { cmCTestLog(this, ERROR_MESSAGE, "Cannot find extra file: " << file << " to submit." @@ -1877,6 +1888,9 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, if (this->CheckArgument(arg, "-Q", "--quiet")) { this->Quiet = true; } + if (this->CheckArgument(arg, "--progress")) { + this->TestProgressOutput = true; + } if (this->CheckArgument(arg, "-V", "--verbose")) { this->Verbose = true; } @@ -1939,7 +1953,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, if (this->CheckArgument(arg, "--interactive-debug-mode") && i < args.size() - 1) { i++; - this->InteractiveDebugMode = cmSystemTools::IsOn(args[i].c_str()); + this->InteractiveDebugMode = cmSystemTools::IsOn(args[i]); } if (this->CheckArgument(arg, "--submit-index") && i < args.size() - 1) { i++; @@ -2040,6 +2054,23 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, return true; } +bool cmCTest::ProgressOutputSupportedByConsole() const +{ +#if defined(_WIN32) + // On Windows we need a console buffer. + void* console = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbi; + return GetConsoleScreenBufferInfo(console, &csbi); +#else + // On UNIX we need a non-dumb tty. + std::string term_env_variable; + if (cmSystemTools::GetEnv("TERM", term_env_variable)) { + return isatty(1) && term_env_variable != "dumb"; + } +#endif + return false; +} + // handle the -S -SR and -SP arguments void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args, bool& SRArgumentSpecified) @@ -2194,6 +2225,18 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) } } + // TestProgressOutput only supported if console supports it and not logging + // to a file + this->TestProgressOutput = this->TestProgressOutput && + !this->OutputLogFile && this->ProgressOutputSupportedByConsole(); +#ifdef _WIN32 + if (this->TestProgressOutput) { + // Disable output line buffering so we can print content without + // a newline. + std::setvbuf(stdout, nullptr, _IONBF, 0); + } +#endif + // now what should cmake do? if --build-and-test was specified then // we run the build and test handler and return if (cmakeAndTest) { @@ -2763,6 +2806,7 @@ static const char* cmCTestStringLogType[] = { "DEBUG", "OUTPUT", "HANDLER_OUTPUT", "HANDLER_PROGRESS_OUTPUT", + "HANDLER_TEST_PROGRESS_OUTPUT", "HANDLER_VERBOSE_OUTPUT", "WARNING", "ERROR_MESSAGE", @@ -2823,6 +2867,34 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg, if (!this->Quiet) { std::ostream& out = *this->StreamOut; std::ostream& err = *this->StreamErr; + + if (logType == HANDLER_TEST_PROGRESS_OUTPUT) { + if (this->TestProgressOutput) { + cmCTestLogOutputFileLine(out); + if (this->FlushTestProgressLine) { + printf("\r"); + this->FlushTestProgressLine = false; + out.flush(); + } + + std::string msg_str{ msg }; + auto const lineBreakIt = msg_str.find('\n'); + if (lineBreakIt != std::string::npos) { + this->FlushTestProgressLine = true; + msg_str.erase(std::remove(msg_str.begin(), msg_str.end(), '\n'), + msg_str.end()); + } + + out << msg_str; +#ifndef _WIN32 + printf("\x1B[K"); // move caret to end +#endif + out.flush(); + return; + } + logType = HANDLER_OUTPUT; + } + switch (logType) { case DEBUG: if (this->Debug) { diff --git a/Source/cmCTest.h b/Source/cmCTest.h index ddeab1a8c..345b538e7 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -7,7 +7,7 @@ #include "cmDuration.h" #include "cmProcessOutput.h" -#include "cmsys/String.hxx" + #include <chrono> #include <map> #include <set> @@ -93,7 +93,7 @@ public: if the string does not name a valid part. */ Part GetPartFromName(const char* name); - typedef std::vector<cmsys::String> VectorOfStrings; + typedef std::vector<std::string> VectorOfStrings; typedef std::set<std::string> SetOfStrings; /** Process Command line arguments */ @@ -390,6 +390,7 @@ public: OUTPUT, HANDLER_OUTPUT, HANDLER_PROGRESS_OUTPUT, + HANDLER_TEST_PROGRESS_OUTPUT, HANDLER_VERBOSE_OUTPUT, WARNING, ERROR_MESSAGE, @@ -429,6 +430,8 @@ public: void SetFailover(bool failover) { this->Failover = failover; } bool GetFailover() { return this->Failover; } + bool GetTestProgressOutput() const { return this->TestProgressOutput; } + bool GetVerbose() { return this->Verbose; } bool GetExtraVerbose() { return this->ExtraVerbose; } @@ -467,6 +470,7 @@ private: std::string ConfigType; std::string ScheduleType; std::chrono::system_clock::time_point StopTime; + bool TestProgressOutput; bool Verbose; bool ExtraVerbose; bool ProduceXML; @@ -476,6 +480,8 @@ private: bool PrintLabels; bool Failover; + bool FlushTestProgressLine; + bool ForceNewCTestProcess; bool RunConfigurationScript; @@ -561,6 +567,9 @@ private: bool HandleCommandLineArguments(size_t& i, std::vector<std::string>& args, std::string& errormsg); + /** returns true iff the console supports progress output */ + bool ProgressOutputSupportedByConsole() const; + /** handle the -S -SP and -SR arguments */ void HandleScriptArguments(size_t& i, std::vector<std::string>& args, bool& SRArgumentSpecified); diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index c6a1cff92..b391dc44b 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -127,15 +127,15 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, } this->CacheMajorVersion = 0; this->CacheMinorVersion = 0; - if (const char* cmajor = + if (const std::string* cmajor = this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) { unsigned int v = 0; - if (sscanf(cmajor, "%u", &v) == 1) { + if (sscanf(cmajor->c_str(), "%u", &v) == 1) { this->CacheMajorVersion = v; } - if (const char* cminor = + if (const std::string* cminor = this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) { - if (sscanf(cminor, "%u", &v) == 1) { + if (sscanf(cminor->c_str(), "%u", &v) == 1) { this->CacheMinorVersion = v; } } @@ -153,18 +153,20 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, } // check to make sure the cache directory has not // been moved - const char* oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); + const std::string* oldDir = + this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); if (internal && oldDir) { std::string currentcwd = path; - std::string oldcwd = oldDir; + std::string oldcwd = *oldDir; cmSystemTools::ConvertToUnixSlashes(currentcwd); currentcwd += "/CMakeCache.txt"; oldcwd += "/CMakeCache.txt"; if (!cmSystemTools::SameFile(oldcwd, currentcwd)) { + const std::string* dir = + this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); std::ostringstream message; message << "The current CMakeCache.txt directory " << currentcwd - << " is different than the directory " - << this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR") + << " is different than the directory " << (dir ? *dir : "") << " where CMakeCache.txt was created. This may result " "in binaries being created in the wrong place. If you " "are not sure, reedit the CMakeCache.txt"; @@ -234,7 +236,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) { std::string cacheFile = path; cacheFile += "/CMakeCache.txt"; - cmGeneratedFileStream fout(cacheFile.c_str()); + cmGeneratedFileStream fout(cacheFile); fout.SetCopyIfDifferent(true); if (!fout) { cmSystemTools::Error("Unable to open cache file for save. ", @@ -512,12 +514,12 @@ cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator(const char* key) return CacheIterator(*this, key); } -const char* cmCacheManager::GetInitializedCacheValue( +const std::string* cmCacheManager::GetInitializedCacheValue( const std::string& key) const { CacheEntryMap::const_iterator i = this->Cache.find(key); if (i != this->Cache.end() && i->second.Initialized) { - return i->second.Value.c_str(); + return &i->second.Value; } return nullptr; } @@ -616,7 +618,7 @@ void cmCacheManager::CacheIterator::SetValue(const char* value) bool cmCacheManager::CacheIterator::GetValueAsBool() const { - return cmSystemTools::IsOn(this->GetEntry().Value.c_str()); + return cmSystemTools::IsOn(this->GetEntry().Value); } std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index 73923d1f5..a269271b8 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -126,7 +126,7 @@ public: int GetSize() { return static_cast<int>(this->Cache.size()); } ///! Get a value from the cache given a key - const char* GetInitializedCacheValue(const std::string& key) const; + const std::string* GetInitializedCacheValue(const std::string& key) const; const char* GetCacheEntryValue(const std::string& key) { diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index ccb4f88b0..2b4ceaa3e 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -68,12 +68,12 @@ const char* cmCommandArgumentParserHelper::ExpandSpecialVariable( return ""; } if (strcmp(key, "CACHE") == 0) { - if (const char* c = + if (const std::string* c = this->Makefile->GetState()->GetInitializedCacheValue(var)) { if (this->EscapeQuotes) { - return this->AddString(cmSystemTools::EscapeQuotes(c)); + return this->AddString(cmSystemTools::EscapeQuotes(*c)); } - return this->AddString(c); + return this->AddString(*c); } return ""; } @@ -172,7 +172,7 @@ void cmCommandArgumentParserHelper::AllocateParserType( return; } char* out = new char[len + 1]; - strncpy(out, str, len); + memcpy(out, str, len); out[len] = 0; pt->str = out; this->Variables.push_back(out); @@ -253,7 +253,6 @@ int cmCommandArgumentParserHelper::ParseString(const char* str, int verb) void cmCommandArgumentParserHelper::CleanupParser() { - std::vector<char*>::iterator sit; for (char* var : this->Variables) { delete[] var; } diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 7c32e6d58..63c539734 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -82,6 +82,7 @@ #if defined(CMAKE_BUILD_WITH_CMAKE) # include "cmAddCompileOptionsCommand.h" +# include "cmAddLinkOptionsCommand.h" # include "cmAuxSourceDirectoryCommand.h" # include "cmBuildNameCommand.h" # include "cmCMakeHostSystemInformationCommand.h" @@ -100,6 +101,8 @@ # include "cmRemoveDefinitionsCommand.h" # include "cmSourceGroupCommand.h" # include "cmSubdirDependsCommand.h" +# include "cmTargetLinkDirectoriesCommand.h" +# include "cmTargetLinkOptionsCommand.h" # include "cmUseMangledMesaCommand.h" # include "cmUtilitySourceCommand.h" # include "cmVariableRequiresCommand.h" @@ -272,7 +275,12 @@ void GetProjectCommands(cmState* state) state->AddBuiltinCommand("include_external_msproject", new cmIncludeExternalMSProjectCommand); state->AddBuiltinCommand("install_programs", new cmInstallProgramsCommand); + state->AddBuiltinCommand("add_link_options", new cmAddLinkOptionsCommand); state->AddBuiltinCommand("link_libraries", new cmLinkLibrariesCommand); + state->AddBuiltinCommand("target_link_options", + new cmTargetLinkOptionsCommand); + state->AddBuiltinCommand("target_link_directories", + new cmTargetLinkDirectoriesCommand); state->AddBuiltinCommand("load_cache", new cmLoadCacheCommand); state->AddBuiltinCommand("qt_wrap_cpp", new cmQTWrapCPPCommand); state->AddBuiltinCommand("qt_wrap_ui", new cmQTWrapUICommand); diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index b1f386094..aa17de6e4 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -279,12 +279,12 @@ cmComputeLinkDepends::Compute() return this->FinalLinkEntries; } -std::map<std::string, int>::iterator cmComputeLinkDepends::AllocateLinkEntry( - std::string const& item) +std::map<cmLinkItem, int>::iterator cmComputeLinkDepends::AllocateLinkEntry( + cmLinkItem const& item) { - std::map<std::string, int>::value_type index_entry( + std::map<cmLinkItem, int>::value_type index_entry( item, static_cast<int>(this->EntryList.size())); - std::map<std::string, int>::iterator lei = + std::map<cmLinkItem, int>::iterator lei = this->LinkEntryIndex.insert(index_entry).first; this->EntryList.emplace_back(); this->InferredDependSets.push_back(nullptr); @@ -295,7 +295,7 @@ std::map<std::string, int>::iterator cmComputeLinkDepends::AllocateLinkEntry( int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) { // Check if the item entry has already been added. - std::map<std::string, int>::iterator lei = this->LinkEntryIndex.find(item); + std::map<cmLinkItem, int>::iterator lei = this->LinkEntryIndex.find(item); if (lei != this->LinkEntryIndex.end()) { // Yes. We do not need to follow the item's dependencies again. return lei->second; @@ -307,10 +307,11 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) // Initialize the item entry. int index = lei->second; LinkEntry& entry = this->EntryList[index]; - entry.Item = item; + entry.Item = item.AsStr(); entry.Target = item.Target; - entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' && - item.substr(0, 10) != "-framework"); + entry.IsFlag = + (!entry.Target && entry.Item[0] == '-' && entry.Item[1] != 'l' && + entry.Item.substr(0, 10) != "-framework"); // If the item has dependencies queue it to follow them. if (entry.Target) { @@ -395,7 +396,7 @@ void cmComputeLinkDepends::QueueSharedDependencies( void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) { // Check if the target already has an entry. - std::map<std::string, int>::iterator lei = + std::map<cmLinkItem, int>::iterator lei = this->LinkEntryIndex.find(dep.Item); if (lei == this->LinkEntryIndex.end()) { // Allocate a spot for the item entry. @@ -403,7 +404,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) // Initialize the item entry. LinkEntry& entry = this->EntryList[lei->second]; - entry.Item = dep.Item; + entry.Item = dep.Item.AsStr(); entry.Target = dep.Item.Target; // This item was added specifically because it is a dependent @@ -473,9 +474,9 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, // If the library is meant for this link type then use it. if (llt == GENERAL_LibraryType || llt == this->LinkType) { - actual_libs.emplace_back(d, this->FindTargetToLink(depender_index, d)); + actual_libs.emplace_back(this->ResolveLinkItem(depender_index, d)); } else if (this->OldLinkDirMode) { - cmLinkItem item(d, this->FindTargetToLink(depender_index, d)); + cmLinkItem item = this->ResolveLinkItem(depender_index, d); this->CheckWrongConfigItem(item); } @@ -512,7 +513,7 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, // Skip entries that will resolve to the target getting linked or // are empty. cmLinkItem const& item = l; - if (item == this->Target->GetName() || item.empty()) { + if (item.AsStr() == this->Target->GetName() || item.AsStr().empty()) { continue; } @@ -553,8 +554,8 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, } } -cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink( - int depender_index, const std::string& name) +cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index, + const std::string& name) { // Look for a target in the scope of the depender. cmGeneratorTarget const* from = this->Target; @@ -564,7 +565,7 @@ cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink( from = depender; } } - return from->FindTargetToLink(name); + return from->ResolveLinkItem(name); } void cmComputeLinkDepends::InferDependencies() diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index dd0e02943..66fb1e652 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -72,19 +72,18 @@ private: std::string Config; EntryVector FinalLinkEntries; - std::map<std::string, int>::iterator AllocateLinkEntry( - std::string const& item); + std::map<cmLinkItem, int>::iterator AllocateLinkEntry( + cmLinkItem const& item); int AddLinkEntry(cmLinkItem const& item); void AddVarLinkEntries(int depender_index, const char* value); void AddDirectLinkEntries(); template <typename T> void AddLinkEntries(int depender_index, std::vector<T> const& libs); - cmGeneratorTarget const* FindTargetToLink(int depender_index, - const std::string& name); + cmLinkItem ResolveLinkItem(int depender_index, const std::string& name); // One entry for each unique item. std::vector<LinkEntry> EntryList; - std::map<std::string, int> LinkEntryIndex; + std::map<cmLinkItem, int> LinkEntryIndex; // BFS of initial dependencies. struct BFSEntry diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 8d6efdebc..0e48ca86d 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -30,7 +30,7 @@ Notes about linking on various platforms: ------------------------------------------------------------------------------ -Linux, FreeBSD, Mac OS X, IRIX, Sun, Windows: +Linux, FreeBSD, macOS, IRIX, Sun, Windows: Linking to libraries using the full path works fine. @@ -357,10 +357,10 @@ cmComputeLinkInformation::cmComputeLinkInformation( } // Add the search path entries requested by the user to path ordering. - this->OrderLinkerSearchPath->AddUserDirectories( - this->Target->GetLinkDirectories()); - this->OrderRuntimeSearchPath->AddUserDirectories( - this->Target->GetLinkDirectories()); + std::vector<std::string> directories; + this->Target->GetLinkDirectories(directories, config, this->LinkLanguage); + this->OrderLinkerSearchPath->AddUserDirectories(directories); + this->OrderRuntimeSearchPath->AddUserDirectories(directories); // Set up the implicit link directories. this->LoadImplicitLinkInfo(); @@ -387,8 +387,7 @@ cmComputeLinkInformation::cmComputeLinkInformation( if (this->OldLinkDirMode) { // Construct a mask to not bother with this behavior for link // directories already specified by the user. - std::vector<std::string> const& dirs = this->Target->GetLinkDirectories(); - this->OldLinkDirMask.insert(dirs.begin(), dirs.end()); + this->OldLinkDirMask.insert(directories.begin(), directories.end()); } this->CMP0060Warn = this->Makefile->PolicyOptionalWarningEnabled( @@ -1725,7 +1724,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, } const char* stagePath = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); - const char* installPrefix = + std::string const& installPrefix = this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); cmSystemTools::ConvertToUnixSlashes(rootPath); std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath(); diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index efdd3a5f8..268e74970 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -195,7 +195,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // dependencies in all targets, because the generated build-systems can't // deal with config-specific dependencies. { - std::set<std::string> emitted; + std::set<cmLinkItem> emitted; std::vector<std::string> configs; depender->Makefile->GetConfigurations(configs); @@ -206,27 +206,31 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) std::vector<cmSourceFile const*> objectFiles; depender->GetExternalObjects(objectFiles, it); for (cmSourceFile const* o : objectFiles) { - std::string objLib = o->GetObjectLibrary(); - if (!objLib.empty() && emitted.insert(objLib).second) { - if (depender->GetType() != cmStateEnums::EXECUTABLE && - depender->GetType() != cmStateEnums::STATIC_LIBRARY && - depender->GetType() != cmStateEnums::SHARED_LIBRARY && - depender->GetType() != cmStateEnums::MODULE_LIBRARY && - depender->GetType() != cmStateEnums::OBJECT_LIBRARY) { - this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - cmake::FATAL_ERROR, - "Only executables and libraries may reference target objects.", - depender->GetBacktrace()); - return; + std::string const& objLib = o->GetObjectLibrary(); + if (!objLib.empty()) { + cmLinkItem const& objItem = depender->ResolveLinkItem(objLib); + if (emitted.insert(objItem).second) { + if (depender->GetType() != cmStateEnums::EXECUTABLE && + depender->GetType() != cmStateEnums::STATIC_LIBRARY && + depender->GetType() != cmStateEnums::SHARED_LIBRARY && + depender->GetType() != cmStateEnums::MODULE_LIBRARY && + depender->GetType() != cmStateEnums::OBJECT_LIBRARY) { + this->GlobalGenerator->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, + "Only executables and libraries may reference target objects.", + depender->GetBacktrace()); + return; + } + const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility( + objLib); } - const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(objLib); } } cmLinkImplementation const* impl = depender->GetLinkImplementation(it); // A target should not depend on itself. - emitted.insert(depender->GetName()); + emitted.insert(cmLinkItem(depender)); for (cmLinkImplItem const& lib : impl->Libraries) { // Don't emit the same library twice for this target. if (emitted.insert(lib).second) { @@ -240,9 +244,9 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // Loop over all utility dependencies. { std::set<cmLinkItem> const& tutils = depender->GetUtilityItems(); - std::set<std::string> emitted; + std::set<cmLinkItem> emitted; // A target should not depend on itself. - emitted.insert(depender->GetName()); + emitted.insert(cmLinkItem(depender)); for (cmLinkItem const& litem : tutils) { // Don't emit the same utility twice for this target. if (emitted.insert(litem).second) { @@ -254,7 +258,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) void cmComputeTargetDepends::AddInterfaceDepends( int depender_index, const cmGeneratorTarget* dependee, - const std::string& config, std::set<std::string>& emitted) + const std::string& config, std::set<cmLinkItem>& emitted) { cmGeneratorTarget const* depender = this->Targets[depender_index]; if (cmLinkInterface const* iface = @@ -271,7 +275,7 @@ void cmComputeTargetDepends::AddInterfaceDepends( void cmComputeTargetDepends::AddInterfaceDepends( int depender_index, cmLinkItem const& dependee_name, - const std::string& config, std::set<std::string>& emitted) + const std::string& config, std::set<cmLinkItem>& emitted) { cmGeneratorTarget const* depender = this->Targets[depender_index]; cmGeneratorTarget const* dependee = dependee_name.Target; @@ -285,7 +289,7 @@ void cmComputeTargetDepends::AddInterfaceDepends( if (dependee) { // A target should not depend on itself. - emitted.insert(depender->GetName()); + emitted.insert(cmLinkItem(depender)); this->AddInterfaceDepends(depender_index, dependee, config, emitted); } } @@ -324,7 +328,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, << depender->GetName() << "\" does not exist."; cmListFileBacktrace const* backtrace = - depender->GetUtilityBacktrace(dependee_name); + depender->GetUtilityBacktrace(dependee_name.AsStr()); if (backtrace) { cm->IssueMessage(messageType, e.str(), *backtrace); } else { diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index e93e376ce..3046e8af9 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -51,11 +51,11 @@ private: bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name, const std::string& config, - std::set<std::string>& emitted); + std::set<cmLinkItem>& emitted); void AddInterfaceDepends(int depender_index, cmGeneratorTarget const* dependee, const std::string& config, - std::set<std::string>& emitted); + std::set<cmLinkItem>& emitted); cmGlobalGenerator* GlobalGenerator; bool DebugMode; bool NoCycles; diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx index b5a639ac5..305262d2d 100644 --- a/Source/cmConfigureFileCommand.cxx +++ b/Source/cmConfigureFileCommand.cxx @@ -20,11 +20,8 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args, } std::string const& inFile = args[0]; - if (!cmSystemTools::FileIsFullPath(inFile)) { - this->InputFile = this->Makefile->GetCurrentSourceDirectory(); - this->InputFile += "/"; - } - this->InputFile += inFile; + this->InputFile = cmSystemTools::CollapseFullPath( + inFile, this->Makefile->GetCurrentSourceDirectory()); // If the input location is a directory, error out. if (cmSystemTools::FileIsDirectory(this->InputFile)) { @@ -39,11 +36,8 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args, } std::string const& outFile = args[1]; - if (!cmSystemTools::FileIsFullPath(outFile)) { - this->OutputFile = this->Makefile->GetCurrentBinaryDirectory(); - this->OutputFile += "/"; - } - this->OutputFile += outFile; + this->OutputFile = cmSystemTools::CollapseFullPath( + outFile, this->Makefile->GetCurrentBinaryDirectory()); // If the output location is already a directory put the file in it. if (cmSystemTools::FileIsDirectory(this->OutputFile)) { diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 6c9f9d6f4..d1c173670 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -64,6 +64,19 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, } this->Depends.insert(this->Depends.end(), result.begin(), result.end()); } + + const std::string& workingdirectory = this->CC.GetWorkingDirectory(); + if (!workingdirectory.empty()) { + std::unique_ptr<cmCompiledGeneratorExpression> cge = + this->GE->Parse(workingdirectory); + this->WorkingDirectory = cge->Evaluate(this->LG, this->Config); + // Convert working directory to a full path. + if (!this->WorkingDirectory.empty()) { + std::string const& build_dir = this->LG->GetCurrentBinaryDirectory(); + this->WorkingDirectory = + cmSystemTools::CollapseFullPath(this->WorkingDirectory, build_dir); + } + } } cmCustomCommandGenerator::~cmCustomCommandGenerator() @@ -186,7 +199,7 @@ const char* cmCustomCommandGenerator::GetComment() const std::string cmCustomCommandGenerator::GetWorkingDirectory() const { - return this->CC.GetWorkingDirectory(); + return this->WorkingDirectory; } std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 34fd653a5..b7e2a3924 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -23,6 +23,7 @@ class cmCustomCommandGenerator cmGeneratorExpression* GE; cmCustomCommandLines CommandLines; std::vector<std::string> Depends; + std::string WorkingDirectory; const char* GetCrossCompilingEmulator(unsigned int c) const; const char* GetArgv0Location(unsigned int c) const; diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index e766854a6..5fafaf943 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -30,11 +30,11 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key, return begin->Map.insert(MapType::value_type(key, def)).first->second; } -const char* cmDefinitions::Get(const std::string& key, StackIter begin, - StackIter end) +const std::string* cmDefinitions::Get(const std::string& key, StackIter begin, + StackIter end) { Def const& def = cmDefinitions::GetInternal(key, begin, end, false); - return def.Exists ? def.c_str() : nullptr; + return def.Exists ? &def : nullptr; } void cmDefinitions::Raise(const std::string& key, StackIter begin, diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index 528b15748..4ab5be6cc 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -23,8 +23,8 @@ class cmDefinitions typedef cmLinkedTree<cmDefinitions>::iterator StackIter; public: - static const char* Get(const std::string& key, StackIter begin, - StackIter end); + static const std::string* Get(const std::string& key, StackIter begin, + StackIter end); static void Raise(const std::string& key, StackIter begin, StackIter end); diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 4716e14d6..6f1afd7bc 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -36,7 +36,7 @@ bool cmDepends::Write(std::ostream& makeDepends, std::ostream& internalDepends) std::string srcLang = "CMAKE_DEPENDS_CHECK_"; srcLang += this->Language; cmMakefile* mf = this->LocalGenerator->GetMakefile(); - const char* srcStr = mf->GetSafeDefinition(srcLang); + std::string const& srcStr = mf->GetSafeDefinition(srcLang); std::vector<std::string> pairs; cmSystemTools::ExpandListArgument(srcStr, pairs); diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index 34c0e9403..f7dd33b37 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -174,7 +174,7 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, // Complain if the file cannot be found and matches the complain // regex. if (fullName.empty() && - this->IncludeRegexComplain.find(current.FileName.c_str())) { + this->IncludeRegexComplain.find(current.FileName)) { cmSystemTools::Error("Cannot find file \"", current.FileName.c_str(), "\"."); return false; @@ -359,7 +359,7 @@ void cmDependsC::Scan(std::istream& is, const char* directory, } // Match include directives. - if (this->IncludeRegexLine.find(line.c_str())) { + if (this->IncludeRegexLine.find(line)) { // Get the file being included. UnscannedEntry entry; entry.FileName = this->IncludeRegexLine.match(2); @@ -383,7 +383,7 @@ void cmDependsC::Scan(std::istream& is, const char* directory, // file their own directory by simply using "filename.h" (#12619) // This kind of problem will be fixed when a more // preprocessor-like implementation of this scanner is created. - if (this->IncludeRegexScan.find(entry.FileName.c_str())) { + if (this->IncludeRegexScan.find(entry.FileName)) { newCacheEntry->UnscannedEntries.push_back(entry); if (this->Encountered.find(entry.FileName) == this->Encountered.end()) { @@ -449,7 +449,7 @@ void cmDependsC::ParseTransform(std::string const& xform) void cmDependsC::TransformLine(std::string& line) { // Check for a transform rule match. Return if none. - if (!this->IncludeRegexTransform.find(line.c_str())) { + if (!this->IncludeRegexTransform.find(line)) { return; } TransformRulesType::const_iterator tri = diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index dbea15ae0..a04cee790 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -178,7 +178,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, // Store the list of modules provided by this target. std::string fiName = this->TargetDirectory; fiName += "/fortran.internal"; - cmGeneratedFileStream fiStream(fiName.c_str()); + cmGeneratedFileStream fiStream(fiName); fiStream << "# The fortran modules provided by this target.\n"; fiStream << "provides\n"; std::set<std::string> const& provides = this->Internal->TargetProvides; @@ -190,7 +190,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, if (!provides.empty()) { std::string fcName = this->TargetDirectory; fcName += "/cmake_clean_Fortran.cmake"; - cmGeneratedFileStream fcStream(fcName.c_str()); + cmGeneratedFileStream fcStream(fcName); fcStream << "# Remove fortran modules provided by this target.\n"; fcStream << "FILE(REMOVE"; std::string currentBinDir = diff --git a/Source/cmDocumentationFormatter.cxx b/Source/cmDocumentationFormatter.cxx index 6b996e4b0..2267ef94b 100644 --- a/Source/cmDocumentationFormatter.cxx +++ b/Source/cmDocumentationFormatter.cxx @@ -90,7 +90,7 @@ void cmDocumentationFormatter::SetIndent(const char* indent) void cmDocumentationFormatter::PrintColumn(std::ostream& os, const char* text) { - // Print text arranged in an indented column of fixed witdh. + // Print text arranged in an indented column of fixed width. const char* l = text; long column = 0; bool newSentence = false; diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index 0ceac85e3..d12ad7fd1 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -7,11 +7,9 @@ #include <sstream> #include <utility> -#include "cmGeneratorExpression.h" -#include "cmGeneratorExpressionDAGChecker.h" +#include "cmAlgorithms.h" #include "cmGeneratorTarget.h" #include "cmLinkItem.h" -#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmPolicies.h" #include "cmStateTypes.h" @@ -103,27 +101,14 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( os << "LOCAL_CPP_FEATURES += "; os << (property.second) << "\n"; } else if (property.first == "INTERFACE_LINK_LIBRARIES") { - // evaluate any generator expressions with the current - // build type of the makefile - cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker( - target->GetName(), "INTERFACE_LINK_LIBRARIES", nullptr, nullptr); - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(property.second); - std::string evaluated = cge->Evaluate( - target->GetLocalGenerator(), config, false, target, &dagChecker); - // need to look at list in pi->second and see if static or shared - // FindTargetToLink - // target->GetLocalGenerator()->FindGeneratorTargetToUse() - // then add to LOCAL_CPPFLAGS - std::vector<std::string> libraries; - cmSystemTools::ExpandListArgument(evaluated, libraries); std::string staticLibs; std::string sharedLibs; std::string ldlibs; - for (std::string const& lib : libraries) { - cmGeneratorTarget* gt = - target->GetLocalGenerator()->FindGeneratorTargetToUse(lib); + cmLinkInterfaceLibraries const* linkIFace = + target->GetLinkInterfaceLibraries(config, target, false); + for (cmLinkItem const& item : linkIFace->Libraries) { + cmGeneratorTarget const* gt = item.Target; + std::string const& lib = item.AsStr(); if (gt) { if (gt->GetType() == cmStateEnums::SHARED_LIBRARY || @@ -169,6 +154,11 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( end = "\\\n"; } os << "\n"; + } else if (property.first == "INTERFACE_LINK_OPTIONS") { + os << "LOCAL_EXPORT_LDFLAGS := "; + std::vector<std::string> linkFlagsList; + cmSystemTools::ExpandListArgument(property.second, linkFlagsList); + os << cmJoin(linkFlagsList, " ") << "\n"; } else { os << "# " << property.first << " " << (property.second) << "\n"; } diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 47636cd23..024e64116 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -95,6 +95,15 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gte, cmGeneratorExpression::BuildInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gte, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_LINK_DIRECTORIES", gte, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_LINK_DEPENDS", gte, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte, properties); diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 4e1d7713a..f965a2993 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -237,7 +237,7 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args) } const char* packageExpr = "^[A-Za-z0-9_.-]+$"; cmsys::RegularExpression packageRegex(packageExpr); - if (!packageRegex.find(package.c_str())) { + if (!packageRegex.find(package)) { std::ostringstream e; e << "PACKAGE given invalid package name \"" << package << "\". " << "Package names must match \"" << packageExpr << "\"."; @@ -254,12 +254,12 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args) // We store the current build directory in the registry as a value // named by a hash of its own content. This is deterministic and is // unique with high probability. - const char* outDir = this->Makefile->GetCurrentBinaryDirectory(); + const std::string& outDir = this->Makefile->GetCurrentBinaryDirectory(); std::string hash = cmSystemTools::ComputeStringMD5(outDir); #if defined(_WIN32) && !defined(__CYGWIN__) - this->StorePackageRegistryWin(package, outDir, hash.c_str()); + this->StorePackageRegistryWin(package, outDir.c_str(), hash.c_str()); #else - this->StorePackageRegistryDir(package, outDir, hash.c_str()); + this->StorePackageRegistryDir(package, outDir.c_str(), hash.c_str()); #endif return true; @@ -339,7 +339,7 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package, fname += "/"; fname += hash; if (!cmSystemTools::FileExists(fname)) { - cmGeneratedFileStream entry(fname.c_str(), true); + cmGeneratedFileStream entry(fname, true); if (entry) { entry << content << "\n"; } else { diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index ce9bc8700..bddc3c4aa 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -75,7 +75,7 @@ bool cmExportFileGenerator::GenerateImportFile() } else { // Generate atomically and with copy-if-different. std::unique_ptr<cmGeneratedFileStream> ap( - new cmGeneratedFileStream(this->MainImportFile.c_str(), true)); + new cmGeneratedFileStream(this->MainImportFile, true)); ap->SetCopyIfDifferent(true); foutPtr = std::move(ap); } @@ -195,7 +195,7 @@ static bool checkInterfaceDirs(const std::string& prepro, cmGeneratorTarget* target, const std::string& prop) { - const char* installDir = + std::string const& installDir = target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); std::string const& topSourceDir = target->GetLocalGenerator()->GetSourceDirectory(); @@ -420,6 +420,68 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( } } +void cmExportFileGenerator::PopulateLinkDependsInterface( + cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap& properties, std::vector<std::string>& missingTargets) +{ + cmGeneratorTarget* gt = tei->Target; + assert(preprocessRule == cmGeneratorExpression::InstallInterface); + + const char* propName = "INTERFACE_LINK_DEPENDS"; + const char* input = gt->GetProperty(propName); + + if (!input) { + return; + } + + if (!*input) { + properties[propName].clear(); + return; + } + + std::string prepro = + cmGeneratorExpression::Preprocess(input, preprocessRule, true); + if (!prepro.empty()) { + this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets); + + if (!checkInterfaceDirs(prepro, gt, propName)) { + return; + } + properties[propName] = prepro; + } +} + +void cmExportFileGenerator::PopulateLinkDirectoriesInterface( + cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap& properties, std::vector<std::string>& missingTargets) +{ + cmGeneratorTarget* gt = tei->Target; + assert(preprocessRule == cmGeneratorExpression::InstallInterface); + + const char* propName = "INTERFACE_LINK_DIRECTORIES"; + const char* input = gt->GetProperty(propName); + + if (!input) { + return; + } + + if (!*input) { + properties[propName].clear(); + return; + } + + std::string prepro = + cmGeneratorExpression::Preprocess(input, preprocessRule, true); + if (!prepro.empty()) { + this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets); + + if (!checkInterfaceDirs(prepro, gt, propName)) { + return; + } + properties[propName] = prepro; + } +} + void cmExportFileGenerator::PopulateInterfaceProperty( const std::string& propName, cmGeneratorTarget* target, cmGeneratorExpression::PreprocessContext preprocessRule, @@ -536,14 +598,17 @@ bool cmExportFileGenerator::AddTargetNamespace( std::string& input, cmGeneratorTarget* target, std::vector<std::string>& missingTargets) { - cmLocalGenerator* lg = target->GetLocalGenerator(); + cmGeneratorTarget::TargetOrString resolved = + target->ResolveTargetReference(input); - cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(input); + cmGeneratorTarget* tgt = resolved.Target; if (!tgt) { + input = resolved.String; return false; } if (tgt->IsImported()) { + input = tgt->GetName(); return true; } if (this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) { @@ -553,6 +618,8 @@ bool cmExportFileGenerator::AddTargetNamespace( this->HandleMissingTarget(namespacedTarget, missingTargets, target, tgt); if (!namespacedTarget.empty()) { input = namespacedTarget; + } else { + input = tgt->GetName(); } } return true; @@ -800,6 +867,16 @@ void cmExportFileGenerator::SetImportDetailProperties( } } +static std::string const& asString(std::string const& l) +{ + return l; +} + +static std::string const& asString(cmLinkItem const& l) +{ + return l.AsStr(); +} + template <typename T> void cmExportFileGenerator::SetImportLinkProperty( std::string const& suffix, cmGeneratorTarget* target, @@ -819,7 +896,7 @@ void cmExportFileGenerator::SetImportLinkProperty( link_entries += sep; sep = ";"; - std::string temp = l; + std::string temp = asString(l); this->AddTargetNamespace(temp, target, missingTargets); link_entries += temp; } diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 954e6c5f8..41c6538d1 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -147,6 +147,14 @@ protected: cmTargetExport* target, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); + void PopulateLinkDirectoriesInterface( + cmTargetExport* target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap& properties, std::vector<std::string>& missingTargets); + void PopulateLinkDependsInterface( + cmTargetExport* target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap& properties, std::vector<std::string>& missingTargets); void SetImportLinkInterface( const std::string& config, std::string const& suffix, diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 02686f3d8..e44408773 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -103,6 +103,13 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gt, cmGeneratorExpression::InstallInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gt, + cmGeneratorExpression::InstallInterface, + properties, missingTargets); + this->PopulateLinkDirectoriesInterface( + te, cmGeneratorExpression::InstallInterface, properties, missingTargets); + this->PopulateLinkDependsInterface( + te, cmGeneratorExpression::InstallInterface, properties, missingTargets); std::string errorMessage; if (!this->PopulateExportProperties(gt, properties, errorMessage)) { @@ -283,7 +290,7 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig( fileName += this->FileExt; // Open the output file to generate it. - cmGeneratedFileStream exportFileStream(fileName.c_str(), true); + cmGeneratedFileStream exportFileStream(fileName, true); if (!exportFileStream) { std::string se = cmSystemTools::GetLastSystemError(); std::ostringstream e; diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index 50f8cb014..b4b2962b1 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -54,7 +54,7 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const cm::make_unique<cmsys::ofstream>(this->Filename.c_str(), std::ios::app); } else { std::unique_ptr<cmGeneratedFileStream> ap( - new cmGeneratedFileStream(this->Filename.c_str(), true)); + new cmGeneratedFileStream(this->Filename, true)); ap->SetCopyIfDifferent(true); foutPtr = std::move(ap); } diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 87648cbb2..c169032dd 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -65,8 +65,7 @@ std::string cmExportTryCompileFileGenerator::FindTargets( cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker(tgt->GetName(), propName, nullptr, - nullptr); + cmGeneratorExpressionDAGChecker dagChecker(tgt, propName, nullptr, nullptr); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx index fe7159a8d..8d3dad73e 100644 --- a/Source/cmExprParserHelper.cxx +++ b/Source/cmExprParserHelper.cxx @@ -6,6 +6,8 @@ #include <iostream> #include <sstream> +#include <stdexcept> +#include <utility> int cmExpr_yyparse(yyscan_t yyscanner); // @@ -13,11 +15,11 @@ cmExprParserHelper::cmExprParserHelper() { this->FileLine = -1; this->FileName = nullptr; + this->Result = 0; } cmExprParserHelper::~cmExprParserHelper() { - this->CleanupParser(); } int cmExprParserHelper::ParseString(const char* str, int verb) @@ -37,16 +39,34 @@ int cmExprParserHelper::ParseString(const char* str, int verb) yyscan_t yyscanner; cmExpr_yylex_init(&yyscanner); cmExpr_yyset_extra(this, yyscanner); - int res = cmExpr_yyparse(yyscanner); + + try { + int res = cmExpr_yyparse(yyscanner); + if (res != 0) { + std::string e = "cannot parse the expression: \"" + InputBuffer + "\": "; + e += ErrorString; + e += "."; + this->SetError(std::move(e)); + } + } catch (std::runtime_error const& fail) { + std::string e = + "cannot evaluate the expression: \"" + InputBuffer + "\": "; + e += fail.what(); + e += "."; + this->SetError(std::move(e)); + } catch (std::out_of_range const&) { + std::string e = "cannot evaluate the expression: \"" + InputBuffer + + "\": a numeric value is out of range."; + this->SetError(std::move(e)); + } catch (...) { + std::string e = "cannot parse the expression: \"" + InputBuffer + "\"."; + this->SetError(std::move(e)); + } cmExpr_yylex_destroy(yyscanner); - if (res != 0) { - // str << "CAL_Parser returned: " << res << std::endl; - // std::cerr << "When parsing: [" << str << "]" << std::endl; + if (!this->ErrorString.empty()) { return 0; } - this->CleanupParser(); - if (Verbose) { std::cerr << "Expanding [" << str << "] produced: [" << this->Result << "]" << std::endl; @@ -54,10 +74,6 @@ int cmExprParserHelper::ParseString(const char* str, int verb) return 1; } -void cmExprParserHelper::CleanupParser() -{ -} - int cmExprParserHelper::LexInput(char* buf, int maxlen) { // std::cout << "JPLexInput "; @@ -85,7 +101,21 @@ void cmExprParserHelper::Error(const char* str) this->ErrorString = ostr.str(); } -void cmExprParserHelper::SetResult(int value) +void cmExprParserHelper::UnexpectedChar(char c) +{ + unsigned long pos = static_cast<unsigned long>(this->InputBufferPos); + std::ostringstream ostr; + ostr << "Unexpected character in expression at position " << pos << ": " << c + << "\n"; + this->WarningString += ostr.str(); +} + +void cmExprParserHelper::SetResult(KWIML_INT_int64_t value) { this->Result = value; } + +void cmExprParserHelper::SetError(std::string errorString) +{ + this->ErrorString = std::move(errorString); +} diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h index dcdaca967..42c460acc 100644 --- a/Source/cmExprParserHelper.h +++ b/Source/cmExprParserHelper.h @@ -5,6 +5,8 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cm_kwiml.h" + #include <string> #include <vector> @@ -13,7 +15,7 @@ class cmExprParserHelper public: struct ParserType { - int Number; + KWIML_INT_int64_t Number; }; cmExprParserHelper(); @@ -24,12 +26,16 @@ public: int LexInput(char* buf, int maxlen); void Error(const char* str); - void SetResult(int value); + void SetResult(KWIML_INT_int64_t value); - int GetResult() { return this->Result; } + KWIML_INT_int64_t GetResult() { return this->Result; } const char* GetError() { return this->ErrorString.c_str(); } + void UnexpectedChar(char c); + + std::string const& GetWarning() const { return this->WarningString; } + private: std::string::size_type InputBufferPos; std::string InputBuffer; @@ -39,12 +45,13 @@ private: void Print(const char* place, const char* str); - void CleanupParser(); + void SetError(std::string errorString); - int Result; + KWIML_INT_int64_t Result; const char* FileName; long FileLine; std::string ErrorString; + std::string WarningString; }; #define YYSTYPE cmExprParserHelper::ParserType diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index b636c736d..07a60de24 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -199,7 +199,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( const std::vector<cmLocalGenerator*>& lgs, const std::string& filename) { const cmMakefile* mf = lgs[0]->GetMakefile(); - cmGeneratedFileStream fout(filename.c_str()); + cmGeneratedFileStream fout(filename); if (!fout) { return; } @@ -476,7 +476,7 @@ std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile( filename += "/"; filename += target->GetName(); filename += ".objlib"; - cmGeneratedFileStream fout(filename.c_str()); + cmGeneratedFileStream fout(filename); if (fout) { /* clang-format off */ fout << "# This is a dummy file for the OBJECT library " @@ -666,7 +666,7 @@ std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf) pureFortran = true; } - std::string compilerId = mf->GetSafeDefinition(compilerIdVar); + std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar); std::string compiler = "gcc"; // default to gcc if (compilerId == "MSVC") { if (mf->IsDefinitionSet("MSVC10")) { diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index b76efb2ff..28106d19d 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -77,7 +77,7 @@ void cmExtraCodeLiteGenerator::Generate() } } - cmGeneratedFileStream fout(workspaceFileName.c_str()); + cmGeneratedFileStream fout(workspaceFileName); cmXMLWriter xml(fout); xml.StartDocument("utf-8"); @@ -122,7 +122,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget( for (cmLocalGenerator* lg : lgs) { for (cmGeneratorTarget* lt : lg->GetGeneratorTargets()) { cmStateEnums::TargetType type = lt->GetType(); - std::string outputDir = lg->GetCurrentBinaryDirectory(); + std::string const& outputDir = lg->GetCurrentBinaryDirectory(); std::string targetName = lt->GetName(); std::string filename = outputDir + "/" + targetName + ".project"; retval.push_back(targetName); @@ -161,7 +161,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps( // for each sub project in the workspace create a codelite project for (auto const& it : this->GlobalGenerator->GetProjectMap()) { - std::string outputDir = it.second[0]->GetCurrentBinaryDirectory(); + std::string const& outputDir = it.second[0]->GetCurrentBinaryDirectory(); std::string projectName = it.second[0]->GetProjectName(); retval.push_back(projectName); std::string filename = outputDir + "/" + projectName + ".project"; @@ -184,7 +184,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps( void cmExtraCodeLiteGenerator::CreateProjectFile( const std::vector<cmLocalGenerator*>& lgs) { - std::string outputDir = lgs[0]->GetCurrentBinaryDirectory(); + std::string const& outputDir = lgs[0]->GetCurrentBinaryDirectory(); std::string projectName = lgs[0]->GetProjectName(); std::string filename = outputDir + "/"; @@ -249,7 +249,7 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile( const std::vector<cmLocalGenerator*>& lgs, const std::string& filename) { const cmMakefile* mf = lgs[0]->GetMakefile(); - cmGeneratedFileStream fout(filename.c_str()); + cmGeneratedFileStream fout(filename); if (!fout) { return; } @@ -547,7 +547,7 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile( const cmGeneratorTarget* gt, const std::string& filename) { const cmMakefile* mf = gt->Makefile; - cmGeneratedFileStream fout(filename.c_str()); + cmGeneratedFileStream fout(filename); if (!fout) { return; } @@ -599,7 +599,7 @@ std::string cmExtraCodeLiteGenerator::GetCodeLiteCompilerName( compilerIdVar = "CMAKE_C_COMPILER_ID"; } - std::string compilerId = mf->GetSafeDefinition(compilerIdVar); + std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar); std::string compiler = "gnu g++"; // default to g++ // Since we need the compiler for parsing purposes only diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 14448f578..34f58adff 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -98,7 +98,7 @@ void cmExtraEclipseCDT4Generator::Generate() std::string eclipseVersion = mf->GetSafeDefinition("CMAKE_ECLIPSE_VERSION"); cmsys::RegularExpression regex(".*([0-9]+\\.[0-9]+).*"); - if (regex.find(eclipseVersion.c_str())) { + if (regex.find(eclipseVersion)) { unsigned int majorVersion = 0; unsigned int minorVersion = 0; int res = @@ -176,7 +176,7 @@ void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() this->GetPathBasename(this->HomeDirectory)); const std::string filename = this->HomeDirectory + "/.project"; - cmGeneratedFileStream fout(filename.c_str()); + cmGeneratedFileStream fout(filename); if (!fout) { return; } @@ -215,7 +215,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, std::string cacheEntryName = "CMAKE_ECLIPSE_ENVVAR_"; cacheEntryName += envVar; - const char* cacheValue = + const std::string* cacheValue = lg->GetState()->GetInitializedCacheValue(cacheEntryName); // now we have both, decide which one to use @@ -232,14 +232,14 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory()); } else if (!envVarSet && cacheValue != nullptr) { // It is already in the cache, but not in the env, so use it from the cache - valueToUse = cacheValue; + valueToUse = *cacheValue; } else { // It is both in the cache and in the env. // Use the version from the env. except if the value from the env is // completely contained in the value from the cache (for the case that we // now have a PATH without MSVC dirs in the env. but had the full PATH with // all MSVC dirs during the cmake run which stored the var in the cache: - valueToUse = cacheValue; + valueToUse = *cacheValue; if (valueToUse.find(envVarValue) == std::string::npos) { valueToUse = envVarValue; mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), @@ -261,7 +261,7 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() const std::string filename = this->HomeOutputDirectory + "/.project"; - cmGeneratedFileStream fout(filename.c_str()); + cmGeneratedFileStream fout(filename); if (!fout) { return; } @@ -555,7 +555,7 @@ void cmExtraEclipseCDT4Generator::AppendIncludeDirectories( // Frameworks/ part has to be stripped // /System/Library/Frameworks/GLUT.framework/Headers cmsys::RegularExpression frameworkRx("(.+/Frameworks)/.+\\.framework/"); - if (frameworkRx.find(dir.c_str())) { + if (frameworkRx.find(dir)) { dir = frameworkRx.match(1); } @@ -582,7 +582,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const const std::string filename = this->HomeOutputDirectory + "/.cproject"; - cmGeneratedFileStream fout(filename.c_str()); + cmGeneratedFileStream fout(filename); if (!fout) { return; } diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index df1871536..f5c4c93e4 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -58,7 +58,7 @@ void cmExtraKateGenerator::CreateKateProjectFile( { std::string filename = lg->GetBinaryDirectory(); filename += "/.kateproject"; - cmGeneratedFileStream fout(filename.c_str()); + cmGeneratedFileStream fout(filename); if (!fout) { return; } @@ -215,7 +215,7 @@ void cmExtraKateGenerator::CreateDummyKateProjectFile( filename += "/"; filename += this->ProjectName; filename += ".kateproject"; - cmGeneratedFileStream fout(filename.c_str()); + cmGeneratedFileStream fout(filename); if (!fout) { return; } diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index fb85a6882..c4cca072b 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -91,7 +91,7 @@ void cmExtraSublimeTextGenerator::CreateNewProjectFile( { const cmMakefile* mf = lgs[0]->GetMakefile(); - cmGeneratedFileStream fout(filename.c_str()); + cmGeneratedFileStream fout(filename); if (!fout) { return; } @@ -354,8 +354,8 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject( lg->GetTargetCompileFlags(gtgt, config, language, flags); // Add source file specific flags. - cmGeneratorExpressionInterpreter genexInterpreter(lg, gtgt, config, - gtgt->GetName(), language); + cmGeneratorExpressionInterpreter genexInterpreter(lg, config, gtgt, + language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) { @@ -381,8 +381,8 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines( cmMakefile* makefile = lg->GetMakefile(); const std::string& language = source->GetLanguage(); const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - cmGeneratorExpressionInterpreter genexInterpreter( - lg, target, config, target->GetName(), language); + cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, + language); // Add the export symbol definition for shared library objects. if (const char* exportMacro = target->GetExportMacro()) { @@ -419,8 +419,8 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes( cmMakefile* makefile = lg->GetMakefile(); const std::string& language = source->GetLanguage(); const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - cmGeneratorExpressionInterpreter genexInterpreter( - lg, target, config, target->GetName(), language); + cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, + language); // Add include directories for this source file const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index 03d1ad1f6..effb4460a 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -23,7 +23,7 @@ bool cmFLTKWrapUICommand::InitialPass(std::vector<std::string> const& args, // what is the current source dir std::string cdir = this->Makefile->GetCurrentSourceDirectory(); - const char* fluid_exe = + std::string const& fluid_exe = this->Makefile->GetRequiredDefinition("FLTK_FLUID_EXECUTABLE"); // get parameter for the command diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index dcb79f7dd..1f7670309 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -7,9 +7,10 @@ #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" -#include "cmsys/String.hxx" + #include <algorithm> #include <assert.h> +#include <ctype.h> #include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> @@ -207,16 +208,20 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args, cmSystemTools::MakeDirectory(dir); mode_t mode = 0; + bool writable = false; // Set permissions to writable if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) { - cmSystemTools::SetPermissions(fileName.c_str(), #if defined(_MSC_VER) || defined(__MINGW32__) - mode | S_IWRITE + writable = mode & S_IWRITE; + mode_t newMode = mode | S_IWRITE; #else - mode | S_IWUSR | S_IWGRP + writable = mode & S_IWUSR; + mode_t newMode = mode | S_IWUSR | S_IWGRP; #endif - ); + if (!writable) { + cmSystemTools::SetPermissions(fileName.c_str(), newMode); + } } // If GetPermissions fails, pretend like it is ok. File open will fail if // the file is not writable @@ -241,7 +246,7 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args, return false; } file.close(); - if (mode) { + if (mode && !writable) { cmSystemTools::SetPermissions(fileName.c_str(), mode); } return true; @@ -609,8 +614,8 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) continue; } - if ((c >= 0x20 && c < 0x7F) || c == '\t' || - (c == '\n' && newline_consume)) { + if (c >= 0 && c <= 0xFF && + (isprint(c) || c == '\t' || (c == '\n' && newline_consume))) { // This is an ASCII character that may be part of a string. // Cast added to avoid compiler warning. Cast is ok because // c is guaranteed to fit in char by the above if... @@ -658,7 +663,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) // The current line has been terminated. Check if the current // string matches the requirements. The length may now be as // low as zero since blank lines are allowed. - if (s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) { + if (s.length() >= minlen && (!have_regex || regex.find(s))) { output_size += static_cast<int>(s.size()) + 1; if (limit_output >= 0 && output_size >= limit_output) { s.clear(); @@ -674,7 +679,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) // string matches the requirements. We require that the length // be at least one no matter what the user specified. if (s.length() >= minlen && !s.empty() && - (!have_regex || regex.find(s.c_str()))) { + (!have_regex || regex.find(s))) { output_size += static_cast<int>(s.size()) + 1; if (limit_output >= 0 && output_size >= limit_output) { s.clear(); @@ -691,7 +696,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) if (maxlen > 0 && s.size() == maxlen) { // Terminate a string if the maximum length is reached. - if (s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) { + if (s.length() >= minlen && (!have_regex || regex.find(s))) { output_size += static_cast<int>(s.size()) + 1; if (limit_output >= 0 && output_size >= limit_output) { s.clear(); @@ -707,7 +712,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) // input file or the input size limit. Check if the current string // matches the requirements. if ((!limit_count || strings.size() < limit_count) && !s.empty() && - s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) { + s.length() >= minlen && (!have_regex || regex.find(s))) { output_size += static_cast<int>(s.size()) + 1; if (limit_output < 0 || output_size < limit_output) { strings.push_back(s); @@ -779,10 +784,10 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, if (*i == "LIST_DIRECTORIES") { ++i; // skip LIST_DIRECTORIES if (i != args.end()) { - if (cmSystemTools::IsOn(i->c_str())) { + if (cmSystemTools::IsOn(*i)) { g.SetListDirs(true); g.SetRecurseListDirs(true); - } else if (cmSystemTools::IsOff(i->c_str())) { + } else if (cmSystemTools::IsOff(*i)) { g.SetListDirs(false); g.SetRecurseListDirs(false); } else { @@ -1270,6 +1275,33 @@ protected: this->DirPermissions |= mode_world_read; this->DirPermissions |= mode_world_execute; } + + bool GetDefaultDirectoryPermissions(mode_t** mode) + { + // check if default dir creation permissions were set + const char* default_dir_install_permissions = + this->Makefile->GetDefinition( + "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); + if (default_dir_install_permissions && *default_dir_install_permissions) { + std::vector<std::string> items; + cmSystemTools::ExpandListArgument(default_dir_install_permissions, + items); + for (const auto& arg : items) { + if (!this->CheckPermissions(arg, **mode)) { + std::ostringstream e; + e << this->FileCommand->GetError() + << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS " + "variable."; + this->FileCommand->SetError(e.str()); + return false; + } + } + } else { + *mode = nullptr; + } + + return true; + } }; bool cmFileCopier::Parse(std::vector<std::string> const& args) @@ -1663,8 +1695,15 @@ bool cmFileCopier::InstallDirectory(const char* source, this->ReportCopy(destination, TypeDir, !cmSystemTools::FileIsDirectory(destination)); + // check if default dir creation permissions were set + mode_t default_dir_mode_v = 0; + mode_t* default_dir_mode = &default_dir_mode_v; + if (!this->GetDefaultDirectoryPermissions(&default_dir_mode)) { + return false; + } + // Make sure the destination directory exists. - if (!cmSystemTools::MakeDirectory(destination)) { + if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) { std::ostringstream e; e << this->Name << " cannot make directory \"" << destination << "\": " << cmSystemTools::GetLastSystemError(); @@ -1751,7 +1790,7 @@ struct cmFileInstaller : public cmFileCopier // Check whether to copy files always or only if they have changed. std::string install_always; if (cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS", install_always)) { - this->Always = cmSystemTools::IsOn(install_always.c_str()); + this->Always = cmSystemTools::IsOn(install_always); } // Get the current manifest. this->Manifest = @@ -2068,23 +2107,9 @@ bool cmFileInstaller::HandleInstallDestination() // check if default dir creation permissions were set mode_t default_dir_mode_v = 0; - mode_t* default_dir_mode = nullptr; - const char* default_dir_install_permissions = this->Makefile->GetDefinition( - "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); - if (default_dir_install_permissions && *default_dir_install_permissions) { - std::vector<std::string> items; - cmSystemTools::ExpandListArgument(default_dir_install_permissions, items); - for (const auto& arg : items) { - if (!this->CheckPermissions(arg, default_dir_mode_v)) { - std::ostringstream e; - e << this->FileCommand->GetError() - << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable."; - this->FileCommand->SetError(e.str()); - return false; - } - } - - default_dir_mode = &default_dir_mode_v; + mode_t* default_dir_mode = &default_dir_mode_v; + if (!this->GetDefaultDirectoryPermissions(&default_dir_mode)) { + return false; } if (this->InstallType != cmInstallType_DIRECTORY) { @@ -2484,11 +2509,11 @@ bool cmFileCommand::HandleCMakePathCommand( #else char pathSep = ':'; #endif - std::vector<cmsys::String> path = cmSystemTools::SplitString(*i, pathSep); + std::vector<std::string> path = cmSystemTools::SplitString(*i, pathSep); i++; const char* var = i->c_str(); std::string value; - for (std::vector<cmsys::String>::iterator j = path.begin(); j != path.end(); + for (std::vector<std::string>::iterator j = path.begin(); j != path.end(); ++j) { if (j != path.begin()) { value += ";"; @@ -2498,7 +2523,7 @@ bool cmFileCommand::HandleCMakePathCommand( } else { *j = cmSystemTools::ConvertToOutputPath(*j); // remove double quotes in the path - cmsys::String& s = *j; + std::string& s = *j; if (s.size() > 1 && s[0] == '\"' && s[s.size() - 1] == '\"') { s = s.substr(1, s.size() - 2); @@ -2742,7 +2767,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) } else if (*i == "TLS_VERIFY") { ++i; if (i != args.end()) { - tls_verify = cmSystemTools::IsOn(i->c_str()); + tls_verify = cmSystemTools::IsOn(*i); } else { this->SetError("TLS_VERIFY missing bool value."); return false; @@ -2881,6 +2906,10 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); check_curl_result(res, "DOWNLOAD cannot set url: "); + // enable auth + res = ::curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + check_curl_result(res, "DOWNLOAD cannot set httpauth: "); + // enable HTTP ERROR parsing res = ::curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); check_curl_result(res, "DOWNLOAD cannot set http failure option: "); @@ -3180,6 +3209,10 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) res = ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); check_curl_result(res, "UPLOAD cannot set url: "); + // enable auth + res = ::curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + check_curl_result(res, "UPLOAD cannot set httpauth: "); + res = ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cmWriteToMemoryCallback); check_curl_result(res, "UPLOAD cannot set write function: "); @@ -3458,7 +3491,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) } if (!cmsys::SystemTools::FileIsFullPath(path)) { - path = this->Makefile->GetCurrentSourceDirectory() + ("/" + path); + path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; } // Unify path (remove '//', '/../', ...) diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 02bae828b..1e1ab147f 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -236,9 +236,9 @@ cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf) this->GG = this->Makefile->GetGlobalGenerator(); // Collect the list of library name prefixes/suffixes to try. - const char* prefixes_list = + std::string const& prefixes_list = this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_PREFIXES"); - const char* suffixes_list = + std::string const& suffixes_list = this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_SUFFIXES"); cmSystemTools::ExpandListArgument(prefixes_list, this->Prefixes, true); cmSystemTools::ExpandListArgument(suffixes_list, this->Suffixes, true); diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 7ac0cdff0..96de6adce 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -337,7 +337,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, return false; } this->Configs.push_back(args[i]); - } else if (!haveVersion && version.find(args[i].c_str())) { + } else if (!haveVersion && version.find(args[i])) { haveVersion = true; this->Version = args[i]; } else { @@ -487,7 +487,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, this->SetModuleVariables(components); - // See if there is a Find<package>.cmake module. + // See if there is a Find<PackageName>.cmake module. if (this->UseFindModules) { bool foundModule = false; if (!this->FindModule(foundModule)) { @@ -538,7 +538,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, } // No find module. Assume the project has a CMake config file. Use - // a <package>_DIR cache variable to locate it. + // a <PackageName>_DIR cache variable to locate it. this->Variable = this->Name; this->Variable += "_DIR"; diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index d8c7ab312..48f17ef11 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -7,6 +7,7 @@ #include "cm_kwiml.h" #include <cstddef> +#include <functional> #include <map> #include <set> #include <string> @@ -15,14 +16,12 @@ // IWYU insists we should forward-declare instead of including <functional>, // but we cannot forward-declare reliably because some C++ standard libraries // put the template in an inline namespace. -#ifdef CMAKE_IWYU +#ifdef CMAKE_IWYU_FORWARD_STD_HASH /* clang-format off */ namespace std { template <class T> struct hash; } /* clang-format on */ -#else -# include <functional> #endif #include "cmFindCommon.h" diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 13a18e20f..db340772f 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -34,6 +34,9 @@ struct cmFindProgramHelper // Current names under consideration. std::vector<std::string> Names; + // Current name with extension under consideration. + std::string TestNameExt; + // Current full path under consideration. std::string TestPath; @@ -43,6 +46,19 @@ struct cmFindProgramHelper this->Names.clear(); this->AddName(name); } + bool CheckCompoundNames() + { + for (std::string const& n : this->Names) { + // Only perform search relative to current directory if the file name + // contains a directory separator. + if (n.find('/') != std::string::npos) { + if (this->CheckDirectoryForName("", n)) { + return true; + } + } + } + return false; + } bool CheckDirectory(std::string const& path) { for (std::string const& n : this->Names) { @@ -55,14 +71,16 @@ struct cmFindProgramHelper bool CheckDirectoryForName(std::string const& path, std::string const& name) { for (std::string const& ext : this->Extensions) { - this->TestPath = path; - this->TestPath += name; if (!ext.empty() && cmSystemTools::StringEndsWith(name, ext.c_str())) { continue; } - this->TestPath += ext; + this->TestNameExt = name; + this->TestNameExt += ext; + this->TestPath = + cmSystemTools::CollapseCombinedPath(path, this->TestNameExt); + if (cmSystemTools::FileExists(this->TestPath, true)) { - this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath); + this->BestPath = this->TestPath; return true; } } @@ -145,8 +163,8 @@ std::string cmFindProgramCommand::FindNormalProgramNamesPerDir() helper.AddName(n); } - // Check for the names themselves (e.g. absolute paths). - if (helper.CheckDirectory(std::string())) { + // Check for the names themselves if they contain a directory separator. + if (helper.CheckCompoundNames()) { return helper.BestPath; } @@ -168,8 +186,8 @@ std::string cmFindProgramCommand::FindNormalProgramDirsPerName() // Switch to searching for this name. helper.SetName(n); - // Check for the name by itself (e.g. an absolute path). - if (helper.CheckDirectory(std::string())) { + // Check for the names themselves if they contain a directory separator. + if (helper.CheckCompoundNames()) { return helper.BestPath; } diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 6bdf3a45c..186ec8c9e 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -24,8 +24,8 @@ cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding) #endif } -cmGeneratedFileStream::cmGeneratedFileStream(const char* name, bool quiet, - Encoding encoding) +cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name, + bool quiet, Encoding encoding) : cmGeneratedFileStreamBase(name) , Stream(TempName.c_str()) { @@ -54,7 +54,7 @@ cmGeneratedFileStream::~cmGeneratedFileStream() this->Okay = !this->fail(); } -cmGeneratedFileStream& cmGeneratedFileStream::Open(const char* name, +cmGeneratedFileStream& cmGeneratedFileStream::Open(std::string const& name, bool quiet, bool binaryFlag) { // Store the file name and construct the temporary file name. @@ -114,7 +114,7 @@ cmGeneratedFileStreamBase::cmGeneratedFileStreamBase() { } -cmGeneratedFileStreamBase::cmGeneratedFileStreamBase(const char* name) +cmGeneratedFileStreamBase::cmGeneratedFileStreamBase(std::string const& name) : Name() , TempName() , CopyIfDifferent(false) @@ -130,7 +130,7 @@ cmGeneratedFileStreamBase::~cmGeneratedFileStreamBase() this->Close(); } -void cmGeneratedFileStreamBase::Open(const char* name) +void cmGeneratedFileStreamBase::Open(std::string const& name) { // Save the original name of the file. this->Name = name; @@ -168,12 +168,12 @@ bool cmGeneratedFileStreamBase::Close() // destination atomically. if (this->Compress) { std::string gzname = this->TempName + ".temp.gz"; - if (this->CompressFile(this->TempName.c_str(), gzname.c_str())) { - this->RenameFile(gzname.c_str(), resname.c_str()); + if (this->CompressFile(this->TempName, gzname)) { + this->RenameFile(gzname, resname); } cmSystemTools::RemoveFile(gzname); } else { - this->RenameFile(this->TempName.c_str(), resname.c_str()); + this->RenameFile(this->TempName, resname); } replaced = true; @@ -188,10 +188,10 @@ bool cmGeneratedFileStreamBase::Close() } #ifdef CMAKE_BUILD_WITH_CMAKE -int cmGeneratedFileStreamBase::CompressFile(const char* oldname, - const char* newname) +int cmGeneratedFileStreamBase::CompressFile(std::string const& oldname, + std::string const& newname) { - gzFile gf = gzopen(newname, "w"); + gzFile gf = gzopen(newname.c_str(), "w"); if (!gf) { return 0; } @@ -214,16 +214,17 @@ int cmGeneratedFileStreamBase::CompressFile(const char* oldname, return 1; } #else -int cmGeneratedFileStreamBase::CompressFile(const char*, const char*) +int cmGeneratedFileStreamBase::CompressFile(std::string const&, + std::string const&) { return 0; } #endif -int cmGeneratedFileStreamBase::RenameFile(const char* oldname, - const char* newname) +int cmGeneratedFileStreamBase::RenameFile(std::string const& oldname, + std::string const& newname) { - return cmSystemTools::RenameFile(oldname, newname); + return cmSystemTools::RenameFile(oldname.c_str(), newname.c_str()); } void cmGeneratedFileStream::SetName(const std::string& fname) diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h index 48f93c52b..dacd16692 100644 --- a/Source/cmGeneratedFileStream.h +++ b/Source/cmGeneratedFileStream.h @@ -20,7 +20,7 @@ protected: cmGeneratedFileStreamBase(); // This constructor prepares the temporary output file. - cmGeneratedFileStreamBase(const char* name); + cmGeneratedFileStreamBase(std::string const& name); // The destructor renames the temporary output file to the real name. ~cmGeneratedFileStreamBase(); @@ -29,14 +29,14 @@ protected: // called before the real stream is opened. Close is always called // after the real stream is closed and Okay is set to whether the // real stream was still valid for writing when it was closed. - void Open(const char* name); + void Open(std::string const& name); bool Close(); // Internal file replacement implementation. - int RenameFile(const char* oldname, const char* newname); + int RenameFile(std::string const& oldname, std::string const& newname); // Internal file compression implementation. - int CompressFile(const char* oldname, const char* newname); + int CompressFile(std::string const& oldname, std::string const& newname); // The name of the final destination file for the output. std::string Name; @@ -87,7 +87,7 @@ public: * file cannot be opened an error message is produced unless the * second argument is set to true. */ - cmGeneratedFileStream(const char* name, bool quiet = false, + cmGeneratedFileStream(std::string const& name, bool quiet = false, Encoding encoding = codecvt::None); /** @@ -103,7 +103,7 @@ public: * temporary file. If the file cannot be opened an error message is * produced unless the second argument is set to true. */ - cmGeneratedFileStream& Open(const char* name, bool quiet = false, + cmGeneratedFileStream& Open(std::string const& name, bool quiet = false, bool binaryFlag = false); /** diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 64ec30ded..2727d9ae4 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -38,7 +38,7 @@ cmGeneratorExpression::~cmGeneratorExpression() { } -const char* cmCompiledGeneratorExpression::Evaluate( +const std::string& cmCompiledGeneratorExpression::Evaluate( cmLocalGenerator* lg, const std::string& config, bool quiet, const cmGeneratorTarget* headTarget, cmGeneratorExpressionDAGChecker* dagChecker, @@ -48,7 +48,7 @@ const char* cmCompiledGeneratorExpression::Evaluate( language); } -const char* cmCompiledGeneratorExpression::Evaluate( +const std::string& cmCompiledGeneratorExpression::Evaluate( cmLocalGenerator* lg, const std::string& config, bool quiet, const cmGeneratorTarget* headTarget, const cmGeneratorTarget* currentTarget, cmGeneratorExpressionDAGChecker* dagChecker, @@ -61,12 +61,12 @@ const char* cmCompiledGeneratorExpression::Evaluate( return this->EvaluateWithContext(context, dagChecker); } -const char* cmCompiledGeneratorExpression::EvaluateWithContext( +const std::string& cmCompiledGeneratorExpression::EvaluateWithContext( cmGeneratorExpressionContext& context, cmGeneratorExpressionDAGChecker* dagChecker) const { if (!this->NeedsEvaluation) { - return this->Input.c_str(); + return this->Input; } this->Output.clear(); @@ -97,8 +97,7 @@ const char* cmCompiledGeneratorExpression::EvaluateWithContext( this->DependTargets = context.DependTargets; this->AllTargetsSeen = context.AllTargets; - // TODO: Return a std::string from here instead? - return this->Output.c_str(); + return this->Output; } cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( @@ -169,7 +168,7 @@ static std::string stripAllGeneratorExpressions(const std::string& input) const char* c = input.c_str() + pos; const char* const cStart = c; for (; *c; ++c) { - if (c[0] == '$' && c[1] == '<') { + if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) { ++nestingLevel; ++c; continue; @@ -244,7 +243,7 @@ static std::string stripExportInterface( const char* c = input.c_str() + pos; const char* const cStart = c; for (; *c; ++c) { - if (c[0] == '$' && c[1] == '<') { + if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) { ++nestingLevel; ++c; continue; @@ -311,7 +310,7 @@ void cmGeneratorExpression::Split(const std::string& input, const char* c = input.c_str() + pos; const char* const cStart = c; for (; *c; ++c) { - if (c[0] == '$' && c[1] == '<') { + if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) { ++nestingLevel; ++c; continue; @@ -387,17 +386,19 @@ void cmCompiledGeneratorExpression::GetMaxLanguageStandard( } } -const char* cmGeneratorExpressionInterpreter::Evaluate( +const std::string& cmGeneratorExpressionInterpreter::Evaluate( const char* expression, const std::string& property) { - if (this->Target.empty()) { - return this->EvaluateExpression(expression); - } + this->CompiledGeneratorExpression = + this->GeneratorExpression.Parse(expression); // Specify COMPILE_OPTIONS to DAGchecker, same semantic as COMPILE_FLAGS cmGeneratorExpressionDAGChecker dagChecker( - this->Target, property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, - nullptr, nullptr); + this->HeadTarget, + property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, nullptr, + nullptr); - return this->EvaluateExpression(expression, &dagChecker); + return this->CompiledGeneratorExpression->Evaluate( + this->LocalGenerator, this->Config, false, this->HeadTarget, &dagChecker, + this->Language); } diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 9fd53c67e..9c05f60c8 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -63,6 +63,15 @@ public: static std::string StripEmptyListElements(const std::string& input); + static inline bool StartsWithGeneratorExpression(const std::string& input) + { + return input.length() >= 2 && input[0] == '$' && input[1] == '<'; + } + static inline bool StartsWithGeneratorExpression(const char* input) + { + return input != nullptr && input[0] == '$' && input[1] == '<'; + } + private: cmListFileBacktrace Backtrace; }; @@ -72,16 +81,17 @@ class cmCompiledGeneratorExpression CM_DISABLE_COPY(cmCompiledGeneratorExpression) public: - const char* Evaluate(cmLocalGenerator* lg, const std::string& config, - bool quiet = false, - cmGeneratorTarget const* headTarget = nullptr, - cmGeneratorTarget const* currentTarget = nullptr, - cmGeneratorExpressionDAGChecker* dagChecker = nullptr, - std::string const& language = std::string()) const; - const char* Evaluate(cmLocalGenerator* lg, const std::string& config, - bool quiet, cmGeneratorTarget const* headTarget, - cmGeneratorExpressionDAGChecker* dagChecker, - std::string const& language = std::string()) const; + const std::string& Evaluate( + cmLocalGenerator* lg, const std::string& config, bool quiet = false, + cmGeneratorTarget const* headTarget = nullptr, + cmGeneratorTarget const* currentTarget = nullptr, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr, + std::string const& language = std::string()) const; + const std::string& Evaluate( + cmLocalGenerator* lg, const std::string& config, bool quiet, + cmGeneratorTarget const* headTarget, + cmGeneratorExpressionDAGChecker* dagChecker, + std::string const& language = std::string()) const; /** Get set of targets found during evaluations. */ std::set<cmGeneratorTarget*> const& GetTargets() const @@ -126,7 +136,7 @@ public: std::map<std::string, std::string>& mapping); private: - const char* EvaluateWithContext( + const std::string& EvaluateWithContext( cmGeneratorExpressionContext& context, cmGeneratorExpressionDAGChecker* dagChecker) const; @@ -159,82 +169,30 @@ class cmGeneratorExpressionInterpreter public: cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator, - cmGeneratorTarget* generatorTarget, - const std::string& config, - const std::string& target, - const std::string& lang) + std::string const& config, + cmGeneratorTarget const* headTarget, + std::string const& lang = std::string()) : LocalGenerator(localGenerator) - , GeneratorTarget(generatorTarget) , Config(config) - , Target(target) + , HeadTarget(headTarget) , Language(lang) { } - cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator, - cmGeneratorTarget* generatorTarget, - const std::string& config) - : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget, config, - std::string(), std::string()) - { - } - const char* Evaluate(const char* expression) - { - return this->EvaluateExpression(expression); - } - const char* Evaluate(const std::string& expression) - { - return this->Evaluate(expression.c_str()); - } - const char* Evaluate(const char* expression, const std::string& property); - const char* Evaluate(const std::string& expression, - const std::string& property) + const std::string& Evaluate(const char* expression, + const std::string& property); + const std::string& Evaluate(const std::string& expression, + const std::string& property) { return this->Evaluate(expression.c_str(), property); } protected: - cmGeneratorExpression& GetGeneratorExpression() - { - return this->GeneratorExpression; - } - - cmCompiledGeneratorExpression& GetCompiledGeneratorExpression() - { - return *(this->CompiledGeneratorExpression); - } - - cmLocalGenerator* GetLocalGenerator() { return this->LocalGenerator; } - - cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; } - - const std::string& GetTargetName() const { return this->Target; } - const std::string& GetLanguage() const { return this->Language; } - - const char* EvaluateExpression( - const char* expression, - cmGeneratorExpressionDAGChecker* dagChecker = nullptr) - { - this->CompiledGeneratorExpression = - this->GeneratorExpression.Parse(expression); - - if (dagChecker == nullptr) { - return this->CompiledGeneratorExpression->Evaluate( - this->LocalGenerator, this->Config, false, this->GeneratorTarget); - } - - return this->CompiledGeneratorExpression->Evaluate( - this->LocalGenerator, this->Config, false, this->GeneratorTarget, - dagChecker, this->Language); - } - -private: cmGeneratorExpression GeneratorExpression; std::unique_ptr<cmCompiledGeneratorExpression> CompiledGeneratorExpression; cmLocalGenerator* LocalGenerator = nullptr; - cmGeneratorTarget* GeneratorTarget = nullptr; std::string Config; - std::string Target; + cmGeneratorTarget const* HeadTarget = nullptr; std::string Language; }; diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index face28228..8d57441c3 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -14,7 +14,7 @@ #include <utility> cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( - const cmListFileBacktrace& backtrace, const std::string& target, + const cmListFileBacktrace& backtrace, cmGeneratorTarget const* target, const std::string& property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent) : Parent(parent) @@ -28,7 +28,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( } cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( - const std::string& target, const std::string& property, + cmGeneratorTarget const* target, const std::string& property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent) : Parent(parent) @@ -58,8 +58,8 @@ void cmGeneratorExpressionDAGChecker::Initialize() TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(clang-tidy) #undef TEST_TRANSITIVE_PROPERTY_METHOD { - std::map<std::string, std::set<std::string>>::const_iterator it = - top->Seen.find(this->Target); + std::map<cmGeneratorTarget const*, std::set<std::string>>::const_iterator + it = top->Seen.find(this->Target); if (it != top->Seen.end()) { const std::set<std::string>& propSet = it->second; if (propSet.find(this->Property) != propSet.end()) { @@ -166,7 +166,8 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression() return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL"; } -bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt) +bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries( + cmGeneratorTarget const* tgt) { const cmGeneratorExpressionDAGChecker* top = this; const cmGeneratorExpressionDAGChecker* parent = this->Parent; @@ -189,7 +190,7 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt) strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0; } -std::string cmGeneratorExpressionDAGChecker::TopTarget() const +cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const { const cmGeneratorExpressionDAGChecker* top = this; const cmGeneratorExpressionDAGChecker* parent = this->Parent; diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index a3a8f69c3..a5134c315 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -13,6 +13,7 @@ struct GeneratorExpressionContent; struct cmGeneratorExpressionContext; +class cmGeneratorTarget; #define CM_SELECT_BOTH(F, A1, A2) F(A1, A2) #define CM_SELECT_FIRST(F, A1, A2) F(A1) @@ -25,7 +26,10 @@ struct cmGeneratorExpressionContext; SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS) \ SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) \ SELECT(F, EvaluatingSources, SOURCES) \ - SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES) + SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES) \ + SELECT(F, EvaluatingLinkOptions, LINK_OPTIONS) \ + SELECT(F, EvaluatingLinkDirectories, LINK_DIRECTORIES) \ + SELECT(F, EvaluatingLinkDepends, LINK_DEPENDS) #define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \ CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH) @@ -39,11 +43,11 @@ struct cmGeneratorExpressionContext; struct cmGeneratorExpressionDAGChecker { cmGeneratorExpressionDAGChecker(const cmListFileBacktrace& backtrace, - const std::string& target, + cmGeneratorTarget const* target, const std::string& property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent); - cmGeneratorExpressionDAGChecker(const std::string& target, + cmGeneratorExpressionDAGChecker(cmGeneratorTarget const* target, const std::string& property, const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* parent); @@ -62,7 +66,7 @@ struct cmGeneratorExpressionDAGChecker const std::string& expr); bool EvaluatingGenexExpression(); - bool EvaluatingLinkLibraries(const char* tgt = nullptr); + bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr); #define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const; @@ -73,7 +77,7 @@ struct cmGeneratorExpressionDAGChecker bool GetTransitivePropertiesOnly(); void SetTransitivePropertiesOnly() { this->TransitivePropertiesOnly = true; } - std::string TopTarget() const; + cmGeneratorTarget const* TopTarget() const; private: Result CheckGraph() const; @@ -81,9 +85,9 @@ private: private: const cmGeneratorExpressionDAGChecker* const Parent; - const std::string Target; + cmGeneratorTarget const* Target; const std::string Property; - std::map<std::string, std::set<std::string>> Seen; + std::map<cmGeneratorTarget const*, std::set<std::string>> Seen; const GeneratorExpressionContent* const Content; const cmListFileBacktrace Backtrace; Result CheckResult; diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index 99b926126..e7a55e054 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -55,7 +55,7 @@ void cmGeneratorExpressionEvaluationFile::Generate( std::string outputFileName = this->OutputFileExpr->Evaluate( lg, config, false, nullptr, nullptr, nullptr, lang); - const std::string outputContent = inputExpression->Evaluate( + const std::string& outputContent = inputExpression->Evaluate( lg, config, false, nullptr, nullptr, nullptr, lang); if (cmSystemTools::FileIsFullPath(outputFileName)) { @@ -85,7 +85,7 @@ void cmGeneratorExpressionEvaluationFile::Generate( this->Files.push_back(outputFileName); outputFiles[outputFileName] = outputContent; - cmGeneratedFileStream fout(outputFileName.c_str()); + cmGeneratedFileStream fout(outputFileName); fout.SetCopyIfDifferent(true); fout << outputContent; if (fout.Close() && perm) { diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 1594904e7..f901215e3 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -156,7 +156,7 @@ static const struct BoolNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* /*content*/, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0"; + return !cmSystemTools::IsOff(*parameters.begin()) ? "1" : "0"; } } boolNode; @@ -378,8 +378,8 @@ protected: { if (context->HeadTarget) { cmGeneratorExpressionDAGChecker dagChecker( - context->Backtrace, context->HeadTarget->GetName(), genexOperator, - content, dagCheckerParent); + context->Backtrace, context->HeadTarget, genexOperator, content, + dagCheckerParent); switch (dagChecker.Check()) { case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: { @@ -580,10 +580,11 @@ struct CompilerIdNode : public cmGeneratorExpressionNode cmGeneratorExpressionDAGChecker* /*unused*/, const std::string& lang) const { - const char* compilerId = context->LG->GetMakefile()->GetSafeDefinition( - "CMAKE_" + lang + "_COMPILER_ID"); + std::string const& compilerId = + context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang + + "_COMPILER_ID"); if (parameters.empty()) { - return compilerId ? compilerId : ""; + return compilerId; } static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$"); if (!compilerIdValidator.find(*parameters.begin())) { @@ -591,15 +592,16 @@ struct CompilerIdNode : public cmGeneratorExpressionNode "Expression syntax not recognized."); return std::string(); } - if (!compilerId) { + if (compilerId.empty()) { return parameters.front().empty() ? "1" : "0"; } - if (strcmp(parameters.begin()->c_str(), compilerId) == 0) { + if (strcmp(parameters.begin()->c_str(), compilerId.c_str()) == 0) { return "1"; } - if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0) { + if (cmsysString_strcasecmp(parameters.begin()->c_str(), + compilerId.c_str()) == 0) { switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) { case cmPolicies::WARN: { std::ostringstream e; @@ -676,11 +678,11 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode cmGeneratorExpressionDAGChecker* /*unused*/, const std::string& lang) const { - const char* compilerVersion = + std::string const& compilerVersion = context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_VERSION"); if (parameters.empty()) { - return compilerVersion ? compilerVersion : ""; + return compilerVersion; } static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$"); @@ -689,13 +691,13 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode "Expression syntax not recognized."); return std::string(); } - if (!compilerVersion) { + if (compilerVersion.empty()) { return parameters.front().empty() ? "1" : "0"; } return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, parameters.begin()->c_str(), - compilerVersion) + compilerVersion.c_str()) ? "1" : "0"; } @@ -757,17 +759,17 @@ struct PlatformIdNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* /*content*/, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - const char* platformId = + std::string const& platformId = context->LG->GetMakefile()->GetSafeDefinition("CMAKE_SYSTEM_NAME"); if (parameters.empty()) { - return platformId ? platformId : ""; + return platformId; } - if (!platformId) { + if (platformId.empty()) { return parameters.front().empty() ? "1" : "0"; } - if (strcmp(parameters.begin()->c_str(), platformId) == 0) { + if (*parameters.begin() == platformId) { return "1"; } return "0"; @@ -1054,7 +1056,9 @@ std::string getLinkedTargetsContent( // Don't follow such link interface entries so as not to create a // self-referencing loop. if (l.Target && l.Target != target) { - depString += sep + "$<TARGET_PROPERTY:" + l.Target->GetName() + "," + + std::string uniqueName = + target->GetGlobalGenerator()->IndexGeneratorTargetUniquely(l.Target); + depString += sep + "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + interfacePropertyName + ">"; sep = ";"; } @@ -1126,7 +1130,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode std::string targetName = parameters.front(); propertyName = parameters[1]; if (!cmGeneratorExpression::IsValidTargetName(targetName)) { - if (!propertyNameValidator.find(propertyName.c_str())) { + if (!propertyNameValidator.find(propertyName)) { ::reportError(context, content->GetOriginalExpression(), "Target name and property name not supported."); return std::string(); @@ -1196,9 +1200,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return target->GetLinkerLanguage(context->Config); } - cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, - target->GetName(), propertyName, - content, dagCheckerParent); + cmGeneratorExpressionDAGChecker dagChecker( + context->Backtrace, target, propertyName, content, dagCheckerParent); switch (dagChecker.Check()) { case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: @@ -1911,9 +1914,9 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode return std::string(); } if (dagChecker && - (dagChecker->EvaluatingLinkLibraries(name.c_str()) || + (dagChecker->EvaluatingLinkLibraries(target) || (dagChecker->EvaluatingSources() && - name == dagChecker->TopTarget()))) { + target == dagChecker->TopTarget()))) { ::reportError(context, content->GetOriginalExpression(), "Expressions which require the linker language may not " "be used while evaluating link libraries"); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 9918b8787..5c294f8c4 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -102,6 +102,8 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) , DebugCompileOptionsDone(false) , DebugCompileFeaturesDone(false) , DebugCompileDefinitionsDone(false) + , DebugLinkOptionsDone(false) + , DebugLinkDirectoriesDone(false) , DebugSourcesDone(false) , LinkImplementationLanguageIsContextDependent(true) , UtilityItemsDone(false) @@ -128,13 +130,20 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) t->GetCompileDefinitionsBacktraces(), this->CompileDefinitionsEntries); + CreatePropertyGeneratorExpressions(t->GetLinkOptionsEntries(), + t->GetLinkOptionsBacktraces(), + this->LinkOptionsEntries); + + CreatePropertyGeneratorExpressions(t->GetLinkDirectoriesEntries(), + t->GetLinkDirectoriesBacktraces(), + this->LinkDirectoriesEntries); + CreatePropertyGeneratorExpressions(t->GetSourceEntries(), t->GetSourceBacktraces(), this->SourceEntries, true); this->DLLPlatform = - strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"), - "") != 0; + !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); this->PolicyMap = t->PolicyMap; } @@ -145,6 +154,8 @@ cmGeneratorTarget::~cmGeneratorTarget() cmDeleteAll(this->CompileOptionsEntries); cmDeleteAll(this->CompileFeaturesEntries); cmDeleteAll(this->CompileDefinitionsEntries); + cmDeleteAll(this->LinkOptionsEntries); + cmDeleteAll(this->LinkDirectoriesEntries); cmDeleteAll(this->SourceEntries); cmDeleteAll(this->LinkInformation); } @@ -215,6 +226,15 @@ const char* cmGeneratorTarget::GetProperty(const std::string& prop) const return this->Target->GetProperty(prop); } +const char* cmGeneratorTarget::GetSafeProperty(const std::string& prop) const +{ + const char* ret = this->GetProperty(prop); + if (!ret) { + return ""; + } + return ret; +} + const char* cmGeneratorTarget::GetOutputTargetType( cmStateEnums::ArtifactType artifact) const { @@ -656,9 +676,12 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const this->UtilityItemsDone = true; std::set<std::string> const& utilities = this->GetUtilities(); for (std::string const& i : utilities) { - cmGeneratorTarget* gt = - this->LocalGenerator->FindGeneratorTargetToUse(i); - this->UtilityItems.insert(cmLinkItem(i, gt)); + if (cmGeneratorTarget* gt = + this->LocalGenerator->FindGeneratorTargetToUse(i)) { + this->UtilityItems.insert(cmLinkItem(gt)); + } else { + this->UtilityItems.insert(cmLinkItem(i)); + } } } return this->UtilityItems; @@ -755,7 +778,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory( if (iter == this->SystemIncludesCache.end()) { cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr); + this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr); bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED"); @@ -801,7 +824,11 @@ static void AddInterfaceEntries( thisTarget->GetLinkImplementationLibraries(config)) { for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target) { - std::string genex = "$<TARGET_PROPERTY:" + lib + "," + prop + ">"; + std::string uniqueName = + thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely( + lib.Target); + std::string genex = + "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + prop + ">"; cmGeneratorExpression ge(lib.Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex); cge->SetEvaluateForBuildsystem(true); @@ -821,7 +848,10 @@ static void AddObjectEntries( for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target && lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { - std::string genex = "$<TARGET_OBJECTS:" + lib + ">"; + std::string uniqueName = + thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely( + lib.Target); + std::string genex = "$<TARGET_OBJECTS:" + std::move(uniqueName) + ">"; cmGeneratorExpression ge(lib.Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex); cge->SetEvaluateForBuildsystem(true); @@ -845,7 +875,7 @@ static bool processSources( for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { cmLinkImplItem const& item = entry->LinkImplItem; - std::string const& targetName = item; + std::string const& targetName = item.AsStr(); std::vector<std::string> entrySources; cmSystemTools::ExpandListArgument( entry->ge->Evaluate(tgt->GetLocalGenerator(), config, false, tgt, tgt, @@ -945,8 +975,8 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files, this->DebugSourcesDone = true; } - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "SOURCES", - nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr, + nullptr); std::unordered_set<std::string> uniqueSrcs; bool contextDependentDirectSources = @@ -1124,7 +1154,7 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, std::string cppFileName = xaml + ".cpp"; files.ExpectedXamlHeaders.insert(hFileName); files.ExpectedXamlSources.insert(cppFileName); - } else if (header_regex.find(sf->GetFullPath().c_str())) { + } else if (header_regex.find(sf->GetFullPath())) { kind = SourceKindHeader; } else { kind = SourceKindExtra; @@ -1680,11 +1710,6 @@ cmListFileBacktrace cmGeneratorTarget::GetBacktrace() const return this->Target->GetBacktrace(); } -const std::vector<std::string>& cmGeneratorTarget::GetLinkDirectories() const -{ - return this->Target->GetLinkDirectories(); -} - const std::set<std::string>& cmGeneratorTarget::GetUtilities() const { return this->Target->GetUtilities(); @@ -1741,7 +1766,7 @@ public: void Visit(cmLinkItem const& item) { if (!item.Target) { - if (item.find("::") != std::string::npos) { + if (item.AsStr().find("::") != std::string::npos) { bool noMessage = false; cmake::MessageType messageType = cmake::FATAL_ERROR; std::ostringstream e; @@ -1762,7 +1787,7 @@ public: if (!noMessage) { e << "Target \"" << this->Target->GetName() - << "\" links to target \"" << item + << "\" links to target \"" << item.AsStr() << "\" but the target was not found. Perhaps a find_package() " "call is missing for an IMPORTED target, or an ALIAS target is " "missing?"; @@ -2059,8 +2084,8 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result, } cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "AUTOUIC_OPTIONS", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr, + nullptr); cmSystemTools::ExpandListArgument( ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, this, &dagChecker), @@ -2462,7 +2487,7 @@ static void processIncludeDirectories( { for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { cmLinkImplItem const& item = entry->LinkImplItem; - std::string const& targetName = item; + std::string const& targetName = item.AsStr(); bool const fromImported = item.Target && item.Target->IsImported(); bool const checkCMP0027 = item.FromGenex; std::vector<std::string> entryIncludes; @@ -2541,7 +2566,7 @@ static void processIncludeDirectories( } } - if (!cmSystemTools::IsOff(entryInclude.c_str())) { + if (!cmSystemTools::IsOff(entryInclude)) { cmSystemTools::ConvertToUnixSlashes(entryInclude); } std::string inc = entryInclude; @@ -2569,8 +2594,8 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories( std::vector<std::string> includes; std::unordered_set<std::string> uniqueIncludes; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "INCLUDE_DIRECTORIES", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES", + nullptr, nullptr); std::vector<std::string> debugProperties; const char* debugProp = @@ -2600,7 +2625,7 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories( cmLinkImplementationLibraries const* impl = this->GetLinkImplementationLibraries(config); for (cmLinkImplItem const& lib : impl->Libraries) { - std::string libDir = cmSystemTools::CollapseFullPath(lib); + std::string libDir = cmSystemTools::CollapseFullPath(lib.AsStr()); static cmsys::RegularExpression frameworkCheck( "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); @@ -2633,7 +2658,7 @@ enum class OptionsParse Shell }; -static void processCompileOptionsInternal( +static void processOptionsInternal( cmGeneratorTarget const* tgt, const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, std::vector<std::string>& options, @@ -2665,7 +2690,7 @@ static void processCompileOptionsInternal( if (!usedOptions.empty()) { tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( cmake::LOG, - std::string("Used compile ") + logName + std::string(" for target ") + + std::string("Used ") + logName + std::string(" for target ") + tgt->GetName() + ":\n" + usedOptions, entry->ge->GetBacktrace()); } @@ -2680,9 +2705,9 @@ static void processCompileOptions( cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, bool debugOptions, std::string const& language) { - processCompileOptionsInternal(tgt, entries, options, uniqueOptions, - dagChecker, config, debugOptions, "options", - language, OptionsParse::Shell); + processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, + config, debugOptions, "compile options", language, + OptionsParse::Shell); } void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result, @@ -2691,8 +2716,8 @@ void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result, { std::unordered_set<std::string> uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "COMPILE_OPTIONS", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr, + nullptr); std::vector<std::string> debugProperties; const char* debugProp = @@ -2734,9 +2759,9 @@ static void processCompileFeatures( cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, bool debugOptions) { - processCompileOptionsInternal(tgt, entries, options, uniqueOptions, - dagChecker, config, debugOptions, "features", - std::string(), OptionsParse::None); + processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, + config, debugOptions, "compile features", + std::string(), OptionsParse::None); } void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result, @@ -2744,8 +2769,8 @@ void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result, { std::unordered_set<std::string> uniqueFeatures; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "COMPILE_FEATURES", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr, + nullptr); std::vector<std::string> debugProperties; const char* debugProp = @@ -2784,9 +2809,9 @@ static void processCompileDefinitions( cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, bool debugOptions, std::string const& language) { - processCompileOptionsInternal(tgt, entries, options, uniqueOptions, - dagChecker, config, debugOptions, - "definitions", language, OptionsParse::None); + processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, + config, debugOptions, "compile definitions", language, + OptionsParse::None); } void cmGeneratorTarget::GetCompileDefinitions( @@ -2795,8 +2820,8 @@ void cmGeneratorTarget::GetCompileDefinitions( { std::unordered_set<std::string> uniqueOptions; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "COMPILE_DEFINITIONS", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS", + nullptr, nullptr); std::vector<std::string> debugProperties; const char* debugProp = @@ -2855,6 +2880,356 @@ void cmGeneratorTarget::GetCompileDefinitions( cmDeleteAll(linkInterfaceCompileDefinitionsEntries); } +namespace { +void processLinkOptions( + cmGeneratorTarget const* tgt, + const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, + std::vector<std::string>& options, + std::unordered_set<std::string>& uniqueOptions, + cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, + bool debugOptions, std::string const& language) +{ + processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, + config, debugOptions, "link options", language, + OptionsParse::Shell); +} +} + +void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result, + const std::string& config, + const std::string& language) const +{ + std::unordered_set<std::string> uniqueOptions; + + cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr, + nullptr); + + std::vector<std::string> debugProperties; + const char* debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugOptions = !this->DebugLinkOptionsDone && + std::find(debugProperties.begin(), debugProperties.end(), + "LINK_OPTIONS") != debugProperties.end(); + + if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { + this->DebugLinkOptionsDone = true; + } + + processLinkOptions(this, this->LinkOptionsEntries, result, uniqueOptions, + &dagChecker, config, debugOptions, language); + + std::vector<cmGeneratorTarget::TargetPropertyEntry*> + linkInterfaceLinkOptionsEntries; + + AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", + linkInterfaceLinkOptionsEntries); + + processLinkOptions(this, linkInterfaceLinkOptionsEntries, result, + uniqueOptions, &dagChecker, config, debugOptions, + language); + + cmDeleteAll(linkInterfaceLinkOptionsEntries); + + // Last step: replace "LINKER:" prefixed elements by + // actual linker wrapper + const std::string wrapper(this->Makefile->GetSafeDefinition( + "CMAKE_" + language + "_LINKER_WRAPPER_FLAG")); + std::vector<std::string> wrapperFlag; + cmSystemTools::ExpandListArgument(wrapper, wrapperFlag); + const std::string wrapperSep(this->Makefile->GetSafeDefinition( + "CMAKE_" + language + "_LINKER_WRAPPER_FLAG_SEP")); + bool concatFlagAndArgs = true; + if (!wrapperFlag.empty() && wrapperFlag.back() == " ") { + concatFlagAndArgs = false; + wrapperFlag.pop_back(); + } + + const std::string LINKER{ "LINKER:" }; + const std::string SHELL{ "SHELL:" }; + const std::string LINKER_SHELL = LINKER + SHELL; + + std::vector<std::string>::iterator entry; + while ((entry = std::find_if(result.begin(), result.end(), + [&LINKER](const std::string& item) -> bool { + return item.compare(0, LINKER.length(), + LINKER) == 0; + })) != result.end()) { + std::vector<std::string> linkerOptions; + if (entry->compare(0, LINKER_SHELL.length(), LINKER_SHELL) == 0) { + cmSystemTools::ParseUnixCommandLine( + entry->c_str() + LINKER_SHELL.length(), linkerOptions); + } else { + linkerOptions = + cmSystemTools::tokenize(entry->substr(LINKER.length()), ","); + } + entry = result.erase(entry); + + if (linkerOptions.empty() || + (linkerOptions.size() == 1 && linkerOptions.front().empty())) { + continue; + } + + // for now, raise an error if prefix SHELL: is part of arguments + if (std::find_if(linkerOptions.begin(), linkerOptions.end(), + [&SHELL](const std::string& item) -> bool { + return item.find(SHELL) != std::string::npos; + }) != linkerOptions.end()) { + this->LocalGenerator->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, + "'SHELL:' prefix is not supported as part of 'LINKER:' arguments.", + this->GetBacktrace()); + return; + } + + if (wrapperFlag.empty()) { + // nothing specified, insert elements as is + result.insert(entry, linkerOptions.begin(), linkerOptions.end()); + } else { + std::vector<std::string> options; + + if (!wrapperSep.empty()) { + if (concatFlagAndArgs) { + // insert flag elements except last one + options.insert(options.end(), wrapperFlag.begin(), + wrapperFlag.end() - 1); + // concatenate last flag element and all LINKER list values + // in one option + options.push_back(wrapperFlag.back() + + cmJoin(linkerOptions, wrapperSep)); + } else { + options.insert(options.end(), wrapperFlag.begin(), + wrapperFlag.end()); + // concatenate all LINKER list values in one option + options.push_back(cmJoin(linkerOptions, wrapperSep)); + } + } else { + // prefix each element of LINKER list with wrapper + if (concatFlagAndArgs) { + std::transform( + linkerOptions.begin(), linkerOptions.end(), linkerOptions.begin(), + [&wrapperFlag](const std::string& value) -> std::string { + return wrapperFlag.back() + value; + }); + } + for (const auto& value : linkerOptions) { + options.insert(options.end(), wrapperFlag.begin(), + concatFlagAndArgs ? wrapperFlag.end() - 1 + : wrapperFlag.end()); + options.push_back(value); + } + } + result.insert(entry, options.begin(), options.end()); + } + } +} + +namespace { +void processStaticLibraryLinkOptions( + cmGeneratorTarget const* tgt, + const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, + std::vector<std::string>& options, + std::unordered_set<std::string>& uniqueOptions, + cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, + std::string const& language) +{ + processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, + config, false, "static library link options", + language, OptionsParse::Shell); +} +} + +void cmGeneratorTarget::GetStaticLibraryLinkOptions( + std::vector<std::string>& result, const std::string& config, + const std::string& language) const +{ + std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries; + std::unordered_set<std::string> uniqueOptions; + + cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS", + nullptr, nullptr); + + if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) { + std::vector<std::string> options; + cmGeneratorExpression ge; + cmSystemTools::ExpandListArgument(linkOptions, options); + for (const auto& option : options) { + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(option); + entries.push_back( + new cmGeneratorTarget::TargetPropertyEntry(std::move(cge))); + } + } + processStaticLibraryLinkOptions(this, entries, result, uniqueOptions, + &dagChecker, config, language); + + cmDeleteAll(entries); +} + +namespace { +void processLinkDirectories( + cmGeneratorTarget const* tgt, + const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, + std::vector<std::string>& directories, + std::unordered_set<std::string>& uniqueDirectories, + cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, + bool debugDirectories, std::string const& language) +{ + for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { + cmLinkImplItem const& item = entry->LinkImplItem; + std::string const& targetName = item.AsStr(); + + std::vector<std::string> entryDirectories; + cmSystemTools::ExpandListArgument( + entry->ge->Evaluate(tgt->GetLocalGenerator(), config, false, tgt, + dagChecker, language), + entryDirectories); + + std::string usedDirectories; + for (std::string& entryDirectory : entryDirectories) { + if (!cmSystemTools::FileIsFullPath(entryDirectory)) { + std::ostringstream e; + bool noMessage = false; + cmake::MessageType messageType = cmake::FATAL_ERROR; + if (!targetName.empty()) { + /* clang-format off */ + e << "Target \"" << targetName << "\" contains relative " + "path in its INTERFACE_LINK_DIRECTORIES:\n" + " \"" << entryDirectory << "\""; + /* clang-format on */ + } else { + switch (tgt->GetPolicyStatusCMP0081()) { + case cmPolicies::WARN: { + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0081) << "\n"; + messageType = cmake::AUTHOR_WARNING; + } break; + case cmPolicies::OLD: + noMessage = true; + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Issue the fatal message. + break; + } + e << "Found relative path while evaluating link directories of " + "\"" + << tgt->GetName() << "\":\n \"" << entryDirectory << "\"\n"; + } + if (!noMessage) { + tgt->GetLocalGenerator()->IssueMessage(messageType, e.str()); + if (messageType == cmake::FATAL_ERROR) { + return; + } + } + } + + // Sanitize the path the same way the link_directories command does + // in case projects set the LINK_DIRECTORIES property directly. + cmSystemTools::ConvertToUnixSlashes(entryDirectory); + if (uniqueDirectories.insert(entryDirectory).second) { + directories.push_back(entryDirectory); + if (debugDirectories) { + usedDirectories += " * " + entryDirectory + "\n"; + } + } + } + if (!usedDirectories.empty()) { + tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( + cmake::LOG, + std::string("Used link directories for target ") + tgt->GetName() + + ":\n" + usedDirectories, + entry->ge->GetBacktrace()); + } + } +} +} + +void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result, + const std::string& config, + const std::string& language) const +{ + std::unordered_set<std::string> uniqueDirectories; + + cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr, + nullptr); + + std::vector<std::string> debugProperties; + const char* debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugDirectories = !this->DebugLinkDirectoriesDone && + std::find(debugProperties.begin(), debugProperties.end(), + "LINK_DIRECTORIES") != debugProperties.end(); + + if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { + this->DebugLinkDirectoriesDone = true; + } + + processLinkDirectories(this, this->LinkDirectoriesEntries, result, + uniqueDirectories, &dagChecker, config, + debugDirectories, language); + + std::vector<cmGeneratorTarget::TargetPropertyEntry*> + linkInterfaceLinkDirectoriesEntries; + + AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", + linkInterfaceLinkDirectoriesEntries); + + processLinkDirectories(this, linkInterfaceLinkDirectoriesEntries, result, + uniqueDirectories, &dagChecker, config, + debugDirectories, language); + + cmDeleteAll(linkInterfaceLinkDirectoriesEntries); +} + +namespace { +void processLinkDepends( + cmGeneratorTarget const* tgt, + const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, + std::vector<std::string>& options, + std::unordered_set<std::string>& uniqueOptions, + cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, + std::string const& language) +{ + processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, + config, false, "link depends", language, + OptionsParse::None); +} +} + +void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result, + const std::string& config, + const std::string& language) const +{ + std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries; + std::unordered_set<std::string> uniqueOptions; + cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr, + nullptr); + + if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) { + std::vector<std::string> depends; + cmGeneratorExpression ge; + cmSystemTools::ExpandListArgument(linkDepends, depends); + for (const auto& depend : depends) { + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depend); + linkDependsEntries.push_back( + new cmGeneratorTarget::TargetPropertyEntry(std::move(cge))); + } + } + AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", + linkDependsEntries); + processLinkDepends(this, linkDependsEntries, result, uniqueOptions, + &dagChecker, config, language); + + cmDeleteAll(linkDependsEntries); +} + void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const { if (this->IsImported()) { @@ -3154,14 +3529,12 @@ std::string cmGeneratorTarget::GetFullNameInternal( return prefix + base + suffix; } -const char* cmGeneratorTarget::ImportedGetLocation( +std::string cmGeneratorTarget::ImportedGetLocation( const std::string& config) const { - static std::string location; assert(this->IsImported()); - location = this->Target->ImportedGetFullPath( + return this->Target->ImportedGetFullPath( config, cmStateEnums::RuntimeBinaryArtifact); - return location.c_str(); } std::string cmGeneratorTarget::GetFullNameImported( @@ -3243,11 +3616,11 @@ void cmGeneratorTarget::GetFullNameInternal( // if there is no prefix on the target use the cmake definition if (!targetPrefix && prefixVar) { - targetPrefix = this->Makefile->GetSafeDefinition(prefixVar); + targetPrefix = this->Makefile->GetSafeDefinition(prefixVar).c_str(); } // if there is no suffix on the target use the cmake definition if (!targetSuffix && suffixVar) { - targetSuffix = this->Makefile->GetSafeDefinition(suffixVar); + targetSuffix = this->Makefile->GetSafeDefinition(suffixVar).c_str(); } // frameworks have directory prefix but no suffix @@ -3363,8 +3736,9 @@ bool cmGeneratorTarget::StrictTargetComparison::operator()( { int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str()); if (nameResult == 0) { - return strcmp(t1->GetLocalGenerator()->GetCurrentBinaryDirectory(), - t2->GetLocalGenerator()->GetCurrentBinaryDirectory()) < 0; + return strcmp( + t1->GetLocalGenerator()->GetCurrentBinaryDirectory().c_str(), + t2->GetLocalGenerator()->GetCurrentBinaryDirectory().c_str()) < 0; } return nameResult < 0; } @@ -4251,7 +4625,7 @@ void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, if (name == this->GetName() || name.empty()) { continue; } - items.emplace_back(name, this->FindTargetToLink(name)); + items.push_back(this->ResolveLinkItem(name)); } } @@ -4261,8 +4635,7 @@ void cmGeneratorTarget::ExpandLinkItems( std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const { cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, nullptr, - nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr); // The $<LINK_ONLY> expression may be in a link interface to specify private // link dependencies that are otherwise excluded from usage requirements. if (usage_requirements_only) { @@ -4327,7 +4700,7 @@ void cmGeneratorTarget::ComputeLinkInterface( this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { // Shared libraries may have runtime implementation dependencies // on other shared libraries that are not in the interface. - std::unordered_set<std::string> emitted; + std::set<cmLinkItem> emitted; for (cmLinkItem const& lib : iface.Libraries) { emitted.insert(lib); } @@ -5320,11 +5693,11 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( end = entryRange.end(); le != end; ++le, ++btIt) { std::vector<std::string> llibs; - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), "LINK_LIBRARIES", nullptr, nullptr); + cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr, + nullptr); cmGeneratorExpression ge(*btIt); std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le); - std::string const evaluated = + std::string const& evaluated = cge->Evaluate(this->LocalGenerator, config, false, head, &dagChecker); cmSystemTools::ExpandListArgument(evaluated, llibs); if (cge->GetHadHeadSensitiveCondition()) { @@ -5366,7 +5739,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - impl.Libraries.emplace_back(name, this->FindTargetToLink(name), *btIt, + impl.Libraries.emplace_back(this->ResolveLinkItem(name), *btIt, evaluated != *le); } @@ -5394,27 +5767,70 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( continue; } // Support OLD behavior for CMP0003. - impl.WrongConfigLibraries.emplace_back(name, - this->FindTargetToLink(name)); + impl.WrongConfigLibraries.push_back(this->ResolveLinkItem(name)); } } } -cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink( +cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( std::string const& name) const { - cmGeneratorTarget* tgt = - this->LocalGenerator->FindGeneratorTargetToUse(name); + cmLocalGenerator const* lg = this->LocalGenerator; + std::string const* lookupName = &name; + + // When target_link_libraries() is called with a LHS target that is + // not created in the calling directory it adds a directory id suffix + // that we can use to look up the calling directory. It is that scope + // in which the item name is meaningful. This case is relatively rare + // so we allocate a separate string only when the directory id is present. + std::string::size_type pos = name.find(CMAKE_DIRECTORY_ID_SEP); + std::string plainName; + if (pos != std::string::npos) { + // We will look up the plain name without the directory id suffix. + plainName = name.substr(0, pos); + + // We will look up in the scope of the directory id. + // If we do not recognize the id then leave the original + // syntax in place to produce an indicative error later. + cmDirectoryId const dirId = + name.substr(pos + sizeof(CMAKE_DIRECTORY_ID_SEP) - 1); + if (cmLocalGenerator const* otherLG = + this->GlobalGenerator->FindLocalGenerator(dirId)) { + lg = otherLG; + lookupName = &plainName; + } + } + + TargetOrString resolved; + + if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(*lookupName)) { + resolved.Target = tgt; + } else if (lookupName == &plainName) { + resolved.String = std::move(plainName); + } else { + resolved.String = name; + } + + return resolved; +} + +cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const +{ + TargetOrString resolved = this->ResolveTargetReference(name); + + if (!resolved.Target) { + return cmLinkItem(resolved.String); + } // Skip targets that will not really be linked. This is probably a // name conflict between an external library and an executable // within the project. - if (tgt && tgt->GetType() == cmStateEnums::EXECUTABLE && - !tgt->IsExecutableWithExports()) { - tgt = nullptr; + if (resolved.Target->GetType() == cmStateEnums::EXECUTABLE && + !resolved.Target->IsExecutableWithExports()) { + return cmLinkItem(resolved.Target->GetName()); } - return tgt; + return cmLinkItem(resolved.Target); } std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 14197f82a..5ed8e5ace 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -68,7 +68,10 @@ public: std::string GetExportName() const; std::vector<std::string> GetPropertyKeys() const; + ///! Might return a nullptr if the property is not set or invalid const char* GetProperty(const std::string& prop) const; + ///! Always returns a valid pointer + const char* GetSafeProperty(const std::string& prop) const; bool GetPropertyAsBool(const std::string& prop) const; void GetSourceFiles(std::vector<cmSourceFile*>& files, const std::string& config) const; @@ -270,8 +273,6 @@ public: cmListFileBacktrace GetBacktrace() const; - const std::vector<std::string>& GetLinkDirectories() const; - std::set<std::string> const& GetUtilities() const; cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const; @@ -354,7 +355,14 @@ public: cmOptionalLinkImplementation& impl, const cmGeneratorTarget* head) const; - cmGeneratorTarget* FindTargetToLink(std::string const& name) const; + struct TargetOrString + { + std::string String; + cmGeneratorTarget* Target = nullptr; + }; + TargetOrString ResolveTargetReference(std::string const& name) const; + + cmLinkItem ResolveLinkItem(std::string const& name) const; // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change @@ -414,6 +422,21 @@ public: const std::string& config, const std::string& language) const; + void GetLinkOptions(std::vector<std::string>& result, + const std::string& config, + const std::string& language) const; + void GetStaticLibraryLinkOptions(std::vector<std::string>& result, + const std::string& config, + const std::string& language) const; + + void GetLinkDirectories(std::vector<std::string>& result, + const std::string& config, + const std::string& language) const; + + void GetLinkDepends(std::vector<std::string>& result, + const std::string& config, + const std::string& language) const; + bool IsSystemIncludeDirectory(const std::string& dir, const std::string& config, const std::string& language) const; @@ -643,7 +666,7 @@ public: no soname at all. */ bool IsImportedSharedLibWithoutSOName(const std::string& config) const; - const char* ImportedGetLocation(const std::string& config) const; + std::string ImportedGetLocation(const std::string& config) const; /** Get the target major and minor version numbers interpreted from the VERSION property. Version 0 is returned if the property is @@ -799,6 +822,8 @@ private: std::vector<TargetPropertyEntry*> CompileOptionsEntries; std::vector<TargetPropertyEntry*> CompileFeaturesEntries; std::vector<TargetPropertyEntry*> CompileDefinitionsEntries; + std::vector<TargetPropertyEntry*> LinkOptionsEntries; + std::vector<TargetPropertyEntry*> LinkDirectoriesEntries; std::vector<TargetPropertyEntry*> SourceEntries; mutable std::set<std::string> LinkImplicitNullProperties; @@ -847,6 +872,8 @@ private: mutable bool DebugCompileOptionsDone; mutable bool DebugCompileFeaturesDone; mutable bool DebugCompileDefinitionsDone; + mutable bool DebugLinkOptionsDone; + mutable bool DebugLinkDirectoriesDone; mutable bool DebugSourcesDone; mutable bool LinkImplementationLanguageIsContextDependent; mutable bool UtilityItemsDone; diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index bf464d9e4..0d4d6534c 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -65,7 +65,7 @@ bool cmGetDirectoryPropertyCommand::InitialPass( "providing the name of the variable to get."); return false; } - std::string output = dir->GetSafeDefinition(*i); + std::string const& output = dir->GetSafeDefinition(*i); this->Makefile->AddDefinition(variable, output.c_str()); return true; } diff --git a/Source/cmGlobVerificationManager.cxx b/Source/cmGlobVerificationManager.cxx index 189b517a0..e8959f2a0 100644 --- a/Source/cmGlobVerificationManager.cxx +++ b/Source/cmGlobVerificationManager.cxx @@ -23,7 +23,7 @@ bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path) cmSystemTools::MakeDirectory(scriptFile); scriptFile += "/VerifyGlobs.cmake"; stampFile += "/cmake.verify_globs"; - cmGeneratedFileStream verifyScriptFile(scriptFile.c_str()); + cmGeneratedFileStream verifyScriptFile(scriptFile); verifyScriptFile.SetCopyIfDifferent(true); if (!verifyScriptFile) { cmSystemTools::Error("Unable to open verification script file for save. ", diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 2872831c6..71e844ec1 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -34,6 +34,7 @@ #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmPolicies.h" +#include "cmQtAutoGen.h" #include "cmQtAutoGenInitializer.h" #include "cmSourceFile.h" #include "cmState.h" @@ -63,8 +64,8 @@ bool cmTarget::StrictTargetComparison::operator()(cmTarget const* t1, { int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str()); if (nameResult == 0) { - return strcmp(t1->GetMakefile()->GetCurrentBinaryDirectory(), - t2->GetMakefile()->GetCurrentBinaryDirectory()) < 0; + return strcmp(t1->GetMakefile()->GetCurrentBinaryDirectory().c_str(), + t2->GetMakefile()->GetCurrentBinaryDirectory().c_str()) < 0; } return nameResult < 0; } @@ -175,7 +176,7 @@ std::string cmGlobalGenerator::SelectMakeProgram( const std::string& inMakeProgram, const std::string& makeDefault) const { std::string makeProgram = inMakeProgram; - if (cmSystemTools::IsOff(makeProgram.c_str())) { + if (cmSystemTools::IsOff(makeProgram)) { const char* makeProgramCSTR = this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); if (cmSystemTools::IsOff(makeProgramCSTR)) { @@ -183,7 +184,7 @@ std::string cmGlobalGenerator::SelectMakeProgram( } else { makeProgram = makeProgramCSTR; } - if (cmSystemTools::IsOff(makeProgram.c_str()) && !makeProgram.empty()) { + if (cmSystemTools::IsOff(makeProgram) && !makeProgram.empty()) { makeProgram = "CMAKE_MAKE_PROGRAM-NOTFOUND"; } } @@ -204,7 +205,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, } return; } - const char* name = mf->GetRequiredDefinition(langComp); + std::string const& name = mf->GetRequiredDefinition(langComp); std::string path; if (!cmSystemTools::FileIsFullPath(name)) { path = cmSystemTools::FindProgram(name); @@ -214,15 +215,15 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, if (!optional && (path.empty() || !cmSystemTools::FileExists(path))) { return; } - const char* cname = + const std::string* cname = this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp); std::string changeVars; if (cname && !optional) { std::string cnameString; - if (!cmSystemTools::FileIsFullPath(cname)) { - cnameString = cmSystemTools::FindProgram(cname); + if (!cmSystemTools::FileIsFullPath(*cname)) { + cnameString = cmSystemTools::FindProgram(*cname); } else { - cnameString = cname; + cnameString = *cname; } std::string pathString = path; // get rid of potentially multiple slashes: @@ -238,7 +239,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, } changeVars += langComp; changeVars += ";"; - changeVars += cname; + changeVars += *cname; this->GetCMakeInstance()->GetState()->SetGlobalProperty( "__CMAKE_DELETE_CACHE_CHANGE_VARS_", changeVars.c_str()); } @@ -827,10 +828,8 @@ void cmGlobalGenerator::EnableLanguage( std::string sharedLibFlagsVar = "CMAKE_SHARED_LIBRARY_"; sharedLibFlagsVar += lang; sharedLibFlagsVar += "_FLAGS"; - const char* sharedLibFlags = mf->GetSafeDefinition(sharedLibFlagsVar); - if (sharedLibFlags) { - this->LanguageToOriginalSharedLibFlags[lang] = sharedLibFlags; - } + this->LanguageToOriginalSharedLibFlags[lang] = + mf->GetSafeDefinition(sharedLibFlagsVar); // Translate compiler ids for compatibility. this->CheckCompilerIdCompatibility(mf, lang); @@ -1091,7 +1090,7 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l, { std::string extensionsVar = std::string("CMAKE_") + std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS"); - std::string exts = mf->GetSafeDefinition(extensionsVar); + const std::string& exts = mf->GetSafeDefinition(extensionsVar); std::vector<std::string> extensionList; cmSystemTools::ExpandListArgument(exts, extensionList); for (std::string const& i : extensionList) { @@ -1111,7 +1110,7 @@ bool cmGlobalGenerator::GlobalSettingIsOn(std::string const& name) const return this->Makefiles[0]->IsOn(name); } -const char* cmGlobalGenerator::GetSafeGlobalSetting( +std::string cmGlobalGenerator::GetSafeGlobalSetting( std::string const& name) const { assert(!this->Makefiles.empty()); @@ -1138,11 +1137,14 @@ void cmGlobalGenerator::ClearEnabledLanguages() void cmGlobalGenerator::CreateLocalGenerators() { + this->LocalGeneratorSearchIndex.clear(); cmDeleteAll(this->LocalGenerators); this->LocalGenerators.clear(); this->LocalGenerators.reserve(this->Makefiles.size()); for (cmMakefile* m : this->Makefiles) { - this->LocalGenerators.push_back(this->CreateLocalGenerator(m)); + cmLocalGenerator* lg = this->CreateLocalGenerator(m); + this->LocalGenerators.push_back(lg); + this->IndexLocalGenerator(lg); } } @@ -1313,14 +1315,10 @@ bool cmGlobalGenerator::Compute() // so create the map from project name to vector of local generators this->FillProjectMap(); -#ifdef CMAKE_BUILD_WITH_CMAKE - // Iterate through all targets and set up automoc for those which have - // the AUTOMOC, AUTOUIC or AUTORCC property set - auto autogenInits = this->CreateQtAutoGenInitializers(); - for (auto& autoGen : autogenInits) { - autoGen->InitCustomTargets(); + // Iterate through all targets and set up AUTOMOC, AUTOUIC and AUTORCC + if (!this->QtAutoGen()) { + return false; } -#endif // Add generator specific helper commands for (cmLocalGenerator* localGen : this->LocalGenerators) { @@ -1339,14 +1337,6 @@ bool cmGlobalGenerator::Compute() } } -#ifdef CMAKE_BUILD_WITH_CMAKE - for (auto& autoGen : autogenInits) { - autoGen->SetupCustomTargets(); - autoGen.reset(nullptr); - } - autogenInits.clear(); -#endif - for (cmLocalGenerator* localGen : this->LocalGenerators) { cmMakefile* mf = localGen->GetMakefile(); for (cmInstallGenerator* g : mf->GetInstallGenerators()) { @@ -1476,12 +1466,11 @@ bool cmGlobalGenerator::ComputeTargetDepends() return true; } -std::vector<std::unique_ptr<cmQtAutoGenInitializer>> -cmGlobalGenerator::CreateQtAutoGenInitializers() +bool cmGlobalGenerator::QtAutoGen() { +#ifdef CMAKE_BUILD_WITH_CMAKE std::vector<std::unique_ptr<cmQtAutoGenInitializer>> autogenInits; -#ifdef CMAKE_BUILD_WITH_CMAKE for (cmLocalGenerator* localGen : this->LocalGenerators) { const std::vector<cmGeneratorTarget*>& targets = localGen->GetGeneratorTargets(); @@ -1508,19 +1497,36 @@ cmGlobalGenerator::CreateQtAutoGenInitializers() continue; } - std::string qtVersionMajor = - cmQtAutoGenInitializer::GetQtMajorVersion(target); + auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target); // don't do anything if there is no Qt4 or Qt5Core (which contains moc) - if (qtVersionMajor != "4" && qtVersionMajor != "5") { + if (qtVersion.Major != 4 && qtVersion.Major != 5) { continue; } - autogenInits.emplace_back(new cmQtAutoGenInitializer( - target, mocEnabled, uicEnabled, rccEnabled, qtVersionMajor)); + autogenInits.emplace_back(cm::make_unique<cmQtAutoGenInitializer>( + target, mocEnabled, uicEnabled, rccEnabled, qtVersion)); + } + } + + if (!autogenInits.empty()) { + // Initialize custom targets + for (auto& autoGen : autogenInits) { + if (!autoGen->InitCustomTargets()) { + return false; + } + } + + // Setup custom targets + for (auto& autoGen : autogenInits) { + if (!autoGen->SetupCustomTargets()) { + return false; + } + autoGen.reset(nullptr); } } #endif - return autogenInits; + + return true; } cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer( @@ -1588,7 +1594,7 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() for (std::string const& li : langs) { std::string const standardIncludesVar = "CMAKE_" + li + "_STANDARD_INCLUDE_DIRECTORIES"; - std::string const standardIncludesStr = + std::string const& standardIncludesStr = mf->GetSafeDefinition(standardIncludesVar); std::vector<std::string> standardIncludesVec; cmSystemTools::ExpandListArgument(standardIncludesStr, @@ -1656,6 +1662,7 @@ void cmGlobalGenerator::ClearGeneratorMembers() this->TargetSearchIndex.clear(); this->GeneratorTargetSearchIndex.clear(); this->MakefileSearchIndex.clear(); + this->LocalGeneratorSearchIndex.clear(); this->ProjectMap.clear(); this->RuleHashes.clear(); this->DirectoryContentMap.clear(); @@ -1965,7 +1972,7 @@ void cmGlobalGenerator::AddMakefile(cmMakefile* mf) // update progress // estimate how many lg there will be - const char* numGenC = + const std::string* numGenC = this->CMakeInstance->GetState()->GetInitializedCacheValue( "CMAKE_NUMBER_OF_MAKEFILES"); @@ -1983,7 +1990,7 @@ void cmGlobalGenerator::AddMakefile(cmMakefile* mf) return; } - int numGen = atoi(numGenC); + int numGen = atoi(numGenC->c_str()); float prog = 0.9f * static_cast<float>(this->Makefiles.size()) / static_cast<float>(numGen); if (prog > 0.9f) { @@ -1992,9 +1999,9 @@ void cmGlobalGenerator::AddMakefile(cmMakefile* mf) this->CMakeInstance->UpdateProgress("Configuring", prog); } -void cmGlobalGenerator::AddInstallComponent(const char* component) +void cmGlobalGenerator::AddInstallComponent(const std::string& component) { - if (component && *component) { + if (!component.empty()) { this->InstallComponents.insert(component); } } @@ -2125,15 +2132,13 @@ cmMakefile* cmGlobalGenerator::FindMakefile(const std::string& start_dir) const return nullptr; } -///! Find a local generator by its startdirectory cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator( - const std::string& start_dir) const + cmDirectoryId const& id) const { - for (cmLocalGenerator* lg : this->LocalGenerators) { - std::string sd = lg->GetCurrentSourceDirectory(); - if (sd == start_dir) { - return lg; - } + LocalGeneratorMap::const_iterator i = + this->LocalGeneratorSearchIndex.find(id.String); + if (i != this->LocalGeneratorSearchIndex.end()) { + return i->second; } return nullptr; } @@ -2163,6 +2168,24 @@ void cmGlobalGenerator::IndexGeneratorTarget(cmGeneratorTarget* gt) } } +std::string cmGlobalGenerator::IndexGeneratorTargetUniquely( + cmGeneratorTarget const* gt) +{ + // Use the pointer value to uniquely identify the target instance. + // Use a "T" prefix to indicate that this identifier is for a target. + // We must satisfy cmGeneratorExpression::IsValidTargetName so use no + // other special characters. + char buf[64]; + sprintf(buf, "::T%p", + static_cast<void const*>(gt)); // cast avoids format warning + std::string id = gt->GetName() + buf; + // We internally index pointers to non-const generator targets + // but our callers only have pointers to const generator targets. + // They will give up non-const privileges when looking up anyway. + this->GeneratorTargetSearchIndex[id] = const_cast<cmGeneratorTarget*>(gt); + return id; +} + void cmGlobalGenerator::IndexMakefile(cmMakefile* mf) { // FIXME: add_subdirectory supports multiple build directories @@ -2174,6 +2197,12 @@ void cmGlobalGenerator::IndexMakefile(cmMakefile* mf) MakefileMap::value_type(mf->GetCurrentSourceDirectory(), mf)); } +void cmGlobalGenerator::IndexLocalGenerator(cmLocalGenerator* lg) +{ + cmDirectoryId id = lg->GetMakefile()->GetDirectoryId(); + this->LocalGeneratorSearchIndex[id.String] = lg; +} + cmTarget* cmGlobalGenerator::FindTargetImpl(std::string const& name) const { TargetMap::const_iterator i = this->TargetSearchIndex.find(name); @@ -2425,7 +2454,7 @@ void cmGlobalGenerator::AddGlobalTarget_EditCache( std::string edit_cmd = this->GetEditCacheCommand(); if (!edit_cmd.empty()) { singleLine.push_back(std::move(edit_cmd)); - singleLine.push_back("-H$(CMAKE_SOURCE_DIR)"); + singleLine.push_back("-S$(CMAKE_SOURCE_DIR)"); singleLine.push_back("-B$(CMAKE_BINARY_DIR)"); gti.Message = "Running CMake cache editor..."; gti.UsesTerminal = true; @@ -2455,7 +2484,7 @@ void cmGlobalGenerator::AddGlobalTarget_RebuildCache( gti.UsesTerminal = true; cmCustomCommandLine singleLine; singleLine.push_back(cmSystemTools::GetCMakeCommand()); - singleLine.push_back("-H$(CMAKE_SOURCE_DIR)"); + singleLine.push_back("-S$(CMAKE_SOURCE_DIR)"); singleLine.push_back("-B$(CMAKE_BINARY_DIR)"); gti.CommandLines.push_back(std::move(singleLine)); targets.push_back(std::move(gti)); @@ -2886,7 +2915,7 @@ void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile, std::string fpath = cmSystemTools::CollapseFullPath(fname, home.c_str()); if (cmSystemTools::FileExists(fpath)) { RuleHash hash; - strncpy(hash.Data, line.c_str(), 32); + memcpy(hash.Data, line.c_str(), 32); this->RuleHashes[fname] = hash; } } @@ -2899,7 +2928,7 @@ void cmGlobalGenerator::WriteRuleHashes(std::string const& pfile) if (this->RuleHashes.empty()) { cmSystemTools::RemoveFile(pfile); } else { - cmGeneratedFileStream fout(pfile.c_str()); + cmGeneratedFileStream fout(pfile); fout << "# Hashes of file build rules.\n"; for (auto const& rh : this->RuleHashes) { fout.write(rh.second.Data, 32); @@ -2914,7 +2943,7 @@ void cmGlobalGenerator::WriteSummary() std::string fname = this->CMakeInstance->GetHomeOutputDirectory(); fname += cmake::GetCMakeFilesDirectory(); fname += "/TargetDirectories.txt"; - cmGeneratedFileStream fout(fname.c_str()); + cmGeneratedFileStream fout(fname); for (cmLocalGenerator* lg : this->LocalGenerators) { const std::vector<cmGeneratorTarget*>& tgts = lg->GetGeneratorTargets(); @@ -2951,7 +2980,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) Json::Value& lj_sources = lj_root["sources"] = Json::arrayValue; cmSystemTools::MakeDirectory(dir); - cmGeneratedFileStream fout(file.c_str()); + cmGeneratedFileStream fout(file); std::vector<std::string> labels; @@ -3025,7 +3054,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) } } } - cmGeneratedFileStream json_fout(json_file.c_str()); + cmGeneratedFileStream json_fout(json_file); json_fout << lj_root; } else #endif @@ -3100,7 +3129,7 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile() return true; } - cmGeneratedFileStream file(path.c_str()); + cmGeneratedFileStream file(path); file << "# CPack properties\n"; for (auto const& i : installedFiles) { diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index a50cc3bb3..1ea2d2445 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -26,6 +26,9 @@ # include "cmFileLockPool.h" #endif +#define CMAKE_DIRECTORY_ID_SEP "::@" + +class cmDirectoryId; class cmExportBuildFileGenerator; class cmExternalMakefileProjectGenerator; class cmGeneratorTarget; @@ -33,7 +36,6 @@ class cmLinkLineComputer; class cmLocalGenerator; class cmMakefile; class cmOutputConverter; -class cmQtAutoGenInitializer; class cmSourceFile; class cmStateDirectory; class cmake; @@ -220,7 +222,7 @@ public: std::string GetExtraGeneratorName() const; - void AddInstallComponent(const char* component); + void AddInstallComponent(const std::string& component); const std::set<std::string>* GetInstallComponents() const { @@ -231,7 +233,7 @@ public: const char* GetGlobalSetting(std::string const& name) const; bool GlobalSettingIsOn(std::string const& name) const; - const char* GetSafeGlobalSetting(std::string const& name) const; + std::string GetSafeGlobalSetting(std::string const& name) const; /** Add a file to the manifest of generated targets for a configuration. */ void AddToManifest(std::string const& f); @@ -285,8 +287,7 @@ public: bool NameResolvesToFramework(const std::string& libname) const; cmMakefile* FindMakefile(const std::string& start_dir) const; - ///! Find a local generator by its startdirectory - cmLocalGenerator* FindLocalGenerator(const std::string& start_dir) const; + cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const; /** Append the subdirectory for the given configuration. If anything is appended the given prefix and suffix will be appended around it, which @@ -306,6 +307,10 @@ public: void IndexTarget(cmTarget* t); void IndexGeneratorTarget(cmGeneratorTarget* gt); + // Index the target using a name that is unique to that target + // even if other targets have the same name. + std::string IndexGeneratorTargetUniquely(cmGeneratorTarget const* gt); + static bool IsReservedTarget(std::string const& name); virtual const char* GetAllTargetName() const { return "ALL_BUILD"; } @@ -354,6 +359,8 @@ public: i.e. "Can I build Debug and Release in the same tree?" */ virtual bool IsMultiConfig() const { return false; } + virtual bool IsXcode() 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. */ @@ -441,9 +448,9 @@ protected: virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const; - // Qt auto generators - std::vector<std::unique_ptr<cmQtAutoGenInitializer>> - CreateQtAutoGenInitializers(); + /// @brief Qt AUTOMOC/UIC/RCC target generation + /// @return true on success + bool QtAutoGen(); std::string SelectMakeProgram(const std::string& makeProgram, const std::string& makeDefault = "") const; @@ -513,6 +520,7 @@ private: typedef std::unordered_map<std::string, cmGeneratorTarget*> GeneratorTargetMap; typedef std::unordered_map<std::string, cmMakefile*> MakefileMap; + typedef std::unordered_map<std::string, cmLocalGenerator*> LocalGeneratorMap; // Map efficiently from target name to cmTarget instance. // Do not use this structure for looping over all targets. // It contains both normal and globally visible imported targets. @@ -524,6 +532,11 @@ private: // It may not contain all of them (see note in IndexMakefile method). MakefileMap MakefileSearchIndex; + // Map efficiently from source directory path to cmLocalGenerator instance. + // Do not use this structure for looping over all directories. + // Its order is not deterministic. + LocalGeneratorMap LocalGeneratorSearchIndex; + cmMakefile* TryCompileOuterMakefile; // If you add a new map here, make sure it is copied // in EnableLanguagesFromGenerator @@ -582,6 +595,7 @@ private: std::string const& reason) const; void IndexMakefile(cmMakefile* mf); + void IndexLocalGenerator(cmLocalGenerator* lg); virtual const char* GetBuildIgnoreErrorsFlag() const { return nullptr; } diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 0328991e6..a9742c531 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -14,13 +14,13 @@ #include "cmVersion.h" const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj"; -const char* cmGlobalGhsMultiGenerator::DEFAULT_MAKE_PROGRAM = "gbuild"; +const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild.exe"; +const char* cmGlobalGhsMultiGenerator::DEFAULT_TOOLSET_ROOT = "C:/ghs"; cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm) : cmGlobalGenerator(cm) , OSDirRelative(false) { - this->GhsBuildCommandInitialized = false; } cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator() @@ -41,133 +41,153 @@ void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry) "Generates Green Hills MULTI files (experimental, work-in-progress)."; } -void cmGlobalGhsMultiGenerator::EnableLanguage( - std::vector<std::string> const& l, cmMakefile* mf, bool optional) +bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, + cmMakefile* mf) { - mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI"); - mf->AddDefinition("CMAKE_SYSTEM_PROCESSOR", "ARM"); - - const std::string ghsCompRoot(GetCompRoot()); - mf->AddDefinition("GHS_COMP_ROOT", ghsCompRoot.c_str()); - std::string ghsCompRootStart = - 0 == ghsCompRootStart.size() ? "" : ghsCompRoot + "/"; - mf->AddDefinition("CMAKE_C_COMPILER", - std::string(ghsCompRootStart + "ccarm.exe").c_str()); + std::string tsp; /* toolset path */ + std::string tsn = ts; /* toolset name */ + + GetToolset(mf, tsp, tsn); + + /* no toolset was found */ + if (tsn.empty()) { + return false; + } else if (ts.empty()) { + std::string message; + message = + "Green Hills MULTI: -T <toolset> not specified; defaulting to \""; + message += tsn; + message += "\""; + cmSystemTools::Message(message.c_str()); + + /* store the toolset for later use + * -- already done if -T<toolset> was specified + */ + mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsn.c_str(), + "Name of generator toolset.", + cmStateEnums::INTERNAL); + } + + /* set the build tool to use */ + const char* prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM"); + std::string gbuild(tsp + "/" + tsn + "/" + DEFAULT_BUILD_PROGRAM); + + /* check if the toolset changed from last generate */ + if (prevTool != NULL && (gbuild != prevTool)) { + std::string message = "generator toolset: "; + message += gbuild; + message += "\nDoes not match the toolset used previously: "; + message += prevTool; + message += "\nEither remove the CMakeCache.txt file and CMakeFiles " + "directory or choose a different binary directory."; + cmSystemTools::Error(message.c_str()); + } else { + /* store the toolset that is being used for this build */ + mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(), + "build program to use", cmStateEnums::INTERNAL, + true); + } + + mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsn.c_str()); + + // FIXME: compiler detection not implemented + // gbuild uses the primaryTarget setting in the top-level project + // file to determine which compiler to use. Because compiler + // detection is not implemented these variables must be + // set to skip past these tests. However cmake will verify that + // the executable pointed to by CMAKE_<LANG>_COMPILER exists. + // To pass this additional check gbuild is used as a place holder for the + // actual compiler. + mf->AddDefinition("CMAKE_C_COMPILER", gbuild.c_str()); mf->AddDefinition("CMAKE_C_COMPILER_ID_RUN", "TRUE"); mf->AddDefinition("CMAKE_C_COMPILER_ID", "GHS"); mf->AddDefinition("CMAKE_C_COMPILER_FORCED", "TRUE"); - mf->AddDefinition("CMAKE_CXX_COMPILER", - std::string(ghsCompRootStart + "cxarm.exe").c_str()); + mf->AddDefinition("CMAKE_CXX_COMPILER", gbuild.c_str()); mf->AddDefinition("CMAKE_CXX_COMPILER_ID_RUN", "TRUE"); mf->AddDefinition("CMAKE_CXX_COMPILER_ID", "GHS"); mf->AddDefinition("CMAKE_CXX_COMPILER_FORCED", "TRUE"); - if (!ghsCompRoot.empty()) { - static const char* compPreFix = "comp_"; - std::string compFilename = - cmsys::SystemTools::FindLastString(ghsCompRoot.c_str(), compPreFix); - cmsys::SystemTools::ReplaceString(compFilename, compPreFix, ""); - mf->AddDefinition("CMAKE_SYSTEM_VERSION", compFilename.c_str()); - } - - mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files - this->cmGlobalGenerator::EnableLanguage(l, mf, optional); + return true; } -bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* mf) +bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, + cmMakefile* mf) { - // The GHS generator knows how to lookup its build tool - // directly instead of needing a helper module to do it, so we - // do not actually need to put CMAKE_MAKE_PROGRAM into the cache. - if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { - mf->AddDefinition("CMAKE_MAKE_PROGRAM", - this->GetGhsBuildCommand().c_str()); + if (p == "") { + cmSystemTools::Message( + "Green Hills MULTI: -A <arch> not specified; defaulting to \"arm\""); + std::string arch = "arm"; + + /* store the platform name for later use + * -- already done if -A<arch> was specified + */ + mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch.c_str(), + "Name of generator platform.", + cmStateEnums::INTERNAL); } - return true; -} -std::string const& cmGlobalGhsMultiGenerator::GetGhsBuildCommand() -{ - if (!this->GhsBuildCommandInitialized) { - this->GhsBuildCommandInitialized = true; - this->GhsBuildCommand = this->FindGhsBuildCommand(); + const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM"); + if (tgtPlatform == nullptr) { + tgtPlatform = "integrity"; } - return this->GhsBuildCommand; + + /* store the platform name for later use */ + mf->AddCacheDefinition("GHS_TARGET_PLATFORM", tgtPlatform, + "Name of GHS target platform.", + cmStateEnums::INTERNAL); + + return true; } -std::string cmGlobalGhsMultiGenerator::FindGhsBuildCommand() +void cmGlobalGhsMultiGenerator::EnableLanguage( + std::vector<std::string> const& l, cmMakefile* mf, bool optional) { - std::vector<std::string> userPaths; - userPaths.push_back(this->GetCompRoot()); - std::string makeProgram = - cmSystemTools::FindProgram(DEFAULT_MAKE_PROGRAM, userPaths); - if (makeProgram.empty()) { - makeProgram = DEFAULT_MAKE_PROGRAM; - } - return makeProgram; + mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI"); + + mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files + this->cmGlobalGenerator::EnableLanguage(l, mf, optional); } -std::string cmGlobalGhsMultiGenerator::GetCompRoot() +bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* /*mf*/) { - std::string output; - - const std::vector<std::string> potentialDirsHardPaths( - GetCompRootHardPaths()); - const std::vector<std::string> potentialDirsRegistry(GetCompRootRegistry()); - - std::vector<std::string> potentialDirsComplete; - potentialDirsComplete.insert(potentialDirsComplete.end(), - potentialDirsHardPaths.begin(), - potentialDirsHardPaths.end()); - potentialDirsComplete.insert(potentialDirsComplete.end(), - potentialDirsRegistry.begin(), - potentialDirsRegistry.end()); - - // Use latest version - std::string outputDirName; - for (std::vector<std::string>::const_iterator potentialDirsCompleteIt = - potentialDirsComplete.begin(); - potentialDirsCompleteIt != potentialDirsComplete.end(); - ++potentialDirsCompleteIt) { - const std::string dirName( - cmsys::SystemTools::GetFilenameName(*potentialDirsCompleteIt)); - if (dirName.compare(outputDirName) > 0) { - output = *potentialDirsCompleteIt; - outputDirName = dirName; - } - } + // The GHS generator only knows how to lookup its build tool + // during generation of the project files, but this + // can only be done after the toolset is specified. - return output; + return true; } -std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootHardPaths() +void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd, + std::string& ts) { - std::vector<std::string> output; - cmSystemTools::Glob("C:/ghs", "comp_[^;]+", output); - for (std::vector<std::string>::iterator outputIt = output.begin(); - outputIt != output.end(); ++outputIt) { - *outputIt = "C:/ghs/" + *outputIt; + const char* ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT"); + + if (!ghsRoot) { + ghsRoot = DEFAULT_TOOLSET_ROOT; } - return output; -} + tsd = ghsRoot; -std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootRegistry() -{ - std::vector<std::string> output(2); - cmsys::SystemTools::ReadRegistryValue( - "HKEY_LOCAL_" - "MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\" - "Windows\\CurrentVersion\\Uninstall\\" - "GreenHillsSoftwared771f1b4;InstallLocation", - output[0]); - cmsys::SystemTools::ReadRegistryValue( - "HKEY_LOCAL_" - "MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\" - "Windows\\CurrentVersion\\Uninstall\\" - "GreenHillsSoftware9881cef6;InstallLocation", - output[1]); - return output; + if (ts.empty()) { + std::vector<std::string> output; + + // Use latest? version + cmSystemTools::Glob(tsd, "comp_[^;]+", output); + + if (output.empty()) { + cmSystemTools::Error("GHS toolset not found in ", tsd.c_str()); + ts = ""; + } else { + ts = output.back(); + } + } else { + std::string tryPath = tsd + std::string("/") + ts; + if (!cmSystemTools::FileExists(tryPath)) { + cmSystemTools::Error("GHS toolset \"", ts.c_str(), "\" not found in ", + tsd.c_str()); + ts = ""; + } + } } void cmGlobalGhsMultiGenerator::OpenBuildFileStream( @@ -216,25 +236,28 @@ void cmGlobalGhsMultiGenerator::OpenBuildFileStream() this->OSDirRelative = true; } - char const* bspName = + std::string bspName; + char const* bspCache = this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME"); - if (NULL == bspName) { - bspName = ""; - cmSystemTools::Error("GHS_BSP_NAME cache variable must be set"); - } else { + if (bspCache) { + bspName = bspCache; this->GetCMakeInstance()->MarkCliAsUsed("GHS_BSP_NAME"); } - std::string fBspName(this->trimQuotes(bspName)); - std::replace(fBspName.begin(), fBspName.end(), '\\', '/'); + if (bspName.empty() || bspName.compare("IGNORE") == 0) { + const char* a = + this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM"); + bspName = "sim"; + bspName += (a ? a : ""); + } + this->WriteMacros(); this->WriteHighLevelDirectives(); GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, this->GetBuildFileStream()); this->WriteDisclaimer(this->GetBuildFileStream()); *this->GetBuildFileStream() << "# Top Level Project File" << std::endl; - if (!fBspName.empty()) { - *this->GetBuildFileStream() << " -bsp " << fBspName << std::endl; - } + *this->GetBuildFileStream() << " -bsp " << bspName << std::endl; + this->WriteCompilerOptions(fOSDir); } @@ -275,8 +298,10 @@ void cmGlobalGhsMultiGenerator::GenerateBuildCommand( const std::string& targetName, const std::string& /*config*/, bool /*fast*/, int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions) { + const char* gbuild = + this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); makeCommand.push_back( - this->SelectMakeProgram(makeProgram, this->GetGhsBuildCommand())); + this->SelectMakeProgram(makeProgram, (std::string)gbuild)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { makeCommand.push_back("-parallel"); @@ -313,8 +338,26 @@ void cmGlobalGhsMultiGenerator::WriteMacros() void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives() { - *this->GetBuildFileStream() - << "primaryTarget=arm_integrity.tgt" << std::endl; + /* set primary target */ + std::string tgt; + const char* t = + this->GetCMakeInstance()->GetCacheDefinition("GHS_PRIMARY_TARGET"); + if (t) { + tgt = t; + this->GetCMakeInstance()->MarkCliAsUsed("GHS_PRIMARY_TARGET"); + } else { + const char* a = + this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM"); + const char* p = + this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM"); + tgt = (a ? a : ""); + tgt += "_"; + tgt += (p ? p : ""); + tgt += ".tgt"; + } + + *this->GetBuildFileStream() << "primaryTarget=" << tgt << std::endl; + char const* const customization = this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION"); if (NULL != customization && strlen(customization) > 0) { @@ -348,16 +391,14 @@ void cmGlobalGhsMultiGenerator::AddFilesUpToPath( { std::string workingPath(path); cmSystemTools::ConvertToUnixSlashes(workingPath); - std::vector<cmsys::String> splitPath = - cmSystemTools::SplitString(workingPath); + std::vector<std::string> splitPath = cmSystemTools::SplitString(workingPath); std::string workingRelPath(relPath); cmSystemTools::ConvertToUnixSlashes(workingRelPath); if (!workingRelPath.empty()) { workingRelPath += "/"; } std::string pathUpTo; - for (std::vector<cmsys::String>::const_iterator splitPathI = - splitPath.begin(); + for (std::vector<std::string>::const_iterator splitPathI = splitPath.begin(); splitPath.end() != splitPathI; ++splitPathI) { pathUpTo += *splitPathI; if (targetFolderBuildStreams->end() == @@ -415,11 +456,11 @@ void cmGlobalGhsMultiGenerator::AddFilesUpToPathNewBuildFile( void cmGlobalGhsMultiGenerator::AddFilesUpToPathAppendNextFile( std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, std::string const& pathUpTo, - std::vector<cmsys::String>::const_iterator splitPathI, - std::vector<cmsys::String>::const_iterator end, + std::vector<std::string>::const_iterator splitPathI, + std::vector<std::string>::const_iterator end, GhsMultiGpj::Types const projType) { - std::vector<cmsys::String>::const_iterator splitPathNextI = splitPathI + 1; + std::vector<std::string>::const_iterator splitPathNextI = splitPathI + 1; if (end != splitPathNextI && targetFolderBuildStreams->end() == targetFolderBuildStreams->find(pathUpTo + "/" + *splitPathNextI)) { @@ -436,7 +477,7 @@ std::string cmGlobalGhsMultiGenerator::GetFileNameFromPath( std::string output(path); if (!path.empty()) { cmSystemTools::ConvertToUnixSlashes(output); - std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(output); + std::vector<std::string> splitPath = cmSystemTools::SplitString(output); output += "/" + splitPath.back() + FILE_EXTENSION; } return output; @@ -457,7 +498,7 @@ void cmGlobalGhsMultiGenerator::UpdateBuildFiles( this->GetCMakeInstance()->GetHomeOutputDirectory().c_str(), folderName, GhsMultiGpj::PROJECT); } - std::vector<cmsys::String> splitPath = cmSystemTools::SplitString( + std::vector<std::string> splitPath = cmSystemTools::SplitString( cmGhsMultiTargetGenerator::GetRelBuildFileName(tgt)); std::string foldNameRelBuildFile(*(splitPath.end() - 2) + "/" + splitPath.back()); diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index 30d4d3b27..13c511302 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -40,13 +40,17 @@ public: * Utilized by the generator factory to determine if this generator * supports toolsets. */ - static bool SupportsToolset() { return false; } + static bool SupportsToolset() { return true; } /** * Utilized by the generator factory to determine if this generator * supports platforms. */ - static bool SupportsPlatform() { return false; } + static bool SupportsPlatform() { return true; } + + // Toolset / Platform Support + virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); + virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf); /** * Try to determine system information such as shared library @@ -93,11 +97,7 @@ protected: std::vector<std::string> const& makeOptions = std::vector<std::string>()); private: - std::string const& GetGhsBuildCommand(); - std::string FindGhsBuildCommand(); - std::string GetCompRoot(); - std::vector<std::string> GetCompRootHardPaths(); - std::vector<std::string> GetCompRootRegistry(); + void GetToolset(cmMakefile* mf, std::string& tsd, std::string& ts); void OpenBuildFileStream(); void WriteMacros(); @@ -112,9 +112,8 @@ private: static void AddFilesUpToPathAppendNextFile( std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams, std::string const& pathUpTo, - std::vector<cmsys::String>::const_iterator splitPathI, - std::vector<cmsys::String>::const_iterator end, - GhsMultiGpj::Types projType); + std::vector<std::string>::const_iterator splitPathI, + std::vector<std::string>::const_iterator end, GhsMultiGpj::Types projType); static std::string GetFileNameFromPath(std::string const& path); void UpdateBuildFiles(const std::vector<cmGeneratorTarget*>& tgts); bool IsTgtForBuild(const cmGeneratorTarget* tgt); @@ -125,9 +124,8 @@ private: std::vector<std::string> LibDirs; bool OSDirRelative; - bool GhsBuildCommandInitialized; - std::string GhsBuildCommand; - static const char* DEFAULT_MAKE_PROGRAM; + static const char* DEFAULT_BUILD_PROGRAM; + static const char* DEFAULT_TOOLSET_ROOT; }; #endif diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 6f7e82ab1..f51340377 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -651,13 +651,13 @@ void cmGlobalNinjaGenerator::EnableLanguage( this->ResolveLanguageCompiler(l, mf, optional); } #ifdef _WIN32 - if (strcmp(mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID"), "MSVC") != 0 && - strcmp(mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID"), "MSVC") != 0 && + if ((mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID") != "MSVC") && + (mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID") != "MSVC") && (mf->IsOn("CMAKE_COMPILER_IS_MINGW") || - strcmp(mf->GetSafeDefinition("CMAKE_C_COMPILER_ID"), "GNU") == 0 || - strcmp(mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"), "GNU") == 0 || - strcmp(mf->GetSafeDefinition("CMAKE_C_COMPILER_ID"), "Clang") == 0 || - strcmp(mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"), "Clang") == 0)) { + (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "GNU") || + (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "GNU") || + (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") || + (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang"))) { this->UsingGCCOnWindows = true; } #endif @@ -763,7 +763,7 @@ void cmGlobalNinjaGenerator::OpenBuildFileStream() // Get a stream where to generate things. if (!this->BuildFileStream) { this->BuildFileStream = new cmGeneratedFileStream( - buildFilePath.c_str(), false, this->GetMakefileEncoding()); + buildFilePath, false, this->GetMakefileEncoding()); if (!this->BuildFileStream) { // An error message is generated by the constructor if it cannot // open the file. @@ -801,7 +801,7 @@ void cmGlobalNinjaGenerator::OpenRulesFileStream() // Get a stream where to generate things. if (!this->RulesFileStream) { this->RulesFileStream = new cmGeneratedFileStream( - rulesFilePath.c_str(), false, this->GetMakefileEncoding()); + rulesFilePath, false, this->GetMakefileEncoding()); if (!this->RulesFileStream) { // An error message is generated by the constructor if it cannot // open the file. @@ -883,8 +883,7 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand( } // Get a stream where to generate things. - this->CompileCommandsStream = - new cmGeneratedFileStream(buildFilePath.c_str()); + this->CompileCommandsStream = new cmGeneratedFileStream(buildFilePath); *this->CompileCommandsStream << "["; } else { *this->CompileCommandsStream << "," << std::endl; @@ -1012,8 +1011,7 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( std::set<std::string> const& utils = target->GetUtilities(); for (std::string const& util : utils) { std::string d = - target->GetLocalGenerator()->GetCurrentBinaryDirectory() + - std::string("/") + util; + target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + util; outputs.push_back(this->ConvertToNinjaPath(d)); } } else { @@ -1112,6 +1110,12 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) continue; } + // Don't write alias if there is a already a custom command with + // matching output + if (this->HasCustomCommandOutput(ta.first)) { + continue; + } + cmNinjaDeps deps; this->AppendTargetOutputs(ta.second, deps); @@ -1336,7 +1340,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) std::ostringstream cmd; cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL) - << " -H" + << " -S" << lg->ConvertToOutputFormat(lg->GetSourceDirectory(), cmOutputConverter::SHELL) << " -B" @@ -1700,7 +1704,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg, } { - cmGeneratedFileStream depfile(arg_dep.c_str()); + cmGeneratedFileStream depfile(arg_dep); depfile << cmSystemTools::ConvertToUnixOutputPath(arg_pp) << ":"; for (std::string const& include : info.Includes) { depfile << " \\\n " << cmSystemTools::ConvertToUnixOutputPath(include); @@ -1723,7 +1727,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg, } } - cmGeneratedFileStream ddif(arg_ddi.c_str()); + cmGeneratedFileStream ddif(arg_ddi); ddif << ddi; if (!ddif) { cmSystemTools::Error("-E cmake_ninja_depends failed to write ", @@ -1827,7 +1831,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( } } - cmGeneratedFileStream ddf(arg_dd.c_str()); + cmGeneratedFileStream ddf(arg_dd); ddf << "ninja_dyndep_version = 1.0\n"; for (cmFortranObjectInfo const& object : objects) { @@ -1862,7 +1866,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( // use by dependents that reference this target in linked-target-dirs. std::string const target_mods_file = cmSystemTools::GetFilenamePath(arg_dd) + "/FortranModules.json"; - cmGeneratedFileStream tmf(target_mods_file.c_str()); + cmGeneratedFileStream tmf(target_mods_file); tmf << tm; return true; diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 61c42be4e..db7235366 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -147,7 +147,7 @@ void cmGlobalUnixMakefileGenerator3::Generate() markFileName += "/"; markFileName += cmake::GetCMakeFilesDirectory(); markFileName += "/progress.marks"; - cmGeneratedFileStream markFile(markFileName.c_str()); + cmGeneratedFileStream markFile(markFileName); markFile << this->CountProgressMarksInAll(lg) << "\n"; } @@ -170,8 +170,7 @@ void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand( std::string commandDatabaseName = std::string(this->GetCMakeInstance()->GetHomeOutputDirectory()) + "/compile_commands.json"; - this->CommandDatabase = - new cmGeneratedFileStream(commandDatabaseName.c_str()); + this->CommandDatabase = new cmGeneratedFileStream(commandDatabaseName); *this->CommandDatabase << "[" << std::endl; } else { *this->CommandDatabase << "," << std::endl; @@ -198,7 +197,7 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() this->GetCMakeInstance()->GetHomeOutputDirectory(); makefileName += cmake::GetCMakeFilesDirectory(); makefileName += "/Makefile2"; - cmGeneratedFileStream makefileStream(makefileName.c_str(), false, + cmGeneratedFileStream makefileStream(makefileName, false, this->GetMakefileEncoding()); if (!makefileStream) { return; @@ -270,7 +269,7 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() this->GetCMakeInstance()->GetHomeOutputDirectory(); cmakefileName += cmake::GetCMakeFilesDirectory(); cmakefileName += "/Makefile.cmake"; - cmGeneratedFileStream cmakefileStream(cmakefileName.c_str()); + cmGeneratedFileStream cmakefileStream(cmakefileName); if (!cmakefileStream) { return; } @@ -876,7 +875,7 @@ void cmGlobalUnixMakefileGenerator3::RecordTargetProgress( void cmGlobalUnixMakefileGenerator3::TargetProgress::WriteProgressVariables( unsigned long total, unsigned long& current) { - cmGeneratedFileStream fout(this->VariableFile.c_str()); + cmGeneratedFileStream fout(this->VariableFile); for (unsigned long i = 1; i <= this->NumberOfActions; ++i) { fout << "CMAKE_PROGRESS_" << i << " = "; if (total <= 100) { diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index a5709d58d..82fcaadde 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -938,6 +938,7 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand( configArg += "Debug"; } makeCommand.push_back(configArg); + makeCommand.push_back("/p:Platform=" + this->GetPlatformName()); makeCommand.push_back(std::string("/p:VisualStudioVersion=") + this->GetIDEVersion()); @@ -1014,7 +1015,7 @@ void cmGlobalVisualStudio10Generator::PathTooLong(cmGeneratorTarget* target, std::string const& sfRel) { size_t len = - (strlen(target->GetLocalGenerator()->GetCurrentBinaryDirectory()) + 1 + + (target->GetLocalGenerator()->GetCurrentBinaryDirectory().length() + 1 + sfRel.length()); if (len > this->LongestSource.Length) { this->LongestSource.Length = len; diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 6eb597c9a..63e690343 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -111,6 +111,8 @@ public: bool FindMakeProgram(cmMakefile* mf) override; + bool IsIPOSupported() const override { return true; } + static std::string GetInstalledNsightTegraVersion(); cmIDEFlagTable const* GetClFlagTable() const; diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index b0db1467b..c3ddb3e01 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -212,6 +212,12 @@ bool cmGlobalVisualStudio14Generator::IsWindowsStoreToolsetInstalled() const cmSystemTools::KeyWOW64_32); } +std::string cmGlobalVisualStudio14Generator::GetWindows10SDKMaxVersion() const +{ + // The last Windows 10 SDK version that VS 2015 can target is 10.0.14393.0. + return "10.0.14393.0"; +} + #if defined(_WIN32) && !defined(__CYGWIN__) struct NoWindowsH { @@ -220,6 +226,20 @@ struct NoWindowsH return !cmSystemTools::FileExists(p + "/um/windows.h", true); } }; +class WindowsSDKTooRecent +{ + std::string const& MaxVersion; + +public: + WindowsSDKTooRecent(std::string const& maxVersion) + : MaxVersion(maxVersion) + { + } + bool operator()(std::string const& v) + { + return cmSystemTools::VersionCompareGreater(v, MaxVersion); + } +}; #endif std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() @@ -276,6 +296,12 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() // Sort the results to make sure we select the most recent one. std::sort(sdks.begin(), sdks.end(), cmSystemTools::VersionCompareGreater); + // Skip SDKs that cannot be used with our toolset. + std::string maxVersion = this->GetWindows10SDKMaxVersion(); + if (!maxVersion.empty()) { + cmEraseIf(sdks, WindowsSDKTooRecent(maxVersion)); + } + // Look for a SDK exactly matching the requested target version. for (std::string const& i : sdks) { if (cmSystemTools::VersionCompareEqual(i, this->SystemVersion)) { diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 4868df02e..9f5bb4e66 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -37,6 +37,10 @@ protected: // of the toolset is installed bool IsWindowsStoreToolsetInstalled() const; + // Used to make sure that the Windows 10 SDK selected can work with the + // version of the toolset. + virtual std::string GetWindows10SDKMaxVersion() const; + const char* GetIDEVersion() override { return "14.0"; } virtual bool SelectWindows10SDK(cmMakefile* mf, bool required); diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index 9983a43de..23fd2d5b4 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -258,6 +258,11 @@ bool cmGlobalVisualStudio15Generator::IsWin81SDKInstalled() const return false; } +std::string cmGlobalVisualStudio15Generator::GetWindows10SDKMaxVersion() const +{ + return std::string(); +} + std::string cmGlobalVisualStudio15Generator::FindMSBuildCommand() { std::string msbuild; diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h index cdc97ad9e..8ab63f141 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudio15Generator.h @@ -52,6 +52,8 @@ protected: // Check for a Win 8 SDK known to the registry or VS installer tool. bool IsWin81SDKInstalled() const; + std::string GetWindows10SDKMaxVersion() const override; + std::string FindMSBuildCommand() override; std::string FindDevEnvCommand() override; diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 158f48431..21121f2bb 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -397,12 +397,12 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( if (written && this->UseFolderProperty()) { const std::string targetFolder = target->GetEffectiveFolderName(); if (!targetFolder.empty()) { - std::vector<cmsys::String> tokens = + std::vector<std::string> tokens = cmSystemTools::SplitString(targetFolder, '/', false); std::string cumulativePath; - for (cmsys::String const& iter : tokens) { + for (std::string const& iter : tokens) { if (!iter.size()) { continue; } diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 117d05175..ba138c22e 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -177,9 +177,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // Create a rule to re-run CMake. cmCustomCommandLine commandLine; commandLine.push_back(cmSystemTools::GetCMakeCommand()); - std::string argH = "-H"; - argH += lg->GetSourceDirectory(); - commandLine.push_back(argH); + std::string argS = "-S"; + argS += lg->GetSourceDirectory(); + commandLine.push_back(argS); std::string argB = "-B"; argB += lg->GetBinaryDirectory(); commandLine.push_back(argB); diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 4aa52c35c..da3daf86b 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -878,12 +878,13 @@ bool cmGlobalVisualStudioGenerator::Open(const std::string& bindir, const std::string& projectName, bool dryRun) { - std::string buildDir = cmSystemTools::ConvertToOutputPath(bindir); - std::string sln = buildDir + "\\" + projectName + ".sln"; + std::string sln = bindir + "/" + projectName + ".sln"; if (dryRun) { return cmSystemTools::FileExists(sln, true); } + sln = cmSystemTools::ConvertToOutputPath(sln); + return std::async(std::launch::async, OpenSolution, sln).get(); } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index e9a08bf7f..e353a3770 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -386,12 +386,46 @@ void cmGlobalXCodeGenerator::AddExtraIDETargets() } } +void cmGlobalXCodeGenerator::ComputeTargetOrder() +{ + size_t index = 0; + auto const& lgens = this->GetLocalGenerators(); + for (cmLocalGenerator* lgen : lgens) { + auto const& targets = lgen->GetGeneratorTargets(); + for (cmGeneratorTarget const* gt : targets) { + this->ComputeTargetOrder(gt, index); + } + } + assert(index == this->TargetOrderIndex.size()); +} + +void cmGlobalXCodeGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt, + size_t& index) +{ + std::map<cmGeneratorTarget const*, size_t>::value_type value(gt, 0); + auto insertion = this->TargetOrderIndex.insert(value); + if (!insertion.second) { + return; + } + auto entry = insertion.first; + + auto& deps = this->GetTargetDirectDepends(gt); + for (auto& d : deps) { + this->ComputeTargetOrder(d, index); + } + + entry->second = index++; +} + void cmGlobalXCodeGenerator::Generate() { this->cmGlobalGenerator::Generate(); if (cmSystemTools::GetErrorOccuredFlag()) { return; } + + this->ComputeTargetOrder(); + for (auto keyVal : this->ProjectMap) { cmLocalGenerator* root = keyVal.second[0]; @@ -717,23 +751,22 @@ class XCodeGeneratorExpressionInterpreter public: XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile, cmLocalGenerator* localGenerator, - cmGeneratorTarget* generatorTarget, + cmGeneratorTarget* headTarget, const std::string& lang) - : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget, - "NO-PER-CONFIG-SUPPORT-IN-XCODE", - generatorTarget->GetName(), lang) + : cmGeneratorExpressionInterpreter( + localGenerator, "NO-PER-CONFIG-SUPPORT-IN-XCODE", headTarget, lang) , SourceFile(sourceFile) { } using cmGeneratorExpressionInterpreter::Evaluate; - const char* Evaluate(const char* expression, const std::string& property) + const std::string& Evaluate(const char* expression, + const std::string& property) { - const char* processed = + const std::string& processed = this->cmGeneratorExpressionInterpreter::Evaluate(expression, property); - if (this->GetCompiledGeneratorExpression() - .GetHadContextSensitiveCondition()) { + if (this->CompiledGeneratorExpression->GetHadContextSensitiveCondition()) { std::ostringstream e; /* clang-format off */ e << @@ -742,7 +775,7 @@ public: "specified for source:\n" " " << this->SourceFile->GetFullPath() << "\n"; /* clang-format on */ - this->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); } return processed; @@ -787,7 +820,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); if (const char* compile_defs = sf->GetProperty(COMPILE_DEFINITIONS)) { this->AppendDefines( - flagsBuild, genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS), + flagsBuild, + genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS).c_str(), true); } if (!flagsBuild.IsEmpty()) { @@ -1031,15 +1065,17 @@ struct cmSourceFilePathCompare struct cmCompareTargets { - bool operator()(std::string const& a, std::string const& b) const + bool operator()(cmXCodeObject* l, cmXCodeObject* r) const { + std::string const& a = l->GetTarget()->GetName(); + std::string const& b = r->GetTarget()->GetName(); if (a == "ALL_BUILD") { return true; } if (b == "ALL_BUILD") { return false; } - return strcmp(a.c_str(), b.c_str()) < 0; + return a < b; } }; @@ -1047,274 +1083,279 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets) { this->SetCurrentLocalGenerator(gen); - typedef std::map<std::string, cmGeneratorTarget*, cmCompareTargets> - cmSortedTargets; - cmSortedTargets sortedTargets; - for (auto tgt : this->CurrentLocalGenerator->GetGeneratorTargets()) { - sortedTargets[tgt->GetName()] = tgt; + std::vector<cmGeneratorTarget*> gts = + this->CurrentLocalGenerator->GetGeneratorTargets(); + std::sort(gts.begin(), gts.end(), + [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) { + return this->TargetOrderIndex[l] < this->TargetOrderIndex[r]; + }); + for (auto gtgt : gts) { + if (!this->CreateXCodeTarget(gtgt, targets)) { + return false; + } } - for (auto& sortedTarget : sortedTargets) { - cmGeneratorTarget* gtgt = sortedTarget.second; - - std::string targetName = gtgt->GetName(); + std::sort(targets.begin(), targets.end(), cmCompareTargets()); + return true; +} - // make sure ALL_BUILD, INSTALL, etc are only done once - if (this->SpecialTargetEmitted(targetName)) { - continue; - } +bool cmGlobalXCodeGenerator::CreateXCodeTarget( + cmGeneratorTarget* gtgt, std::vector<cmXCodeObject*>& targets) +{ + std::string targetName = gtgt->GetName(); - if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - continue; - } + // make sure ALL_BUILD, INSTALL, etc are only done once + if (this->SpecialTargetEmitted(targetName)) { + return true; + } - if (gtgt->GetType() == cmStateEnums::UTILITY || - gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { - cmXCodeObject* t = this->CreateUtilityTarget(gtgt); - if (!t) { - return false; - } - targets.push_back(t); - continue; - } + if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + return true; + } - // organize the sources - std::vector<cmSourceFile*> classes; - if (!gtgt->GetConfigCommonSourceFiles(classes)) { + if (gtgt->GetType() == cmStateEnums::UTILITY || + gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { + cmXCodeObject* t = this->CreateUtilityTarget(gtgt); + if (!t) { return false; } + targets.push_back(t); + return true; + } - // Add CMakeLists.txt file for user convenience. - this->AddXCodeProjBuildRule(gtgt, classes); + // organize the sources + std::vector<cmSourceFile*> classes; + if (!gtgt->GetConfigCommonSourceFiles(classes)) { + return false; + } - std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); + // Add CMakeLists.txt file for user convenience. + this->AddXCodeProjBuildRule(gtgt, classes); - gtgt->ComputeObjectMapping(); + std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); - std::vector<cmXCodeObject*> externalObjFiles; - std::vector<cmXCodeObject*> headerFiles; - std::vector<cmXCodeObject*> resourceFiles; - std::vector<cmXCodeObject*> sourceFiles; - for (auto sourceFile : classes) { - cmXCodeObject* xsf = this->CreateXCodeSourceFile( - this->CurrentLocalGenerator, sourceFile, gtgt); - cmXCodeObject* fr = xsf->GetObject("fileRef"); - cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); + gtgt->ComputeObjectMapping(); - cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(sourceFile); + std::vector<cmXCodeObject*> externalObjFiles; + std::vector<cmXCodeObject*> headerFiles; + std::vector<cmXCodeObject*> resourceFiles; + std::vector<cmXCodeObject*> sourceFiles; + for (auto sourceFile : classes) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, sourceFile, gtgt); + cmXCodeObject* fr = xsf->GetObject("fileRef"); + cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); - if (filetype && filetype->GetString() == "compiled.mach-o.objfile") { - if (sourceFile->GetObjectLibrary().empty()) { - externalObjFiles.push_back(xsf); - } - } else if (this->IsHeaderFile(sourceFile) || - (tsFlags.Type == - cmGeneratorTarget::SourceFileTypePrivateHeader) || - (tsFlags.Type == - cmGeneratorTarget::SourceFileTypePublicHeader)) { - headerFiles.push_back(xsf); - } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) { - resourceFiles.push_back(xsf); - } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) { - // Include this file in the build if it has a known language - // and has not been listed as an ignored extension for this - // generator. - if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile) - .empty() && - !this->IgnoreFile(sourceFile->GetExtension().c_str())) { - sourceFiles.push_back(xsf); - } - } - } + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(sourceFile); - if (this->XcodeVersion < 50) { - // Add object library contents as external objects. (Equivalent to - // the externalObjFiles above, except each one is not a cmSourceFile - // within the target.) - std::vector<cmSourceFile const*> objs; - gtgt->GetExternalObjects(objs, ""); - for (auto sourceFile : objs) { - if (sourceFile->GetObjectLibrary().empty()) { - continue; - } - std::string const& obj = sourceFile->GetFullPath(); - cmXCodeObject* xsf = - this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr); + if (filetype && filetype->GetString() == "compiled.mach-o.objfile") { + if (sourceFile->GetObjectLibrary().empty()) { externalObjFiles.push_back(xsf); } - } - - // some build phases only apply to bundles and/or frameworks - bool isFrameworkTarget = gtgt->IsFrameworkOnApple(); - bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE"); - bool isCFBundleTarget = gtgt->IsCFBundleOnApple(); - - cmXCodeObject* buildFiles = nullptr; - - // create source build phase - cmXCodeObject* sourceBuildPhase = nullptr; - if (!sourceFiles.empty()) { - sourceBuildPhase = - this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase); - sourceBuildPhase->SetComment("Sources"); - sourceBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for (auto& sourceFile : sourceFiles) { - buildFiles->AddObject(sourceFile); + } else if (this->IsHeaderFile(sourceFile) || + (tsFlags.Type == + cmGeneratorTarget::SourceFileTypePrivateHeader) || + (tsFlags.Type == + cmGeneratorTarget::SourceFileTypePublicHeader)) { + headerFiles.push_back(xsf); + } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) { + resourceFiles.push_back(xsf); + } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) { + // Include this file in the build if it has a known language + // and has not been listed as an ignored extension for this + // generator. + if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile) + .empty() && + !this->IgnoreFile(sourceFile->GetExtension().c_str())) { + sourceFiles.push_back(xsf); } - sourceBuildPhase->AddAttribute("files", buildFiles); - sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); } + } - // create header build phase - only for framework targets - cmXCodeObject* headerBuildPhase = nullptr; - if (!headerFiles.empty() && isFrameworkTarget) { - headerBuildPhase = - this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase); - headerBuildPhase->SetComment("Headers"); - headerBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for (auto& headerFile : headerFiles) { - buildFiles->AddObject(headerFile); + if (this->XcodeVersion < 50) { + // Add object library contents as external objects. (Equivalent to + // the externalObjFiles above, except each one is not a cmSourceFile + // within the target.) + std::vector<cmSourceFile const*> objs; + gtgt->GetExternalObjects(objs, ""); + for (auto sourceFile : objs) { + if (sourceFile->GetObjectLibrary().empty()) { + continue; } - headerBuildPhase->AddAttribute("files", buildFiles); - headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); + std::string const& obj = sourceFile->GetFullPath(); + cmXCodeObject* xsf = + this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr); + externalObjFiles.push_back(xsf); + } + } + + // some build phases only apply to bundles and/or frameworks + bool isFrameworkTarget = gtgt->IsFrameworkOnApple(); + bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE"); + bool isCFBundleTarget = gtgt->IsCFBundleOnApple(); + + cmXCodeObject* buildFiles = nullptr; + + // create source build phase + cmXCodeObject* sourceBuildPhase = nullptr; + if (!sourceFiles.empty()) { + sourceBuildPhase = this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase); + sourceBuildPhase->SetComment("Sources"); + sourceBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (auto& sourceFile : sourceFiles) { + buildFiles->AddObject(sourceFile); + } + sourceBuildPhase->AddAttribute("files", buildFiles); + sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } + + // create header build phase - only for framework targets + cmXCodeObject* headerBuildPhase = nullptr; + if (!headerFiles.empty() && isFrameworkTarget) { + headerBuildPhase = this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase); + headerBuildPhase->SetComment("Headers"); + headerBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (auto& headerFile : headerFiles) { + buildFiles->AddObject(headerFile); + } + headerBuildPhase->AddAttribute("files", buildFiles); + headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } + + // create resource build phase - only for framework or bundle targets + cmXCodeObject* resourceBuildPhase = nullptr; + if (!resourceFiles.empty() && + (isFrameworkTarget || isBundleTarget || isCFBundleTarget)) { + resourceBuildPhase = + this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase); + resourceBuildPhase->SetComment("Resources"); + resourceBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (auto& resourceFile : resourceFiles) { + buildFiles->AddObject(resourceFile); } + resourceBuildPhase->AddAttribute("files", buildFiles); + resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } - // create resource build phase - only for framework or bundle targets - cmXCodeObject* resourceBuildPhase = nullptr; - if (!resourceFiles.empty() && - (isFrameworkTarget || isBundleTarget || isCFBundleTarget)) { - resourceBuildPhase = - this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase); - resourceBuildPhase->SetComment("Resources"); - resourceBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for (auto& resourceFile : resourceFiles) { - buildFiles->AddObject(resourceFile); - } - resourceBuildPhase->AddAttribute("files", buildFiles); - resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - } - - // create vector of "non-resource content file" build phases - only for - // framework or bundle targets - std::vector<cmXCodeObject*> contentBuildPhases; - if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { - typedef std::map<std::string, std::vector<cmSourceFile*>> - mapOfVectorOfSourceFiles; - mapOfVectorOfSourceFiles bundleFiles; - for (auto sourceFile : classes) { - cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(sourceFile); - if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { - bundleFiles[tsFlags.MacFolder].push_back(sourceFile); - } + // create vector of "non-resource content file" build phases - only for + // framework or bundle targets + std::vector<cmXCodeObject*> contentBuildPhases; + if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { + typedef std::map<std::string, std::vector<cmSourceFile*>> + mapOfVectorOfSourceFiles; + mapOfVectorOfSourceFiles bundleFiles; + for (auto sourceFile : classes) { + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(sourceFile); + if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { + bundleFiles[tsFlags.MacFolder].push_back(sourceFile); } - for (auto keySources : bundleFiles) { - cmXCodeObject* copyFilesBuildPhase = - this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); - copyFilesBuildPhase->SetComment("Copy files"); - copyFilesBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", - this->CreateString("6")); - std::ostringstream ostr; - if (gtgt->IsFrameworkOnApple()) { - // dstPath in frameworks is relative to Versions/<version> + } + for (auto keySources : bundleFiles) { + cmXCodeObject* copyFilesBuildPhase = + this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); + copyFilesBuildPhase->SetComment("Copy files"); + copyFilesBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", + this->CreateString("6")); + std::ostringstream ostr; + if (gtgt->IsFrameworkOnApple()) { + // dstPath in frameworks is relative to Versions/<version> + ostr << keySources.first; + } else if (keySources.first != "MacOS") { + if (gtgt->Target->GetMakefile()->PlatformIsAppleEmbedded()) { ostr << keySources.first; - } else if (keySources.first != "MacOS") { - if (gtgt->Target->GetMakefile()->PlatformIsAppleEmbedded()) { - ostr << keySources.first; - } else { - // dstPath in bundles is relative to Contents/MacOS - ostr << "../" << keySources.first; - } - } - copyFilesBuildPhase->AddAttribute("dstPath", - this->CreateString(ostr.str())); - copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - copyFilesBuildPhase->AddAttribute("files", buildFiles); - for (auto sourceFile : keySources.second) { - cmXCodeObject* xsf = this->CreateXCodeSourceFile( - this->CurrentLocalGenerator, sourceFile, gtgt); - buildFiles->AddObject(xsf); + } else { + // dstPath in bundles is relative to Contents/MacOS + ostr << "../" << keySources.first; } - contentBuildPhases.push_back(copyFilesBuildPhase); } + copyFilesBuildPhase->AddAttribute("dstPath", + this->CreateString(ostr.str())); + copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + copyFilesBuildPhase->AddAttribute("files", buildFiles); + for (auto sourceFile : keySources.second) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, sourceFile, gtgt); + buildFiles->AddObject(xsf); + } + contentBuildPhases.push_back(copyFilesBuildPhase); } + } - // create vector of "resource content file" build phases - only for - // framework or bundle targets - if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { - typedef std::map<std::string, std::vector<cmSourceFile*>> - mapOfVectorOfSourceFiles; - mapOfVectorOfSourceFiles bundleFiles; - for (auto sourceFile : classes) { - cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(sourceFile); - if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) { - bundleFiles[tsFlags.MacFolder].push_back(sourceFile); - } - } - for (auto keySources : bundleFiles) { - cmXCodeObject* copyFilesBuildPhase = - this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); - copyFilesBuildPhase->SetComment("Copy files"); - copyFilesBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", - this->CreateString("7")); - copyFilesBuildPhase->AddAttribute( - "dstPath", this->CreateString(keySources.first)); - copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - copyFilesBuildPhase->AddAttribute("files", buildFiles); - for (auto sourceFile : keySources.second) { - cmXCodeObject* xsf = this->CreateXCodeSourceFile( - this->CurrentLocalGenerator, sourceFile, gtgt); - buildFiles->AddObject(xsf); - } - contentBuildPhases.push_back(copyFilesBuildPhase); + // create vector of "resource content file" build phases - only for + // framework or bundle targets + if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { + typedef std::map<std::string, std::vector<cmSourceFile*>> + mapOfVectorOfSourceFiles; + mapOfVectorOfSourceFiles bundleFiles; + for (auto sourceFile : classes) { + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(sourceFile); + if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) { + bundleFiles[tsFlags.MacFolder].push_back(sourceFile); } } - - // create framework build phase - cmXCodeObject* frameworkBuildPhase = nullptr; - if (!externalObjFiles.empty()) { - frameworkBuildPhase = - this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase); - frameworkBuildPhase->SetComment("Frameworks"); - frameworkBuildPhase->AddAttribute("buildActionMask", + for (auto keySources : bundleFiles) { + cmXCodeObject* copyFilesBuildPhase = + this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); + copyFilesBuildPhase->SetComment("Copy files"); + copyFilesBuildPhase->AddAttribute("buildActionMask", this->CreateString("2147483647")); + copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", + this->CreateString("7")); + copyFilesBuildPhase->AddAttribute("dstPath", + this->CreateString(keySources.first)); + copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - frameworkBuildPhase->AddAttribute("files", buildFiles); - for (auto& externalObjFile : externalObjFiles) { - buildFiles->AddObject(externalObjFile); + copyFilesBuildPhase->AddAttribute("files", buildFiles); + for (auto sourceFile : keySources.second) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, sourceFile, gtgt); + buildFiles->AddObject(xsf); } - frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); + contentBuildPhases.push_back(copyFilesBuildPhase); + } + } + + // create framework build phase + cmXCodeObject* frameworkBuildPhase = nullptr; + if (!externalObjFiles.empty()) { + frameworkBuildPhase = + this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase); + frameworkBuildPhase->SetComment("Frameworks"); + frameworkBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + frameworkBuildPhase->AddAttribute("files", buildFiles); + for (auto& externalObjFile : externalObjFiles) { + buildFiles->AddObject(externalObjFile); } + frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } - // create list of build phases and create the Xcode target - cmXCodeObject* buildPhases = - this->CreateObject(cmXCodeObject::OBJECT_LIST); + // create list of build phases and create the Xcode target + cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST); - this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase, - resourceBuildPhase, contentBuildPhases, - frameworkBuildPhase, gtgt); + this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase, + resourceBuildPhase, contentBuildPhases, + frameworkBuildPhase, gtgt); - targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases)); - } + targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases)); return true; } @@ -1803,7 +1844,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY || gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) { this->CurrentLocalGenerator->GetStaticLibraryFlags( - extraLinkOptions, cmSystemTools::UpperCase(configName), gtgt); + extraLinkOptions, cmSystemTools::UpperCase(configName), llang, gtgt); } else { const char* targetLinkFlags = gtgt->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { @@ -1817,6 +1858,10 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, linkFlags); } } + std::vector<std::string> opts; + gtgt->GetLinkOptions(opts, configName, llang); + // LINK_OPTIONS are escaped. + this->CurrentLocalGenerator->AppendCompileOptions(extraLinkOptions, opts); } // Set target-specific architectures. @@ -2995,7 +3040,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( // Point Xcode at the top of the source tree. { std::string pdir = - this->RelativeToBinary(root->GetCurrentSourceDirectory()); + this->RelativeToBinary(root->GetCurrentSourceDirectory().c_str()); this->RootObject->AddAttribute("projectDirPath", this->CreateString(pdir)); this->RootObject->AddAttribute("projectRoot", this->CreateString("")); } @@ -3315,13 +3360,6 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( if (generators.empty()) { return; } - // Skip local generators that are excluded from this project. - for (auto generator : generators) { - if (this->IsExcluded(root, generator)) { - continue; - } - } - if (!this->CreateXCodeObjects(root, generators)) { return; } diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index ccef6e21b..62f70302a 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -96,6 +96,8 @@ public: i.e. "Can I build Debug and Release in the same tree?" */ bool IsMultiConfig() const override; + bool IsXcode() const override { return true; } + bool HasKnownObjectFileLocation(std::string* reason) const override; bool IsIPOSupported() const override { return true; } @@ -109,6 +111,8 @@ public: protected: void AddExtraIDETargets() override; + void ComputeTargetOrder(); + void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index); void Generate() override; private: @@ -204,6 +208,8 @@ private: void AddXCodeProjBuildRule(cmGeneratorTarget* target, std::vector<cmSourceFile*>& sources) const; bool CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&); + bool CreateXCodeTarget(cmGeneratorTarget* gtgt, + std::vector<cmXCodeObject*>&); bool IsHeaderFile(cmSourceFile*); void AddDependTarget(cmXCodeObject* target, cmXCodeObject* dependTarget); void CreateXCodeDependHackTarget(std::vector<cmXCodeObject*>& targets); @@ -286,6 +292,7 @@ private: std::string ObjectDirArchDefault; std::string ObjectDirArch; std::string GeneratorToolset; + std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex; }; #endif diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index 1bbfbe03f..fcdf03fc9 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -257,7 +257,7 @@ void cmGraphVizWriter::WriteTargetDependersFiles(const char* fileName) currentFilename += ptr.first; currentFilename += ".dependers"; - cmGeneratedFileStream str(currentFilename.c_str()); + cmGeneratedFileStream str(currentFilename); if (!str) { return; } @@ -300,7 +300,7 @@ void cmGraphVizWriter::WritePerTargetFiles(const char* fileName) std::string currentFilename = fileName; currentFilename += "."; currentFilename += ptr.first; - cmGeneratedFileStream str(currentFilename.c_str()); + cmGeneratedFileStream str(currentFilename); if (!str) { return; } diff --git a/Source/cmHexFileConverter.cxx b/Source/cmHexFileConverter.cxx index 8deb8c183..4e29f399a 100644 --- a/Source/cmHexFileConverter.cxx +++ b/Source/cmHexFileConverter.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmHexFileConverter.h" +#include <ctype.h> #include <stdio.h> #include <string.h> @@ -12,13 +13,6 @@ #define MOTOROLA_SREC_MIN_LINE_LENGTH (2 + 2 + 4 + 2) #define MOTOROLA_SREC_MAX_LINE_LENGTH (2 + 2 + 8 + (256 * 2) + 2) -// might go to SystemTools ? -static bool cm_IsHexChar(char c) -{ - return (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) || - ((c >= 'A') && (c <= 'F'))); -} - static unsigned int ChompStrlen(const char* line) { if (line == nullptr) { @@ -169,7 +163,7 @@ cmHexFileConverter::FileType cmHexFileConverter::DetermineFileType( } for (unsigned int i = 1; i < slen; i++) { - if (!cm_IsHexChar(buf[i])) { + if (!isxdigit(buf[i])) { return Binary; } } diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index 4f80fb85a..caec67db7 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -5,6 +5,7 @@ #include <algorithm> #include <set> +#include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmSystemTools.h" @@ -69,11 +70,6 @@ bool cmIncludeDirectoryCommand::InitialPass( return true; } -static bool StartsWithGeneratorExpression(const std::string& input) -{ - return input[0] == '$' && input[1] == '<'; -} - // do a lot of cleanup on the arguments because this is one place where folks // sometimes take the output of a program and pass it directly into this // command not thinking that a single argument could be filled with spaces @@ -120,11 +116,11 @@ void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc) return; } - if (!cmSystemTools::IsOff(inc.c_str())) { + if (!cmSystemTools::IsOff(inc)) { cmSystemTools::ConvertToUnixSlashes(inc); if (!cmSystemTools::FileIsFullPath(inc)) { - if (!StartsWithGeneratorExpression(inc)) { + if (!cmGeneratorExpression::StartsWithGeneratorExpression(inc)) { std::string tmp = this->Makefile->GetCurrentSourceDirectory(); tmp += "/"; tmp += inc; diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 87dcb188d..6e33cf7a3 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -5,7 +5,6 @@ #include "cmsys/Glob.hxx" #include <sstream> #include <stddef.h> -#include <string.h> #include <utility> #include "cmAlgorithms.h" @@ -187,7 +186,7 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args) // Tell the global generator about any installation component names // specified. - this->Makefile->GetGlobalGenerator()->AddInstallComponent(component.c_str()); + this->Makefile->GetGlobalGenerator()->AddInstallComponent(component); return true; } @@ -350,8 +349,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // Check whether this is a DLL platform. bool dll_platform = - strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"), - "") != 0; + !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); for (std::string const& tgt : targetList.GetVector()) { @@ -362,7 +360,12 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) return false; } // Lookup this target in the current directory. - if (cmTarget* target = this->Makefile->FindLocalNonAliasTarget(tgt)) { + cmTarget* target = this->Makefile->FindLocalNonAliasTarget(tgt); + if (!target) { + // If no local target has been found, find it in the global scope. + target = this->Makefile->GetGlobalGenerator()->FindTarget(tgt, true); + } + if (target) { // Found the target. Check its type. if (target->GetType() != cmStateEnums::EXECUTABLE && target->GetType() != cmStateEnums::STATIC_LIBRARY && @@ -381,8 +384,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } else { // Did not find the target. std::ostringstream e; - e << "TARGETS given target \"" << tgt - << "\" which does not exist in this directory."; + e << "TARGETS given target \"" << tgt << "\" which does not exist."; this->SetError(e.str()); return false; } @@ -757,43 +759,43 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // specified if (installsArchive) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( - archiveArgs.GetComponent().c_str()); + archiveArgs.GetComponent()); } if (installsLibrary) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( - libraryArgs.GetComponent().c_str()); + libraryArgs.GetComponent()); } if (installsNamelink) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( - libraryArgs.GetNamelinkComponent().c_str()); + libraryArgs.GetNamelinkComponent()); } if (installsRuntime) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( - runtimeArgs.GetComponent().c_str()); + runtimeArgs.GetComponent()); } if (installsObject) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( - objectArgs.GetComponent().c_str()); + objectArgs.GetComponent()); } if (installsFramework) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( - frameworkArgs.GetComponent().c_str()); + frameworkArgs.GetComponent()); } if (installsBundle) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( - bundleArgs.GetComponent().c_str()); + bundleArgs.GetComponent()); } if (installsPrivateHeader) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( - privateHeaderArgs.GetComponent().c_str()); + privateHeaderArgs.GetComponent()); } if (installsPublicHeader) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( - publicHeaderArgs.GetComponent().c_str()); + publicHeaderArgs.GetComponent()); } if (installsResource) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( - resourceArgs.GetComponent().c_str()); + resourceArgs.GetComponent()); } return true; @@ -895,7 +897,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) // Tell the global generator about any installation component names // specified. this->Makefile->GetGlobalGenerator()->AddInstallComponent( - ica.GetComponent().c_str()); + ica.GetComponent()); return true; } @@ -1192,7 +1194,7 @@ bool cmInstallCommand::HandleDirectoryMode( // Tell the global generator about any installation component names // specified. - this->Makefile->GetGlobalGenerator()->AddInstallComponent(component.c_str()); + this->Makefile->GetGlobalGenerator()->AddInstallComponent(component); return true; } diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index b569b731b..c9b50a3b6 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -73,7 +73,7 @@ void cmInstallDirectoryGenerator::GenerateScriptForConfig( cmMakefile const& mf = *this->LocalGenerator->GetMakefile(); for (std::string& d : dirs) { if (!cmSystemTools::FileIsFullPath(d)) { - d = std::string(mf.GetCurrentSourceDirectory()) + "/" + d; + d = mf.GetCurrentSourceDirectory() + "/" + d; } } diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index e0afa2d4d..8b8f79b98 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -440,7 +440,13 @@ std::string cmInstallTargetGenerator::GetInstallFilename( void cmInstallTargetGenerator::Compute(cmLocalGenerator* lg) { + // Lookup this target in the current directory. this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName); + if (!this->Target) { + // If no local target has been found, find it in the global scope. + this->Target = + lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName); + } } void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent, diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index 3ffeabdb5..0e0602981 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -102,7 +102,7 @@ bool cmInstalledFile::GetPropertyAsBool(const std::string& prop) const { std::string value; bool isSet = this->GetProperty(prop, value); - return isSet && cmSystemTools::IsOn(value.c_str()); + return isSet && cmSystemTools::IsOn(value); } void cmInstalledFile::GetPropertyAsList(const std::string& prop, diff --git a/Source/cmJsonObjectDictionary.h b/Source/cmJsonObjectDictionary.h new file mode 100644 index 000000000..8a2b52995 --- /dev/null +++ b/Source/cmJsonObjectDictionary.h @@ -0,0 +1,45 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include <string> + +// Vocabulary: + +static const std::string kARTIFACTS_KEY = "artifacts"; +static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory"; +static const std::string kCOMPILE_FLAGS_KEY = "compileFlags"; +static const std::string kCONFIGURATIONS_KEY = "configurations"; +static const std::string kDEFINES_KEY = "defines"; +static const std::string kFILE_GROUPS_KEY = "fileGroups"; +static const std::string kFRAMEWORK_PATH_KEY = "frameworkPath"; +static const std::string kFULL_NAME_KEY = "fullName"; +static const std::string kINCLUDE_PATH_KEY = "includePath"; +static const std::string kIS_CMAKE_KEY = "isCMake"; +static const std::string kIS_GENERATED_KEY = "isGenerated"; +static const std::string kIS_SYSTEM_KEY = "isSystem"; +static const std::string kIS_TEMPORARY_KEY = "isTemporary"; +static const std::string kKEY_KEY = "key"; +static const std::string kLANGUAGE_KEY = "language"; +static const std::string kLINKER_LANGUAGE_KEY = "linkerLanguage"; +static const std::string kLINK_FLAGS_KEY = "linkFlags"; +static const std::string kLINK_LANGUAGE_FLAGS_KEY = "linkLanguageFlags"; +static const std::string kLINK_LIBRARIES_KEY = "linkLibraries"; +static const std::string kLINK_PATH_KEY = "linkPath"; +static const std::string kNAME_KEY = "name"; +static const std::string kPATH_KEY = "path"; +static const std::string kPROJECTS_KEY = "projects"; +static const std::string kPROPERTIES_KEY = "properties"; +static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory"; +static const std::string kSOURCES_KEY = "sources"; +static const std::string kSYSROOT_KEY = "sysroot"; +static const std::string kTARGETS_KEY = "targets"; +static const std::string kTYPE_KEY = "type"; +static const std::string kVALUE_KEY = "value"; +static const std::string kHAS_INSTALL_RULE = "hasInstallRule"; +static const std::string kINSTALL_PATHS = "installPaths"; +static const std::string kCTEST_NAME = "ctestName"; +static const std::string kCTEST_COMMAND = "ctestCommand"; +static const std::string kCTEST_INFO = "ctestInfo"; +static const std::string kMINIMUM_CMAKE_VERSION = "minimumCMakeVersion"; +static const std::string kIS_GENERATOR_PROVIDED_KEY = "isGeneratorProvided"; diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx new file mode 100644 index 000000000..4148894f3 --- /dev/null +++ b/Source/cmJsonObjects.cxx @@ -0,0 +1,687 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmJsonObjects.h" // IWYU pragma: keep + +#include "cmGeneratorExpression.h" +#include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" +#include "cmInstallGenerator.h" +#include "cmInstallTargetGenerator.h" +#include "cmJsonObjectDictionary.h" +#include "cmJsonObjects.h" +#include "cmLinkLineComputer.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmProperty.h" +#include "cmSourceFile.h" +#include "cmState.h" +#include "cmStateDirectory.h" +#include "cmStateSnapshot.h" +#include "cmStateTypes.h" +#include "cmSystemTools.h" +#include "cmTarget.h" +#include "cmTest.h" +#include "cmake.h" + +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <functional> +#include <limits> +#include <map> +#include <set> +#include <string> +#include <unordered_map> +#include <utility> +#include <vector> + +namespace { + +std::vector<std::string> getConfigurations(const cmake* cm) +{ + std::vector<std::string> configurations; + auto makefiles = cm->GetGlobalGenerator()->GetMakefiles(); + if (makefiles.empty()) { + return configurations; + } + + makefiles[0]->GetConfigurations(configurations); + if (configurations.empty()) { + configurations.push_back(""); + } + return configurations; +} + +bool hasString(const Json::Value& v, const std::string& s) +{ + return !v.isNull() && + std::any_of(v.begin(), v.end(), + [s](const Json::Value& i) { return i.asString() == s; }); +} + +template <class T> +Json::Value fromStringList(const T& in) +{ + Json::Value result = Json::arrayValue; + for (std::string const& i : in) { + result.append(i); + } + return result; +} + +} // namespace + +void cmGetCMakeInputs(const cmGlobalGenerator* gg, + const std::string& sourceDir, + const std::string& buildDir, + std::vector<std::string>* internalFiles, + std::vector<std::string>* explicitFiles, + std::vector<std::string>* tmpFiles) +{ + const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/'; + std::vector<cmMakefile*> const& makefiles = gg->GetMakefiles(); + for (cmMakefile const* mf : makefiles) { + for (std::string const& lf : mf->GetListFiles()) { + + const std::string startOfFile = lf.substr(0, cmakeRootDir.size()); + const bool isInternal = (startOfFile == cmakeRootDir); + const bool isTemporary = !isInternal && (lf.find(buildDir + '/') == 0); + + std::string toAdd = lf; + if (!sourceDir.empty()) { + const std::string& relative = + cmSystemTools::RelativePath(sourceDir, lf); + if (toAdd.size() > relative.size()) { + toAdd = relative; + } + } + + if (isInternal) { + if (internalFiles) { + internalFiles->push_back(std::move(toAdd)); + } + } else { + if (isTemporary) { + if (tmpFiles) { + tmpFiles->push_back(std::move(toAdd)); + } + } else { + if (explicitFiles) { + explicitFiles->push_back(std::move(toAdd)); + } + } + } + } + } +} + +Json::Value cmDumpCMakeInputs(const cmake* cm) +{ + const cmGlobalGenerator* gg = cm->GetGlobalGenerator(); + const std::string& buildDir = cm->GetHomeOutputDirectory(); + const std::string& sourceDir = cm->GetHomeDirectory(); + + std::vector<std::string> internalFiles; + std::vector<std::string> explicitFiles; + std::vector<std::string> tmpFiles; + cmGetCMakeInputs(gg, sourceDir, buildDir, &internalFiles, &explicitFiles, + &tmpFiles); + + Json::Value array = Json::arrayValue; + + Json::Value tmp = Json::objectValue; + tmp[kIS_CMAKE_KEY] = true; + tmp[kIS_TEMPORARY_KEY] = false; + tmp[kSOURCES_KEY] = fromStringList(internalFiles); + array.append(tmp); + + tmp = Json::objectValue; + tmp[kIS_CMAKE_KEY] = false; + tmp[kIS_TEMPORARY_KEY] = false; + tmp[kSOURCES_KEY] = fromStringList(explicitFiles); + array.append(tmp); + + tmp = Json::objectValue; + tmp[kIS_CMAKE_KEY] = false; + tmp[kIS_TEMPORARY_KEY] = true; + tmp[kSOURCES_KEY] = fromStringList(tmpFiles); + array.append(tmp); + + return array; +} + +class LanguageData +{ +public: + bool operator==(const LanguageData& other) const; + + void SetDefines(const std::set<std::string>& defines); + + bool IsGenerated = false; + std::string Language; + std::string Flags; + std::vector<std::string> Defines; + std::vector<std::pair<std::string, bool>> IncludePathList; +}; + +bool LanguageData::operator==(const LanguageData& other) const +{ + return Language == other.Language && Defines == other.Defines && + Flags == other.Flags && IncludePathList == other.IncludePathList && + IsGenerated == other.IsGenerated; +} + +void LanguageData::SetDefines(const std::set<std::string>& defines) +{ + std::vector<std::string> result; + result.reserve(defines.size()); + for (std::string const& i : defines) { + result.push_back(i); + } + std::sort(result.begin(), result.end()); + Defines = std::move(result); +} + +namespace std { + +template <> +struct hash<LanguageData> +{ + std::size_t operator()(const LanguageData& in) const + { + using std::hash; + size_t result = + hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags); + for (auto const& i : in.IncludePathList) { + result = result ^ + (hash<std::string>()(i.first) ^ + (i.second ? std::numeric_limits<size_t>::max() : 0)); + } + for (auto const& i : in.Defines) { + result = result ^ hash<std::string>()(i); + } + result = + result ^ (in.IsGenerated ? std::numeric_limits<size_t>::max() : 0); + return result; + } +}; + +} // namespace std + +static Json::Value DumpSourceFileGroup(const LanguageData& data, + const std::vector<std::string>& files, + const std::string& baseDir) +{ + Json::Value result = Json::objectValue; + + if (!data.Language.empty()) { + result[kLANGUAGE_KEY] = data.Language; + if (!data.Flags.empty()) { + result[kCOMPILE_FLAGS_KEY] = data.Flags; + } + if (!data.IncludePathList.empty()) { + Json::Value includes = Json::arrayValue; + for (auto const& i : data.IncludePathList) { + Json::Value tmp = Json::objectValue; + tmp[kPATH_KEY] = i.first; + if (i.second) { + tmp[kIS_SYSTEM_KEY] = i.second; + } + includes.append(tmp); + } + result[kINCLUDE_PATH_KEY] = includes; + } + if (!data.Defines.empty()) { + result[kDEFINES_KEY] = fromStringList(data.Defines); + } + } + + result[kIS_GENERATED_KEY] = data.IsGenerated; + + Json::Value sourcesValue = Json::arrayValue; + for (auto const& i : files) { + const std::string relPath = cmSystemTools::RelativePath(baseDir, i); + sourcesValue.append(relPath.size() < i.size() ? relPath : i); + } + + result[kSOURCES_KEY] = sourcesValue; + return result; +} + +static Json::Value DumpSourceFilesList( + cmGeneratorTarget* target, const std::string& config, + const std::map<std::string, LanguageData>& languageDataMap) +{ + // Collect sourcefile groups: + + std::vector<cmSourceFile*> files; + target->GetSourceFiles(files, config); + + std::unordered_map<LanguageData, std::vector<std::string>> fileGroups; + for (cmSourceFile* file : files) { + LanguageData fileData; + fileData.Language = file->GetLanguage(); + if (!fileData.Language.empty()) { + const LanguageData& ld = languageDataMap.at(fileData.Language); + cmLocalGenerator* lg = target->GetLocalGenerator(); + cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, + fileData.Language); + + std::string compileFlags = ld.Flags; + const std::string COMPILE_FLAGS("COMPILE_FLAGS"); + if (const char* cflags = file->GetProperty(COMPILE_FLAGS)) { + lg->AppendFlags(compileFlags, + genexInterpreter.Evaluate(cflags, COMPILE_FLAGS)); + } + const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); + if (const char* coptions = file->GetProperty(COMPILE_OPTIONS)) { + lg->AppendCompileOptions( + compileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS)); + } + fileData.Flags = compileFlags; + + // Add include directories from source file properties. + std::vector<std::string> includes; + + const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); + if (const char* cincludes = file->GetProperty(INCLUDE_DIRECTORIES)) { + const std::string& evaluatedIncludes = + genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES); + lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file); + + for (const auto& include : includes) { + fileData.IncludePathList.push_back( + std::make_pair(include, + target->IsSystemIncludeDirectory( + include, config, fileData.Language))); + } + } + + fileData.IncludePathList.insert(fileData.IncludePathList.end(), + ld.IncludePathList.begin(), + ld.IncludePathList.end()); + + const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); + std::set<std::string> defines; + if (const char* defs = file->GetProperty(COMPILE_DEFINITIONS)) { + lg->AppendDefines( + defines, genexInterpreter.Evaluate(defs, COMPILE_DEFINITIONS)); + } + + const std::string defPropName = + "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config); + if (const char* config_defs = file->GetProperty(defPropName)) { + lg->AppendDefines( + defines, + genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS)); + } + + defines.insert(ld.Defines.begin(), ld.Defines.end()); + + fileData.SetDefines(defines); + } + + fileData.IsGenerated = file->GetPropertyAsBool("GENERATED"); + std::vector<std::string>& groupFileList = fileGroups[fileData]; + groupFileList.push_back(file->GetFullPath()); + } + + const std::string& baseDir = target->Makefile->GetCurrentSourceDirectory(); + Json::Value result = Json::arrayValue; + for (auto const& it : fileGroups) { + Json::Value group = DumpSourceFileGroup(it.first, it.second, baseDir); + if (!group.isNull()) { + result.append(group); + } + } + + return result; +} + +static Json::Value DumpCTestInfo(cmLocalGenerator* lg, cmTest* testInfo, + const std::string& config) +{ + Json::Value result = Json::objectValue; + result[kCTEST_NAME] = testInfo->GetName(); + + // Concat command entries together. After the first should be the arguments + // for the command + std::string command; + for (auto const& cmd : testInfo->GetCommand()) { + command.append(cmd); + command.append(" "); + } + + // Remove any config specific variables from the output. + cmGeneratorExpression ge; + auto cge = ge.Parse(command); + const std::string& processed = cge->Evaluate(lg, config); + result[kCTEST_COMMAND] = processed; + + // Build up the list of properties that may have been specified + Json::Value properties = Json::arrayValue; + for (auto& prop : testInfo->GetProperties()) { + Json::Value entry = Json::objectValue; + entry[kKEY_KEY] = prop.first; + + // Remove config variables from the value too. + auto cge_value = ge.Parse(prop.second.GetValue()); + const std::string& processed_value = cge_value->Evaluate(lg, config); + entry[kVALUE_KEY] = processed_value; + properties.append(entry); + } + result[kPROPERTIES_KEY] = properties; + + return result; +} + +static void DumpMakefileTests(cmLocalGenerator* lg, const std::string& config, + Json::Value* result) +{ + auto mf = lg->GetMakefile(); + std::vector<cmTest*> tests; + mf->GetTests(config, tests); + for (auto test : tests) { + Json::Value tmp = DumpCTestInfo(lg, test, config); + if (!tmp.isNull()) { + result->append(tmp); + } + } +} + +static Json::Value DumpCTestProjectList(const cmake* cm, + std::string const& config) +{ + Json::Value result = Json::arrayValue; + + auto globalGen = cm->GetGlobalGenerator(); + + for (const auto& projectIt : globalGen->GetProjectMap()) { + Json::Value pObj = Json::objectValue; + pObj[kNAME_KEY] = projectIt.first; + + Json::Value tests = Json::arrayValue; + + // Gather tests for every generator + for (const auto& lg : projectIt.second) { + // Make sure they're generated. + lg->GenerateTestFiles(); + DumpMakefileTests(lg, config, &tests); + } + + pObj[kCTEST_INFO] = tests; + + result.append(pObj); + } + + return result; +} + +static Json::Value DumpCTestConfiguration(const cmake* cm, + const std::string& config) +{ + Json::Value result = Json::objectValue; + result[kNAME_KEY] = config; + + result[kPROJECTS_KEY] = DumpCTestProjectList(cm, config); + + return result; +} + +static Json::Value DumpCTestConfigurationsList(const cmake* cm) +{ + Json::Value result = Json::arrayValue; + + for (const std::string& c : getConfigurations(cm)) { + result.append(DumpCTestConfiguration(cm, c)); + } + + return result; +} + +Json::Value cmDumpCTestInfo(const cmake* cm) +{ + Json::Value result = Json::objectValue; + result[kCONFIGURATIONS_KEY] = DumpCTestConfigurationsList(cm); + return result; +} + +static Json::Value DumpTarget(cmGeneratorTarget* target, + const std::string& config) +{ + cmLocalGenerator* lg = target->GetLocalGenerator(); + const cmState* state = lg->GetState(); + + const cmStateEnums::TargetType type = target->GetType(); + const std::string typeName = state->GetTargetTypeName(type); + + Json::Value ttl = Json::arrayValue; + ttl.append("EXECUTABLE"); + ttl.append("STATIC_LIBRARY"); + ttl.append("SHARED_LIBRARY"); + ttl.append("MODULE_LIBRARY"); + ttl.append("OBJECT_LIBRARY"); + ttl.append("UTILITY"); + ttl.append("INTERFACE_LIBRARY"); + + if (!hasString(ttl, typeName) || target->IsImported()) { + return Json::Value(); + } + + Json::Value result = Json::objectValue; + result[kNAME_KEY] = target->GetName(); + result[kIS_GENERATOR_PROVIDED_KEY] = + target->Target->GetIsGeneratorProvided(); + result[kTYPE_KEY] = typeName; + result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory(); + result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory(); + + if (type == cmStateEnums::INTERFACE_LIBRARY) { + return result; + } + + result[kFULL_NAME_KEY] = target->GetFullName(config); + + if (target->Target->GetHaveInstallRule()) { + result[kHAS_INSTALL_RULE] = true; + + Json::Value installPaths = Json::arrayValue; + auto targetGenerators = target->Makefile->GetInstallGenerators(); + for (auto installGenerator : targetGenerators) { + auto installTargetGenerator = + dynamic_cast<cmInstallTargetGenerator*>(installGenerator); + if (installTargetGenerator != nullptr && + installTargetGenerator->GetTarget()->Target == target->Target) { + auto dest = installTargetGenerator->GetDestination(config); + + std::string installPath; + if (!dest.empty() && cmSystemTools::FileIsFullPath(dest)) { + installPath = dest; + } else { + std::string installPrefix = + target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); + installPath = installPrefix + '/' + dest; + } + + installPaths.append(installPath); + } + } + + result[kINSTALL_PATHS] = installPaths; + } + + if (target->HaveWellDefinedOutputFiles()) { + Json::Value artifacts = Json::arrayValue; + artifacts.append( + target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact)); + if (target->IsDLLPlatform()) { + artifacts.append( + target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); + const cmGeneratorTarget::OutputInfo* output = + target->GetOutputInfo(config); + if (output && !output->PdbDir.empty()) { + artifacts.append(output->PdbDir + '/' + target->GetPDBName(config)); + } + } + result[kARTIFACTS_KEY] = artifacts; + + result[kLINKER_LANGUAGE_KEY] = target->GetLinkerLanguage(config); + + std::string linkLibs; + std::string linkFlags; + std::string linkLanguageFlags; + std::string frameworkPath; + std::string linkPath; + cmLinkLineComputer linkLineComputer(lg, + lg->GetStateSnapshot().GetDirectory()); + lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags, + linkFlags, frameworkPath, linkPath, target); + + linkLibs = cmSystemTools::TrimWhitespace(linkLibs); + linkFlags = cmSystemTools::TrimWhitespace(linkFlags); + linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags); + frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath); + linkPath = cmSystemTools::TrimWhitespace(linkPath); + + if (!cmSystemTools::TrimWhitespace(linkLibs).empty()) { + result[kLINK_LIBRARIES_KEY] = linkLibs; + } + if (!cmSystemTools::TrimWhitespace(linkFlags).empty()) { + result[kLINK_FLAGS_KEY] = linkFlags; + } + if (!cmSystemTools::TrimWhitespace(linkLanguageFlags).empty()) { + result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags; + } + if (!frameworkPath.empty()) { + result[kFRAMEWORK_PATH_KEY] = frameworkPath; + } + if (!linkPath.empty()) { + result[kLINK_PATH_KEY] = linkPath; + } + const std::string sysroot = + lg->GetMakefile()->GetSafeDefinition("CMAKE_SYSROOT"); + if (!sysroot.empty()) { + result[kSYSROOT_KEY] = sysroot; + } + } + + std::set<std::string> languages; + target->GetLanguages(languages, config); + std::map<std::string, LanguageData> languageDataMap; + + for (std::string const& lang : languages) { + LanguageData& ld = languageDataMap[lang]; + ld.Language = lang; + lg->GetTargetCompileFlags(target, config, lang, ld.Flags); + std::set<std::string> defines; + lg->GetTargetDefines(target, config, lang, defines); + ld.SetDefines(defines); + std::vector<std::string> includePathList; + lg->GetIncludeDirectories(includePathList, target, lang, config, true); + for (std::string const& i : includePathList) { + ld.IncludePathList.push_back( + std::make_pair(i, target->IsSystemIncludeDirectory(i, config, lang))); + } + } + + Json::Value sourceGroupsValue = + DumpSourceFilesList(target, config, languageDataMap); + if (!sourceGroupsValue.empty()) { + result[kFILE_GROUPS_KEY] = sourceGroupsValue; + } + + return result; +} + +static Json::Value DumpTargetsList( + const std::vector<cmLocalGenerator*>& generators, const std::string& config) +{ + Json::Value result = Json::arrayValue; + + std::vector<cmGeneratorTarget*> targetList; + for (auto const& lgIt : generators) { + const auto& list = lgIt->GetGeneratorTargets(); + targetList.insert(targetList.end(), list.begin(), list.end()); + } + std::sort(targetList.begin(), targetList.end()); + + for (cmGeneratorTarget* target : targetList) { + Json::Value tmp = DumpTarget(target, config); + if (!tmp.isNull()) { + result.append(tmp); + } + } + + return result; +} + +static Json::Value DumpProjectList(const cmake* cm, std::string const& config) +{ + Json::Value result = Json::arrayValue; + + auto globalGen = cm->GetGlobalGenerator(); + + for (auto const& projectIt : globalGen->GetProjectMap()) { + Json::Value pObj = Json::objectValue; + pObj[kNAME_KEY] = projectIt.first; + + // All Projects must have at least one local generator + assert(!projectIt.second.empty()); + const cmLocalGenerator* lg = projectIt.second.at(0); + + // Project structure information: + const cmMakefile* mf = lg->GetMakefile(); + auto minVersion = mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); + pObj[kMINIMUM_CMAKE_VERSION] = minVersion ? minVersion : ""; + pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory(); + pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory(); + pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config); + + // For a project-level install rule it might be defined in any of its + // associated generators. + bool hasInstallRule = false; + for (const auto generator : projectIt.second) { + hasInstallRule = + generator->GetMakefile()->GetInstallGenerators().empty() == false; + + if (hasInstallRule) { + break; + } + } + + pObj[kHAS_INSTALL_RULE] = hasInstallRule; + + result.append(pObj); + } + + return result; +} + +static Json::Value DumpConfiguration(const cmake* cm, + const std::string& config) +{ + Json::Value result = Json::objectValue; + result[kNAME_KEY] = config; + + result[kPROJECTS_KEY] = DumpProjectList(cm, config); + + return result; +} + +static Json::Value DumpConfigurationsList(const cmake* cm) +{ + Json::Value result = Json::arrayValue; + + for (std::string const& c : getConfigurations(cm)) { + result.append(DumpConfiguration(cm, c)); + } + + return result; +} + +Json::Value cmDumpCodeModel(const cmake* cm) +{ + Json::Value result = Json::objectValue; + result[kCONFIGURATIONS_KEY] = DumpConfigurationsList(cm); + return result; +} diff --git a/Source/cmJsonObjects.h b/Source/cmJsonObjects.h new file mode 100644 index 000000000..cd4da94f4 --- /dev/null +++ b/Source/cmJsonObjects.h @@ -0,0 +1,27 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmJsonObjects_h +#define cmJsonObjects_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_jsoncpp_value.h" + +#include <string> +#include <vector> + +class cmake; +class cmGlobalGenerator; + +extern void cmGetCMakeInputs(const cmGlobalGenerator* gg, + const std::string& sourceDir, + const std::string& buildDir, + std::vector<std::string>* internalFiles, + std::vector<std::string>* explicitFiles, + std::vector<std::string>* tmpFiles); + +extern Json::Value cmDumpCodeModel(const cmake* cm); +extern Json::Value cmDumpCTestInfo(const cmake* cm); +extern Json::Value cmDumpCMakeInputs(const cmake* cm); + +#endif diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx index 1371c5352..10425fdb7 100644 --- a/Source/cmLinkDirectoriesCommand.cxx +++ b/Source/cmLinkDirectoriesCommand.cxx @@ -4,6 +4,8 @@ #include <sstream> +#include "cmAlgorithms.h" +#include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmPolicies.h" #include "cmSystemTools.h" @@ -19,17 +21,34 @@ bool cmLinkDirectoriesCommand::InitialPass( return true; } - for (std::string const& i : args) { - this->AddLinkDir(i); + bool before = this->Makefile->IsOn("CMAKE_LINK_DIRECTORIES_BEFORE"); + + auto i = args.cbegin(); + if ((*i) == "BEFORE") { + before = true; + ++i; + } else if ((*i) == "AFTER") { + before = false; + ++i; + } + + std::vector<std::string> directories; + for (; i != args.cend(); ++i) { + this->AddLinkDir(*i, directories); } + + this->Makefile->AddLinkDirectory(cmJoin(directories, ";"), before); + return true; } -void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir) +void cmLinkDirectoriesCommand::AddLinkDir( + std::string const& dir, std::vector<std::string>& directories) { std::string unixPath = dir; cmSystemTools::ConvertToUnixSlashes(unixPath); - if (!cmSystemTools::FileIsFullPath(unixPath)) { + if (!cmSystemTools::FileIsFullPath(unixPath) && + !cmGeneratorExpression::StartsWithGeneratorExpression(unixPath)) { bool convertToAbsolute = false; std::ostringstream e; /* clang-format off */ @@ -41,6 +60,7 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir) case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015); this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + break; case cmPolicies::OLD: // OLD behavior does not convert break; @@ -61,5 +81,5 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir) unixPath = tmp; } } - this->Makefile->AppendProperty("LINK_DIRECTORIES", unixPath.c_str()); + directories.push_back(unixPath); } diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h index 3fd4e50ab..ae4fb7f5f 100644 --- a/Source/cmLinkDirectoriesCommand.h +++ b/Source/cmLinkDirectoriesCommand.h @@ -36,7 +36,8 @@ public: cmExecutionStatus& status) override; private: - void AddLinkDir(std::string const& dir); + void AddLinkDir(std::string const& dir, + std::vector<std::string>& directories); }; #endif diff --git a/Source/cmLinkItem.cxx b/Source/cmLinkItem.cxx new file mode 100644 index 000000000..69b6821c1 --- /dev/null +++ b/Source/cmLinkItem.cxx @@ -0,0 +1,72 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmLinkItem.h" + +#include "cmGeneratorTarget.h" + +#include <utility> // IWYU pragma: keep + +cmLinkItem::cmLinkItem() + : String() + , Target(nullptr) +{ +} + +cmLinkItem::cmLinkItem(std::string const& n) + : String(n) + , Target(nullptr) +{ +} + +cmLinkItem::cmLinkItem(cmGeneratorTarget const* t) + : String() + , Target(t) +{ +} + +std::string const& cmLinkItem::AsStr() const +{ + return this->Target ? this->Target->GetName() : this->String; +} + +bool operator<(cmLinkItem const& l, cmLinkItem const& r) +{ + // Order among targets. + if (l.Target && r.Target) { + return l.Target < r.Target; + } + // Order targets before strings. + if (l.Target) { + return true; + } + if (r.Target) { + return false; + } + // Order among strings. + return l.String < r.String; +} + +bool operator==(cmLinkItem const& l, cmLinkItem const& r) +{ + return l.Target == r.Target && l.String == r.String; +} + +std::ostream& operator<<(std::ostream& os, cmLinkItem const& item) +{ + return os << item.AsStr(); +} + +cmLinkImplItem::cmLinkImplItem() + : cmLinkItem() + , Backtrace() + , FromGenex(false) +{ +} + +cmLinkImplItem::cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt, + bool fromGenex) + : cmLinkItem(std::move(item)) + , Backtrace(bt) + , FromGenex(fromGenex) +{ +} diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index e8c94871b..74fd298e4 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -7,6 +7,7 @@ #include <algorithm> #include <map> +#include <ostream> #include <string> #include <vector> @@ -17,40 +18,27 @@ class cmGeneratorTarget; // Basic information about each link item. -class cmLinkItem : public std::string +class cmLinkItem { - typedef std::string std_string; + std::string String; public: - cmLinkItem() - : std_string() - , Target(nullptr) - { - } - cmLinkItem(const std_string& n, cmGeneratorTarget const* t) - : std_string(n) - , Target(t) - { - } + cmLinkItem(); + explicit cmLinkItem(std::string const& s); + explicit cmLinkItem(cmGeneratorTarget const* t); + std::string const& AsStr() const; cmGeneratorTarget const* Target; + friend bool operator<(cmLinkItem const& l, cmLinkItem const& r); + friend bool operator==(cmLinkItem const& l, cmLinkItem const& r); + friend std::ostream& operator<<(std::ostream& os, cmLinkItem const& item); }; class cmLinkImplItem : public cmLinkItem { public: - cmLinkImplItem() - : cmLinkItem() - , Backtrace() - , FromGenex(false) - { - } - cmLinkImplItem(std::string const& n, cmGeneratorTarget const* t, - cmListFileBacktrace const& bt, bool fromGenex) - : cmLinkItem(n, t) - , Backtrace(bt) - , FromGenex(fromGenex) - { - } + cmLinkImplItem(); + cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt, + bool fromGenex); cmListFileBacktrace Backtrace; bool FromGenex; }; diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 20bd5378c..a93ec1271 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -3,7 +3,9 @@ #include "cmLinkLineDeviceComputer.h" +#include <set> #include <sstream> +#include <utility> #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" @@ -45,6 +47,12 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( { // Write the library flags to the build rule. std::ostringstream fout; + + // Generate the unique set of link items when device linking. + // The nvcc device linker is designed so that each static library + // with device symbols only needs to be listed once as it doesn't + // care about link order. + std::set<std::string> emitted; typedef cmComputeLinkInformation::ItemVector ItemVector; ItemVector const& items = cli.GetItems(); std::string config = cli.GetConfig(); @@ -67,6 +75,7 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( } } + std::string out; if (item.IsPath) { // nvcc understands absolute paths to libraries ending in '.a' or '.lib'. // These should be passed to nvlink. Other extensions need to be left @@ -74,13 +83,16 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( // can tolerate '.so' or '.dylib' it cannot tolerate '.so.1'. if (cmHasLiteralSuffix(item.Value, ".a") || cmHasLiteralSuffix(item.Value, ".lib")) { - fout << this->ConvertToOutputFormat( + out += this->ConvertToOutputFormat( this->ConvertToLinkReference(item.Value)); } } else if (cmLinkItemValidForDevice(item.Value)) { - fout << item.Value; + out += item.Value; + } + + if (emitted.insert(out).second) { + fout << out << " "; } - fout << " "; } if (!stdLibString.empty()) { diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index 1ac2cc2bf..d7de2fa5b 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -289,12 +289,10 @@ bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args) if (item < 0) { item = static_cast<int>(nitem) + item; } - if (item < 0 || nitem <= static_cast<size_t>(item)) { + if (item < 0 || nitem < static_cast<size_t>(item)) { std::ostringstream str; str << "index: " << item << " out of range (-" << varArgsExpanded.size() - << ", " - << (varArgsExpanded.empty() ? 0 : (varArgsExpanded.size() - 1)) - << ")"; + << ", " << varArgsExpanded.size() << ")"; this->SetError(str.str()); return false; } @@ -963,14 +961,193 @@ bool cmListCommand::HandleTransformCommand( return true; } +class cmStringSorter +{ +public: + enum class Order + { + UNINITIALIZED, + ASCENDING, + DESCENDING, + }; + + enum class Compare + { + UNINITIALIZED, + STRING, + FILE_BASENAME, + }; + enum class CaseSensitivity + { + UNINITIALIZED, + SENSITIVE, + INSENSITIVE, + }; + +protected: + typedef std::string (*StringFilter)(const std::string& in); + StringFilter GetCompareFilter(Compare compare) + { + return (compare == Compare::FILE_BASENAME) ? cmSystemTools::GetFilenameName + : nullptr; + } + + StringFilter GetCaseFilter(CaseSensitivity sensitivity) + { + return (sensitivity == CaseSensitivity::INSENSITIVE) + ? cmSystemTools::LowerCase + : nullptr; + } + +public: + cmStringSorter(Compare compare, CaseSensitivity caseSensitivity, + Order desc = Order::ASCENDING) + : filters{ GetCompareFilter(compare), GetCaseFilter(caseSensitivity) } + , descending(desc == Order::DESCENDING) + { + } + + std::string ApplyFilter(const std::string& argument) + { + std::string result = argument; + for (auto filter : filters) { + if (filter != nullptr) { + result = filter(result); + } + } + return result; + } + + bool operator()(const std::string& a, const std::string& b) + { + std::string af = ApplyFilter(a); + std::string bf = ApplyFilter(b); + bool result; + if (descending) { + result = bf < af; + } else { + result = af < bf; + } + return result; + } + +protected: + StringFilter filters[2] = { nullptr, nullptr }; + bool descending; +}; + bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args) { assert(args.size() >= 2); - if (args.size() > 2) { - this->SetError("sub-command SORT only takes one argument."); + if (args.size() > 8) { + this->SetError("sub-command SORT only takes up to six arguments."); return false; } + auto sortCompare = cmStringSorter::Compare::UNINITIALIZED; + auto sortCaseSensitivity = cmStringSorter::CaseSensitivity::UNINITIALIZED; + auto sortOrder = cmStringSorter::Order::UNINITIALIZED; + + size_t argumentIndex = 2; + const std::string messageHint = "sub-command SORT "; + + while (argumentIndex < args.size()) { + const std::string option = args[argumentIndex++]; + if (option == "COMPARE") { + if (sortCompare != cmStringSorter::Compare::UNINITIALIZED) { + std::string error = messageHint + "option \"" + option + + "\" has been specified multiple times."; + this->SetError(error); + return false; + } + if (argumentIndex < args.size()) { + const std::string argument = args[argumentIndex++]; + if (argument == "STRING") { + sortCompare = cmStringSorter::Compare::STRING; + } else if (argument == "FILE_BASENAME") { + sortCompare = cmStringSorter::Compare::FILE_BASENAME; + } else { + std::string error = messageHint + "value \"" + argument + + "\" for option \"" + option + "\" is invalid."; + this->SetError(error); + return false; + } + } else { + std::string error = + messageHint + "missing argument for option \"" + option + "\"."; + this->SetError(error); + return false; + } + } else if (option == "CASE") { + if (sortCaseSensitivity != + cmStringSorter::CaseSensitivity::UNINITIALIZED) { + std::string error = messageHint + "option \"" + option + + "\" has been specified multiple times."; + this->SetError(error); + return false; + } + if (argumentIndex < args.size()) { + const std::string argument = args[argumentIndex++]; + if (argument == "SENSITIVE") { + sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE; + } else if (argument == "INSENSITIVE") { + sortCaseSensitivity = cmStringSorter::CaseSensitivity::INSENSITIVE; + } else { + std::string error = messageHint + "value \"" + argument + + "\" for option \"" + option + "\" is invalid."; + this->SetError(error); + return false; + } + } else { + std::string error = + messageHint + "missing argument for option \"" + option + "\"."; + this->SetError(error); + return false; + } + } else if (option == "ORDER") { + + if (sortOrder != cmStringSorter::Order::UNINITIALIZED) { + std::string error = messageHint + "option \"" + option + + "\" has been specified multiple times."; + this->SetError(error); + return false; + } + if (argumentIndex < args.size()) { + const std::string argument = args[argumentIndex++]; + if (argument == "ASCENDING") { + sortOrder = cmStringSorter::Order::ASCENDING; + } else if (argument == "DESCENDING") { + sortOrder = cmStringSorter::Order::DESCENDING; + } else { + std::string error = messageHint + "value \"" + argument + + "\" for option \"" + option + "\" is invalid."; + this->SetError(error); + return false; + } + } else { + std::string error = + messageHint + "missing argument for option \"" + option + "\"."; + this->SetError(error); + return false; + } + } else { + std::string error = + messageHint + "option \"" + option + "\" is unknown."; + this->SetError(error); + return false; + } + } + // set Default Values if Option is not given + if (sortCompare == cmStringSorter::Compare::UNINITIALIZED) { + sortCompare = cmStringSorter::Compare::STRING; + } + if (sortCaseSensitivity == cmStringSorter::CaseSensitivity::UNINITIALIZED) { + sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE; + } + if (sortOrder == cmStringSorter::Order::UNINITIALIZED) { + sortOrder = cmStringSorter::Order::ASCENDING; + } + const std::string& listName = args[1]; // expand the variable std::vector<std::string> varArgsExpanded; @@ -979,7 +1156,14 @@ bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args) return false; } - std::sort(varArgsExpanded.begin(), varArgsExpanded.end()); + if ((sortCompare == cmStringSorter::Compare::STRING) && + (sortCaseSensitivity == cmStringSorter::CaseSensitivity::SENSITIVE) && + (sortOrder == cmStringSorter::Order::ASCENDING)) { + std::sort(varArgsExpanded.begin(), varArgsExpanded.end()); + } else { + cmStringSorter sorter(sortCompare, sortCaseSensitivity, sortOrder); + std::sort(varArgsExpanded.begin(), varArgsExpanded.end(), sorter); + } std::string value = cmJoin(varArgsExpanded, ";"); this->Makefile->AddDefinition(listName, value.c_str()); diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index b468257d0..4d7e1e2ad 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -11,6 +11,7 @@ #include <algorithm> #include <assert.h> +#include <memory> #include <sstream> cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=( @@ -285,91 +286,66 @@ bool cmListFileParser::AddArgument(cmListFileLexer_Token* token, return true; } -struct cmListFileBacktrace::Entry : public cmListFileContext +// We hold either the bottom scope of a directory or a call/file context. +// Discriminate these cases via the parent pointer. +struct cmListFileBacktrace::Entry { - Entry(cmListFileContext const& lfc, Entry* up) - : cmListFileContext(lfc) - , Up(up) - , RefCount(0) + Entry(cmStateSnapshot bottom) + : Bottom(bottom) { - if (this->Up) { - this->Up->Ref(); - } } - ~Entry() + + Entry(std::shared_ptr<Entry const> parent, cmListFileContext lfc) + : Context(std::move(lfc)) + , Parent(std::move(parent)) { - if (this->Up) { - this->Up->Unref(); - } } - void Ref() { ++this->RefCount; } - void Unref() + + ~Entry() { - if (--this->RefCount == 0) { - delete this; + if (this->Parent) { + this->Context.~cmListFileContext(); + } else { + this->Bottom.~cmStateSnapshot(); } } - Entry* Up; - unsigned int RefCount; -}; -cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& bottom, - Entry* up, - cmListFileContext const& lfc) - : Bottom(bottom) - , Cur(new Entry(lfc, up)) -{ - assert(this->Bottom.IsValid()); - this->Cur->Ref(); -} - -cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& bottom, - Entry* cur) - : Bottom(bottom) - , Cur(cur) -{ - if (this->Cur) { - assert(this->Bottom.IsValid()); - this->Cur->Ref(); - } -} + bool IsBottom() const { return !this->Parent; } -cmListFileBacktrace::cmListFileBacktrace() - : Bottom() - , Cur(nullptr) -{ -} + union + { + cmStateSnapshot Bottom; + cmListFileContext Context; + }; + std::shared_ptr<Entry const> Parent; +}; cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& snapshot) - : Bottom(snapshot.GetCallStackBottom()) - , Cur(nullptr) + : TopEntry(std::make_shared<Entry const>(snapshot.GetCallStackBottom())) { } -cmListFileBacktrace::cmListFileBacktrace(cmListFileBacktrace const& r) - : Bottom(r.Bottom) - , Cur(r.Cur) +cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> parent, + cmListFileContext const& lfc) + : TopEntry(std::make_shared<Entry const>(std::move(parent), lfc)) { - if (this->Cur) { - assert(this->Bottom.IsValid()); - this->Cur->Ref(); - } } -cmListFileBacktrace& cmListFileBacktrace::operator=( - cmListFileBacktrace const& r) +cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> top) + : TopEntry(std::move(top)) { - cmListFileBacktrace tmp(r); - std::swap(this->Cur, tmp.Cur); - std::swap(this->Bottom, tmp.Bottom); - return *this; } -cmListFileBacktrace::~cmListFileBacktrace() +cmStateSnapshot cmListFileBacktrace::GetBottom() const { - if (this->Cur) { - this->Cur->Unref(); + cmStateSnapshot bottom; + if (Entry const* cur = this->TopEntry.get()) { + while (Entry const* parent = cur->Parent.get()) { + cur = parent; + } + bottom = cur->Bottom; } + return bottom; } cmListFileBacktrace cmListFileBacktrace::Push(std::string const& file) const @@ -380,54 +356,62 @@ cmListFileBacktrace cmListFileBacktrace::Push(std::string const& file) const // skipped during call stack printing. cmListFileContext lfc; lfc.FilePath = file; - return cmListFileBacktrace(this->Bottom, this->Cur, lfc); + return this->Push(lfc); } cmListFileBacktrace cmListFileBacktrace::Push( cmListFileContext const& lfc) const { - return cmListFileBacktrace(this->Bottom, this->Cur, lfc); + assert(this->TopEntry); + assert(!this->TopEntry->IsBottom() || this->TopEntry->Bottom.IsValid()); + return cmListFileBacktrace(this->TopEntry, lfc); } cmListFileBacktrace cmListFileBacktrace::Pop() const { - assert(this->Cur); - return cmListFileBacktrace(this->Bottom, this->Cur->Up); + assert(this->TopEntry); + assert(!this->TopEntry->IsBottom()); + return cmListFileBacktrace(this->TopEntry->Parent); } cmListFileContext const& cmListFileBacktrace::Top() const { - if (this->Cur) { - return *this->Cur; - } - static cmListFileContext const empty; - return empty; + assert(this->TopEntry); + assert(!this->TopEntry->IsBottom()); + return this->TopEntry->Context; } void cmListFileBacktrace::PrintTitle(std::ostream& out) const { - if (!this->Cur) { + // The title exists only if we have a call on top of the bottom. + if (!this->TopEntry || this->TopEntry->IsBottom()) { return; } - cmOutputConverter converter(this->Bottom); - cmListFileContext lfc = *this->Cur; - if (!this->Bottom.GetState()->GetIsInTryCompile()) { + cmListFileContext lfc = this->TopEntry->Context; + cmStateSnapshot bottom = this->GetBottom(); + cmOutputConverter converter(bottom); + if (!bottom.GetState()->GetIsInTryCompile()) { lfc.FilePath = converter.ConvertToRelativePath( - this->Bottom.GetState()->GetSourceDirectory(), lfc.FilePath); + bottom.GetState()->GetSourceDirectory(), lfc.FilePath); } out << (lfc.Line ? " at " : " in ") << lfc; } void cmListFileBacktrace::PrintCallStack(std::ostream& out) const { - if (!this->Cur || !this->Cur->Up) { + // The call stack exists only if we have at least two calls on top + // of the bottom. + if (!this->TopEntry || this->TopEntry->IsBottom() || + this->TopEntry->Parent->IsBottom()) { return; } bool first = true; - cmOutputConverter converter(this->Bottom); - for (Entry* i = this->Cur->Up; i; i = i->Up) { - if (i->Name.empty()) { + cmStateSnapshot bottom = this->GetBottom(); + cmOutputConverter converter(bottom); + for (Entry const* cur = this->TopEntry->Parent.get(); !cur->IsBottom(); + cur = cur->Parent.get()) { + if (cur->Context.Name.empty()) { // Skip this whole-file scope. When we get here we already will // have printed a more-specific context within the file. continue; @@ -436,10 +420,10 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const first = false; out << "Call Stack (most recent call first):\n"; } - cmListFileContext lfc = *i; - if (!this->Bottom.GetState()->GetIsInTryCompile()) { + cmListFileContext lfc = cur->Context; + if (!bottom.GetState()->GetIsInTryCompile()) { lfc.FilePath = converter.ConvertToRelativePath( - this->Bottom.GetState()->GetSourceDirectory(), lfc.FilePath); + bottom.GetState()->GetSourceDirectory(), lfc.FilePath); } out << " " << lfc << "\n"; } @@ -448,16 +432,19 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const size_t cmListFileBacktrace::Depth() const { size_t depth = 0; - if (this->Cur == nullptr) { - return 0; - } - - for (Entry* i = this->Cur->Up; i; i = i->Up) { - depth++; + if (Entry const* cur = this->TopEntry.get()) { + for (; !cur->IsBottom(); cur = cur->Parent.get()) { + ++depth; + } } return depth; } +bool cmListFileBacktrace::Empty() const +{ + return !this->TopEntry || this->TopEntry->IsBottom(); +} + std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc) { os << lfc.FilePath; diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 70f7166cb..3d3afdf9b 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> // IWYU pragma: keep #include <stddef.h> #include <string> #include <vector> @@ -115,18 +116,22 @@ public: // Default-constructed backtrace may not be used until after // set via assignment from a backtrace constructed with a // valid snapshot. - cmListFileBacktrace(); + cmListFileBacktrace() = default; // Construct an empty backtrace whose bottom sits in the directory // indicated by the given valid snapshot. cmListFileBacktrace(cmStateSnapshot const& snapshot); - // Backtraces may be copied and assigned as values. - cmListFileBacktrace(cmListFileBacktrace const& r); - cmListFileBacktrace& operator=(cmListFileBacktrace const& r); - ~cmListFileBacktrace(); + // Backtraces may be copied, moved, and assigned as values. + cmListFileBacktrace(cmListFileBacktrace const&) = default; + cmListFileBacktrace(cmListFileBacktrace&&) // NOLINT(clang-tidy) + noexcept = default; + cmListFileBacktrace& operator=(cmListFileBacktrace const&) = default; + cmListFileBacktrace& operator=(cmListFileBacktrace&&) // NOLINT(clang-tidy) + noexcept = default; + ~cmListFileBacktrace() = default; - cmStateSnapshot GetBottom() const { return this->Bottom; } + cmStateSnapshot GetBottom() const; // Get a backtrace with the given file scope added to the top. // May not be called until after construction with a valid snapshot. @@ -141,7 +146,7 @@ public: cmListFileBacktrace Pop() const; // Get the context at the top of the backtrace. - // Returns an empty context if the backtrace is empty. + // This may be called only if Empty() would return false. cmListFileContext const& Top() const; // Print the top of the backtrace. @@ -153,14 +158,15 @@ public: // Get the number of 'frames' in this backtrace size_t Depth() const; + // Return true if this backtrace is empty. + bool Empty() const; + private: struct Entry; - - cmStateSnapshot Bottom; - Entry* Cur; - cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* up, + std::shared_ptr<Entry const> TopEntry; + cmListFileBacktrace(std::shared_ptr<Entry const> parent, cmListFileContext const& lfc); - cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* cur); + cmListFileBacktrace(std::shared_ptr<Entry const> top); }; struct cmListFile diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index 5a43f2e2c..7ce2c828f 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -54,9 +54,8 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags( this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT"); } if (!mod_dir.empty()) { - const char* moddir_flag = + std::string modflag = this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG"); - std::string modflag = moddir_flag; modflag += mod_dir; this->AppendFlags(flags, modflag); } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index a3f4a8fe7..70307252e 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -253,7 +253,7 @@ void cmLocalGenerator::GenerateTestFiles() file += "/"; file += "CTestTestfile.cmake"; - cmGeneratedFileStream fout(file.c_str()); + cmGeneratedFileStream fout(file); fout.SetCopyIfDifferent(true); fout << "# CMake generated Testfile for " << std::endl @@ -429,7 +429,7 @@ void cmLocalGenerator::GenerateInstallRules() toplevel_install = 1; } file += "/cmake_install.cmake"; - cmGeneratedFileStream fout(file.c_str()); + cmGeneratedFileStream fout(file); fout.SetCopyIfDifferent(true); // Write the header. @@ -683,7 +683,7 @@ std::string cmLocalGenerator::GetIncludeFlags( std::string flagVar = "CMAKE_INCLUDE_FLAG_"; flagVar += lang; - const char* includeFlag = this->Makefile->GetSafeDefinition(flagVar); + std::string const& includeFlag = this->Makefile->GetSafeDefinition(flagVar); flagVar = "CMAKE_INCLUDE_FLAG_SEP_"; flagVar += lang; const char* sep = this->Makefile->GetDefinition(flagVar); @@ -844,12 +844,11 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, cmGeneratorTarget const* target, const std::string& lang, const std::string& config, - bool stripImplicitInclDirs) const + bool stripImplicitDirs, + bool appendAllImplicitDirs) const { - // Need to decide whether to automatically include the source and - // binary directories at the beginning of the include path. - bool includeSourceDir = false; - bool includeBinaryDir = false; + // Do not repeat an include path. + std::set<std::string> emitted; // When automatic include directories are requested for a build then // include the source and binary directories at the beginning of the @@ -859,26 +858,21 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, // cannot fix this because not all native build tools support // per-source-file include paths. if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR")) { - includeSourceDir = true; - includeBinaryDir = true; - } - - // Do not repeat an include path. - std::set<std::string> emitted; - - // Store the automatic include paths. - if (includeBinaryDir) { - std::string binDir = this->StateSnapshot.GetDirectory().GetCurrentBinary(); - if (emitted.find(binDir) == emitted.end()) { - dirs.push_back(binDir); - emitted.insert(binDir); + // Current binary directory + { + std::string binDir = + this->StateSnapshot.GetDirectory().GetCurrentBinary(); + if (emitted.insert(binDir).second) { + dirs.push_back(std::move(binDir)); + } } - } - if (includeSourceDir) { - std::string srcDir = this->StateSnapshot.GetDirectory().GetCurrentSource(); - if (emitted.find(srcDir) == emitted.end()) { - dirs.push_back(srcDir); - emitted.insert(srcDir); + // Current source directory + { + std::string srcDir = + this->StateSnapshot.GetDirectory().GetCurrentSource(); + if (emitted.insert(srcDir).second) { + dirs.push_back(std::move(srcDir)); + } } } @@ -886,43 +880,45 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, return; } - std::string rootPath; - if (const char* sysrootCompile = - this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { - rootPath = sysrootCompile; - } else { - rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); - } - + // Implicit include directories std::vector<std::string> implicitDirs; - // Load implicit include directories for this language. - std::string impDirVar = "CMAKE_"; - impDirVar += lang; - impDirVar += "_IMPLICIT_INCLUDE_DIRECTORIES"; - if (const char* value = this->Makefile->GetDefinition(impDirVar)) { - std::vector<std::string> impDirVec; - cmSystemTools::ExpandListArgument(value, impDirVec); - for (std::string const& i : impDirVec) { - std::string d = rootPath + i; - cmSystemTools::ConvertToUnixSlashes(d); - emitted.insert(std::move(d)); - if (!stripImplicitInclDirs) { + { + std::string rootPath; + if (const char* sysrootCompile = + this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { + rootPath = sysrootCompile; + } else { + rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + } + + // Load implicit include directories for this language. + std::string key = "CMAKE_"; + key += lang; + key += "_IMPLICIT_INCLUDE_DIRECTORIES"; + if (const char* value = this->Makefile->GetDefinition(key)) { + std::vector<std::string> impDirVec; + cmSystemTools::ExpandListArgument(value, impDirVec); + for (std::string const& i : impDirVec) { + { + std::string d = rootPath + i; + cmSystemTools::ConvertToUnixSlashes(d); + emitted.insert(std::move(d)); + } implicitDirs.push_back(i); } } } // Get the target-specific include directories. - std::vector<std::string> includes; - - includes = target->GetIncludeDirectories(config, lang); + std::vector<std::string> userDirs = + target->GetIncludeDirectories(config, lang); // Support putting all the in-project include directories first if // it is requested by the project. if (this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")) { std::string const &topSourceDir = this->GetState()->GetSourceDirectory(), &topBinaryDir = this->GetState()->GetBinaryDirectory(); - for (std::string const& i : includes) { + for (std::string const& i : userDirs) { // Emit this directory only if it is a subdirectory of the // top-level source or binary tree. if (cmSystemTools::ComparePath(i, topSourceDir) || @@ -937,7 +933,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, } // Construct the final ordered include directory list. - for (std::string const& i : includes) { + for (std::string const& i : userDirs) { if (emitted.insert(i).second) { dirs.push_back(i); } @@ -946,28 +942,44 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, this->MoveSystemIncludesToEnd(dirs, config, lang, target); // Add standard include directories for this language. - // We do not filter out implicit directories here. - std::string const standardIncludesVar = - "CMAKE_" + lang + "_STANDARD_INCLUDE_DIRECTORIES"; - std::string const standardIncludes = - this->Makefile->GetSafeDefinition(standardIncludesVar); - std::vector<std::string>::size_type const before = includes.size(); - cmSystemTools::ExpandListArgument(standardIncludes, includes); - for (std::vector<std::string>::iterator i = includes.begin() + before; - i != includes.end(); ++i) { - cmSystemTools::ConvertToUnixSlashes(*i); - dirs.push_back(*i); - } - - for (std::string const& i : implicitDirs) { - if (std::find(includes.begin(), includes.end(), i) != includes.end()) { - dirs.push_back(i); + { + std::vector<std::string>::size_type const before = userDirs.size(); + { + std::string key = "CMAKE_"; + key += lang; + key += "_STANDARD_INCLUDE_DIRECTORIES"; + std::string const value = this->Makefile->GetSafeDefinition(key); + cmSystemTools::ExpandListArgument(value, userDirs); + } + for (std::vector<std::string>::iterator i = userDirs.begin() + before, + ie = userDirs.end(); + i != ie; ++i) { + cmSystemTools::ConvertToUnixSlashes(*i); + dirs.push_back(*i); + } + } + + if (!stripImplicitDirs) { + // Append only implicit directories that were requested by the user + for (std::string const& i : implicitDirs) { + if (std::find(userDirs.begin(), userDirs.end(), i) != userDirs.end()) { + dirs.push_back(i); + } + } + // Append remaining implicit directories on demand + if (appendAllImplicitDirs) { + for (std::string const& i : implicitDirs) { + if (std::find(dirs.begin(), dirs.end(), i) == dirs.end()) { + dirs.push_back(i); + } + } } } } void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags, std::string const& config, + std::string const& linkLanguage, cmGeneratorTarget* target) { this->AppendFlags( @@ -981,6 +993,11 @@ void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags, std::string name = "STATIC_LIBRARY_FLAGS_" + config; this->AppendFlags(flags, target->GetProperty(name)); } + + std::vector<std::string> options; + target->GetStaticLibraryLinkOptions(options, config, linkLanguage); + // STATIC_LIBRARY_OPTIONS are escaped. + this->AppendCompileOptions(flags, options); } void cmLocalGenerator::GetTargetFlags( @@ -998,7 +1015,7 @@ void cmLocalGenerator::GetTargetFlags( switch (target->GetType()) { case cmStateEnums::STATIC_LIBRARY: - this->GetStaticLibraryFlags(linkFlags, buildType, target); + this->GetStaticLibraryFlags(linkFlags, buildType, linkLanguage, target); break; case cmStateEnums::MODULE_LIBRARY: libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS"; @@ -1042,6 +1059,10 @@ void cmLocalGenerator::GetTargetFlags( linkFlags += " "; } } + std::vector<std::string> opts; + target->GetLinkOptions(opts, config, linkLanguage); + // LINK_OPTIONS are escaped. + this->AppendCompileOptions(linkFlags, opts); if (pcli) { this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath, linkPath); @@ -1113,6 +1134,10 @@ void cmLocalGenerator::GetTargetFlags( linkFlags += " "; } } + std::vector<std::string> opts; + target->GetLinkOptions(opts, config, linkLanguage); + // LINK_OPTIONS are escaped. + this->AppendCompileOptions(linkFlags, opts); } break; default: break; @@ -1320,7 +1345,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, const std::string& lang, const std::string& config) { - // Only add Mac OS X specific flags on Darwin platforms (OSX and iphone): + // Only add macOS specific flags on Darwin platforms (macOS and iOS): if (this->Makefile->IsOn("APPLE") && this->EmitUniversalBinaryFlags) { std::vector<std::string> archs; target->GetAppleArchs(config, archs); @@ -1630,7 +1655,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( std::string option_flag = "CMAKE_" + lang + *stdIt + "_" + type + "_COMPILE_OPTION"; - const char* opt = + std::string const& opt = target->Target->GetMakefile()->GetRequiredDefinition(option_flag); std::vector<std::string> optVec; cmSystemTools::ExpandListArgument(opt, optVec); @@ -1799,9 +1824,9 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared, std::string flagsVar = "CMAKE_SHARED_LIBRARY_"; flagsVar += lang; flagsVar += "_FLAGS"; - const char* flags = this->Makefile->GetSafeDefinition(flagsVar); + std::string const& flags = this->Makefile->GetSafeDefinition(flagsVar); - if (flags && flags != originalFlags) { + if (flags != originalFlags) { switch (this->GetPolicyStatus(cmPolicies::CMP0018)) { case cmPolicies::WARN: { std::ostringstream e; @@ -1834,7 +1859,7 @@ void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags, std::string const& lang, int targetType) { - const char* picFlags = nullptr; + std::string picFlags; if (targetType == cmStateEnums::EXECUTABLE) { std::string flagsVar = "CMAKE_"; @@ -1842,13 +1867,13 @@ void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags, flagsVar += "_COMPILE_OPTIONS_PIE"; picFlags = this->Makefile->GetSafeDefinition(flagsVar); } - if (!picFlags) { + if (picFlags.empty()) { std::string flagsVar = "CMAKE_"; flagsVar += lang; flagsVar += "_COMPILE_OPTIONS_PIC"; picFlags = this->Makefile->GetSafeDefinition(flagsVar); } - if (picFlags) { + if (!picFlags.empty()) { std::vector<std::string> options; cmSystemTools::ExpandListArgument(picFlags, options); for (std::string const& o : options) { @@ -1952,7 +1977,7 @@ void cmLocalGenerator::AppendCompileOptions( cmsys::RegularExpression r(regex); for (std::string const& opt : options_vec) { - if (r.find(opt.c_str())) { + if (r.find(opt)) { this->AppendFlagEscape(options, opt); } } @@ -1999,7 +2024,7 @@ void cmLocalGenerator::AppendIncludeDirectories( std::string inc = include; - if (!cmSystemTools::IsOff(inc.c_str())) { + if (!cmSystemTools::IsOff(inc)) { cmSystemTools::ConvertToUnixSlashes(inc); } @@ -2503,12 +2528,12 @@ std::string const& cmLocalGenerator::GetBinaryDirectory() const return this->GetCMakeInstance()->GetHomeOutputDirectory(); } -const char* cmLocalGenerator::GetCurrentBinaryDirectory() const +std::string const& cmLocalGenerator::GetCurrentBinaryDirectory() const { return this->StateSnapshot.GetDirectory().GetCurrentBinary(); } -const char* cmLocalGenerator::GetCurrentSourceDirectory() const +std::string const& cmLocalGenerator::GetCurrentSourceDirectory() const { return this->StateSnapshot.GetDirectory().GetCurrentSource(); } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 9ba62cc8d..58b776225 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -237,12 +237,18 @@ public: return true; } - /** Get the include flags for the current makefile and language. */ + /** @brief Get the include directories for the current makefile and language. + * @arg stripImplicitDirs Strip all directories found in + * CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES from the result. + * @arg appendAllImplicitDirs Append all directories found in + * CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES to the result. + */ void GetIncludeDirectories(std::vector<std::string>& dirs, cmGeneratorTarget const* target, const std::string& lang = "C", const std::string& config = "", - bool stripImplicitInclDirs = true) const; + bool stripImplicitDirs = true, + bool appendAllImplicitDirs = false) const; void AddCompileOptions(std::string& flags, cmGeneratorTarget* target, const std::string& lang, const std::string& config); void AddCompileDefinitions(std::set<std::string>& defines, @@ -290,18 +296,18 @@ public: std::string const& GetSourceDirectory() const; std::string const& GetBinaryDirectory() const; - const char* GetCurrentBinaryDirectory() const; - const char* GetCurrentSourceDirectory() const; + std::string const& GetCurrentBinaryDirectory() const; + std::string const& GetCurrentSourceDirectory() const; /** - * Generate a Mac OS X application bundle Info.plist file. + * Generate a macOS application bundle Info.plist file. */ void GenerateAppleInfoPList(cmGeneratorTarget* target, const std::string& targetName, const char* fname); /** - * Generate a Mac OS X framework Info.plist file. + * Generate a macOS framework Info.plist file. */ void GenerateFrameworkInfoPList(cmGeneratorTarget* target, const std::string& targetName, @@ -317,6 +323,7 @@ public: /** Fill out the static linker flags for the given target. */ void GetStaticLibraryFlags(std::string& flags, std::string const& config, + std::string const& linkLanguage, cmGeneratorTarget* target); /** Fill out these strings for the given target. Libraries to link, diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 360f73da5..eb3147880 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -564,8 +564,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( return std::string(); } - // Expand rules in the empty string. It may insert the launcher and - // perform replacements. + // Expand rule variables referenced in the given launcher command. cmRulePlaceholderExpander::RuleVariables vars; std::string output; @@ -580,12 +579,10 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( } vars.Output = output.c_str(); - std::string launcher = property_value; - launcher += " "; - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( this->CreateRulePlaceholderExpander()); + std::string launcher = property_value; rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars); if (!launcher.empty()) { launcher += " "; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 9fd2ddb72..4d19b3acb 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -211,8 +211,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() // rules may depend on this file itself. std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName); cmGeneratedFileStream ruleFileStream( - ruleFileNameFull.c_str(), false, - this->GlobalGenerator->GetMakefileEncoding()); + ruleFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); if (!ruleFileStream) { return; } @@ -433,7 +432,7 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile() infoFileName += "/CMakeDirectoryInformation.cmake"; // Open the output file. - cmGeneratedFileStream infoFileStream(infoFileName.c_str()); + cmGeneratedFileStream infoFileStream(infoFileName); if (!infoFileStream) { return; } @@ -774,7 +773,7 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom( std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash(); cmakefileName += "Makefile.cmake"; std::string runRule = - "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"; + "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"; runRule += " --check-build-system "; runRule += this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL); @@ -968,8 +967,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( // Short-circuit if there is no launcher. const char* val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM"); if (val && *val) { - // Expand rules in the empty string. It may insert the launcher and - // perform replacements. + // Expand rule variables referenced in the given launcher command. cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = target->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(target->GetType()); @@ -987,7 +985,6 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( vars.Output = output.c_str(); launcher = val; - launcher += " "; rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars); if (!launcher.empty()) { launcher += " "; @@ -1403,8 +1400,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( std::string ruleFileNameFull = dir; ruleFileNameFull += "/depend.make"; cmGeneratedFileStream ruleFileStream( - ruleFileNameFull.c_str(), false, - this->GlobalGenerator->GetMakefileEncoding()); + ruleFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); ruleFileStream.SetCopyIfDifferent(true); if (!ruleFileStream) { return false; @@ -1416,7 +1412,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( std::string internalRuleFileNameFull = dir; internalRuleFileNameFull += "/depend.internal"; cmGeneratedFileStream internalRuleFileStream( - internalRuleFileNameFull.c_str(), false, + internalRuleFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); if (!internalRuleFileStream) { return false; @@ -1426,7 +1422,8 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( this->WriteDisclaimer(internalRuleFileStream); // for each language we need to scan, scan it - const char* langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES"); + std::string const& langStr = + mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES"); std::vector<std::string> langs; cmSystemTools::ExpandListArgument(langStr, langs); for (std::string const& lang : langs) { @@ -1686,7 +1683,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( cmakefileName += "Makefile.cmake"; { std::string runRule = - "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"; + "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"; runRule += " --check-build-system "; runRule += this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 346028920..842867264 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -118,7 +118,7 @@ void cmLocalVisualStudio7Generator::WriteProjectFiles() if (this->GetCurrentBinaryDirectory() != this->GetSourceDirectory()) { if (!cmSystemTools::MakeDirectory(this->GetCurrentBinaryDirectory())) { cmSystemTools::Error("Error creating directory ", - this->GetCurrentBinaryDirectory()); + this->GetCurrentBinaryDirectory().c_str()); } } @@ -260,7 +260,7 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() std::string comment = "Building Custom Rule "; comment += makefileIn; std::string args; - args = "-H"; + args = "-S"; args += this->GetSourceDirectory(); commandLine.push_back(args); args = "-B"; @@ -665,11 +665,11 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( std::string baseFlagVar = "CMAKE_"; baseFlagVar += langForClCompile; baseFlagVar += "_FLAGS"; - flags = this->Makefile->GetRequiredDefinition(baseFlagVar.c_str()); + flags = this->Makefile->GetRequiredDefinition(baseFlagVar); std::string flagVar = baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName); flags += " "; - flags += this->Makefile->GetRequiredDefinition(flagVar.c_str()); + flags += this->Makefile->GetRequiredDefinition(flagVar); } // set the correct language if (linkLanguage == "C") { @@ -712,8 +712,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( targetOptions.FixExceptionHandlingDefault(); std::string asmLocation = configName + "/"; targetOptions.AddFlag("AssemblerListingLocation", asmLocation); - targetOptions.Parse(flags.c_str()); - targetOptions.Parse(defineFlags.c_str()); + targetOptions.Parse(flags); + targetOptions.Parse(defineFlags); targetOptions.ParseFinish(); if (!langForClCompile.empty()) { std::vector<std::string> targetDefines; @@ -931,8 +931,7 @@ std::string cmLocalVisualStudio7Generator::GetBuildTypeLinkerFlags( rootLinkerFlags + "_" + configTypeUpper; std::string extraLinkOptionsBuildType = - this->Makefile->GetRequiredDefinition( - extraLinkOptionsBuildTypeDef.c_str()); + this->Makefile->GetRequiredDefinition(extraLinkOptionsBuildTypeDef); return extraLinkOptionsBuildType; } @@ -977,13 +976,20 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( extraLinkOptions += " "; extraLinkOptions += targetLinkFlags; } + + std::vector<std::string> opts; + target->GetLinkOptions(opts, configName, + target->GetLinkerLanguage(configName)); + // LINK_OPTIONS are escaped. + this->AppendCompileOptions(extraLinkOptions, opts); + Options linkOptions(this, Options::Linker); if (this->FortranProject) { linkOptions.AddTable(cmLocalVisualStudio7GeneratorFortranLinkFlagTable); } linkOptions.AddTable(cmLocalVisualStudio7GeneratorLinkFlagTable); - linkOptions.Parse(extraLinkOptions.c_str()); + linkOptions.Parse(extraLinkOptions); cmGeneratorTarget::ModuleDefinitionInfo const* mdi = target->GetModuleDefinitionInfo(configName); if (mdi && !mdi->DefFile.empty()) { @@ -1031,7 +1037,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( } } std::string libflags; - this->GetStaticLibraryFlags(libflags, configTypeUpper, target); + this->GetStaticLibraryFlags(libflags, configTypeUpper, + target->GetLinkerLanguage(configName), + target); if (!libflags.empty()) { fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n"; } @@ -1074,7 +1082,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " - << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + << this->Makefile->GetSafeDefinition(standardLibsVar); if (this->FortranProject) { this->Internal->OutputObjects(fout, target, configName, " "); } @@ -1159,7 +1167,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " - << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + << this->Makefile->GetSafeDefinition(standardLibsVar); if (this->FortranProject) { this->Internal->OutputObjects(fout, target, configName, " "); } @@ -1226,30 +1234,56 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( } } +static std::string cmLocalVisualStudio7GeneratorEscapeForXML( + const std::string& s) +{ + std::string ret = s; + cmSystemTools::ReplaceString(ret, "&", "&"); + cmSystemTools::ReplaceString(ret, "\"", """); + cmSystemTools::ReplaceString(ret, "<", "<"); + cmSystemTools::ReplaceString(ret, ">", ">"); + cmSystemTools::ReplaceString(ret, "\n", "
"); + return ret; +} + +static std::string GetEscapedPropertyIfValueNotNULL(const char* propertyValue) +{ + return propertyValue == nullptr + ? std::string() + : cmLocalVisualStudio7GeneratorEscapeForXML(propertyValue); +} + void cmLocalVisualStudio7Generator::OutputDeploymentDebuggerTool( std::ostream& fout, std::string const& config, cmGeneratorTarget* target) { if (this->WindowsCEProject) { - if (const char* dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY")) { - /* clang-format off */ - fout << - "\t\t\t<DeploymentTool\n" - "\t\t\t\tForceDirty=\"-1\"\n" - "\t\t\t\tRemoteDirectory=\"" << this->EscapeForXML(dir) << "\"\n" - "\t\t\t\tRegisterOutput=\"0\"\n" - "\t\t\t\tAdditionalFiles=\"\"/>\n" - ; - /* clang-format on */ + const char* dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY"); + const char* additionalFiles = + target->GetProperty("DEPLOYMENT_ADDITIONAL_FILES"); + + if (dir == nullptr && additionalFiles == nullptr) { + return; + } + + fout << "\t\t\t<DeploymentTool\n" + "\t\t\t\tForceDirty=\"-1\"\n" + "\t\t\t\tRemoteDirectory=\"" + << GetEscapedPropertyIfValueNotNULL(dir) + << "\"\n" + "\t\t\t\tRegisterOutput=\"0\"\n" + "\t\t\t\tAdditionalFiles=\"" + << GetEscapedPropertyIfValueNotNULL(additionalFiles) << "\"/>\n"; + + if (dir != nullptr) { std::string const exe = dir + std::string("\\") + target->GetFullName(config); - /* clang-format off */ - fout << - "\t\t\t<DebuggerTool\n" - "\t\t\t\tRemoteExecutable=\"" << this->EscapeForXML(exe) << "\"\n" - "\t\t\t\tArguments=\"\"\n" - "\t\t\t/>\n" - ; - /* clang-format on */ + + fout << "\t\t\t<DebuggerTool\n" + "\t\t\t\tRemoteExecutable=\"" + << this->EscapeForXML(exe) + << "\"\n" + "\t\t\t\tArguments=\"\"\n" + "\t\t\t/>\n"; } } } @@ -1463,8 +1497,7 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( lang = sourceLang; } - cmGeneratorExpressionInterpreter genexInterpreter(lg, gt, *i, - gt->GetName(), lang); + cmGeneratorExpressionInterpreter genexInterpreter(lg, *i, gt, lang); bool needfc = false; if (!objectName.empty()) { @@ -1702,7 +1735,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup( table = cmLocalVisualStudio7GeneratorFortranFlagTable; } Options fileOptions(this, tool, table, gg->ExtraFlagTable); - fileOptions.Parse(fc.CompileFlags.c_str()); + fileOptions.Parse(fc.CompileFlags); fileOptions.AddDefines(fc.CompileDefs); fileOptions.AddDefines(fc.CompileDefsConfig); // validate source level include directories @@ -2049,17 +2082,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFooter( << "</VisualStudioProject>\n"; } -std::string cmLocalVisualStudio7GeneratorEscapeForXML(const std::string& s) -{ - std::string ret = s; - cmSystemTools::ReplaceString(ret, "&", "&"); - cmSystemTools::ReplaceString(ret, "\"", """); - cmSystemTools::ReplaceString(ret, "<", "<"); - cmSystemTools::ReplaceString(ret, ">", ">"); - cmSystemTools::ReplaceString(ret, "\n", "
"); - return ret; -} - std::string cmLocalVisualStudio7Generator::EscapeForXML(const std::string& s) { return cmLocalVisualStudio7GeneratorEscapeForXML(s); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index af97f8097..8d163b77d 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -11,6 +11,7 @@ #include <iterator> #include <memory> // IWYU pragma: keep #include <sstream> +#include <stdio.h> #include <stdlib.h> #include <utility> @@ -48,6 +49,11 @@ class cmMessenger; +cmDirectoryId::cmDirectoryId(std::string s) + : String(std::move(s)) +{ +} + // default is not to be building executables cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, cmStateSnapshot const& snapshot) @@ -111,6 +117,17 @@ cmMakefile::~cmMakefile() cmDeleteAll(this->EvaluationFiles); } +cmDirectoryId cmMakefile::GetDirectoryId() const +{ + // Use the instance pointer value to uniquely identify this directory. + // If we ever need to expose this to CMake language code we should + // add a read-only property in cmMakefile::GetProperty. + char buf[32]; + sprintf(buf, "<%p>", + static_cast<void const*>(this)); // cast avoids format warning + return std::string(buf); +} + void cmMakefile::IssueMessage(cmake::MessageType t, std::string const& text) const { @@ -216,6 +233,27 @@ cmBacktraceRange cmMakefile::GetCompileDefinitionsBacktraces() const .GetCompileDefinitionsEntryBacktraces(); } +cmStringRange cmMakefile::GetLinkOptionsEntries() const +{ + return this->StateSnapshot.GetDirectory().GetLinkOptionsEntries(); +} + +cmBacktraceRange cmMakefile::GetLinkOptionsBacktraces() const +{ + return this->StateSnapshot.GetDirectory().GetLinkOptionsEntryBacktraces(); +} + +cmStringRange cmMakefile::GetLinkDirectoriesEntries() const +{ + return this->StateSnapshot.GetDirectory().GetLinkDirectoriesEntries(); +} + +cmBacktraceRange cmMakefile::GetLinkDirectoriesBacktraces() const +{ + return this->StateSnapshot.GetDirectory() + .GetLinkDirectoriesEntryBacktraces(); +} + cmListFileBacktrace cmMakefile::GetBacktrace() const { return this->Backtrace; @@ -1205,6 +1243,23 @@ void cmMakefile::AddCompileOption(std::string const& option) this->AppendProperty("COMPILE_OPTIONS", option.c_str()); } +void cmMakefile::AddLinkOption(std::string const& option) +{ + this->AppendProperty("LINK_OPTIONS", option.c_str()); +} + +void cmMakefile::AddLinkDirectory(std::string const& directory, bool before) +{ + cmListFileBacktrace lfbt = this->GetBacktrace(); + if (before) { + this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry(directory, + lfbt); + } else { + this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry(directory, + lfbt); + } +} + bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) { // Create a regular expression to match valid definitions. @@ -1303,10 +1358,6 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent) // link libraries this->SetProperty("LINK_LIBRARIES", parent->GetProperty("LINK_LIBRARIES")); - // link directories - this->SetProperty("LINK_DIRECTORIES", - parent->GetProperty("LINK_DIRECTORIES")); - // the initial project name this->StateSnapshot.SetProjectName(parent->StateSnapshot.GetProjectName()); @@ -1620,12 +1671,12 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, } } -const char* cmMakefile::GetCurrentSourceDirectory() const +const std::string& cmMakefile::GetCurrentSourceDirectory() const { return this->StateSnapshot.GetDirectory().GetCurrentSource(); } -const char* cmMakefile::GetCurrentBinaryDirectory() const +const std::string& cmMakefile::GetCurrentBinaryDirectory() const { return this->StateSnapshot.GetDirectory().GetCurrentBinary(); } @@ -1703,7 +1754,8 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, cmStateEnums::CacheEntryType type, bool force) { - const char* existingValue = this->GetState()->GetInitializedCacheValue(name); + const std::string* existingValue = + this->GetState()->GetInitializedCacheValue(name); // must be outside the following if() to keep it alive long enough std::string nvalue; @@ -1713,7 +1765,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, // if this is not a force, then use the value from the cache // if it is a force, then use the value being passed in if (!force) { - value = existingValue; + value = existingValue->c_str(); } if (type == cmStateEnums::PATH || type == cmStateEnums::FILEPATH) { std::vector<std::string>::size_type cc; @@ -1723,7 +1775,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, cmSystemTools::ExpandListArgument(nvalue, files); nvalue.clear(); for (cc = 0; cc < files.size(); cc++) { - if (!cmSystemTools::IsOff(files[cc].c_str())) { + if (!cmSystemTools::IsOff(files[cc])) { files[cc] = cmSystemTools::CollapseFullPath(files[cc]); } if (cc > 0) { @@ -1733,7 +1785,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, } this->GetCMakeInstance()->AddCacheEntry(name, nvalue.c_str(), doc, type); - nvalue = this->GetState()->GetInitializedCacheValue(name); + nvalue = *this->GetState()->GetInitializedCacheValue(name); value = nvalue.c_str(); } } @@ -1839,17 +1891,6 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target) return; default:; } - if (const char* linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) { - std::vector<std::string> linkDirs; - cmSystemTools::ExpandListArgument(linkDirsProp, linkDirs); - - for (std::string& linkDir : linkDirs) { - // Sanitize the path the same way the link_directories command does - // in case projects set the LINK_DIRECTORIES property directly. - cmSystemTools::ConvertToUnixSlashes(linkDir); - target.AddLinkDirectory(linkDir); - } - } if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { std::vector<std::string> linkLibs; @@ -2339,21 +2380,21 @@ bool cmMakefile::CanIWriteThisFile(std::string const& fileName) const cmSystemTools::SameFile(fileName, this->GetHomeOutputDirectory()); } -const char* cmMakefile::GetRequiredDefinition(const std::string& name) const +std::string cmMakefile::GetRequiredDefinition(const std::string& name) const { const char* ret = this->GetDefinition(name); if (!ret) { cmSystemTools::Error("Error required internal CMake variable not " "set, cmake may not be built correctly.\n", "Missing variable is:\n", name.c_str()); - return ""; + return std::string(); } - return ret; + return std::string(ret); } bool cmMakefile::IsDefinitionSet(const std::string& name) const { - const char* def = this->StateSnapshot.GetDefinition(name); + const std::string* def = this->StateSnapshot.GetDefinition(name); if (!def) { def = this->GetState()->GetInitializedCacheValue(name); } @@ -2361,16 +2402,16 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const if (cmVariableWatch* vv = this->GetVariableWatch()) { if (!def) { vv->VariableAccessed( - name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, def, this); + name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, nullptr, this); } } #endif return def != nullptr; } -const char* cmMakefile::GetDefinition(const std::string& name) const +const std::string* cmMakefile::GetDef(const std::string& name) const { - const char* def = this->StateSnapshot.GetDefinition(name); + const std::string* def = this->StateSnapshot.GetDefinition(name); if (!def) { def = this->GetState()->GetInitializedCacheValue(name); } @@ -2381,7 +2422,7 @@ const char* cmMakefile::GetDefinition(const std::string& name) const vv->VariableAccessed(name, def ? cmVariableWatch::VARIABLE_READ_ACCESS : cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS, - def, this); + (def ? def->c_str() : nullptr), this); if (watch_function_executed) { // A callback was executed and may have caused re-allocation of the @@ -2397,13 +2438,23 @@ const char* cmMakefile::GetDefinition(const std::string& name) const return def; } -const char* cmMakefile::GetSafeDefinition(const std::string& def) const +const char* cmMakefile::GetDefinition(const std::string& name) const { - const char* ret = this->GetDefinition(def); - if (!ret) { - return ""; + const std::string* def = GetDef(name); + if (!def) { + return nullptr; } - return ret; + return def->c_str(); +} + +const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const +{ + static std::string const empty; + const std::string* def = GetDef(name); + if (!def) { + return empty; + } + return *def; } std::vector<std::string> cmMakefile::GetDefinitions() const @@ -4151,7 +4202,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, // Deprecate old policies, especially those that require a lot // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0054) { + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0063) { this->IssueMessage(cmake::DEPRECATION_WARNING, cmPolicies::GetPolicyDeprecatedWarning(id)); } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index a7c8df559..b30f281b5 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -47,6 +47,14 @@ class cmTest; class cmTestGenerator; class cmVariableWatch; +/** A type-safe wrapper for a string representing a directory id. */ +class cmDirectoryId +{ +public: + cmDirectoryId(std::string s); + std::string String; +}; + /** \class cmMakefile * \brief Process the input CMakeLists.txt file. * @@ -75,6 +83,8 @@ public: */ ~cmMakefile(); + cmDirectoryId GetDirectoryId() const; + bool ReadListFile(const char* filename); bool ReadDependentFile(const char* filename, bool noPolicyScope = true); @@ -171,6 +181,8 @@ public: void RemoveDefineFlag(std::string const& definition); void AddCompileDefinition(std::string const& definition); void AddCompileOption(std::string const& option); + void AddLinkOption(std::string const& option); + void AddLinkDirectory(std::string const& directory, bool before = false); /** Create a new imported target with the name and type given. */ cmTarget* AddImportedTarget(const std::string& name, @@ -326,8 +338,8 @@ public: */ void SetArgcArgv(const std::vector<std::string>& args); - const char* GetCurrentSourceDirectory() const; - const char* GetCurrentBinaryDirectory() const; + std::string const& GetCurrentSourceDirectory() const; + std::string const& GetCurrentBinaryDirectory() const; //@} @@ -421,8 +433,9 @@ public: * cache is then queried. */ const char* GetDefinition(const std::string&) const; - const char* GetSafeDefinition(const std::string&) const; - const char* GetRequiredDefinition(const std::string& name) const; + const std::string* GetDef(const std::string&) const; + const std::string& GetSafeDefinition(const std::string&) const; + std::string GetRequiredDefinition(const std::string& name) const; bool IsDefinitionSet(const std::string&) const; /** * Get the list of all variables in the current space. If argument @@ -788,6 +801,10 @@ public: cmBacktraceRange GetCompileOptionsBacktraces() const; cmStringRange GetCompileDefinitionsEntries() const; cmBacktraceRange GetCompileDefinitionsBacktraces() const; + cmStringRange GetLinkOptionsEntries() const; + cmBacktraceRange GetLinkOptionsBacktraces() const; + cmStringRange GetLinkDirectoriesEntries() const; + cmBacktraceRange GetLinkDirectoriesBacktraces() const; std::set<std::string> const& GetSystemIncludeDirectories() const { diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 1e59f44ce..08bb2cedf 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -97,15 +97,15 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( std::vector<std::string> commands; - // Build list of dependencies. - std::vector<std::string> depends; - this->AppendLinkDepends(depends); - // Get the language to use for linking this library. std::string linkLanguage = "CUDA"; std::string const objExt = this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); + // Build list of dependencies. + std::vector<std::string> depends; + this->AppendLinkDepends(depends, linkLanguage); + // Get the name of the device object to generate. std::string const targetOutputReal = this->GeneratorTarget->ObjectDirectory + "cmake_device_link" + objExt; @@ -154,12 +154,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( linkLanguage, this->ConfigName); // Add target-specific linker flags. - this->LocalGenerator->AppendFlags( - linkFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); - std::string linkFlagsConfig = "LINK_FLAGS_"; - linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName); - this->LocalGenerator->AppendFlags( - linkFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig)); + this->GetTargetLinkFlags(linkFlags, linkLanguage); // Construct a list of files associated with this executable that // may need to be cleaned. @@ -299,13 +294,6 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) { std::vector<std::string> commands; - // Build list of dependencies. - std::vector<std::string> depends; - this->AppendLinkDepends(depends); - if (!this->DeviceLinkObject.empty()) { - depends.push_back(this->DeviceLinkObject); - } - // Get the name of the executable to generate. std::string targetName; std::string targetNameReal; @@ -383,6 +371,13 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) return; } + // Build list of dependencies. + std::vector<std::string> depends; + this->AppendLinkDepends(depends, linkLanguage); + if (!this->DeviceLinkObject.empty()) { + depends.push_back(this->DeviceLinkObject); + } + this->NumberOfProgressActions++; if (!this->NoRuleMessages) { cmLocalUnixMakefileGenerator3::EchoProgress progress; @@ -437,12 +432,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) linkLanguage, this->ConfigName); // Add target-specific linker flags. - this->LocalGenerator->AppendFlags( - linkFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); - std::string linkFlagsConfig = "LINK_FLAGS_"; - linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName); - this->LocalGenerator->AppendFlags( - linkFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig)); + this->GetTargetLinkFlags(linkFlags, linkLanguage); { std::unique_ptr<cmLinkLineComputer> linkLineComputer( @@ -466,7 +456,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // clean set just in case. exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), - (targetFullPath + ".manifest").c_str())); + targetFullPath + ".manifest")); #endif if (targetNameReal != targetName) { exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index c53899285..2d2915c21 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -137,10 +137,7 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() this->GeneratorTarget->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS"); if (hasCUDA && resolveDeviceSymbols) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; - std::string extraFlags; - this->LocalGenerator->AppendFlags( - extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); - this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, false); + this->WriteDeviceLibraryRules(linkRuleVar, false); } std::string linkLanguage = @@ -151,7 +148,7 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() std::string extraFlags; this->LocalGenerator->GetStaticLibraryFlags( - extraFlags, cmSystemTools::UpperCase(this->ConfigName), + extraFlags, cmSystemTools::UpperCase(this->ConfigName), linkLanguage, this->GeneratorTarget); this->WriteLibraryRules(linkRuleVar, extraFlags, false); } @@ -173,10 +170,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) cuda_lang) != closure->Languages.end()); if (hasCUDA) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; - std::string extraFlags; - this->LocalGenerator->AppendFlags( - extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); - this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, relink); + this->WriteDeviceLibraryRules(linkRuleVar, relink); } } @@ -187,13 +181,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) linkRuleVar += "_CREATE_SHARED_LIBRARY"; std::string extraFlags; - this->LocalGenerator->AppendFlags( - extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); - std::string linkFlagsConfig = "LINK_FLAGS_"; - linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName); - this->LocalGenerator->AppendFlags( - extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig)); - + this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName); @@ -223,10 +211,7 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) cuda_lang) != closure->Languages.end()); if (hasCUDA) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; - std::string extraFlags; - this->LocalGenerator->AppendFlags( - extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); - this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, relink); + this->WriteDeviceLibraryRules(linkRuleVar, relink); } } @@ -237,12 +222,7 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) linkRuleVar += "_CREATE_SHARED_MODULE"; std::string extraFlags; - this->LocalGenerator->AppendFlags( - extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); - std::string linkFlagsConfig = "LINK_FLAGS_"; - linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName); - this->LocalGenerator->AppendFlags( - extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig)); + this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName); @@ -265,12 +245,7 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink) linkRuleVar += "_CREATE_MACOSX_FRAMEWORK"; std::string extraFlags; - this->LocalGenerator->AppendFlags( - extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); - std::string linkFlagsConfig = "LINK_FLAGS_"; - linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName); - this->LocalGenerator->AppendFlags( - extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig)); + this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName); @@ -278,25 +253,25 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink) } void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( - const std::string& linkRuleVar, const std::string& extraFlags, bool relink) + const std::string& linkRuleVar, bool relink) { #ifdef CMAKE_BUILD_WITH_CMAKE // TODO: Merge the methods that call this method to avoid // code duplication. std::vector<std::string> commands; - // Build list of dependencies. - std::vector<std::string> depends; - this->AppendLinkDepends(depends); - // Get the language to use for linking this library. std::string linkLanguage = "CUDA"; std::string const objExt = this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); + // Build list of dependencies. + std::vector<std::string> depends; + this->AppendLinkDepends(depends, linkLanguage); + // Create set of linking flags. std::string linkFlags; - this->LocalGenerator->AppendFlags(linkFlags, extraFlags); + this->GetTargetLinkFlags(linkFlags, linkLanguage); // Get the name of the device object to generate. std::string const targetOutputReal = @@ -458,7 +433,6 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( this->WriteTargetDriverRule(targetOutputReal, relink); #else static_cast<void>(linkRuleVar); - static_cast<void>(extraFlags); static_cast<void>(relink); #endif } @@ -470,13 +444,6 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // code duplication. std::vector<std::string> commands; - // Build list of dependencies. - std::vector<std::string> depends; - this->AppendLinkDepends(depends); - if (!this->DeviceLinkObject.empty()) { - depends.push_back(this->DeviceLinkObject); - } - // Get the language to use for linking this library. std::string linkLanguage = this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); @@ -488,6 +455,13 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( return; } + // Build list of dependencies. + std::vector<std::string> depends; + this->AppendLinkDepends(depends, linkLanguage); + if (!this->DeviceLinkObject.empty()) { + depends.push_back(this->DeviceLinkObject); + } + // Create set of linking flags. std::string linkFlags; this->LocalGenerator->AppendFlags(linkFlags, extraFlags); @@ -661,7 +635,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) { libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), - (targetFullPath + ".manifest").c_str())); + targetFullPath + ".manifest")); } #endif diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h index 02fa029cd..35e43277d 100644 --- a/Source/cmMakefileLibraryTargetGenerator.h +++ b/Source/cmMakefileLibraryTargetGenerator.h @@ -27,8 +27,7 @@ protected: void WriteSharedLibraryRules(bool relink); void WriteModuleLibraryRules(bool relink); - void WriteDeviceLibraryRules(const std::string& linkRule, - const std::string& extraFlags, bool relink); + void WriteDeviceLibraryRules(const std::string& linkRule, bool relink); void WriteLibraryRules(const std::string& linkRule, const std::string& extraFlags, bool relink); // MacOSX Framework support methods diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 1f65f0896..f423560eb 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -82,6 +82,23 @@ cmMakefileTargetGenerator* cmMakefileTargetGenerator::New( return result; } +void cmMakefileTargetGenerator::GetTargetLinkFlags( + std::string& flags, const std::string& linkLanguage) +{ + this->LocalGenerator->AppendFlags( + flags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); + + std::string linkFlagsConfig = "LINK_FLAGS_"; + linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName); + this->LocalGenerator->AppendFlags( + flags, this->GeneratorTarget->GetProperty(linkFlagsConfig)); + + std::vector<std::string> opts; + this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage); + // LINK_OPTIONS are escaped. + this->LocalGenerator->AppendCompileOptions(flags, opts); +} + void cmMakefileTargetGenerator::CreateRuleFile() { // Create a directory for this target. @@ -107,7 +124,7 @@ void cmMakefileTargetGenerator::CreateRuleFile() // Open the rule file. This should be copy-if-different because the // rules may depend on this file itself. this->BuildFileStream = - new cmGeneratedFileStream(this->BuildFileNameFull.c_str(), false, + new cmGeneratedFileStream(this->BuildFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); this->BuildFileStream->SetCopyIfDifferent(true); if (!this->BuildFileStream) { @@ -164,6 +181,36 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, output)); } + const std::vector<std::string>& byproducts = ccg.GetByproducts(); + for (std::string const& byproduct : byproducts) { + this->CleanFiles.push_back( + this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, + byproduct)); + } + } + } + + // Add byproducts from build events to the clean rules + if (clean) { + std::vector<cmCustomCommand> buildEventCommands = + this->GeneratorTarget->GetPreBuildCommands(); + + buildEventCommands.insert( + buildEventCommands.end(), + this->GeneratorTarget->GetPreLinkCommands().begin(), + this->GeneratorTarget->GetPreLinkCommands().end()); + buildEventCommands.insert( + buildEventCommands.end(), + this->GeneratorTarget->GetPostBuildCommands().begin(), + this->GeneratorTarget->GetPostBuildCommands().end()); + + for (const auto& be : buildEventCommands) { + const std::vector<std::string>& byproducts = be.GetByproducts(); + for (std::string const& byproduct : byproducts) { + this->CleanFiles.push_back( + this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, + byproduct)); + } } } std::vector<cmSourceFile const*> headerSources; @@ -220,8 +267,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() if (!cmSystemTools::FileExists(dependFileNameFull)) { // Write an empty dependency file. cmGeneratedFileStream depFileStream( - dependFileNameFull.c_str(), false, - this->GlobalGenerator->GetMakefileEncoding()); + dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); depFileStream << "# Empty dependencies file for " << this->GeneratorTarget->GetName() << ".\n" << "# This may be replaced when dependencies are built." @@ -233,7 +279,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() this->FlagFileNameFull = this->TargetBuildDirectoryFull; this->FlagFileNameFull += "/flags.make"; this->FlagFileStream = - new cmGeneratedFileStream(this->FlagFileNameFull.c_str(), false, + new cmGeneratedFileStream(this->FlagFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); this->FlagFileStream->SetCopyIfDifferent(true); if (!this->FlagFileStream) { @@ -418,8 +464,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( std::string config = this->LocalGenerator->GetConfigName(); std::string configUpper = cmSystemTools::UpperCase(config); cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->GeneratorTarget, config, - this->GeneratorTarget->GetName(), lang); + this->LocalGenerator, config, this->GeneratorTarget, lang); // Add Fortran format flags. if (lang == "Fortran") { @@ -429,7 +474,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( // Add flags from source file properties. const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = source.GetProperty(COMPILE_FLAGS)) { - const char* evaluatedFlags = + const std::string& evaluatedFlags = genexInterpreter.Evaluate(cflags, COMPILE_FLAGS); this->LocalGenerator->AppendFlags(flags, evaluatedFlags); *this->FlagFileStream << "# Custom flags: " << relativeObj @@ -439,7 +484,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); if (const char* coptions = source.GetProperty(COMPILE_OPTIONS)) { - const char* evaluatedOptions = + const std::string& evaluatedOptions = genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS); this->LocalGenerator->AppendCompileOptions(flags, evaluatedOptions); *this->FlagFileStream << "# Custom options: " << relativeObj @@ -452,7 +497,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); if (const char* cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) { - const char* evaluatedIncludes = + const std::string& evaluatedIncludes = genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES); this->LocalGenerator->AppendIncludeDirectories(includes, evaluatedIncludes, source); @@ -468,7 +513,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( // Add source-specific preprocessor definitions. const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); if (const char* compile_defs = source.GetProperty(COMPILE_DEFINITIONS)) { - const char* evaluatedDefs = + const std::string& evaluatedDefs = genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS); this->LocalGenerator->AppendDefines(defines, evaluatedDefs); *this->FlagFileStream << "# Custom defines: " << relativeObj @@ -478,7 +523,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( std::string defPropName = "COMPILE_DEFINITIONS_"; defPropName += configUpper; if (const char* config_compile_defs = source.GetProperty(defPropName)) { - const char* evaluatedDefs = + const std::string& evaluatedDefs = genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS); this->LocalGenerator->AppendDefines(defines, evaluatedDefs); *this->FlagFileStream << "# Custom defines: " << relativeObj << "_DEFINES_" @@ -957,8 +1002,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() this->InfoFileNameFull += "/DependInfo.cmake"; this->InfoFileNameFull = this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull); - this->InfoFileStream = - new cmGeneratedFileStream(this->InfoFileNameFull.c_str()); + this->InfoFileStream = new cmGeneratedFileStream(this->InfoFileNameFull); this->InfoFileStream->SetCopyIfDifferent(true); if (!*this->InfoFileStream) { return; @@ -1370,7 +1414,7 @@ void cmMakefileTargetGenerator::AppendObjectDepends( } void cmMakefileTargetGenerator::AppendLinkDepends( - std::vector<std::string>& depends) + std::vector<std::string>& depends, const std::string& linkLanguage) { this->AppendObjectDepends(depends); @@ -1394,10 +1438,8 @@ void cmMakefileTargetGenerator::AppendLinkDepends( } // Add user-specified dependencies. - if (const char* linkDepends = - this->GeneratorTarget->GetProperty("LINK_DEPENDS")) { - cmSystemTools::ExpandListArgument(linkDepends, depends); - } + this->GeneratorTarget->GetLinkDepends(depends, this->ConfigName, + linkLanguage); } std::string cmMakefileTargetGenerator::GetLinkRule( @@ -1431,7 +1473,7 @@ void cmMakefileTargetGenerator::CreateLinkScript( std::string linkScriptName = this->TargetBuildDirectoryFull; linkScriptName += "/"; linkScriptName += name; - cmGeneratedFileStream linkScriptStream(linkScriptName.c_str()); + cmGeneratedFileStream linkScriptStream(linkScriptName); linkScriptStream.SetCopyIfDifferent(true); for (std::string const& link_command : link_commands) { // Do not write out empty commands or commands beginning in the @@ -1515,7 +1557,7 @@ std::string cmMakefileTargetGenerator::CreateResponseFile( std::string responseFileNameFull = this->TargetBuildDirectoryFull; responseFileNameFull += "/"; responseFileNameFull += name; - cmGeneratedFileStream responseStream(responseFileNameFull.c_str()); + cmGeneratedFileStream responseStream(responseFileNameFull); responseStream.SetCopyIfDifferent(true); responseStream << options << "\n"; @@ -1703,7 +1745,7 @@ void cmMakefileTargetGenerator::GenDefFile( cmOutputConverter::SHELL); real_link_commands.insert(real_link_commands.begin(), cmd); // create a list of obj files for the -E __create_def to read - cmGeneratedFileStream fout(objlist_file.c_str()); + cmGeneratedFileStream fout(objlist_file); if (mdi->WindowsExportAllSymbols) { for (std::string const& obj : this->Objects) { diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 7af3cf39e..529b4db44 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -52,6 +52,8 @@ public: cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; } protected: + void GetTargetLinkFlags(std::string& flags, const std::string& linkLanguage); + // create the file and directory etc void CreateRuleFile(); @@ -69,7 +71,7 @@ protected: // write the depend rules for this target void WriteTargetDependRules(); - // write rules for Mac OS X Application Bundle content. + // write rules for macOS Application Bundle content. struct MacOSXContentGeneratorType : cmOSXBundleGenerator::MacOSXContentGeneratorType { @@ -126,7 +128,8 @@ protected: void AppendObjectDepends(std::vector<std::string>& depends); // Append link rule dependencies (objects, etc.). - void AppendLinkDepends(std::vector<std::string>& depends); + void AppendLinkDepends(std::vector<std::string>& depends, + const std::string& linkLanguage); // Lookup the link rule for this target. std::string GetLinkRule(const std::string& linkRuleVar); @@ -234,7 +237,7 @@ protected: std::string TargetNameImport; std::string TargetNamePDB; - // Mac OS X content info. + // macOS content info. std::set<std::string> MacContentFolders; cmOSXBundleGenerator* OSXBundleGenerator; MacOSXContentGeneratorType* MacOSXContentGenerator; diff --git a/Source/cmMathCommand.cxx b/Source/cmMathCommand.cxx index c1cd1b6c2..a50e5fc33 100644 --- a/Source/cmMathCommand.cxx +++ b/Source/cmMathCommand.cxx @@ -2,10 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMathCommand.h" -#include <stdio.h> - #include "cmExprParserHelper.h" #include "cmMakefile.h" +#include "cm_kwiml.h" +#include "cmake.h" + +#include <stdio.h> class cmExecutionStatus; @@ -27,24 +29,83 @@ bool cmMathCommand::InitialPass(std::vector<std::string> const& args, bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args) { - if (args.size() != 3) { + if ((args.size() != 3) && (args.size() != 5)) { this->SetError("EXPR called with incorrect arguments."); return false; } + enum class NumericFormat + { + UNINITIALIZED, + DECIMAL, + HEXADECIMAL, + }; + const std::string& outputVariable = args[1]; const std::string& expression = args[2]; + size_t argumentIndex = 3; + NumericFormat outputFormat = NumericFormat::UNINITIALIZED; + + this->Makefile->AddDefinition(outputVariable, "ERROR"); + + if (argumentIndex < args.size()) { + const std::string messageHint = "sub-command EXPR "; + const std::string option = args[argumentIndex++]; + if (option == "OUTPUT_FORMAT") { + if (argumentIndex < args.size()) { + const std::string argument = args[argumentIndex++]; + if (argument == "DECIMAL") { + outputFormat = NumericFormat::DECIMAL; + } else if (argument == "HEXADECIMAL") { + outputFormat = NumericFormat::HEXADECIMAL; + } else { + std::string error = messageHint + "value \"" + argument + + "\" for option \"" + option + "\" is invalid."; + this->SetError(error); + return false; + } + } else { + std::string error = + messageHint + "missing argument for option \"" + option + "\"."; + this->SetError(error); + return false; + } + } else { + std::string error = + messageHint + "option \"" + option + "\" is unknown."; + this->SetError(error); + return false; + } + } + + if (outputFormat == NumericFormat::UNINITIALIZED) { + outputFormat = NumericFormat::DECIMAL; + } cmExprParserHelper helper; if (!helper.ParseString(expression.c_str(), 0)) { - std::string e = "cannot parse the expression: \"" + expression + "\": "; - e += helper.GetError(); - this->SetError(e); + this->SetError(helper.GetError()); return false; } char buffer[1024]; - sprintf(buffer, "%d", helper.GetResult()); + const char* fmt; + switch (outputFormat) { + case NumericFormat::HEXADECIMAL: + fmt = "0x%" KWIML_INT_PRIx64; + break; + case NumericFormat::DECIMAL: + CM_FALLTHROUGH; + default: + fmt = "%" KWIML_INT_PRId64; + break; + } + sprintf(buffer, fmt, helper.GetResult()); + + std::string const& w = helper.GetWarning(); + if (!w.empty()) { + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w); + } this->Makefile->AddDefinition(outputVariable, buffer); return true; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 739418866..64369698e 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -530,7 +530,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); - const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar); + std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmSystemTools::ExpandListArgument(linkCmd, linkCmds); } { @@ -541,7 +541,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); - const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar); + std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmSystemTools::ExpandListArgument(linkCmd, linkCmds); } return linkCmds; @@ -625,7 +625,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() outputs.push_back(targetOutputReal); // Compute specific libraries to link with. cmNinjaDeps explicitDeps = this->GetObjects(); - cmNinjaDeps implicitDeps = this->ComputeLinkDeps(); + cmNinjaDeps implicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage); std::string frameworkPath; std::string linkPath; @@ -794,7 +794,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Compute specific libraries to link with. cmNinjaDeps explicitDeps = this->GetObjects(); - cmNinjaDeps implicitDeps = this->ComputeLinkDeps(); + cmNinjaDeps implicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage); if (!this->DeviceLinkObject.empty()) { explicitDeps.push_back(this->DeviceLinkObject); @@ -956,7 +956,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() preLinkCmdLines.push_back(std::move(cmd)); // create a list of obj files for the -E __create_def to read - cmGeneratedFileStream fout(obj_list_file.c_str()); + cmGeneratedFileStream fout(obj_list_file); if (mdi->WindowsExportAllSymbols) { cmNinjaDeps objs = this->GetObjects(); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 9d4194826..7ac8d1b91 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -10,7 +10,6 @@ #include <map> #include <memory> // IWYU pragma: keep #include <sstream> -#include <string.h> #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" @@ -136,9 +135,8 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( // Add source file specific flags. cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->GeneratorTarget, - this->LocalGenerator->GetConfigName(), this->GeneratorTarget->GetName(), - language); + this->LocalGenerator, this->LocalGenerator->GetConfigName(), + this->GeneratorTarget, language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) { @@ -175,9 +173,8 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags, bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const { - return strcmp(this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" + - lang), - "msvc") == 0; + return (this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" + + lang) == "msvc"); } // TODO: Refactor with @@ -188,8 +185,7 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, std::set<std::string> defines; const std::string config = this->LocalGenerator->GetConfigName(); cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->GeneratorTarget, config, - this->GeneratorTarget->GetName(), language); + this->LocalGenerator, config, this->GeneratorTarget, language); const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { @@ -217,8 +213,7 @@ std::string cmNinjaTargetGenerator::ComputeIncludes( std::vector<std::string> includes; const std::string config = this->LocalGenerator->GetConfigName(); cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->GeneratorTarget, config, - this->GeneratorTarget->GetName(), language); + this->LocalGenerator, config, this->GeneratorTarget, language); const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); if (const char* cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) { @@ -235,7 +230,8 @@ std::string cmNinjaTargetGenerator::ComputeIncludes( return includesString; } -cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const +cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( + const std::string& linkLanguage) const { // Static libraries never depend on other targets for linking. if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || @@ -270,13 +266,11 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const } // Add user-specified dependencies. - if (const char* linkDepends = - this->GeneratorTarget->GetProperty("LINK_DEPENDS")) { - std::vector<std::string> linkDeps; - cmSystemTools::ExpandListArgument(linkDepends, linkDeps); - std::transform(linkDeps.begin(), linkDeps.end(), - std::back_inserter(result), MapToNinjaPath()); - } + std::vector<std::string> linkDeps; + this->GeneratorTarget->GetLinkDepends(linkDeps, this->ConfigName, + linkLanguage); + std::transform(linkDeps.begin(), linkDeps.end(), std::back_inserter(result), + MapToNinjaPath()); return result; } @@ -1134,7 +1128,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) } std::string const tdin = this->GetTargetDependInfoPath(lang); - cmGeneratedFileStream tdif(tdin.c_str()); + cmGeneratedFileStream tdif(tdin); tdif << tdi; } diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 4660a3ae8..373c693bf 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -95,7 +95,7 @@ protected: } /// @return the list of link dependency for the given target @a target. - cmNinjaDeps ComputeLinkDeps() const; + cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage) const; /// @return the source file path for the given @a source. std::string GetSourceFilePath(cmSourceFile const* source) const; @@ -135,7 +135,7 @@ protected: void EnsureDirectoryExists(const std::string& dir) const; void EnsureParentDirectoryExists(const std::string& path) const; - // write rules for Mac OS X Application Bundle content. + // write rules for macOS Application Bundle content. struct MacOSXContentGeneratorType : cmOSXBundleGenerator::MacOSXContentGeneratorType { diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx index 00a2d2bce..006211ddc 100644 --- a/Source/cmOptionCommand.cxx +++ b/Source/cmOptionCommand.cxx @@ -2,11 +2,16 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmOptionCommand.h" +#include <sstream> + #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmPolicies.h" #include "cmState.h" +#include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmSystemTools.h" +#include "cmake.h" class cmExecutionStatus; @@ -14,19 +19,7 @@ class cmExecutionStatus; bool cmOptionCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus&) { - bool argError = false; - if (args.size() < 2) { - argError = true; - } - // for VTK 4.0 we have to support the option command with more than 3 - // arguments if CMAKE_MINIMUM_REQUIRED_VERSION is not defined, if - // CMAKE_MINIMUM_REQUIRED_VERSION is defined, then we can have stricter - // checking. - if (this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { - if (args.size() > 3) { - argError = true; - } - } + const bool argError = (args.size() < 2) || (args.size() > 3); if (argError) { std::string m = "called with incorrect number of arguments: "; m += cmJoin(args, " "); @@ -34,23 +27,62 @@ bool cmOptionCommand::InitialPass(std::vector<std::string> const& args, return false; } - std::string initialValue = "Off"; - // Now check and see if the value has been stored in the cache - // already, if so use that value and don't look for the program + // Determine the state of the option policy + bool checkAndWarn = false; + { + auto status = this->Makefile->GetPolicyStatus(cmPolicies::CMP0077); + const auto* existsBeforeSet = + this->Makefile->GetStateSnapshot().GetDefinition(args[0]); + switch (status) { + case cmPolicies::WARN: + checkAndWarn = (existsBeforeSet != nullptr); + break; + case cmPolicies::OLD: + // OLD behavior does not warn. + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: { + // See if a local variable with this name already exists. + // If so we ignore the option command. + if (existsBeforeSet) { + return true; + } + } break; + } + } + + // See if a cache variable with this name already exists + // If so just make sure the doc state is correct cmState* state = this->Makefile->GetState(); const char* existingValue = state->GetCacheEntryValue(args[0]); - if (existingValue) { - if (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED) { - state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]); - return true; - } - initialValue = existingValue; + if (existingValue && + (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED)) { + state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]); + return true; } + + // Nothing in the cache so add it + std::string initialValue = existingValue ? existingValue : "Off"; if (args.size() == 3) { initialValue = args[2]; } - bool init = cmSystemTools::IsOn(initialValue.c_str()); + bool init = cmSystemTools::IsOn(initialValue); this->Makefile->AddCacheDefinition(args[0], init ? "ON" : "OFF", args[1].c_str(), cmStateEnums::BOOL); + + if (checkAndWarn) { + const auto* existsAfterSet = + this->Makefile->GetStateSnapshot().GetDefinition(args[0]); + if (!existsAfterSet) { + std::ostringstream w; + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0077) + << "\n" + "For compatibility with older versions of CMake, option " + "is clearing the normal variable '" + << args[0] << "'."; + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + } + } return true; } diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index fd42c5341..dbe6fa1c8 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -83,9 +83,9 @@ bool cmOutputConverter::ContainedInDirectory(std::string const& local_path, std::string const& remote_path, cmStateDirectory const& directory) { - const std::string relativePathTopBinary = + const std::string& relativePathTopBinary = directory.GetRelativePathTopBinary(); - const std::string relativePathTopSource = + const std::string& relativePathTopSource = directory.GetRelativePathTopSource(); const bool bothInBinary = diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index bdb98cad5..e2de3f98e 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -356,8 +356,7 @@ protected: if (!found) { // Couldn't find any dependency information. - if (this->ComplainFileRegularExpression.find( - info->IncludeName.c_str())) { + if (this->ComplainFileRegularExpression.find(info->IncludeName)) { cmSystemTools::Error("error cannot find dependencies for ", path); } else { // Destroy the name of the file so that it won't be output as a diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index ba50fb8ae..5caea7d1f 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -135,7 +135,7 @@ static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy, cmPolicies::PolicyStatus* defaultSetting) { std::string defaultVar = "CMAKE_POLICY_DEFAULT_" + policy; - std::string defaultValue = mf->GetSafeDefinition(defaultVar); + std::string const& defaultValue = mf->GetSafeDefinition(defaultVar); if (defaultValue == "NEW") { *defaultSetting = cmPolicies::NEW; } else if (defaultValue == "OLD") { diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 1ef1813c2..a367e47dd 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -223,7 +223,24 @@ class cmMakefile; 3, 12, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0075, \ "Include file check macros honor CMAKE_REQUIRED_LIBRARIES.", 3, 12, \ - 0, cmPolicies::WARN) + 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0076, \ + "target_sources() command converts relative paths to absolute.", 3, \ + 13, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0077, "option() honors normal variables.", 3, 13, 0, \ + cmPolicies::WARN) \ + SELECT(POLICY, CMP0078, "UseSWIG generates standard target names.", 3, 13, \ + 0, cmPolicies::WARN) \ + SELECT( \ + POLICY, CMP0079, \ + "target_link_libraries allows use with targets in other directories.", 3, \ + 13, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0080, \ + "BundleUtilities cannot be included at configure time", 3, 13, 0, \ + cmPolicies::WARN) \ + SELECT(POLICY, CMP0081, \ + "Relative paths not allowed in LINK_DIRECTORIES target property.", \ + 3, 13, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -248,7 +265,9 @@ class cmMakefile; F(CMP0065) \ F(CMP0068) \ F(CMP0069) \ - F(CMP0073) + F(CMP0073) \ + F(CMP0076) \ + F(CMP0081) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index ee440079f..8f565c815 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -35,19 +35,19 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, srcdir += "_SOURCE_DIR"; this->Makefile->AddCacheDefinition( - bindir, this->Makefile->GetCurrentBinaryDirectory(), + bindir, this->Makefile->GetCurrentBinaryDirectory().c_str(), "Value Computed by CMake", cmStateEnums::STATIC); this->Makefile->AddCacheDefinition( - srcdir, this->Makefile->GetCurrentSourceDirectory(), + srcdir, this->Makefile->GetCurrentSourceDirectory().c_str(), "Value Computed by CMake", cmStateEnums::STATIC); bindir = "PROJECT_BINARY_DIR"; srcdir = "PROJECT_SOURCE_DIR"; - this->Makefile->AddDefinition(bindir, - this->Makefile->GetCurrentBinaryDirectory()); - this->Makefile->AddDefinition(srcdir, - this->Makefile->GetCurrentSourceDirectory()); + this->Makefile->AddDefinition( + bindir, this->Makefile->GetCurrentBinaryDirectory().c_str()); + this->Makefile->AddDefinition( + srcdir, this->Makefile->GetCurrentSourceDirectory().c_str()); this->Makefile->AddDefinition("PROJECT_NAME", projectName.c_str()); @@ -300,19 +300,15 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } } - if (haveDescription) { - this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str()); - this->Makefile->AddDefinition(projectName + "_DESCRIPTION", - description.c_str()); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_DESCRIPTION", description.c_str()); - } + this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str()); + this->Makefile->AddDefinition(projectName + "_DESCRIPTION", + description.c_str()); + TopLevelCMakeVarCondSet("CMAKE_PROJECT_DESCRIPTION", description.c_str()); - if (haveHomepage) { - this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage.c_str()); - this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL", - homepage.c_str()); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str()); - } + this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage.c_str()); + this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL", + homepage.c_str()); + TopLevelCMakeVarCondSet("CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str()); if (languages.empty()) { // if no language is specified do c and c++ diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx index 09cc63a40..d2133ed79 100644 --- a/Source/cmQTWrapCPPCommand.cxx +++ b/Source/cmQTWrapCPPCommand.cxx @@ -21,7 +21,7 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& args, } // Get the moc executable to run in the custom command. - const char* moc_exe = + std::string const& moc_exe = this->Makefile->GetRequiredDefinition("QT_MOC_EXECUTABLE"); // Get the variable holding the list of sources. diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx index da36cdf43..25dcd1a64 100644 --- a/Source/cmQTWrapUICommand.cxx +++ b/Source/cmQTWrapUICommand.cxx @@ -21,9 +21,9 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args, } // Get the uic and moc executables to run in the custom commands. - const char* uic_exe = + std::string const& uic_exe = this->Makefile->GetRequiredDefinition("QT_UIC_EXECUTABLE"); - const char* moc_exe = + std::string const& moc_exe = this->Makefile->GetRequiredDefinition("QT_MOC_EXECUTABLE"); // Get the variable holding the list of sources. diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index a3e16ac1a..4118dc79c 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -28,6 +28,32 @@ public: RCC }; + /// @brief Integer version + struct IntegerVersion + { + unsigned int Major = 0; + unsigned int Minor = 0; + + IntegerVersion() = default; + IntegerVersion(unsigned int major, unsigned int minor) + : Major(major) + , Minor(minor) + { + } + + bool operator>(IntegerVersion const version) + { + return (this->Major > version.Major) || + ((this->Major == version.Major) && (this->Minor > version.Minor)); + } + + bool operator>=(IntegerVersion const version) + { + return (this->Major > version.Major) || + ((this->Major == version.Major) && (this->Minor >= version.Minor)); + } + }; + public: /// @brief Returns the generator name static std::string const& GeneratorName(GeneratorT genType); diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 34196d9d8..8a202a2f6 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -37,23 +37,6 @@ #include <utility> #include <vector> -inline static const char* SafeString(const char* value) -{ - return (value != nullptr) ? value : ""; -} - -inline static std::string GetSafeProperty(cmGeneratorTarget const* target, - const char* key) -{ - return std::string(SafeString(target->GetProperty(key))); -} - -inline static std::string GetSafeProperty(cmSourceFile const* sf, - const char* key) -{ - return std::string(SafeString(sf->GetProperty(key))); -} - static std::size_t GetParallelCPUCount() { static std::size_t count = 0; @@ -190,21 +173,20 @@ static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin, return cycle; } -cmQtAutoGenInitializer::cmQtAutoGenInitializer( - cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled, - std::string const& qtVersionMajor) +cmQtAutoGenInitializer::cmQtAutoGenInitializer(cmGeneratorTarget* target, + bool mocEnabled, + bool uicEnabled, + bool rccEnabled, + IntegerVersion const& qtVersion) : Target(target) - , MocEnabled(mocEnabled) - , UicEnabled(uicEnabled) - , RccEnabled(rccEnabled) - , MultiConfig(false) - , QtVersionMajor(qtVersionMajor) + , QtVersion(qtVersion) { - this->QtVersionMinor = - cmQtAutoGenInitializer::GetQtMinorVersion(target, this->QtVersionMajor); + Moc.Enabled = mocEnabled; + Uic.Enabled = uicEnabled; + Rcc.Enabled = rccEnabled; } -void cmQtAutoGenInitializer::InitCustomTargets() +bool cmQtAutoGenInitializer::InitCustomTargets() { cmMakefile* makefile = this->Target->Target->GetMakefile(); cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); @@ -217,48 +199,17 @@ void cmQtAutoGenInitializer::InitCustomTargets() this->ConfigsList.push_back(this->ConfigDefault); } - // Autogen target name - this->AutogenTargetName = this->Target->GetName(); - this->AutogenTargetName += "_autogen"; - - // Autogen directories - { - // Collapsed current binary directory - std::string const cbd = cmSystemTools::CollapseFullPath( - "", makefile->GetCurrentBinaryDirectory()); - - // Autogen info dir - this->DirInfo = cbd; - this->DirInfo += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); - this->DirInfo += '/'; - this->DirInfo += this->AutogenTargetName; - this->DirInfo += ".dir"; - cmSystemTools::ConvertToUnixSlashes(this->DirInfo); - - // Autogen build dir - this->DirBuild = GetSafeProperty(this->Target, "AUTOGEN_BUILD_DIR"); - if (this->DirBuild.empty()) { - this->DirBuild = cbd; - this->DirBuild += '/'; - this->DirBuild += this->AutogenTargetName; + // Verbosity + this->Verbosity = makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE"); + if (!this->Verbosity.empty()) { + unsigned long iVerb = 0; + if (!cmSystemTools::StringToULong(this->Verbosity.c_str(), &iVerb)) { + // Non numeric verbosity + this->Verbosity = cmSystemTools::IsOn(this->Verbosity) ? "1" : "0"; } - cmSystemTools::ConvertToUnixSlashes(this->DirBuild); - - // Working directory - this->DirWork = cbd; - cmSystemTools::ConvertToUnixSlashes(this->DirWork); } - // Autogen files - { - this->AutogenInfoFile = this->DirInfo; - this->AutogenInfoFile += "/AutogenInfo.cmake"; - - this->AutogenSettingsFile = this->DirInfo; - this->AutogenSettingsFile += "/AutogenOldSettings.txt"; - } - - // Autogen target FOLDER property + // Targets FOLDER { const char* folder = makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); @@ -268,107 +219,321 @@ void cmQtAutoGenInitializer::InitCustomTargets() } // Inherit FOLDER property from target (#13688) if (folder == nullptr) { - folder = SafeString(this->Target->Target->GetProperty("FOLDER")); + folder = this->Target->GetProperty("FOLDER"); } if (folder != nullptr) { - this->AutogenFolder = folder; + this->TargetsFolder = folder; } } - std::set<std::string> autogenDependFiles; - std::set<cmTarget*> autogenDependTargets; - std::vector<std::string> autogenProvides; - - // Remove build directories on cleanup - AddCleanFile(makefile, this->DirBuild); - // Remove old settings on cleanup + // Common directories { - std::string base = this->DirInfo; - base += "/AutogenOldSettings"; + // Collapsed current binary directory + std::string const cbd = cmSystemTools::CollapseFullPath( + std::string(), makefile->GetCurrentBinaryDirectory()); + + // Info directory + this->Dir.Info = cbd; + this->Dir.Info += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); + this->Dir.Info += '/'; + this->Dir.Info += this->Target->GetName(); + this->Dir.Info += "_autogen"; + this->Dir.Info += ".dir"; + cmSystemTools::ConvertToUnixSlashes(this->Dir.Info); + + // Build directory + this->Dir.Build = this->Target->GetSafeProperty("AUTOGEN_BUILD_DIR"); + if (this->Dir.Build.empty()) { + this->Dir.Build = cbd; + this->Dir.Build += '/'; + this->Dir.Build += this->Target->GetName(); + this->Dir.Build += "_autogen"; + } + cmSystemTools::ConvertToUnixSlashes(this->Dir.Build); + // Cleanup build directory + AddCleanFile(makefile, this->Dir.Build); + + // Working directory + this->Dir.Work = cbd; + cmSystemTools::ConvertToUnixSlashes(this->Dir.Work); + + // Include directory + this->Dir.Include = this->Dir.Build; + this->Dir.Include += "/include"; + if (this->MultiConfig) { + this->Dir.Include += "_$<CONFIG>"; + } + // Per config include directories if (this->MultiConfig) { for (std::string const& cfg : this->ConfigsList) { - std::string filename = base; - filename += '_'; - filename += cfg; - filename += ".cmake"; - AddCleanFile(makefile, filename); + std::string& dir = this->Dir.ConfigInclude[cfg]; + dir = this->Dir.Build; + dir += "/include_"; + dir += cfg; } - } else { - AddCleanFile(makefile, base.append(".cmake")); } } - // Add moc compilation to generated files list - if (this->MocEnabled) { - std::string mocsComp = this->DirBuild + "/mocs_compilation.cpp"; - this->AddGeneratedSource(mocsComp, GeneratorT::MOC); - autogenProvides.push_back(std::move(mocsComp)); + // Moc, Uic and _autogen target settings + if (this->Moc.Enabled || this->Uic.Enabled) { + // Init moc specific settings + if (this->Moc.Enabled && !InitMoc()) { + return false; + } + + // Init uic specific settings + if (this->Uic.Enabled && !InitUic()) { + return false; + } + + // Autogen target name + this->AutogenTarget.Name = this->Target->GetName(); + this->AutogenTarget.Name += "_autogen"; + + // Autogen target parallel processing + this->AutogenTarget.Parallel = + this->Target->GetSafeProperty("AUTOGEN_PARALLEL"); + if (this->AutogenTarget.Parallel.empty() || + (this->AutogenTarget.Parallel == "AUTO")) { + // Autodetect number of CPUs + this->AutogenTarget.Parallel = std::to_string(GetParallelCPUCount()); + } + + // Autogen target info and settings files + { + this->AutogenTarget.InfoFile = this->Dir.Info; + this->AutogenTarget.InfoFile += "/AutogenInfo.cmake"; + + this->AutogenTarget.SettingsFile = this->Dir.Info; + this->AutogenTarget.SettingsFile += "/AutogenOldSettings.txt"; + + if (this->MultiConfig) { + for (std::string const& cfg : this->ConfigsList) { + std::string& filename = this->AutogenTarget.ConfigSettingsFile[cfg]; + filename = + AppendFilenameSuffix(this->AutogenTarget.SettingsFile, "_" + cfg); + AddCleanFile(makefile, filename); + } + } else { + AddCleanFile(makefile, this->AutogenTarget.SettingsFile); + } + } + + // Autogen target: Compute user defined dependencies + { + std::string const deps = + this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS"); + if (!deps.empty()) { + std::vector<std::string> extraDeps; + cmSystemTools::ExpandListArgument(deps, extraDeps); + for (std::string const& depName : extraDeps) { + // Allow target and file dependencies + auto* depTarget = makefile->FindTargetToUse(depName); + if (depTarget != nullptr) { + this->AutogenTarget.DependTargets.insert(depTarget); + } else { + this->AutogenTarget.DependFiles.insert(depName); + } + } + } + } } - // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES - if (this->MocEnabled || this->UicEnabled || - (this->RccEnabled && this->MultiConfig)) { - std::string includeDir = this->DirBuild; - includeDir += "/include"; + // Init rcc specific settings + if (this->Rcc.Enabled && !InitRcc()) { + return false; + } + + // Add autogen include directory to the origin target INCLUDE_DIRECTORIES + if (this->Moc.Enabled || this->Uic.Enabled || + (this->Rcc.Enabled && this->MultiConfig)) { + this->Target->AddIncludeDirectory(this->Dir.Include, true); + } + + // Scan files + if (!this->InitScanFiles()) { + return false; + } + + // Create autogen target + if ((this->Moc.Enabled || this->Uic.Enabled) && !this->InitAutogenTarget()) { + return false; + } + + // Create rcc targets + if (this->Rcc.Enabled && !this->InitRccTargets()) { + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::InitMoc() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + + // Mocs compilation file + this->Moc.MocsCompilation = this->Dir.Build; + this->Moc.MocsCompilation += "/mocs_compilation.cpp"; + + // Moc predefs command + if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && + (this->QtVersion >= IntegerVersion(5, 8))) { + this->Moc.PredefsCmd = + makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"); + } + + // Moc includes + { + bool const appendImplicit = (this->QtVersion.Major == 5); + auto GetIncludeDirs = + [this, localGen, appendImplicit](std::string const& cfg) -> std::string { + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + std::vector<std::string> dirs; + localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false, + appendImplicit); + return cmJoin(dirs, ";"); + }; + + // Default configuration include directories + this->Moc.Includes = GetIncludeDirs(this->ConfigDefault); + // Other configuration settings if (this->MultiConfig) { - includeDir += "_$<CONFIG>"; + for (std::string const& cfg : this->ConfigsList) { + std::string dirs = GetIncludeDirs(cfg); + if (dirs != this->Moc.Includes) { + this->Moc.ConfigIncludes[cfg] = std::move(dirs); + } + } } - this->Target->AddIncludeDirectory(includeDir, true); } - // Acquire rcc executable and features - if (this->RccEnabled) { - { - std::string err; - if (this->QtVersionMajor == "5") { - cmGeneratorTarget* tgt = - localGen->FindGeneratorTargetToUse("Qt5::rcc"); - if (tgt != nullptr) { - this->RccExecutable = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTORCC: Qt5::rcc target not found"; - } - } else if (QtVersionMajor == "4") { - cmGeneratorTarget* tgt = - localGen->FindGeneratorTargetToUse("Qt4::rcc"); - if (tgt != nullptr) { - this->RccExecutable = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTORCC: Qt4::rcc target not found"; + // Moc compile definitions + { + auto GetCompileDefinitions = + [this, localGen](std::string const& cfg) -> std::string { + std::set<std::string> defines; + localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX"); + return cmJoin(defines, ";"); + }; + + // Default configuration defines + this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault); + // Other configuration defines + if (this->MultiConfig) { + for (std::string const& cfg : this->ConfigsList) { + std::string defines = GetCompileDefinitions(cfg); + if (defines != this->Moc.Defines) { + this->Moc.ConfigDefines[cfg] = std::move(defines); } - } else { - err = "The AUTORCC feature supports only Qt 4 and Qt 5"; } - if (!err.empty()) { - err += " ("; - err += this->Target->GetName(); - err += ")"; - cmSystemTools::Error(err.c_str()); + } + } + + // Moc executable + if (!GetMocExecutable()) { + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::InitUic() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + // Uic search paths + { + std::string const usp = + this->Target->GetSafeProperty("AUTOUIC_SEARCH_PATHS"); + if (!usp.empty()) { + cmSystemTools::ExpandListArgument(usp, this->Uic.SearchPaths); + std::string const& srcDir = makefile->GetCurrentSourceDirectory(); + for (std::string& path : this->Uic.SearchPaths) { + path = cmSystemTools::CollapseFullPath(path, srcDir); } } - // Detect if rcc supports (-)-list - if (!this->RccExecutable.empty() && (this->QtVersionMajor == "5")) { - std::vector<std::string> command; - command.push_back(this->RccExecutable); - command.push_back("--help"); - std::string rccStdOut; - std::string rccStdErr; - int retVal = 0; - bool result = cmSystemTools::RunSingleCommand( - command, &rccStdOut, &rccStdErr, &retVal, nullptr, - cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); - if (result && retVal == 0 && - rccStdOut.find("--list") != std::string::npos) { - this->RccListOptions.push_back("--list"); - } else { - this->RccListOptions.push_back("-list"); + } + // Uic target options + { + auto UicGetOpts = [this](std::string const& cfg) -> std::string { + std::vector<std::string> opts; + this->Target->GetAutoUicOptions(opts, cfg); + return cmJoin(opts, ";"); + }; + + // Default settings + this->Uic.Options = UicGetOpts(this->ConfigDefault); + + // Configuration specific settings + if (this->MultiConfig) { + for (std::string const& cfg : this->ConfigsList) { + std::string options = UicGetOpts(cfg); + if (options != this->Uic.Options) { + this->Uic.ConfigOptions[cfg] = std::move(options); + } + } + } + } + // .ui files skip and options + { + std::string const uiExt = "ui"; + std::string pathError; + for (cmSourceFile* sf : makefile->GetSourceFiles()) { + // sf->GetExtension() is only valid after sf->GetFullPath() ... + // Since we're iterating over source files that might be not in the + // target we need to check for path errors (not existing files). + std::string const& fPath = sf->GetFullPath(&pathError); + if (!pathError.empty()) { + pathError.clear(); + continue; + } + if (sf->GetExtension() == uiExt) { + std::string const absFile = cmSystemTools::GetRealPath(fPath); + // Check if the .ui file should be skipped + if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || + sf->GetPropertyAsBool("SKIP_AUTOGEN")) { + this->Uic.Skip.insert(absFile); + } + // Check if the .ui file has uic options + std::string const uicOpts = sf->GetSafeProperty("AUTOUIC_OPTIONS"); + if (!uicOpts.empty()) { + // Check if file isn't skipped + if (this->Uic.Skip.count(absFile) == 0) { + this->Uic.FileFiles.push_back(absFile); + std::vector<std::string> optsVec; + cmSystemTools::ExpandListArgument(uicOpts, optsVec); + this->Uic.FileOptions.push_back(std::move(optsVec)); + } + } } } } - // Extract relevant source files - std::vector<std::string> generatedSources; - std::vector<std::string> generatedHeaders; + // Uic executable + if (!GetUicExecutable()) { + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::InitRcc() +{ + if (!GetRccExecutable()) { + return false; + } + return true; +} + +bool cmQtAutoGenInitializer::InitScanFiles() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + // Scan through target files { std::string const qrcExt = "qrc"; std::vector<cmSourceFile*> srcFiles; @@ -381,34 +546,34 @@ void cmQtAutoGenInitializer::InitCustomTargets() std::string const& fPath = sf->GetFullPath(); std::string const& ext = sf->GetExtension(); // Register generated files that will be scanned by moc or uic - if (this->MocEnabled || this->UicEnabled) { + if (this->Moc.Enabled || this->Uic.Enabled) { cmSystemTools::FileFormat const fileType = cmSystemTools::GetFileFormat(ext.c_str()); if ((fileType == cmSystemTools::CXX_FILE_FORMAT) || (fileType == cmSystemTools::HEADER_FILE_FORMAT)) { std::string const absPath = cmSystemTools::GetRealPath(fPath); - if ((this->MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) || - (this->UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) { + if ((this->Moc.Enabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) || + (this->Uic.Enabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) { // Register source const bool generated = sf->GetPropertyAsBool("GENERATED"); if (fileType == cmSystemTools::HEADER_FILE_FORMAT) { if (generated) { - generatedHeaders.push_back(absPath); + this->AutogenTarget.HeadersGenerated.push_back(absPath); } else { - this->Headers.push_back(absPath); + this->AutogenTarget.Headers.push_back(absPath); } } else { if (generated) { - generatedSources.push_back(absPath); + this->AutogenTarget.SourcesGenerated.push_back(absPath); } else { - this->Sources.push_back(absPath); + this->AutogenTarget.Sources.push_back(absPath); } } } } } // Register rcc enabled files - if (this->RccEnabled && (ext == qrcExt) && + if (this->Rcc.Enabled && (ext == qrcExt) && !sf->GetPropertyAsBool("SKIP_AUTORCC")) { // Register qrc file { @@ -419,148 +584,155 @@ void cmQtAutoGenInitializer::InitCustomTargets() qrc.Generated = sf->GetPropertyAsBool("GENERATED"); // RCC options { - std::string const opts = GetSafeProperty(sf, "AUTORCC_OPTIONS"); + std::string const opts = sf->GetSafeProperty("AUTORCC_OPTIONS"); if (!opts.empty()) { cmSystemTools::ExpandListArgument(opts, qrc.Options); } } - this->Qrcs.push_back(std::move(qrc)); + this->Rcc.Qrcs.push_back(std::move(qrc)); } } } - // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's - // sources meta data cache. Clear it so that OBJECT library targets that - // are AUTOGEN initialized after this target get their added - // mocs_compilation.cpp source acknowledged by this target. - this->Target->ClearSourcesCache(); } - // Read skip files from makefile sources - if (this->MocEnabled || this->UicEnabled) { - std::string pathError; - for (cmSourceFile* sf : makefile->GetSourceFiles()) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - // Since we're iterating over source files that might be not in the - // target we need to check for path errors (not existing files). - std::string const& fPath = sf->GetFullPath(&pathError); - if (!pathError.empty()) { - pathError.clear(); - continue; - } - cmSystemTools::FileFormat const fileType = - cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); - if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && - !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { - continue; - } - const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN"); - const bool mocSkip = - this->MocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); - const bool uicSkip = - this->UicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); - if (mocSkip || uicSkip) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - if (mocSkip) { - this->MocSkip.insert(absFile); + // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's + // sources meta data cache. Clear it so that OBJECT library targets that + // are AUTOGEN initialized after this target get their added + // mocs_compilation.cpp source acknowledged by this target. + this->Target->ClearSourcesCache(); + + if (this->Moc.Enabled || this->Uic.Enabled) { + // Read skip files from makefile sources + { + std::string pathError; + for (cmSourceFile* sf : makefile->GetSourceFiles()) { + // sf->GetExtension() is only valid after sf->GetFullPath() ... + // Since we're iterating over source files that might be not in the + // target we need to check for path errors (not existing files). + std::string const& fPath = sf->GetFullPath(&pathError); + if (!pathError.empty()) { + pathError.clear(); + continue; + } + cmSystemTools::FileFormat const fileType = + cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); + if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && + !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { + continue; } - if (uicSkip) { - this->UicSkip.insert(absFile); + const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN"); + const bool mocSkip = this->Moc.Enabled && + (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); + const bool uicSkip = this->Uic.Enabled && + (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); + if (mocSkip || uicSkip) { + std::string const absFile = cmSystemTools::GetRealPath(fPath); + if (mocSkip) { + this->Moc.Skip.insert(absFile); + } + if (uicSkip) { + this->Uic.Skip.insert(absFile); + } } } } - } - // Process GENERATED sources and headers - if (!generatedSources.empty() || !generatedHeaders.empty()) { - // Check status of policy CMP0071 - bool policyAccept = false; - bool policyWarn = false; - cmPolicies::PolicyStatus const CMP0071_status = - makefile->GetPolicyStatus(cmPolicies::CMP0071); - switch (CMP0071_status) { - case cmPolicies::WARN: - policyWarn = true; - CM_FALLTHROUGH; - case cmPolicies::OLD: - // Ignore GENERATED file - break; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - // Process GENERATED file - policyAccept = true; - break; - } - - if (policyAccept) { - // Accept GENERATED sources - for (std::string const& absFile : generatedHeaders) { - this->Headers.push_back(absFile); - autogenDependFiles.insert(absFile); - } - for (std::string const& absFile : generatedSources) { - this->Sources.push_back(absFile); - autogenDependFiles.insert(absFile); + // Process GENERATED sources and headers + if (!this->AutogenTarget.SourcesGenerated.empty() || + !this->AutogenTarget.HeadersGenerated.empty()) { + // Check status of policy CMP0071 + bool policyAccept = false; + bool policyWarn = false; + cmPolicies::PolicyStatus const CMP0071_status = + makefile->GetPolicyStatus(cmPolicies::CMP0071); + switch (CMP0071_status) { + case cmPolicies::WARN: + policyWarn = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + // Ignore GENERATED file + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Process GENERATED file + policyAccept = true; + break; } - } else { - if (policyWarn) { - std::string msg; - msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071); - msg += "\n"; - std::string tools; - std::string property; - if (this->MocEnabled && this->UicEnabled) { - tools = "AUTOMOC and AUTOUIC"; - property = "SKIP_AUTOGEN"; - } else if (this->MocEnabled) { - tools = "AUTOMOC"; - property = "SKIP_AUTOMOC"; - } else if (this->UicEnabled) { - tools = "AUTOUIC"; - property = "SKIP_AUTOUIC"; + + if (policyAccept) { + // Accept GENERATED sources + for (std::string const& absFile : + this->AutogenTarget.HeadersGenerated) { + this->AutogenTarget.Headers.push_back(absFile); + this->AutogenTarget.DependFiles.insert(absFile); } - msg += "For compatibility, CMake is excluding the GENERATED source " - "file(s):\n"; - for (const std::string& absFile : generatedHeaders) { - msg.append(" ").append(Quoted(absFile)).append("\n"); + for (std::string const& absFile : + this->AutogenTarget.SourcesGenerated) { + this->AutogenTarget.Sources.push_back(absFile); + this->AutogenTarget.DependFiles.insert(absFile); } - for (const std::string& absFile : generatedSources) { - msg.append(" ").append(Quoted(absFile)).append("\n"); + } else { + if (policyWarn) { + std::string msg; + msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071); + msg += "\n"; + std::string tools; + std::string property; + if (this->Moc.Enabled && this->Uic.Enabled) { + tools = "AUTOMOC and AUTOUIC"; + property = "SKIP_AUTOGEN"; + } else if (this->Moc.Enabled) { + tools = "AUTOMOC"; + property = "SKIP_AUTOMOC"; + } else if (this->Uic.Enabled) { + tools = "AUTOUIC"; + property = "SKIP_AUTOUIC"; + } + msg += "For compatibility, CMake is excluding the GENERATED source " + "file(s):\n"; + for (const std::string& absFile : + this->AutogenTarget.HeadersGenerated) { + msg.append(" ").append(Quoted(absFile)).append("\n"); + } + for (const std::string& absFile : + this->AutogenTarget.SourcesGenerated) { + msg.append(" ").append(Quoted(absFile)).append("\n"); + } + msg += "from processing by "; + msg += tools; + msg += + ". If any of the files should be processed, set CMP0071 to NEW. " + "If any of the files should not be processed, " + "explicitly exclude them by setting the source file property "; + msg += property; + msg += ":\n set_property(SOURCE file.h PROPERTY "; + msg += property; + msg += " ON)\n"; + makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); } - msg += "from processing by "; - msg += tools; - msg += - ". If any of the files should be processed, set CMP0071 to NEW. " - "If any of the files should not be processed, " - "explicitly exclude them by setting the source file property "; - msg += property; - msg += ":\n set_property(SOURCE file.h PROPERTY "; - msg += property; - msg += " ON)\n"; - makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); } } - // Clear lists - generatedSources.clear(); - generatedHeaders.clear(); - } - // Sort headers and sources - if (this->MocEnabled || this->UicEnabled) { - std::sort(this->Headers.begin(), this->Headers.end()); - std::sort(this->Sources.begin(), this->Sources.end()); + // Sort headers and sources + if (this->Moc.Enabled || this->Uic.Enabled) { + std::sort(this->AutogenTarget.Headers.begin(), + this->AutogenTarget.Headers.end()); + std::sort(this->AutogenTarget.Sources.begin(), + this->AutogenTarget.Sources.end()); + } } // Process qrc files - if (!this->Qrcs.empty()) { - const bool QtV5 = (this->QtVersionMajor == "5"); + if (!this->Rcc.Qrcs.empty()) { + const bool QtV5 = (this->QtVersion.Major == 5); // Target rcc options std::vector<std::string> optionsTarget; cmSystemTools::ExpandListArgument( - GetSafeProperty(this->Target, "AUTORCC_OPTIONS"), optionsTarget); + this->Target->GetSafeProperty("AUTORCC_OPTIONS"), optionsTarget); // Check if file name is unique - for (Qrc& qrc : this->Qrcs) { + for (Qrc& qrc : this->Rcc.Qrcs) { qrc.Unique = true; - for (Qrc const& qrc2 : this->Qrcs) { + for (Qrc const& qrc2 : this->Rcc.Qrcs) { if ((&qrc != &qrc2) && (qrc.QrcName == qrc2.QrcName)) { qrc.Unique = false; break; @@ -570,11 +742,11 @@ void cmQtAutoGenInitializer::InitCustomTargets() // Path checksum and file names { cmFilePathChecksum const fpathCheckSum(makefile); - for (Qrc& qrc : this->Qrcs) { + for (Qrc& qrc : this->Rcc.Qrcs) { qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile); // RCC output file name { - std::string rccFile = this->DirBuild + "/"; + std::string rccFile = this->Dir.Build + "/"; rccFile += qrc.PathChecksum; rccFile += "/qrc_"; rccFile += qrc.QrcName; @@ -582,7 +754,7 @@ void cmQtAutoGenInitializer::InitCustomTargets() qrc.RccFile = std::move(rccFile); } { - std::string base = this->DirInfo; + std::string base = this->Dir.Info; base += "/RCC"; base += qrc.QrcName; if (!qrc.Unique) { @@ -597,11 +769,18 @@ void cmQtAutoGenInitializer::InitCustomTargets() qrc.SettingsFile = base; qrc.SettingsFile += "Settings.txt"; + + if (this->MultiConfig) { + for (std::string const& cfg : this->ConfigsList) { + qrc.ConfigSettingsFile[cfg] = + AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg); + } + } } } } // RCC options - for (Qrc& qrc : this->Qrcs) { + for (Qrc& qrc : this->Rcc.Qrcs) { // Target options std::vector<std::string> opts = optionsTarget; // Merge computed "-name XYZ" option @@ -622,313 +801,410 @@ void cmQtAutoGenInitializer::InitCustomTargets() RccMergeOptions(opts, qrc.Options, QtV5); qrc.Options = std::move(opts); } - for (Qrc& qrc : this->Qrcs) { - // Register file at target - this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC); - - std::vector<std::string> ccOutput; - ccOutput.push_back(qrc.RccFile); - - cmCustomCommandLines commandLines; - if (this->MultiConfig) { - // Build for all configurations - for (std::string const& config : this->ConfigsList) { - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autorcc"); - currentLine.push_back(qrc.InfoFile); - currentLine.push_back(config); - commandLines.push_back(std::move(currentLine)); + // RCC resources + for (Qrc& qrc : this->Rcc.Qrcs) { + if (!qrc.Generated) { + std::string error; + if (!RccListInputs(qrc.QrcFile, qrc.Resources, error)) { + cmSystemTools::Error(error.c_str()); + return false; } - } else { - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autorcc"); - currentLine.push_back(qrc.InfoFile); - currentLine.push_back("$<CONFIG>"); - commandLines.push_back(std::move(currentLine)); } - std::string ccComment = "Automatic RCC for "; - ccComment += FileProjectRelativePath(makefile, qrc.QrcFile); + } + } - if (qrc.Generated) { - // Create custom rcc target - std::string ccName; - { - ccName = this->Target->GetName(); - ccName += "_arcc_"; - ccName += qrc.QrcName; - if (!qrc.Unique) { - ccName += "_"; - ccName += qrc.PathChecksum; - } - std::vector<std::string> ccDepends; - // Add the .qrc and info file to the custom target dependencies - ccDepends.push_back(qrc.QrcFile); - ccDepends.push_back(qrc.InfoFile); - - cmTarget* autoRccTarget = makefile->AddUtilityCommand( - ccName, cmMakefile::TargetOrigin::Generator, true, - this->DirWork.c_str(), ccOutput, ccDepends, commandLines, false, - ccComment.c_str()); - // Create autogen generator target - localGen->AddGeneratorTarget( - new cmGeneratorTarget(autoRccTarget, localGen)); - - // Set FOLDER property in autogen target - if (!this->AutogenFolder.empty()) { - autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str()); - } - } - // Add autogen target to the origin target dependencies - this->Target->Target->AddUtility(ccName, makefile); - } else { - // Create custom rcc command - { - std::vector<std::string> ccByproducts; - std::vector<std::string> ccDepends; - // Add the .qrc and info file to the custom command dependencies - ccDepends.push_back(qrc.QrcFile); - ccDepends.push_back(qrc.InfoFile); + return true; +} - // Add the resource files to the dependencies - { - std::string error; - if (RccListInputs(qrc.QrcFile, qrc.Resources, error)) { - for (std::string const& fileName : qrc.Resources) { - // Add resource file to the custom command dependencies - ccDepends.push_back(fileName); - } - } else { - cmSystemTools::Error(error.c_str()); - } - } - makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends, - /*main_dependency*/ std::string(), - commandLines, ccComment.c_str(), - this->DirWork.c_str()); - } - // Reconfigure when .qrc file changes - makefile->AddCMakeDependFile(qrc.QrcFile); +bool cmQtAutoGenInitializer::InitAutogenTarget() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator(); + + // Register info file as generated by CMake + makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile); + + // Files provided by the autogen target + std::vector<std::string> autogenProvides; + if (this->Moc.Enabled) { + this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC); + autogenProvides.push_back(this->Moc.MocsCompilation); + } + + // Compose target comment + std::string autogenComment; + { + std::string tools; + if (this->Moc.Enabled) { + tools += "MOC"; + } + if (this->Uic.Enabled) { + if (!tools.empty()) { + tools += " and "; } + tools += "UIC"; } + autogenComment = "Automatic "; + autogenComment += tools; + autogenComment += " for target "; + autogenComment += this->Target->GetName(); } - // Create _autogen target - if (this->MocEnabled || this->UicEnabled) { - // Add user defined autogen target dependencies - { - std::string const deps = - GetSafeProperty(this->Target, "AUTOGEN_TARGET_DEPENDS"); - if (!deps.empty()) { - std::vector<std::string> extraDeps; - cmSystemTools::ExpandListArgument(deps, extraDeps); - for (std::string const& depName : extraDeps) { - // Allow target and file dependencies - auto* depTarget = makefile->FindTargetToUse(depName); - if (depTarget != nullptr) { - autogenDependTargets.insert(depTarget); - } else { - autogenDependFiles.insert(depName); - } - } - } + // Compose command lines + cmCustomCommandLines commandLines; + { + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_autogen"); + currentLine.push_back(this->AutogenTarget.InfoFile); + currentLine.push_back("$<CONFIGURATION>"); + commandLines.push_back(std::move(currentLine)); + } + + // Use PRE_BUILD on demand + bool usePRE_BUILD = false; + if (globalGen->GetName().find("Visual Studio") != std::string::npos) { + // Under VS use a PRE_BUILD event instead of a separate target to + // reduce the number of targets loaded into the IDE. + // This also works around a VS 11 bug that may skip updating the target: + // https://connect.microsoft.com/VisualStudio/feedback/details/769495 + usePRE_BUILD = true; + } + // Disable PRE_BUILD in some cases + if (usePRE_BUILD) { + // Cannot use PRE_BUILD with file depends + if (!this->AutogenTarget.DependFiles.empty()) { + usePRE_BUILD = false; + } + } + // Create the autogen target/command + if (usePRE_BUILD) { + // Add additional autogen target dependencies to origin target + for (cmTarget* depTarget : this->AutogenTarget.DependTargets) { + this->Target->Target->AddUtility(depTarget->GetName(), makefile); } - // Compose target comment - std::string autogenComment; + // Add the pre-build command directly to bypass the OBJECT_LIBRARY + // rejection in cmMakefile::AddCustomCommandToTarget because we know + // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. + // + // PRE_BUILD does not support file dependencies! + const std::vector<std::string> no_output; + const std::vector<std::string> no_deps; + cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps, + commandLines, autogenComment.c_str(), + this->Dir.Work.c_str()); + cc.SetEscapeOldStyle(false); + cc.SetEscapeAllowMakeVars(true); + this->Target->Target->AddPreBuildCommand(cc); + } else { + + // Add link library target dependencies to the autogen target + // dependencies { - std::string tools; - if (this->MocEnabled) { - tools += "MOC"; + // add_dependencies/addUtility do not support generator expressions. + // We depend only on the libraries found in all configs therefore. + std::map<cmGeneratorTarget const*, std::size_t> commonTargets; + for (std::string const& config : this->ConfigsList) { + cmLinkImplementationLibraries const* libs = + this->Target->GetLinkImplementationLibraries(config); + if (libs != nullptr) { + for (cmLinkItem const& item : libs->Libraries) { + cmGeneratorTarget const* libTarget = item.Target; + if ((libTarget != nullptr) && + !StaticLibraryCycle(this->Target, libTarget, config)) { + // Increment target config count + commonTargets[libTarget]++; + } + } + } } - if (this->UicEnabled) { - if (!tools.empty()) { - tools += " and "; + for (auto const& item : commonTargets) { + if (item.second == this->ConfigsList.size()) { + this->AutogenTarget.DependTargets.insert(item.first->Target); } - tools += "UIC"; } - autogenComment = "Automatic "; - autogenComment += tools; - autogenComment += " for target "; - autogenComment += this->Target->GetName(); } - // Compose command lines + // Create autogen target + cmTarget* autogenTarget = makefile->AddUtilityCommand( + this->AutogenTarget.Name, cmMakefile::TargetOrigin::Generator, true, + this->Dir.Work.c_str(), /*byproducts=*/autogenProvides, + std::vector<std::string>(this->AutogenTarget.DependFiles.begin(), + this->AutogenTarget.DependFiles.end()), + commandLines, false, autogenComment.c_str()); + // Create autogen generator target + localGen->AddGeneratorTarget( + new cmGeneratorTarget(autogenTarget, localGen)); + + // Forward origin utilities to autogen target + for (std::string const& depName : this->Target->Target->GetUtilities()) { + autogenTarget->AddUtility(depName, makefile); + } + // Add additional autogen target dependencies to autogen target + for (cmTarget* depTarget : this->AutogenTarget.DependTargets) { + autogenTarget->AddUtility(depTarget->GetName(), makefile); + } + + // Set FOLDER property in autogen target + if (!this->TargetsFolder.empty()) { + autogenTarget->SetProperty("FOLDER", this->TargetsFolder.c_str()); + } + + // Add autogen target to the origin target dependencies + this->Target->Target->AddUtility(this->AutogenTarget.Name, makefile); + } + + return true; +} + +bool cmQtAutoGenInitializer::InitRccTargets() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + + for (Qrc const& qrc : this->Rcc.Qrcs) { + // Register info file as generated by CMake + makefile->AddCMakeOutputFile(qrc.InfoFile); + // Register file at target + this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC); + + std::vector<std::string> ccOutput; + ccOutput.push_back(qrc.RccFile); + cmCustomCommandLines commandLines; - { + if (this->MultiConfig) { + // Build for all configurations + for (std::string const& config : this->ConfigsList) { + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_autorcc"); + currentLine.push_back(qrc.InfoFile); + currentLine.push_back(config); + commandLines.push_back(std::move(currentLine)); + } + } else { cmCustomCommandLine currentLine; currentLine.push_back(cmSystemTools::GetCMakeCommand()); currentLine.push_back("-E"); - currentLine.push_back("cmake_autogen"); - currentLine.push_back(this->AutogenInfoFile); - currentLine.push_back("$<CONFIGURATION>"); + currentLine.push_back("cmake_autorcc"); + currentLine.push_back(qrc.InfoFile); + currentLine.push_back("$<CONFIG>"); commandLines.push_back(std::move(currentLine)); } + std::string ccComment = "Automatic RCC for "; + ccComment += FileProjectRelativePath(makefile, qrc.QrcFile); - // Use PRE_BUILD on demand - bool usePRE_BUILD = false; - if (globalGen->GetName().find("Visual Studio") != std::string::npos) { - // Under VS use a PRE_BUILD event instead of a separate target to - // reduce the number of targets loaded into the IDE. - // This also works around a VS 11 bug that may skip updating the target: - // https://connect.microsoft.com/VisualStudio/feedback/details/769495 - usePRE_BUILD = true; - } - // Disable PRE_BUILD in some cases - if (usePRE_BUILD) { - // Cannot use PRE_BUILD with file depends - if (!autogenDependFiles.empty()) { - usePRE_BUILD = false; - } - } - // Create the autogen target/command - if (usePRE_BUILD) { - // Add additional autogen target dependencies to origin target - for (cmTarget* depTarget : autogenDependTargets) { - this->Target->Target->AddUtility(depTarget->GetName(), makefile); - } - - // Add the pre-build command directly to bypass the OBJECT_LIBRARY - // rejection in cmMakefile::AddCustomCommandToTarget because we know - // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. - // - // PRE_BUILD does not support file dependencies! - const std::vector<std::string> no_output; - const std::vector<std::string> no_deps; - cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps, - commandLines, autogenComment.c_str(), - this->DirWork.c_str()); - cc.SetEscapeOldStyle(false); - cc.SetEscapeAllowMakeVars(true); - this->Target->Target->AddPreBuildCommand(cc); - } else { - - // Add link library target dependencies to the autogen target - // dependencies + if (qrc.Generated) { + // Create custom rcc target + std::string ccName; { - // add_dependencies/addUtility do not support generator expressions. - // We depend only on the libraries found in all configs therefore. - std::map<cmGeneratorTarget const*, std::size_t> commonTargets; - for (std::string const& config : this->ConfigsList) { - cmLinkImplementationLibraries const* libs = - this->Target->GetLinkImplementationLibraries(config); - if (libs != nullptr) { - for (cmLinkItem const& item : libs->Libraries) { - cmGeneratorTarget const* libTarget = item.Target; - if ((libTarget != nullptr) && - !StaticLibraryCycle(this->Target, libTarget, config)) { - // Increment target config count - commonTargets[libTarget]++; - } - } - } + ccName = this->Target->GetName(); + ccName += "_arcc_"; + ccName += qrc.QrcName; + if (!qrc.Unique) { + ccName += "_"; + ccName += qrc.PathChecksum; } - for (auto const& item : commonTargets) { - if (item.second == this->ConfigsList.size()) { - autogenDependTargets.insert(item.first->Target); - } + std::vector<std::string> ccDepends; + // Add the .qrc and info file to the custom target dependencies + ccDepends.push_back(qrc.QrcFile); + ccDepends.push_back(qrc.InfoFile); + + cmTarget* autoRccTarget = makefile->AddUtilityCommand( + ccName, cmMakefile::TargetOrigin::Generator, true, + this->Dir.Work.c_str(), ccOutput, ccDepends, commandLines, false, + ccComment.c_str()); + // Create autogen generator target + localGen->AddGeneratorTarget( + new cmGeneratorTarget(autoRccTarget, localGen)); + + // Set FOLDER property in autogen target + if (!this->TargetsFolder.empty()) { + autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str()); } } - - // Create autogen target - cmTarget* autogenTarget = makefile->AddUtilityCommand( - this->AutogenTargetName, cmMakefile::TargetOrigin::Generator, true, - this->DirWork.c_str(), /*byproducts=*/autogenProvides, - std::vector<std::string>(autogenDependFiles.begin(), - autogenDependFiles.end()), - commandLines, false, autogenComment.c_str()); - // Create autogen generator target - localGen->AddGeneratorTarget( - new cmGeneratorTarget(autogenTarget, localGen)); - - // Forward origin utilities to autogen target - for (std::string const& depName : this->Target->Target->GetUtilities()) { - autogenTarget->AddUtility(depName, makefile); - } - // Add additional autogen target dependencies to autogen target - for (cmTarget* depTarget : autogenDependTargets) { - autogenTarget->AddUtility(depTarget->GetName(), makefile); - } - - // Set FOLDER property in autogen target - if (!this->AutogenFolder.empty()) { - autogenTarget->SetProperty("FOLDER", this->AutogenFolder.c_str()); - } - // Add autogen target to the origin target dependencies - this->Target->Target->AddUtility(this->AutogenTargetName, makefile); + this->Target->Target->AddUtility(ccName, makefile); + } else { + // Create custom rcc command + { + std::vector<std::string> ccByproducts; + std::vector<std::string> ccDepends; + // Add the .qrc and info file to the custom command dependencies + ccDepends.push_back(qrc.QrcFile); + ccDepends.push_back(qrc.InfoFile); + + // Add the resource files to the dependencies + for (std::string const& fileName : qrc.Resources) { + // Add resource file to the custom command dependencies + ccDepends.push_back(fileName); + } + makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends, + /*main_dependency*/ std::string(), + commandLines, ccComment.c_str(), + this->Dir.Work.c_str()); + } + // Reconfigure when .qrc file changes + makefile->AddCMakeDependFile(qrc.QrcFile); } } + + return true; } -void cmQtAutoGenInitializer::SetupCustomTargets() +bool cmQtAutoGenInitializer::SetupCustomTargets() { - cmMakefile* makefile = this->Target->Target->GetMakefile(); - // Create info directory on demand - if (!cmSystemTools::MakeDirectory(this->DirInfo)) { - std::string emsg = ("Could not create directory: "); - emsg += Quoted(this->DirInfo); + if (!cmSystemTools::MakeDirectory(this->Dir.Info)) { + std::string emsg = ("AutoGen: Could not create directory: "); + emsg += Quoted(this->Dir.Info); cmSystemTools::Error(emsg.c_str()); - } - - // Configuration include directories - std::string includeDir = "include"; - std::map<std::string, std::string> includeDirs; - for (std::string const& cfg : this->ConfigsList) { - std::string& dir = includeDirs[cfg]; - dir = "include_"; - dir += cfg; + return false; } // Generate autogen target info file - if (this->MocEnabled || this->UicEnabled) { - if (this->MocEnabled) { - this->SetupCustomTargetsMoc(); + if (this->Moc.Enabled || this->Uic.Enabled) { + // Write autogen target info files + if (!this->SetupWriteAutogenInfo()) { + return false; } - if (this->UicEnabled) { - this->SetupCustomTargetsUic(); + } + + // Write AUTORCC info files + if (this->Rcc.Enabled && !this->SetupWriteRccInfo()) { + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + cmGeneratedFileStream ofs; + ofs.SetCopyIfDifferent(true); + ofs.Open(this->AutogenTarget.InfoFile, false, true); + if (ofs) { + // Utility lambdas + auto CWrite = [&ofs](const char* key, std::string const& value) { + ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) + << ")\n"; + }; + auto CWriteUInt = [&ofs](const char* key, unsigned int value) { + ofs << "set(" << key << " " << value << ")\n"; + }; + auto CWriteList = [&CWrite](const char* key, + std::vector<std::string> const& list) { + CWrite(key, cmJoin(list, ";")); + }; + auto CWriteNestedLists = + [&CWrite](const char* key, + std::vector<std::vector<std::string>> const& lists) { + std::vector<std::string> seplist; + for (const std::vector<std::string>& list : lists) { + std::string blist = "{"; + blist += cmJoin(list, ";"); + blist += "}"; + seplist.push_back(std::move(blist)); + } + CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep)); + }; + auto CWriteSet = [&CWrite](const char* key, + std::set<std::string> const& list) { + CWrite(key, cmJoin(list, ";")); + }; + auto CWriteMap = [&ofs](const char* key, + std::map<std::string, std::string> const& map) { + for (auto const& item : map) { + ofs << "set(" << key << "_" << item.first << " " + << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; + } + }; + auto MfDef = [makefile](const char* key) { + return makefile->GetSafeDefinition(key); + }; + + // Write + ofs << "# Meta\n"; + CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); + CWrite("AM_PARALLEL", this->AutogenTarget.Parallel); + CWrite("AM_VERBOSITY", this->Verbosity); + + ofs << "# Directories\n"; + CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR")); + CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR")); + CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR")); + CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR")); + CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE", + MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")); + CWrite("AM_BUILD_DIR", this->Dir.Build); + CWrite("AM_INCLUDE_DIR", this->Dir.Include); + CWriteMap("AM_INCLUDE_DIR", this->Dir.ConfigInclude); + + ofs << "# Files\n"; + CWriteList("AM_SOURCES", this->AutogenTarget.Sources); + CWriteList("AM_HEADERS", this->AutogenTarget.Headers); + CWrite("AM_SETTINGS_FILE", this->AutogenTarget.SettingsFile); + CWriteMap("AM_SETTINGS_FILE", this->AutogenTarget.ConfigSettingsFile); + + ofs << "# Qt\n"; + CWriteUInt("AM_QT_VERSION_MAJOR", this->QtVersion.Major); + CWrite("AM_QT_MOC_EXECUTABLE", this->Moc.Executable); + CWrite("AM_QT_UIC_EXECUTABLE", this->Uic.Executable); + + if (this->Moc.Enabled) { + ofs << "# MOC settings\n"; + CWriteSet("AM_MOC_SKIP", this->Moc.Skip); + CWrite("AM_MOC_DEFINITIONS", this->Moc.Defines); + CWriteMap("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines); + CWrite("AM_MOC_INCLUDES", this->Moc.Includes); + CWriteMap("AM_MOC_INCLUDES", this->Moc.ConfigIncludes); + CWrite("AM_MOC_OPTIONS", + this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS")); + CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE")); + CWrite("AM_MOC_MACRO_NAMES", + this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES")); + CWrite("AM_MOC_DEPEND_FILTERS", + this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS")); + CWrite("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd); } - // Parallel processing - this->Parallel = GetSafeProperty(this->Target, "AUTOGEN_PARALLEL"); - if (this->Parallel.empty() || (this->Parallel == "AUTO")) { - // Autodetect number of CPUs - this->Parallel = std::to_string(GetParallelCPUCount()); + if (this->Uic.Enabled) { + ofs << "# UIC settings\n"; + CWriteSet("AM_UIC_SKIP", this->Uic.Skip); + CWrite("AM_UIC_TARGET_OPTIONS", this->Uic.Options); + CWriteMap("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions); + CWriteList("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles); + CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions); + CWriteList("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths); } + } else { + std::string err = "AutoGen: Could not write file "; + err += this->AutogenTarget.InfoFile; + cmSystemTools::Error(err.c_str()); + return false; + } + + return true; +} +bool cmQtAutoGenInitializer::SetupWriteRccInfo() +{ + for (Qrc const& qrc : this->Rcc.Qrcs) { cmGeneratedFileStream ofs; ofs.SetCopyIfDifferent(true); - ofs.Open(this->AutogenInfoFile.c_str(), false, true); + ofs.Open(qrc.InfoFile, false, true); if (ofs) { // Utility lambdas auto CWrite = [&ofs](const char* key, std::string const& value) { ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) << ")\n"; }; - auto CWriteList = [&CWrite](const char* key, - std::vector<std::string> const& list) { - CWrite(key, cmJoin(list, ";")); - }; - auto CWriteNestedLists = - [&CWrite](const char* key, - std::vector<std::vector<std::string>> const& lists) { - std::vector<std::string> seplist; - for (const std::vector<std::string>& list : lists) { - std::string blist = "{"; - blist += cmJoin(list, ";"); - blist += "}"; - seplist.push_back(std::move(blist)); - } - CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep)); - }; - auto CWriteSet = [&CWrite](const char* key, - std::set<std::string> const& list) { - CWrite(key, cmJoin(list, ";")); - }; auto CWriteMap = [&ofs](const char* key, std::map<std::string, std::string> const& map) { for (auto const& item : map) { @@ -936,401 +1212,306 @@ void cmQtAutoGenInitializer::SetupCustomTargets() << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; } }; - auto MfDef = [makefile](const char* key) { - return std::string(makefile->GetSafeDefinition(key)); - }; // Write - ofs << "# Meta\n"; - CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); - CWrite("AM_PARALLEL", this->Parallel); + ofs << "# Configurations\n"; + CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); + CWrite("ARCC_VERBOSITY", this->Verbosity); + ofs << "# Settings file\n"; + CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile); + CWriteMap("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile); ofs << "# Directories\n"; - CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR")); - CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR")); - CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR")); - CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR")); - CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE", - MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")); - CWrite("AM_BUILD_DIR", this->DirBuild); - if (this->MultiConfig) { - CWriteMap("AM_INCLUDE_DIR", includeDirs); - } else { - CWrite("AM_INCLUDE_DIR", includeDir); - } - - ofs << "# Files\n"; - CWriteList("AM_SOURCES", this->Sources); - CWriteList("AM_HEADERS", this->Headers); - if (this->MultiConfig) { - std::map<std::string, std::string> settingsFiles; - for (std::string const& cfg : this->ConfigsList) { - settingsFiles[cfg] = - AppendFilenameSuffix(this->AutogenSettingsFile, "_" + cfg); - } - CWriteMap("AM_SETTINGS_FILE", settingsFiles); - } else { - CWrite("AM_SETTINGS_FILE", this->AutogenSettingsFile); - } - - ofs << "# Qt\n"; - CWrite("AM_QT_VERSION_MAJOR", this->QtVersionMajor); - CWrite("AM_QT_MOC_EXECUTABLE", this->MocExecutable); - CWrite("AM_QT_UIC_EXECUTABLE", this->UicExecutable); - - if (this->MocEnabled) { - ofs << "# MOC settings\n"; - CWriteSet("AM_MOC_SKIP", this->MocSkip); - CWrite("AM_MOC_DEFINITIONS", this->MocDefines); - CWriteMap("AM_MOC_DEFINITIONS", this->MocDefinesConfig); - CWrite("AM_MOC_INCLUDES", this->MocIncludes); - CWriteMap("AM_MOC_INCLUDES", this->MocIncludesConfig); - CWrite("AM_MOC_OPTIONS", - GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS")); - CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE")); - CWrite("AM_MOC_MACRO_NAMES", - GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES")); - CWrite("AM_MOC_DEPEND_FILTERS", - GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS")); - CWrite("AM_MOC_PREDEFS_CMD", this->MocPredefsCmd); - } - - if (this->UicEnabled) { - ofs << "# UIC settings\n"; - CWriteSet("AM_UIC_SKIP", this->UicSkip); - CWrite("AM_UIC_TARGET_OPTIONS", this->UicOptions); - CWriteMap("AM_UIC_TARGET_OPTIONS", this->UicOptionsConfig); - CWriteList("AM_UIC_OPTIONS_FILES", this->UicFileFiles); - CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->UicFileOptions); - CWriteList("AM_UIC_SEARCH_PATHS", this->UicSearchPaths); - } + CWrite("ARCC_BUILD_DIR", this->Dir.Build); + CWrite("ARCC_INCLUDE_DIR", this->Dir.Include); + CWriteMap("ARCC_INCLUDE_DIR", this->Dir.ConfigInclude); + + ofs << "# Rcc executable\n"; + CWrite("ARCC_RCC_EXECUTABLE", this->Rcc.Executable); + CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->Rcc.ListOptions, ";")); + + ofs << "# Rcc job\n"; + CWrite("ARCC_LOCK_FILE", qrc.LockFile); + CWrite("ARCC_SOURCE", qrc.QrcFile); + CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum); + CWrite("ARCC_OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.RccFile)); + CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";")); + CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";")); } else { - return; + std::string err = "AutoRcc: Could not write file "; + err += qrc.InfoFile; + cmSystemTools::Error(err.c_str()); + return false; } } - // Generate auto RCC info files - if (this->RccEnabled) { - for (Qrc const& qrc : this->Qrcs) { - // Register rcc info file as generated - makefile->AddCMakeOutputFile(qrc.InfoFile); - - cmGeneratedFileStream ofs; - ofs.SetCopyIfDifferent(true); - ofs.Open(qrc.InfoFile.c_str(), false, true); - if (ofs) { - // Utility lambdas - auto CWrite = [&ofs](const char* key, std::string const& value) { - ofs << "set(" << key << " " - << cmOutputConverter::EscapeForCMake(value) << ")\n"; - }; - auto CWriteMap = - [&ofs](const char* key, - std::map<std::string, std::string> const& map) { - for (auto const& item : map) { - ofs << "set(" << key << "_" << item.first << " " - << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; - } - }; - - // Write - ofs << "# Configurations\n"; - CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); - - ofs << "# Settings file\n"; - if (this->MultiConfig) { - std::map<std::string, std::string> settingsFiles; - for (std::string const& cfg : this->ConfigsList) { - settingsFiles[cfg] = - AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg); - } - CWriteMap("ARCC_SETTINGS_FILE", settingsFiles); - } else { - CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile); - } - - ofs << "# Directories\n"; - CWrite("ARCC_BUILD_DIR", this->DirBuild); - if (this->MultiConfig) { - CWriteMap("ARCC_INCLUDE_DIR", includeDirs); - } else { - CWrite("ARCC_INCLUDE_DIR", includeDir); - } + return true; +} - ofs << "# Rcc executable\n"; - CWrite("ARCC_RCC_EXECUTABLE", this->RccExecutable); - CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->RccListOptions, ";")); - - ofs << "# Rcc job\n"; - CWrite("ARCC_LOCK_FILE", qrc.LockFile); - CWrite("ARCC_SOURCE", qrc.QrcFile); - CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum); - CWrite("ARCC_OUTPUT_NAME", - cmSystemTools::GetFilenameName(qrc.RccFile)); - CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";")); - CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";")); - } else { - return; - } - } +void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename, + GeneratorT genType) +{ + // Register source file in makefile + cmMakefile* makefile = this->Target->Target->GetMakefile(); + { + cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true); + gFile->SetProperty("GENERATED", "1"); + gFile->SetProperty("SKIP_AUTOGEN", "On"); } + + // Add source file to source group + AddToSourceGroup(makefile, filename, genType); + + // Add source file to target + this->Target->AddSource(filename); } -void cmQtAutoGenInitializer::SetupCustomTargetsMoc() +cmQtAutoGenInitializer::IntegerVersion cmQtAutoGenInitializer::GetQtVersion( + cmGeneratorTarget const* target) { - cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); - cmMakefile* makefile = this->Target->Target->GetMakefile(); + cmQtAutoGenInitializer::IntegerVersion res; + cmMakefile* makefile = target->Target->GetMakefile(); - // Moc predefs command - if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && - this->QtVersionGreaterOrEqual(5, 8)) { - this->MocPredefsCmd = - makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"); + // -- Major version + std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); + if (qtMajor.empty()) { + qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); } - - // Moc includes and compile definitions { - auto GetIncludeDirs = [this, - localGen](std::string const& cfg) -> std::string { - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see - // https://gitlab.kitware.com/cmake/cmake/issues/13667 - std::vector<std::string> includeDirs; - localGen->GetIncludeDirectories(includeDirs, this->Target, "CXX", cfg, - false); - return cmJoin(includeDirs, ";"); - }; - auto GetCompileDefinitions = - [this, localGen](std::string const& cfg) -> std::string { - std::set<std::string> defines; - localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX"); - return cmJoin(defines, ";"); - }; - - // Default configuration settings - this->MocIncludes = GetIncludeDirs(this->ConfigDefault); - this->MocDefines = GetCompileDefinitions(this->ConfigDefault); - // Other configuration settings - for (std::string const& cfg : this->ConfigsList) { - { - std::string const configIncludeDirs = GetIncludeDirs(cfg); - if (configIncludeDirs != this->MocIncludes) { - this->MocIncludesConfig[cfg] = configIncludeDirs; - } - } - { - std::string const configCompileDefs = GetCompileDefinitions(cfg); - if (configCompileDefs != this->MocDefines) { - this->MocDefinesConfig[cfg] = configCompileDefs; - } - } + const char* targetQtVersion = + target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""); + if (targetQtVersion != nullptr) { + qtMajor = targetQtVersion; } } - // Moc executable - { - std::string mocExec; - std::string err; - - if (this->QtVersionMajor == "5") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc"); - if (tgt != nullptr) { - mocExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOMOC: Qt5::moc target not found"; - } - } else if (this->QtVersionMajor == "4") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc"); - if (tgt != nullptr) { - mocExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOMOC: Qt4::moc target not found"; + // -- Minor version + std::string qtMinor; + if (!qtMajor.empty()) { + if (qtMajor == "5") { + qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR"); + } + if (qtMinor.empty()) { + qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR"); + } + { + const char* targetQtVersion = + target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", + ""); + if (targetQtVersion != nullptr) { + qtMinor = targetQtVersion; } - } else { - err = "The AUTOMOC feature supports only Qt 4 and Qt 5"; } + } - if (err.empty()) { - this->MocExecutable = mocExec; - } else { - err += " ("; - err += this->Target->GetName(); - err += ")"; - cmSystemTools::Error(err.c_str()); + // -- Convert to integer + if (!qtMajor.empty() && !qtMinor.empty()) { + unsigned long majorUL(0); + unsigned long minorUL(0); + if (cmSystemTools::StringToULong(qtMajor.c_str(), &majorUL) && + cmSystemTools::StringToULong(qtMinor.c_str(), &minorUL)) { + res.Major = static_cast<unsigned int>(majorUL); + res.Minor = static_cast<unsigned int>(minorUL); } } + + return res; } -void cmQtAutoGenInitializer::SetupCustomTargetsUic() +bool cmQtAutoGenInitializer::GetMocExecutable() { - cmMakefile* makefile = this->Target->Target->GetMakefile(); + std::string err; - // Uic search paths + // Find moc executable { - std::string const usp = - GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS"); - if (!usp.empty()) { - cmSystemTools::ExpandListArgument(usp, this->UicSearchPaths); - std::string const srcDir = makefile->GetCurrentSourceDirectory(); - for (std::string& path : this->UicSearchPaths) { - path = cmSystemTools::CollapseFullPath(path, srcDir); + std::string targetName; + if (this->QtVersion.Major == 5) { + targetName = "Qt5::moc"; + } else if (this->QtVersion.Major == 4) { + targetName = "Qt4::moc"; + } else { + err = "The AUTOMOC feature supports only Qt 4 and Qt 5"; + } + if (!targetName.empty()) { + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName); + if (tgt != nullptr) { + this->Moc.Executable = tgt->ImportedGetLocation(""); + } else { + err = "Could not find target " + targetName; } } } - // Uic target options - { - auto UicGetOpts = [this](std::string const& cfg) -> std::string { - std::vector<std::string> opts; - this->Target->GetAutoUicOptions(opts, cfg); - return cmJoin(opts, ";"); - }; - // Default settings - this->UicOptions = UicGetOpts(this->ConfigDefault); - - // Configuration specific settings - for (std::string const& cfg : this->ConfigsList) { - std::string const configUicOpts = UicGetOpts(cfg); - if (configUicOpts != this->UicOptions) { - this->UicOptionsConfig[cfg] = configUicOpts; + // Test moc command + if (err.empty()) { + if (cmSystemTools::FileExists(this->Moc.Executable, true)) { + std::vector<std::string> command; + command.push_back(this->Moc.Executable); + command.push_back("-h"); + std::string stdOut; + std::string stdErr; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand( + command, &stdOut, &stdErr, &retVal, nullptr, + cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); + if (!result) { + err = "The moc test command failed: "; + err += QuotedCommand(command); } + } else { + err = "The moc executable "; + err += Quoted(this->Moc.Executable); + err += " does not exist"; } } - // .ui files skip and options - { - std::string const uiExt = "ui"; - std::string pathError; - for (cmSourceFile* sf : makefile->GetSourceFiles()) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - // Since we're iterating over source files that might be not in the - // target we need to check for path errors (not existing files). - std::string const& fPath = sf->GetFullPath(&pathError); - if (!pathError.empty()) { - pathError.clear(); - continue; - } - if (sf->GetExtension() == uiExt) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - // Check if the .ui file should be skipped - if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || - sf->GetPropertyAsBool("SKIP_AUTOGEN")) { - this->UicSkip.insert(absFile); - } - // Check if the .ui file has uic options - std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS"); - if (!uicOpts.empty()) { - // Check if file isn't skipped - if (this->UicSkip.count(absFile) == 0) { - this->UicFileFiles.push_back(absFile); - std::vector<std::string> optsVec; - cmSystemTools::ExpandListArgument(uicOpts, optsVec); - this->UicFileOptions.push_back(std::move(optsVec)); - } - } - } - } + + // Print error + if (!err.empty()) { + std::string msg = "AutoMoc ("; + msg += this->Target->GetName(); + msg += "): "; + msg += err; + cmSystemTools::Error(msg.c_str()); + return false; } - // Uic executable - { - std::string err; - std::string uicExec; + return true; +} - cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); - if (this->QtVersionMajor == "5") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic"); - if (tgt != nullptr) { - uicExec = SafeString(tgt->ImportedGetLocation("")); - } else { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway - } - } else if (this->QtVersionMajor == "4") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic"); +bool cmQtAutoGenInitializer::GetUicExecutable() +{ + std::string err; + + // Find uic executable + { + std::string targetName; + if (this->QtVersion.Major == 5) { + targetName = "Qt5::uic"; + } else if (this->QtVersion.Major == 4) { + targetName = "Qt4::uic"; + } else { + err = "The AUTOUIC feature supports only Qt 4 and Qt 5"; + } + if (!targetName.empty()) { + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName); if (tgt != nullptr) { - uicExec = SafeString(tgt->ImportedGetLocation("")); + this->Uic.Executable = tgt->ImportedGetLocation(""); } else { - err = "AUTOUIC: Qt4::uic target not found"; + if (this->QtVersion.Major == 5) { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } else { + err = "Could not find target " + targetName; + } } - } else { - err = "The AUTOUIC feature supports only Qt 4 and Qt 5"; } + } - if (err.empty()) { - this->UicExecutable = uicExec; + // Test uic command + if (err.empty()) { + if (cmSystemTools::FileExists(this->Uic.Executable, true)) { + std::vector<std::string> command; + command.push_back(this->Uic.Executable); + command.push_back("-h"); + std::string stdOut; + std::string stdErr; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand( + command, &stdOut, &stdErr, &retVal, nullptr, + cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); + if (!result) { + err = "The uic test command failed: "; + err += QuotedCommand(command); + } } else { - err += " ("; - err += this->Target->GetName(); - err += ")"; - cmSystemTools::Error(err.c_str()); + err = "The uic executable "; + err += Quoted(this->Uic.Executable); + err += " does not exist"; } } -} -void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename, - GeneratorT genType) -{ - // Register source file in makefile - cmMakefile* makefile = this->Target->Target->GetMakefile(); - { - cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true); - gFile->SetProperty("GENERATED", "1"); - gFile->SetProperty("SKIP_AUTOGEN", "On"); + // Print error + if (!err.empty()) { + std::string msg = "AutoUic ("; + msg += this->Target->GetName(); + msg += "): "; + msg += err; + cmSystemTools::Error(msg.c_str()); + return false; } - // Add source file to source group - AddToSourceGroup(makefile, filename, genType); - - // Add source file to target - this->Target->AddSource(filename); + return true; } -std::string cmQtAutoGenInitializer::GetQtMajorVersion( - cmGeneratorTarget const* target) +bool cmQtAutoGenInitializer::GetRccExecutable() { - cmMakefile* makefile = target->Target->GetMakefile(); - std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); - if (qtMajor.empty()) { - qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); - } - const char* targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""); - if (targetQtVersion != nullptr) { - qtMajor = targetQtVersion; - } - return qtMajor; -} + std::string err; -std::string cmQtAutoGenInitializer::GetQtMinorVersion( - cmGeneratorTarget const* target, std::string const& qtVersionMajor) -{ - cmMakefile* makefile = target->Target->GetMakefile(); - std::string qtMinor; - if (qtVersionMajor == "5") { - qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR"); - } - if (qtMinor.empty()) { - qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR"); + // Find rcc executable + { + std::string targetName; + if (this->QtVersion.Major == 5) { + targetName = "Qt5::rcc"; + } else if (this->QtVersion.Major == 4) { + targetName = "Qt4::rcc"; + } else { + err = "The AUTORCC feature supports only Qt 4 and Qt 5"; + } + if (!targetName.empty()) { + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName); + if (tgt != nullptr) { + this->Rcc.Executable = tgt->ImportedGetLocation(""); + } else { + err = "Could not find target " + targetName; + } + } } - const char* targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", ""); - if (targetQtVersion != nullptr) { - qtMinor = targetQtVersion; + // Test rcc command + if (err.empty()) { + if (cmSystemTools::FileExists(this->Rcc.Executable, true)) { + std::vector<std::string> command; + command.push_back(this->Rcc.Executable); + command.push_back("-h"); + std::string stdOut; + std::string stdErr; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand( + command, &stdOut, &stdErr, &retVal, nullptr, + cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); + if (result) { + // Detect if rcc supports (-)-list + if (this->QtVersion.Major == 5) { + if (stdOut.find("--list") != std::string::npos) { + this->Rcc.ListOptions.push_back("--list"); + } else { + this->Rcc.ListOptions.push_back("-list"); + } + } + } else { + err = "The rcc test command failed: "; + err += QuotedCommand(command); + } + } else { + err = "The rcc executable "; + err += Quoted(this->Rcc.Executable); + err += " does not exist"; + } } - return qtMinor; -} -bool cmQtAutoGenInitializer::QtVersionGreaterOrEqual( - unsigned long requestMajor, unsigned long requestMinor) const -{ - unsigned long majorUL(0); - unsigned long minorUL(0); - if (cmSystemTools::StringToULong(this->QtVersionMajor.c_str(), &majorUL) && - cmSystemTools::StringToULong(this->QtVersionMinor.c_str(), &minorUL)) { - return (majorUL > requestMajor) || - (majorUL == requestMajor && minorUL >= requestMinor); + // Print error + if (!err.empty()) { + std::string msg = "AutoRcc ("; + msg += this->Target->GetName(); + msg += "): "; + msg += err; + cmSystemTools::Error(msg.c_str()); + return false; } - return false; + + return true; } /// @brief Reads the resource files list from from a .qrc file @@ -1346,9 +1527,9 @@ bool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName, error += "\n"; return false; } - if (!RccListOptions.empty()) { + if (!this->Rcc.ListOptions.empty()) { // Use rcc for file listing - if (RccExecutable.empty()) { + if (this->Rcc.Executable.empty()) { error = "rcc executable not available"; return false; } @@ -1367,8 +1548,9 @@ bool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName, std::string rccStdErr; { std::vector<std::string> cmd; - cmd.push_back(RccExecutable); - cmd.insert(cmd.end(), RccListOptions.begin(), RccListOptions.end()); + cmd.push_back(this->Rcc.Executable); + cmd.insert(cmd.end(), this->Rcc.ListOptions.begin(), + this->Rcc.ListOptions.end()); cmd.push_back(fileNameName); result = cmSystemTools::RunSingleCommand( cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(), diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 5fbf0cbdc..ce00e00fe 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -12,15 +12,12 @@ #include <vector> class cmGeneratorTarget; +class cmTarget; /// @brief Initializes the QtAutoGen generators class cmQtAutoGenInitializer : public cmQtAutoGen { public: - static std::string GetQtMajorVersion(cmGeneratorTarget const* target); - static std::string GetQtMinorVersion(cmGeneratorTarget const* target, - std::string const& qtVersionMajor); - /// @brief Rcc job information class Qrc { @@ -38,6 +35,7 @@ public: std::string PathChecksum; std::string InfoFile; std::string SettingsFile; + std::map<std::string, std::string> ConfigSettingsFile; std::string RccFile; bool Generated; bool Unique; @@ -46,21 +44,32 @@ public: }; public: + static IntegerVersion GetQtVersion(cmGeneratorTarget const* target); + cmQtAutoGenInitializer(cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled, - std::string const& qtVersionMajor); + IntegerVersion const& qtVersion); - void InitCustomTargets(); - void SetupCustomTargets(); + bool InitCustomTargets(); + bool SetupCustomTargets(); private: - void SetupCustomTargetsMoc(); - void SetupCustomTargetsUic(); + bool InitMoc(); + bool InitUic(); + bool InitRcc(); + + bool InitScanFiles(); + bool InitAutogenTarget(); + bool InitRccTargets(); + + bool SetupWriteAutogenInfo(); + bool SetupWriteRccInfo(); void AddGeneratedSource(std::string const& filename, GeneratorT genType); - bool QtVersionGreaterOrEqual(unsigned long requestMajor, - unsigned long requestMinor) const; + bool GetMocExecutable(); + bool GetUicExecutable(); + bool GetRccExecutable(); bool RccListInputs(std::string const& fileName, std::vector<std::string>& files, @@ -68,49 +77,80 @@ private: private: cmGeneratorTarget* Target; - bool MocEnabled; - bool UicEnabled; - bool RccEnabled; - bool MultiConfig; - // Qt - std::string QtVersionMajor; - std::string QtVersionMinor; - std::string MocExecutable; - std::string UicExecutable; - std::string RccExecutable; - std::vector<std::string> RccListOptions; - // Configurations + + // Configuration + IntegerVersion QtVersion; + bool MultiConfig = false; std::string ConfigDefault; std::vector<std::string> ConfigsList; - std::string Parallel; - // Names - std::string AutogenTargetName; - std::string AutogenFolder; - std::string AutogenInfoFile; - std::string AutogenSettingsFile; - // Directories - std::string DirInfo; - std::string DirBuild; - std::string DirWork; - // Sources - std::vector<std::string> Headers; - std::vector<std::string> Sources; - // Moc - std::string MocPredefsCmd; - std::set<std::string> MocSkip; - std::string MocIncludes; - std::map<std::string, std::string> MocIncludesConfig; - std::string MocDefines; - std::map<std::string, std::string> MocDefinesConfig; - // Uic - std::set<std::string> UicSkip; - std::vector<std::string> UicSearchPaths; - std::string UicOptions; - std::map<std::string, std::string> UicOptionsConfig; - std::vector<std::string> UicFileFiles; - std::vector<std::vector<std::string>> UicFileOptions; - // Rcc - std::vector<Qrc> Qrcs; + std::string Verbosity; + std::string TargetsFolder; + + /// @brief Common directories + struct + { + std::string Info; + std::string Build; + std::string Work; + std::string Include; + std::map<std::string, std::string> ConfigInclude; + } Dir; + + /// @brief Autogen target variables + struct + { + std::string Name; + // Settings + std::string Parallel; + // Configuration files + std::string InfoFile; + std::string SettingsFile; + std::map<std::string, std::string> ConfigSettingsFile; + // Dependencies + std::set<std::string> DependFiles; + std::set<cmTarget*> DependTargets; + // Sources to process + std::vector<std::string> Headers; + std::vector<std::string> Sources; + std::vector<std::string> HeadersGenerated; + std::vector<std::string> SourcesGenerated; + } AutogenTarget; + + /// @brief Moc only variables + struct + { + bool Enabled = false; + std::string Executable; + std::string PredefsCmd; + std::set<std::string> Skip; + std::string Includes; + std::map<std::string, std::string> ConfigIncludes; + std::string Defines; + std::map<std::string, std::string> ConfigDefines; + std::string MocsCompilation; + } Moc; + + ///@brief Uic only variables + struct + { + bool Enabled = false; + std::string Executable; + std::set<std::string> Skip; + std::vector<std::string> SearchPaths; + std::string Options; + std::map<std::string, std::string> ConfigOptions; + std::vector<std::string> FileFiles; + std::vector<std::vector<std::string>> FileOptions; + } Uic; + + /// @brief Rcc only variables + struct + { + bool Enabled = false; + std::string Executable; + std::vector<std::string> ListOptions; + std::vector<Qrc> Qrcs; + } Rcc; }; #endif diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 7aa792f8a..734b2d70d 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -17,9 +17,14 @@ // -- Class methods -void cmQtAutoGenerator::Logger::SetVerbose(bool value) +void cmQtAutoGenerator::Logger::RaiseVerbosity(std::string const& value) { - Verbose_ = value; + unsigned long verbosity = 0; + if (cmSystemTools::StringToULong(value.c_str(), &verbosity)) { + if (this->Verbosity_ < verbosity) { + this->Verbosity_ = static_cast<unsigned int>(verbosity); + } + } } void cmQtAutoGenerator::Logger::SetColorOutput(bool value) @@ -632,12 +637,23 @@ cmQtAutoGenerator::cmQtAutoGenerator() : FileSys_(&Logger_) { // Initialize logger - Logger_.SetVerbose(cmSystemTools::HasEnv("VERBOSE")); + { + std::string verbose; + if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) { + unsigned long iVerbose = 0; + if (cmSystemTools::StringToULong(verbose.c_str(), &iVerbose)) { + Logger_.SetVerbosity(static_cast<unsigned int>(iVerbose)); + } else { + // Non numeric verbosity + Logger_.SetVerbose(cmSystemTools::IsOn(verbose)); + } + } + } { std::string colorEnv; cmSystemTools::GetEnv("COLOR", colorEnv); if (!colorEnv.empty()) { - Logger_.SetColorOutput(cmSystemTools::IsOn(colorEnv.c_str())); + Logger_.SetColorOutput(cmSystemTools::IsOn(colorEnv)); } else { Logger_.SetColorOutput(true); } diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index 4e3841306..75143f5a6 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -33,8 +33,11 @@ public: { public: // -- Verbosity - bool Verbose() const { return this->Verbose_; } - void SetVerbose(bool value); + unsigned int Verbosity() const { return this->Verbosity_; } + void SetVerbosity(unsigned int value) { this->Verbosity_ = value; } + void RaiseVerbosity(std::string const& value); + bool Verbose() const { return (this->Verbosity_ != 0); } + void SetVerbose(bool value) { this->Verbosity_ = value ? 1 : 0; } bool ColorOutput() const { return this->ColorOutput_; } void SetColorOutput(bool value); // -- Log info @@ -56,8 +59,8 @@ public: private: std::mutex Mutex_; - bool volatile Verbose_ = false; - bool volatile ColorOutput_ = false; + unsigned int Verbosity_ = 0; + bool ColorOutput_ = false; }; /// @brief Thread safe file system interface diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index f196b97b9..2e6f90f7c 100644 --- a/Source/cmQtAutoGeneratorMocUic.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -1204,7 +1204,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) valueConf = makefile->GetDefinition(keyConf); } if (valueConf == nullptr) { - valueConf = makefile->GetSafeDefinition(key); + return makefile->GetSafeDefinition(key); } return std::string(valueConf); }; @@ -1222,10 +1222,11 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) } // -- Meta + Log().RaiseVerbosity(InfoGet("AM_VERBOSITY")); Base_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG"); { unsigned long num = Base_.NumThreads; - if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL"), &num)) { + if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL").c_str(), &num)) { num = std::max<unsigned long>(num, 1); num = std::min<unsigned long>(num, ParallelMax); Base_.NumThreads = static_cast<unsigned int>(num); @@ -1246,14 +1247,11 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) return false; } // include directory - { - std::string dirRel = InfoGetConfig("AM_INCLUDE_DIR"); - if (dirRel.empty()) { - Log().ErrorFile(GeneratorT::GEN, InfoFile(), - "Autogen include directory missing"); - return false; - } - Base_.AutogenIncludeDir = Base_.AbsoluteBuildPath(dirRel); + Base_.AutogenIncludeDir = InfoGetConfig("AM_INCLUDE_DIR"); + if (Base_.AutogenIncludeDir.empty()) { + Log().ErrorFile(GeneratorT::GEN, InfoFile(), + "Autogen include directory missing"); + return false; } // - Files @@ -1266,7 +1264,8 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) // - Qt environment { unsigned long qtv = Base_.QtVersionMajor; - if (cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR"), &qtv)) { + if (cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR").c_str(), + &qtv)) { Base_.QtVersionMajor = static_cast<unsigned int>(qtv); } } diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx index 3064895d7..65c674110 100644 --- a/Source/cmQtAutoGeneratorRcc.cxx +++ b/Source/cmQtAutoGeneratorRcc.cxx @@ -52,7 +52,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile) valueConf = makefile->GetDefinition(keyConf); } if (valueConf == nullptr) { - valueConf = makefile->GetSafeDefinition(key); + return makefile->GetSafeDefinition(key); } return std::string(valueConf); }; @@ -70,6 +70,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile) } // - Configurations + Log().RaiseVerbosity(InfoGet("ARCC_VERBOSITY")); MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG"); // - Directories @@ -140,9 +141,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile) // Compute rcc output file name if (IsMultiConfig()) { - RccFileOutput_ = AutogenBuildDir_; - RccFileOutput_ += '/'; - RccFileOutput_ += IncludeDir_; + RccFileOutput_ = IncludeDir_; RccFileOutput_ += '/'; RccFileOutput_ += MultiConfigOutput(); } else { diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx index 12817ae4b..32ad0b080 100644 --- a/Source/cmRST.cxx +++ b/Source/cmRST.cxx @@ -34,7 +34,7 @@ cmRST::cmRST(std::ostream& os, std::string const& docroot) , NoteDirective("^.. note::[ \t]*(.*)$") , ModuleRST("^#\\[(=*)\\[\\.rst:$") , CMakeRole("(:cmake)?:(" - "command|generator|variable|envvar|module|policy|" + "command|cpack_gen|generator|variable|envvar|module|policy|" "prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|" "prop_test|prop_tgt|" "manual" diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index 5b2986880..5dd4413c4 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -69,7 +69,8 @@ void cmSearchPath::AddUserPath(const std::string& path) // Process them all from the current directory for (std::string const& p : outPaths) { - this->AddPathInternal(p, this->FC->Makefile->GetCurrentSourceDirectory()); + this->AddPathInternal( + p, this->FC->Makefile->GetCurrentSourceDirectory().c_str()); } } @@ -83,8 +84,8 @@ void cmSearchPath::AddCMakePath(const std::string& variable) cmSystemTools::ExpandListArgument(value, expanded); for (std::string const& p : expanded) { - this->AddPathInternal(p, - this->FC->Makefile->GetCurrentSourceDirectory()); + this->AddPathInternal( + p, this->FC->Makefile->GetCurrentSourceDirectory().c_str()); } } } @@ -107,8 +108,8 @@ void cmSearchPath::AddCMakePrefixPath(const std::string& variable) std::vector<std::string> expanded; cmSystemTools::ExpandListArgument(value, expanded); - this->AddPrefixPaths(expanded, - this->FC->Makefile->GetCurrentSourceDirectory()); + this->AddPrefixPaths( + expanded, this->FC->Makefile->GetCurrentSourceDirectory().c_str()); } } diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index 1b04ca287..f15a14a4c 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -5,6 +5,7 @@ #include "cmAlgorithms.h" #include "cmConnection.h" #include "cmFileMonitor.h" +#include "cmJsonObjectDictionary.h" #include "cmServerDictionary.h" #include "cmServerProtocol.h" #include "cmSystemTools.h" diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h index 685542c14..961e4b7ea 100644 --- a/Source/cmServerDictionary.h +++ b/Source/cmServerDictionary.h @@ -25,77 +25,40 @@ static const std::string kSET_GLOBAL_SETTINGS_TYPE = "setGlobalSettings"; static const std::string kSIGNAL_TYPE = "signal"; static const std::string kCTEST_INFO_TYPE = "ctestInfo"; -static const std::string kARTIFACTS_KEY = "artifacts"; -static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory"; static const std::string kBUILD_FILES_KEY = "buildFiles"; static const std::string kCACHE_ARGUMENTS_KEY = "cacheArguments"; static const std::string kCACHE_KEY = "cache"; static const std::string kCAPABILITIES_KEY = "capabilities"; static const std::string kCHECK_SYSTEM_VARS_KEY = "checkSystemVars"; static const std::string kCMAKE_ROOT_DIRECTORY_KEY = "cmakeRootDirectory"; -static const std::string kCOMPILE_FLAGS_KEY = "compileFlags"; -static const std::string kCONFIGURATIONS_KEY = "configurations"; static const std::string kCOOKIE_KEY = "cookie"; static const std::string kDEBUG_OUTPUT_KEY = "debugOutput"; -static const std::string kDEFINES_KEY = "defines"; static const std::string kERROR_MESSAGE_KEY = "errorMessage"; static const std::string kEXTRA_GENERATOR_KEY = "extraGenerator"; -static const std::string kFILE_GROUPS_KEY = "fileGroups"; -static const std::string kFRAMEWORK_PATH_KEY = "frameworkPath"; -static const std::string kFULL_NAME_KEY = "fullName"; static const std::string kGENERATOR_KEY = "generator"; -static const std::string kINCLUDE_PATH_KEY = "includePath"; -static const std::string kIS_CMAKE_KEY = "isCMake"; static const std::string kIS_EXPERIMENTAL_KEY = "isExperimental"; -static const std::string kIS_GENERATED_KEY = "isGenerated"; -static const std::string kIS_SYSTEM_KEY = "isSystem"; -static const std::string kIS_TEMPORARY_KEY = "isTemporary"; -static const std::string kKEY_KEY = "key"; static const std::string kKEYS_KEY = "keys"; -static const std::string kLANGUAGE_KEY = "language"; -static const std::string kLINKER_LANGUAGE_KEY = "linkerLanguage"; -static const std::string kLINK_FLAGS_KEY = "linkFlags"; -static const std::string kLINK_LANGUAGE_FLAGS_KEY = "linkLanguageFlags"; -static const std::string kLINK_LIBRARIES_KEY = "linkLibraries"; -static const std::string kLINK_PATH_KEY = "linkPath"; static const std::string kMAJOR_KEY = "major"; static const std::string kMESSAGE_KEY = "message"; static const std::string kMINOR_KEY = "minor"; -static const std::string kNAME_KEY = "name"; -static const std::string kPATH_KEY = "path"; static const std::string kPLATFORM_KEY = "platform"; static const std::string kPROGRESS_CURRENT_KEY = "progressCurrent"; static const std::string kPROGRESS_MAXIMUM_KEY = "progressMaximum"; static const std::string kPROGRESS_MESSAGE_KEY = "progressMessage"; static const std::string kPROGRESS_MINIMUM_KEY = "progressMinimum"; -static const std::string kPROJECTS_KEY = "projects"; -static const std::string kPROPERTIES_KEY = "properties"; static const std::string kPROTOCOL_VERSION_KEY = "protocolVersion"; static const std::string kREPLY_TO_KEY = "inReplyTo"; -static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory"; -static const std::string kSOURCES_KEY = "sources"; static const std::string kSUPPORTED_PROTOCOL_VERSIONS = "supportedProtocolVersions"; -static const std::string kSYSROOT_KEY = "sysroot"; -static const std::string kTARGETS_KEY = "targets"; static const std::string kTITLE_KEY = "title"; static const std::string kTOOLSET_KEY = "toolset"; static const std::string kTRACE_EXPAND_KEY = "traceExpand"; static const std::string kTRACE_KEY = "trace"; -static const std::string kTYPE_KEY = "type"; -static const std::string kVALUE_KEY = "value"; static const std::string kWARN_UNINITIALIZED_KEY = "warnUninitialized"; static const std::string kWARN_UNUSED_CLI_KEY = "warnUnusedCli"; static const std::string kWARN_UNUSED_KEY = "warnUnused"; static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories"; static const std::string kWATCHED_FILES_KEY = "watchedFiles"; -static const std::string kHAS_INSTALL_RULE = "hasInstallRule"; -static const std::string kINSTALL_PATHS = "installPaths"; -static const std::string kCTEST_NAME = "ctestName"; -static const std::string kCTEST_COMMAND = "ctestCommand"; -static const std::string kCTEST_INFO = "ctestInfo"; -static const std::string kMINIMUM_CMAKE_VERSION = "minimumCMakeVersion"; -static const std::string kIS_GENERATOR_PROVIDED_KEY = "isGeneratorProvided"; static const std::string kSTART_MAGIC = "[== \"CMake Server\" ==["; static const std::string kEND_MAGIC = "]== \"CMake Server\" ==]"; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index c26716013..f051fd9b1 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -5,38 +5,21 @@ #include "cmAlgorithms.h" #include "cmExternalMakefileProjectGenerator.h" #include "cmFileMonitor.h" -#include "cmGeneratorExpression.h" -#include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" -#include "cmInstallGenerator.h" -#include "cmInstallTargetGenerator.h" -#include "cmLinkLineComputer.h" -#include "cmLocalGenerator.h" -#include "cmMakefile.h" -#include "cmProperty.h" +#include "cmJsonObjectDictionary.h" +#include "cmJsonObjects.h" #include "cmServer.h" #include "cmServerDictionary.h" -#include "cmSourceFile.h" #include "cmState.h" -#include "cmStateDirectory.h" -#include "cmStateSnapshot.h" -#include "cmStateTypes.h" #include "cmSystemTools.h" -#include "cmTarget.h" -#include "cmTest.h" #include "cm_uv.h" #include "cmake.h" #include <algorithm> #include <cassert> -#include <cstddef> #include <functional> -#include <limits> -#include <map> #include <memory> -#include <set> #include <string> -#include <unordered_map> #include <vector> // Get rid of some windows macros: @@ -44,38 +27,6 @@ namespace { -std::vector<std::string> getConfigurations(const cmake* cm) -{ - std::vector<std::string> configurations; - auto makefiles = cm->GetGlobalGenerator()->GetMakefiles(); - if (makefiles.empty()) { - return configurations; - } - - makefiles[0]->GetConfigurations(configurations); - if (configurations.empty()) { - configurations.push_back(""); - } - return configurations; -} - -bool hasString(const Json::Value& v, const std::string& s) -{ - return !v.isNull() && - std::any_of(v.begin(), v.end(), - [s](const Json::Value& i) { return i.asString() == s; }); -} - -template <class T> -Json::Value fromStringList(const T& in) -{ - Json::Value result = Json::arrayValue; - for (std::string const& i : in) { - result.append(i); - } - return result; -} - std::vector<std::string> toStringList(const Json::Value& in) { std::vector<std::string> result; @@ -85,49 +36,6 @@ std::vector<std::string> toStringList(const Json::Value& in) return result; } -void getCMakeInputs(const cmGlobalGenerator* gg, const std::string& sourceDir, - const std::string& buildDir, - std::vector<std::string>* internalFiles, - std::vector<std::string>* explicitFiles, - std::vector<std::string>* tmpFiles) -{ - const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/'; - std::vector<cmMakefile*> const& makefiles = gg->GetMakefiles(); - for (cmMakefile const* mf : makefiles) { - for (std::string const& lf : mf->GetListFiles()) { - - const std::string startOfFile = lf.substr(0, cmakeRootDir.size()); - const bool isInternal = (startOfFile == cmakeRootDir); - const bool isTemporary = !isInternal && (lf.find(buildDir + '/') == 0); - - std::string toAdd = lf; - if (!sourceDir.empty()) { - const std::string& relative = - cmSystemTools::RelativePath(sourceDir, lf); - if (toAdd.size() > relative.size()) { - toAdd = relative; - } - } - - if (isInternal) { - if (internalFiles) { - internalFiles->push_back(std::move(toAdd)); - } - } else { - if (isTemporary) { - if (tmpFiles) { - tmpFiles->push_back(std::move(toAdd)); - } - } else { - if (explicitFiles) { - explicitFiles->push_back(std::move(toAdd)); - } - } - } - } - } -} - } // namespace cmServerRequest::cmServerRequest(cmServer* server, cmConnection* connection, @@ -553,568 +461,16 @@ cmServerResponse cmServerProtocol1::ProcessCMakeInputs( } const cmake* cm = this->CMakeInstance(); - const cmGlobalGenerator* gg = cm->GetGlobalGenerator(); const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot(); - const std::string& buildDir = cm->GetHomeOutputDirectory(); const std::string& sourceDir = cm->GetHomeDirectory(); Json::Value result = Json::objectValue; result[kSOURCE_DIRECTORY_KEY] = sourceDir; result[kCMAKE_ROOT_DIRECTORY_KEY] = cmakeRootDir; - - std::vector<std::string> internalFiles; - std::vector<std::string> explicitFiles; - std::vector<std::string> tmpFiles; - getCMakeInputs(gg, sourceDir, buildDir, &internalFiles, &explicitFiles, - &tmpFiles); - - Json::Value array = Json::arrayValue; - - Json::Value tmp = Json::objectValue; - tmp[kIS_CMAKE_KEY] = true; - tmp[kIS_TEMPORARY_KEY] = false; - tmp[kSOURCES_KEY] = fromStringList(internalFiles); - array.append(tmp); - - tmp = Json::objectValue; - tmp[kIS_CMAKE_KEY] = false; - tmp[kIS_TEMPORARY_KEY] = false; - tmp[kSOURCES_KEY] = fromStringList(explicitFiles); - array.append(tmp); - - tmp = Json::objectValue; - tmp[kIS_CMAKE_KEY] = false; - tmp[kIS_TEMPORARY_KEY] = true; - tmp[kSOURCES_KEY] = fromStringList(tmpFiles); - array.append(tmp); - - result[kBUILD_FILES_KEY] = array; - + result[kBUILD_FILES_KEY] = cmDumpCMakeInputs(cm); return request.Reply(result); } -class LanguageData -{ -public: - bool operator==(const LanguageData& other) const; - - void SetDefines(const std::set<std::string>& defines); - - bool IsGenerated = false; - std::string Language; - std::string Flags; - std::vector<std::string> Defines; - std::vector<std::pair<std::string, bool>> IncludePathList; -}; - -bool LanguageData::operator==(const LanguageData& other) const -{ - return Language == other.Language && Defines == other.Defines && - Flags == other.Flags && IncludePathList == other.IncludePathList && - IsGenerated == other.IsGenerated; -} - -void LanguageData::SetDefines(const std::set<std::string>& defines) -{ - std::vector<std::string> result; - result.reserve(defines.size()); - for (std::string const& i : defines) { - result.push_back(i); - } - std::sort(result.begin(), result.end()); - Defines = std::move(result); -} - -namespace std { - -template <> -struct hash<LanguageData> -{ - std::size_t operator()(const LanguageData& in) const - { - using std::hash; - size_t result = - hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags); - for (auto const& i : in.IncludePathList) { - result = result ^ - (hash<std::string>()(i.first) ^ - (i.second ? std::numeric_limits<size_t>::max() : 0)); - } - for (auto const& i : in.Defines) { - result = result ^ hash<std::string>()(i); - } - result = - result ^ (in.IsGenerated ? std::numeric_limits<size_t>::max() : 0); - return result; - } -}; - -} // namespace std - -static Json::Value DumpSourceFileGroup(const LanguageData& data, - const std::vector<std::string>& files, - const std::string& baseDir) -{ - Json::Value result = Json::objectValue; - - if (!data.Language.empty()) { - result[kLANGUAGE_KEY] = data.Language; - if (!data.Flags.empty()) { - result[kCOMPILE_FLAGS_KEY] = data.Flags; - } - if (!data.IncludePathList.empty()) { - Json::Value includes = Json::arrayValue; - for (auto const& i : data.IncludePathList) { - Json::Value tmp = Json::objectValue; - tmp[kPATH_KEY] = i.first; - if (i.second) { - tmp[kIS_SYSTEM_KEY] = i.second; - } - includes.append(tmp); - } - result[kINCLUDE_PATH_KEY] = includes; - } - if (!data.Defines.empty()) { - result[kDEFINES_KEY] = fromStringList(data.Defines); - } - } - - result[kIS_GENERATED_KEY] = data.IsGenerated; - - Json::Value sourcesValue = Json::arrayValue; - for (auto const& i : files) { - const std::string relPath = cmSystemTools::RelativePath(baseDir, i); - sourcesValue.append(relPath.size() < i.size() ? relPath : i); - } - - result[kSOURCES_KEY] = sourcesValue; - return result; -} - -static Json::Value DumpSourceFilesList( - cmGeneratorTarget* target, const std::string& config, - const std::map<std::string, LanguageData>& languageDataMap) -{ - // Collect sourcefile groups: - - std::vector<cmSourceFile*> files; - target->GetSourceFiles(files, config); - - std::unordered_map<LanguageData, std::vector<std::string>> fileGroups; - for (cmSourceFile* file : files) { - LanguageData fileData; - fileData.Language = file->GetLanguage(); - if (!fileData.Language.empty()) { - const LanguageData& ld = languageDataMap.at(fileData.Language); - cmLocalGenerator* lg = target->GetLocalGenerator(); - cmGeneratorExpressionInterpreter genexInterpreter( - lg, target, config, target->GetName(), fileData.Language); - - std::string compileFlags = ld.Flags; - const std::string COMPILE_FLAGS("COMPILE_FLAGS"); - if (const char* cflags = file->GetProperty(COMPILE_FLAGS)) { - lg->AppendFlags(compileFlags, - genexInterpreter.Evaluate(cflags, COMPILE_FLAGS)); - } - const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); - if (const char* coptions = file->GetProperty(COMPILE_OPTIONS)) { - lg->AppendCompileOptions( - compileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS)); - } - fileData.Flags = compileFlags; - - // Add include directories from source file properties. - std::vector<std::string> includes; - - const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); - if (const char* cincludes = file->GetProperty(INCLUDE_DIRECTORIES)) { - const char* evaluatedIncludes = - genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES); - lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file); - - for (const auto& include : includes) { - fileData.IncludePathList.push_back( - std::make_pair(include, - target->IsSystemIncludeDirectory( - include, config, fileData.Language))); - } - } - - fileData.IncludePathList.insert(fileData.IncludePathList.end(), - ld.IncludePathList.begin(), - ld.IncludePathList.end()); - - const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); - std::set<std::string> defines; - if (const char* defs = file->GetProperty(COMPILE_DEFINITIONS)) { - lg->AppendDefines( - defines, genexInterpreter.Evaluate(defs, COMPILE_DEFINITIONS)); - } - - const std::string defPropName = - "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config); - if (const char* config_defs = file->GetProperty(defPropName)) { - lg->AppendDefines( - defines, - genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS)); - } - - defines.insert(ld.Defines.begin(), ld.Defines.end()); - - fileData.SetDefines(defines); - } - - fileData.IsGenerated = file->GetPropertyAsBool("GENERATED"); - std::vector<std::string>& groupFileList = fileGroups[fileData]; - groupFileList.push_back(file->GetFullPath()); - } - - const std::string baseDir = target->Makefile->GetCurrentSourceDirectory(); - Json::Value result = Json::arrayValue; - for (auto const& it : fileGroups) { - Json::Value group = DumpSourceFileGroup(it.first, it.second, baseDir); - if (!group.isNull()) { - result.append(group); - } - } - - return result; -} - -static Json::Value DumpCTestInfo(cmLocalGenerator* lg, cmTest* testInfo, - const std::string& config) -{ - Json::Value result = Json::objectValue; - result[kCTEST_NAME] = testInfo->GetName(); - - // Concat command entries together. After the first should be the arguments - // for the command - std::string command; - for (auto const& cmd : testInfo->GetCommand()) { - command.append(cmd); - command.append(" "); - } - - // Remove any config specific variables from the output. - cmGeneratorExpression ge; - auto cge = ge.Parse(command.c_str()); - const char* processed = cge->Evaluate(lg, config); - - result[kCTEST_COMMAND] = processed; - - // Build up the list of properties that may have been specified - Json::Value properties = Json::arrayValue; - for (auto& prop : testInfo->GetProperties()) { - Json::Value entry = Json::objectValue; - entry[kKEY_KEY] = prop.first; - - // Remove config variables from the value too. - auto cge_value = ge.Parse(prop.second.GetValue()); - const char* processed_value = cge_value->Evaluate(lg, config); - entry[kVALUE_KEY] = processed_value; - properties.append(entry); - } - result[kPROPERTIES_KEY] = properties; - - return result; -} - -static void DumpMakefileTests(cmLocalGenerator* lg, const std::string& config, - Json::Value* result) -{ - auto mf = lg->GetMakefile(); - std::vector<cmTest*> tests; - mf->GetTests(config, tests); - for (auto test : tests) { - Json::Value tmp = DumpCTestInfo(lg, test, config); - if (!tmp.isNull()) { - result->append(tmp); - } - } -} - -static Json::Value DumpCTestProjectList(const cmake* cm, - std::string const& config) -{ - Json::Value result = Json::arrayValue; - - auto globalGen = cm->GetGlobalGenerator(); - - for (const auto& projectIt : globalGen->GetProjectMap()) { - Json::Value pObj = Json::objectValue; - pObj[kNAME_KEY] = projectIt.first; - - Json::Value tests = Json::arrayValue; - - // Gather tests for every generator - for (const auto& lg : projectIt.second) { - // Make sure they're generated. - lg->GenerateTestFiles(); - DumpMakefileTests(lg, config, &tests); - } - - pObj[kCTEST_INFO] = tests; - - result.append(pObj); - } - - return result; -} - -static Json::Value DumpCTestConfiguration(const cmake* cm, - const std::string& config) -{ - Json::Value result = Json::objectValue; - result[kNAME_KEY] = config; - - result[kPROJECTS_KEY] = DumpCTestProjectList(cm, config); - - return result; -} - -static Json::Value DumpCTestConfigurationsList(const cmake* cm) -{ - Json::Value result = Json::arrayValue; - - for (const std::string& c : getConfigurations(cm)) { - result.append(DumpCTestConfiguration(cm, c)); - } - - return result; -} - -static Json::Value DumpTarget(cmGeneratorTarget* target, - const std::string& config) -{ - cmLocalGenerator* lg = target->GetLocalGenerator(); - const cmState* state = lg->GetState(); - - const cmStateEnums::TargetType type = target->GetType(); - const std::string typeName = state->GetTargetTypeName(type); - - Json::Value ttl = Json::arrayValue; - ttl.append("EXECUTABLE"); - ttl.append("STATIC_LIBRARY"); - ttl.append("SHARED_LIBRARY"); - ttl.append("MODULE_LIBRARY"); - ttl.append("OBJECT_LIBRARY"); - ttl.append("UTILITY"); - ttl.append("INTERFACE_LIBRARY"); - - if (!hasString(ttl, typeName) || target->IsImported()) { - return Json::Value(); - } - - Json::Value result = Json::objectValue; - result[kNAME_KEY] = target->GetName(); - result[kIS_GENERATOR_PROVIDED_KEY] = - target->Target->GetIsGeneratorProvided(); - result[kTYPE_KEY] = typeName; - result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory(); - result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory(); - - if (type == cmStateEnums::INTERFACE_LIBRARY) { - return result; - } - - result[kFULL_NAME_KEY] = target->GetFullName(config); - - if (target->Target->GetHaveInstallRule()) { - result[kHAS_INSTALL_RULE] = true; - - Json::Value installPaths = Json::arrayValue; - auto targetGenerators = target->Makefile->GetInstallGenerators(); - for (auto installGenerator : targetGenerators) { - auto installTargetGenerator = - dynamic_cast<cmInstallTargetGenerator*>(installGenerator); - if (installTargetGenerator != nullptr && - installTargetGenerator->GetTarget()->Target == target->Target) { - auto dest = installTargetGenerator->GetDestination(config); - - std::string installPath; - if (!dest.empty() && cmSystemTools::FileIsFullPath(dest)) { - installPath = dest; - } else { - std::string installPrefix = - target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); - installPath = installPrefix + '/' + dest; - } - - installPaths.append(installPath); - } - } - - result[kINSTALL_PATHS] = installPaths; - } - - if (target->HaveWellDefinedOutputFiles()) { - Json::Value artifacts = Json::arrayValue; - artifacts.append( - target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact)); - if (target->IsDLLPlatform()) { - artifacts.append( - target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); - const cmGeneratorTarget::OutputInfo* output = - target->GetOutputInfo(config); - if (output && !output->PdbDir.empty()) { - artifacts.append(output->PdbDir + '/' + target->GetPDBName(config)); - } - } - result[kARTIFACTS_KEY] = artifacts; - - result[kLINKER_LANGUAGE_KEY] = target->GetLinkerLanguage(config); - - std::string linkLibs; - std::string linkFlags; - std::string linkLanguageFlags; - std::string frameworkPath; - std::string linkPath; - cmLinkLineComputer linkLineComputer(lg, - lg->GetStateSnapshot().GetDirectory()); - lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags, - linkFlags, frameworkPath, linkPath, target); - - linkLibs = cmSystemTools::TrimWhitespace(linkLibs); - linkFlags = cmSystemTools::TrimWhitespace(linkFlags); - linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags); - frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath); - linkPath = cmSystemTools::TrimWhitespace(linkPath); - - if (!cmSystemTools::TrimWhitespace(linkLibs).empty()) { - result[kLINK_LIBRARIES_KEY] = linkLibs; - } - if (!cmSystemTools::TrimWhitespace(linkFlags).empty()) { - result[kLINK_FLAGS_KEY] = linkFlags; - } - if (!cmSystemTools::TrimWhitespace(linkLanguageFlags).empty()) { - result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags; - } - if (!frameworkPath.empty()) { - result[kFRAMEWORK_PATH_KEY] = frameworkPath; - } - if (!linkPath.empty()) { - result[kLINK_PATH_KEY] = linkPath; - } - const std::string sysroot = - lg->GetMakefile()->GetSafeDefinition("CMAKE_SYSROOT"); - if (!sysroot.empty()) { - result[kSYSROOT_KEY] = sysroot; - } - } - - std::set<std::string> languages; - target->GetLanguages(languages, config); - std::map<std::string, LanguageData> languageDataMap; - for (std::string const& lang : languages) { - LanguageData& ld = languageDataMap[lang]; - ld.Language = lang; - lg->GetTargetCompileFlags(target, config, lang, ld.Flags); - std::set<std::string> defines; - lg->GetTargetDefines(target, config, lang, defines); - ld.SetDefines(defines); - std::vector<std::string> includePathList; - lg->GetIncludeDirectories(includePathList, target, lang, config, true); - for (std::string const& i : includePathList) { - ld.IncludePathList.push_back( - std::make_pair(i, target->IsSystemIncludeDirectory(i, config, lang))); - } - } - - Json::Value sourceGroupsValue = - DumpSourceFilesList(target, config, languageDataMap); - if (!sourceGroupsValue.empty()) { - result[kFILE_GROUPS_KEY] = sourceGroupsValue; - } - - return result; -} - -static Json::Value DumpTargetsList( - const std::vector<cmLocalGenerator*>& generators, const std::string& config) -{ - Json::Value result = Json::arrayValue; - - std::vector<cmGeneratorTarget*> targetList; - for (auto const& lgIt : generators) { - const auto& list = lgIt->GetGeneratorTargets(); - targetList.insert(targetList.end(), list.begin(), list.end()); - } - std::sort(targetList.begin(), targetList.end()); - - for (cmGeneratorTarget* target : targetList) { - Json::Value tmp = DumpTarget(target, config); - if (!tmp.isNull()) { - result.append(tmp); - } - } - - return result; -} - -static Json::Value DumpProjectList(const cmake* cm, std::string const& config) -{ - Json::Value result = Json::arrayValue; - - auto globalGen = cm->GetGlobalGenerator(); - - for (auto const& projectIt : globalGen->GetProjectMap()) { - Json::Value pObj = Json::objectValue; - pObj[kNAME_KEY] = projectIt.first; - - // All Projects must have at least one local generator - assert(!projectIt.second.empty()); - const cmLocalGenerator* lg = projectIt.second.at(0); - - // Project structure information: - const cmMakefile* mf = lg->GetMakefile(); - auto minVersion = mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); - pObj[kMINIMUM_CMAKE_VERSION] = minVersion ? minVersion : ""; - pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory(); - pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory(); - pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config); - - // For a project-level install rule it might be defined in any of its - // associated generators. - bool hasInstallRule = false; - for (const auto generator : projectIt.second) { - hasInstallRule = - generator->GetMakefile()->GetInstallGenerators().empty() == false; - - if (hasInstallRule) { - break; - } - } - - pObj[kHAS_INSTALL_RULE] = hasInstallRule; - - result.append(pObj); - } - - return result; -} - -static Json::Value DumpConfiguration(const cmake* cm, - const std::string& config) -{ - Json::Value result = Json::objectValue; - result[kNAME_KEY] = config; - - result[kPROJECTS_KEY] = DumpProjectList(cm, config); - - return result; -} - -static Json::Value DumpConfigurationsList(const cmake* cm) -{ - Json::Value result = Json::arrayValue; - - for (std::string const& c : getConfigurations(cm)) { - result.append(DumpConfiguration(cm, c)); - } - - return result; -} - cmServerResponse cmServerProtocol1::ProcessCodeModel( const cmServerRequest& request) { @@ -1122,9 +478,7 @@ cmServerResponse cmServerProtocol1::ProcessCodeModel( return request.ReportError("No build system was generated yet."); } - Json::Value result = Json::objectValue; - result[kCONFIGURATIONS_KEY] = DumpConfigurationsList(this->CMakeInstance()); - return request.Reply(result); + return request.Reply(cmDumpCodeModel(this->CMakeInstance())); } cmServerResponse cmServerProtocol1::ProcessCompute( @@ -1198,20 +552,20 @@ cmServerResponse cmServerProtocol1::ProcessConfigure( if (cm->LoadCache(buildDir)) { // build directory has been set up before - const char* cachedSourceDir = + const std::string* cachedSourceDir = cm->GetState()->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY"); if (!cachedSourceDir) { return request.ReportError("No CMAKE_HOME_DIRECTORY found in cache."); } if (sourceDir.empty()) { - sourceDir = std::string(cachedSourceDir); + sourceDir = *cachedSourceDir; cm->SetHomeDirectory(sourceDir); } - const char* cachedGenerator = + const std::string* cachedGenerator = cm->GetState()->GetInitializedCacheValue("CMAKE_GENERATOR"); if (cachedGenerator) { - if (gg && gg->GetName() != cachedGenerator) { + if (gg && gg->GetName() != *cachedGenerator) { return request.ReportError("Configured generator does not match with " "CMAKE_GENERATOR found in cache."); } @@ -1241,7 +595,8 @@ cmServerResponse cmServerProtocol1::ProcessConfigure( } std::vector<std::string> toWatchList; - getCMakeInputs(gg, std::string(), buildDir, nullptr, &toWatchList, nullptr); + cmGetCMakeInputs(gg, std::string(), buildDir, nullptr, &toWatchList, + nullptr); FileMonitor()->MonitorPaths(toWatchList, [this](const std::string& p, int e, int s) { @@ -1347,10 +702,7 @@ cmServerResponse cmServerProtocol1::ProcessCTests( return request.ReportError("This instance was not yet computed."); } - Json::Value result = Json::objectValue; - result[kCONFIGURATIONS_KEY] = - DumpCTestConfigurationsList(this->CMakeInstance()); - return request.Reply(result); + return request.Reply(cmDumpCTestInfo(this->CMakeInstance())); } cmServerProtocol1::GeneratorInformation::GeneratorInformation( diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 171b62e46..3c4111bc1 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -330,8 +330,8 @@ bool cmSetPropertyCommand::HandleTest(cmTest* test) bool cmSetPropertyCommand::HandleCacheMode() { if (this->PropertyName == "ADVANCED") { - if (!this->Remove && !cmSystemTools::IsOn(this->PropertyValue.c_str()) && - !cmSystemTools::IsOff(this->PropertyValue.c_str())) { + if (!this->Remove && !cmSystemTools::IsOn(this->PropertyValue) && + !cmSystemTools::IsOff(this->PropertyValue)) { std::ostringstream e; e << "given non-boolean value \"" << this->PropertyValue << "\" for CACHE property \"ADVANCED\". "; diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx index 33e1b2e06..8445b027a 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.cxx +++ b/Source/cmSetSourceFilesPropertiesCommand.cxx @@ -87,7 +87,7 @@ bool cmSetSourceFilesPropertiesCommand::RunCommand( propertyPairs.push_back(*j); if (*j == "GENERATED") { ++j; - if (j != propend && cmSystemTools::IsOn(j->c_str())) { + if (j != propend && cmSystemTools::IsOn(*j)) { generated = true; } } else { diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index d2e83a6aa..7f33b7a33 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -50,7 +50,7 @@ bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args, } #else // try to find the hostname for this computer - if (!cmSystemTools::IsOff(hostname_cmd.c_str())) { + if (!cmSystemTools::IsOff(hostname_cmd)) { std::string host; cmSystemTools::RunSingleCommand(hostname_cmd.c_str(), &host, nullptr, nullptr, nullptr, diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 6792d6638..5d1f3f006 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -132,8 +132,8 @@ bool cmSourceFile::FindFullPath(std::string* error) cmMakefile const* mf = this->Location.GetMakefile(); const char* tryDirs[3] = { nullptr, nullptr, nullptr }; if (this->Location.DirectoryIsAmbiguous()) { - tryDirs[0] = mf->GetCurrentSourceDirectory(); - tryDirs[1] = mf->GetCurrentBinaryDirectory(); + tryDirs[0] = mf->GetCurrentSourceDirectory().c_str(); + tryDirs[1] = mf->GetCurrentBinaryDirectory().c_str(); } else { tryDirs[0] = ""; } @@ -296,6 +296,15 @@ const char* cmSourceFile::GetProperty(const std::string& prop) const return retVal; } +const char* cmSourceFile::GetSafeProperty(const std::string& prop) const +{ + const char* ret = this->GetProperty(prop); + if (!ret) { + return ""; + } + return ret; +} + bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const { return cmSystemTools::IsOn(this->GetProperty(prop)); diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 1516d98ed..ab0f22927 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -45,7 +45,10 @@ public: void SetProperty(const std::string& prop, const char* value); void AppendProperty(const std::string& prop, const char* value, bool asString = false); + ///! Might return a nullptr if the property is not set or invalid const char* GetProperty(const std::string& prop) const; + ///! Always returns a valid pointer + const char* GetSafeProperty(const std::string& prop) const; bool GetPropertyAsBool(const std::string& prop) const; /** Implement getting a property when called from a CMake language diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index bd8d318d7..15433f94f 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -205,18 +205,18 @@ bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc) } } else if (this->AmbiguousDirectory) { // Compare possible directory combinations. - std::string const& srcDir = cmSystemTools::CollapseFullPath( + std::string const srcDir = cmSystemTools::CollapseFullPath( this->Directory, this->Makefile->GetCurrentSourceDirectory()); - std::string const& binDir = cmSystemTools::CollapseFullPath( + std::string const binDir = cmSystemTools::CollapseFullPath( this->Directory, this->Makefile->GetCurrentBinaryDirectory()); if (srcDir != loc.Directory && binDir != loc.Directory) { return false; } } else if (loc.AmbiguousDirectory) { // Compare possible directory combinations. - std::string const& srcDir = cmSystemTools::CollapseFullPath( + std::string const srcDir = cmSystemTools::CollapseFullPath( loc.Directory, loc.Makefile->GetCurrentSourceDirectory()); - std::string const& binDir = cmSystemTools::CollapseFullPath( + std::string const binDir = cmSystemTools::CollapseFullPath( loc.Directory, loc.Makefile->GetCurrentBinaryDirectory()); if (srcDir != this->Directory && binDir != this->Directory) { return false; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index a32e04a2e..a2008a0d1 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -140,7 +140,8 @@ const char* cmState::GetCacheEntryValue(std::string const& key) const return e->Value.c_str(); } -const char* cmState::GetInitializedCacheValue(std::string const& key) const +const std::string* cmState::GetInitializedCacheValue( + std::string const& key) const { return this->CacheManager->GetInitializedCacheValue(key); } @@ -281,6 +282,10 @@ cmStateSnapshot cmState::Reset() it->CompileDefinitionsBacktraces.clear(); it->CompileOptions.clear(); it->CompileOptionsBacktraces.clear(); + it->LinkOptions.clear(); + it->LinkOptionsBacktraces.clear(); + it->LinkDirectories.clear(); + it->LinkDirectoriesBacktraces.clear(); it->DirectoryEnd = pos; it->NormalTargetNames.clear(); it->Properties.clear(); @@ -296,9 +301,9 @@ cmStateSnapshot cmState::Reset() { std::string srcDir = - cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root); + *cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root); std::string binDir = - cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root); + *cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root); this->VarTree.Clear(); pos->Vars = this->VarTree.Push(this->VarTree.Root()); pos->Parent = this->VarTree.Root(); @@ -666,6 +671,8 @@ cmStateSnapshot cmState::CreateBaseSnapshot() pos->IncludeDirectoryPosition = 0; pos->CompileDefinitionsPosition = 0; pos->CompileOptionsPosition = 0; + pos->LinkOptionsPosition = 0; + pos->LinkDirectoriesPosition = 0; pos->BuildSystemDirectory->DirectoryEnd = pos; pos->Policies = this->PolicyStack.Root(); pos->PolicyRoot = this->PolicyStack.Root(); @@ -817,6 +824,10 @@ cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot) prevPos->BuildSystemDirectory->CompileDefinitions.size(); prevPos->CompileOptionsPosition = prevPos->BuildSystemDirectory->CompileOptions.size(); + prevPos->LinkOptionsPosition = + prevPos->BuildSystemDirectory->LinkOptions.size(); + prevPos->LinkDirectoriesPosition = + prevPos->BuildSystemDirectory->LinkDirectories.size(); prevPos->BuildSystemDirectory->DirectoryEnd = prevPos; if (!pos->Keep && this->SnapshotData.IsLast(pos)) { diff --git a/Source/cmState.h b/Source/cmState.h index b20e8c686..916985dbb 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -68,7 +68,7 @@ public: std::vector<std::string> GetCacheEntryKeys() const; const char* GetCacheEntryValue(std::string const& key) const; - const char* GetInitializedCacheValue(std::string const& key) const; + const std::string* GetInitializedCacheValue(std::string const& key) const; cmStateEnums::CacheEntryType GetCacheEntryType(std::string const& key) const; void SetCacheEntryValue(std::string const& key, std::string const& value); void SetCacheValue(std::string const& key, std::string const& value); diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 85e6366d9..f94e7146e 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -84,9 +84,9 @@ void cmStateDirectory::ComputeRelativePathTopBinary() } } -const char* cmStateDirectory::GetCurrentSource() const +std::string const& cmStateDirectory::GetCurrentSource() const { - return this->DirectoryState->Location.c_str(); + return this->DirectoryState->Location; } void cmStateDirectory::SetCurrentSource(std::string const& dir) @@ -101,9 +101,9 @@ void cmStateDirectory::SetCurrentSource(std::string const& dir) this->Snapshot_.SetDefinition("CMAKE_CURRENT_SOURCE_DIR", loc); } -const char* cmStateDirectory::GetCurrentBinary() const +std::string const& cmStateDirectory::GetCurrentBinary() const { - return this->DirectoryState->OutputLocation.c_str(); + return this->DirectoryState->OutputLocation; } void cmStateDirectory::SetCurrentBinary(std::string const& dir) @@ -118,14 +118,14 @@ void cmStateDirectory::SetCurrentBinary(std::string const& dir) this->Snapshot_.SetDefinition("CMAKE_CURRENT_BINARY_DIR", loc); } -const char* cmStateDirectory::GetRelativePathTopSource() const +std::string const& cmStateDirectory::GetRelativePathTopSource() const { - return this->DirectoryState->RelativePathTopSource.c_str(); + return this->DirectoryState->RelativePathTopSource; } -const char* cmStateDirectory::GetRelativePathTopBinary() const +std::string const& cmStateDirectory::GetRelativePathTopBinary() const { - return this->DirectoryState->RelativePathTopBinary.c_str(); + return this->DirectoryState->RelativePathTopBinary; } void cmStateDirectory::SetRelativePathTopSource(const char* dir) @@ -360,6 +360,106 @@ void cmStateDirectory::ClearCompileOptions() this->Snapshot_.Position->CompileOptionsPosition); } +cmStringRange cmStateDirectory::GetLinkOptionsEntries() const +{ + return GetPropertyContent(this->DirectoryState->LinkOptions, + this->Snapshot_.Position->LinkOptionsPosition); +} + +cmBacktraceRange cmStateDirectory::GetLinkOptionsEntryBacktraces() const +{ + return GetPropertyBacktraces(this->DirectoryState->LinkOptions, + this->DirectoryState->LinkOptionsBacktraces, + this->Snapshot_.Position->LinkOptionsPosition); +} + +void cmStateDirectory::AppendLinkOptionsEntry(const std::string& vec, + const cmListFileBacktrace& lfbt) +{ + AppendEntry(this->DirectoryState->LinkOptions, + this->DirectoryState->LinkOptionsBacktraces, + this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt); +} + +void cmStateDirectory::SetLinkOptions(const std::string& vec, + const cmListFileBacktrace& lfbt) +{ + SetContent(this->DirectoryState->LinkOptions, + this->DirectoryState->LinkOptionsBacktraces, + this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt); +} + +void cmStateDirectory::ClearLinkOptions() +{ + ClearContent(this->DirectoryState->LinkOptions, + this->DirectoryState->LinkOptionsBacktraces, + this->Snapshot_.Position->LinkOptionsPosition); +} + +cmStringRange cmStateDirectory::GetLinkDirectoriesEntries() const +{ + return GetPropertyContent(this->DirectoryState->LinkDirectories, + this->Snapshot_.Position->LinkDirectoriesPosition); +} + +cmBacktraceRange cmStateDirectory::GetLinkDirectoriesEntryBacktraces() const +{ + return GetPropertyBacktraces( + this->DirectoryState->LinkDirectories, + this->DirectoryState->LinkDirectoriesBacktraces, + this->Snapshot_.Position->LinkDirectoriesPosition); +} + +void cmStateDirectory::AppendLinkDirectoriesEntry( + const std::string& vec, const cmListFileBacktrace& lfbt) +{ + AppendEntry(this->DirectoryState->LinkDirectories, + this->DirectoryState->LinkDirectoriesBacktraces, + this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt); +} +void cmStateDirectory::PrependLinkDirectoriesEntry( + const std::string& vec, const cmListFileBacktrace& lfbt) +{ + std::vector<std::string>::iterator entryEnd = + this->DirectoryState->LinkDirectories.begin() + + this->Snapshot_.Position->LinkDirectoriesPosition; + + std::vector<std::string>::reverse_iterator rend = + this->DirectoryState->LinkDirectories.rend(); + std::vector<std::string>::reverse_iterator rbegin = + cmMakeReverseIterator(entryEnd); + rbegin = std::find(rbegin, rend, cmPropertySentinal); + + std::vector<std::string>::iterator entryIt = rbegin.base(); + std::vector<std::string>::iterator entryBegin = + this->DirectoryState->LinkDirectories.begin(); + + std::vector<cmListFileBacktrace>::iterator btIt = + this->DirectoryState->LinkDirectoriesBacktraces.begin() + + std::distance(entryBegin, entryIt); + + this->DirectoryState->LinkDirectories.insert(entryIt, vec); + this->DirectoryState->LinkDirectoriesBacktraces.insert(btIt, lfbt); + + this->Snapshot_.Position->LinkDirectoriesPosition = + this->DirectoryState->LinkDirectories.size(); +} + +void cmStateDirectory::SetLinkDirectories(const std::string& vec, + const cmListFileBacktrace& lfbt) +{ + SetContent(this->DirectoryState->LinkDirectories, + this->DirectoryState->LinkDirectoriesBacktraces, + this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt); +} + +void cmStateDirectory::ClearLinkDirectories() +{ + ClearContent(this->DirectoryState->LinkDirectories, + this->DirectoryState->LinkDirectoriesBacktraces, + this->Snapshot_.Position->LinkDirectoriesPosition); +} + void cmStateDirectory::SetProperty(const std::string& prop, const char* value, cmListFileBacktrace const& lfbt) { @@ -387,6 +487,22 @@ void cmStateDirectory::SetProperty(const std::string& prop, const char* value, this->SetCompileDefinitions(value, lfbt); return; } + if (prop == "LINK_OPTIONS") { + if (!value) { + this->ClearLinkOptions(); + return; + } + this->SetLinkOptions(value, lfbt); + return; + } + if (prop == "LINK_DIRECTORIES") { + if (!value) { + this->ClearLinkDirectories(); + return; + } + this->SetLinkDirectories(value, lfbt); + return; + } this->DirectoryState->Properties.SetProperty(prop, value); } @@ -407,6 +523,14 @@ void cmStateDirectory::AppendProperty(const std::string& prop, this->AppendCompileDefinitionsEntry(value, lfbt); return; } + if (prop == "LINK_OPTIONS") { + this->AppendLinkOptionsEntry(value, lfbt); + return; + } + if (prop == "LINK_DIRECTORIES") { + this->AppendLinkDirectoriesEntry(value, lfbt); + return; + } this->DirectoryState->Properties.AppendProperty(prop, value, asString); } @@ -426,7 +550,7 @@ const char* cmStateDirectory::GetProperty(const std::string& prop, if (prop == "PARENT_DIRECTORY") { cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent(); if (parent.IsValid()) { - return parent.GetDirectory().GetCurrentSource(); + return parent.GetDirectory().GetCurrentSource().c_str(); } return ""; } @@ -490,6 +614,14 @@ const char* cmStateDirectory::GetProperty(const std::string& prop, output = cmJoin(this->GetCompileDefinitionsEntries(), ";"); return output.c_str(); } + if (prop == "LINK_OPTIONS") { + output = cmJoin(this->GetLinkOptionsEntries(), ";"); + return output.c_str(); + } + if (prop == "LINK_DIRECTORIES") { + output = cmJoin(this->GetLinkDirectoriesEntries(), ";"); + return output.c_str(); + } const char* retVal = this->DirectoryState->Properties.GetPropertyValue(prop); if (!retVal && chain) { diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index 79bb36943..e5f4d05d1 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -22,13 +22,13 @@ class cmStateDirectory cmStateSnapshot const& snapshot); public: - const char* GetCurrentSource() const; + std::string const& GetCurrentSource() const; void SetCurrentSource(std::string const& dir); - const char* GetCurrentBinary() const; + std::string const& GetCurrentBinary() const; void SetCurrentBinary(std::string const& dir); - const char* GetRelativePathTopSource() const; - const char* GetRelativePathTopBinary() const; + std::string const& GetRelativePathTopSource() const; + std::string const& GetRelativePathTopBinary() const; void SetRelativePathTopSource(const char* dir); void SetRelativePathTopBinary(const char* dir); @@ -58,6 +58,23 @@ public: cmListFileBacktrace const& lfbt); void ClearCompileOptions(); + cmStringRange GetLinkOptionsEntries() const; + cmBacktraceRange GetLinkOptionsEntryBacktraces() const; + void AppendLinkOptionsEntry(std::string const& vec, + cmListFileBacktrace const& lfbt); + void PrependLinkDirectoriesEntry(std::string const& vec, + cmListFileBacktrace const& lfbt); + void SetLinkOptions(std::string const& vec, cmListFileBacktrace const& lfbt); + void ClearLinkOptions(); + + cmStringRange GetLinkDirectoriesEntries() const; + cmBacktraceRange GetLinkDirectoriesEntryBacktraces() const; + void AppendLinkDirectoriesEntry(std::string const& vec, + cmListFileBacktrace const& lfbt); + void SetLinkDirectories(std::string const& vec, + cmListFileBacktrace const& lfbt); + void ClearLinkDirectories(); + void SetProperty(const std::string& prop, const char* value, cmListFileBacktrace const& lfbt); void AppendProperty(const std::string& prop, const char* value, diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h index f36ee37ea..e76f2af37 100644 --- a/Source/cmStatePrivate.h +++ b/Source/cmStatePrivate.h @@ -42,6 +42,8 @@ struct cmStateDetail::SnapshotDataType std::vector<std::string>::size_type IncludeDirectoryPosition; std::vector<std::string>::size_type CompileDefinitionsPosition; std::vector<std::string>::size_type CompileOptionsPosition; + std::vector<std::string>::size_type LinkOptionsPosition; + std::vector<std::string>::size_type LinkDirectoriesPosition; }; struct cmStateDetail::PolicyStackEntry : public cmPolicies::PolicyMap @@ -84,6 +86,12 @@ struct cmStateDetail::BuildsystemDirectoryStateType std::vector<std::string> CompileOptions; std::vector<cmListFileBacktrace> CompileOptionsBacktraces; + std::vector<std::string> LinkOptions; + std::vector<cmListFileBacktrace> LinkOptionsBacktraces; + + std::vector<std::string> LinkDirectories; + std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces; + std::vector<std::string> NormalTargetNames; std::string ProjectName; diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 8f5f58c95..c2510f355 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -204,7 +204,8 @@ bool cmStateSnapshot::HasDefinedPolicyCMP0011() return !this->Position->Policies->IsEmpty(); } -const char* cmStateSnapshot::GetDefinition(std::string const& name) const +std::string const* cmStateSnapshot::GetDefinition( + std::string const& name) const { assert(this->Position->Vars.IsValid()); return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root); @@ -390,6 +391,20 @@ void cmStateSnapshot::InitializeFromParent() this->Position->BuildSystemDirectory->CompileOptionsBacktraces, this->Position->CompileOptionsPosition); + InitializeContentFromParent( + parent->BuildSystemDirectory->LinkOptions, + this->Position->BuildSystemDirectory->LinkOptions, + parent->BuildSystemDirectory->LinkOptionsBacktraces, + this->Position->BuildSystemDirectory->LinkOptionsBacktraces, + this->Position->LinkOptionsPosition); + + InitializeContentFromParent( + parent->BuildSystemDirectory->LinkDirectories, + this->Position->BuildSystemDirectory->LinkDirectories, + parent->BuildSystemDirectory->LinkDirectoriesBacktraces, + this->Position->BuildSystemDirectory->LinkDirectoriesBacktraces, + this->Position->LinkDirectoriesPosition); + const char* include_regex = parent->BuildSystemDirectory->Properties.GetPropertyValue( "INCLUDE_REGULAR_EXPRESSION"); @@ -419,8 +434,8 @@ std::string cmStateSnapshot::GetProjectName() const void cmStateSnapshot::InitializeFromParent_ForSubdirsCommand() { - std::string currentSrcDir = this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR"); - std::string currentBinDir = this->GetDefinition("CMAKE_CURRENT_BINARY_DIR"); + std::string currentSrcDir = *this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR"); + std::string currentBinDir = *this->GetDefinition("CMAKE_CURRENT_BINARY_DIR"); this->InitializeFromParent(); this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory()); this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory()); diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h index af5653b99..014c62e9d 100644 --- a/Source/cmStateSnapshot.h +++ b/Source/cmStateSnapshot.h @@ -22,7 +22,7 @@ public: cmStateSnapshot(cmState* state = nullptr); cmStateSnapshot(cmState* state, cmStateDetail::PositionType position); - const char* GetDefinition(std::string const& name) const; + std::string const* GetDefinition(std::string const& name) const; bool IsInitialized(std::string const& name) const; void SetDefinition(std::string const& name, std::string const& value); void RemoveDefinition(std::string const& name); diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index ed88a1e72..1605fd7bc 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -273,7 +273,7 @@ bool cmStringCommand::RegexMatch(std::vector<std::string> const& args) // Scan through the input for all matches. std::string output; - if (re.find(input.c_str())) { + if (re.find(input)) { this->Makefile->StoreMatches(re); std::string::size_type l = re.start(); std::string::size_type r = re.end(); diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx index c74ca59bb..9d36228d2 100644 --- a/Source/cmSubdirCommand.cxx +++ b/Source/cmSubdirCommand.cxx @@ -30,18 +30,17 @@ bool cmSubdirCommand::InitialPass(std::vector<std::string> const& args, // if they specified a relative path then compute the full std::string srcPath = - std::string(this->Makefile->GetCurrentSourceDirectory()) + "/" + i; + this->Makefile->GetCurrentSourceDirectory() + "/" + i; if (cmSystemTools::FileIsDirectory(srcPath)) { std::string binPath = - std::string(this->Makefile->GetCurrentBinaryDirectory()) + "/" + i; + this->Makefile->GetCurrentBinaryDirectory() + "/" + i; this->Makefile->AddSubDirectory(srcPath, binPath, excludeFromAll, false); } // otherwise it is a full path else if (cmSystemTools::FileIsDirectory(i)) { // we must compute the binPath from the srcPath, we just take the last // element from the source path and use that - std::string binPath = - std::string(this->Makefile->GetCurrentBinaryDirectory()) + "/" + + std::string binPath = this->Makefile->GetCurrentBinaryDirectory() + "/" + cmSystemTools::GetFilenameName(i); this->Makefile->AddSubDirectory(i, binPath, excludeFromAll, false); } else { diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 75c8caf79..568ee828a 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -6,6 +6,7 @@ #include "cmDuration.h" #include "cmProcessOutput.h" #include "cm_sys_stat.h" +#include "cm_uv.h" #if defined(CMAKE_BUILD_WITH_CMAKE) # include "cmArchiveWrite.h" @@ -42,7 +43,6 @@ #include <ctype.h> #include <errno.h> #include <iostream> -#include <set> #include <sstream> #include <stdio.h> #include <stdlib.h> @@ -56,8 +56,6 @@ # include <wincrypt.h> # include <fcntl.h> /* _O_TEXT */ - -# include "cm_uv.h" #else # include <sys/time.h> # include <unistd.h> @@ -372,24 +370,36 @@ bool cmSystemTools::IsOn(const char* val) if (!val) { return false; } - size_t len = strlen(val); - if (len > 4) { - return false; + /* clang-format off */ + // "1" + if (val[0] == '1' && val[1] == '\0') { + return true; } - std::string v(val, len); - - static std::set<std::string> onValues; - if (onValues.empty()) { - onValues.insert("ON"); - onValues.insert("1"); - onValues.insert("YES"); - onValues.insert("TRUE"); - onValues.insert("Y"); + // "ON" + if ((val[0] == 'O' || val[0] == 'o') && + (val[1] == 'N' || val[1] == 'n') && val[2] == '\0') { + return true; } - for (char& c : v) { - c = static_cast<char>(toupper(c)); + // "Y", "YES" + if ((val[0] == 'Y' || val[0] == 'y') && (val[1] == '\0' || ( + (val[1] == 'E' || val[1] == 'e') && + (val[2] == 'S' || val[2] == 's') && val[3] == '\0'))) { + return true; + } + // "TRUE" + if ((val[0] == 'T' || val[0] == 't') && + (val[1] == 'R' || val[1] == 'r') && + (val[2] == 'U' || val[2] == 'u') && + (val[3] == 'E' || val[3] == 'e') && val[4] == '\0') { + return true; } - return (onValues.count(v) > 0); + /* clang-format on */ + return false; +} + +bool cmSystemTools::IsOn(const std::string& val) +{ + return cmSystemTools::IsOn(val.c_str()); } bool cmSystemTools::IsNOTFOUND(const char* val) @@ -402,30 +412,50 @@ bool cmSystemTools::IsNOTFOUND(const char* val) bool cmSystemTools::IsOff(const char* val) { - if (!val || !*val) { + // "" + if (!val || val[0] == '\0') { return true; } - size_t len = strlen(val); - // Try and avoid toupper() for large strings. - if (len > 6) { - return cmSystemTools::IsNOTFOUND(val); + /* clang-format off */ + // "0" + if (val[0] == '0' && val[1] == '\0') { + return true; } - - static std::set<std::string> offValues; - if (offValues.empty()) { - offValues.insert("OFF"); - offValues.insert("0"); - offValues.insert("NO"); - offValues.insert("FALSE"); - offValues.insert("N"); - offValues.insert("IGNORE"); + // "OFF" + if ((val[0] == 'O' || val[0] == 'o') && + (val[1] == 'F' || val[1] == 'f') && + (val[2] == 'F' || val[2] == 'f') && val[3] == '\0') { + return true; } - // Try and avoid toupper(). - std::string v(val, len); - for (char& c : v) { - c = static_cast<char>(toupper(c)); + // "N", "NO" + if ((val[0] == 'N' || val[0] == 'n') && (val[1] == '\0' || ( + (val[1] == 'O' || val[1] == 'o') && val[2] == '\0'))) { + return true; } - return (offValues.count(v) > 0); + // "FALSE" + if ((val[0] == 'F' || val[0] == 'f') && + (val[1] == 'A' || val[1] == 'a') && + (val[2] == 'L' || val[2] == 'l') && + (val[3] == 'S' || val[3] == 's') && + (val[4] == 'E' || val[4] == 'e') && val[5] == '\0') { + return true; + } + // "IGNORE" + if ((val[0] == 'I' || val[0] == 'i') && + (val[1] == 'G' || val[1] == 'g') && + (val[2] == 'N' || val[2] == 'n') && + (val[3] == 'O' || val[3] == 'o') && + (val[4] == 'R' || val[4] == 'r') && + (val[5] == 'E' || val[5] == 'e') && val[6] == '\0') { + return true; + } + /* clang-format on */ + return cmSystemTools::IsNOTFOUND(val); +} + +bool cmSystemTools::IsOff(const std::string& val) +{ + return cmSystemTools::IsOff(val.c_str()); } void cmSystemTools::ParseWindowsCommandLine(const char* command, @@ -2814,11 +2844,11 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, // contain the location of the linker map, however on MIPS the // .dynamic section is always read-only so this is not possible. MIPS // objects instead contain a DT_MIPS_RLD_MAP tag which contains the - // address where the dyanmic linker will write to (an indirect + // address where the dynamic linker will write to (an indirect // version of DT_DEBUG). Since this doesn't work when using PIE, a // relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this // version contains a relative offset, moving it changes the - // calculated address. This may cause the dyanmic linker to write + // calculated address. This may cause the dynamic linker to write // into memory it should not be changing. // // To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If @@ -2975,3 +3005,25 @@ bool cmSystemTools::StringToULong(const char* str, unsigned long* value) *value = strtoul(str, &endp, 10); return (*endp == '\0') && (endp != str) && (errno == 0); } + +bool cmSystemTools::CreateSymlink(const std::string& origName, + const std::string& newName) +{ + uv_fs_t req; + int flags = 0; +#if defined(_WIN32) + if (cmsys::SystemTools::FileIsDirectory(origName)) { + flags |= UV_FS_SYMLINK_DIR; + } +#endif + int err = uv_fs_symlink(nullptr, &req, origName.c_str(), newName.c_str(), + flags, nullptr); + if (err) { + std::string e = + "failed to create symbolic link '" + newName + "': " + uv_strerror(err); + cmSystemTools::Error(e.c_str()); + return false; + } + + return true; +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index c0a1b6b55..98300eb33 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -129,6 +129,7 @@ public: * as ifdef. */ static bool IsOn(const char* val); + static bool IsOn(const std::string& val); /** * does a string indicate a false or off value ? Note that this is @@ -138,6 +139,7 @@ public: * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. */ static bool IsOff(const char* val); + static bool IsOff(const std::string& val); ///! Return true if value is NOTFOUND or ends in -NOTFOUND. static bool IsNOTFOUND(const char* value); @@ -511,6 +513,11 @@ public: /** Perform one-time initialization of libuv. */ static void InitializeLibUV(); + /** Create a symbolic link if the platform supports it. Returns whether + creation succeeded. */ + static bool CreateSymlink(const std::string& origName, + const std::string& newName); + private: static bool s_ForceUnixPaths; static bool s_RunCommandHideConsole; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 18688163c..f0d6519bb 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -166,6 +166,10 @@ public: std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces; std::vector<std::string> SourceEntries; std::vector<cmListFileBacktrace> SourceBacktraces; + std::vector<std::string> LinkOptionsEntries; + std::vector<cmListFileBacktrace> LinkOptionsBacktraces; + std::vector<std::string> LinkDirectoriesEntries; + std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces; std::vector<std::string> LinkImplementationPropertyEntries; std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces; }; @@ -188,13 +192,11 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, // Check whether this is a DLL platform. this->DLLPlatform = - strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"), - "") != 0; + !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); // Check whether we are targeting an Android platform. this->IsAndroid = - strcmp(this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME"), - "Android") == 0; + (this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android"); // Setup default property values. if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && @@ -276,6 +278,31 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("LINK_SEARCH_START_STATIC", nullptr); this->SetPropertyDefault("LINK_SEARCH_END_STATIC", nullptr); this->SetPropertyDefault("FOLDER", nullptr); +#ifdef __APPLE__ + if (this->GetGlobalGenerator()->IsXcode()) { + this->SetPropertyDefault("XCODE_SCHEME_ADDRESS_SANITIZER", nullptr); + this->SetPropertyDefault( + "XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN", nullptr); + this->SetPropertyDefault("XCODE_SCHEME_THREAD_SANITIZER", nullptr); + this->SetPropertyDefault("XCODE_SCHEME_THREAD_SANITIZER_STOP", nullptr); + this->SetPropertyDefault("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER", + nullptr); + this->SetPropertyDefault( + "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP", nullptr); + this->SetPropertyDefault("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER", + nullptr); + this->SetPropertyDefault("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP", + nullptr); + this->SetPropertyDefault("XCODE_SCHEME_MALLOC_SCRIBBLE", nullptr); + this->SetPropertyDefault("XCODE_SCHEME_MALLOC_GUARD_EDGES", nullptr); + this->SetPropertyDefault("XCODE_SCHEME_GUARD_MALLOC", nullptr); + this->SetPropertyDefault("XCODE_SCHEME_ZOMBIE_OBJECTS", nullptr); + this->SetPropertyDefault("XCODE_SCHEME_MALLOC_STACK", nullptr); + this->SetPropertyDefault("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE", + nullptr); + this->SetPropertyDefault("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS", nullptr); + } +#endif } // Collect the set of configuration types. @@ -343,17 +370,41 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SystemIncludeDirectories.insert(parentSystemIncludes.begin(), parentSystemIncludes.end()); - const cmStringRange parentOptions = + const cmStringRange parentCompileOptions = this->Makefile->GetCompileOptionsEntries(); - const cmBacktraceRange parentOptionsBts = + const cmBacktraceRange parentCompileOptionsBts = this->Makefile->GetCompileOptionsBacktraces(); this->Internal->CompileOptionsEntries.insert( - this->Internal->CompileOptionsEntries.end(), parentOptions.begin(), - parentOptions.end()); + this->Internal->CompileOptionsEntries.end(), + parentCompileOptions.begin(), parentCompileOptions.end()); this->Internal->CompileOptionsBacktraces.insert( - this->Internal->CompileOptionsBacktraces.end(), parentOptionsBts.begin(), - parentOptionsBts.end()); + this->Internal->CompileOptionsBacktraces.end(), + parentCompileOptionsBts.begin(), parentCompileOptionsBts.end()); + + const cmStringRange parentLinkOptions = + this->Makefile->GetLinkOptionsEntries(); + const cmBacktraceRange parentLinkOptionsBts = + this->Makefile->GetLinkOptionsBacktraces(); + + this->Internal->LinkOptionsEntries.insert( + this->Internal->LinkOptionsEntries.end(), parentLinkOptions.begin(), + parentLinkOptions.end()); + this->Internal->LinkOptionsBacktraces.insert( + this->Internal->LinkOptionsBacktraces.end(), + parentLinkOptionsBts.begin(), parentLinkOptionsBts.end()); + + const cmStringRange parentLinkDirectories = + this->Makefile->GetLinkDirectoriesEntries(); + const cmBacktraceRange parentLinkDirectoriesBts = + this->Makefile->GetLinkDirectoriesBacktraces(); + + this->Internal->LinkDirectoriesEntries.insert( + this->Internal->LinkDirectoriesEntries.end(), + parentLinkDirectories.begin(), parentLinkDirectories.end()); + this->Internal->LinkDirectoriesBacktraces.insert( + this->Internal->LinkDirectoriesBacktraces.end(), + parentLinkDirectoriesBts.begin(), parentLinkDirectoriesBts.end()); } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && @@ -403,6 +454,31 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, if (this->TargetTypeValue <= cmStateEnums::UTILITY) { this->SetPropertyDefault("DOTNET_TARGET_FRAMEWORK_VERSION", nullptr); } + + if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && + this->GetType() != cmStateEnums::UTILITY) { + + // check for "CMAKE_VS_GLOBALS" variable and set up target properties + // if any + const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS"); + if (globals) { + const std::string genName = mf->GetGlobalGenerator()->GetName(); + if (cmHasLiteralPrefix(genName, "Visual Studio")) { + std::vector<std::string> props; + cmSystemTools::ExpandListArgument(globals, props); + const std::string vsGlobal = "VS_GLOBAL_"; + for (const std::string& i : props) { + // split NAME=VALUE + const std::string::size_type assignment = i.find('='); + if (assignment != std::string::npos) { + const std::string propName = vsGlobal + i.substr(0, assignment); + const std::string propValue = i.substr(assignment + 1); + this->SetPropertyDefault(propName, propValue.c_str()); + } + } + } + } + } } cmGlobalGenerator* cmTarget::GetGlobalGenerator() const @@ -477,9 +553,7 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs) std::string srcFiles; const char* sep = ""; for (auto filename : srcs) { - const char* src = filename.c_str(); - - if (!(src[0] == '$' && src[1] == '<')) { + if (!cmGeneratorExpression::StartsWithGeneratorExpression(filename)) { if (!filename.empty()) { filename = this->ProcessSourceItemCMP0049(filename); if (filename.empty()) { @@ -619,19 +693,6 @@ cmSourceFile* cmTarget::AddSource(const std::string& src) cmSourceFileLocationKind::Known); } -void cmTarget::AddLinkDirectory(const std::string& d) -{ - // Make sure we don't add unnecessary search directories. - if (this->LinkDirectoriesEmmitted.insert(d).second) { - this->LinkDirectories.push_back(d); - } -} - -const std::vector<std::string>& cmTarget::GetLinkDirectories() const -{ - return this->LinkDirectories; -} - void cmTarget::ClearDependencyInformation(cmMakefile& mf) { std::string depname = this->GetName(); @@ -706,20 +767,27 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib, cmTargetLinkLibraryType llt) { - cmTarget* tgt = this->Makefile->FindTargetToUse(lib); + this->AddLinkLibrary(mf, lib, lib, llt); +} + +void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, + std::string const& libRef, + cmTargetLinkLibraryType llt) +{ + cmTarget* tgt = mf.FindTargetToUse(lib); { const bool isNonImportedTarget = tgt && !tgt->IsImported(); const std::string libName = (isNonImportedTarget && llt != GENERAL_LibraryType) - ? targetNameGenex(lib) - : lib; + ? targetNameGenex(libRef) + : libRef; this->AppendProperty( "LINK_LIBRARIES", this->GetDebugGeneratorExpressions(libName, llt).c_str()); } - if (cmGeneratorExpression::Find(lib) != std::string::npos || + if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef || (tgt && (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY || tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) || @@ -822,6 +890,26 @@ cmBacktraceRange cmTarget::GetSourceBacktraces() const return cmMakeRange(this->Internal->SourceBacktraces); } +cmStringRange cmTarget::GetLinkOptionsEntries() const +{ + return cmMakeRange(this->Internal->LinkOptionsEntries); +} + +cmBacktraceRange cmTarget::GetLinkOptionsBacktraces() const +{ + return cmMakeRange(this->Internal->LinkOptionsBacktraces); +} + +cmStringRange cmTarget::GetLinkDirectoriesEntries() const +{ + return cmMakeRange(this->Internal->LinkDirectoriesEntries); +} + +cmBacktraceRange cmTarget::GetLinkDirectoriesBacktraces() const +{ + return cmMakeRange(this->Internal->LinkDirectoriesBacktraces); +} + cmStringRange cmTarget::GetLinkImplementationEntries() const { return cmMakeRange(this->Internal->LinkImplementationPropertyEntries); @@ -847,6 +935,8 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) MAKE_STATIC_PROP(EXPORT_NAME); MAKE_STATIC_PROP(IMPORTED_GLOBAL); MAKE_STATIC_PROP(INCLUDE_DIRECTORIES); + MAKE_STATIC_PROP(LINK_OPTIONS); + MAKE_STATIC_PROP(LINK_DIRECTORIES); MAKE_STATIC_PROP(LINK_LIBRARIES); MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES); MAKE_STATIC_PROP(NAME); @@ -925,6 +1015,22 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileDefinitionsBacktraces.push_back(lfbt); } + } else if (prop == propLINK_OPTIONS) { + this->Internal->LinkOptionsEntries.clear(); + this->Internal->LinkOptionsBacktraces.clear(); + if (value) { + this->Internal->LinkOptionsEntries.push_back(value); + cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); + this->Internal->LinkOptionsBacktraces.push_back(lfbt); + } + } else if (prop == propLINK_DIRECTORIES) { + this->Internal->LinkDirectoriesEntries.clear(); + this->Internal->LinkDirectoriesBacktraces.clear(); + if (value) { + this->Internal->LinkDirectoriesEntries.push_back(value); + cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); + this->Internal->LinkDirectoriesBacktraces.push_back(lfbt); + } } else if (prop == propLINK_LIBRARIES) { this->Internal->LinkImplementationPropertyEntries.clear(); this->Internal->LinkImplementationPropertyBacktraces.clear(); @@ -1030,6 +1136,18 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->CompileDefinitionsBacktraces.push_back(lfbt); } + } else if (prop == "LINK_OPTIONS") { + if (value && *value) { + this->Internal->LinkOptionsEntries.push_back(value); + cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); + this->Internal->LinkOptionsBacktraces.push_back(lfbt); + } + } else if (prop == "LINK_DIRECTORIES") { + if (value && *value) { + this->Internal->LinkDirectoriesEntries.push_back(value); + cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); + this->Internal->LinkDirectoriesBacktraces.push_back(lfbt); + } } else if (prop == "LINK_LIBRARIES") { if (value && *value) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); @@ -1063,10 +1181,11 @@ void cmTarget::AppendBuildInterfaceIncludes() this->BuildInterfaceIncludesAppended = true; if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")) { - const char* binDir = this->Makefile->GetCurrentBinaryDirectory(); - const char* srcDir = this->Makefile->GetCurrentSourceDirectory(); - const std::string dirs = std::string(binDir ? binDir : "") + - std::string(binDir ? ";" : "") + std::string(srcDir ? srcDir : ""); + std::string dirs = this->Makefile->GetCurrentBinaryDirectory(); + if (!dirs.empty()) { + dirs += ';'; + } + dirs += this->Makefile->GetCurrentSourceDirectory(); if (!dirs.empty()) { this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", ("$<BUILD_INTERFACE:" + dirs + ">").c_str()); @@ -1111,6 +1230,36 @@ void cmTarget::InsertCompileDefinition(std::string const& entry, this->Internal->CompileDefinitionsBacktraces.push_back(bt); } +void cmTarget::InsertLinkOption(std::string const& entry, + cmListFileBacktrace const& bt, bool before) +{ + std::vector<std::string>::iterator position = before + ? this->Internal->LinkOptionsEntries.begin() + : this->Internal->LinkOptionsEntries.end(); + + std::vector<cmListFileBacktrace>::iterator btPosition = before + ? this->Internal->LinkOptionsBacktraces.begin() + : this->Internal->LinkOptionsBacktraces.end(); + + this->Internal->LinkOptionsEntries.insert(position, entry); + this->Internal->LinkOptionsBacktraces.insert(btPosition, bt); +} + +void cmTarget::InsertLinkDirectory(std::string const& entry, + cmListFileBacktrace const& bt, bool before) +{ + std::vector<std::string>::iterator position = before + ? this->Internal->LinkDirectoriesEntries.begin() + : this->Internal->LinkDirectoriesEntries.end(); + + std::vector<cmListFileBacktrace>::iterator btPosition = before + ? this->Internal->LinkDirectoriesBacktraces.begin() + : this->Internal->LinkDirectoriesBacktraces.end(); + + this->Internal->LinkDirectoriesEntries.insert(position, entry); + this->Internal->LinkDirectoriesBacktraces.insert(btPosition, bt); +} + static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop, const char* value, cmMakefile* context, @@ -1230,6 +1379,8 @@ const char* cmTarget::GetProperty(const std::string& prop) const MAKE_STATIC_PROP(COMPILE_FEATURES); MAKE_STATIC_PROP(COMPILE_OPTIONS); MAKE_STATIC_PROP(COMPILE_DEFINITIONS); + MAKE_STATIC_PROP(LINK_OPTIONS); + MAKE_STATIC_PROP(LINK_DIRECTORIES); MAKE_STATIC_PROP(IMPORTED); MAKE_STATIC_PROP(IMPORTED_GLOBAL); MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES); @@ -1245,6 +1396,8 @@ const char* cmTarget::GetProperty(const std::string& prop) const specialProps.insert(propCOMPILE_FEATURES); specialProps.insert(propCOMPILE_OPTIONS); specialProps.insert(propCOMPILE_DEFINITIONS); + specialProps.insert(propLINK_OPTIONS); + specialProps.insert(propLINK_DIRECTORIES); specialProps.insert(propIMPORTED); specialProps.insert(propIMPORTED_GLOBAL); specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES); @@ -1303,6 +1456,25 @@ const char* cmTarget::GetProperty(const std::string& prop) const output = cmJoin(this->Internal->CompileDefinitionsEntries, ";"); return output.c_str(); } + if (prop == propLINK_OPTIONS) { + if (this->Internal->LinkOptionsEntries.empty()) { + return nullptr; + } + + static std::string output; + output = cmJoin(this->Internal->LinkOptionsEntries, ";"); + return output.c_str(); + } + if (prop == propLINK_DIRECTORIES) { + if (this->Internal->LinkDirectoriesEntries.empty()) { + return nullptr; + } + + static std::string output; + output = cmJoin(this->Internal->LinkDirectoriesEntries, ";"); + + return output.c_str(); + } if (prop == propMANUALLY_ADDED_DEPENDENCIES) { if (this->Utilities.empty()) { return nullptr; @@ -1325,13 +1497,15 @@ const char* cmTarget::GetProperty(const std::string& prop) const return this->GetMakefile() ->GetStateSnapshot() .GetDirectory() - .GetCurrentBinary(); + .GetCurrentBinary() + .c_str(); } if (prop == propSOURCE_DIR) { return this->GetMakefile() ->GetStateSnapshot() .GetDirectory() - .GetCurrentSource(); + .GetCurrentSource() + .c_str(); } } @@ -1347,6 +1521,15 @@ const char* cmTarget::GetProperty(const std::string& prop) const return retVal; } +const char* cmTarget::GetSafeProperty(const std::string& prop) const +{ + const char* ret = this->GetProperty(prop); + if (!ret) { + return ""; + } + return ret; +} + bool cmTarget::GetPropertyAsBool(const std::string& prop) const { return cmSystemTools::IsOn(this->GetProperty(prop)); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 3abb47ed1..694de1c3c 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -142,6 +142,9 @@ public: void AddLinkLibrary(cmMakefile& mf, const std::string& lib, cmTargetLinkLibraryType llt); + void AddLinkLibrary(cmMakefile& mf, std::string const& lib, + std::string const& libRef, cmTargetLinkLibraryType llt); + enum TLLSignature { KeywordTLLSignature, @@ -151,10 +154,6 @@ public: cmListFileContext const& lfc); void GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const; - const std::vector<std::string>& GetLinkDirectories() const; - - void AddLinkDirectory(const std::string& d); - /** * Set the path where this target should be installed. This is relative to * INSTALL_PREFIX @@ -200,7 +199,10 @@ public: void SetProperty(const std::string& prop, const char* value); void AppendProperty(const std::string& prop, const char* value, bool asString = false); + ///! Might return a nullptr if the property is not set or invalid const char* GetProperty(const std::string& prop) const; + ///! Always returns a valid pointer + const char* GetSafeProperty(const std::string& prop) const; bool GetPropertyAsBool(const std::string& prop) const; void CheckProperty(const std::string& prop, cmMakefile* context) const; const char* GetComputedProperty(const std::string& prop, @@ -239,6 +241,10 @@ public: cmListFileBacktrace const& bt, bool before = false); void InsertCompileDefinition(std::string const& entry, cmListFileBacktrace const& bt); + void InsertLinkOption(std::string const& entry, + cmListFileBacktrace const& bt, bool before = false); + void InsertLinkDirectory(std::string const& entry, + cmListFileBacktrace const& bt, bool before = false); void AppendBuildInterfaceIncludes(); @@ -265,6 +271,13 @@ public: cmStringRange GetSourceEntries() const; cmBacktraceRange GetSourceBacktraces() const; + + cmStringRange GetLinkOptionsEntries() const; + cmBacktraceRange GetLinkOptionsBacktraces() const; + + cmStringRange GetLinkDirectoriesEntries() const; + cmBacktraceRange GetLinkDirectoriesBacktraces() const; + cmStringRange GetLinkImplementationEntries() const; cmBacktraceRange GetLinkImplementationBacktraces() const; @@ -294,14 +307,12 @@ private: bool IsGeneratorProvided; cmPropertyMap Properties; std::set<std::string> SystemIncludeDirectories; - std::set<std::string> LinkDirectoriesEmmitted; std::set<std::string> Utilities; std::map<std::string, cmListFileBacktrace> UtilityBacktraces; cmPolicies::PolicyMap PolicyMap; std::string Name; std::string InstallPath; std::string RuntimeInstallPath; - std::vector<std::string> LinkDirectories; std::vector<cmCustomCommand> PreBuildCommands; std::vector<cmCustomCommand> PreLinkCommands; std::vector<cmCustomCommand> PostBuildCommands; diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index fc546cc3c..af142aa97 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -35,8 +35,7 @@ std::string cmTargetIncludeDirectoriesCommand::Join( { std::string dirs; std::string sep; - std::string prefix = - this->Makefile->GetCurrentSourceDirectory() + std::string("/"); + std::string prefix = this->Makefile->GetCurrentSourceDirectory() + "/"; for (std::string const& it : content) { if (cmSystemTools::FileIsFullPath(it) || cmGeneratorExpression::Find(it) == 0) { @@ -56,8 +55,7 @@ bool cmTargetIncludeDirectoriesCommand::HandleDirectContent( cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); tgt->InsertInclude(this->Join(content), lfbt, prepend); if (system) { - std::string prefix = - this->Makefile->GetCurrentSourceDirectory() + std::string("/"); + std::string prefix = this->Makefile->GetCurrentSourceDirectory() + "/"; std::set<std::string> sdirs; for (std::string const& it : content) { if (cmSystemTools::FileIsFullPath(it) || diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx new file mode 100644 index 000000000..bca3e45dd --- /dev/null +++ b/Source/cmTargetLinkDirectoriesCommand.cxx @@ -0,0 +1,61 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmTargetLinkDirectoriesCommand.h" + +#include <sstream> + +#include "cmAlgorithms.h" +#include "cmGeneratorExpression.h" +#include "cmListFileCache.h" +#include "cmMakefile.h" +#include "cmSystemTools.h" +#include "cmTarget.h" +#include "cmake.h" + +class cmExecutionStatus; + +bool cmTargetLinkDirectoriesCommand::InitialPass( + std::vector<std::string> const& args, cmExecutionStatus&) +{ + return this->HandleArguments(args, "LINK_DIRECTORIES", PROCESS_BEFORE); +} + +void cmTargetLinkDirectoriesCommand::HandleMissingTarget( + const std::string& name) +{ + std::ostringstream e; + e << "Cannot specify link directories for target \"" << name + << "\" which is not built by this project."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +std::string cmTargetLinkDirectoriesCommand::Join( + const std::vector<std::string>& content) +{ + std::vector<std::string> directories; + + for (const auto& dir : content) { + auto unixPath = dir; + cmSystemTools::ConvertToUnixSlashes(unixPath); + if (!cmSystemTools::FileIsFullPath(unixPath) && + !cmGeneratorExpression::StartsWithGeneratorExpression(unixPath)) { + auto tmp = this->Makefile->GetCurrentSourceDirectory(); + tmp += "/"; + tmp += unixPath; + unixPath = tmp; + } + directories.push_back(unixPath); + } + + return cmJoin(directories, ";"); +} + +bool cmTargetLinkDirectoriesCommand::HandleDirectContent( + cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool) +{ + cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); + + tgt->InsertLinkDirectory(this->Join(content), lfbt, prepend); + + return true; // Successfully handled. +} diff --git a/Source/cmTargetLinkDirectoriesCommand.h b/Source/cmTargetLinkDirectoriesCommand.h new file mode 100644 index 000000000..52c75a0b9 --- /dev/null +++ b/Source/cmTargetLinkDirectoriesCommand.h @@ -0,0 +1,41 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmTargetLinkDirectoriesCommand_h +#define cmTargetLinkDirectoriesCommand_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <string> +#include <vector> + +#include "cmTargetPropCommandBase.h" + +class cmCommand; +class cmExecutionStatus; +class cmTarget; + +class cmTargetLinkDirectoriesCommand : public cmTargetPropCommandBase +{ +public: + /** + * This is a virtual constructor for the command. + */ + cmCommand* Clone() override { return new cmTargetLinkDirectoriesCommand; } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + bool InitialPass(std::vector<std::string> const& args, + cmExecutionStatus& status) override; + +private: + void HandleMissingTarget(const std::string& name) override; + + std::string Join(const std::vector<std::string>& content) override; + bool HandleDirectContent(cmTarget* tgt, + const std::vector<std::string>& content, + bool prepend, bool system) override; +}; + +#endif diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 1bbcf4692..ad33f9850 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -359,30 +359,53 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, } } + bool warnRemoteInterface = false; + bool rejectRemoteLinking = false; + bool encodeRemoteReference = false; + if (this->Makefile != this->Target->GetMakefile()) { + // The LHS target was created in another directory. + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0079)) { + case cmPolicies::WARN: + warnRemoteInterface = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + rejectRemoteLinking = true; + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + encodeRemoteReference = true; + break; + } + } + + std::string libRef; + if (encodeRemoteReference && !cmSystemTools::FileIsFullPath(lib)) { + // This is a library name added by a caller that is not in the + // same directory as the target was created. Add a suffix to + // the name to tell ResolveLinkItem to look up the name in the + // caller's directory. + cmDirectoryId const dirId = this->Makefile->GetDirectoryId(); + libRef = lib + CMAKE_DIRECTORY_ID_SEP + dirId.String; + } else { + // This is an absolute path or a library name added by a caller + // in the same directory as the target was created. We can use + // the original name directly. + libRef = lib; + } + // Handle normal case where the command was called with another keyword than // INTERFACE / LINK_INTERFACE_LIBRARIES or none at all. (The "LINK_LIBRARIES" // property of the target on the LHS shall be populated.) if (this->CurrentProcessingState != ProcessingKeywordLinkInterface && this->CurrentProcessingState != ProcessingPlainLinkInterface) { - // Assure that the target on the LHS was created in the current directory. - cmTarget* t = - this->Makefile->FindLocalNonAliasTarget(this->Target->GetName()); - if (!t) { - const std::vector<cmTarget*>& importedTargets = - this->Makefile->GetOwnedImportedTargets(); - for (cmTarget* importedTarget : importedTargets) { - if (importedTarget->GetName() == this->Target->GetName()) { - t = importedTarget; - break; - } - } - } - if (!t) { + if (rejectRemoteLinking) { std::ostringstream e; e << "Attempt to add link library \"" << lib << "\" to target \"" << this->Target->GetName() - << "\" which is not built in this directory."; + << "\" which is not built in this directory.\n" + << "This is allowed only when policy CMP0079 is set to NEW."; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return false; } @@ -404,7 +427,20 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); } - this->Target->AddLinkLibrary(*this->Makefile, lib, llt); + this->Target->AddLinkLibrary(*this->Makefile, lib, libRef, llt); + } + + if (warnRemoteInterface) { + std::ostringstream w; + /* clang-format off */ + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0079) << "\n" + "Target\n " << this->Target->GetName() << "\nis not created in this " + "directory. For compatibility with older versions of CMake, link " + "library\n " << lib << "\nwill be looked up in the directory in " + "which the target was created rather than in this calling " + "directory."; + /* clang-format on */ + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); } // Handle (additional) case where the command was called with PRIVATE / @@ -415,9 +451,9 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, this->CurrentProcessingState == ProcessingPlainPrivateInterface) { if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY) { std::string configLib = - this->Target->GetDebugGeneratorExpressions(lib, llt); - if (cmGeneratorExpression::IsValidTargetName(lib) || - cmGeneratorExpression::Find(lib) != std::string::npos) { + this->Target->GetDebugGeneratorExpressions(libRef, llt); + if (cmGeneratorExpression::IsValidTargetName(libRef) || + cmGeneratorExpression::Find(libRef) != std::string::npos) { configLib = "$<LINK_ONLY:" + configLib + ">"; } this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES", @@ -431,7 +467,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, // property of the target on the LHS shall be populated.) this->Target->AppendProperty( "INTERFACE_LINK_LIBRARIES", - this->Target->GetDebugGeneratorExpressions(lib, llt).c_str()); + this->Target->GetDebugGeneratorExpressions(libRef, llt).c_str()); // Stop processing if called without any keyword. if (this->CurrentProcessingState == ProcessingLinkLibraries) { @@ -464,12 +500,12 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, for (std::string const& dc : debugConfigs) { prop = "LINK_INTERFACE_LIBRARIES_"; prop += dc; - this->Target->AppendProperty(prop, lib.c_str()); + this->Target->AppendProperty(prop, libRef.c_str()); } } if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) { // Put in the non-DEBUG configuration interfaces. - this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib.c_str()); + this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef.c_str()); // Make sure the DEBUG configuration interfaces exist so that the // general one will not be used as a fall-back. diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx new file mode 100644 index 000000000..d6ed5ae6e --- /dev/null +++ b/Source/cmTargetLinkOptionsCommand.cxx @@ -0,0 +1,41 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmTargetLinkOptionsCommand.h" + +#include <sstream> + +#include "cmAlgorithms.h" +#include "cmListFileCache.h" +#include "cmMakefile.h" +#include "cmTarget.h" +#include "cmake.h" + +class cmExecutionStatus; + +bool cmTargetLinkOptionsCommand::InitialPass( + std::vector<std::string> const& args, cmExecutionStatus&) +{ + return this->HandleArguments(args, "LINK_OPTIONS", PROCESS_BEFORE); +} + +void cmTargetLinkOptionsCommand::HandleMissingTarget(const std::string& name) +{ + std::ostringstream e; + e << "Cannot specify link options for target \"" << name + << "\" which is not built by this project."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +std::string cmTargetLinkOptionsCommand::Join( + const std::vector<std::string>& content) +{ + return cmJoin(content, ";"); +} + +bool cmTargetLinkOptionsCommand::HandleDirectContent( + cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool) +{ + cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); + tgt->InsertLinkOption(this->Join(content), lfbt, prepend); + return true; // Successfully handled. +} diff --git a/Source/cmTargetLinkOptionsCommand.h b/Source/cmTargetLinkOptionsCommand.h new file mode 100644 index 000000000..a1fc9fc2e --- /dev/null +++ b/Source/cmTargetLinkOptionsCommand.h @@ -0,0 +1,41 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmTargetLinkOptionsCommand_h +#define cmTargetLinkOptionsCommand_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <string> +#include <vector> + +#include "cmTargetPropCommandBase.h" + +class cmCommand; +class cmExecutionStatus; +class cmTarget; + +class cmTargetLinkOptionsCommand : public cmTargetPropCommandBase +{ +public: + /** + * This is a virtual constructor for the command. + */ + cmCommand* Clone() override { return new cmTargetLinkOptionsCommand; } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + bool InitialPass(std::vector<std::string> const& args, + cmExecutionStatus& status) override; + +private: + void HandleMissingTarget(const std::string& name) override; + + bool HandleDirectContent(cmTarget* tgt, + const std::vector<std::string>& content, + bool prepend, bool system) override; + std::string Join(const std::vector<std::string>& content) override; +}; + +#endif diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index 3dd374879..7429053ea 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -5,7 +5,10 @@ #include <sstream> #include "cmAlgorithms.h" +#include "cmGeneratorExpression.h" #include "cmMakefile.h" +#include "cmPolicies.h" +#include "cmSystemTools.h" #include "cmTarget.h" #include "cmake.h" @@ -17,6 +20,14 @@ bool cmTargetSourcesCommand::InitialPass(std::vector<std::string> const& args, return this->HandleArguments(args, "SOURCES"); } +void cmTargetSourcesCommand::HandleInterfaceContent( + cmTarget* tgt, const std::vector<std::string>& content, bool prepend, + bool system) +{ + cmTargetPropCommandBase::HandleInterfaceContent( + tgt, ConvertToAbsoluteContent(tgt, content, true), prepend, system); +} + void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name) { std::ostringstream e; @@ -35,6 +46,79 @@ std::string cmTargetSourcesCommand::Join( bool cmTargetSourcesCommand::HandleDirectContent( cmTarget* tgt, const std::vector<std::string>& content, bool, bool) { - tgt->AppendProperty("SOURCES", this->Join(content).c_str()); + tgt->AppendProperty( + "SOURCES", + this->Join(ConvertToAbsoluteContent(tgt, content, false)).c_str()); return true; // Successfully handled. } + +std::vector<std::string> cmTargetSourcesCommand::ConvertToAbsoluteContent( + cmTarget* tgt, const std::vector<std::string>& content, + bool isInterfaceContent) +{ + // Skip conversion in case old behavior has been explicitly requested + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076) == + cmPolicies::OLD) { + return content; + } + + bool changedPath = false; + std::vector<std::string> absoluteContent; + absoluteContent.reserve(content.size()); + for (std::string const& src : content) { + std::string absoluteSrc; + if (cmSystemTools::FileIsFullPath(src) || + cmGeneratorExpression::Find(src) == 0 || + (!isInterfaceContent && + (this->Makefile->GetCurrentSourceDirectory() == + tgt->GetMakefile()->GetCurrentSourceDirectory()))) { + absoluteSrc = src; + } else { + changedPath = true; + absoluteSrc = this->Makefile->GetCurrentSourceDirectory(); + absoluteSrc += "/"; + absoluteSrc += src; + } + absoluteContent.push_back(absoluteSrc); + } + + if (!changedPath) { + return content; + } + + bool issueMessage = true; + bool useAbsoluteContent = false; + std::ostringstream e; + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076)) { + case cmPolicies::WARN: + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0076) << "\n"; + break; + case cmPolicies::OLD: + issueMessage = false; + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076)); + break; + case cmPolicies::NEW: { + issueMessage = false; + useAbsoluteContent = true; + break; + } + } + + if (issueMessage) { + if (isInterfaceContent) { + e << "An interface source of target \"" << tgt->GetName() + << "\" has a relative path."; + } else { + e << "A private source from a directory other than that of target \"" + << tgt->GetName() << "\" has a relative path."; + } + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + } + + return useAbsoluteContent ? absoluteContent : content; +} diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h index ea8776abb..b01e3ca25 100644 --- a/Source/cmTargetSourcesCommand.h +++ b/Source/cmTargetSourcesCommand.h @@ -29,6 +29,11 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; +protected: + void HandleInterfaceContent(cmTarget* tgt, + const std::vector<std::string>& content, + bool prepend, bool system) override; + private: void HandleMissingTarget(const std::string& name) override; @@ -37,6 +42,10 @@ private: bool prepend, bool system) override; std::string Join(const std::vector<std::string>& content) override; + + std::vector<std::string> ConvertToAbsoluteContent( + cmTarget* tgt, const std::vector<std::string>& content, + bool isInterfaceContent); }; #endif diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index c532efb81..796d2df64 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -103,7 +103,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, } } else { // Use the command name given. - exe = ge.Parse(exe.c_str())->Evaluate(this->LG, config); + exe = ge.Parse(exe)->Evaluate(this->LG, config); cmSystemTools::ConvertToUnixSlashes(exe); } diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 14cf6e964..da5d21ebb 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -96,7 +96,7 @@ time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const // From Linux timegm() manpage. std::string tz_old; - cmSystemTools::GetEnv("TZ", tz_old); + bool const tz_was_set = cmSystemTools::GetEnv("TZ", tz_old); tz_old = "TZ=" + tz_old; // The standard says that "TZ=" or "TZ=[UNRECOGNIZED_TZ]" means UTC. @@ -109,7 +109,17 @@ time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const time_t result = mktime(&tm); +# ifdef CMAKE_BUILD_WITH_CMAKE + if (tz_was_set) { + cmSystemTools::PutEnv(tz_old); + } else { + cmSystemTools::UnsetEnv("TZ"); + } +# else + // No UnsetEnv during bootstrap. This is good enough for CMake itself. cmSystemTools::PutEnv(tz_old); + static_cast<void>(tz_was_set); +# endif tzset(); diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h index fbe0d78b6..82378780e 100644 --- a/Source/cmTryCompileCommand.h +++ b/Source/cmTryCompileCommand.h @@ -16,7 +16,7 @@ class cmExecutionStatus; /** \class cmTryCompileCommand * \brief Specifies where to install some files * - * cmTryCompileCommand is used to test if soucre code can be compiled + * cmTryCompileCommand is used to test if source code can be compiled */ class cmTryCompileCommand : public cmCoreTryCompile { diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h index b632ef580..c54622c63 100644 --- a/Source/cmTryRunCommand.h +++ b/Source/cmTryRunCommand.h @@ -16,7 +16,7 @@ class cmExecutionStatus; /** \class cmTryRunCommand * \brief Specifies where to install some files * - * cmTryRunCommand is used to test if soucre code can be compiled + * cmTryRunCommand is used to test if source code can be compiled */ class cmTryRunCommand : public cmCoreTryCompile { diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index ea012f6ca..01ef5cbea 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -82,12 +82,12 @@ void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader(const char* source, // regular expression for gl GL or xmesa in a file (match(1) of above) cmsys::RegularExpression glLine("(gl|GL|xmesa)"); while (cmSystemTools::GetLineFromStream(fin, inLine)) { - if (includeLine.find(inLine.c_str())) { + if (includeLine.find(inLine)) { std::string includeFile = includeLine.match(1); - if (glDirLine.find(includeFile.c_str())) { + if (glDirLine.find(includeFile)) { std::string gfile = glDirLine.match(3); fout << "#include \"" << outdir << "/" << gfile << "\"\n"; - } else if (glLine.find(includeFile.c_str())) { + } else if (glLine.find(includeFile)) { fout << "#include \"" << outdir << "/" << includeLine.match(1) << "\"\n"; } else { diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index a60163719..f37462644 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -28,7 +28,7 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args, // If it exists already and appears up to date then we are done. If // the string contains "(IntDir)" but that is not the // CMAKE_CFG_INTDIR setting then the value is out of date. - const char* intDir = + std::string const& intDir = this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR"); bool haveCacheValue = false; @@ -46,7 +46,7 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args, cmState* state = this->Makefile->GetState(); haveCacheValue = (cacheValue && (strstr(cacheValue, "(IntDir)") == nullptr || - (intDir && strcmp(intDir, "$(IntDir)") == 0)) && + (intDir == "$(IntDir)")) && (state->GetCacheMajorVersion() != 0 && state->GetCacheMinorVersion() != 0)); } diff --git a/Source/cmVS10CSharpFlagTable.h b/Source/cmVS10CSharpFlagTable.h index 18d587c50..6ac7a76ae 100644 --- a/Source/cmVS10CSharpFlagTable.h +++ b/Source/cmVS10CSharpFlagTable.h @@ -21,8 +21,8 @@ static cmVS7FlagTable cmVS10CSharpFlagTable[] = { { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable }, { "", "link", "", "", 0 }, - { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired }, - { "ApplicationIcon", "win32icon", "", "", + { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired }, + { "ApplicationIcon", "win32icon:", "", "", cmIDEFlagTable::UserValueRequired }, { "ApplicationManifest", "win32manifest:", "", "", diff --git a/Source/cmVS11CSharpFlagTable.h b/Source/cmVS11CSharpFlagTable.h index e3ba83c2c..18b804a63 100644 --- a/Source/cmVS11CSharpFlagTable.h +++ b/Source/cmVS11CSharpFlagTable.h @@ -21,8 +21,8 @@ static cmVS7FlagTable cmVS11CSharpFlagTable[] = { { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable }, { "", "link", "", "", 0 }, - { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired }, - { "ApplicationIcon", "win32icon", "", "", + { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired }, + { "ApplicationIcon", "win32icon:", "", "", cmIDEFlagTable::UserValueRequired }, { "ApplicationManifest", "win32manifest:", "", "", diff --git a/Source/cmVS12CSharpFlagTable.h b/Source/cmVS12CSharpFlagTable.h index f8db63670..0370499db 100644 --- a/Source/cmVS12CSharpFlagTable.h +++ b/Source/cmVS12CSharpFlagTable.h @@ -21,8 +21,8 @@ static cmVS7FlagTable cmVS12CSharpFlagTable[] = { { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable }, { "", "link", "", "", 0 }, - { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired }, - { "ApplicationIcon", "win32icon", "", "", + { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired }, + { "ApplicationIcon", "win32icon:", "", "", cmIDEFlagTable::UserValueRequired }, { "ApplicationManifest", "win32manifest:", "", "", diff --git a/Source/cmVS140CSharpFlagTable.h b/Source/cmVS140CSharpFlagTable.h index 055d5cba0..f695f4582 100644 --- a/Source/cmVS140CSharpFlagTable.h +++ b/Source/cmVS140CSharpFlagTable.h @@ -21,8 +21,8 @@ static cmVS7FlagTable cmVS140CSharpFlagTable[] = { { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable }, { "", "link", "", "", 0 }, - { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired }, - { "ApplicationIcon", "win32icon", "", "", + { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired }, + { "ApplicationIcon", "win32icon:", "", "", cmIDEFlagTable::UserValueRequired }, { "ApplicationManifest", "win32manifest:", "", "", diff --git a/Source/cmVS141CLFlagTable.h b/Source/cmVS141CLFlagTable.h index 7d3e35602..2a9944aab 100644 --- a/Source/cmVS141CLFlagTable.h +++ b/Source/cmVS141CLFlagTable.h @@ -83,6 +83,8 @@ static cmVS7FlagTable cmVS141CLFlagTable[] = { { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 }, { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 }, + { "SpectreMitigation", "Qspectre", "Spectre mitigations", "Spectre", 0 }, + { "LanguageStandard", "std:c++17", "ISO C++17 Standard", "stdcpp17", 0 }, { "LanguageStandard", "std:c++14", "ISO C++14 Standard", "stdcpp14", 0 }, { "LanguageStandard", "std:c++latest", "ISO C++ Latest Draft Standard", diff --git a/Source/cmVS141CSharpFlagTable.h b/Source/cmVS141CSharpFlagTable.h index 5de9bf33f..1f840970b 100644 --- a/Source/cmVS141CSharpFlagTable.h +++ b/Source/cmVS141CSharpFlagTable.h @@ -21,8 +21,8 @@ static cmVS7FlagTable cmVS141CSharpFlagTable[] = { { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable }, { "", "link", "", "", 0 }, - { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired }, - { "ApplicationIcon", "win32icon", "", "", + { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired }, + { "ApplicationIcon", "win32icon:", "", "", cmIDEFlagTable::UserValueRequired }, { "ApplicationManifest", "win32manifest:", "", "", @@ -76,7 +76,12 @@ static cmVS7FlagTable cmVS141CSharpFlagTable[] = { { "LangVersion", "langversion:4", "", "4", 0 }, { "LangVersion", "langversion:5", "", "5", 0 }, { "LangVersion", "langversion:6", "", "6", 0 }, + { "LangVersion", "langversion:7.0", "", "7.0", 0 }, + { "LangVersion", "langversion:7.1", "", "7.1", 0 }, + { "LangVersion", "langversion:7.2", "", "7.2", 0 }, + { "LangVersion", "langversion:7.3", "", "7.3", 0 }, { "LangVersion", "langversion:default", "", "default", 0 }, + { "LangVersion", "langversion:latest", "", "latest", 0 }, { "DelaySign", "delaysign", "", "true", 0 }, { "DelaySign", "delaysign-", "", "false", 0 }, diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index c455fa25c..334c15b45 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -249,11 +249,10 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator( this->TargetCompileAsWinRT = false; this->IsMissingFiles = false; this->DefaultArtifactDir = - this->LocalGenerator->GetCurrentBinaryDirectory() + std::string("/") + + this->LocalGenerator->GetCurrentBinaryDirectory() + "/" + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - this->InSourceBuild = - (strcmp(this->Makefile->GetCurrentSourceDirectory(), - this->Makefile->GetCurrentBinaryDirectory()) == 0); + this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() == + this->Makefile->GetCurrentBinaryDirectory()); } cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator() @@ -369,7 +368,7 @@ void cmVisualStudio10TargetGenerator::Generate() path += "/"; path += this->Name; path += ProjectFileExtension; - cmGeneratedFileStream BuildFileStream(path.c_str()); + cmGeneratedFileStream BuildFileStream(path); const std::string PathToProjectFile = path; BuildFileStream.SetCopyIfDifferent(true); @@ -721,8 +720,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) if (!name.empty()) { std::string path = i.second.GetValue(); if (!cmsys::SystemTools::FileIsFullPath(path)) { - path = std::string(this->Makefile->GetCurrentSourceDirectory()) + - "/" + path; + path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; } ConvertToWindowsSlash(path); this->DotNetHintReferences[""].push_back( @@ -928,8 +926,10 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0) e2.SetHasElements(); if (this->ProjectType == csproj && !this->InSourceBuild) { // add <Link> tag to written XAML source if necessary - const std::string srcDir = this->Makefile->GetCurrentSourceDirectory(); - const std::string binDir = this->Makefile->GetCurrentBinaryDirectory(); + const std::string& srcDir = + this->Makefile->GetCurrentSourceDirectory(); + const std::string& binDir = + this->Makefile->GetCurrentBinaryDirectory(); std::string link; if (obj.find(srcDir) == 0) { link = obj.substr(srcDir.length() + 1); @@ -1121,11 +1121,21 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) { e1.Element("WindowsAppContainer", "true"); } + if (this->IPOEnabledConfigurations.count(config) > 0) { + e1.Element("WholeProgramOptimization", "true"); + } + if (this->SpectreMitigationConfigurations.count(config) > 0) { + e1.Element("SpectreMitigation", "Spectre"); + } } void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( Elem& e1, std::string const& config) { + if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) { + return; + } + cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; Options& o = *(this->ClOptions[config]); @@ -1400,7 +1410,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() path += this->Name; path += computeProjectFileExtension(this->GeneratorTarget); path += ".filters"; - cmGeneratedFileStream fout(path.c_str()); + cmGeneratedFileStream fout(path); fout.SetCopyIfDifferent(true); char magic[] = { char(0xEF), char(0xBB), char(0xBF) }; fout.write(magic, 3); @@ -1744,10 +1754,8 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, e2.Element("Link", deployLocation + "\\%(FileName)%(Extension)"); } for (size_t i = 0; i != this->Configurations.size(); ++i) { - if (0 == - strcmp( - cge->Evaluate(this->LocalGenerator, this->Configurations[i]), - "1")) { + if (cge->Evaluate(this->LocalGenerator, this->Configurations[i]) == + "1") { e2.WritePlatformConfigTag("DeploymentContent", "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] + "|" + @@ -1795,9 +1803,9 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, ge.Parse(shaderEnableDebug); for (size_t i = 0; i != this->Configurations.size(); ++i) { - const char* enableDebug = + const std::string& enableDebug = cge->Evaluate(this->LocalGenerator, this->Configurations[i]); - if (strlen(enableDebug) > 0) { + if (!enableDebug.empty()) { e2.WritePlatformConfigTag( "EnableDebuggingInformation", "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] + @@ -1812,9 +1820,9 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, ge.Parse(shaderDisableOptimizations); for (size_t i = 0; i != this->Configurations.size(); ++i) { - const char* disableOptimizations = + const std::string& disableOptimizations = cge->Evaluate(this->LocalGenerator, this->Configurations[i]); - if (strlen(disableOptimizations) > 0) { + if (!disableOptimizations.empty()) { e2.WritePlatformConfigTag( "DisableOptimizations", "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] + @@ -1880,7 +1888,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2, std::string sourceRel = this->ConvertPath(sf->GetFullPath(), true); size_t const maxLen = 250; if (sf->GetCustomCommand() || - ((strlen(this->LocalGenerator->GetCurrentBinaryDirectory()) + 1 + + ((this->LocalGenerator->GetCurrentBinaryDirectory().length() + 1 + sourceRel.length()) <= maxLen)) { forceRelative = true; sourceFile = sourceRel; @@ -1889,7 +1897,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2, } } ConvertToWindowsSlash(sourceFile); - e2.StartElement(tool.c_str()); + e2.StartElement(tool); e2.Attribute("Include", sourceFile); ToolSource toolSource = { sf, forceRelative }; @@ -2117,8 +2125,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( flagtable = gg->GetCSharpFlagTable(); } cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->GeneratorTarget, config, - this->GeneratorTarget->GetName(), lang); + this->LocalGenerator, config, this->GeneratorTarget, lang); cmVS10GeneratorOptions clOptions( this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler, flagtable, this); @@ -2131,7 +2138,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( if (configDependentFlags) { clOptions.Parse(genexInterpreter.Evaluate(flags, "COMPILE_FLAGS")); } else { - clOptions.Parse(flags.c_str()); + clOptions.Parse(flags); } if (!options.empty()) { std::string expandedOptions; @@ -2142,7 +2149,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } else { this->LocalGenerator->AppendCompileOptions(expandedOptions, options); } - clOptions.Parse(expandedOptions.c_str()); + clOptions.Parse(expandedOptions); } if (clOptions.HasFlag("DisableSpecificWarnings")) { clOptions.AppendFlag("DisableSpecificWarnings", @@ -2288,14 +2295,51 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( if (const char* workingDir = this->GeneratorTarget->GetProperty( "VS_DEBUGGER_WORKING_DIRECTORY")) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(workingDir); + std::string genWorkingDir = + cge->Evaluate(this->LocalGenerator, config); + e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond, - workingDir); + genWorkingDir); + } + + if (const char* environment = + this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(environment); + std::string genEnvironment = + cge->Evaluate(this->LocalGenerator, config); + + e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond, + genEnvironment); } if (const char* debuggerCommand = this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) { + + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(debuggerCommand); + std::string genDebuggerCommand = + cge->Evaluate(this->LocalGenerator, config); + e1.WritePlatformConfigTag("LocalDebuggerCommand", cond, - debuggerCommand); + genDebuggerCommand); + } + + if (const char* commandArguments = this->GeneratorTarget->GetProperty( + "VS_DEBUGGER_COMMAND_ARGUMENTS")) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(commandArguments); + std::string genCommandArguments = + cge->Evaluate(this->LocalGenerator, config); + + e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond, + genCommandArguments); } std::string name = @@ -2334,9 +2378,11 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental( Options& linkOptions = *(this->LinkOptions[configName]); const std::string cond = this->CalcCondition(configName); - const char* incremental = linkOptions.GetFlag("LinkIncremental"); - e1.WritePlatformConfigTag("LinkIncremental", cond, - (incremental ? incremental : "true")); + if (this->IPOEnabledConfigurations.count(configName) == 0) { + const char* incremental = linkOptions.GetFlag("LinkIncremental"); + e1.WritePlatformConfigTag("LinkIncremental", cond, + (incremental ? incremental : "true")); + } linkOptions.RemoveFlag("LinkIncremental"); const char* manifest = linkOptions.GetFlag("GenerateManifest"); @@ -2436,7 +2482,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( baseFlagVar += "_FLAGS"; flags = this->Makefile->GetRequiredDefinition(baseFlagVar); std::string flagVar = - baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName); + baseFlagVar + "_" + cmSystemTools::UpperCase(configName); flags += " "; flags += this->Makefile->GetRequiredDefinition(flagVar); this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, @@ -2450,14 +2496,26 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( clOptions.AddFlag("CompileAs", "CompileAsCpp"); } - // Check IPO related warning/error. - this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName); + // Put the IPO enabled configurations into a set. + if (this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName)) { + this->IPOEnabledConfigurations.insert(configName); + } // Get preprocessor definitions for this directory. std::string defineFlags = this->Makefile->GetDefineFlags(); if (this->MSTools) { if (this->ProjectType == vcxproj) { clOptions.FixExceptionHandlingDefault(); + if (this->GlobalGenerator->GetVersion() >= + cmGlobalVisualStudioGenerator::VS15) { + // Toolsets that come with VS 2017 may now enable UseFullPaths + // by default and there is no negative /FC option that projects + // can use to switch it back. Older toolsets disable this by + // default anyway so this will not hurt them. If the project + // is using an explicit /FC option then parsing flags will + // replace this setting with "true" below. + clOptions.AddFlag("UseFullPaths", "false"); + } clOptions.AddFlag("PrecompiledHeader", "NotUsing"); std::string asmLocation = configName + "/"; clOptions.AddFlag("AssemblerListingLocation", asmLocation); @@ -2491,8 +2549,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } } - clOptions.Parse(flags.c_str()); - clOptions.Parse(defineFlags.c_str()); + clOptions.Parse(flags); + clOptions.Parse(defineFlags); std::vector<std::string> targetDefines; switch (this->ProjectType) { case vcxproj: @@ -2529,8 +2587,10 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } if (this->MSTools) { - // If we have the VS_WINRT_COMPONENT set then force Compile as WinRT. - if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) { + // If we have the VS_WINRT_COMPONENT or CMAKE_VS_WINRT_BY_DEFAULT + // set then force Compile as WinRT. + if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") || + this->Makefile->IsOn("CMAKE_VS_WINRT_BY_DEFAULT")) { clOptions.AddFlag("CompileAsWinRT", "true"); // For WinRT components, add the _WINRT_DLL define to produce a lib if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || @@ -2570,6 +2630,11 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } } + if (clOptions.HasFlag("SpectreMitigation")) { + this->SpectreMitigationConfigurations.insert(configName); + clOptions.RemoveFlag("SpectreMitigation"); + } + this->ClOptions[configName] = std::move(pOptions); return true; } @@ -2616,6 +2681,13 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( // Specify the compiler program database file if configured. std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName); if (!pdb.empty()) { + if (this->GlobalGenerator->IsCudaEnabled()) { + // CUDA does not quote paths with spaces correctly when forwarding + // this to the host compiler. Use a relative path to avoid spaces. + // FIXME: We can likely do this even when CUDA is not involved, + // but for now we will make a minimal change. + pdb = this->ConvertPath(pdb, true); + } ConvertToWindowsSlash(pdb); e2.Element("ProgramDataBaseFileName", pdb); } @@ -2653,13 +2725,11 @@ bool cmVisualStudio10TargetGenerator::ComputeRcOptions( Options& rcOptions = *pOptions; std::string CONFIG = cmSystemTools::UpperCase(configName); - std::string rcConfigFlagsVar = std::string("CMAKE_RC_FLAGS_") + CONFIG; - std::string flags = - std::string(this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS")) + - std::string(" ") + - std::string(this->Makefile->GetSafeDefinition(rcConfigFlagsVar)); + std::string rcConfigFlagsVar = "CMAKE_RC_FLAGS_" + CONFIG; + std::string flags = this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS") + + " " + this->Makefile->GetSafeDefinition(rcConfigFlagsVar); - rcOptions.Parse(flags.c_str()); + rcOptions.Parse(flags); // For historical reasons, add the C preprocessor defines to RC. Options& clOptions = *(this->ClOptions[configName]); @@ -2711,18 +2781,16 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( // Get compile flags for CUDA in this directory. std::string CONFIG = cmSystemTools::UpperCase(configName); std::string configFlagsVar = std::string("CMAKE_CUDA_FLAGS_") + CONFIG; - std::string flags = - std::string(this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS")) + - std::string(" ") + - std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + std::string flags = this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS") + + " " + this->Makefile->GetSafeDefinition(configFlagsVar); this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA", configName); // Get preprocessor definitions for this directory. std::string defineFlags = this->Makefile->GetDefineFlags(); - cudaOptions.Parse(flags.c_str()); - cudaOptions.Parse(defineFlags.c_str()); + cudaOptions.Parse(flags); + cudaOptions.Parse(defineFlags); cudaOptions.ParseFinish(); // If we haven't explicitly enabled GPU debug information @@ -2760,15 +2828,19 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( // Specify the compiler program database file if configured. std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName); if (!pdb.empty()) { - // CUDA does not have a field for this and does not honor the - // ProgramDataBaseFileName field in ClCompile. Work around this - // limitation by creating the directory and passing the flag ourselves. + // CUDA does not make the directory if it is non-standard. std::string const pdbDir = cmSystemTools::GetFilenamePath(pdb); cmSystemTools::MakeDirectory(pdbDir); - pdb = this->ConvertPath(pdb, true); - ConvertToWindowsSlash(pdb); - std::string const clFd = "-Xcompiler=\"-Fd\\\"" + pdb + "\\\"\""; - cudaOptions.AppendFlagString("AdditionalOptions", clFd); + if (cmSystemTools::VersionCompareGreaterEq( + "9.2", this->GlobalGenerator->GetPlatformToolsetCudaString())) { + // CUDA does not have a field for this and does not honor the + // ProgramDataBaseFileName field in ClCompile. Work around this + // limitation by creating the directory and passing the flag ourselves. + pdb = this->ConvertPath(pdb, true); + ConvertToWindowsSlash(pdb); + std::string const clFd = "-Xcompiler=\"-Fd\\\"" + pdb + "\\\"\""; + cudaOptions.AppendFlagString("AdditionalOptions", clFd); + } } // CUDA automatically passes the proper '--machine' flag to nvcc @@ -2925,11 +2997,10 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions( std::string CONFIG = cmSystemTools::UpperCase(configName); std::string configFlagsVar = std::string("CMAKE_ASM_MASM_FLAGS_") + CONFIG; std::string flags = - std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_MASM_FLAGS")) + - std::string(" ") + - std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + this->Makefile->GetSafeDefinition("CMAKE_ASM_MASM_FLAGS") + " " + + this->Makefile->GetSafeDefinition(configFlagsVar); - masmOptions.Parse(flags.c_str()); + masmOptions.Parse(flags); // Get includes for this target masmOptions.AddIncludes(this->GetIncludes(configName, "ASM_MASM")); @@ -2978,15 +3049,12 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions( Options& nasmOptions = *pOptions; std::string CONFIG = cmSystemTools::UpperCase(configName); - std::string configFlagsVar = std::string("CMAKE_ASM_NASM_FLAGS_") + CONFIG; + std::string configFlagsVar = "CMAKE_ASM_NASM_FLAGS_" + CONFIG; std::string flags = - std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_FLAGS")) + - std::string(" -f") + - std::string( - this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT")) + - std::string(" ") + - std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); - nasmOptions.Parse(flags.c_str()); + this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_FLAGS") + " -f" + + this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT") + " " + + this->Makefile->GetSafeDefinition(configFlagsVar); + nasmOptions.Parse(flags); // Get includes for this target nasmOptions.AddIncludes(this->GetIncludes(configName, "ASM_NASM")); @@ -3023,16 +3091,21 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions( this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) { return; } + + const std::string& linkLanguage = + this->GeneratorTarget->GetLinkClosure(config)->LinkerLanguage; + std::string libflags; this->LocalGenerator->GetStaticLibraryFlags( - libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget); + libflags, cmSystemTools::UpperCase(config), linkLanguage, + this->GeneratorTarget); if (!libflags.empty()) { Elem e2(e1, "Lib"); cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; cmVS10GeneratorOptions libOptions(this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker, gg->GetLibFlagTable(), this); - libOptions.Parse(libflags.c_str()); + libOptions.Parse(libflags); OptionsHelper oh(libOptions, e2); oh.PrependInheritedString("AdditionalOptions"); oh.OutputFlagMap(); @@ -3239,6 +3312,11 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( flags += flagsConfig; } + std::vector<std::string> opts; + this->GeneratorTarget->GetLinkOptions(opts, config, linkLanguage); + // LINK_OPTIONS are escaped. + this->LocalGenerator->AppendCompileOptions(flags, opts); + cmComputeLinkInformation* pcli = this->GeneratorTarget->GetLinkInformation(config); if (!pcli) { @@ -3373,7 +3451,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( linkOptions.AddFlag("SoName", targetNameSO); } - linkOptions.Parse(flags.c_str()); + linkOptions.Parse(flags); linkOptions.FixManifestUACFlags(); if (this->MSTools) { @@ -3740,31 +3818,29 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) e2.Element("Project", "{" + this->GlobalGenerator->GetGUID(name) + "}"); e2.Element("Name", name); this->WriteDotNetReferenceCustomTags(e2, name); - if (this->Managed) { - // If the dependency target is not managed (compiled with /clr or - // C# target) we cannot reference it and have to set - // 'ReferenceOutputAssembly' to false. - auto referenceNotManaged = - dt->GetManagedType("") < cmGeneratorTarget::ManagedType::Mixed; - // Workaround to check for manually set /clr flags. - if (referenceNotManaged) { - if (const auto* flags = dt->GetProperty("COMPILE_OPTIONS")) { - std::string flagsStr = flags; - if (flagsStr.find("clr") != std::string::npos) { - // There is a warning already issued when building the flags. - referenceNotManaged = false; - } + + // If the dependency target is not managed (compiled with /clr or + // C# target) we cannot reference it and have to set + // 'ReferenceOutputAssembly' to false. + auto referenceNotManaged = + dt->GetManagedType("") < cmGeneratorTarget::ManagedType::Mixed; + // Workaround to check for manually set /clr flags. + if (referenceNotManaged) { + if (const auto* flags = dt->GetProperty("COMPILE_OPTIONS")) { + std::string flagsStr = flags; + if (flagsStr.find("clr") != std::string::npos) { + // There is a warning already issued when building the flags. + referenceNotManaged = false; } } - // Workaround for static library C# targets - if (referenceNotManaged && - dt->GetType() == cmStateEnums::STATIC_LIBRARY) { - referenceNotManaged = !dt->IsCSharpOnly(); - } - if (referenceNotManaged) { - e2.Element("ReferenceOutputAssembly", "false"); - e2.Element("CopyToOutputDirectory", "Never"); - } + } + // Workaround for static library C# targets + if (referenceNotManaged && dt->GetType() == cmStateEnums::STATIC_LIBRARY) { + referenceNotManaged = !dt->IsCSharpOnly(); + } + if (referenceNotManaged) { + e2.Element("ReferenceOutputAssembly", "false"); + e2.Element("CopyToOutputDirectory", "Never"); } } } @@ -4094,8 +4170,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80(Elem& e1) // this can cause an overwrite problem if projects aren't organized in // folders std::string manifestFile = - this->LocalGenerator->GetCurrentBinaryDirectory() + - std::string("/WMAppManifest.xml"); + this->LocalGenerator->GetCurrentBinaryDirectory() + "/WMAppManifest.xml"; std::string artifactDir = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); ConvertToWindowsSlash(artifactDir); @@ -4103,7 +4178,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80(Elem& e1) std::string targetNameXML = cmVS10EscapeXML(this->GeneratorTarget->GetName()); - cmGeneratedFileStream fout(manifestFile.c_str()); + cmGeneratedFileStream fout(manifestFile); fout.SetCopyIfDifferent(true); /* clang-format off */ @@ -4186,7 +4261,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81(Elem& e1) std::string targetNameXML = cmVS10EscapeXML(this->GeneratorTarget->GetName()); - cmGeneratedFileStream fout(manifestFile.c_str()); + cmGeneratedFileStream fout(manifestFile); fout.SetCopyIfDifferent(true); /* clang-format off */ @@ -4249,7 +4324,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80(Elem& e1) std::string targetNameXML = cmVS10EscapeXML(this->GeneratorTarget->GetName()); - cmGeneratedFileStream fout(manifestFile.c_str()); + cmGeneratedFileStream fout(manifestFile); fout.SetCopyIfDifferent(true); /* clang-format off */ @@ -4304,7 +4379,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81(Elem& e1) std::string targetNameXML = cmVS10EscapeXML(this->GeneratorTarget->GetName()); - cmGeneratedFileStream fout(manifestFile.c_str()); + cmGeneratedFileStream fout(manifestFile); fout.SetCopyIfDifferent(true); /* clang-format off */ @@ -4364,7 +4439,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0(Elem& e1) std::string targetNameXML = cmVS10EscapeXML(this->GeneratorTarget->GetName()); - cmGeneratedFileStream fout(manifestFile.c_str()); + cmGeneratedFileStream fout(manifestFile); fout.SetCopyIfDifferent(true); /* clang-format off */ @@ -4531,7 +4606,7 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceLink( std::string const& binaryDir = LocalGenerator->GetCurrentBinaryDirectory(); if (!cmSystemTools::IsSubDirectory(sourceFilePath, binaryDir)) { - const std::string stripFromPath = + const std::string& stripFromPath = this->Makefile->GetCurrentSourceDirectory(); if (sourceFilePath.find(stripFromPath) == 0) { if (const char* l = sf->GetProperty("VS_CSHARP_Link")) { diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 15e47b4b0..0dc03b655 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -204,6 +204,8 @@ private: bool NsightTegra; unsigned int NsightTegraVersion[4]; bool TargetCompileAsWinRT; + std::set<std::string> IPOEnabledConfigurations; + std::set<std::string> SpectreMitigationConfigurations; cmGlobalVisualStudio10Generator* const GlobalGenerator; cmLocalVisualStudio10Generator* const LocalGenerator; std::set<std::string> CSharpCustomCommandNames; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 4afef8b2f..5d67dcf51 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -297,12 +297,12 @@ void cmVisualStudioGeneratorOptions::FixManifestUACFlags() AddFlag(ENABLE_UAC, "true"); } -void cmVisualStudioGeneratorOptions::Parse(const char* flags) +void cmVisualStudioGeneratorOptions::Parse(const std::string& flags) { // Parse the input string as a windows command line since the string // is intended for writing directly into the build files. std::vector<std::string> args; - cmSystemTools::ParseWindowsCommandLine(flags, args); + cmSystemTools::ParseWindowsCommandLine(flags.c_str(), args); // Process flags that need to be represented specially in the IDE // project file. @@ -366,7 +366,7 @@ void cmVisualStudioGeneratorOptions::Reparse(std::string const& key) std::string const original = i->second[0]; i->second[0] = ""; this->UnknownFlagField = key; - this->Parse(original.c_str()); + this->Parse(original); } void cmVisualStudioGeneratorOptions::StoreUnknownFlag(std::string const& flag) diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index c6b594dbc..a30a67fc2 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -42,7 +42,7 @@ public: void ClearTables(); // Store options from command line flags. - void Parse(const char* flags); + void Parse(const std::string& flags); void ParseFinish(); void PrependInheritedString(std::string const& key); diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx index d3d2db09a..c504ef436 100644 --- a/Source/cmWriteFileCommand.cxx +++ b/Source/cmWriteFileCommand.cxx @@ -45,16 +45,20 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::MakeDirectory(dir); mode_t mode = 0; + bool writable = false; // Set permissions to writable if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) { - cmSystemTools::SetPermissions(fileName.c_str(), #if defined(_MSC_VER) || defined(__MINGW32__) - mode | S_IWRITE + writable = mode & S_IWRITE; + mode_t newMode = mode | S_IWRITE; #else - mode | S_IWUSR | S_IWGRP + writable = mode & S_IWUSR; + mode_t newMode = mode | S_IWUSR | S_IWGRP; #endif - ); + if (!writable) { + cmSystemTools::SetPermissions(fileName.c_str(), newMode); + } } // If GetPermissions fails, pretend like it is ok. File open will fail if // the file is not writable @@ -69,7 +73,7 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args, } file << message << std::endl; file.close(); - if (mode) { + if (mode && !writable) { cmSystemTools::SetPermissions(fileName.c_str(), mode); } diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index f1dce6420..58cb9c9d3 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -143,6 +143,41 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, xout.Attribute("debugServiceExtension", "internal"); xout.Attribute("allowLocationSimulation", "YES"); + // Diagnostics tab begin + + bool useAddressSanitizer = WriteLaunchActionAttribute( + xout, "enableAddressSanitizer", + "XCODE_SCHEME_ADDRESS_SANITIZER"); // not allowed with + // enableThreadSanitizer=YES + WriteLaunchActionAttribute( + xout, "enableASanStackUseAfterReturn", + "XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN"); + + bool useThreadSanitizer = false; + if (!useAddressSanitizer) { + useThreadSanitizer = WriteLaunchActionAttribute( + xout, "enableThreadSanitizer", + "XCODE_SCHEME_THREAD_SANITIZER"); // not allowed with + // enableAddressSanitizer=YES + } + + WriteLaunchActionAttribute(xout, "stopOnEveryThreadSanitizerIssue", + "XCODE_SCHEME_THREAD_SANITIZER_STOP"); + + WriteLaunchActionAttribute(xout, "enableUBSanitizer", + "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER"); + WriteLaunchActionAttribute( + xout, "stopOnEveryUBSanitizerIssue", + "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP"); + + WriteLaunchActionAttribute( + xout, "disableMainThreadChecker", + "XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER"); // negative enabled! + WriteLaunchActionAttribute(xout, "stopOnEveryMainThreadCheckerIssue", + "XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP"); + + // Diagnostics tab end + if (IsExecutable(this->Target)) { xout.StartElement("BuildableProductRunnable"); xout.BreakAttributes(); @@ -156,12 +191,144 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, xout.EndElement(); // MacroExpansion + // Info tab begin + + if (const char* exe = + this->Target->GetTarget()->GetProperty("XCODE_SCHEME_EXECUTABLE")) { + + xout.StartElement("PathRunnable"); + xout.BreakAttributes(); + + xout.Attribute("runnableDebuggingMode", "0"); + xout.Attribute("FilePath", exe); + + xout.EndElement(); // PathRunnable + } + + // Info tab end + + // Arguments tab begin + + if (const char* argList = + this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ARGUMENTS")) { + std::vector<std::string> arguments; + cmSystemTools::ExpandListArgument(argList, arguments); + if (!arguments.empty()) { + xout.StartElement("CommandLineArguments"); + + for (auto argument : arguments) { + xout.StartElement("CommandLineArgument"); + xout.BreakAttributes(); + + xout.Attribute("argument", argument); + xout.Attribute("isEnabled", "YES"); + + xout.EndElement(); // CommandLineArgument + } + + xout.EndElement(); // CommandLineArguments + } + } + + if (const char* envList = + this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ENVIRONMENT")) { + std::vector<std::string> envs; + cmSystemTools::ExpandListArgument(envList, envs); + if (!envs.empty()) { + xout.StartElement("EnvironmentVariables"); + + for (auto env : envs) { + + xout.StartElement("EnvironmentVariable"); + xout.BreakAttributes(); + + std::string envValue; + const auto p = env.find_first_of('='); + if (p != std::string::npos) { + envValue = env.substr(p + 1); + env.resize(p); + } + + xout.Attribute("key", env); + xout.Attribute("value", envValue); + xout.Attribute("isEnabled", "YES"); + + xout.EndElement(); // EnvironmentVariable + } + + xout.EndElement(); // EnvironmentVariables + } + } + + // Arguments tab end + xout.StartElement("AdditionalOptions"); + + if (!useThreadSanitizer) { + WriteLaunchActionAdditionalOption(xout, "MallocScribble", "", + "XCODE_SCHEME_MALLOC_SCRIBBLE"); + } + + if (!useThreadSanitizer && !useAddressSanitizer) { + WriteLaunchActionAdditionalOption(xout, "MallocGuardEdges", "", + "XCODE_SCHEME_MALLOC_GUARD_EDGES"); + } + + if (!useThreadSanitizer && !useAddressSanitizer) { + WriteLaunchActionAdditionalOption(xout, "DYLD_INSERT_LIBRARIES", + "/usr/lib/libgmalloc.dylib", + "XCODE_SCHEME_GUARD_MALLOC"); + } + + WriteLaunchActionAdditionalOption(xout, "NSZombieEnabled", "YES", + "XCODE_SCHEME_ZOMBIE_OBJECTS"); + + if (!useThreadSanitizer && !useAddressSanitizer) { + WriteLaunchActionAdditionalOption(xout, "MallocStackLogging", "", + "XCODE_SCHEME_MALLOC_STACK"); + } + + WriteLaunchActionAdditionalOption(xout, "DYLD_PRINT_APIS", "", + "XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE"); + + WriteLaunchActionAdditionalOption(xout, "DYLD_PRINT_LIBRARIES", "", + "XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS"); + xout.EndElement(); xout.EndElement(); // LaunchAction } +bool cmXCodeScheme::WriteLaunchActionAttribute(cmXMLWriter& xout, + const std::string& attrName, + const std::string& varName) +{ + if (Target->GetTarget()->GetPropertyAsBool(varName)) { + xout.Attribute(attrName.c_str(), "YES"); + return true; + } + return false; +} + +bool cmXCodeScheme::WriteLaunchActionAdditionalOption( + cmXMLWriter& xout, const std::string& key, const std::string& value, + const std::string& varName) +{ + if (Target->GetTarget()->GetPropertyAsBool(varName)) { + xout.StartElement("AdditionalOption"); + xout.BreakAttributes(); + + xout.Attribute("key", key); + xout.Attribute("value", value); + xout.Attribute("isEnabled", "YES"); + + xout.EndElement(); // AdditionalOption + + return true; + } + return false; +} + void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout, const std::string& configuration) { diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h index e5e501a6f..96c76e642 100644 --- a/Source/cmXCodeScheme.h +++ b/Source/cmXCodeScheme.h @@ -41,6 +41,16 @@ private: const std::string& container); void WriteLaunchAction(cmXMLWriter& xout, const std::string& configuration, const std::string& container); + + bool WriteLaunchActionAttribute(cmXMLWriter& xout, + const std::string& attrName, + const std::string& varName); + + bool WriteLaunchActionAdditionalOption(cmXMLWriter& xout, + const std::string& attrName, + const std::string& value, + const std::string& varName); + void WriteProfileAction(cmXMLWriter& xout, const std::string& configuration); void WriteAnalyzeAction(cmXMLWriter& xout, const std::string& configuration); void WriteArchiveAction(cmXMLWriter& xout, const std::string& configuration); diff --git a/Source/cmXMLParser.cxx b/Source/cmXMLParser.cxx index 920e3a5e9..4c6c35acc 100644 --- a/Source/cmXMLParser.cxx +++ b/Source/cmXMLParser.cxx @@ -186,8 +186,8 @@ void cmXMLParserCharacterDataHandler(void* parser, const char* data, void cmXMLParser::ReportXmlParseError() { XML_Parser parser = static_cast<XML_Parser>(this->Parser); - this->ReportError(XML_GetCurrentLineNumber(parser), - XML_GetCurrentColumnNumber(parser), + this->ReportError(static_cast<int>(XML_GetCurrentLineNumber(parser)), + static_cast<int>(XML_GetCurrentColumnNumber(parser)), XML_ErrorString(XML_GetErrorCode(parser))); } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 6edaa7468..889a5fbdf 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -225,10 +225,8 @@ cmake::~cmake() } #if defined(CMAKE_BUILD_WITH_CMAKE) -Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const +Json::Value cmake::ReportVersionJson() const { - Json::Value obj = Json::objectValue; - // Version information: Json::Value version = Json::objectValue; version["string"] = CMake_VERSION; version["major"] = CMake_VERSION_MAJOR; @@ -236,8 +234,15 @@ Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const version["suffix"] = CMake_VERSION_SUFFIX; version["isDirty"] = (CMake_VERSION_IS_DIRTY == 1); version["patch"] = CMake_VERSION_PATCH; + return version; +} - obj["version"] = version; +Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const +{ + Json::Value obj = Json::objectValue; + + // Version information: + obj["version"] = this->ReportVersionJson(); // Generators: std::vector<cmake::GeneratorInfo> generatorInfoList; @@ -319,9 +324,10 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) bool haveValue = false; std::string cachedValue; if (this->WarnUnusedCli) { - if (const char* v = this->State->GetInitializedCacheValue(var)) { + if (const std::string* v = + this->State->GetInitializedCacheValue(var)) { haveValue = true; - cachedValue = v; + cachedValue = *v; } } @@ -331,7 +337,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) if (this->WarnUnusedCli) { if (!haveValue || - cachedValue != this->State->GetInitializedCacheValue(var)) { + cachedValue != *this->State->GetInitializedCacheValue(var)) { this->WatchUnusedCli(var); } } @@ -407,7 +413,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) for (std::string const& ck : cacheKeys) { cmStateEnums::CacheEntryType t = this->State->GetCacheEntryType(ck); if (t != cmStateEnums::STATIC) { - if (regex.find(ck.c_str())) { + if (regex.find(ck)) { entriesToDelete.push_back(ck); } } @@ -611,19 +617,43 @@ void cmake::SetArgs(const std::vector<std::string>& args, bool havePlatform = false; for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; - if (arg.find("-H", 0) == 0) { + if (arg.find("-H", 0) == 0 || arg.find("-S", 0) == 0) { directoriesSet = true; std::string path = arg.substr(2); + if (path.empty()) { + ++i; + if (i >= args.size()) { + cmSystemTools::Error("No source directory specified for -S"); + return; + } + path = args[i]; + if (path[0] == '-') { + cmSystemTools::Error("No source directory specified for -S"); + return; + } + } + path = cmSystemTools::CollapseFullPath(path); cmSystemTools::ConvertToUnixSlashes(path); this->SetHomeDirectory(path); - } else if (arg.find("-S", 0) == 0) { - // There is no local generate anymore. Ignore -S option. } else if (arg.find("-O", 0) == 0) { // There is no local generate anymore. Ignore -O option. } else if (arg.find("-B", 0) == 0) { directoriesSet = true; std::string path = arg.substr(2); + if (path.empty()) { + ++i; + if (i >= args.size()) { + cmSystemTools::Error("No build directory specified for -B"); + return; + } + path = args[i]; + if (path[0] == '-') { + cmSystemTools::Error("No build directory specified for -B"); + return; + } + } + path = cmSystemTools::CollapseFullPath(path); cmSystemTools::ConvertToUnixSlashes(path); this->SetHomeOutputDirectory(path); @@ -835,20 +865,27 @@ void cmake::SetDirectoriesFromFile(const char* arg) this->SetHomeOutputDirectory(listPath); } else { // Source directory given on command line. Use current working - // directory as build tree. - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - this->SetHomeOutputDirectory(cwd); + // directory as build tree if -B hasn't been given already + if (this->GetHomeOutputDirectory().empty()) { + std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); + this->SetHomeOutputDirectory(cwd); + } } return; } - // We didn't find a CMakeLists.txt or CMakeCache.txt file from the - // argument. Assume it is the path to the source tree, and use the - // current working directory as the build tree. - std::string full = cmSystemTools::CollapseFullPath(arg); - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - this->SetHomeDirectory(full); - this->SetHomeOutputDirectory(cwd); + if (this->GetHomeDirectory().empty()) { + // We didn't find a CMakeLists.txt and it wasn't specified + // with -S. Assume it is the path to the source tree + std::string full = cmSystemTools::CollapseFullPath(arg); + this->SetHomeDirectory(full); + } + if (this->GetHomeOutputDirectory().empty()) { + // We didn't find a CMakeCache.txt and it wasn't specified + // with -B. Assume the current working directory as the build tree. + std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); + this->SetHomeOutputDirectory(cwd); + } } // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the @@ -1107,7 +1144,7 @@ int cmake::DoPreConfigureChecks() // do a sanity check on some values if (this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY")) { std::string cacheStart = - this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY"); + *this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY"); cacheStart += "/CMakeLists.txt"; std::string currentStart = this->GetHomeDirectory(); currentStart += "/CMakeLists.txt"; @@ -1262,10 +1299,7 @@ int cmake::ActualConfigure() this->UpdateConversionPathTable(); this->CleanupCommandsAndMacros(); - int res = 0; - if (this->GetWorkingMode() == NORMAL_MODE) { - res = this->DoPreConfigureChecks(); - } + int res = this->DoPreConfigureChecks(); if (res < 0) { return -2; } @@ -1279,14 +1313,14 @@ int cmake::ActualConfigure() // no generator specified on the command line if (!this->GlobalGenerator) { - const char* genName = + const std::string* genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR"); - const char* extraGenName = + const std::string* extraGenName = this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR"); if (genName) { std::string fullName = cmExternalMakefileProjectGenerator::CreateFullGeneratorName( - genName, extraGenName ? extraGenName : ""); + *genName, extraGenName ? *extraGenName : ""); this->GlobalGenerator = this->CreateGlobalGenerator(fullName); } if (this->GlobalGenerator) { @@ -1304,14 +1338,14 @@ int cmake::ActualConfigure() } } - const char* genName = + const std::string* genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR"); if (genName) { - if (!this->GlobalGenerator->MatchesGeneratorName(genName)) { + if (!this->GlobalGenerator->MatchesGeneratorName(*genName)) { std::string message = "Error: generator : "; message += this->GlobalGenerator->GetName(); message += "\nDoes not match the generator used previously: "; - message += genName; + message += *genName; message += "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."; cmSystemTools::Error(message.c_str()); @@ -1328,14 +1362,14 @@ int cmake::ActualConfigure() cmStateEnums::INTERNAL); } - if (const char* instance = + if (const std::string* instance = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) { if (!this->GeneratorInstance.empty() && - this->GeneratorInstance != instance) { + this->GeneratorInstance != *instance) { std::string message = "Error: generator instance: "; message += this->GeneratorInstance; message += "\nDoes not match the instance used previously: "; - message += instance; + message += *instance; message += "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."; cmSystemTools::Error(message.c_str()); @@ -1347,14 +1381,14 @@ int cmake::ActualConfigure() "Generator instance identifier.", cmStateEnums::INTERNAL); } - if (const char* platformName = + if (const std::string* platformName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) { if (!this->GeneratorPlatform.empty() && - this->GeneratorPlatform != platformName) { + this->GeneratorPlatform != *platformName) { std::string message = "Error: generator platform: "; message += this->GeneratorPlatform; message += "\nDoes not match the platform used previously: "; - message += platformName; + message += *platformName; message += "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."; cmSystemTools::Error(message.c_str()); @@ -1366,13 +1400,13 @@ int cmake::ActualConfigure() "Name of generator platform.", cmStateEnums::INTERNAL); } - if (const char* tsName = + if (const std::string* tsName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) { - if (!this->GeneratorToolset.empty() && this->GeneratorToolset != tsName) { + if (!this->GeneratorToolset.empty() && this->GeneratorToolset != *tsName) { std::string message = "Error: generator toolset: "; message += this->GeneratorToolset; message += "\nDoes not match the toolset used previously: "; - message += tsName; + message += *tsName; message += "\nEither remove the CMakeCache.txt file and CMakeFiles " "directory or choose a different binary directory."; cmSystemTools::Error(message.c_str()); @@ -1431,11 +1465,8 @@ int cmake::ActualConfigure() "CMakeLists.txt ?"); } - // only save the cache if there were no fatal errors - if (this->GetWorkingMode() == NORMAL_MODE) { - this->State->SaveVerificationScript(this->GetHomeOutputDirectory()); - this->SaveCache(this->GetHomeOutputDirectory()); - } + this->State->SaveVerificationScript(this->GetHomeOutputDirectory()); + this->SaveCache(this->GetHomeOutputDirectory()); if (cmSystemTools::GetErrorOccuredFlag()) { return -1; } @@ -1588,7 +1619,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) } int ret = this->Configure(); - if (ret || this->GetWorkingMode() != NORMAL_MODE) { + if (ret) { #if defined(CMAKE_HAVE_VS_GENERATORS) if (!this->VSSolutionFile.empty() && this->GlobalGenerator) { // CMake is running to regenerate a Visual Studio build tree @@ -1634,9 +1665,8 @@ int cmake::Generate() // Save the cache again after a successful Generate so that any internal // variables created during Generate are saved. (Specifically target GUIDs // for the Visual Studio and Xcode generators.) - if (this->GetWorkingMode() == NORMAL_MODE) { - this->SaveCache(this->GetHomeOutputDirectory()); - } + this->SaveCache(this->GetHomeOutputDirectory()); + return 0; } @@ -1692,7 +1722,8 @@ std::string cmake::StripExtension(const std::string& file) const const char* cmake::GetCacheDefinition(const std::string& name) const { - return this->State->GetInitializedCacheValue(name); + const std::string* p = this->State->GetInitializedCacheValue(name); + return p ? p->c_str() : nullptr; } void cmake::AddScriptingCommands() @@ -1875,14 +1906,14 @@ void cmake::PrintGeneratorList() void cmake::UpdateConversionPathTable() { // Update the path conversion table with any specified file: - const char* tablepath = + const std::string* tablepath = this->State->GetInitializedCacheValue("CMAKE_PATH_TRANSLATION_FILE"); if (tablepath) { - cmsys::ifstream table(tablepath); + cmsys::ifstream table(tablepath->c_str()); if (!table) { - cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath, - ". CMake can not open file."); + cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", + tablepath->c_str(), ". CMake can not open file."); cmSystemTools::ReportLastSystemError("CMake can not open file."); } else { std::string a, b; @@ -2436,6 +2467,14 @@ int cmake::Build(int jobs, const std::string& dir, const std::string& target, return 1; } } + const char* cachedGeneratorPlatform = + this->State->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); + if (cachedGeneratorPlatform) { + cmMakefile mf(gen, this->GetCurrentSnapshot()); + if (!gen->SetGeneratorPlatform(cachedGeneratorPlatform, &mf)) { + return 1; + } + } std::string output; std::string projName; const char* cachedProjectName = @@ -2534,11 +2573,11 @@ bool cmake::Open(const std::string& dir, bool dryRun) std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n"; return false; } - const char* extraGenName = + const std::string* extraGenName = this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR"); std::string fullName = cmExternalMakefileProjectGenerator::CreateFullGeneratorName( - genName, extraGenName ? extraGenName : ""); + genName, extraGenName ? *extraGenName : ""); std::unique_ptr<cmGlobalGenerator> gen( this->CreateGlobalGenerator(fullName)); diff --git a/Source/cmake.h b/Source/cmake.h index 86e06df45..d3d0e805d 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -128,6 +128,7 @@ public: ~cmake(); #if defined(CMAKE_BUILD_WITH_CMAKE) + Json::Value ReportVersionJson() const; Json::Value ReportCapabilitiesJson(bool haveServerMode) const; #endif std::string ReportCapabilities(bool haveServerMode) const; @@ -297,8 +298,10 @@ public: ///! this is called by generators to update the progress void UpdateProgress(const char* msg, float prog); +#if defined(CMAKE_BUILD_WITH_CMAKE) ///! Get the variable watch object cmVariableWatch* GetVariableWatch() { return this->VariableWatch; } +#endif void GetGeneratorDocumentation(std::vector<cmDocumentationEntry>&); @@ -493,8 +496,6 @@ protected: void GenerateGraphViz(const char* fileName) const; - cmVariableWatch* VariableWatch; - private: ProgressCallbackType ProgressCallback; void* ProgressCallbackClientData; @@ -525,6 +526,10 @@ private: std::string GraphVizFile; InstalledFilesMap InstalledFiles; +#if defined(CMAKE_BUILD_WITH_CMAKE) + cmVariableWatch* VariableWatch; +#endif + cmState* State; cmStateSnapshot CurrentSnapshot; cmMessenger* Messenger; @@ -552,7 +557,9 @@ private: }; #define CMAKE_STANDARD_OPTIONS_TABLE \ - { "-C <initial-cache>", "Pre-load a script to populate the cache." }, \ + { "-S <path-to-source>", "Explicitly specify a source directory." }, \ + { "-B <path-to-build>", "Explicitly specify a build directory." }, \ + { "-C <initial-cache>", "Pre-load a script to populate the cache." }, \ { "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, \ { "-U <globbing_expr>", "Remove matching entries from CMake cache." }, \ { "-G <generator-name>", "Specify a build system generator." }, \ diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index e3d94f66e..75dabde22 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -38,7 +38,8 @@ static const char* cmDocumentationName[][2] = { static const char* cmDocumentationUsage[][2] = { { nullptr, " cmake [options] <path-to-source>\n" - " cmake [options] <path-to-existing-build>" }, + " cmake [options] <path-to-existing-build>\n" + " cmake [options] -S <path-to-source> -B <path-to-build>" }, { nullptr, "Specify a source directory to (re-)generate a build system for " "it in the current working directory. Specify an existing build " diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 0a75e77d2..1d2f741d8 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -24,6 +24,7 @@ #if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) # include "bindexplib.h" +# include "cmsys/ConsoleBuf.hxx" #endif #if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) && !defined(__CYGWIN__) @@ -107,6 +108,7 @@ void CMakeCommandUsage(const char* program) << " time command [args...] - run command and display elapsed time\n" << " touch file - touch a file.\n" << " touch_nocreate file - touch a file but do not create it.\n" + << " create_symlink old new - create a symbolic link new -> old\n" #if defined(_WIN32) && !defined(__CYGWIN__) << "Available on Windows only:\n" << " delete_regv key - delete registry value\n" @@ -115,9 +117,6 @@ void CMakeCommandUsage(const char* program) << " env_vs9_wince sdkname - displays a batch file which sets the " "environment for the provided Windows CE SDK installed in VS2008\n" << " write_regv key value - write registry value\n" -#else - << "Available on UNIX only:\n" - << " create_symlink old new - create a symbolic link new -> old\n" #endif ; /* clang-format on */ @@ -867,9 +866,6 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) return 1; } if (!cmSystemTools::CreateSymlink(args[2], args[3])) { - std::string emsg = cmSystemTools::GetLastSystemError(); - std::cerr << "failed to create symbolic link '" << destinationFileName - << "': " << emsg << "\n"; return 1; } return 0; @@ -916,8 +912,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) if (args.size() >= 9 && args[8].length() >= 8 && args[8].substr(0, 8) == "--color=") { // Enable or disable color based on the switch value. - color = (args[8].size() == 8 || - cmSystemTools::IsOn(args[8].substr(8).c_str())); + color = + (args[8].size() == 8 || cmSystemTools::IsOn(args[8].substr(8))); } } else { // Support older signature for existing makefiles: @@ -1353,7 +1349,7 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string>& args) // Enable or disable color based on the switch value. std::string value = args[i].substr(9); if (!value.empty()) { - enabled = cmSystemTools::IsOn(value.c_str()); + enabled = cmSystemTools::IsOn(value); } } else if (cmHasLiteralPrefix(args[i], "--progress-dir=")) { progressDir = args[i].substr(15); @@ -1406,7 +1402,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string>& args) bool verbose = false; if (args.size() >= 4) { if (args[3].find("--verbose=") == 0) { - if (!cmSystemTools::IsOff(args[3].substr(10).c_str())) { + if (!cmSystemTools::IsOff(args[3].substr(10))) { verbose = true; } } @@ -1545,6 +1541,15 @@ private: // still works. int cmcmd::VisualStudioLink(std::vector<std::string> const& args, int type) { +#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) + // Replace streambuf so we output in the system codepage. CMake is set up + // to output in Unicode (see SetUTF8Pipes) but the Visual Studio linker + // outputs using the system codepage so we need to change behavior when + // we run the link command. + cmsys::ConsoleBuf::Manager consoleOut(std::cout); + cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true); +#endif + if (args.size() < 2) { return -1; } @@ -1775,6 +1780,8 @@ int cmVSLink::LinkIncremental() if (!fout) { return -1; } + // Insert a pragma statement to specify utf-8 encoding. + fout << "#pragma code_page(65001)\n"; fout << this->Type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ " "24 /* RT_MANIFEST */ \"" diff --git a/Source/ctest.cxx b/Source/ctest.cxx index b338dea48..ca8a7763a 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -27,6 +27,7 @@ static const char* cmDocumentationUsage[][2] = { { nullptr, static const char* cmDocumentationOptions[][2] = { { "-C <cfg>, --build-config <cfg>", "Choose configuration to test." }, + { "--progress", "Enable short progress output from tests." }, { "-V,--verbose", "Enable verbose output from tests." }, { "-VV,--extra-verbose", "Enable more verbose output from tests." }, { "--debug", "Displaying more verbose internals of CTest." }, diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 96088c8f6..43aec00bf 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -35,6 +35,7 @@ # target_link_libraries. Because of how interface # properties propagate, this target is not suitable # for use with PUBLIC or INTERFACE linking. +# KWSYS_ALIAS_TARGET = The name of an alias target to create to the actual target. # # Example: # @@ -887,6 +888,9 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) ADD_LIBRARY(${KWSYS_TARGET_INTERFACE} ${KWSYS_LIBRARY_TYPE} ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS}) ENDIF() + if (KWSYS_ALIAS_TARGET) + add_library(${KWSYS_ALIAS_TARGET} ALIAS ${KWSYS_TARGET_INTERFACE}) + endif () SET_TARGET_PROPERTIES(${KWSYS_TARGET_OBJECT} PROPERTIES C_CLANG_TIDY "" CXX_CLANG_TIDY "" @@ -1193,13 +1197,17 @@ 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" AND - NOT (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND - NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1")) + ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL") # Tell IBM XL not to warn about our test infinite loop - # v13.1.1 and newer on Linux ppc64le is clang based and does not accept - # the -qsuppress option - SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010") + IF(CMAKE_SYSTEM MATCHES "Linux.*ppc64le" + AND CMAKE_C_COMPILER_VERSION VERSION_LESS "16.1.0" + AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1") + # v13.1.[1-6] on Linux ppc64le is clang based and does not accept + # the -qsuppress option, so just suppress all warnings. + SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -w") + ELSE() + SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010") + ENDIF() ENDIF() IF(CMAKE_C_FLAGS MATCHES "-fsanitize=") SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -DCRASH_USING_ABORT") diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index 9fa0cb12a..2a2e73761 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -973,8 +973,8 @@ void kwsysProcess_Execute(kwsysProcess* cp) wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN); DWORD error; cp->PipeChildStd[0] = - CreateFileW(wstdin, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + CreateFileW(wstdin, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, + OPEN_EXISTING, 0, 0); error = GetLastError(); /* Check now in case free changes this. */ free(wstdin); if (cp->PipeChildStd[0] == INVALID_HANDLE_VALUE) { diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index cfe62b4b4..d368fa29f 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -112,7 +112,8 @@ typedef int siginfo_t; # endif #endif -#if defined(__linux) || defined(__sun) || defined(_SCO_DS) +#if defined(__linux) || defined(__sun) || defined(_SCO_DS) || \ + defined(__GLIBC__) || defined(__GNU__) # include <netdb.h> # include <netinet/in.h> # include <sys/socket.h> @@ -3495,7 +3496,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() // Chip Model Name this->ChipID.ModelName = - this->ExtractValueFromCpuInfoFile(buffer, "model name").c_str(); + this->ExtractValueFromCpuInfoFile(buffer, "model name"); // L1 Cache size // Different architectures may show different names for the caches. @@ -4613,7 +4614,7 @@ std::string SystemInformationImplementation::ExtractValueFromSysCtl( std::string SystemInformationImplementation::RunProcess( std::vector<const char*> args) { - std::string buffer = ""; + std::string buffer; // Run the application kwsysProcess* gp = kwsysProcess_New(); @@ -4668,11 +4669,7 @@ std::string SystemInformationImplementation::RunProcess( std::string SystemInformationImplementation::ParseValueFromKStat( const char* arguments) { - std::vector<const char*> args; - args.clear(); - args.push_back("kstat"); - args.push_back("-p"); - + std::vector<std::string> args_string; std::string command = arguments; size_t start = std::string::npos; size_t pos = command.find(' ', 0); @@ -4691,35 +4688,35 @@ std::string SystemInformationImplementation::ParseValueFromKStat( } if (!inQuotes) { - std::string arg = command.substr(start + 1, pos - start - 1); + args_string.push_back(command.substr(start + 1, pos - start - 1)); + std::string& arg = args_string.back(); // Remove the quotes if any - size_t quotes = arg.find('"'); - while (quotes != std::string::npos) { - arg.erase(quotes, 1); - quotes = arg.find('"'); - } - args.push_back(arg.c_str()); + arg.erase(std::remove(arg.begin(), arg.end(), '"'), arg.end()); start = pos; } pos = command.find(' ', pos + 1); } - std::string lastArg = command.substr(start + 1, command.size() - start - 1); - args.push_back(lastArg.c_str()); + args_string.push_back(command.substr(start + 1, command.size() - start - 1)); + std::vector<const char*> args; + args.reserve(3 + args_string.size()); + args.push_back("kstat"); + args.push_back("-p"); + for (size_t i = 0; i < args_string.size(); ++i) { + args.push_back(args_string[i].c_str()); + } args.push_back(KWSYS_NULLPTR); std::string buffer = this->RunProcess(args); - std::string value = ""; + std::string value; for (size_t i = buffer.size() - 1; i > 0; i--) { if (buffer[i] == ' ' || buffer[i] == '\t') { break; } if (buffer[i] != '\n' && buffer[i] != '\r') { - std::string val = value; - value = buffer[i]; - value += val; + value.insert(0u, 1, buffer[i]); } } return value; diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 0079da286..0a4ad7aac 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -686,7 +686,7 @@ public: for (iterator i = this->begin(); i != this->end(); ++i) { # if defined(_WIN32) const std::string s = Encoding::ToNarrow(*i); - kwsysUnPutEnv(s.c_str()); + kwsysUnPutEnv(s); # else kwsysUnPutEnv(*i); # endif @@ -1197,9 +1197,27 @@ bool SystemTools::FileExists(const std::string& filename) } return access(filename.c_str(), R_OK) == 0; #elif defined(_WIN32) - return ( - GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str()) != - INVALID_FILE_ATTRIBUTES); + DWORD attr = + GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str()); + if (attr == INVALID_FILE_ATTRIBUTES) { + return false; + } + + if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { + // Using 0 instead of GENERIC_READ as it allows reading of file attributes + // even if we do not have permission to read the file itself + HANDLE handle = + CreateFileW(Encoding::ToWindowsExtendedPath(filename).c_str(), 0, 0, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + + if (handle == INVALID_HANDLE_VALUE) { + return false; + } + + CloseHandle(handle); + } + + return true; #else // SCO OpenServer 5.0.7/3.2's command has 711 permission. # if defined(_SCO_DS) @@ -1752,11 +1770,11 @@ std::string SystemTools::CropString(const std::string& s, size_t max_len) return n; } -std::vector<kwsys::String> SystemTools::SplitString(const std::string& p, - char sep, bool isPath) +std::vector<std::string> SystemTools::SplitString(const std::string& p, + char sep, bool isPath) { std::string path = p; - std::vector<kwsys::String> paths; + std::vector<std::string> paths; if (path.empty()) { return paths; } @@ -1973,7 +1991,7 @@ std::string SystemTools::ConvertToUnixOutputPath(const std::string& path) } // escape spaces and () in the path if (ret.find_first_of(" ") != std::string::npos) { - std::string result = ""; + std::string result; char lastch = 1; for (const char* ch = ret.c_str(); *ch != '\0'; ++ch) { // if it is already escaped then don't try to escape it again @@ -3140,7 +3158,7 @@ void SystemTools::AddTranslationPath(const std::string& a, void SystemTools::AddKeepPath(const std::string& dir) { std::string cdir; - Realpath(SystemTools::CollapseFullPath(dir).c_str(), cdir); + Realpath(SystemTools::CollapseFullPath(dir), cdir); SystemTools::AddTranslationPath(cdir, dir); } @@ -3279,13 +3297,12 @@ std::string SystemTools::RelativePath(const std::string& local, std::string r = SystemTools::CollapseFullPath(remote); // split up both paths into arrays of strings using / as a separator - std::vector<kwsys::String> localSplit = - SystemTools::SplitString(l, '/', true); - std::vector<kwsys::String> remoteSplit = + std::vector<std::string> localSplit = SystemTools::SplitString(l, '/', true); + std::vector<std::string> remoteSplit = SystemTools::SplitString(r, '/', true); - std::vector<kwsys::String> + std::vector<std::string> commonPath; // store shared parts of path in this array - std::vector<kwsys::String> finalPath; // store the final relative path here + std::vector<std::string> finalPath; // store the final relative path here // count up how many matching directory names there are from the start unsigned int sameCount = 0; while (((sameCount <= (localSplit.size() - 1)) && @@ -3325,7 +3342,7 @@ std::string SystemTools::RelativePath(const std::string& local, } // for each entry that is not common in the remote path add it // to the final path. - for (std::vector<String>::iterator vit = remoteSplit.begin(); + for (std::vector<std::string>::iterator vit = remoteSplit.begin(); vit != remoteSplit.end(); ++vit) { if (!vit->empty()) { finalPath.push_back(*vit); @@ -3334,7 +3351,7 @@ std::string SystemTools::RelativePath(const std::string& local, std::string relativePath; // result string // now turn the array of directories into a unix path by puttint / // between each entry that does not already have one - for (std::vector<String>::iterator vit1 = finalPath.begin(); + for (std::vector<std::string>::iterator vit1 = finalPath.begin(); vit1 != finalPath.end(); ++vit1) { if (!relativePath.empty() && *relativePath.rbegin() != '/') { relativePath += "/"; @@ -3623,11 +3640,11 @@ bool SystemTools::Split(const std::string& str, while (lpos < data.length()) { std::string::size_type rpos = data.find_first_of(separator, lpos); if (rpos == std::string::npos) { - // Line ends at end of string without a newline. + // String ends at end of string without a separator. lines.push_back(data.substr(lpos)); return false; } else { - // Line ends in a "\n", remove the character. + // String ends in a separator, remove the character. lines.push_back(data.substr(lpos, rpos - lpos)); } lpos = rpos + 1; @@ -3641,7 +3658,7 @@ bool SystemTools::Split(const std::string& str, std::string data(str); std::string::size_type lpos = 0; while (lpos < data.length()) { - std::string::size_type rpos = data.find_first_of("\n", lpos); + std::string::size_type rpos = data.find_first_of('\n', lpos); if (rpos == std::string::npos) { // Line ends at end of string without a newline. lines.push_back(data.substr(lpos)); diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 928ee41f2..8d1f78cf7 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -10,8 +10,6 @@ #include <string> #include <vector> -#include <@KWSYS_NAMESPACE@/String.hxx> - #include <sys/types.h> // include sys/stat.h after sys/types.h #include <sys/stat.h> @@ -197,9 +195,9 @@ public: s starts with a / then the first element of the returned array will be /, so /foo/bar will be [/, foo, bar] */ - static std::vector<String> SplitString(const std::string& s, - char separator = '/', - bool isPath = false); + static std::vector<std::string> SplitString(const std::string& s, + char separator = '/', + bool isPath = false); /** * Perform a case-independent string comparison */ diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c index f0d9c6409..4dd246148 100644 --- a/Source/kwsys/Terminal.c +++ b/Source/kwsys/Terminal.c @@ -103,6 +103,8 @@ static int kwsysTerminalStreamIsNotInteractive(FILE* stream) /* List of terminal names known to support VT100 color escape sequences. */ static const char* kwsysTerminalVT100Names[] = { "Eterm", + "alacritty", + "alacritty-direct", "ansi", "color-xterm", "con132x25", @@ -209,27 +211,34 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, } /* VT100 escape sequence strings. */ -#define KWSYS_TERMINAL_VT100_NORMAL "\33[0m" -#define KWSYS_TERMINAL_VT100_BOLD "\33[1m" -#define KWSYS_TERMINAL_VT100_UNDERLINE "\33[4m" -#define KWSYS_TERMINAL_VT100_BLINK "\33[5m" -#define KWSYS_TERMINAL_VT100_INVERSE "\33[7m" -#define KWSYS_TERMINAL_VT100_FOREGROUND_BLACK "\33[30m" -#define KWSYS_TERMINAL_VT100_FOREGROUND_RED "\33[31m" -#define KWSYS_TERMINAL_VT100_FOREGROUND_GREEN "\33[32m" -#define KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW "\33[33m" -#define KWSYS_TERMINAL_VT100_FOREGROUND_BLUE "\33[34m" -#define KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA "\33[35m" -#define KWSYS_TERMINAL_VT100_FOREGROUND_CYAN "\33[36m" -#define KWSYS_TERMINAL_VT100_FOREGROUND_WHITE "\33[37m" -#define KWSYS_TERMINAL_VT100_BACKGROUND_BLACK "\33[40m" -#define KWSYS_TERMINAL_VT100_BACKGROUND_RED "\33[41m" -#define KWSYS_TERMINAL_VT100_BACKGROUND_GREEN "\33[42m" -#define KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW "\33[43m" -#define KWSYS_TERMINAL_VT100_BACKGROUND_BLUE "\33[44m" -#define KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA "\33[45m" -#define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN "\33[46m" -#define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE "\33[47m" +#if defined(__MVS__) +/* if building on z/OS (aka MVS), assume we are using EBCDIC */ +# define ESCAPE_CHAR "\47" +#else +# define ESCAPE_CHAR "\33" +#endif + +#define KWSYS_TERMINAL_VT100_NORMAL ESCAPE_CHAR "[0m" +#define KWSYS_TERMINAL_VT100_BOLD ESCAPE_CHAR "[1m" +#define KWSYS_TERMINAL_VT100_UNDERLINE ESCAPE_CHAR "[4m" +#define KWSYS_TERMINAL_VT100_BLINK ESCAPE_CHAR "[5m" +#define KWSYS_TERMINAL_VT100_INVERSE ESCAPE_CHAR "[7m" +#define KWSYS_TERMINAL_VT100_FOREGROUND_BLACK ESCAPE_CHAR "[30m" +#define KWSYS_TERMINAL_VT100_FOREGROUND_RED ESCAPE_CHAR "[31m" +#define KWSYS_TERMINAL_VT100_FOREGROUND_GREEN ESCAPE_CHAR "[32m" +#define KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW ESCAPE_CHAR "[33m" +#define KWSYS_TERMINAL_VT100_FOREGROUND_BLUE ESCAPE_CHAR "[34m" +#define KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA ESCAPE_CHAR "[35m" +#define KWSYS_TERMINAL_VT100_FOREGROUND_CYAN ESCAPE_CHAR "[36m" +#define KWSYS_TERMINAL_VT100_FOREGROUND_WHITE ESCAPE_CHAR "[37m" +#define KWSYS_TERMINAL_VT100_BACKGROUND_BLACK ESCAPE_CHAR "[40m" +#define KWSYS_TERMINAL_VT100_BACKGROUND_RED ESCAPE_CHAR "[41m" +#define KWSYS_TERMINAL_VT100_BACKGROUND_GREEN ESCAPE_CHAR "[42m" +#define KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW ESCAPE_CHAR "[43m" +#define KWSYS_TERMINAL_VT100_BACKGROUND_BLUE ESCAPE_CHAR "[44m" +#define KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA ESCAPE_CHAR "[45m" +#define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN ESCAPE_CHAR "[46m" +#define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE ESCAPE_CHAR "[47m" /* Write VT100 escape sequences to the stream for the given color. */ static void kwsysTerminalSetVT100Color(FILE* stream, int color) diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx index 0385a3dc6..ef874361f 100644 --- a/Source/kwsys/testCommandLineArguments.cxx +++ b/Source/kwsys/testCommandLineArguments.cxx @@ -77,7 +77,7 @@ int testCommandLineArguments(int argc, char* argv[]) int some_int_variable = 10; double some_double_variable = 10.10; char* some_string_variable = KWSYS_NULLPTR; - std::string some_stl_string_variable = ""; + std::string some_stl_string_variable; bool some_bool_variable = false; bool some_bool_variable1 = false; bool bool_arg1 = false; diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index e6f9701c3..0477d5937 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -206,7 +206,7 @@ static bool CheckFileOperations() res = false; } - if (!kwsys::SystemTools::Touch(testNewFile.c_str(), true)) { + if (!kwsys::SystemTools::Touch(testNewFile, true)) { std::cerr << "Problem with Touch for: " << testNewFile << std::endl; res = false; } @@ -415,7 +415,7 @@ static bool CheckFileOperations() res = false; } - kwsys::SystemTools::Touch(testNewFile.c_str(), true); + kwsys::SystemTools::Touch(testNewFile, true); if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) { std::cerr << "Problem with RemoveADirectory for: " << testNewDir << std::endl; @@ -806,7 +806,7 @@ static bool CheckFind() const std::string testFindFile(TEST_SYSTEMTOOLS_BINARY_DIR "/" + testFindFileName); - if (!kwsys::SystemTools::Touch(testFindFile.c_str(), true)) { + if (!kwsys::SystemTools::Touch(testFindFile, true)) { std::cerr << "Problem with Touch for: " << testFindFile << std::endl; // abort here as the existence of the file only makes the test meaningful return false; |