summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt42
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx353
-rw-r--r--Source/CPack/cmCPackDebGenerator.h5
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx11
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx2
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.h4
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx5
-rw-r--r--Source/CTest/cmCTestRunTest.cxx182
-rw-r--r--Source/CTest/cmCTestRunTest.h3
-rw-r--r--Source/CTest/cmCTestStartCommand.cxx8
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx4
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx196
-rw-r--r--Source/CTest/cmCTestTestHandler.h14
-rw-r--r--Source/CTest/cmCTestTestMeasurementXMLParser.cxx26
-rw-r--r--Source/CTest/cmCTestTestMeasurementXMLParser.h21
-rw-r--r--Source/LexerParser/cmFortranParser.cxx78
-rw-r--r--Source/LexerParser/cmFortranParser.y4
-rw-r--r--Source/QtDialog/QCMake.cxx21
-rw-r--r--Source/cmArchiveWrite.cxx3
-rw-r--r--Source/cmBinUtilsLinuxELFLinker.cxx11
-rw-r--r--Source/cmCMakePolicyCommand.cxx1
-rw-r--r--Source/cmCacheManager.cxx6
-rw-r--r--Source/cmCacheManager.h2
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx2
-rw-r--r--Source/cmCommonTargetGenerator.cxx6
-rw-r--r--Source/cmCommonTargetGenerator.h6
-rw-r--r--Source/cmConditionEvaluator.cxx972
-rw-r--r--Source/cmConditionEvaluator.h30
-rw-r--r--Source/cmConfigure.cmake.h.in1
-rw-r--r--Source/cmCoreTryCompile.cxx10
-rw-r--r--Source/cmDefinitions.cxx6
-rw-r--r--Source/cmDefinitions.h4
-rw-r--r--Source/cmDependsFortran.cxx17
-rw-r--r--Source/cmDependsFortran.h3
-rw-r--r--Source/cmELF.cxx74
-rw-r--r--Source/cmELF.h7
-rw-r--r--Source/cmExportBuildFileGenerator.cxx7
-rw-r--r--Source/cmExportBuildFileGenerator.h8
-rw-r--r--Source/cmExportFileGenerator.cxx52
-rw-r--r--Source/cmExportFileGenerator.h37
-rw-r--r--Source/cmExportInstallFileGenerator.cxx15
-rw-r--r--Source/cmExportInstallFileGenerator.h8
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx2
-rw-r--r--Source/cmExportTryCompileFileGenerator.h5
-rw-r--r--Source/cmFileAPICodemodel.cxx3
-rw-r--r--Source/cmFileCommand.cxx24
-rw-r--r--Source/cmFileCopier.h5
-rw-r--r--Source/cmFileInstaller.cxx118
-rw-r--r--Source/cmFileInstaller.h5
-rw-r--r--Source/cmFindBase.cxx4
-rw-r--r--Source/cmFindLibraryCommand.cxx35
-rw-r--r--Source/cmFindPackageCommand.cxx24
-rw-r--r--Source/cmForEachCommand.cxx1
-rw-r--r--Source/cmFortranParser.h5
-rw-r--r--Source/cmFortranParserImpl.cxx13
-rw-r--r--Source/cmGeneratorExpressionNode.cxx2
-rw-r--r--Source/cmGeneratorTarget.cxx124
-rw-r--r--Source/cmGeneratorTarget.h13
-rw-r--r--Source/cmGetPropertyCommand.cxx19
-rw-r--r--Source/cmGetTestPropertyCommand.cxx5
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx2
-rw-r--r--Source/cmGlobalCommonGenerator.cxx34
-rw-r--r--Source/cmGlobalCommonGenerator.h5
-rw-r--r--Source/cmGlobalGenerator.cxx48
-rw-r--r--Source/cmGlobalGenerator.h5
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx3
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx22
-rw-r--r--Source/cmGlobalNinjaGenerator.h4
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx30
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h2
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx28
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx9
-rw-r--r--Source/cmIncludeGuardCommand.cxx1
-rw-r--r--Source/cmInstallCommand.cxx5
-rw-r--r--Source/cmInstallMode.h17
-rw-r--r--Source/cmListFileCache.cxx4
-rw-r--r--Source/cmLocalGenerator.cxx65
-rw-r--r--Source/cmLocalGenerator.h4
-rw-r--r--Source/cmLocalNinjaGenerator.cxx2
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx2
-rw-r--r--Source/cmMakefile.cxx59
-rw-r--r--Source/cmMakefile.h7
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx23
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx25
-rw-r--r--Source/cmMakefileTargetGenerator.cxx7
-rw-r--r--Source/cmMarkAsAdvancedCommand.cxx1
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx39
-rw-r--r--Source/cmOptionCommand.cxx4
-rw-r--r--Source/cmPolicies.cxx1
-rw-r--r--Source/cmProperty.cxx113
-rw-r--r--Source/cmProperty.h210
-rw-r--r--Source/cmPropertyMap.cxx2
-rw-r--r--Source/cmQtAutoGen.cxx36
-rw-r--r--Source/cmQtAutoGen.h3
-rw-r--r--Source/cmQtAutoGenInitializer.cxx53
-rw-r--r--Source/cmQtAutoGenInitializer.h2
-rw-r--r--Source/cmQtAutoGenerator.cxx37
-rw-r--r--Source/cmQtAutoGenerator.h2
-rw-r--r--Source/cmQtAutoMocUic.cxx20
-rw-r--r--Source/cmQtAutoUicHelpers.cxx25
-rw-r--r--Source/cmQtAutoUicHelpers.h20
-rw-r--r--Source/cmSourceFile.cxx14
-rw-r--r--Source/cmStandardLevelResolver.cxx36
-rw-r--r--Source/cmStandardLevelResolver.h4
-rw-r--r--Source/cmState.cxx51
-rw-r--r--Source/cmState.h28
-rw-r--r--Source/cmStateDirectory.cxx30
-rw-r--r--Source/cmStateSnapshot.cxx3
-rw-r--r--Source/cmStateSnapshot.h3
-rw-r--r--Source/cmStringAlgorithms.cxx70
-rw-r--r--Source/cmStringAlgorithms.h64
-rw-r--r--Source/cmSystemTools.cxx211
-rw-r--r--Source/cmTarget.cxx55
-rw-r--r--Source/cmTarget.h3
-rw-r--r--Source/cmTargetExport.h1
-rw-r--r--Source/cmTargetPropertyComputer.h6
-rw-r--r--Source/cmTest.cxx6
-rw-r--r--Source/cmTest.h3
-rw-r--r--Source/cmTimestamp.cxx23
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx7
-rw-r--r--Source/cmWhileCommand.cxx89
-rw-r--r--Source/cmake.cxx24
-rw-r--r--Source/cmake.h4
-rw-r--r--Source/cmcmd.cxx11
126 files changed, 2567 insertions, 1838 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 0142c07..7e37141 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -10,36 +10,6 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
endif()
include(CheckIncludeFile)
-# Check if we can build support for ELF parsing.
-if(WIN32)
- set(HAVE_ELF_H 0)
-elseif(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD")
- CHECK_INCLUDE_FILES("stdint.h;elf_abi.h" HAVE_ELF_H)
-else()
- CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H)
-endif()
-if(HAVE_ELF_H)
- set(CMake_USE_ELF_PARSER 1)
-elseif(HAIKU)
- # On Haiku, we need to include elf32.h from the private headers
- set(CMake_HAIKU_INCLUDE_DIRS
- /boot/system/develop/headers/private/system
- /boot/system/develop/headers/private/system/arch/x86
- )
-
- set(CMAKE_REQUIRED_INCLUDES ${CMake_HAIKU_INCLUDE_DIRS})
- CHECK_INCLUDE_FILE("elf32.h" HAVE_ELF32_H)
- unset(CMAKE_REQUIRED_INCLUDES)
-
- if(HAVE_ELF32_H)
- set(CMake_USE_ELF_PARSER 1)
- else()
- unset(CMake_HAIKU_INCLUDE_DIRS)
- set(CMake_USE_ELF_PARSER)
- endif()
-else()
- set(CMake_USE_ELF_PARSER)
-endif()
if(NOT CMake_DEFAULT_RECURSION_LIMIT)
if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST})
@@ -111,11 +81,6 @@ include_directories(
${CMake_HAIKU_INCLUDE_DIRS}
)
-# Check if we can build the ELF parser.
-if(CMake_USE_ELF_PARSER)
- set(ELF_SRCS cmELF.h cmELF.cxx)
-endif()
-
# Check if we can build the Mach-O parser.
if(CMake_USE_MACH_PARSER)
set(MACH_SRCS cmMachO.h cmMachO.cxx)
@@ -245,7 +210,8 @@ set(SRCS
cmDocumentationSection.cxx
cmDynamicLoader.cxx
cmDynamicLoader.h
- ${ELF_SRCS}
+ cmELF.h
+ cmELF.cxx
cmExprParserHelper.cxx
cmExportBuildAndroidMKGenerator.h
cmExportBuildAndroidMKGenerator.cxx
@@ -415,6 +381,7 @@ set(SRCS
cmProcessOutput.h
cmProcessTools.cxx
cmProcessTools.h
+ cmProperty.cxx
cmProperty.h
cmPropertyDefinition.cxx
cmPropertyDefinition.h
@@ -432,8 +399,6 @@ set(SRCS
cmQtAutoMocUic.h
cmQtAutoRcc.cxx
cmQtAutoRcc.h
- cmQtAutoUicHelpers.cxx
- cmQtAutoUicHelpers.h
cmRST.cxx
cmRST.h
cmRuntimeDependencyArchive.cxx
@@ -996,6 +961,7 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestSubmitHandler.cxx
CTest/cmCTestTestCommand.cxx
CTest/cmCTestTestHandler.cxx
+ CTest/cmCTestTestMeasurementXMLParser.cxx
CTest/cmCTestUpdateCommand.cxx
CTest/cmCTestUpdateHandler.cxx
CTest/cmCTestUploadCommand.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 88263e0..d10822f 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 21)
-set(CMake_VERSION_PATCH 1)
+set(CMake_VERSION_PATCH 20210824)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 006d66d..829cef4 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -2,11 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackDebGenerator.h"
-#include <cstdlib>
+#include <algorithm>
#include <cstring>
#include <map>
#include <ostream>
#include <set>
+#include <stdexcept>
#include <utility>
#include "cmsys/Glob.hxx"
@@ -54,7 +55,7 @@ private:
const std::string TopLevelDir;
const std::string TemporaryDir;
const char* DebianArchiveType;
- int NumThreads;
+ long NumThreads;
const std::map<std::string, std::string> ControlValues;
const bool GenShLibs;
const std::string ShLibsFilename;
@@ -98,19 +99,22 @@ DebGenerator::DebGenerator(
debianCompressionType = "gzip";
}
- if (!strcmp(debianCompressionType, "lzma")) {
+ if (!std::strcmp(debianCompressionType, "lzma")) {
this->CompressionSuffix = ".lzma";
this->TarCompressionType = cmArchiveWrite::CompressLZMA;
- } else if (!strcmp(debianCompressionType, "xz")) {
+ } else if (!std::strcmp(debianCompressionType, "xz")) {
this->CompressionSuffix = ".xz";
this->TarCompressionType = cmArchiveWrite::CompressXZ;
- } else if (!strcmp(debianCompressionType, "bzip2")) {
+ } else if (!std::strcmp(debianCompressionType, "bzip2")) {
this->CompressionSuffix = ".bz2";
this->TarCompressionType = cmArchiveWrite::CompressBZip2;
- } else if (!strcmp(debianCompressionType, "gzip")) {
+ } else if (!std::strcmp(debianCompressionType, "gzip")) {
this->CompressionSuffix = ".gz";
this->TarCompressionType = cmArchiveWrite::CompressGZip;
- } else if (!strcmp(debianCompressionType, "none")) {
+ } else if (!std::strcmp(debianCompressionType, "zstd")) {
+ this->CompressionSuffix = ".zst";
+ this->TarCompressionType = cmArchiveWrite::CompressZstd;
+ } else if (!std::strcmp(debianCompressionType, "none")) {
this->CompressionSuffix.clear();
this->TarCompressionType = cmArchiveWrite::CompressNone;
} else {
@@ -119,16 +123,15 @@ DebGenerator::DebGenerator(
<< debianCompressionType << std::endl);
}
- if (numThreads == nullptr) {
- numThreads = "1";
- }
-
- char* endptr;
- this->NumThreads = static_cast<int>(strtol(numThreads, &endptr, 10));
- if (numThreads != endptr && *endptr != '\0') {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Unrecognized number of threads: " << numThreads
- << std::endl);
+ if (numThreads != nullptr) {
+ if (!cmStrToLong(numThreads, &this->NumThreads)) {
+ this->NumThreads = 1;
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Unrecognized number of threads: " << numThreads
+ << std::endl);
+ }
+ } else {
+ this->NumThreads = 1;
}
}
@@ -187,8 +190,15 @@ bool DebGenerator::generateDataTar() const
return false;
}
cmArchiveWrite data_tar(fileStream_data_tar, this->TarCompressionType,
- this->DebianArchiveType, 0, this->NumThreads);
- data_tar.Open();
+ this->DebianArchiveType, 0,
+ static_cast<int>(this->NumThreads));
+ if (!data_tar.Open()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the archive \""
+ << filename_data_tar
+ << "\", ERROR = " << data_tar.GetError() << std::endl);
+ return false;
+ }
// uid/gid should be the one of the root user, and this root user has
// always uid/gid equal to 0.
@@ -248,11 +258,15 @@ bool DebGenerator::generateDataTar() const
// 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: " << this->WorkDir << std::endl
- << "#file: " << file << std::endl
- << "#error:" << data_tar.GetError() << std::endl);
+ "Problem adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: "
+ << file
+ << "\n"
+ "#error:"
+ << data_tar.GetError() << std::endl);
return false;
}
}
@@ -309,7 +323,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
cmArchiveWrite control_tar(fileStream_control_tar,
cmArchiveWrite::CompressGZip,
this->DebianArchiveType);
- control_tar.Open();
+ if (!control_tar.Open()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the archive \""
+ << filename_control_tar
+ << "\", ERROR = " << control_tar.GetError() << std::endl);
+ return false;
+ }
// sets permissions and uid/gid for the files
control_tar.SetUIDAndGID(0u, 0u);
@@ -334,11 +354,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
!control_tar.Add(this->WorkDir + "/control", this->WorkDir.length(),
".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << this->WorkDir << std::endl
- << "#file: \"control\" or \"md5sums\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
+ "Error adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: \"control\" or \"md5sums\"\n"
+ "#error:"
+ << control_tar.GetError() << std::endl);
return false;
}
@@ -346,11 +368,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
if (this->GenShLibs) {
if (!control_tar.Add(this->ShLibsFilename, this->WorkDir.length(), ".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << this->WorkDir << std::endl
- << "#file: \"shlibs\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
+ "Error adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: \"shlibs\"\n"
+ "#error:"
+ << control_tar.GetError() << std::endl);
return false;
}
}
@@ -360,11 +384,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
control_tar.SetPermissions(permission755);
if (!control_tar.Add(this->PostInst, this->WorkDir.length(), ".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << this->WorkDir << std::endl
- << "#file: \"postinst\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
+ "Error adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: \"postinst\"\n"
+ "#error:"
+ << control_tar.GetError() << std::endl);
return false;
}
control_tar.SetPermissions(permission644);
@@ -374,11 +400,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
control_tar.SetPermissions(permission755);
if (!control_tar.Add(this->PostRm, this->WorkDir.length(), ".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << this->WorkDir << std::endl
- << "#file: \"postinst\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
+ "Error adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: \"postinst\"\n"
+ "#error:"
+ << control_tar.GetError() << std::endl);
return false;
}
control_tar.SetPermissions(permission644);
@@ -412,11 +440,12 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
// if we can copy the file, it means it does exist, let's add it:
if (!cmsys::SystemTools::FileExists(i)) {
cmCPackLogger(cmCPackLog::LOG_WARNING,
- "Adding file to tar:" << std::endl
- << "#top level directory: "
- << this->WorkDir << std::endl
- << "#missing file: " << i
- << std::endl);
+ "Adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#missing file: "
+ << i << std::endl);
}
if (cmsys::SystemTools::CopyFileIfDifferent(i, localcopy)) {
@@ -440,7 +469,13 @@ bool DebGenerator::generateDeb() const
cmGeneratedFileStream debStream;
debStream.Open(outputPath, false, true);
cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd");
- deb.Open();
+ if (!deb.Open()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the archive \""
+ << outputPath << "\", ERROR = " << deb.GetError()
+ << std::endl);
+ return false;
+ }
// uid/gid should be the one of the root user, and this root user has
// always uid/gid equal to 0.
@@ -451,17 +486,37 @@ bool DebGenerator::generateDeb() const
!deb.Add(tlDir + "control.tar.gz", tlDir.length()) ||
!deb.Add(tlDir + "data.tar" + this->CompressionSuffix, tlDir.length())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error creating debian package:"
- << std::endl
- << "#top level directory: " << this->TopLevelDir
- << std::endl
- << "#file: " << this->OutputName << std::endl
- << "#error:" << deb.GetError() << std::endl);
+ "Error creating debian package:\n"
+ "#top level directory: "
+ << this->TopLevelDir
+ << "\n"
+ "#file: "
+ << this->OutputName
+ << "\n"
+ "#error:"
+ << deb.GetError() << std::endl);
return false;
}
return true;
}
+std::vector<std::string> findFilesIn(const std::string& path)
+{
+ cmsys::Glob gl;
+ std::string findExpr = path + "/*";
+ gl.RecurseOn();
+ gl.SetRecurseListDirs(true);
+ gl.SetRecurseThroughSymlinks(false);
+ if (!gl.FindFiles(findExpr)) {
+ throw std::runtime_error(
+ "Cannot find any files in the installed directory");
+ }
+ std::vector<std::string> files{ gl.GetFiles() };
+ // Sort files so that they have a reproducible order
+ std::sort(files.begin(), files.end());
+ return files;
+}
+
} // end anonymous namespace
cmCPackDebGenerator::cmCPackDebGenerator() = default;
@@ -480,7 +535,6 @@ int cmCPackDebGenerator::InitializeInternal()
int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
std::string const& packageName)
{
- int retval = 1;
// Begin the archive for this pack
std::string localToplevel(initialTopLevel);
std::string packageFileName(
@@ -507,101 +561,48 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while execution CPackDeb.cmake" << std::endl);
- retval = 0;
- return retval;
- }
-
- { // Isolate globbing of binaries vs. dbgsyms
- cmsys::Glob gl;
- std::string findExpr(this->GetOption("GEN_WDIR"));
- findExpr += "/*";
- gl.RecurseOn();
- gl.SetRecurseListDirs(true);
- gl.SetRecurseThroughSymlinks(false);
- if (!gl.FindFiles(findExpr)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory"
- << std::endl);
- return 0;
- }
- this->packageFiles = gl.GetFiles();
- }
-
- int res = this->createDeb();
- if (res != 1) {
- retval = 0;
- }
- // add the generated package to package file names list
- packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
- this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
- this->packageFileNames.push_back(std::move(packageFileName));
-
- if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") &&
- this->GetOption("GEN_DBGSYMDIR")) {
- cmsys::Glob gl;
- std::string findExpr(this->GetOption("GEN_DBGSYMDIR"));
- findExpr += "/*";
- gl.RecurseOn();
- gl.SetRecurseListDirs(true);
- gl.SetRecurseThroughSymlinks(false);
- if (!gl.FindFiles(findExpr)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory"
- << std::endl);
- return 0;
- }
- this->packageFiles = gl.GetFiles();
-
- res = this->createDbgsymDDeb();
- if (res != 1) {
- retval = 0;
- }
- // add the generated package to package file names list
- packageFileName =
- cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
- this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"));
- this->packageFileNames.push_back(std::move(packageFileName));
+ return 0;
}
- return retval;
+ return this->createDebPackages();
}
int cmCPackDebGenerator::PackageComponents(bool ignoreGroup)
{
- int retval = 1;
- /* Reset package file name list it will be populated during the
- * component packaging run*/
+ // Reset package file name list it will be populated during the
+ // component packaging run
this->packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
+ int retval = 1;
// The default behavior is to have one package by component group
// unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
- if (!ignoreGroup) {
- for (auto const& compG : this->ComponentGroups) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Packaging component group: " << compG.first << std::endl);
- // Begin the archive for this group
- retval &= this->PackageOnePack(initialTopLevel, compG.first);
- }
- // Handle Orphan components (components not belonging to any groups)
+ if (ignoreGroup) {
+ // CPACK_COMPONENTS_IGNORE_GROUPS is set
+ // We build 1 package per component
for (auto const& comp : this->Components) {
- // Does the component belong to a group?
- if (comp.second.Group == nullptr) {
- cmCPackLogger(
- cmCPackLog::LOG_VERBOSE,
- "Component <"
- << comp.second.Name
- << "> does not belong to any group, package it separately."
- << std::endl);
- // Begin the archive for this orphan component
- retval &= this->PackageOnePack(initialTopLevel, comp.first);
- }
+ retval &= this->PackageOnePack(initialTopLevel, comp.first);
}
+ return retval;
}
- // CPACK_COMPONENTS_IGNORE_GROUPS is set
- // We build 1 package per component
- else {
- for (auto const& comp : this->Components) {
+
+ for (auto const& compG : this->ComponentGroups) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compG.first << std::endl);
+ // Begin the archive for this group
+ retval &= this->PackageOnePack(initialTopLevel, compG.first);
+ }
+ // Handle Orphan components (components not belonging to any groups)
+ for (auto const& comp : this->Components) {
+ // Does the component belong to a group?
+ if (comp.second.Group == nullptr) {
+ cmCPackLogger(
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
+ << comp.second.Name
+ << "> does not belong to any group, package it separately."
+ << std::endl);
+ // Begin the archive for this orphan component
retval &= this->PackageOnePack(initialTopLevel, comp.first);
}
}
@@ -612,7 +613,6 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup)
int cmCPackDebGenerator::PackageComponentsAllInOne(
const std::string& compInstDirName)
{
- int retval = 1;
/* Reset package file name list it will be populated during the
* component packaging run*/
this->packageFileNames.clear();
@@ -655,33 +655,10 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
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);
- gl.SetRecurseThroughSymlinks(false);
- if (!gl.FindFiles(findExpr)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory"
- << std::endl);
return 0;
}
- this->packageFiles = gl.GetFiles();
- int res = this->createDeb();
- if (res != 1) {
- retval = 0;
- }
- // add the generated package to package file names list
- packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
- this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
- this->packageFileNames.push_back(std::move(packageFileName));
- return retval;
+ return this->createDebPackages();
}
int cmCPackDebGenerator::PackageFiles()
@@ -705,7 +682,40 @@ int cmCPackDebGenerator::PackageFiles()
return this->PackageComponentsAllInOne("");
}
-int cmCPackDebGenerator::createDeb()
+bool cmCPackDebGenerator::createDebPackages()
+{
+ auto make_package = [this](const char* const path,
+ const char* const output_var,
+ bool (cmCPackDebGenerator::*creator)()) -> bool {
+ try {
+ this->packageFiles = findFilesIn(path);
+ } catch (const std::runtime_error& ex) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl);
+ return false;
+ }
+
+ if ((this->*creator)()) {
+ // add the generated package to package file names list
+ this->packageFileNames.emplace_back(
+ cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+ this->GetOption(output_var)));
+ return true;
+ }
+ return false;
+ };
+ bool retval =
+ make_package(this->GetOption("GEN_WDIR"), "GEN_CPACK_OUTPUT_FILE_NAME",
+ &cmCPackDebGenerator::createDeb);
+ const char* const dbgsymdir_path = this->GetOption("GEN_DBGSYMDIR");
+ if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && dbgsymdir_path) {
+ retval = make_package(dbgsymdir_path, "GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME",
+ &cmCPackDebGenerator::createDbgsymDDeb) &&
+ retval;
+ }
+ return int(retval);
+}
+
+bool cmCPackDebGenerator::createDeb()
{
std::map<std::string, std::string> controlValues;
@@ -829,13 +839,10 @@ int cmCPackDebGenerator::createDeb()
this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
this->packageFiles);
- if (!gen.generate()) {
- return 0;
- }
- return 1;
+ return gen.generate();
}
-int cmCPackDebGenerator::createDbgsymDDeb()
+bool cmCPackDebGenerator::createDbgsymDDeb()
{
// Packages containing debug symbols follow the same structure as .debs
// but have different metadata and content.
@@ -875,7 +882,6 @@ int cmCPackDebGenerator::createDbgsymDDeb()
DebGenerator gen(
this->Logger, this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"),
this->GetOption("GEN_DBGSYMDIR"),
-
this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
this->GetOption("CPACK_TEMPORARY_DIRECTORY"),
this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"),
@@ -885,10 +891,7 @@ int cmCPackDebGenerator::createDbgsymDDeb()
this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
this->packageFiles);
- if (!gen.generate()) {
- return 0;
- }
- return 1;
+ return gen.generate();
}
bool cmCPackDebGenerator::SupportsComponentInstallation() const
diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h
index ee8f39a..61a6616 100644
--- a/Source/CPack/cmCPackDebGenerator.h
+++ b/Source/CPack/cmCPackDebGenerator.h
@@ -63,8 +63,9 @@ protected:
const std::string& componentName) override;
private:
- int createDeb();
- int createDbgsymDDeb();
+ bool createDebPackages();
+ bool createDeb();
+ bool createDbgsymDDeb();
std::vector<std::string> packageFiles;
};
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 6bd0d1b..395b1df 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -235,6 +235,13 @@ int cmCPackNSISGenerator::PackageFiles()
brandingTextCode.c_str());
}
+ if (!this->IsSet("CPACK_NSIS_IGNORE_LICENSE_PAGE")) {
+ std::string licenceCode =
+ cmStrCat("!insertmacro MUI_PAGE_LICENSE \"",
+ this->GetOption("CPACK_RESOURCE_FILE_LICENSE"), "\"\n");
+ this->SetOptionIfNotSet("CPACK_NSIS_LICENSE_PAGE", licenceCode.c_str());
+ }
+
// Setup all of the component sections
if (this->Components.empty()) {
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", "");
@@ -487,12 +494,12 @@ int cmCPackNSISGenerator::InitializeInternal()
}
if (versionRex.find(output)) {
double nsisVersion = atof(versionRex.match(1).c_str());
- double minNSISVersion = 3.0;
+ double minNSISVersion = 3.03;
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"NSIS Version: " << nsisVersion << std::endl);
if (nsisVersion < minNSISVersion) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPack requires NSIS Version 3.0 or greater. "
+ "CPack requires NSIS Version 3.03 or greater. "
"NSIS found on the system was: "
<< nsisVersion << std::endl);
return 0;
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 125d003..6bb8e79 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -305,7 +305,7 @@ int cmCTestMemCheckHandler::GetDefectCount() const
return this->DefectCount;
}
-void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
+void cmCTestMemCheckHandler::GenerateCTestXML(cmXMLWriter& xml)
{
if (!this->CTest->GetProduceXML()) {
return;
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index b200c43..a63a24d 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -119,9 +119,9 @@ private:
bool InitializeMemoryChecking();
/**
- * Generate the Dart compatible output
+ * Generate CTest DynamicAnalysis.xml files
*/
- void GenerateDartOutput(cmXMLWriter& xml) override;
+ void GenerateCTestXML(cmXMLWriter& xml) override;
std::vector<std::string> CustomPreMemCheck;
std::vector<std::string> CustomPostMemCheck;
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 86a8e00..d90c4a6 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -1026,6 +1026,11 @@ static Json::Value DumpCTestProperties(
properties.append(DumpCTestProperty(
"ENVIRONMENT", DumpToJsonArray(testProperties.Environment)));
}
+ if (!testProperties.EnvironmentModification.empty()) {
+ properties.append(DumpCTestProperty(
+ "ENVIRONMENT_MODIFICATION",
+ DumpToJsonArray(testProperties.EnvironmentModification)));
+ }
if (!testProperties.ErrorRegularExpressions.empty()) {
properties.append(DumpCTestProperty(
"FAIL_REGULAR_EXPRESSION",
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index a892113..20f0ed3 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -2,17 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestRunTest.h"
+#include <algorithm>
#include <chrono>
#include <cstddef> // IWYU pragma: keep
#include <cstdint>
#include <cstdio>
#include <cstring>
+#include <functional>
#include <iomanip>
#include <ratio>
#include <sstream>
#include <utility>
#include <cm/memory>
+#include <cm/optional>
+#include <cm/string_view>
+#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
@@ -44,7 +49,9 @@ void cmCTestRunTest::CheckOutput(std::string const& line)
// Check for special CTest XML tags in this line of output.
// If any are found, this line is excluded from ProcessOutput.
if (!line.empty() && line.find("<CTest") != std::string::npos) {
+ bool ctest_tag_found = false;
if (this->TestHandler->CustomCompletionStatusRegex.find(line)) {
+ ctest_tag_found = true;
this->TestResult.CustomCompletionStatus =
this->TestHandler->CustomCompletionStatusRegex.match(1);
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -52,6 +59,20 @@ void cmCTestRunTest::CheckOutput(std::string const& line)
<< "Test Details changed to '"
<< this->TestResult.CustomCompletionStatus
<< "'" << std::endl);
+ } else if (this->TestHandler->CustomLabelRegex.find(line)) {
+ ctest_tag_found = true;
+ auto label = this->TestHandler->CustomLabelRegex.match(1);
+ auto& labels = this->TestProperties->Labels;
+ if (std::find(labels.begin(), labels.end(), label) == labels.end()) {
+ labels.push_back(label);
+ std::sort(labels.begin(), labels.end());
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->GetIndex()
+ << ": "
+ << "Test Label added: '" << label << "'" << std::endl);
+ }
+ }
+ if (ctest_tag_found) {
return;
}
}
@@ -245,7 +266,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
*this->TestHandler->LogFile << "Test time = " << buf << std::endl;
}
- this->DartProcessing();
+ this->ParseOutputForMeasurements();
// if this is doing MemCheck then all the output needs to be put into
// Output since that is what is parsed by cmCTestMemCheckHandler
@@ -623,6 +644,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
return this->ForkProcess(timeout, this->TestProperties->ExplicitTimeout,
&this->TestProperties->Environment,
+ &this->TestProperties->EnvironmentModification,
&this->TestProperties->Affinity);
}
@@ -679,28 +701,45 @@ void cmCTestRunTest::ComputeArguments()
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
this->Index << ": " << env << std::endl);
}
+ if (!this->TestProperties->EnvironmentModification.empty()) {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": "
+ << "Environment variable modifications: "
+ << std::endl);
+ }
+ for (std::string const& envmod :
+ this->TestProperties->EnvironmentModification) {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": " << envmod << std::endl);
+ }
}
-void cmCTestRunTest::DartProcessing()
+void cmCTestRunTest::ParseOutputForMeasurements()
{
if (!this->ProcessOutput.empty() &&
- this->ProcessOutput.find("<DartMeasurement") != std::string::npos) {
- if (this->TestHandler->DartStuff.find(this->ProcessOutput)) {
- this->TestResult.DartString = this->TestHandler->DartStuff.match(1);
+ (this->ProcessOutput.find("<DartMeasurement") != std::string::npos ||
+ this->ProcessOutput.find("<CTestMeasurement") != std::string::npos)) {
+ if (this->TestHandler->AllTestMeasurementsRegex.find(
+ this->ProcessOutput)) {
+ this->TestResult.TestMeasurementsOutput =
+ this->TestHandler->AllTestMeasurementsRegex.match(1);
// keep searching and replacing until none are left
- while (this->TestHandler->DartStuff1.find(this->ProcessOutput)) {
+ while (this->TestHandler->SingleTestMeasurementRegex.find(
+ this->ProcessOutput)) {
// replace the exact match for the string
cmSystemTools::ReplaceString(
- this->ProcessOutput, this->TestHandler->DartStuff1.match(1).c_str(),
- "");
+ this->ProcessOutput,
+ this->TestHandler->SingleTestMeasurementRegex.match(1).c_str(), "");
}
}
}
}
-bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
- std::vector<std::string>* environment,
- std::vector<size_t>* affinity)
+bool cmCTestRunTest::ForkProcess(
+ cmDuration testTimeOut, bool explicitTimeout,
+ std::vector<std::string>* environment,
+ std::vector<std::string>* environment_modification,
+ std::vector<size_t>* affinity)
{
this->TestProcess->SetId(this->Index);
this->TestProcess->SetWorkingDirectory(this->TestProperties->Directory);
@@ -749,6 +788,127 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
}
}
+ if (environment_modification && !environment_modification->empty()) {
+ std::map<std::string, cm::optional<std::string>> env_application;
+
+#ifdef _WIN32
+ char path_sep = ';';
+#else
+ char path_sep = ':';
+#endif
+
+ auto apply_diff =
+ [&env_application](const std::string& name,
+ std::function<void(std::string&)> const& apply) {
+ auto entry = env_application.find(name);
+ std::string output;
+ if (entry != env_application.end() && entry->second) {
+ output = *entry->second;
+ }
+ apply(output);
+ entry->second = output;
+ };
+
+ bool err_occurred = false;
+
+ for (auto const& envmod : *environment_modification) {
+ // Split on `=`
+ auto const eq_loc = envmod.find_first_of('=');
+ if (eq_loc == std::string::npos) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error: Missing `=` after the variable name in: "
+ << envmod << std::endl);
+ err_occurred = true;
+ continue;
+ }
+ auto const name = envmod.substr(0, eq_loc);
+
+ // Split value on `:`
+ auto const op_value_start = eq_loc + 1;
+ auto const colon_loc = envmod.find_first_of(':', op_value_start);
+ if (colon_loc == std::string::npos) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error: Missing `:` after the operation in: " << envmod
+ << std::endl);
+ err_occurred = true;
+ continue;
+ }
+ auto const op =
+ envmod.substr(op_value_start, colon_loc - op_value_start);
+
+ auto const value_start = colon_loc + 1;
+ auto const value = envmod.substr(value_start);
+
+ // Determine what to do with the operation.
+ if (op == "reset"_s) {
+ auto entry = env_application.find(name);
+ if (entry != env_application.end()) {
+ env_application.erase(entry);
+ }
+ } else if (op == "set"_s) {
+ env_application[name] = value;
+ } else if (op == "unset"_s) {
+ env_application[name] = {};
+ } else if (op == "string_append"_s) {
+ apply_diff(name, [&value](std::string& output) { output += value; });
+ } else if (op == "string_prepend"_s) {
+ apply_diff(name,
+ [&value](std::string& output) { output.insert(0, value); });
+ } else if (op == "path_list_append"_s) {
+ apply_diff(name, [&value, path_sep](std::string& output) {
+ if (!output.empty()) {
+ output += path_sep;
+ }
+ output += value;
+ });
+ } else if (op == "path_list_prepend"_s) {
+ apply_diff(name, [&value, path_sep](std::string& output) {
+ if (!output.empty()) {
+ output.insert(output.begin(), path_sep);
+ }
+ output.insert(0, value);
+ });
+ } else if (op == "cmake_list_append"_s) {
+ apply_diff(name, [&value](std::string& output) {
+ if (!output.empty()) {
+ output += ';';
+ }
+ output += value;
+ });
+ } else if (op == "cmake_list_prepend"_s) {
+ apply_diff(name, [&value](std::string& output) {
+ if (!output.empty()) {
+ output.insert(output.begin(), ';');
+ }
+ output.insert(0, value);
+ });
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error: Unrecognized environment manipulation argument: "
+ << op << std::endl);
+ err_occurred = true;
+ continue;
+ }
+ }
+
+ if (err_occurred) {
+ return false;
+ }
+
+ for (auto const& env_apply : env_application) {
+ if (env_apply.second) {
+ auto const env_update =
+ cmStrCat(env_apply.first, '=', *env_apply.second);
+ cmSystemTools::PutEnv(env_update);
+ envMeasurement << env_update << std::endl;
+ } else {
+ cmSystemTools::UnsetEnv(env_apply.first.c_str());
+ // Signify that this variable is being actively unset
+ envMeasurement << "#" << env_apply.first << "=" << std::endl;
+ }
+ }
+ }
+
if (this->UseAllocatedResources) {
std::vector<std::string> envLog;
this->SetupResourcesEnvironment(&envLog);
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 863ac1b..2082156 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -109,10 +109,11 @@ public:
private:
bool NeedsToRepeat();
- void DartProcessing();
+ void ParseOutputForMeasurements();
void ExeNotFound(std::string exe);
bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
std::vector<std::string>* environment,
+ std::vector<std::string>* environment_modification,
std::vector<size_t>* affinity);
void WriteLogOutputTop(size_t completed, size_t total);
// Run post processing of the process output for MemCheck
diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx
index 53e1b2f..a8c2403 100644
--- a/Source/CTest/cmCTestStartCommand.cxx
+++ b/Source/CTest/cmCTestStartCommand.cxx
@@ -30,8 +30,8 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
size_t cnt = 0;
const char* smodel = nullptr;
- const std::string* src_dir = nullptr;
- const std::string* bld_dir = nullptr;
+ cmProp src_dir;
+ cmProp bld_dir;
while (cnt < args.size()) {
if (args[cnt] == "GROUP" || args[cnt] == "TRACK") {
@@ -55,10 +55,10 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
smodel = args[cnt].c_str();
cnt++;
} else if (!src_dir) {
- src_dir = &args[cnt];
+ src_dir = cmProp(args[cnt]);
cnt++;
} else if (!bld_dir) {
- bld_dir = &args[cnt];
+ bld_dir = cmProp(args[cnt]);
cnt++;
} else {
this->SetError("Too many arguments");
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index bdba0e5..7aeb288 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -36,8 +36,8 @@ std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone()
cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
{
- const std::string* submitURL = !this->SubmitURL.empty()
- ? &this->SubmitURL
+ cmProp submitURL = !this->SubmitURL.empty()
+ ? cmProp(this->SubmitURL)
: this->Makefile->GetDefinition("CTEST_SUBMIT_URL");
if (submitURL) {
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 730ec0f..1157d10 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -32,6 +32,7 @@
#include "cmCTest.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmCTestResourceGroupsLexerHelper.h"
+#include "cmCTestTestMeasurementXMLParser.h"
#include "cmDuration.h"
#include "cmExecutionStatus.h"
#include "cmGeneratedFileStream.h"
@@ -303,15 +304,24 @@ cmCTestTestHandler::cmCTestTestHandler()
// Support for JUnit XML output.
this->JUnitXMLFileName = "";
- // regex to detect <DartMeasurement>...</DartMeasurement>
- this->DartStuff.compile("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
- // regex to detect each individual <DartMeasurement>...</DartMeasurement>
- this->DartStuff1.compile(
- "(<DartMeasurement[^<]*</DartMeasurement[a-zA-Z]*>)");
+ // Regular expressions to scan test output for custom measurements.
- // regex to detect <CTestDetails>...</CTestDetails>
+ // Capture the whole section of test output from the first opening
+ // <(CTest|Dart)Measurement*> tag to the last </(CTest|Dart)Measurement*>
+ // closing tag.
+ this->AllTestMeasurementsRegex.compile(
+ "(<(CTest|Dart)Measurement.*/(CTest|Dart)Measurement[a-zA-Z]*>)");
+
+ // Capture a single <(CTest|Dart)Measurement*> XML element.
+ this->SingleTestMeasurementRegex.compile(
+ "(<(CTest|Dart)Measurement[^<]*</(CTest|Dart)Measurement[a-zA-Z]*>)");
+
+ // Capture content from <CTestDetails>...</CTestDetails>
this->CustomCompletionStatusRegex.compile(
"<CTestDetails>(.*)</CTestDetails>");
+
+ // Capture content from <CTestLabel>...</CTestLabel>
+ this->CustomLabelRegex.compile("<CTestLabel>(.*)</CTestLabel>");
}
void cmCTestTestHandler::Initialize()
@@ -692,7 +702,7 @@ bool cmCTestTestHandler::GenerateXML()
return false;
}
cmXMLWriter xml(xmlfile);
- this->GenerateDartOutput(xml);
+ this->GenerateCTestXML(xml);
}
return true;
@@ -1400,7 +1410,7 @@ void cmCTestTestHandler::GenerateTestCommand(
{
}
-void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
+void cmCTestTestHandler::GenerateCTestXML(cmXMLWriter& xml)
{
if (!this->CTest->GetProduceXML()) {
return;
@@ -1436,7 +1446,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.Element("Value", result.ReturnValue);
xml.EndElement(); // NamedMeasurement
}
- this->GenerateRegressionImages(xml, result.DartString);
+ this->RecordCustomTestMeasurements(xml, result.TestMeasurementsOutput);
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "numeric/double");
xml.Attribute("name", "Execution Time");
@@ -1976,124 +1986,48 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
}
}
-// Just for convenience
-#define SPACE_REGEX "[ \t\r\n]"
-void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
- const std::string& dart)
-{
- cmsys::RegularExpression twoattributes(
- "<DartMeasurement" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*>([^<]*)</DartMeasurement>");
- cmsys::RegularExpression threeattributes(
- "<DartMeasurement" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*>([^<]*)</DartMeasurement>");
- cmsys::RegularExpression fourattributes(
- "<DartMeasurement" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*>([^<]*)</DartMeasurement>");
- cmsys::RegularExpression cdatastart(
- "<DartMeasurement" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*>" SPACE_REGEX "*<!\\[CDATA\\[");
- cmsys::RegularExpression cdataend("]]>" SPACE_REGEX "*</DartMeasurement>");
- cmsys::RegularExpression measurementfile(
- "<DartMeasurementFile" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*>([^<]*)</DartMeasurementFile>");
-
- bool done = false;
- std::string cxml = dart;
- while (!done) {
- if (twoattributes.find(cxml)) {
- xml.StartElement("NamedMeasurement");
- xml.Attribute(twoattributes.match(1).c_str(), twoattributes.match(2));
- xml.Attribute(twoattributes.match(3).c_str(), twoattributes.match(4));
- xml.Element("Value", twoattributes.match(5));
- xml.EndElement();
- cxml.erase(twoattributes.start(),
- twoattributes.end() - twoattributes.start());
- } else if (threeattributes.find(cxml)) {
- xml.StartElement("NamedMeasurement");
- xml.Attribute(threeattributes.match(1).c_str(),
- threeattributes.match(2));
- xml.Attribute(threeattributes.match(3).c_str(),
- threeattributes.match(4));
- xml.Attribute(threeattributes.match(5).c_str(),
- threeattributes.match(6));
- xml.Element("Value", twoattributes.match(7));
- xml.EndElement();
- cxml.erase(threeattributes.start(),
- threeattributes.end() - threeattributes.start());
- } else if (fourattributes.find(cxml)) {
+void cmCTestTestHandler::RecordCustomTestMeasurements(cmXMLWriter& xml,
+ std::string content)
+{
+ while (this->SingleTestMeasurementRegex.find(content)) {
+ // Extract regex match from content and parse it as an XML element.
+ auto measurement_str = this->SingleTestMeasurementRegex.match(1);
+ auto parser = cmCTestTestMeasurementXMLParser();
+ parser.Parse(measurement_str.c_str());
+
+ if (parser.ElementName == "CTestMeasurement" ||
+ parser.ElementName == "DartMeasurement") {
xml.StartElement("NamedMeasurement");
- xml.Attribute(fourattributes.match(1).c_str(), fourattributes.match(2));
- xml.Attribute(fourattributes.match(3).c_str(), fourattributes.match(4));
- xml.Attribute(fourattributes.match(5).c_str(), fourattributes.match(6));
- xml.Attribute(fourattributes.match(7).c_str(), fourattributes.match(8));
- xml.Element("Value", twoattributes.match(9));
+ xml.Attribute("type", parser.MeasurementType);
+ xml.Attribute("name", parser.MeasurementName);
+ xml.Element("Value", parser.CharacterData);
xml.EndElement();
- cxml.erase(fourattributes.start(),
- fourattributes.end() - fourattributes.start());
- } else if (cdatastart.find(cxml) && cdataend.find(cxml)) {
- xml.StartElement("NamedMeasurement");
- xml.Attribute(cdatastart.match(1).c_str(), cdatastart.match(2));
- xml.Attribute(cdatastart.match(3).c_str(), cdatastart.match(4));
- xml.StartElement("Value");
- xml.CData(
- cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end()));
- xml.EndElement(); // Value
- xml.EndElement(); // NamedMeasurement
- cxml.erase(cdatastart.start(), cdataend.end() - cdatastart.start());
- } else if (measurementfile.find(cxml)) {
- const std::string& filename =
- cmCTest::CleanString(measurementfile.match(5));
- if (cmSystemTools::FileExists(filename)) {
+ } else if (parser.ElementName == "CTestMeasurementFile" ||
+ parser.ElementName == "DartMeasurementFile") {
+ const std::string& filename = cmCTest::CleanString(parser.CharacterData);
+ if (!cmSystemTools::FileExists(filename)) {
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("name", parser.MeasurementName);
+ xml.Attribute("text", "text/string");
+ xml.Element("Value", "File " + filename + " not found");
+ xml.EndElement();
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
+ "File \"" << filename << "\" not found." << std::endl, this->Quiet);
+ } else {
long len = cmSystemTools::FileLength(filename);
- std::string k1 = measurementfile.match(1);
- std::string v1 = measurementfile.match(2);
- std::string k2 = measurementfile.match(3);
- std::string v2 = measurementfile.match(4);
if (len == 0) {
- if (cmSystemTools::LowerCase(k1) == "type") {
- v1 = "text/string";
- }
- if (cmSystemTools::LowerCase(k2) == "type") {
- v2 = "text/string";
- }
-
xml.StartElement("NamedMeasurement");
- xml.Attribute(k1.c_str(), v1);
- xml.Attribute(k2.c_str(), v2);
+ xml.Attribute("name", parser.MeasurementName);
+ xml.Attribute("type", "text/string");
xml.Attribute("encoding", "none");
xml.Element("Value", "Image " + filename + " is empty");
xml.EndElement();
} else {
- std::string type;
- std::string name;
- if (cmSystemTools::LowerCase(k1) == "type") {
- type = v1;
- } else if (cmSystemTools::LowerCase(k2) == "type") {
- type = v2;
- }
- if (cmSystemTools::LowerCase(k1) == "name") {
- name = v1;
- } else if (cmSystemTools::LowerCase(k2) == "name") {
- name = v2;
- }
- if (type == "file") {
+ if (parser.MeasurementType == "file") {
// Treat this measurement like an "ATTACHED_FILE" when the type
// is explicitly "file" (not an image).
- this->AttachFile(xml, filename, name);
+ this->AttachFile(xml, filename, parser.MeasurementName);
} else {
cmsys::ifstream ifs(filename.c_str(),
std::ios::in
@@ -2110,10 +2044,8 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
encoded_buffer.get(), 1);
xml.StartElement("NamedMeasurement");
- xml.Attribute(measurementfile.match(1).c_str(),
- measurementfile.match(2));
- xml.Attribute(measurementfile.match(3).c_str(),
- measurementfile.match(4));
+ xml.Attribute("name", parser.MeasurementName);
+ xml.Attribute("type", parser.MeasurementType);
xml.Attribute("encoding", "base64");
std::ostringstream ostr;
for (size_t cc = 0; cc < rlen; cc++) {
@@ -2126,25 +2058,11 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
xml.EndElement(); // NamedMeasurement
}
}
- } else {
- int idx = 4;
- if (measurementfile.match(1) == "name") {
- idx = 2;
- }
- xml.StartElement("NamedMeasurement");
- xml.Attribute("name", measurementfile.match(idx));
- xml.Attribute("text", "text/string");
- xml.Element("Value", "File " + filename + " not found");
- xml.EndElement();
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT,
- "File \"" << filename << "\" not found." << std::endl, this->Quiet);
}
- cxml.erase(measurementfile.start(),
- measurementfile.end() - measurementfile.start());
- } else {
- done = true;
}
+
+ // Remove this element from content.
+ cmSystemTools::ReplaceString(content, measurement_str.c_str(), "");
}
}
@@ -2247,7 +2165,7 @@ bool cmCTestTestHandler::SetTestsProperties(
// Ensure we have complete triples otherwise the data is corrupt.
if (triples.size() % 3 == 0) {
- cmState state;
+ cmState state(cmState::Unknown);
rt.Backtrace = cmListFileBacktrace(state.CreateBaseSnapshot());
// the first entry represents the top of the trace so we need to
@@ -2327,6 +2245,8 @@ bool cmCTestTestHandler::SetTestsProperties(
cmExpandList(val, rt.Depends);
} else if (key == "ENVIRONMENT"_s) {
cmExpandList(val, rt.Environment);
+ } else if (key == "ENVIRONMENT_MODIFICATION"_s) {
+ cmExpandList(val, rt.EnvironmentModification);
} else if (key == "LABELS"_s) {
std::vector<std::string> Labels = cmExpandedList(val);
rt.Labels.insert(rt.Labels.end(), Labels.begin(), Labels.end());
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index bd51738..f2da320 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -151,6 +151,7 @@ public:
// return code of test which will mark test as "not run"
int SkipReturnCode;
std::vector<std::string> Environment;
+ std::vector<std::string> EnvironmentModification;
std::vector<std::string> Labels;
std::set<std::string> LockedResources;
std::set<std::string> FixturesSetup;
@@ -177,7 +178,7 @@ public:
std::string CompletionStatus;
std::string CustomCompletionStatus;
std::string Output;
- std::string DartString;
+ std::string TestMeasurementsOutput;
int TestCount;
cmCTestTestProperties* Properties;
};
@@ -276,9 +277,9 @@ public:
private:
/**
- * Generate the Dart compatible output
+ * Write test results in CTest's Test.xml format
*/
- virtual void GenerateDartOutput(cmXMLWriter& xml);
+ virtual void GenerateCTestXML(cmXMLWriter& xml);
/**
* Write test results in JUnit XML format
@@ -348,8 +349,7 @@ private:
cmCTestResourceSpec ResourceSpec;
std::string ResourceSpecFile;
- void GenerateRegressionImages(cmXMLWriter& xml, const std::string& dart);
- cmsys::RegularExpression DartStuff1;
+ void RecordCustomTestMeasurements(cmXMLWriter& xml, std::string content);
void CheckLabelFilter(cmCTestTestProperties& it);
void CheckLabelFilterExclude(cmCTestTestProperties& it);
void CheckLabelFilterInclude(cmCTestTestProperties& it);
@@ -358,8 +358,10 @@ private:
bool UseUnion;
ListOfTests TestList;
size_t TotalNumberOfTests;
- cmsys::RegularExpression DartStuff;
+ cmsys::RegularExpression AllTestMeasurementsRegex;
+ cmsys::RegularExpression SingleTestMeasurementRegex;
cmsys::RegularExpression CustomCompletionStatusRegex;
+ cmsys::RegularExpression CustomLabelRegex;
std::ostream* LogFile;
diff --git a/Source/CTest/cmCTestTestMeasurementXMLParser.cxx b/Source/CTest/cmCTestTestMeasurementXMLParser.cxx
new file mode 100644
index 0000000..636be24
--- /dev/null
+++ b/Source/CTest/cmCTestTestMeasurementXMLParser.cxx
@@ -0,0 +1,26 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmCTestTestMeasurementXMLParser.h"
+
+#include <cstring>
+
+void cmCTestTestMeasurementXMLParser::StartElement(const std::string& name,
+ const char** attributes)
+{
+ this->CharacterData.clear();
+ this->ElementName = name;
+ for (const char** attr = attributes; *attr; attr += 2) {
+ if (strcmp(attr[0], "name") == 0) {
+ this->MeasurementName = attr[1];
+ } else if (strcmp(attr[0], "type") == 0) {
+ this->MeasurementType = attr[1];
+ }
+ }
+}
+
+void cmCTestTestMeasurementXMLParser::CharacterDataHandler(const char* data,
+ int length)
+{
+ this->CharacterData.append(data, length);
+}
diff --git a/Source/CTest/cmCTestTestMeasurementXMLParser.h b/Source/CTest/cmCTestTestMeasurementXMLParser.h
new file mode 100644
index 0000000..b2c3eb3
--- /dev/null
+++ b/Source/CTest/cmCTestTestMeasurementXMLParser.h
@@ -0,0 +1,21 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include <string>
+
+#include "cmXMLParser.h"
+
+class cmCTestTestMeasurementXMLParser : public cmXMLParser
+{
+public:
+ cmCTestTestMeasurementXMLParser() {}
+ std::string CharacterData;
+ std::string ElementName;
+ std::string MeasurementName;
+ std::string MeasurementType;
+
+protected:
+ void StartElement(const std::string& name, const char** atts) override;
+ void EndElement(const std::string& /*name*/) override {}
+ void CharacterDataHandler(const char* data, int length) override;
+};
diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
index 3f3ddde..50e9752 100644
--- a/Source/LexerParser/cmFortranParser.cxx
+++ b/Source/LexerParser/cmFortranParser.cxx
@@ -600,12 +600,12 @@ static const yytype_int8 yytranslate[] =
static const yytype_uint8 yyrline[] =
{
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, 247
+ 140, 144, 149, 161, 166, 171, 176, 181, 186, 191,
+ 196, 201, 205, 209, 213, 217, 218, 223, 223, 223,
+ 224, 224, 225, 225, 226, 226, 227, 227, 228, 228,
+ 229, 229, 230, 230, 231, 231, 232, 232, 235, 236,
+ 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251
};
#endif
@@ -1747,142 +1747,146 @@ yyreduce:
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
}
+ if (cmsysString_strcasecmp((yyvsp[-4].string), "intrinsic") == 0) {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUseIntrinsic(parser, (yyvsp[-2].string));
+ }
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1754 "cmFortranParser.cxx"
+#line 1758 "cmFortranParser.cxx"
break;
case 13: /* stmt: INCLUDE STRING other EOSTMT */
-#line 157 "cmFortranParser.y"
+#line 161 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1764 "cmFortranParser.cxx"
+#line 1768 "cmFortranParser.cxx"
break;
case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */
-#line 162 "cmFortranParser.y"
+#line 166 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1774 "cmFortranParser.cxx"
+#line 1778 "cmFortranParser.cxx"
break;
case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */
-#line 167 "cmFortranParser.y"
+#line 171 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1784 "cmFortranParser.cxx"
+#line 1788 "cmFortranParser.cxx"
break;
case 16: /* stmt: include STRING other EOSTMT */
-#line 172 "cmFortranParser.y"
+#line 176 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1794 "cmFortranParser.cxx"
+#line 1798 "cmFortranParser.cxx"
break;
case 17: /* stmt: define WORD other EOSTMT */
-#line 177 "cmFortranParser.y"
+#line 181 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1804 "cmFortranParser.cxx"
+#line 1808 "cmFortranParser.cxx"
break;
case 18: /* stmt: undef WORD other EOSTMT */
-#line 182 "cmFortranParser.y"
+#line 186 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1814 "cmFortranParser.cxx"
+#line 1818 "cmFortranParser.cxx"
break;
case 19: /* stmt: ifdef WORD other EOSTMT */
-#line 187 "cmFortranParser.y"
+#line 191 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1824 "cmFortranParser.cxx"
+#line 1828 "cmFortranParser.cxx"
break;
case 20: /* stmt: ifndef WORD other EOSTMT */
-#line 192 "cmFortranParser.y"
+#line 196 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1834 "cmFortranParser.cxx"
+#line 1838 "cmFortranParser.cxx"
break;
case 21: /* stmt: if other EOSTMT */
-#line 197 "cmFortranParser.y"
+#line 201 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIf(parser);
}
-#line 1843 "cmFortranParser.cxx"
+#line 1847 "cmFortranParser.cxx"
break;
case 22: /* stmt: elif other EOSTMT */
-#line 201 "cmFortranParser.y"
+#line 205 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElif(parser);
}
-#line 1852 "cmFortranParser.cxx"
+#line 1856 "cmFortranParser.cxx"
break;
case 23: /* stmt: else other EOSTMT */
-#line 205 "cmFortranParser.y"
+#line 209 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElse(parser);
}
-#line 1861 "cmFortranParser.cxx"
+#line 1865 "cmFortranParser.cxx"
break;
case 24: /* stmt: endif other EOSTMT */
-#line 209 "cmFortranParser.y"
+#line 213 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleEndif(parser);
}
-#line 1870 "cmFortranParser.cxx"
+#line 1874 "cmFortranParser.cxx"
break;
case 48: /* misc_code: WORD */
-#line 231 "cmFortranParser.y"
+#line 235 "cmFortranParser.y"
{ free ((yyvsp[0].string)); }
-#line 1876 "cmFortranParser.cxx"
+#line 1880 "cmFortranParser.cxx"
break;
case 55: /* misc_code: STRING */
-#line 238 "cmFortranParser.y"
+#line 242 "cmFortranParser.y"
{ free ((yyvsp[0].string)); }
-#line 1882 "cmFortranParser.cxx"
+#line 1886 "cmFortranParser.cxx"
break;
-#line 1886 "cmFortranParser.cxx"
+#line 1890 "cmFortranParser.cxx"
default: break;
}
@@ -2107,6 +2111,6 @@ yyreturn:
return yyresult;
}
-#line 250 "cmFortranParser.y"
+#line 254 "cmFortranParser.y"
/* End of grammar */
diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y
index a3e1c24..8ef1903 100644
--- a/Source/LexerParser/cmFortranParser.y
+++ b/Source/LexerParser/cmFortranParser.y
@@ -151,6 +151,10 @@ stmt:
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, $5);
}
+ if (cmsysString_strcasecmp($3, "intrinsic") == 0) {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUseIntrinsic(parser, $5);
+ }
free($3);
free($5);
}
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index e6faef4..41e8a55 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -128,11 +128,11 @@ void QCMake::setBinaryDirectory(const QString& _dir)
}
cmProp gen = state->GetCacheEntryValue("CMAKE_GENERATOR");
if (gen) {
- const std::string* extraGen =
+ cmProp extraGen =
state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
std::string curGen =
- cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- *gen, extraGen ? *extraGen : "");
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(*gen,
+ *extraGen);
this->setGenerator(QString::fromLocal8Bit(curGen.c_str()));
}
@@ -550,17 +550,14 @@ void QCMake::loadPresets()
}
QCMakePreset preset;
- preset.name = std::move(QString::fromLocal8Bit(p.Name.data()));
- preset.displayName =
- std::move(QString::fromLocal8Bit(p.DisplayName.data()));
- preset.description =
- std::move(QString::fromLocal8Bit(p.Description.data()));
- preset.generator = std::move(QString::fromLocal8Bit(p.Generator.data()));
- preset.architecture =
- std::move(QString::fromLocal8Bit(p.Architecture.data()));
+ preset.name = QString::fromLocal8Bit(p.Name.data());
+ preset.displayName = QString::fromLocal8Bit(p.DisplayName.data());
+ preset.description = QString::fromLocal8Bit(p.Description.data());
+ preset.generator = QString::fromLocal8Bit(p.Generator.data());
+ preset.architecture = QString::fromLocal8Bit(p.Architecture.data());
preset.setArchitecture = !p.ArchitectureStrategy ||
p.ArchitectureStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set;
- preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data()));
+ preset.toolset = QString::fromLocal8Bit(p.Toolset.data());
preset.setToolset = !p.ToolsetStrategy ||
p.ToolsetStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set;
preset.enabled = it.Expanded && it.Expanded->ConditionResult &&
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 54b2998..9e0d80c 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -250,6 +250,9 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
bool cmArchiveWrite::Open()
{
+ if (!this->Error.empty()) {
+ return false;
+ }
if (archive_write_open(
this->Archive, this, nullptr,
reinterpret_cast<archive_write_callback*>(&Callback::Write),
diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx
index 99707a3..a69c00d 100644
--- a/Source/cmBinUtilsLinuxELFLinker.cxx
+++ b/Source/cmBinUtilsLinuxELFLinker.cxx
@@ -11,6 +11,7 @@
#include <cmsys/RegularExpression.hxx>
#include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h"
+#include "cmELF.h"
#include "cmLDConfigLDConfigTool.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -18,10 +19,6 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#ifdef CMake_USE_ELF_PARSER
-# include "cmELF.h"
-#endif
-
static std::string ReplaceOrigin(const std::string& rpath,
const std::string& origin)
{
@@ -91,7 +88,6 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies(
{
std::vector<std::string> parentRpaths;
-#ifdef CMake_USE_ELF_PARSER
cmELF elf(file.c_str());
if (!elf) {
return false;
@@ -106,7 +102,6 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies(
this->Machine = elf.GetMachine();
}
}
-#endif
return this->ScanDependencies(file, parentRpaths);
}
@@ -175,15 +170,11 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies(
namespace {
bool FileHasArchitecture(const char* filename, std::uint16_t machine)
{
-#ifdef CMake_USE_ELF_PARSER
cmELF elf(filename);
if (!elf) {
return false;
}
return machine == 0 || machine == elf.GetMachine();
-#else
- return true;
-#endif
}
}
diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index 1f99043..b2830e2 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -6,6 +6,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 1a950df..8fefaa6 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -500,7 +500,7 @@ cmProp cmCacheManager::GetInitializedCacheValue(const std::string& key) const
{
if (const auto* entry = this->GetCacheEntry(key)) {
if (entry->Initialized) {
- return &entry->GetValue();
+ return cmProp(entry->GetValue());
}
}
return nullptr;
@@ -568,10 +568,10 @@ std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const
cmProp cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const
{
if (prop == "TYPE") {
- return &cmState::CacheEntryTypeToString(this->Type);
+ return cmProp(cmState::CacheEntryTypeToString(this->Type));
}
if (prop == "VALUE") {
- return &this->Value;
+ return cmProp(this->Value);
}
return this->Properties.GetPropertyValue(prop);
}
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index 7a9a7dc..0238fb8 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -75,7 +75,7 @@ public:
cmProp GetCacheEntryValue(const std::string& key) const
{
if (const auto* entry = this->GetCacheEntry(key)) {
- return &entry->GetValue();
+ return cmProp(entry->GetValue());
}
return nullptr;
}
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index deddba8..415f0c0 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -113,7 +113,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
if (this->EscapeQuotes && value) {
return this->AddString(cmEscapeQuotes(*value));
}
- return this->AddString(cmToCStrSafe(value));
+ return this->AddString(value);
}
const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 7c2e20c..59e4141 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -39,10 +39,10 @@ std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const
return this->ConfigNames;
}
-const char* cmCommonTargetGenerator::GetFeature(const std::string& feature,
- const std::string& config)
+cmProp cmCommonTargetGenerator::GetFeature(const std::string& feature,
+ const std::string& config)
{
- return this->GeneratorTarget->GetFeature(feature, config)->c_str();
+ return this->GeneratorTarget->GetFeature(feature, config);
}
void cmCommonTargetGenerator::AddModuleDefinitionFlag(
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h
index a156a41..463a445 100644
--- a/Source/cmCommonTargetGenerator.h
+++ b/Source/cmCommonTargetGenerator.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include "cmProperty.h"
+
class cmGeneratorTarget;
class cmGlobalCommonGenerator;
class cmLinkLineComputer;
@@ -28,8 +30,7 @@ public:
protected:
// Feature query methods.
- const char* GetFeature(const std::string& feature,
- const std::string& config);
+ cmProp GetFeature(const std::string& feature, const std::string& config);
// Helper to add flag for windows .def file.
void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer,
@@ -40,6 +41,7 @@ protected:
cmLocalCommonGenerator* LocalCommonGenerator;
cmGlobalCommonGenerator* GlobalCommonGenerator;
std::vector<std::string> ConfigNames;
+ bool UseLWYU = false;
void AppendFortranFormatFlags(std::string& flags,
cmSourceFile const& source);
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index f99592c..68bc4d8 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -2,16 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmConditionEvaluator.h"
+#include <array>
#include <cstdio>
#include <cstdlib>
#include <functional>
+#include <iterator>
+#include <list>
#include <sstream>
#include <utility>
+#include <cm/string_view>
#include <cmext/algorithm>
#include "cmsys/RegularExpression.hxx"
+#include "cmExpandedCommandArgument.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmProperty.h"
@@ -20,40 +25,184 @@
#include "cmSystemTools.h"
#include "cmake.h"
-class cmTest;
-
-static std::string const keyAND = "AND";
-static std::string const keyCOMMAND = "COMMAND";
-static std::string const keyDEFINED = "DEFINED";
-static std::string const keyEQUAL = "EQUAL";
-static std::string const keyEXISTS = "EXISTS";
-static std::string const keyGREATER = "GREATER";
-static std::string const keyGREATER_EQUAL = "GREATER_EQUAL";
-static std::string const keyIN_LIST = "IN_LIST";
-static std::string const keyIS_ABSOLUTE = "IS_ABSOLUTE";
-static std::string const keyIS_DIRECTORY = "IS_DIRECTORY";
-static std::string const keyIS_NEWER_THAN = "IS_NEWER_THAN";
-static std::string const keyIS_SYMLINK = "IS_SYMLINK";
-static std::string const keyLESS = "LESS";
-static std::string const keyLESS_EQUAL = "LESS_EQUAL";
-static std::string const keyMATCHES = "MATCHES";
-static std::string const keyNOT = "NOT";
-static std::string const keyOR = "OR";
-static std::string const keyParenL = "(";
-static std::string const keyParenR = ")";
-static std::string const keyPOLICY = "POLICY";
-static std::string const keySTREQUAL = "STREQUAL";
-static std::string const keySTRGREATER = "STRGREATER";
-static std::string const keySTRGREATER_EQUAL = "STRGREATER_EQUAL";
-static std::string const keySTRLESS = "STRLESS";
-static std::string const keySTRLESS_EQUAL = "STRLESS_EQUAL";
-static std::string const keyTARGET = "TARGET";
-static std::string const keyTEST = "TEST";
-static std::string const keyVERSION_EQUAL = "VERSION_EQUAL";
-static std::string const keyVERSION_GREATER = "VERSION_GREATER";
-static std::string const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL";
-static std::string const keyVERSION_LESS = "VERSION_LESS";
-static std::string const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL";
+namespace {
+auto const keyAND = "AND"_s;
+auto const keyCOMMAND = "COMMAND"_s;
+auto const keyDEFINED = "DEFINED"_s;
+auto const keyEQUAL = "EQUAL"_s;
+auto const keyEXISTS = "EXISTS"_s;
+auto const keyGREATER = "GREATER"_s;
+auto const keyGREATER_EQUAL = "GREATER_EQUAL"_s;
+auto const keyIN_LIST = "IN_LIST"_s;
+auto const keyIS_ABSOLUTE = "IS_ABSOLUTE"_s;
+auto const keyIS_DIRECTORY = "IS_DIRECTORY"_s;
+auto const keyIS_NEWER_THAN = "IS_NEWER_THAN"_s;
+auto const keyIS_SYMLINK = "IS_SYMLINK"_s;
+auto const keyLESS = "LESS"_s;
+auto const keyLESS_EQUAL = "LESS_EQUAL"_s;
+auto const keyMATCHES = "MATCHES"_s;
+auto const keyNOT = "NOT"_s;
+auto const keyOR = "OR"_s;
+auto const keyParenL = "("_s;
+auto const keyParenR = ")"_s;
+auto const keyPOLICY = "POLICY"_s;
+auto const keySTREQUAL = "STREQUAL"_s;
+auto const keySTRGREATER = "STRGREATER"_s;
+auto const keySTRGREATER_EQUAL = "STRGREATER_EQUAL"_s;
+auto const keySTRLESS = "STRLESS"_s;
+auto const keySTRLESS_EQUAL = "STRLESS_EQUAL"_s;
+auto const keyTARGET = "TARGET"_s;
+auto const keyTEST = "TEST"_s;
+auto const keyVERSION_EQUAL = "VERSION_EQUAL"_s;
+auto const keyVERSION_GREATER = "VERSION_GREATER"_s;
+auto const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"_s;
+auto const keyVERSION_LESS = "VERSION_LESS"_s;
+auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s;
+
+cmSystemTools::CompareOp const MATCH2CMPOP[5] = {
+ cmSystemTools::OP_LESS, cmSystemTools::OP_LESS_EQUAL,
+ cmSystemTools::OP_GREATER, cmSystemTools::OP_GREATER_EQUAL,
+ cmSystemTools::OP_EQUAL
+};
+
+// Run-Time to Compile-Time template selector
+template <template <typename> class Comp, template <typename> class... Ops>
+struct cmRt2CtSelector
+{
+ template <typename T>
+ static bool eval(int r, T lhs, T rhs)
+ {
+ switch (r) {
+ case 0:
+ return false;
+ case 1:
+ return Comp<T>()(lhs, rhs);
+ default:
+ return cmRt2CtSelector<Ops...>::eval(r - 1, lhs, rhs);
+ }
+ }
+};
+
+template <template <typename> class Comp>
+struct cmRt2CtSelector<Comp>
+{
+ template <typename T>
+ static bool eval(int r, T lhs, T rhs)
+ {
+ return r == 1 && Comp<T>()(lhs, rhs);
+ }
+};
+
+std::string bool2string(bool const value)
+{
+ return std::string(std::size_t(1), static_cast<char>('0' + int(value)));
+}
+
+bool looksLikeSpecialVariable(const std::string& var,
+ cm::static_string_view prefix,
+ const std::size_t varNameLen)
+{
+ // NOTE Expecting a variable name at least 1 char length:
+ // <prefix> + `{` + <varname> + `}`
+ return ((prefix.size() + 3) <= varNameLen) &&
+ cmHasPrefix(var, cmStrCat(prefix, '{')) && var[varNameLen - 1] == '}';
+}
+} // anonymous namespace
+
+#if defined(__SUNPRO_CC)
+# define CM_INHERIT_CTOR(Class, Base, Tpl) \
+ template <typename... Args> \
+ Class(Args&&... args) \
+ : Base Tpl(std::forward<Args>(args)...) \
+ { \
+ }
+#else
+# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base;
+#endif
+
+// BEGIN cmConditionEvaluator::cmArgumentList
+class cmConditionEvaluator::cmArgumentList
+ : public std::list<cmExpandedCommandArgument>
+{
+ using base_t = std::list<cmExpandedCommandArgument>;
+
+public:
+ CM_INHERIT_CTOR(cmArgumentList, list, <cmExpandedCommandArgument>);
+
+ class CurrentAndNextIter
+ {
+ friend class cmConditionEvaluator::cmArgumentList;
+
+ public:
+ base_t::iterator current;
+ base_t::iterator next;
+
+ CurrentAndNextIter advance(base_t& args)
+ {
+ this->current = std::next(this->current);
+ this->next =
+ std::next(this->current, difference_type(this->current != args.end()));
+ return *this;
+ }
+
+ private:
+ CurrentAndNextIter(base_t& args)
+ : current(args.begin())
+ , next(std::next(this->current,
+ difference_type(this->current != args.end())))
+ {
+ }
+ };
+
+ class CurrentAndTwoMoreIter
+ {
+ friend class cmConditionEvaluator::cmArgumentList;
+
+ public:
+ base_t::iterator current;
+ base_t::iterator next;
+ base_t::iterator nextnext;
+
+ CurrentAndTwoMoreIter advance(base_t& args)
+ {
+ this->current = std::next(this->current);
+ this->next =
+ std::next(this->current, difference_type(this->current != args.end()));
+ this->nextnext =
+ std::next(this->next, difference_type(this->next != args.end()));
+ return *this;
+ }
+
+ private:
+ CurrentAndTwoMoreIter(base_t& args)
+ : current(args.begin())
+ , next(std::next(this->current,
+ difference_type(this->current != args.end())))
+ , nextnext(
+ std::next(this->next, difference_type(this->next != args.end())))
+ {
+ }
+ };
+
+ CurrentAndNextIter make2ArgsIterator() { return *this; }
+ CurrentAndTwoMoreIter make3ArgsIterator() { return *this; }
+
+ template <typename Iter>
+ void ReduceOneArg(const bool value, Iter args)
+ {
+ *args.current = cmExpandedCommandArgument(bool2string(value), true);
+ this->erase(args.next);
+ }
+
+ void ReduceTwoArgs(const bool value, CurrentAndTwoMoreIter args)
+ {
+ *args.current = cmExpandedCommandArgument(bool2string(value), true);
+ this->erase(args.nextnext);
+ this->erase(args.next);
+ }
+};
+
+// END cmConditionEvaluator::cmArgumentList
cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile,
cmListFileBacktrace bt)
@@ -99,25 +248,29 @@ bool cmConditionEvaluator::IsTrue(
// now loop through the arguments and see if we can reduce any of them
// we do this multiple times. Once for each level of precedence
// parens
- if (!this->HandleLevel0(newArgs, errorString, status)) {
- return false;
- }
- // predicates
- if (!this->HandleLevel1(newArgs, errorString, status)) {
- return false;
- }
- // binary ops
- if (!this->HandleLevel2(newArgs, errorString, status)) {
- return false;
- }
+ using handlerFn_t = bool (cmConditionEvaluator::*)(
+ cmArgumentList&, std::string&, MessageType&);
+ const std::array<handlerFn_t, 5> handlers = { {
+ &cmConditionEvaluator::HandleLevel0, // parenthesis
+ &cmConditionEvaluator::HandleLevel1, // predicates
+ &cmConditionEvaluator::HandleLevel2, // binary ops
+ &cmConditionEvaluator::HandleLevel3, // NOT
+ &cmConditionEvaluator::HandleLevel4 // AND OR
+ } };
+ for (auto fn : handlers) {
+ // Call the reducer 'till there is anything to reduce...
+ // (i.e., if after an iteration the size becomes smaller)
+ auto levelResult = true;
+ for (auto beginSize = newArgs.size();
+ (levelResult = (this->*fn)(newArgs, errorString, status)) &&
+ newArgs.size() < beginSize;
+ beginSize = newArgs.size()) {
+ }
- // NOT
- if (!this->HandleLevel3(newArgs, errorString, status)) {
- return false;
- }
- // AND OR
- if (!this->HandleLevel4(newArgs, errorString, status)) {
- return false;
+ if (!levelResult) {
+ // NOTE `errorString` supposed to be set already
+ return false;
+ }
}
// now at the end there should only be one argument left
@@ -147,11 +300,13 @@ cmProp cmConditionEvaluator::GetDefinitionIfUnquoted(
this->Policy54Status == cmPolicies::WARN) {
if (!this->Makefile.HasCMP0054AlreadyBeenReported(this->Backtrace.Top())) {
std::ostringstream e;
- e << (cmPolicies::GetPolicyWarning(cmPolicies::CMP0054)) << "\n";
- e << "Quoted variables like \"" << argument.GetValue()
- << "\" will no longer be dereferenced "
- "when the policy is set to NEW. "
+ // clang-format off
+ e << (cmPolicies::GetPolicyWarning(cmPolicies::CMP0054))
+ << "\n"
+ "Quoted variables like \"" << argument.GetValue() << "\" "
+ "will no longer be dereferenced when the policy is set to NEW. "
"Since the policy is not set the OLD behavior will be used.";
+ // clang-format on
this->Makefile.GetCMakeInstance()->IssueMessage(
MessageType::AUTHOR_WARNING, e.str(), this->Backtrace);
@@ -168,15 +323,16 @@ cmProp cmConditionEvaluator::GetVariableOrString(
cmProp def = this->GetDefinitionIfUnquoted(argument);
if (!def) {
- def = &argument.GetValue();
+ def = cmProp(argument.GetValue());
}
return def;
}
//=========================================================================
-bool cmConditionEvaluator::IsKeyword(std::string const& keyword,
- cmExpandedCommandArgument& argument) const
+bool cmConditionEvaluator::IsKeyword(
+ cm::static_string_view keyword,
+ const cmExpandedCommandArgument& argument) const
{
if ((this->Policy54Status != cmPolicies::WARN &&
this->Policy54Status != cmPolicies::OLD) &&
@@ -184,17 +340,20 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword,
return false;
}
- bool isKeyword = argument.GetValue() == keyword;
+ const auto isKeyword = argument.GetValue() == keyword;
if (isKeyword && argument.WasQuoted() &&
this->Policy54Status == cmPolicies::WARN) {
if (!this->Makefile.HasCMP0054AlreadyBeenReported(this->Backtrace.Top())) {
std::ostringstream e;
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0054) << "\n";
- e << "Quoted keywords like \"" << argument.GetValue()
- << "\" will no longer be interpreted as keywords "
+ // clang-format off
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0054)
+ << "\n"
+ "Quoted keywords like \"" << argument.GetValue() << "\" "
+ "will no longer be interpreted as keywords "
"when the policy is set to NEW. "
"Since the policy is not set the OLD behavior will be used.";
+ // clang-format on
this->Makefile.GetCMakeInstance()->IssueMessage(
MessageType::AUTHOR_WARNING, e.str(), this->Backtrace);
@@ -208,15 +367,7 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword,
bool cmConditionEvaluator::GetBooleanValue(
cmExpandedCommandArgument& arg) const
{
- // Check basic constants.
- if (arg == "0") {
- return false;
- }
- if (arg == "1") {
- return true;
- }
-
- // Check named constants.
+ // Check basic and named constants.
if (cmIsOn(arg.GetValue())) {
return true;
}
@@ -227,7 +378,7 @@ bool cmConditionEvaluator::GetBooleanValue(
// Check for numbers.
if (!arg.empty()) {
char* end;
- double d = strtod(arg.GetValue().c_str(), &end);
+ const double d = std::strtod(arg.GetValue().c_str(), &end);
if (*end == '\0') {
// The whole string is a number. Use C conversion to bool.
return static_cast<bool>(d);
@@ -242,7 +393,7 @@ bool cmConditionEvaluator::GetBooleanValue(
//=========================================================================
// Boolean value behavior from CMake 2.6.4 and below.
bool cmConditionEvaluator::GetBooleanValueOld(
- cmExpandedCommandArgument const& arg, bool one) const
+ cmExpandedCommandArgument const& arg, bool const one) const
{
if (one) {
// Old IsTrue behavior for single argument.
@@ -257,8 +408,8 @@ bool cmConditionEvaluator::GetBooleanValueOld(
}
// Old GetVariableOrNumber behavior.
cmProp def = this->GetDefinitionIfUnquoted(arg);
- if (!def && atoi(arg.GetValue().c_str())) {
- def = &arg.GetValue();
+ if (!def && std::atoi(arg.GetValue().c_str())) {
+ def = cmProp(arg.GetValue());
}
return !cmIsOff(def);
}
@@ -267,7 +418,7 @@ bool cmConditionEvaluator::GetBooleanValueOld(
// returns the resulting boolean value
bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
cmExpandedCommandArgument& newArg, std::string& errorString,
- MessageType& status, bool oneArg) const
+ MessageType& status, bool const oneArg) const
{
// Use the policy if it is set.
if (this->Policy12Status == cmPolicies::NEW) {
@@ -278,8 +429,8 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
}
// Check policy only if old and new results differ.
- bool newResult = this->GetBooleanValue(newArg);
- bool oldResult = this->GetBooleanValueOld(newArg, oneArg);
+ const auto newResult = this->GetBooleanValue(newArg);
+ const auto oldResult = this->GetBooleanValueOld(newArg, oneArg);
if (newResult != oldResult) {
switch (this->Policy12Status) {
case cmPolicies::WARN:
@@ -304,56 +455,31 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
return newResult;
}
-//=========================================================================
-void cmConditionEvaluator::IncrementArguments(
- cmArgumentList& newArgs, cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2) const
+template <int N>
+inline int cmConditionEvaluator::matchKeysImpl(
+ const cmExpandedCommandArgument&)
{
- if (argP1 != newArgs.end()) {
- argP1++;
- argP2 = argP1;
- if (argP1 != newArgs.end()) {
- argP2++;
- }
- }
+ // Zero means "not found"
+ return 0;
}
-//=========================================================================
-// helper function to reduce code duplication
-void cmConditionEvaluator::HandlePredicate(
- bool value, int& reducible, cmArgumentList::iterator& arg,
- cmArgumentList& newArgs, cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2) const
+template <int N, typename T, typename... Keys>
+inline int cmConditionEvaluator::matchKeysImpl(
+ const cmExpandedCommandArgument& arg, T current, Keys... key)
{
- if (value) {
- *arg = cmExpandedCommandArgument("1", true);
- } else {
- *arg = cmExpandedCommandArgument("0", true);
+ if (this->IsKeyword(current, arg)) {
+ // Stop searching as soon as smth has found
+ return N;
}
- newArgs.erase(argP1);
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- reducible = 1;
+ return matchKeysImpl<N + 1>(arg, key...);
}
-//=========================================================================
-// helper function to reduce code duplication
-void cmConditionEvaluator::HandleBinaryOp(bool value, int& reducible,
- cmArgumentList::iterator& arg,
- cmArgumentList& newArgs,
- cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2)
+template <typename... Keys>
+inline int cmConditionEvaluator::matchKeys(
+ const cmExpandedCommandArgument& arg, Keys... key)
{
- if (value) {
- *arg = cmExpandedCommandArgument("1", true);
- } else {
- *arg = cmExpandedCommandArgument("0", true);
- }
- newArgs.erase(argP2);
- newArgs.erase(argP1);
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- reducible = 1;
+ // Get index of the matched key (1-based)
+ return matchKeysImpl<1>(arg, key...);
}
//=========================================================================
@@ -362,55 +488,35 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
std::string& errorString,
MessageType& status)
{
- int reducible;
- do {
- reducible = 0;
- auto arg = newArgs.begin();
- while (arg != newArgs.end()) {
- if (this->IsKeyword(keyParenL, *arg)) {
- // search for the closing paren for this opening one
- cmArgumentList::iterator argClose;
- argClose = arg;
- argClose++;
- unsigned int depth = 1;
- while (argClose != newArgs.end() && depth) {
- if (this->IsKeyword(keyParenL, *argClose)) {
- depth++;
- }
- if (this->IsKeyword(keyParenR, *argClose)) {
- depth--;
- }
- argClose++;
- }
- if (depth) {
- errorString = "mismatched parenthesis in condition";
- status = MessageType::FATAL_ERROR;
- return false;
- }
- // store the reduced args in this vector
- std::vector<cmExpandedCommandArgument> newArgs2;
-
- // copy to the list structure
- auto argP1 = arg;
- argP1++;
- cm::append(newArgs2, argP1, argClose);
- newArgs2.pop_back();
- // now recursively invoke IsTrue to handle the values inside the
- // parenthetical expression
- bool value = this->IsTrue(newArgs2, errorString, status);
- if (value) {
- *arg = cmExpandedCommandArgument("1", true);
- } else {
- *arg = cmExpandedCommandArgument("0", true);
- }
- argP1 = arg;
- argP1++;
- // remove the now evaluated parenthetical expression
- newArgs.erase(argP1, argClose);
+ for (auto arg = newArgs.begin(); arg != newArgs.end(); ++arg) {
+ if (this->IsKeyword(keyParenL, *arg)) {
+ // search for the closing paren for this opening one
+ auto depth = 1;
+ auto argClose = std::next(arg);
+ for (; argClose != newArgs.end() && depth; ++argClose) {
+ depth += int(this->IsKeyword(keyParenL, *argClose)) -
+ int(this->IsKeyword(keyParenR, *argClose));
}
- ++arg;
+ if (depth) {
+ errorString = "mismatched parenthesis in condition";
+ status = MessageType::FATAL_ERROR;
+ return false;
+ }
+
+ // store the reduced args in this vector
+ auto argOpen = std::next(arg);
+ const std::vector<cmExpandedCommandArgument> subExpr(
+ argOpen, std::prev(argClose));
+
+ // now recursively invoke IsTrue to handle the values inside the
+ // parenthetical expression
+ const auto value = this->IsTrue(subExpr, errorString, status);
+ *arg = cmExpandedCommandArgument(bool2string(value), true);
+ argOpen = std::next(arg);
+ // remove the now evaluated parenthetical expression
+ newArgs.erase(argOpen, argClose);
}
- } while (reducible);
+ }
return true;
}
@@ -419,96 +525,104 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
MessageType&)
{
- int reducible;
- do {
- reducible = 0;
- auto arg = newArgs.begin();
- cmArgumentList::iterator argP1;
- cmArgumentList::iterator argP2;
- while (arg != newArgs.end()) {
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- // does a file exist
- if (this->IsKeyword(keyEXISTS, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a directory with this name exist
- if (this->IsKeyword(keyIS_DIRECTORY, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(
- cmSystemTools::FileIsDirectory(argP1->GetValue()), reducible, arg,
- newArgs, argP1, argP2);
- }
- // does a symlink with this name exist
- if (this->IsKeyword(keyIS_SYMLINK, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // is the given path an absolute path ?
- if (this->IsKeyword(keyIS_ABSOLUTE, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a command exist
- if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) {
- cmState::Command command =
- this->Makefile.GetState()->GetCommand(argP1->GetValue());
- this->HandlePredicate(command != nullptr, reducible, arg, newArgs,
- argP1, argP2);
- }
- // does a policy exist
- if (this->IsKeyword(keyPOLICY, *arg) && argP1 != newArgs.end()) {
- cmPolicies::PolicyID pid;
- this->HandlePredicate(
- cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), reducible,
- arg, newArgs, argP1, argP2);
- }
- // does a target exist
- if (this->IsKeyword(keyTARGET, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(
- this->Makefile.FindTargetToUse(argP1->GetValue()) != nullptr,
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a test exist
- if (this->Policy64Status != cmPolicies::OLD &&
- this->Policy64Status != cmPolicies::WARN) {
- if (this->IsKeyword(keyTEST, *arg) && argP1 != newArgs.end()) {
- const cmTest* haveTest = this->Makefile.GetTest(argP1->GetValue());
- this->HandlePredicate(haveTest != nullptr, reducible, arg, newArgs,
- argP1, argP2);
- }
- } else if (this->Policy64Status == cmPolicies::WARN &&
- this->IsKeyword(keyTEST, *arg)) {
+ const auto policy64IsOld = this->Policy64Status == cmPolicies::OLD ||
+ this->Policy64Status == cmPolicies::WARN;
+
+ for (auto args = newArgs.make2ArgsIterator(); args.current != newArgs.end();
+ args.advance(newArgs)) {
+
+ auto policyCheck = [&, this](const cmPolicies::PolicyID id,
+ const cmPolicies::PolicyStatus status,
+ const cm::static_string_view kw) {
+ if (status == cmPolicies::WARN && this->IsKeyword(kw, *args.current)) {
std::ostringstream e;
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0064) << "\n";
- e << "TEST will be interpreted as an operator "
+ e << cmPolicies::GetPolicyWarning(id) << "\n"
+ << kw
+ << " will be interpreted as an operator "
"when the policy is set to NEW. "
"Since the policy is not set the OLD behavior will be used.";
this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
- // is a variable defined
- if (this->IsKeyword(keyDEFINED, *arg) && argP1 != newArgs.end()) {
- size_t argP1len = argP1->GetValue().size();
- bool bdef = false;
- if (argP1len > 4 && cmHasLiteralPrefix(argP1->GetValue(), "ENV{") &&
- argP1->GetValue().operator[](argP1len - 1) == '}') {
- std::string env = argP1->GetValue().substr(4, argP1len - 5);
- bdef = cmSystemTools::HasEnv(env);
- } else if (argP1len > 6 &&
- cmHasLiteralPrefix(argP1->GetValue(), "CACHE{") &&
- argP1->GetValue().operator[](argP1len - 1) == '}') {
- std::string cache = argP1->GetValue().substr(6, argP1len - 7);
- bdef =
- this->Makefile.GetState()->GetCacheEntryValue(cache) != nullptr;
- } else {
- bdef = this->Makefile.IsDefinitionSet(argP1->GetValue());
- }
- this->HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2);
+ };
+
+ // NOTE Checking policies for warnings are not require an access to the
+ // next arg. Check them first!
+ policyCheck(cmPolicies::CMP0064, this->Policy64Status, keyTEST);
+
+ // NOTE Fail fast: All the predicates below require the next arg to be
+ // valid
+ if (args.next == newArgs.end()) {
+ continue;
+ }
+
+ // does a file exist
+ if (this->IsKeyword(keyEXISTS, *args.current)) {
+ newArgs.ReduceOneArg(cmSystemTools::FileExists(args.next->GetValue()),
+ args);
+ }
+ // does a directory with this name exist
+ else if (this->IsKeyword(keyIS_DIRECTORY, *args.current)) {
+ newArgs.ReduceOneArg(
+ cmSystemTools::FileIsDirectory(args.next->GetValue()), args);
+ }
+ // does a symlink with this name exist
+ else if (this->IsKeyword(keyIS_SYMLINK, *args.current)) {
+ newArgs.ReduceOneArg(cmSystemTools::FileIsSymlink(args.next->GetValue()),
+ args);
+ }
+ // is the given path an absolute path ?
+ else if (this->IsKeyword(keyIS_ABSOLUTE, *args.current)) {
+ newArgs.ReduceOneArg(
+ cmSystemTools::FileIsFullPath(args.next->GetValue()), args);
+ }
+ // does a command exist
+ else if (this->IsKeyword(keyCOMMAND, *args.current)) {
+ newArgs.ReduceOneArg(
+ bool(this->Makefile.GetState()->GetCommand(args.next->GetValue())),
+ args);
+ }
+ // does a policy exist
+ else if (this->IsKeyword(keyPOLICY, *args.current)) {
+ cmPolicies::PolicyID pid;
+ newArgs.ReduceOneArg(
+ cmPolicies::GetPolicyID(args.next->GetValue().c_str(), pid), args);
+ }
+ // does a target exist
+ else if (this->IsKeyword(keyTARGET, *args.current)) {
+ newArgs.ReduceOneArg(
+ bool(this->Makefile.FindTargetToUse(args.next->GetValue())), args);
+ }
+ // is a variable defined
+ else if (this->IsKeyword(keyDEFINED, *args.current)) {
+ const auto& var = args.next->GetValue();
+ const auto varNameLen = var.size();
+
+ auto result = false;
+ if (looksLikeSpecialVariable(var, "ENV"_s, varNameLen)) {
+ const auto env = args.next->GetValue().substr(4, varNameLen - 5);
+ result = cmSystemTools::HasEnv(env);
+ }
+
+ else if (looksLikeSpecialVariable(var, "CACHE"_s, varNameLen)) {
+ const auto cache = args.next->GetValue().substr(6, varNameLen - 7);
+ result = bool(this->Makefile.GetState()->GetCacheEntryValue(cache));
}
- ++arg;
+
+ else {
+ result = this->Makefile.IsDefinitionSet(args.next->GetValue());
+ }
+ newArgs.ReduceOneArg(result, args);
+ }
+ // does a test exist
+ else if (this->IsKeyword(keyTEST, *args.current)) {
+ if (policy64IsOld) {
+ continue;
+ }
+ newArgs.ReduceOneArg(bool(this->Makefile.GetTest(args.next->GetValue())),
+ args);
}
- } while (reducible);
+ }
return true;
}
@@ -518,178 +632,143 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
std::string& errorString,
MessageType& status)
{
- int reducible;
- std::string def_buf;
- cmProp def;
- cmProp def2;
- do {
- reducible = 0;
- auto arg = newArgs.begin();
- cmArgumentList::iterator argP1;
- cmArgumentList::iterator argP2;
- while (arg != newArgs.end()) {
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- this->IsKeyword(keyMATCHES, *argP1)) {
- def = this->GetDefinitionIfUnquoted(*arg);
- if (!def) {
- def = &arg->GetValue();
- } else if (cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) {
- // The string to match is owned by our match result variables.
- // Move it to our own buffer before clearing them.
- def_buf = *def;
- def = &def_buf;
- }
- const std::string& rex = argP2->GetValue();
- this->Makefile.ClearMatches();
- cmsys::RegularExpression regEntry;
- if (!regEntry.compile(rex)) {
- std::ostringstream error;
- error << "Regular expression \"" << rex << "\" cannot compile";
- errorString = error.str();
- status = MessageType::FATAL_ERROR;
- return false;
- }
- if (regEntry.find(*def)) {
- this->Makefile.StoreMatches(regEntry);
- *arg = cmExpandedCommandArgument("1", true);
- } else {
- *arg = cmExpandedCommandArgument("0", true);
- }
- newArgs.erase(argP2);
- newArgs.erase(argP1);
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- reducible = 1;
- }
+ for (auto args = newArgs.make3ArgsIterator(); args.current != newArgs.end();
+ args.advance(newArgs)) {
- if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) {
- *arg = cmExpandedCommandArgument("0", true);
- newArgs.erase(argP1);
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- reducible = 1;
- }
+ int matchNo;
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- (this->IsKeyword(keyLESS, *argP1) ||
- this->IsKeyword(keyLESS_EQUAL, *argP1) ||
- this->IsKeyword(keyGREATER, *argP1) ||
- this->IsKeyword(keyGREATER_EQUAL, *argP1) ||
- this->IsKeyword(keyEQUAL, *argP1))) {
- def = this->GetVariableOrString(*arg);
- def2 = this->GetVariableOrString(*argP2);
- double lhs;
- double rhs;
- bool result;
- if (sscanf(def->c_str(), "%lg", &lhs) != 1 ||
- sscanf(def2->c_str(), "%lg", &rhs) != 1) {
- result = false;
- } else if (*(argP1) == keyLESS) {
- result = (lhs < rhs);
- } else if (*(argP1) == keyLESS_EQUAL) {
- result = (lhs <= rhs);
- } else if (*(argP1) == keyGREATER) {
- result = (lhs > rhs);
- } else if (*(argP1) == keyGREATER_EQUAL) {
- result = (lhs >= rhs);
- } else {
- result = (lhs == rhs);
- }
- this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
- }
+ // NOTE Handle special case `if(... BLAH_BLAH MATCHES)`
+ // (i.e., w/o regex to match which is possibly result of
+ // variable expansion to an empty string)
+ if (args.next != newArgs.end() &&
+ this->IsKeyword(keyMATCHES, *args.current)) {
+ newArgs.ReduceOneArg(false, args);
+ }
+
+ // NOTE Fail fast: All the binary ops below require 2 arguments.
+ else if (args.next == newArgs.end() || args.nextnext == newArgs.end()) {
+ continue;
+ }
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- (this->IsKeyword(keySTRLESS, *argP1) ||
- this->IsKeyword(keySTRLESS_EQUAL, *argP1) ||
- this->IsKeyword(keySTRGREATER, *argP1) ||
- this->IsKeyword(keySTRGREATER_EQUAL, *argP1) ||
- this->IsKeyword(keySTREQUAL, *argP1))) {
- def = this->GetVariableOrString(*arg);
- def2 = this->GetVariableOrString(*argP2);
- int val = (*def).compare(*def2);
- bool result;
- if (*(argP1) == keySTRLESS) {
- result = (val < 0);
- } else if (*(argP1) == keySTRLESS_EQUAL) {
- result = (val <= 0);
- } else if (*(argP1) == keySTRGREATER) {
- result = (val > 0);
- } else if (*(argP1) == keySTRGREATER_EQUAL) {
- result = (val >= 0);
- } else // strequal
- {
- result = (val == 0);
- }
- this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
+ else if (this->IsKeyword(keyMATCHES, *args.next)) {
+ cmProp def = this->GetDefinitionIfUnquoted(*args.current);
+
+ std::string def_buf;
+ if (!def) {
+ def = cmProp(args.current->GetValue());
+ } else if (cmHasLiteralPrefix(args.current->GetValue(),
+ "CMAKE_MATCH_")) {
+ // The string to match is owned by our match result variables.
+ // Move it to our own buffer before clearing them.
+ def_buf = *def;
+ def = cmProp(def_buf);
}
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- (this->IsKeyword(keyVERSION_LESS, *argP1) ||
- this->IsKeyword(keyVERSION_LESS_EQUAL, *argP1) ||
- this->IsKeyword(keyVERSION_GREATER, *argP1) ||
- this->IsKeyword(keyVERSION_GREATER_EQUAL, *argP1) ||
- this->IsKeyword(keyVERSION_EQUAL, *argP1))) {
- def = this->GetVariableOrString(*arg);
- def2 = this->GetVariableOrString(*argP2);
- cmSystemTools::CompareOp op;
- if (*argP1 == keyVERSION_LESS) {
- op = cmSystemTools::OP_LESS;
- } else if (*argP1 == keyVERSION_LESS_EQUAL) {
- op = cmSystemTools::OP_LESS_EQUAL;
- } else if (*argP1 == keyVERSION_GREATER) {
- op = cmSystemTools::OP_GREATER;
- } else if (*argP1 == keyVERSION_GREATER_EQUAL) {
- op = cmSystemTools::OP_GREATER_EQUAL;
- } else { // version_equal
- op = cmSystemTools::OP_EQUAL;
- }
- bool result =
- cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str());
- this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
+ this->Makefile.ClearMatches();
+
+ const auto& rex = args.nextnext->GetValue();
+ cmsys::RegularExpression regEntry;
+ if (!regEntry.compile(rex)) {
+ std::ostringstream error;
+ error << "Regular expression \"" << rex << "\" cannot compile";
+ errorString = error.str();
+ status = MessageType::FATAL_ERROR;
+ return false;
}
- // is file A newer than file B
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- this->IsKeyword(keyIS_NEWER_THAN, *argP1)) {
- int fileIsNewer = 0;
- cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare(
- arg->GetValue(), (argP2)->GetValue(), &fileIsNewer);
- this->HandleBinaryOp(
- (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg,
- newArgs, argP1, argP2);
+ const auto match = regEntry.find(*def);
+ if (match) {
+ this->Makefile.StoreMatches(regEntry);
}
+ newArgs.ReduceTwoArgs(match, args);
+ }
+
+ else if ((matchNo =
+ this->matchKeys(*args.next, keyLESS, keyLESS_EQUAL, keyGREATER,
+ keyGREATER_EQUAL, keyEQUAL))) {
+
+ cmProp ldef = this->GetVariableOrString(*args.current);
+ cmProp rdef = this->GetVariableOrString(*args.nextnext);
+
+ double lhs;
+ double rhs;
+ auto parseDoubles = [&]() {
+ return std::sscanf(ldef->c_str(), "%lg", &lhs) == 1 &&
+ std::sscanf(rdef->c_str(), "%lg", &rhs) == 1;
+ };
+ // clang-format off
+ const auto result = parseDoubles() &&
+ cmRt2CtSelector<
+ std::less, std::less_equal,
+ std::greater, std::greater_equal,
+ std::equal_to
+ >::eval(matchNo, lhs, rhs);
+ // clang-format on
+ newArgs.ReduceTwoArgs(result, args);
+ }
+
+ else if ((matchNo = this->matchKeys(*args.next, keySTRLESS,
+ keySTRLESS_EQUAL, keySTRGREATER,
+ keySTRGREATER_EQUAL, keySTREQUAL))) {
+
+ const cmProp lhs = this->GetVariableOrString(*args.current);
+ const cmProp rhs = this->GetVariableOrString(*args.nextnext);
+ const auto val = (*lhs).compare(*rhs);
+ // clang-format off
+ const auto result = cmRt2CtSelector<
+ std::less, std::less_equal,
+ std::greater, std::greater_equal,
+ std::equal_to
+ >::eval(matchNo, val, 0);
+ // clang-format on
+ newArgs.ReduceTwoArgs(result, args);
+ }
+
+ else if ((matchNo =
+ this->matchKeys(*args.next, keyVERSION_LESS,
+ keyVERSION_LESS_EQUAL, keyVERSION_GREATER,
+ keyVERSION_GREATER_EQUAL, keyVERSION_EQUAL))) {
+ const auto op = MATCH2CMPOP[matchNo - 1];
+ const cmProp lhs = this->GetVariableOrString(*args.current);
+ const cmProp rhs = this->GetVariableOrString(*args.nextnext);
+ const auto result =
+ cmSystemTools::VersionCompare(op, lhs->c_str(), rhs->c_str());
+ newArgs.ReduceTwoArgs(result, args);
+ }
+
+ // is file A newer than file B
+ else if (this->IsKeyword(keyIS_NEWER_THAN, *args.next)) {
+ auto fileIsNewer = 0;
+ cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare(
+ args.current->GetValue(), args.nextnext->GetValue(), &fileIsNewer);
+ newArgs.ReduceTwoArgs(
+ (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), args);
+ }
+
+ else if (this->IsKeyword(keyIN_LIST, *args.next)) {
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- this->IsKeyword(keyIN_LIST, *argP1)) {
- if (this->Policy57Status != cmPolicies::OLD &&
- this->Policy57Status != cmPolicies::WARN) {
- bool result = false;
-
- def = this->GetVariableOrString(*arg);
- def2 = this->Makefile.GetDefinition(argP2->GetValue());
-
- if (def2) {
- std::vector<std::string> list = cmExpandedList(*def2, true);
- result = cm::contains(list, *def);
- }
-
- this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
- } else if (this->Policy57Status == cmPolicies::WARN) {
- std::ostringstream e;
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) << "\n";
- e << "IN_LIST will be interpreted as an operator "
- "when the policy is set to NEW. "
- "Since the policy is not set the OLD behavior will be used.";
-
- this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
- }
+ if (this->Policy57Status != cmPolicies::OLD &&
+ this->Policy57Status != cmPolicies::WARN) {
+
+ cmProp lhs = this->GetVariableOrString(*args.current);
+ cmProp rhs = this->Makefile.GetDefinition(args.nextnext->GetValue());
+
+ newArgs.ReduceTwoArgs(
+ rhs && cm::contains(cmExpandedList(*rhs, true), *lhs), args);
}
- ++arg;
+ else if (this->Policy57Status == cmPolicies::WARN) {
+ std::ostringstream e;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057)
+ << "\n"
+ "IN_LIST will be interpreted as an operator "
+ "when the policy is set to NEW. "
+ "Since the policy is not set the OLD behavior will be used.";
+
+ this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
+ }
}
- } while (reducible);
+ }
return true;
}
@@ -699,23 +778,14 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs,
std::string& errorString,
MessageType& status)
{
- int reducible;
- do {
- reducible = 0;
- auto arg = newArgs.begin();
- cmArgumentList::iterator argP1;
- cmArgumentList::iterator argP2;
- while (arg != newArgs.end()) {
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) {
- bool rhs = this->GetBooleanValueWithAutoDereference(
- *argP1, errorString, status);
- this->HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2);
- }
- ++arg;
+ for (auto args = newArgs.make2ArgsIterator(); args.next != newArgs.end();
+ args.advance(newArgs)) {
+ if (this->IsKeyword(keyNOT, *args.current)) {
+ const auto rhs = this->GetBooleanValueWithAutoDereference(
+ *args.next, errorString, status);
+ newArgs.ReduceOneArg(!rhs, args);
}
- } while (reducible);
+ }
return true;
}
@@ -725,38 +795,24 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs,
std::string& errorString,
MessageType& status)
{
- int reducible;
- bool lhs;
- bool rhs;
- do {
- reducible = 0;
- auto arg = newArgs.begin();
- cmArgumentList::iterator argP1;
- cmArgumentList::iterator argP2;
- while (arg != newArgs.end()) {
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- if (argP1 != newArgs.end() && this->IsKeyword(keyAND, *argP1) &&
- argP2 != newArgs.end()) {
- lhs =
- this->GetBooleanValueWithAutoDereference(*arg, errorString, status);
- rhs = this->GetBooleanValueWithAutoDereference(*argP2, errorString,
- status);
- this->HandleBinaryOp((lhs && rhs), reducible, arg, newArgs, argP1,
- argP2);
- }
-
- if (argP1 != newArgs.end() && this->IsKeyword(keyOR, *argP1) &&
- argP2 != newArgs.end()) {
- lhs =
- this->GetBooleanValueWithAutoDereference(*arg, errorString, status);
- rhs = this->GetBooleanValueWithAutoDereference(*argP2, errorString,
- status);
- this->HandleBinaryOp((lhs || rhs), reducible, arg, newArgs, argP1,
- argP2);
- }
- ++arg;
+ for (auto args = newArgs.make3ArgsIterator(); args.nextnext != newArgs.end();
+ args.advance(newArgs)) {
+
+ int matchNo;
+
+ if ((matchNo = this->matchKeys(*args.next, keyAND, keyOR))) {
+ const auto lhs = this->GetBooleanValueWithAutoDereference(
+ *args.current, errorString, status);
+ const auto rhs = this->GetBooleanValueWithAutoDereference(
+ *args.nextnext, errorString, status);
+ // clang-format off
+ const auto result =
+ cmRt2CtSelector<
+ std::logical_and, std::logical_or
+ >::eval(matchNo, lhs, rhs);
+ // clang-format on
+ newArgs.ReduceTwoArgs(result, args);
}
- } while (reducible);
+ }
return true;
}
diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h
index cf00ede..00d896b 100644
--- a/Source/cmConditionEvaluator.h
+++ b/Source/cmConditionEvaluator.h
@@ -4,23 +4,22 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <list>
#include <string>
#include <vector>
-#include "cmExpandedCommandArgument.h"
+#include <cmext/string_view>
+
#include "cmListFileCache.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmProperty.h"
+class cmExpandedCommandArgument;
class cmMakefile;
class cmConditionEvaluator
{
public:
- using cmArgumentList = std::list<cmExpandedCommandArgument>;
-
cmConditionEvaluator(cmMakefile& makefile, cmListFileBacktrace bt);
// this is a shared function for both If and Else to determine if the
@@ -30,14 +29,16 @@ public:
std::string& errorString, MessageType& status);
private:
+ class cmArgumentList;
+
// Filter the given variable definition based on policy CMP0054.
cmProp GetDefinitionIfUnquoted(
const cmExpandedCommandArgument& argument) const;
cmProp GetVariableOrString(const cmExpandedCommandArgument& argument) const;
- bool IsKeyword(std::string const& keyword,
- cmExpandedCommandArgument& argument) const;
+ bool IsKeyword(cm::static_string_view keyword,
+ const cmExpandedCommandArgument& argument) const;
bool GetBooleanValue(cmExpandedCommandArgument& arg) const;
@@ -49,19 +50,14 @@ private:
MessageType& status,
bool oneArg = false) const;
- void IncrementArguments(cmArgumentList& newArgs,
- cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2) const;
+ template <int N>
+ int matchKeysImpl(const cmExpandedCommandArgument&);
- void HandlePredicate(bool value, int& reducible,
- cmArgumentList::iterator& arg, cmArgumentList& newArgs,
- cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2) const;
+ template <int N, typename T, typename... Keys>
+ int matchKeysImpl(const cmExpandedCommandArgument&, T, Keys...);
- void HandleBinaryOp(bool value, int& reducible,
- cmArgumentList::iterator& arg, cmArgumentList& newArgs,
- cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2);
+ template <typename... Keys>
+ int matchKeys(const cmExpandedCommandArgument&, Keys...);
bool HandleLevel0(cmArgumentList& newArgs, std::string& errorString,
MessageType& status);
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index aeca6b4..6a419f6 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -16,7 +16,6 @@
#cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE
#cmakedefine HAVE_UNSETENV
-#cmakedefine CMake_USE_ELF_PARSER
#cmakedefine CMake_USE_MACH_PARSER
#cmakedefine CMake_USE_XCOFF_PARSER
#define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index bf18143..0fd48f0 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -606,7 +606,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
std::string langFlags = "CMAKE_" + li + "_FLAGS";
cmProp flags = this->Makefile->GetDefinition(langFlags);
fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li.c_str(),
- cmOutputConverter::EscapeForCMake(cmToCStrSafe(flags)).c_str());
+ cmOutputConverter::EscapeForCMake(flags).c_str());
fprintf(fout,
"set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
" ${COMPILE_DEFINITIONS}\")\n",
@@ -644,9 +644,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
std::string const langFlagsCfg =
cmStrCat("CMAKE_", li, "_FLAGS_", cfg);
cmProp flagsCfg = this->Makefile->GetDefinition(langFlagsCfg);
- fprintf(
- fout, "set(%s %s)\n", langFlagsCfg.c_str(),
- cmOutputConverter::EscapeForCMake(cmToCStrSafe(flagsCfg)).c_str());
+ fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(),
+ cmOutputConverter::EscapeForCMake(flagsCfg).c_str());
}
} break;
}
@@ -679,8 +678,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
cmProp exeLinkFlags =
this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS");
fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n",
- cmOutputConverter::EscapeForCMake(cmToCStrSafe(exeLinkFlags))
- .c_str());
+ cmOutputConverter::EscapeForCMake(exeLinkFlags).c_str());
}
break;
}
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx
index 4a4f87d..9e2d7b9 100644
--- a/Source/cmDefinitions.cxx
+++ b/Source/cmDefinitions.cxx
@@ -34,11 +34,11 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key,
return begin->Map.emplace(key, def).first->second;
}
-const std::string* cmDefinitions::Get(const std::string& key, StackIter begin,
- StackIter end)
+cmProp cmDefinitions::Get(const std::string& key, StackIter begin,
+ StackIter end)
{
Def const& def = cmDefinitions::GetInternal(key, begin, end, false);
- return def.Value ? def.Value.str_if_stable() : nullptr;
+ return def.Value ? cmProp(def.Value.str_if_stable()) : nullptr;
}
void cmDefinitions::Raise(const std::string& key, StackIter begin,
diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h
index b650aa8..ee1db7a 100644
--- a/Source/cmDefinitions.h
+++ b/Source/cmDefinitions.h
@@ -12,6 +12,7 @@
#include <cm/string_view>
#include "cmLinkedTree.h"
+#include "cmProperty.h"
#include "cmString.hxx"
/** \class cmDefinitions
@@ -28,8 +29,7 @@ class cmDefinitions
public:
// -- Static member functions
- static const std::string* Get(const std::string& key, StackIter begin,
- StackIter end);
+ static cmProp Get(const std::string& key, StackIter begin, StackIter end);
static void Raise(const std::string& key, StackIter begin, StackIter end);
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index bca26b9..6024cf6 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -163,12 +163,17 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory();
}
+ bool building_intrinsics =
+ !mf->GetSafeDefinition("CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_MODULES")
+ .empty();
+
// Actually write dependencies to the streams.
using ObjectInfoMap = cmDependsFortranInternals::ObjectInfoMap;
ObjectInfoMap const& objInfo = this->Internal->ObjectInfo;
for (auto const& i : objInfo) {
if (!this->WriteDependenciesReal(i.first, i.second, mod_dir, stamp_dir,
- makeDepends, internalDepends)) {
+ makeDepends, internalDepends,
+ building_intrinsics)) {
return false;
}
}
@@ -307,7 +312,8 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
std::string const& mod_dir,
std::string const& stamp_dir,
std::ostream& makeDepends,
- std::ostream& internalDepends)
+ std::ostream& internalDepends,
+ bool buildingIntrinsics)
{
// Get the source file for this object.
std::string const& src = info.Source;
@@ -339,8 +345,13 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
makeDepends << '\n';
}
+ std::set<std::string> req = info.Requires;
+ if (buildingIntrinsics) {
+ req.insert(info.Intrinsics.begin(), info.Intrinsics.end());
+ }
+
// Write module requirements to the output stream.
- for (std::string const& i : info.Requires) {
+ for (std::string const& i : req) {
// Require only modules not provided in the same source.
if (info.Provides.find(i) != info.Provides.cend()) {
continue;
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index 0d407bc..a74db91 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -72,7 +72,8 @@ protected:
std::string const& mod_dir,
std::string const& stamp_dir,
std::ostream& makeDepends,
- std::ostream& internalDepends);
+ std::ostream& internalDepends,
+ bool buildingIntrinsics);
// The source file from which to start scanning.
std::string SourceFile;
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index 9a474e3..1678ce8 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -17,41 +17,9 @@
#include "cmsys/FStream.hxx"
-// Include the ELF format information system header.
-#if defined(__OpenBSD__)
-# include <elf_abi.h>
-#elif defined(__HAIKU__)
-# include <elf32.h>
-# include <elf64.h>
-using Elf32_Ehdr = struct Elf32_Ehdr;
-using Elf32_Shdr = struct Elf32_Shdr;
-using Elf32_Sym = struct Elf32_Sym;
-using Elf32_Rel = struct Elf32_Rel;
-using Elf32_Rela = struct Elf32_Rela;
-# define ELFMAG0 0x7F
-# define ELFMAG1 'E'
-# define ELFMAG2 'L'
-# define ELFMAG3 'F'
-# define ET_NONE 0
-# define ET_REL 1
-# define ET_EXEC 2
-# define ET_DYN 3
-# define ET_CORE 4
-# define EM_386 3
-# define EM_SPARC 2
-# define EM_PPC 20
-#else
-# include <elf.h>
-#endif
-#if defined(__sun)
-# include <sys/link.h> // For dynamic section information
-#endif
-#ifdef _SCO_DS
-# include <link.h> // For DT_SONAME etc.
-#endif
-#ifndef DT_RUNPATH
-# define DT_RUNPATH 29
-#endif
+#include "cmelf/elf32.h"
+#include "cmelf/elf64.h"
+#include "cmelf/elf_common.h"
// Low-level byte swapping implementation.
template <size_t s>
@@ -145,6 +113,7 @@ public:
virtual std::vector<char> EncodeDynamicEntries(
const cmELF::DynamicEntryList&) = 0;
virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0;
+ virtual bool IsMips() const = 0;
virtual void PrintInfo(std::ostream& os) const = 0;
// Lookup the SONAME in the DYNAMIC section.
@@ -218,7 +187,6 @@ struct cmELFTypes32
};
// Configure the implementation template for 64-bit ELF files.
-#ifndef _SCO_DS
struct cmELFTypes64
{
using ELF_Ehdr = Elf64_Ehdr;
@@ -228,7 +196,6 @@ struct cmELFTypes64
using tagtype = ::uint64_t;
static const char* GetName() { return "64-bit"; }
};
-#endif
// Parser implementation template.
template <class Types>
@@ -262,6 +229,8 @@ public:
// Lookup a string from the dynamic section with the given tag.
StringEntry const* GetDynamicSectionString(unsigned int tag) override;
+ bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; }
+
// Print information about the ELF file.
void PrintInfo(std::ostream& os) const override
{
@@ -345,16 +314,12 @@ private:
eti == ET_CORE) {
return true;
}
-#if defined(ET_LOOS) && defined(ET_HIOS)
if (eti >= ET_LOOS && eti <= ET_HIOS) {
return true;
}
-#endif
-#if defined(ET_LOPROC) && defined(ET_HIPROC)
if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
return true;
}
-#endif
return false;
}
@@ -465,18 +430,14 @@ cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external,
break;
default: {
unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type);
-#if defined(ET_LOOS) && defined(ET_HIOS)
if (eti >= ET_LOOS && eti <= ET_HIOS) {
this->ELFType = cmELF::FileTypeSpecificOS;
break;
}
-#endif
-#if defined(ET_LOPROC) && defined(ET_HIPROC)
if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
this->ELFType = cmELF::FileTypeSpecificProc;
break;
}
-#endif
std::ostringstream e;
e << "Unknown ELF file type " << eti;
this->SetErrorMessage(e.str().c_str());
@@ -681,17 +642,12 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
const long cmELF::TagRPath = DT_RPATH;
const long cmELF::TagRunPath = DT_RUNPATH;
-
-#ifdef DT_MIPS_RLD_MAP_REL
const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL;
-#else
-const long cmELF::TagMipsRldMapRel = 0;
-#endif
cmELF::cmELF(const char* fname)
{
// Try to open the file.
- auto fin = cm::make_unique<cmsys::ifstream>(fname);
+ auto fin = cm::make_unique<cmsys::ifstream>(fname, std::ios::binary);
// Quit now if the file could not be opened.
if (!fin || !*fin) {
@@ -736,15 +692,11 @@ cmELF::cmELF(const char* fname)
// 32-bit ELF
this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>(
this, std::move(fin), order);
- }
-#ifndef _SCO_DS
- else if (ident[EI_CLASS] == ELFCLASS64) {
+ } else if (ident[EI_CLASS] == ELFCLASS64) {
// 64-bit ELF
this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>(
this, std::move(fin), order);
- }
-#endif
- else {
+ } else {
this->ErrorMessage = "ELF file class is not 32-bit or 64-bit.";
return;
}
@@ -846,6 +798,14 @@ cmELF::StringEntry const* cmELF::GetRunPath()
return nullptr;
}
+bool cmELF::IsMIPS() const
+{
+ if (this->Valid()) {
+ return this->Internal->IsMips();
+ }
+ return false;
+}
+
void cmELF::PrintInfo(std::ostream& os) const
{
if (this->Valid()) {
diff --git a/Source/cmELF.h b/Source/cmELF.h
index f88ebe9..ce8bd7f 100644
--- a/Source/cmELF.h
+++ b/Source/cmELF.h
@@ -11,10 +11,6 @@
#include <utility>
#include <vector>
-#if !defined(CMake_USE_ELF_PARSER)
-# error "This file may be included only if CMake_USE_ELF_PARSER is enabled."
-#endif
-
class cmELFInternal;
/** \class cmELF
@@ -102,6 +98,9 @@ public:
/** Get the RUNPATH field if any. */
StringEntry const* GetRunPath();
+ /** Returns true if the ELF file targets a MIPS CPU. */
+ bool IsMIPS() const;
+
/** Print human-readable information about the ELF file. */
void PrintInfo(std::ostream& os) const;
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 1a31ae4..6e3f918 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -18,6 +18,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
@@ -254,7 +255,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
void cmExportBuildFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
+ cmGeneratorTarget const* depender, cmGeneratorTarget* dependee)
{
// The target is not in the export.
if (!this->AppendMode) {
@@ -321,7 +322,7 @@ cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg,
}
void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee,
+ cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
std::vector<std::string> const& exportFiles)
{
std::ostringstream e;
@@ -344,7 +345,7 @@ void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
}
std::string cmExportBuildFileGenerator::InstallNameDir(
- cmGeneratorTarget* target, const std::string& config)
+ cmGeneratorTarget const* target, const std::string& config)
{
std::string install_name_dir;
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 264494d..244f526 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -60,11 +60,11 @@ protected:
cmGeneratorTarget const* target) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
- cmGeneratorTarget* depender,
+ cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee) override;
- void ComplainAboutMissingTarget(cmGeneratorTarget* depender,
- cmGeneratorTarget* dependee,
+ void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
+ cmGeneratorTarget const* dependee,
std::vector<std::string> const& namespaces);
/** Fill in properties indicating built file locations. */
@@ -73,7 +73,7 @@ protected:
cmGeneratorTarget* target,
ImportPropertyMap& properties);
- std::string InstallNameDir(cmGeneratorTarget* target,
+ std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index dd611de..8b06a15 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -27,7 +27,6 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmTargetExport.h"
static std::string cmExportFileGeneratorEscape(std::string const& str)
{
@@ -123,7 +122,7 @@ void cmExportFileGenerator::GenerateImportConfig(
}
void cmExportFileGenerator::PopulateInterfaceProperty(
- const std::string& propName, cmGeneratorTarget* target,
+ const std::string& propName, cmGeneratorTarget const* target,
ImportPropertyMap& properties)
{
cmProp input = target->GetProperty(propName);
@@ -134,7 +133,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty(
void cmExportFileGenerator::PopulateInterfaceProperty(
const std::string& propName, const std::string& outputName,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
@@ -168,7 +167,7 @@ void cmExportFileGenerator::GenerateRequiredCMakeVersion(
}
bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
@@ -196,7 +195,7 @@ static bool isSubDirectory(std::string const& a, std::string const& b)
}
static bool checkInterfaceDirs(const std::string& prepro,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
const std::string& prop)
{
std::string const& installDir =
@@ -335,10 +334,10 @@ static void prefixItems(std::string& exportDirs)
}
void cmExportFileGenerator::PopulateSourcesInterface(
- cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmGeneratorTarget const* gt,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- cmGeneratorTarget* gt = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char* propName = "INTERFACE_SOURCES";
@@ -366,10 +365,10 @@ void cmExportFileGenerator::PopulateSourcesInterface(
}
void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
- cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmGeneratorTarget const* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- cmGeneratorTarget* target = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char* propName = "INTERFACE_INCLUDE_DIRECTORIES";
@@ -378,7 +377,8 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
cmGeneratorExpression ge;
std::string dirs = cmGeneratorExpression::Preprocess(
- tei->InterfaceIncludeDirectories, preprocessRule, true);
+ cmJoin(target->Target->GetInstallIncludeDirectoriesEntries(), ";"),
+ preprocessRule, true);
this->ReplaceInstallPrefix(dirs);
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
std::string exportDirs =
@@ -424,10 +424,10 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
}
void cmExportFileGenerator::PopulateLinkDependsInterface(
- cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmGeneratorTarget const* gt,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- cmGeneratorTarget* gt = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char* propName = "INTERFACE_LINK_DEPENDS";
@@ -455,10 +455,10 @@ void cmExportFileGenerator::PopulateLinkDependsInterface(
}
void cmExportFileGenerator::PopulateLinkDirectoriesInterface(
- cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmGeneratorTarget const* gt,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- cmGeneratorTarget* gt = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char* propName = "INTERFACE_LINK_DIRECTORIES";
@@ -486,7 +486,7 @@ void cmExportFileGenerator::PopulateLinkDirectoriesInterface(
}
void cmExportFileGenerator::PopulateInterfaceProperty(
- const std::string& propName, cmGeneratorTarget* target,
+ const std::string& propName, cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
@@ -505,7 +505,7 @@ void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop,
ifaceProperties.insert(content.begin(), content.end());
}
-void getCompatibleInterfaceProperties(cmGeneratorTarget* target,
+void getCompatibleInterfaceProperties(cmGeneratorTarget const* target,
std::set<std::string>& ifaceProperties,
const std::string& config)
{
@@ -544,7 +544,7 @@ void getCompatibleInterfaceProperties(cmGeneratorTarget* target,
}
void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
- cmGeneratorTarget* gtarget, ImportPropertyMap& properties)
+ cmGeneratorTarget const* gtarget, ImportPropertyMap& properties)
{
this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", gtarget,
properties);
@@ -596,7 +596,7 @@ void cmExportFileGenerator::GenerateInterfaceProperties(
}
bool cmExportFileGenerator::AddTargetNamespace(
- std::string& input, cmGeneratorTarget* target,
+ std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets)
{
cmGeneratorTarget::TargetOrString resolved =
@@ -627,7 +627,7 @@ bool cmExportFileGenerator::AddTargetNamespace(
}
void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
- std::string& input, cmGeneratorTarget* target,
+ std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets, FreeTargetsReplace replace)
{
if (replace == NoReplaceFreeTargets) {
@@ -654,7 +654,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
}
void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
- std::string& input, cmGeneratorTarget* target,
+ std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets)
{
std::string::size_type pos = 0;
@@ -744,7 +744,7 @@ void cmExportFileGenerator::ReplaceInstallPrefix(std::string& /*unused*/)
void cmExportFileGenerator::SetImportLinkInterface(
const std::string& config, std::string const& suffix,
cmGeneratorExpression::PreprocessContext preprocessRule,
- cmGeneratorTarget* target, ImportPropertyMap& properties,
+ cmGeneratorTarget const* target, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets)
{
// Add the transitive link dependencies for this configuration.
@@ -880,7 +880,7 @@ static std::string const& asString(cmLinkItem const& l)
template <typename T>
void cmExportFileGenerator::SetImportLinkProperty(
- std::string const& suffix, cmGeneratorTarget* target,
+ std::string const& suffix, cmGeneratorTarget const* target,
const std::string& propName, std::vector<T> const& entries,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets,
ImportLinkPropertyTargetNames targetNames)
@@ -917,20 +917,20 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
// Protect that file against use with older CMake versions.
/* clang-format off */
os << "# Generated by CMake\n\n";
- os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
+ os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.6)\n"
<< " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
<< "endif()\n";
/* clang-format on */
// Isolate the file policy level.
// Support CMake versions as far back as 2.6 but also support using NEW
- // policy settings for up to CMake 3.19 (this upper limit may be reviewed
+ // policy settings for up to CMake 3.20 (this upper limit may be reviewed
// and increased from time to time). This reduces the opportunity for CMake
// warnings when an older export file is later used with newer CMake
// versions.
/* clang-format off */
os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION 2.6...3.19)\n";
+ << "cmake_policy(VERSION 2.6...3.20)\n";
/* clang-format on */
}
@@ -1211,7 +1211,7 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode(
}
bool cmExportFileGenerator::PopulateExportProperties(
- cmGeneratorTarget* gte, ImportPropertyMap& properties,
+ cmGeneratorTarget const* gte, ImportPropertyMap& properties,
std::string& errorMessage)
{
const auto& targetProperties = gte->Target->GetProperties();
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 45eaed0..24e048b 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -27,8 +27,6 @@ class cmGeneratorTarget;
CMake_VERSION_MINOR) "." STRINGIFY(CMake_VERSION_PATCH) \
: #major "." #minor ".0")
-class cmTargetExport;
-
/** \class cmExportFileGenerator
* \brief Generate a file exporting targets from a build or install tree.
*
@@ -108,7 +106,7 @@ protected:
};
template <typename T>
void SetImportLinkProperty(std::string const& suffix,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
const std::string& propName,
std::vector<T> const& entries,
ImportPropertyMap& properties,
@@ -127,44 +125,45 @@ protected:
* export set. */
virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
- cmGeneratorTarget* depender,
+ cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee) = 0;
- void PopulateInterfaceProperty(const std::string&, cmGeneratorTarget* target,
+ void PopulateInterfaceProperty(const std::string&,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
bool PopulateInterfaceLinkLibrariesProperty(
- cmGeneratorTarget* target, cmGeneratorExpression::PreprocessContext,
+ cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void PopulateInterfaceProperty(const std::string& propName,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
ImportPropertyMap& properties);
- void PopulateCompatibleInterfaceProperties(cmGeneratorTarget* target,
+ void PopulateCompatibleInterfaceProperties(cmGeneratorTarget const* target,
ImportPropertyMap& properties);
virtual void GenerateInterfaceProperties(
cmGeneratorTarget const* target, std::ostream& os,
const ImportPropertyMap& properties);
void PopulateIncludeDirectoriesInterface(
- cmTargetExport* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void PopulateSourcesInterface(
- cmTargetExport* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void PopulateLinkDirectoriesInterface(
- cmTargetExport* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void PopulateLinkDependsInterface(
- cmTargetExport* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void SetImportLinkInterface(
const std::string& config, std::string const& suffix,
cmGeneratorExpression::PreprocessContext preprocessRule,
- cmGeneratorTarget* target, ImportPropertyMap& properties,
+ cmGeneratorTarget const* target, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
enum FreeTargetsReplace
@@ -174,14 +173,14 @@ protected:
};
void ResolveTargetsInGeneratorExpressions(
- std::string& input, cmGeneratorTarget* target,
+ std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets,
FreeTargetsReplace replace = NoReplaceFreeTargets);
virtual void GenerateRequiredCMakeVersion(std::ostream& os,
const char* versionString);
- bool PopulateExportProperties(cmGeneratorTarget* gte,
+ bool PopulateExportProperties(cmGeneratorTarget const* gte,
ImportPropertyMap& properties,
std::string& errorMessage);
@@ -205,20 +204,20 @@ protected:
private:
void PopulateInterfaceProperty(const std::string&, const std::string&,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
- bool AddTargetNamespace(std::string& input, cmGeneratorTarget* target,
+ bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets);
void ResolveTargetsInGeneratorExpression(
- std::string& input, cmGeneratorTarget* target,
+ std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets);
virtual void ReplaceInstallPrefix(std::string& input);
- virtual std::string InstallNameDir(cmGeneratorTarget* target,
+ virtual std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) = 0;
};
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 3c69c50..46d2d31 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -16,6 +16,7 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -85,8 +86,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
ImportPropertyMap properties;
this->PopulateIncludeDirectoriesInterface(
- te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
- this->PopulateSourcesInterface(te, cmGeneratorExpression::InstallInterface,
+ gt, cmGeneratorExpression::InstallInterface, properties, missingTargets);
+ this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt,
cmGeneratorExpression::InstallInterface,
@@ -110,9 +111,9 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
this->PopulateLinkDirectoriesInterface(
- te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
+ gt, cmGeneratorExpression::InstallInterface, properties, missingTargets);
this->PopulateLinkDependsInterface(
- te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
+ gt, cmGeneratorExpression::InstallInterface, properties, missingTargets);
std::string errorMessage;
if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
@@ -447,7 +448,7 @@ cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
void cmExportInstallFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
+ cmGeneratorTarget const* depender, cmGeneratorTarget* dependee)
{
const std::string name = dependee->GetName();
cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator();
@@ -499,7 +500,7 @@ cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
}
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee,
+ cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
std::vector<std::string> const& exportFiles)
{
std::ostringstream e;
@@ -521,7 +522,7 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
}
std::string cmExportInstallFileGenerator::InstallNameDir(
- cmGeneratorTarget* target, const std::string& config)
+ cmGeneratorTarget const* target, const std::string& config)
{
std::string install_name_dir;
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 2d8de9d..5cec2e0 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -63,13 +63,13 @@ protected:
cmTargetExport const* targetExport) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
- cmGeneratorTarget* depender,
+ cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee) override;
void ReplaceInstallPrefix(std::string& input) override;
- void ComplainAboutMissingTarget(cmGeneratorTarget* depender,
- cmGeneratorTarget* dependee,
+ void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
+ cmGeneratorTarget const* dependee,
std::vector<std::string> const& exportFiles);
std::pair<std::vector<std::string>, std::string> FindNamespaces(
@@ -94,7 +94,7 @@ protected:
ImportPropertyMap& properties,
std::set<std::string>& importedLocations);
- std::string InstallNameDir(cmGeneratorTarget* target,
+ std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
cmInstallExportGenerator* IEGen;
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index cac60e1..f89d0ad 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -126,7 +126,7 @@ void cmExportTryCompileFileGenerator::PopulateProperties(
}
std::string cmExportTryCompileFileGenerator::InstallNameDir(
- cmGeneratorTarget* target, const std::string& config)
+ cmGeneratorTarget const* target, const std::string& config)
{
std::string install_name_dir;
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 6bf5781..127b8df 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -36,7 +36,8 @@ protected:
{
}
void HandleMissingTarget(std::string&, std::vector<std::string>&,
- cmGeneratorTarget*, cmGeneratorTarget*) override
+ cmGeneratorTarget const*,
+ cmGeneratorTarget*) override
{
}
@@ -44,7 +45,7 @@ protected:
ImportPropertyMap& properties,
std::set<const cmGeneratorTarget*>& emitted);
- std::string InstallNameDir(cmGeneratorTarget* target,
+ std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
private:
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index a2b5460..adeba74 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -813,8 +813,7 @@ Json::Value CodemodelConfig::DumpProject(Project& p)
Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s)
{
Json::Value minimumCMakeVersion;
- if (std::string const* def =
- s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
+ if (cmProp def = s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
minimumCMakeVersion = Json::objectValue;
minimumCMakeVersion["string"] = *def;
}
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 0ad59c7..2730a07 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -31,6 +31,7 @@
#include "cmArgumentParser.h"
#include "cmCMakePath.h"
#include "cmCryptoHash.h"
+#include "cmELF.h"
#include "cmExecutionStatus.h"
#include "cmFSPermissions.h"
#include "cmFileCopier.h"
@@ -64,10 +65,6 @@
# include "cmFileLockResult.h"
#endif
-#if defined(CMake_USE_ELF_PARSER)
-# include "cmELF.h"
-#endif
-
#if defined(_WIN32)
# include <windows.h>
#endif
@@ -1242,8 +1239,12 @@ bool HandleReadElfCommand(std::vector<std::string> const& args,
return false;
}
-#if defined(CMake_USE_ELF_PARSER)
cmELF elf(fileNameArg.c_str());
+ if (!elf) {
+ status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg,
+ "\" that is not a valid ELF file."));
+ return false;
+ }
if (!arguments.RPath.empty()) {
if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
@@ -1261,15 +1262,6 @@ bool HandleReadElfCommand(std::vector<std::string> const& args,
}
return true;
-#else
- std::string error = "ELF parser not available on this platform.";
- if (arguments.Error.empty()) {
- status.SetError(error);
- return false;
- }
- status.GetMakefile().AddDefinition(arguments.Error, error);
- return true;
-#endif
}
bool HandleInstallCommand(std::vector<std::string> const& args,
@@ -1858,7 +1850,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
} else if (*i == "TLS_CAINFO") {
++i;
if (i != args.end()) {
- cainfo = &(*i);
+ cainfo = cmProp(*i);
} else {
status.SetError("DOWNLOAD missing file value for TLS_CAINFO.");
return false;
@@ -2244,7 +2236,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
} else if (*i == "TLS_CAINFO") {
++i;
if (i != args.end()) {
- cainfo = &(*i);
+ cainfo = cmProp(*i);
} else {
status.SetError("UPLOAD missing file value for TLS_CAINFO.");
return false;
diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h
index 217d58d..ee9872d 100644
--- a/Source/cmFileCopier.h
+++ b/Source/cmFileCopier.h
@@ -67,8 +67,9 @@ protected:
bool InstallSymlinkChain(std::string& fromFile, std::string& toFile);
bool InstallSymlink(const std::string& fromFile, const std::string& toFile);
- bool InstallFile(const std::string& fromFile, const std::string& toFile,
- MatchProperties match_properties);
+ virtual bool InstallFile(const std::string& fromFile,
+ const std::string& toFile,
+ MatchProperties match_properties);
bool InstallDirectory(const std::string& source,
const std::string& destination,
MatchProperties match_properties);
diff --git a/Source/cmFileInstaller.cxx b/Source/cmFileInstaller.cxx
index c89be96..0d8ba2d 100644
--- a/Source/cmFileInstaller.cxx
+++ b/Source/cmFileInstaller.cxx
@@ -3,7 +3,12 @@
#include "cmFileInstaller.h"
+#include <map>
#include <sstream>
+#include <utility>
+
+#include <cm/string_view>
+#include <cmext/string_view>
#include "cm_sys_stat.h"
@@ -18,6 +23,7 @@ using namespace cmFSPermissions;
cmFileInstaller::cmFileInstaller(cmExecutionStatus& status)
: cmFileCopier(status, "INSTALL")
, InstallType(cmInstallType_FILES)
+ , InstallMode(cmInstallMode::COPY)
, Optional(false)
, MessageAlways(false)
, MessageLazy(false)
@@ -82,6 +88,93 @@ bool cmFileInstaller::Install(const std::string& fromFile,
return this->cmFileCopier::Install(fromFile, toFile);
}
+bool cmFileInstaller::InstallFile(const std::string& fromFile,
+ const std::string& toFile,
+ MatchProperties match_properties)
+{
+ if (this->InstallMode == cmInstallMode::COPY) {
+ return this->cmFileCopier::InstallFile(fromFile, toFile, match_properties);
+ }
+
+ std::string newFromFile;
+
+ if (this->InstallMode == cmInstallMode::REL_SYMLINK ||
+ this->InstallMode == cmInstallMode::REL_SYMLINK_OR_COPY ||
+ this->InstallMode == cmInstallMode::SYMLINK ||
+ this->InstallMode == cmInstallMode::SYMLINK_OR_COPY) {
+ // Try to get a relative path.
+ std::string toDir = cmSystemTools::GetParentDirectory(toFile);
+ newFromFile = cmSystemTools::ForceToRelativePath(toDir, fromFile);
+
+ // Double check that we can restore the original path.
+ std::string reassembled =
+ cmSystemTools::CollapseFullPath(newFromFile, toDir);
+ if (!cmSystemTools::ComparePath(reassembled, fromFile)) {
+ if (this->InstallMode == cmInstallMode::SYMLINK ||
+ this->InstallMode == cmInstallMode::SYMLINK_OR_COPY) {
+ // User does not mind, silently proceed with absolute path.
+ newFromFile = fromFile;
+ } else if (this->InstallMode == cmInstallMode::REL_SYMLINK_OR_COPY) {
+ // User expects a relative symbolic link or a copy.
+ // Since an absolute symlink won't do, copy instead.
+ return this->cmFileCopier::InstallFile(fromFile, toFile,
+ match_properties);
+ } else {
+ // We cannot meet user's expectation (REL_SYMLINK)
+ auto e = cmStrCat(this->Name,
+ " cannot determine relative path for symlink to \"",
+ newFromFile, "\" at \"", toFile, "\".");
+ this->Status.SetError(e);
+ return false;
+ }
+ }
+ } else {
+ newFromFile = fromFile; // stick with absolute path
+ }
+
+ // Compare the symlink value to that at the destination if not
+ // always installing.
+ bool copy = true;
+ if (!this->Always) {
+ std::string oldSymlinkTarget;
+ if (cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget)) {
+ if (newFromFile == oldSymlinkTarget) {
+ copy = false;
+ }
+ }
+ }
+
+ // Inform the user about this file installation.
+ this->ReportCopy(toFile, TypeLink, copy);
+
+ if (copy) {
+ // Remove the destination file so we can always create the symlink.
+ cmSystemTools::RemoveFile(toFile);
+
+ // Create destination directory if it doesn't exist
+ cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(toFile));
+
+ // Create the symlink.
+ if (!cmSystemTools::CreateSymlink(newFromFile, toFile)) {
+ if (this->InstallMode == cmInstallMode::ABS_SYMLINK_OR_COPY ||
+ this->InstallMode == cmInstallMode::REL_SYMLINK_OR_COPY ||
+ this->InstallMode == cmInstallMode::SYMLINK_OR_COPY) {
+ // Failed to create a symbolic link, fall back to copying.
+ return this->cmFileCopier::InstallFile(newFromFile, toFile,
+ match_properties);
+ }
+
+ auto e = cmStrCat(this->Name, " cannot create symlink to \"",
+ newFromFile, "\" at \"", toFile,
+ "\": ", cmSystemTools::GetLastSystemError(), "\".");
+ this->Status.SetError(e);
+ return false;
+ }
+ }
+
+ return true;
+}
+
void cmFileInstaller::DefaultFilePermissions()
{
this->cmFileCopier::DefaultFilePermissions();
@@ -141,6 +234,31 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args)
return false;
}
+ static const std::map<cm::string_view, cmInstallMode> install_mode_dict{
+ { "ABS_SYMLINK"_s, cmInstallMode::ABS_SYMLINK },
+ { "ABS_SYMLINK_OR_COPY"_s, cmInstallMode::ABS_SYMLINK_OR_COPY },
+ { "REL_SYMLINK"_s, cmInstallMode::REL_SYMLINK },
+ { "REL_SYMLINK_OR_COPY"_s, cmInstallMode::REL_SYMLINK_OR_COPY },
+ { "SYMLINK"_s, cmInstallMode::SYMLINK },
+ { "SYMLINK_OR_COPY"_s, cmInstallMode::SYMLINK_OR_COPY }
+ };
+
+ std::string install_mode;
+ cmSystemTools::GetEnv("CMAKE_INSTALL_MODE", install_mode);
+ if (install_mode.empty() || install_mode == "COPY"_s) {
+ this->InstallMode = cmInstallMode::COPY;
+ } else {
+ auto it = install_mode_dict.find(install_mode);
+ if (it != install_mode_dict.end()) {
+ this->InstallMode = it->second;
+ } else {
+ auto e = cmStrCat("Unrecognized value '", install_mode,
+ "' for environment variable CMAKE_INSTALL_MODE");
+ this->Status.SetError(e);
+ return false;
+ }
+ }
+
return true;
}
diff --git a/Source/cmFileInstaller.h b/Source/cmFileInstaller.h
index 3a905d3..3f6bd45 100644
--- a/Source/cmFileInstaller.h
+++ b/Source/cmFileInstaller.h
@@ -8,6 +8,7 @@
#include <vector>
#include "cmFileCopier.h"
+#include "cmInstallMode.h"
#include "cmInstallType.h"
class cmExecutionStatus;
@@ -19,6 +20,7 @@ struct cmFileInstaller : public cmFileCopier
protected:
cmInstallType InstallType;
+ cmInstallMode InstallMode;
bool Optional;
bool MessageAlways;
bool MessageLazy;
@@ -35,7 +37,8 @@ protected:
bool ReportMissing(const std::string& fromFile) override;
bool Install(const std::string& fromFile,
const std::string& toFile) override;
-
+ bool InstallFile(const std::string& fromFile, const std::string& toFile,
+ MatchProperties match_properties) override;
bool Parse(std::vector<std::string> const& args) override;
enum
{
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 1038ac2..f4e1763 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -311,7 +311,7 @@ bool cmFindBase::CheckForVariableDefined()
if (cached && cacheType != cmStateEnums::UNINITIALIZED) {
this->VariableType = cacheType;
- if (const auto* hs =
+ if (const auto& hs =
state->GetCacheEntryProperty(this->VariableName, "HELPSTRING")) {
this->VariableDocumentation = *hs;
}
@@ -336,7 +336,7 @@ void cmFindBase::NormalizeFindResult()
if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0125) ==
cmPolicies::NEW) {
// ensure the path returned by find_* command is absolute
- const auto* existingValue =
+ const auto& existingValue =
this->Makefile->GetDefinition(this->VariableName);
std::string value;
if (!existingValue->empty()) {
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index 0cbe637..ef960d1 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -259,6 +259,34 @@ struct cmFindLibraryHelper
};
};
+namespace {
+
+std::string const& get_prefixes(cmMakefile* mf)
+{
+#ifdef _WIN32
+ static std::string defaultPrefix = ";lib";
+#else
+ static std::string defaultPrefix = "lib";
+#endif
+ cmProp prefixProp = mf->GetDefinition("CMAKE_FIND_LIBRARY_PREFIXES");
+ return (prefixProp) ? *prefixProp : defaultPrefix;
+}
+
+std::string const& get_suffixes(cmMakefile* mf)
+{
+#ifdef _WIN32
+ static std::string defaultSuffix = ".lib;.dll.a;.a";
+#elif defined(__APPLE__)
+ static std::string defaultSuffix = ".tbd;.dylib;.so;.a";
+#elif defined(__hpux)
+ static std::string defaultSuffix = ".sl;.so;.a";
+#else
+ static std::string defaultSuffix = ".so;.a";
+#endif
+ cmProp suffixProp = mf->GetDefinition("CMAKE_FIND_LIBRARY_SUFFIXES");
+ return (suffixProp) ? *suffixProp : defaultSuffix;
+}
+}
cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
cmFindBase const* base)
: Makefile(mf)
@@ -268,10 +296,9 @@ cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
this->GG = this->Makefile->GetGlobalGenerator();
// Collect the list of library name prefixes/suffixes to try.
- std::string const& prefixes_list =
- this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_PREFIXES");
- std::string const& suffixes_list =
- this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_SUFFIXES");
+ std::string const& prefixes_list = get_prefixes(this->Makefile);
+ std::string const& suffixes_list = get_suffixes(this->Makefile);
+
cmExpandList(prefixes_list, this->Prefixes, true);
cmExpandList(suffixes_list, this->Suffixes, true);
this->RegexFromList(this->PrefixRegexStr, this->Prefixes);
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index fba736e..a0de74c 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -478,17 +478,35 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
this->VersionMaxPatch, this->VersionMaxTweak);
}
+ const std::string makePackageRequiredVar =
+ cmStrCat("CMAKE_REQUIRE_FIND_PACKAGE_", this->Name);
+ const bool makePackageRequiredSet =
+ this->Makefile->IsOn(makePackageRequiredVar);
+ if (makePackageRequiredSet) {
+ if (this->Required) {
+ this->Makefile->IssueMessage(
+ MessageType::WARNING,
+ cmStrCat("for module ", this->Name,
+ " already called with REQUIRED, thus ",
+ makePackageRequiredVar, " has no effect."));
+ } else {
+ this->Required = true;
+ }
+ }
+
std::string disableFindPackageVar =
cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name);
if (this->Makefile->IsOn(disableFindPackageVar)) {
if (this->Required) {
this->SetError(
- cmStrCat("for module ", this->Name, " called with REQUIRED, but ",
- disableFindPackageVar,
+ cmStrCat("for module ", this->Name,
+ (makePackageRequiredSet
+ ? " was made REQUIRED with " + makePackageRequiredVar
+ : " called with REQUIRED, "),
+ " but ", disableFindPackageVar,
" is enabled. A REQUIRED package cannot be disabled."));
return false;
}
-
return true;
}
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 4845a6d..b44f797 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -27,6 +27,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h
index 1b14d17..70fe537 100644
--- a/Source/cmFortranParser.h
+++ b/Source/cmFortranParser.h
@@ -40,6 +40,8 @@ int cmFortranParser_GetOldStartcond(cmFortranParser* parser);
/* Callbacks for parser. */
void cmFortranParser_Error(cmFortranParser* parser, const char* message);
void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name);
+void cmFortranParser_RuleUseIntrinsic(cmFortranParser* parser,
+ const char* module_name);
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
const char* filename);
void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name);
@@ -99,6 +101,9 @@ public:
std::set<std::string> Provides;
std::set<std::string> Requires;
+ // Set of intrinsic modules.
+ std::set<std::string> Intrinsics;
+
// Set of files included in the translation unit.
std::set<std::string> Includes;
};
diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx
index 054a2a9..efcc5bb 100644
--- a/Source/cmFortranParserImpl.cxx
+++ b/Source/cmFortranParserImpl.cxx
@@ -197,6 +197,19 @@ void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name)
parser->Info.Requires.insert(parser->ModName(mod_name));
}
+void cmFortranParser_RuleUseIntrinsic(cmFortranParser* parser,
+ const char* module_name)
+{
+ if (parser->InPPFalseBranch) {
+ return;
+ }
+
+ // syntax: "use, intrinsic:: module_name"
+ // requires: "module_name.mod"
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ parser->Info.Intrinsics.insert(parser->ModName(mod_name));
+}
+
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
const char* filename)
{
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 217ebe5..3e90ead 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1777,7 +1777,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
testedFeatures[lang].push_back(p);
if (availableFeatures.find(lang) == availableFeatures.end()) {
- const char* featuresKnown =
+ cmProp featuresKnown =
standardResolver.CompileFeaturesAvailable(lang, &error);
if (!featuresKnown) {
reportError(context, content->GetOriginalExpression(), error);
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index f1ef130..4208689 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -62,7 +62,7 @@ cmProp cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
cmGeneratorTarget const* tgt, cmMessenger* /* messenger */,
cmListFileBacktrace const& /* context */)
{
- return &tgt->GetSourcesProperty();
+ return tgt->GetSourcesProperty();
}
template <>
@@ -332,7 +332,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
cmGeneratorTarget::~cmGeneratorTarget() = default;
-const std::string& cmGeneratorTarget::GetSourcesProperty() const
+cmProp cmGeneratorTarget::GetSourcesProperty() const
{
std::vector<std::string> values;
for (auto const& se : this->SourceEntries) {
@@ -341,7 +341,7 @@ const std::string& cmGeneratorTarget::GetSourcesProperty() const
static std::string value;
value.clear();
value = cmJoin(values, ";");
- return value;
+ return cmProp(value);
}
cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const
@@ -396,13 +396,7 @@ cmProp cmGeneratorTarget::GetProperty(const std::string& prop) const
std::string const& cmGeneratorTarget::GetSafeProperty(
std::string const& prop) const
{
- cmProp ret = this->GetProperty(prop);
- if (ret) {
- return *ret;
- }
-
- static std::string const s_empty;
- return s_empty;
+ return this->GetProperty(prop);
}
const char* cmGeneratorTarget::GetOutputTargetType(
@@ -564,7 +558,7 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const
// framework postfix.
frameworkPostfix = this->GetFrameworkMultiConfigPostfix(config);
if (!frameworkPostfix.empty()) {
- postfix = &frameworkPostfix;
+ postfix = cmProp(frameworkPostfix);
}
}
return postfix ? *postfix : std::string();
@@ -966,7 +960,7 @@ cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang,
this->GetLanguageStandardProperty(lang, config);
if (languageStandard) {
- return &(languageStandard->Value);
+ return cmProp(languageStandard->Value);
}
return nullptr;
@@ -2142,7 +2136,6 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
return true;
}
-#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER)
// Enable if the rpath flag uses a separator and the target uses
// binaries we know how to edit.
std::string ll = this->GetLinkerLanguage(config);
@@ -2155,21 +2148,17 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
// CMAKE_EXECUTABLE_FORMAT.
if (cmProp fmt =
this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) {
-# if defined(CMake_USE_ELF_PARSER)
if (*fmt == "ELF") {
return true;
}
-# endif
-# if defined(CMake_USE_XCOFF_PARSER)
+#if defined(CMake_USE_XCOFF_PARSER)
if (*fmt == "XCOFF") {
return true;
}
-# endif
+#endif
}
}
}
-#endif
- static_cast<void>(config);
return false;
}
@@ -4466,6 +4455,13 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
// Last step: replace "LINKER:" prefixed elements by
// actual linker wrapper
+ return this->ResolveLinkerWrapper(result, language);
+}
+
+std::vector<BT<std::string>>& cmGeneratorTarget::ResolveLinkerWrapper(
+ std::vector<BT<std::string>>& result, const std::string& language) const
+{
+ // replace "LINKER:" prefixed elements by actual linker wrapper
const std::string wrapper(this->Makefile->GetSafeDefinition(
"CMAKE_" + language +
(this->IsDeviceLink() ? "_DEVICE_LINKER_WRAPPER_FLAG"
@@ -5119,13 +5115,13 @@ void cmGeneratorTarget::GetFullNameInternal(
if (this->IsFrameworkOnApple()) {
fw_prefix =
cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/');
- targetPrefix = &fw_prefix;
+ targetPrefix = cmProp(fw_prefix);
targetSuffix = nullptr;
}
if (this->IsCFBundleOnApple()) {
fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/');
- targetPrefix = &fw_prefix;
+ targetPrefix = cmProp(fw_prefix);
targetSuffix = nullptr;
}
@@ -5141,7 +5137,7 @@ void cmGeneratorTarget::GetFullNameInternal(
// EXECUTABLE_SUFFIX attribute.
if (this->IsFrameworkOnApple() &&
this->GetGlobalGenerator()->GetName() == "Xcode") {
- targetSuffix = &configPostfix;
+ targetSuffix = cmProp(configPostfix);
} else {
outBase += configPostfix;
}
@@ -5672,6 +5668,11 @@ std::string valueAsString<std::string>(std::string value)
return value;
}
template <>
+std::string valueAsString<cmProp>(cmProp value)
+{
+ return value ? value : std::string("(unset)");
+}
+template <>
std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/)
{
return "(unset)";
@@ -5747,7 +5748,7 @@ std::string getTypedProperty<std::string>(
cmProp value = tgt->GetProperty(prop);
if (genexInterpreter == nullptr) {
- return valueAsString(cmToCStr(value));
+ return valueAsString(value);
}
return genexInterpreter->Evaluate(value ? *value : "", prop);
@@ -6175,6 +6176,14 @@ std::string cmGeneratorTarget::GetFortranModuleDirectory(
return this->FortranModuleDirectory;
}
+bool cmGeneratorTarget::IsFortranBuildingInstrinsicModules() const
+{
+ if (cmProp prop = this->GetProperty("Fortran_BUILDING_INSTRINSIC_MODULES")) {
+ return cmIsOn(*prop);
+ }
+ return false;
+}
+
std::string cmGeneratorTarget::CreateFortranModuleDirectory(
std::string const& working_dir) const
{
@@ -6362,12 +6371,12 @@ cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem(
return maybeItem;
}
-void cmGeneratorTarget::ExpandLinkItems(
- std::string const& prop, std::string const& value, std::string const& config,
- cmGeneratorTarget const* headTarget, bool usage_requirements_only,
- std::vector<cmLinkItem>& items, std::vector<cmLinkItem>& objects,
- bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition,
- bool& hadLinkLanguageSensitiveCondition) const
+void cmGeneratorTarget::ExpandLinkItems(std::string const& prop,
+ std::string const& value,
+ std::string const& config,
+ cmGeneratorTarget const* headTarget,
+ bool usage_requirements_only,
+ cmLinkInterface& iface) const
{
// Keep this logic in sync with ComputeLinkImplementationLibraries.
cmGeneratorExpression ge;
@@ -6389,24 +6398,27 @@ void cmGeneratorTarget::ExpandLinkItems(
for (std::string const& lib : libs) {
if (cm::optional<cmLinkItem> maybeItem =
this->LookupLinkItem(lib, cge->GetBacktrace(), &scope)) {
- if (!maybeItem->Target) {
+ cmLinkItem item = std::move(*maybeItem);
+
+ if (!item.Target) {
// Report explicitly linked object files separately.
- std::string const& maybeObj = maybeItem->AsStr();
+ std::string const& maybeObj = item.AsStr();
if (cmSystemTools::FileIsFullPath(maybeObj)) {
cmSourceFile const* sf =
mf->GetSource(maybeObj, cmSourceFileLocationKind::Known);
if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
- objects.emplace_back(std::move(*maybeItem));
+ iface.Objects.emplace_back(std::move(item));
continue;
}
}
}
- items.emplace_back(std::move(*maybeItem));
+
+ iface.Libraries.emplace_back(std::move(item));
}
}
- hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
- hadContextSensitiveCondition = cge->GetHadContextSensitiveCondition();
- hadLinkLanguageSensitiveCondition =
+ iface.HadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
+ iface.HadContextSensitiveCondition = cge->GetHadContextSensitiveCondition();
+ iface.HadLinkLanguageSensitiveCondition =
cge->GetHadLinkLanguageSensitiveCondition();
}
@@ -6903,23 +6915,20 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
return;
}
iface.Exists = true;
+
+ // If CMP0022 is NEW then the plain tll signature sets the
+ // INTERFACE_LINK_LIBRARIES property. Even if the project
+ // clears it, the link interface is still explicit.
iface.Explicit = cmp0022NEW || explicitLibraries;
if (explicitLibraries) {
// The interface libraries have been explicitly set.
this->ExpandLinkItems(linkIfaceProp, *explicitLibraries, config,
- headTarget, usage_requirements_only, iface.Libraries,
- iface.Objects, iface.HadHeadSensitiveCondition,
- iface.HadContextSensitiveCondition,
- iface.HadLinkLanguageSensitiveCondition);
- return;
+ headTarget, usage_requirements_only, iface);
}
- // If CMP0022 is NEW then the plain tll signature sets the
- // INTERFACE_LINK_LIBRARIES, so if we get here then the project
- // cleared the property explicitly and we should not fall back
- // to the link implementation.
- if (cmp0022NEW) {
+ // If the link interface is explicit, do not fall back to the link impl.
+ if (iface.Explicit) {
return;
}
@@ -6932,22 +6941,15 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
!this->PolicyWarnedCMP0022 && !usage_requirements_only) {
// Compare the link implementation fallback link interface to the
// preferred new link interface property and warn if different.
- std::vector<cmLinkItem> ifaceLibs;
- std::vector<cmLinkItem> ifaceObjects;
+ cmLinkInterface ifaceNew;
static const std::string newProp = "INTERFACE_LINK_LIBRARIES";
if (cmProp newExplicitLibraries = this->GetProperty(newProp)) {
- bool hadHeadSensitiveConditionDummy = false;
- bool hadContextSensitiveConditionDummy = false;
- bool hadLinkLanguageSensitiveConditionDummy = false;
this->ExpandLinkItems(newProp, *newExplicitLibraries, config,
- headTarget, usage_requirements_only, ifaceLibs,
- ifaceObjects, hadHeadSensitiveConditionDummy,
- hadContextSensitiveConditionDummy,
- hadLinkLanguageSensitiveConditionDummy);
+ headTarget, usage_requirements_only, ifaceNew);
}
- if (ifaceLibs != iface.Libraries) {
+ if (ifaceNew.Libraries != iface.Libraries) {
std::string oldLibraries = cmJoin(impl->Libraries, ";");
- std::string newLibraries = cmJoin(ifaceLibs, ";");
+ std::string newLibraries = cmJoin(ifaceNew.Libraries, ";");
if (oldLibraries.empty()) {
oldLibraries = "(empty)";
}
@@ -7085,10 +7087,7 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
iface.Multiplicity = info->Multiplicity;
cmExpandList(info->Languages, iface.Languages);
this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config,
- headTarget, usage_requirements_only, iface.Libraries,
- iface.Objects, iface.HadHeadSensitiveCondition,
- iface.HadContextSensitiveCondition,
- iface.HadLinkLanguageSensitiveCondition);
+ headTarget, usage_requirements_only, iface);
std::vector<std::string> deps = cmExpandedList(info->SharedDeps);
LookupLinkItemScope scope{ this->LocalGenerator };
for (std::string const& dep : deps) {
@@ -7628,6 +7627,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
std::string const& evaluated =
cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr,
this->LinkerLanguage);
+ bool const fromGenex = evaluated != *le;
cmExpandList(evaluated, llibs);
if (cge->GetHadHeadSensitiveCondition()) {
impl.HadHeadSensitiveCondition = true;
@@ -7699,7 +7699,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
}
}
- impl.Libraries.emplace_back(std::move(item), evaluated != *le);
+ impl.Libraries.emplace_back(std::move(item), fromGenex);
}
std::set<std::string> const& seenProps = cge->GetSeenTargetProperties();
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 6d2aa85..fb1b2e6 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -498,6 +498,9 @@ public:
std::vector<BT<std::string>> GetLinkOptions(
std::string const& config, std::string const& language) const;
+ std::vector<BT<std::string>>& ResolveLinkerWrapper(
+ std::vector<BT<std::string>>& result, const std::string& language) const;
+
void GetStaticLibraryLinkOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
@@ -832,8 +835,9 @@ public:
std::string const& config) const;
std::string GetFortranModuleDirectory(std::string const& working_dir) const;
+ bool IsFortranBuildingInstrinsicModules() const;
- const std::string& GetSourcesProperty() const;
+ cmProp GetSourcesProperty() const;
void AddISPCGeneratedHeader(std::string const& header,
std::string const& config);
@@ -1037,11 +1041,8 @@ private:
std::string const& config,
const cmGeneratorTarget* headTarget,
bool usage_requirements_only,
- std::vector<cmLinkItem>& items,
- std::vector<cmLinkItem>& objects,
- bool& hadHeadSensitiveCondition,
- bool& hadContextSensitiveCondition,
- bool& hadLinkLanguageSensitiveCondition) const;
+ cmLinkInterface& iface) const;
+
struct LookupLinkItemScope
{
cmLocalGenerator const* LG;
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index cb657f9..bb3a40b 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -268,6 +268,11 @@ bool StoreResult(OutType infoType, cmMakefile& makefile,
}
return true;
}
+bool StoreResult(OutType infoType, cmMakefile& makefile,
+ const std::string& variable, cmProp value)
+{
+ return StoreResult(infoType, makefile, variable, value.GetCStr());
+}
bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
OutType infoType, const std::string& variable,
@@ -280,9 +285,8 @@ bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
// Get the property.
cmake* cm = status.GetMakefile().GetCMakeInstance();
- return StoreResult(
- infoType, status.GetMakefile(), variable,
- cmToCStr(cm->GetState()->GetGlobalProperty(propertyName)));
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ cm->GetState()->GetGlobalProperty(propertyName));
}
bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
@@ -329,7 +333,7 @@ bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
// Get the property.
return StoreResult(infoType, status.GetMakefile(), variable,
- cmToCStr(mf->GetProperty(propertyName)));
+ mf->GetProperty(propertyName));
}
bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
@@ -365,8 +369,7 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
if (!prop) {
prop = target->GetProperty(propertyName);
}
- return StoreResult(infoType, status.GetMakefile(), variable,
- cmToCStr(prop));
+ return StoreResult(infoType, status.GetMakefile(), variable, prop);
}
status.SetError(cmStrCat("could not find TARGET ", name,
". Perhaps it has not yet been created."));
@@ -391,7 +394,7 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::string& name,
if (cmSourceFile* sf =
directory_makefile.GetOrCreateSource(source_file_absolute_path)) {
return StoreResult(infoType, status.GetMakefile(), variable,
- cmToCStr(sf->GetPropertyForUser(propertyName)));
+ sf->GetPropertyForUser(propertyName));
}
status.SetError(
cmStrCat("given SOURCE name that could not be found or created: ",
@@ -447,7 +450,7 @@ bool HandleCacheMode(cmExecutionStatus& status, const std::string& name,
value = status.GetMakefile().GetState()->GetCacheEntryProperty(
name, propertyName);
}
- StoreResult(infoType, status.GetMakefile(), variable, cmToCStr(value));
+ StoreResult(infoType, status.GetMakefile(), variable, value);
return true;
}
diff --git a/Source/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx
index cf8c1d5..077353e 100644
--- a/Source/cmGetTestPropertyCommand.cxx
+++ b/Source/cmGetTestPropertyCommand.cxx
@@ -4,6 +4,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmTest.h"
bool cmGetTestPropertyCommand(std::vector<std::string> const& args,
@@ -19,12 +20,12 @@ bool cmGetTestPropertyCommand(std::vector<std::string> const& args,
cmMakefile& mf = status.GetMakefile();
cmTest* test = mf.GetTest(testName);
if (test) {
- const char* prop = nullptr;
+ cmProp prop;
if (!args[1].empty()) {
prop = test->GetProperty(args[1]);
}
if (prop) {
- mf.AddDefinition(var, prop);
+ mf.AddDefinition(var, prop->c_str());
return true;
}
}
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 32238e4..12fd9c4 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -376,7 +376,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
#ifdef _WIN32
std::string check_error = "if %errorlevel% neq 0 exit /b %errorlevel%";
#else
- std::string check_error = "if [[ $? -ne 0 ]]; then exit 1; fi";
+ std::string check_error = "if [ $? -ne 0 ]; then exit 1; fi";
#endif
#ifdef _WIN32
diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx
index 9e5bbca..a8e0f23 100644
--- a/Source/cmGlobalCommonGenerator.cxx
+++ b/Source/cmGlobalCommonGenerator.cxx
@@ -16,8 +16,8 @@
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
-
-class cmake;
+#include "cmSystemTools.h"
+#include "cmake.h"
cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
: cmGlobalGenerator(cm)
@@ -95,3 +95,33 @@ bool cmGlobalCommonGenerator::IsExcludedFromAllInConfig(
}
return !t.ExcludedFromAllInConfigs.empty();
}
+
+std::string cmGlobalCommonGenerator::GetEditCacheCommand() const
+{
+ // If generating for an extra IDE, the edit_cache target cannot
+ // launch a terminal-interactive tool, so always use cmake-gui.
+ if (!this->GetExtraGeneratorName().empty()) {
+ return cmSystemTools::GetCMakeGUICommand();
+ }
+
+ // Use an internal cache entry to track the latest dialog used
+ // to edit the cache, and use that for the edit_cache target.
+ cmake* cm = this->GetCMakeInstance();
+ std::string editCacheCommand = cm->GetCMakeEditCommand();
+ if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") ||
+ !editCacheCommand.empty()) {
+ if (this->SupportsDirectConsole() && editCacheCommand.empty()) {
+ editCacheCommand = cmSystemTools::GetCMakeCursesCommand();
+ }
+ if (editCacheCommand.empty()) {
+ editCacheCommand = cmSystemTools::GetCMakeGUICommand();
+ }
+ if (!editCacheCommand.empty()) {
+ cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
+ "Path to cache edit program executable.",
+ cmStateEnums::INTERNAL);
+ }
+ }
+ cmProp edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND");
+ return edit_cmd ? *edit_cmd : std::string();
+}
diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h
index 2aa9d27..fed9ce8 100644
--- a/Source/cmGlobalCommonGenerator.h
+++ b/Source/cmGlobalCommonGenerator.h
@@ -42,4 +42,9 @@ public:
std::map<std::string, DirectoryTarget> ComputeDirectoryTargets() const;
bool IsExcludedFromAllInConfig(const DirectoryTarget::Target& t,
const std::string& config);
+
+protected:
+ virtual bool SupportsDirectConsole() const { return true; }
+ const char* GetEditCacheTargetName() const override { return "edit_cache"; }
+ std::string GetEditCacheCommand() const override;
};
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 9193778..3561deb 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -242,7 +242,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
std::vector<std::string> cnameArgVec;
if (cname && !cname->empty()) {
cmExpandList(*cname, cnameArgVec);
- cname = &cnameArgVec.front();
+ cname = cmProp(cnameArgVec.front());
}
std::string changeVars;
@@ -498,6 +498,18 @@ bool cmGlobalGenerator::CheckLanguages(
void cmGlobalGenerator::EnableLanguage(
std::vector<std::string> const& languages, cmMakefile* mf, bool optional)
{
+ if (!this->IsMultiConfig()) {
+ std::string envBuildType;
+ if (!mf->GetDefinition("CMAKE_BUILD_TYPE") &&
+ cmSystemTools::GetEnv("CMAKE_BUILD_TYPE", envBuildType)) {
+ mf->AddCacheDefinition(
+ "CMAKE_BUILD_TYPE", envBuildType,
+ "Choose the type of build. Options include: empty, "
+ "Debug, Release, RelWithDebInfo, MinSizeRel.",
+ cmStateEnums::STRING);
+ }
+ }
+
if (languages.empty()) {
cmSystemTools::Error("EnableLanguage must have a lang specified!");
cmSystemTools::SetFatalErrorOccured();
@@ -1167,10 +1179,10 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l,
}
}
-const char* cmGlobalGenerator::GetGlobalSetting(std::string const& name) const
+cmProp cmGlobalGenerator::GetGlobalSetting(std::string const& name) const
{
assert(!this->Makefiles.empty());
- return cmToCStr(this->Makefiles[0]->GetDefinition(name));
+ return this->Makefiles[0]->GetDefinition(name);
}
bool cmGlobalGenerator::GlobalSettingIsOn(std::string const& name) const
@@ -1183,7 +1195,7 @@ std::string cmGlobalGenerator::GetSafeGlobalSetting(
std::string const& name) const
{
assert(!this->Makefiles.empty());
- return this->Makefiles[0]->GetSafeDefinition(name);
+ return this->Makefiles[0]->GetDefinition(name);
}
bool cmGlobalGenerator::IgnoreFile(const char* ext) const
@@ -1251,10 +1263,8 @@ void cmGlobalGenerator::Configure()
this->CreateDefaultGlobalTargets(globalTargets);
for (const auto& mf : this->Makefiles) {
- auto& targets = mf->GetTargets();
for (GlobalTargetInfo const& globalTarget : globalTargets) {
- targets.emplace(globalTarget.Name,
- this->CreateGlobalTarget(globalTarget, mf.get()));
+ this->CreateGlobalTarget(globalTarget, mf.get());
}
}
}
@@ -1771,9 +1781,8 @@ void cmGlobalGenerator::CreateGeneratorTargets(
std::map<cmTarget*, cmGeneratorTarget*> const& importedMap)
{
if (targetTypes == AllTargets) {
- for (auto& target : mf->GetTargets()) {
- cmTarget* t = &target.second;
- lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(t, lg));
+ for (cmTarget* target : mf->GetOrderedTargets()) {
+ lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(target, lg));
}
}
@@ -2740,7 +2749,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
singleLine.push_back(cfgArg);
cfgArg = "-DEFFECTIVE_PLATFORM_NAME=$(EFFECTIVE_PLATFORM_NAME)";
} else {
- cfgArg += cmToCStr(mf->GetDefinition("CMAKE_CFG_INTDIR"));
+ cfgArg += *mf->GetDefinition("CMAKE_CFG_INTDIR");
}
singleLine.push_back(cfgArg);
}
@@ -2812,12 +2821,19 @@ bool cmGlobalGenerator::UseFolderProperty() const
return false;
}
-cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
- cmMakefile* mf)
+void cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
+ cmMakefile* mf)
{
// Package
- cmTarget target(gti.Name, cmStateEnums::GLOBAL_TARGET,
- cmTarget::VisibilityNormal, mf, gti.PerConfig);
+ auto tb =
+ mf->CreateNewTarget(gti.Name, cmStateEnums::GLOBAL_TARGET, gti.PerConfig);
+
+ // Do nothing if gti.Name is already used
+ if (!tb.second) {
+ return;
+ }
+
+ cmTarget& target = tb.first;
target.SetProperty("EXCLUDE_FROM_ALL", "TRUE");
std::vector<std::string> no_outputs;
@@ -2841,8 +2857,6 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
if (this->UseFolderProperty()) {
target.SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
}
-
- return target;
}
std::string cmGlobalGenerator::GenerateRuleFile(
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 147146e..34646d9 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -23,6 +23,7 @@
#include "cmCustomCommandLines.h"
#include "cmDuration.h"
#include "cmExportSet.h"
+#include "cmProperty.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -308,7 +309,7 @@ public:
cmExportSetMap& GetExportSets() { return this->ExportSets; }
- const char* GetGlobalSetting(std::string const& name) const;
+ cmProp GetGlobalSetting(std::string const& name) const;
bool GlobalSettingIsOn(std::string const& name) const;
std::string GetSafeGlobalSetting(std::string const& name) const;
@@ -596,7 +597,7 @@ protected:
void AddGlobalTarget_RebuildCache(
std::vector<GlobalTargetInfo>& targets) const;
void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets);
- cmTarget CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);
+ void CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);
std::string FindMakeProgramFile;
std::string ConfiguredFilesPath;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 7cf3e93..b81f82e 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -186,8 +186,7 @@ void cmGlobalGhsMultiGenerator::EnableLanguage(
mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
- const char* tgtPlatform =
- cmToCStrSafe(mf->GetDefinition("GHS_TARGET_PLATFORM"));
+ const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM")->c_str();
if (!tgtPlatform) {
cmSystemTools::Message("Green Hills MULTI: GHS_TARGET_PLATFORM not "
"specified; defaulting to \"integrity\"");
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 963118f..47a931d 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -382,7 +382,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
if (restat) {
vars["restat"] = "1";
}
- if (uses_terminal && this->SupportsConsolePool()) {
+ if (uses_terminal && this->SupportsDirectConsole()) {
vars["pool"] = "console";
} else if (!job_pool.empty()) {
vars["pool"] = job_pool;
@@ -920,14 +920,7 @@ void cmGlobalNinjaGenerator::EnableLanguage(
std::vector<std::string> const& langs, cmMakefile* mf, bool optional)
{
if (this->IsMultiConfig()) {
- if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
- mf->AddCacheDefinition(
- "CMAKE_CONFIGURATION_TYPES", "Debug;Release;RelWithDebInfo",
- "Semicolon separated list of supported configuration types, only "
- "supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything "
- "else will be ignored",
- cmStateEnums::STRING);
- }
+ mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;RelWithDebInfo");
}
this->cmGlobalGenerator::EnableLanguage(langs, mf, optional);
@@ -1019,13 +1012,6 @@ bool cmGlobalNinjaGenerator::HasRule(const std::string& name)
// Private virtual overrides
-std::string cmGlobalNinjaGenerator::GetEditCacheCommand() const
-{
- // Ninja by design does not run interactive tools in the terminal,
- // so our only choice is cmake-gui.
- return cmSystemTools::GetCMakeGUICommand();
-}
-
void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory(
cmGeneratorTarget* gt) const
{
@@ -1847,7 +1833,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
// Use 'console' pool to get non buffered output of the CMake re-run call
// Available since Ninja 1.5
- if (this->SupportsConsolePool()) {
+ if (this->SupportsDirectConsole()) {
reBuild.Variables["pool"] = "console";
}
@@ -1941,7 +1927,7 @@ std::string cmGlobalNinjaGenerator::NinjaCmd() const
return "ninja";
}
-bool cmGlobalNinjaGenerator::SupportsConsolePool() const
+bool cmGlobalNinjaGenerator::SupportsDirectConsole() const
{
return this->NinjaSupportsConsolePool;
}
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index bb4ce2b..ec73475 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -220,7 +220,6 @@ public:
{
return "package_source";
}
- const char* GetEditCacheTargetName() const override { return "edit_cache"; }
const char* GetRebuildCacheTargetName() const override
{
return "rebuild_cache";
@@ -406,7 +405,7 @@ public:
return "1.10.2";
}
static std::string RequiredNinjaVersionForCodePage() { return "1.11"; }
- bool SupportsConsolePool() const;
+ bool SupportsDirectConsole() const override;
bool SupportsImplicitOuts() const;
bool SupportsManifestRestat() const;
bool SupportsMultilineDepfile() const;
@@ -489,7 +488,6 @@ protected:
std::string DefaultFileConfig;
private:
- std::string GetEditCacheCommand() const override;
bool FindMakeProgram(cmMakefile* mf) override;
void CheckNinjaFeatures();
void CheckNinjaCodePage();
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 9c3de1e..d9f94a1 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -78,36 +78,6 @@ void cmGlobalUnixMakefileGenerator3::GetDocumentation(
entry.Brief = "Generates standard UNIX makefiles.";
}
-std::string cmGlobalUnixMakefileGenerator3::GetEditCacheCommand() const
-{
- // If generating for an extra IDE, the edit_cache target cannot
- // launch a terminal-interactive tool, so always use cmake-gui.
- if (!this->GetExtraGeneratorName().empty()) {
- return cmSystemTools::GetCMakeGUICommand();
- }
-
- // Use an internal cache entry to track the latest dialog used
- // to edit the cache, and use that for the edit_cache target.
- cmake* cm = this->GetCMakeInstance();
- std::string editCacheCommand = cm->GetCMakeEditCommand();
- if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") ||
- !editCacheCommand.empty()) {
- if (editCacheCommand.empty()) {
- editCacheCommand = cmSystemTools::GetCMakeCursesCommand();
- }
- if (editCacheCommand.empty()) {
- editCacheCommand = cmSystemTools::GetCMakeGUICommand();
- }
- if (!editCacheCommand.empty()) {
- cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
- "Path to cache edit program executable.",
- cmStateEnums::INTERNAL);
- }
- }
- cmProp edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND");
- return edit_cmd ? *edit_cmd : std::string();
-}
-
void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory(
cmGeneratorTarget* gt) const
{
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 7c950cc..94ee476 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -228,7 +228,6 @@ protected:
{
return "package_source";
}
- const char* GetEditCacheTargetName() const override { return "edit_cache"; }
const char* GetRebuildCacheTargetName() const override
{
return "rebuild_cache";
@@ -278,7 +277,6 @@ protected:
private:
const char* GetBuildIgnoreErrorsFlag() const override { return "-i"; }
- std::string GetEditCacheCommand() const override;
std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>,
cmStateSnapshot::StrictWeakOrder>
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index fdb7155..488ff2e 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -88,7 +88,7 @@ public:
void GetDocumentation(cmDocumentationEntry& entry) const override
{
entry.Name = std::string(vs10generatorName) + " [arch]";
- entry.Brief = "Generates Visual Studio 2010 project files. "
+ entry.Brief = "Deprecated. Generates Visual Studio 2010 project files. "
"Optional [arch] can be \"Win64\" or \"IA64\".";
}
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 0c85a044..34dba1e 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -107,14 +107,7 @@ void cmGlobalVisualStudio7Generator::EnableLanguage(
{
mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
- if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
- mf->AddCacheDefinition(
- "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
- "Semicolon separated list of supported configuration types, "
- "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
- "anything else will be ignored.",
- cmStateEnums::STRING);
- }
+ mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;MinSizeRel;RelWithDebInfo");
// Create list of configurations requested by user's cache, if any.
this->cmGlobalVisualStudioGenerator::EnableLanguage(lang, mf, optional);
@@ -303,6 +296,25 @@ void cmGlobalVisualStudio7Generator::Generate()
this->CallVisualStudioMacro(MacroReload,
GetSLNFile(this->LocalGenerators[0].get()));
}
+
+ if (this->Version == VS10 && !this->CMakeInstance->GetIsInTryCompile()) {
+ std::string cmakeWarnVS10;
+ if (cmProp cached = this->CMakeInstance->GetState()->GetCacheEntryValue(
+ "CMAKE_WARN_VS10")) {
+ this->CMakeInstance->MarkCliAsUsed("CMAKE_WARN_VS10");
+ cmakeWarnVS10 = *cached;
+ } else {
+ cmSystemTools::GetEnv("CMAKE_WARN_VS10", cmakeWarnVS10);
+ }
+ if (cmakeWarnVS10.empty() || !cmIsOff(cmakeWarnVS10)) {
+ this->CMakeInstance->IssueMessage(
+ MessageType::WARNING,
+ "The \"Visual Studio 10 2010\" generator is deprecated "
+ "and will be removed in a future version of CMake."
+ "\n"
+ "Add CMAKE_WARN_VS10=OFF to the cache to disable this warning.");
+ }
+ }
}
void cmGlobalVisualStudio7Generator::OutputSLNFile(
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 77403b0..3994816 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -431,14 +431,7 @@ void cmGlobalXCodeGenerator::EnableLanguage(
{
mf->AddDefinition("XCODE", "1");
mf->AddDefinition("XCODE_VERSION", this->VersionString);
- if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
- mf->AddCacheDefinition(
- "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
- "Semicolon separated list of supported configuration types, "
- "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
- "anything else will be ignored.",
- cmStateEnums::STRING);
- }
+ mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;MinSizeRel;RelWithDebInfo");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
this->ComputeArchitectures(mf);
diff --git a/Source/cmIncludeGuardCommand.cxx b/Source/cmIncludeGuardCommand.cxx
index aefd098..d48c823 100644
--- a/Source/cmIncludeGuardCommand.cxx
+++ b/Source/cmIncludeGuardCommand.cxx
@@ -4,6 +4,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 79109b5..687741b 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -36,6 +36,7 @@
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmProperty.h"
+#include "cmRange.h"
#include "cmRuntimeDependencyArchive.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -681,8 +682,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
te->LibraryGenerator = libraryGenerator.get();
te->RuntimeGenerator = runtimeGenerator.get();
te->ObjectsGenerator = objectGenerator.get();
- te->InterfaceIncludeDirectories =
- cmJoin(includesArgs.GetIncludeDirs(), ";");
+ target.AddInstallIncludeDirectories(
+ cmMakeRange(includesArgs.GetIncludeDirs()));
te->NamelinkOnly = namelinkOnly;
helper.Makefile->GetGlobalGenerator()
->GetExportSets()[exports]
diff --git a/Source/cmInstallMode.h b/Source/cmInstallMode.h
new file mode 100644
index 0000000..5343d34
--- /dev/null
+++ b/Source/cmInstallMode.h
@@ -0,0 +1,17 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/**
+ * Enumerate types known to file(INSTALL).
+ */
+enum class cmInstallMode
+{
+ COPY,
+ ABS_SYMLINK,
+ ABS_SYMLINK_OR_COPY,
+ REL_SYMLINK,
+ REL_SYMLINK_OR_COPY,
+ SYMLINK,
+ SYMLINK_OR_COPY
+};
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 4f7c959..2e444f2 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -548,7 +548,7 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) const
}
cmListFileContext lfc = this->TopEntry->Context;
cmStateSnapshot bottom = this->GetBottom();
- if (!bottom.GetState()->GetIsInTryCompile()) {
+ if (bottom.GetState()->GetProjectKind() == cmState::ProjectKind::Normal) {
lfc.FilePath = cmSystemTools::RelativeIfUnder(
bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
}
@@ -579,7 +579,7 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
out << "Call Stack (most recent call first):\n";
}
cmListFileContext lfc = cur->Context;
- if (!bottom.GetState()->GetIsInTryCompile()) {
+ if (bottom.GetState()->GetProjectKind() == cmState::ProjectKind::Normal) {
lfc.FilePath = cmSystemTools::RelativeIfUnder(
bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
}
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3b282de..028952a 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -107,10 +107,9 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
{
std::vector<std::string> cpath;
cmSystemTools::GetPath(cpath, "CPATH");
- for (std::string& cp : cpath) {
+ for (std::string const& cp : cpath) {
if (cmSystemTools::FileIsFullPath(cp)) {
- cp = cmSystemTools::CollapseFullPath(cp);
- this->EnvCPATH.emplace(std::move(cp));
+ this->EnvCPATH.emplace_back(cmSystemTools::CollapseFullPath(cp));
}
}
}
@@ -878,9 +877,12 @@ std::string cmLocalGenerator::GetIncludeFlags(
// Support special system include flag if it is available and the
// normal flag is repeated for each directory.
cmProp sysIncludeFlag = nullptr;
+ cmProp sysIncludeFlagWarning = nullptr;
if (repeatFlag) {
sysIncludeFlag = this->Makefile->GetDefinition(
cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", lang));
+ sysIncludeFlagWarning = this->Makefile->GetDefinition(
+ cmStrCat("_CMAKE_INCLUDE_SYSTEM_FLAG_", lang, "_WARNING"));
}
cmProp fwSearchFlag = this->Makefile->GetDefinition(
@@ -889,6 +891,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
cmStrCat("CMAKE_", lang, "_SYSTEM_FRAMEWORK_SEARCH_FLAG"));
bool flagUsed = false;
+ bool sysIncludeFlagUsed = false;
std::set<std::string> emitted;
#ifdef __APPLE__
emitted.insert("/System/Library/Frameworks");
@@ -915,6 +918,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
if (sysIncludeFlag && target &&
target->IsSystemIncludeDirectory(i, config, lang)) {
includeFlags << *sysIncludeFlag;
+ sysIncludeFlagUsed = true;
} else {
includeFlags << includeFlag;
}
@@ -931,6 +935,9 @@ std::string cmLocalGenerator::GetIncludeFlags(
}
includeFlags << sep;
}
+ if (sysIncludeFlagUsed && sysIncludeFlagWarning) {
+ includeFlags << *sysIncludeFlagWarning;
+ }
std::string flags = includeFlags.str();
// remove trailing separators
if ((sep[0] != ' ') && !flags.empty() && flags.back() == sep[0]) {
@@ -1239,19 +1246,31 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
}
}
+ bool const isCorCxx = (lang == "C" || lang == "CXX");
+
+ // Resolve symlinks in CPATH for comparison with resolved include paths.
+ // We do this here instead of when EnvCPATH is populated in case symlinks
+ // on disk have changed in the meantime.
+ std::set<std::string> resolvedEnvCPATH;
+ if (isCorCxx) {
+ for (std::string const& i : this->EnvCPATH) {
+ resolvedEnvCPATH.emplace(this->GlobalGenerator->GetRealPath(i));
+ }
+ }
+
// Checks if this is not an excluded (implicit) include directory.
- auto notExcluded = [this, &implicitSet, &implicitExclude,
- &lang](std::string const& dir) {
- return (
- // Do not exclude directories that are not in an excluded set.
- ((!cm::contains(implicitSet, this->GlobalGenerator->GetRealPath(dir))) &&
- (!cm::contains(implicitExclude, dir)))
+ auto notExcluded = [this, &implicitSet, &implicitExclude, &resolvedEnvCPATH,
+ isCorCxx](std::string const& dir) -> bool {
+ std::string const& real_dir = this->GlobalGenerator->GetRealPath(dir);
+ return
+ // Do not exclude directories that are not in any excluded set.
+ !(cm::contains(implicitSet, real_dir) ||
+ cm::contains(implicitExclude, dir))
// Do not exclude entries of the CPATH environment variable even though
// they are implicitly searched by the compiler. They are meant to be
// user-specified directories that can be re-ordered or converted to
// -isystem without breaking real compiler builtin headers.
- ||
- ((lang == "C" || lang == "CXX") && cm::contains(this->EnvCPATH, dir)));
+ || (isCorCxx && cm::contains(resolvedEnvCPATH, real_dir));
};
// Get the target-specific include directories.
@@ -3039,6 +3058,30 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags(
}
}
+bool cmLocalGenerator::AppendLWYUFlags(std::string& flags,
+ const cmGeneratorTarget* target,
+ const std::string& lang)
+{
+ auto useLWYU = target->GetPropertyAsBool("LINK_WHAT_YOU_USE") &&
+ (target->GetType() == cmStateEnums::TargetType::EXECUTABLE ||
+ target->GetType() == cmStateEnums::TargetType::SHARED_LIBRARY ||
+ target->GetType() == cmStateEnums::TargetType::MODULE_LIBRARY);
+
+ if (useLWYU) {
+ const auto& lwyuFlag = this->GetMakefile()->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_LINK_WHAT_YOU_USE_FLAG"));
+ useLWYU = !lwyuFlag.empty();
+
+ if (useLWYU) {
+ std::vector<BT<std::string>> lwyuOpts;
+ lwyuOpts.emplace_back(lwyuFlag);
+ this->AppendFlags(flags, target->ResolveLinkerWrapper(lwyuOpts, lang));
+ }
+ }
+
+ return useLWYU;
+}
+
void cmLocalGenerator::AppendCompileOptions(std::string& options,
std::string const& options_list,
const char* regex) const
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 993280a..1e09b23 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -171,6 +171,8 @@ public:
cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
+ bool AppendLWYUFlags(std::string& flags, const cmGeneratorTarget* target,
+ const std::string& lang);
enum class IncludePathStyle
{
@@ -587,7 +589,7 @@ protected:
std::string::size_type ObjectPathMax;
std::set<std::string> ObjectMaxPathViolations;
- std::set<std::string> EnvCPATH;
+ std::vector<std::string> EnvCPATH;
using GeneratorTargetMap =
std::unordered_map<std::string, cmGeneratorTarget*>;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 7f7b1e7..9f8e7ed 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -279,7 +279,7 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os)
std::string requiredVersion = cmGlobalNinjaGenerator::RequiredNinjaVersion();
// Ninja generator uses the 'console' pool if available (>= 1.5)
- if (this->GetGlobalNinjaGenerator()->SupportsConsolePool()) {
+ if (this->GetGlobalNinjaGenerator()->SupportsDirectConsole()) {
requiredVersion =
cmGlobalNinjaGenerator::RequiredNinjaVersionForConsolePool();
}
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 002f484..46f9d31 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -171,7 +171,7 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
// for visual studio IDE add extra stuff to the PATH
// if CMAKE_MSVCIDE_RUN_PATH is set.
- if (this->Makefile->GetDefinition("MSVC_IDE")) {
+ if (this->GetGlobalGenerator()->IsVisualStudio()) {
cmProp extraPath = this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH");
if (extraPath) {
script += newline;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index c970abe..0b8778f 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2118,15 +2118,23 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName,
cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type,
const std::string& name)
{
- auto it = this->Targets
- .emplace(name,
- cmTarget(name, type, cmTarget::VisibilityNormal, this,
- cmTarget::PerConfig::Yes))
- .first;
+ return &this->CreateNewTarget(name, type).first;
+}
+
+std::pair<cmTarget&, bool> cmMakefile::CreateNewTarget(
+ const std::string& name, cmStateEnums::TargetType type,
+ cmTarget::PerConfig perConfig)
+{
+ auto ib = this->Targets.emplace(
+ name, cmTarget(name, type, cmTarget::VisibilityNormal, this, perConfig));
+ auto it = ib.first;
+ if (!ib.second) {
+ return std::make_pair(std::ref(it->second), false);
+ }
this->OrderedTargets.push_back(&it->second);
this->GetGlobalGenerator()->IndexTarget(&it->second);
this->GetStateSnapshot().GetDirectory().AddNormalTargetName(name);
- return &it->second;
+ return std::make_pair(std::ref(it->second), true);
}
cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName,
@@ -2571,12 +2579,7 @@ cmProp cmMakefile::GetDefinition(const std::string& name) const
const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const
{
- static std::string const empty;
- cmProp def = this->GetDefinition(name);
- if (!def) {
- return empty;
- }
- return *def;
+ return this->GetDefinition(name);
}
bool cmMakefile::GetDefExpandList(const std::string& name,
@@ -2959,7 +2962,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew(
break;
case ENVIRONMENT:
if (cmSystemTools::GetEnv(lookup, svalue)) {
- value = &svalue;
+ value = cmProp(svalue);
}
break;
case CACHE:
@@ -3182,6 +3185,23 @@ void cmMakefile::RemoveVariablesInString(std::string& source,
}
}
+void cmMakefile::InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault)
+{
+ if (this->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
+ return;
+ }
+ std::string initConfigs;
+ if (!cmSystemTools::GetEnv("CMAKE_CONFIGURATION_TYPES", initConfigs)) {
+ initConfigs = genDefault;
+ }
+ this->AddCacheDefinition(
+ "CMAKE_CONFIGURATION_TYPES", initConfigs,
+ "Semicolon separated list of supported configuration types, "
+ "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
+ "anything else will be ignored.",
+ cmStateEnums::STRING);
+}
+
std::string cmMakefile::GetDefaultConfiguration() const
{
if (this->GetGlobalGenerator()->IsMultiConfig()) {
@@ -3542,8 +3562,8 @@ int cmMakefile::TryCompile(const std::string& srcdir,
// make sure the same generator is used
// use this program as the cmake to be run, it should not
// be run that way but the cmake object requires a vailid path
- cmake cm(cmake::RoleProject, cmState::Project);
- cm.SetIsInTryCompile(true);
+ cmake cm(cmake::RoleProject, cmState::Project,
+ cmState::ProjectKind::TryCompile);
auto gg = cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName());
if (!gg) {
this->IssueMessage(MessageType::INTERNAL_ERROR,
@@ -3987,7 +4007,7 @@ cmProp cmMakefile::GetProperty(const std::string& prop) const
return pair.first;
});
output = cmJoin(keys, ";");
- return &output;
+ return cmProp(output);
}
return this->StateSnapshot.GetDirectory().GetProperty(prop);
@@ -4426,13 +4446,12 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
return false;
}
- // Deprecate old policies, especially those that require a lot
- // of code to maintain the old behavior.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0081 &&
+ // Deprecate old policies.
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0088 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
- id == cmPolicies::CMP0065))) {
+ id == cmPolicies::CMP0065 || id == cmPolicies::CMP0083))) {
this->IssueMessage(MessageType::DEPRECATION_WARNING,
cmPolicies::GetPolicyDeprecatedWarning(id));
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 77e9c74..5886c86 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -13,6 +13,7 @@
#include <stack>
#include <string>
#include <unordered_map>
+#include <utility>
#include <vector>
#include <cm/optional>
@@ -230,6 +231,10 @@ public:
cmTarget* AddImportedTarget(const std::string& name,
cmStateEnums::TargetType type, bool global);
+ std::pair<cmTarget&, bool> CreateNewTarget(
+ const std::string& name, cmStateEnums::TargetType type,
+ cmTarget::PerConfig perConfig = cmTarget::PerConfig::Yes);
+
cmTarget* AddNewTarget(cmStateEnums::TargetType type,
const std::string& name);
@@ -310,6 +315,8 @@ public:
*/
void SetProjectName(std::string const& name);
+ void InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault);
+
/* Get the default configuration */
std::string GetDefaultConfiguration() const;
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 3a2744e..306b38f 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -397,9 +397,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
this->LocalGenerator->GetLinkLibsCMP0065(
linkLanguage, *this->GeneratorTarget));
- if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- this->LocalGenerator->AppendFlags(linkFlags, " -Wl,--no-as-needed");
- }
+ this->UseLWYU = this->LocalGenerator->AppendLWYUFlags(
+ linkFlags, this->GeneratorTarget, linkLanguage);
// Add language feature flags.
this->LocalGenerator->AddLanguageFlagsForLinking(
@@ -577,12 +576,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
vars.Launcher = linkerLauncher.c_str();
}
- if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- std::string cmakeCommand =
- cmStrCat(this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
- " -E __run_co_compile --lwyu=", targetOutPathReal);
- real_link_commands.push_back(std::move(cmakeCommand));
+ if (this->UseLWYU) {
+ cmProp lwyuCheck =
+ this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK");
+ if (lwyuCheck) {
+ std::string cmakeCommand = cmStrCat(
+ this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+ " -E __run_co_compile --lwyu=");
+ cmakeCommand += this->LocalGenerator->EscapeForShell(*lwyuCheck);
+ cmakeCommand += cmStrCat(" --source=", targetOutPathReal);
+ real_link_commands.push_back(std::move(cmakeCommand));
+ }
}
std::string launcher;
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index d0e3837..64992f2 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -178,9 +178,9 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags,
this->GetConfigName());
- if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed");
- }
+ this->UseLWYU = this->LocalGenerator->AppendLWYUFlags(
+ extraFlags, this->GeneratorTarget, linkLanguage);
+
this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
}
@@ -871,13 +871,18 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Get the set of commands.
std::string linkRule = this->GetLinkRule(linkRuleVar);
cmExpandList(linkRule, real_link_commands);
- if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE") &&
- (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY)) {
- std::string cmakeCommand = cmStrCat(
- this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
- " -E __run_co_compile --lwyu=", targetOutPathReal);
- real_link_commands.push_back(std::move(cmakeCommand));
+ if (this->UseLWYU) {
+ cmProp lwyuCheck =
+ this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK");
+ if (lwyuCheck) {
+ std::string cmakeCommand = cmStrCat(
+ this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+ " -E __run_co_compile --lwyu=");
+ cmakeCommand += this->LocalGenerator->EscapeForShell(*lwyuCheck);
+ cmakeCommand += cmStrCat(" --source=", targetOutPathReal);
+ real_link_commands.push_back(std::move(cmakeCommand));
+ }
}
// Expand placeholders.
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index a3e5553..626453f 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1398,6 +1398,13 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< "set(CMAKE_Fortran_TARGET_MODULE_DIR \""
<< this->GeneratorTarget->GetFortranModuleDirectory(working_dir)
<< "\")\n";
+
+ if (this->GeneratorTarget->IsFortranBuildingInstrinsicModules()) {
+ *this->InfoFileStream
+ << "\n"
+ << "# Fortran compiler is building intrinsic modules.\n"
+ << "set(CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_MODULES ON) \n";
+ }
/* clang-format on */
// and now write the rule to use it
diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx
index 45043fa..5908f74 100644
--- a/Source/cmMarkAsAdvancedCommand.cxx
+++ b/Source/cmMarkAsAdvancedCommand.cxx
@@ -6,6 +6,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 5c21d1b..96e9142 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -581,17 +581,23 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd(
}
}
cmExpandList(linkCmdStr, linkCmds);
- if (this->GetGeneratorTarget()->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- std::string cmakeCommand = cmStrCat(
- this->GetLocalGenerator()->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
- " -E __run_co_compile --lwyu=");
- cmGeneratorTarget& gt = *this->GetGeneratorTarget();
- std::string targetOutputReal = this->ConvertToNinjaPath(
- gt.GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact,
- /*realname=*/true));
- cmakeCommand += targetOutputReal;
- linkCmds.push_back(std::move(cmakeCommand));
+ if (this->UseLWYU) {
+ cmProp lwyuCheck = mf->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK");
+ if (lwyuCheck) {
+ std::string cmakeCommand = cmStrCat(
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+ " -E __run_co_compile --lwyu=");
+ cmakeCommand +=
+ this->GetLocalGenerator()->EscapeForShell(*lwyuCheck);
+
+ std::string targetOutputReal =
+ this->ConvertToNinjaPath(this->GetGeneratorTarget()->GetFullPath(
+ config, cmStateEnums::RuntimeBinaryArtifact,
+ /*realname=*/true));
+ cmakeCommand += cmStrCat(" --source=", targetOutputReal);
+ linkCmds.push_back(std::move(cmakeCommand));
+ }
}
return linkCmds;
}
@@ -1156,12 +1162,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"],
config);
- if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE") &&
- (gt->GetType() == cmStateEnums::TargetType::EXECUTABLE ||
- gt->GetType() == cmStateEnums::TargetType::SHARED_LIBRARY ||
- gt->GetType() == cmStateEnums::TargetType::MODULE_LIBRARY)) {
- vars["LINK_FLAGS"] += " -Wl,--no-as-needed";
- }
+
+ this->UseLWYU = this->GetLocalGenerator()->AppendLWYUFlags(
+ vars["LINK_FLAGS"], this->GetGeneratorTarget(),
+ this->TargetLinkLanguage(config));
+
vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]);
vars["MANIFESTS"] = this->GetManifests(config);
diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx
index bae67e0..014da4d 100644
--- a/Source/cmOptionCommand.cxx
+++ b/Source/cmOptionCommand.cxx
@@ -29,7 +29,7 @@ bool cmOptionCommand(std::vector<std::string> const& args,
{
auto policyStatus =
status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077);
- const auto* existsBeforeSet =
+ const auto& existsBeforeSet =
status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]);
switch (policyStatus) {
case cmPolicies::WARN:
@@ -77,7 +77,7 @@ bool cmOptionCommand(std::vector<std::string> const& args,
}
if (checkAndWarn) {
- const auto* existsAfterSet =
+ const auto& existsAfterSet =
status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]);
if (!existsAfterSet) {
status.GetMakefile().IssueMessage(
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 01e8c04..fc839c5 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -10,6 +10,7 @@
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmProperty.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
diff --git a/Source/cmProperty.cxx b/Source/cmProperty.cxx
new file mode 100644
index 0000000..d012630
--- /dev/null
+++ b/Source/cmProperty.cxx
@@ -0,0 +1,113 @@
+
+#include "cmProperty.h"
+
+#include <string>
+
+#include <cmext/string_view>
+
+#include "cmStringAlgorithms.h"
+
+std::string cmProp::Empty;
+
+bool cmProp::IsOn(cm::string_view value) noexcept
+{
+ switch (value.size()) {
+ case 1:
+ return value[0] == '1' || value[0] == 'Y' || value[0] == 'y';
+ case 2:
+ return //
+ (value[0] == 'O' || value[0] == 'o') && //
+ (value[1] == 'N' || value[1] == 'n');
+ case 3:
+ return //
+ (value[0] == 'Y' || value[0] == 'y') && //
+ (value[1] == 'E' || value[1] == 'e') && //
+ (value[2] == 'S' || value[2] == 's');
+ case 4:
+ return //
+ (value[0] == 'T' || value[0] == 't') && //
+ (value[1] == 'R' || value[1] == 'r') && //
+ (value[2] == 'U' || value[2] == 'u') && //
+ (value[3] == 'E' || value[3] == 'e');
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool cmProp::IsOff(cm::string_view value) noexcept
+{
+ switch (value.size()) {
+ case 0:
+ return true;
+ case 1:
+ return value[0] == '0' || value[0] == 'N' || value[0] == 'n';
+ case 2:
+ return //
+ (value[0] == 'N' || value[0] == 'n') && //
+ (value[1] == 'O' || value[1] == 'o');
+ case 3:
+ return //
+ (value[0] == 'O' || value[0] == 'o') && //
+ (value[1] == 'F' || value[1] == 'f') && //
+ (value[2] == 'F' || value[2] == 'f');
+ case 5:
+ return //
+ (value[0] == 'F' || value[0] == 'f') && //
+ (value[1] == 'A' || value[1] == 'a') && //
+ (value[2] == 'L' || value[2] == 'l') && //
+ (value[3] == 'S' || value[3] == 's') && //
+ (value[4] == 'E' || value[4] == 'e');
+ case 6:
+ return //
+ (value[0] == 'I' || value[0] == 'i') && //
+ (value[1] == 'G' || value[1] == 'g') && //
+ (value[2] == 'N' || value[2] == 'n') && //
+ (value[3] == 'O' || value[3] == 'o') && //
+ (value[4] == 'R' || value[4] == 'r') && //
+ (value[5] == 'E' || value[5] == 'e');
+ default:
+ break;
+ }
+
+ return IsNOTFOUND(value);
+}
+bool cmProp::IsNOTFOUND(cm::string_view value) noexcept
+{
+ return (value == "NOTFOUND"_s) || cmHasSuffix(value, "-NOTFOUND"_s);
+}
+
+int cmProp::Compare(cmProp value) const noexcept
+{
+ if (this->Value == nullptr && !value) {
+ return 0;
+ }
+ if (this->Value == nullptr) {
+ return -1;
+ }
+ if (!value) {
+ return 1;
+ }
+ return this->Value->compare(*value);
+}
+
+int cmProp::Compare(cm::string_view value) const noexcept
+{
+ if (this->Value == nullptr && value.data() == nullptr) {
+ return 0;
+ }
+ if (this->Value == nullptr) {
+ return -1;
+ }
+ if (value.data() == nullptr) {
+ return 1;
+ }
+ return cm::string_view(*this->Value).compare(value);
+}
+
+std::ostream& operator<<(std::ostream& o, cmProp v)
+{
+ o << *v;
+ return o;
+}
diff --git a/Source/cmProperty.h b/Source/cmProperty.h
index 1e03c3f..3a0a5be 100644
--- a/Source/cmProperty.h
+++ b/Source/cmProperty.h
@@ -4,8 +4,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
+#include <iosfwd>
#include <string>
+#include <cm/string_view>
+
class cmProperty
{
public:
@@ -23,14 +27,210 @@ public:
};
};
-using cmProp = const std::string*;
+class cmProp
+{
+public:
+ cmProp() noexcept = default;
+ cmProp(std::nullptr_t) noexcept {}
+ explicit cmProp(const std::string* value) noexcept
+ : Value(value)
+ {
+ }
+ explicit cmProp(const std::string& value) noexcept
+ : Value(&value)
+ {
+ }
+ cmProp(const cmProp& other) noexcept = default;
-inline const char* cmToCStr(cmProp p)
+ cmProp& operator=(const cmProp& other) noexcept = default;
+ cmProp& operator=(std::nullptr_t) noexcept
+ {
+ this->Value = nullptr;
+ return *this;
+ }
+
+ const std::string* Get() const noexcept { return this->Value; }
+ const char* GetCStr() const noexcept
+ {
+ return this->Value == nullptr ? nullptr : this->Value->c_str();
+ }
+
+ const std::string* operator->() const noexcept
+ {
+ return this->Value == nullptr ? &cmProp::Empty : this->Value;
+ }
+ const std::string& operator*() const noexcept
+ {
+ return this->Value == nullptr ? cmProp::Empty : *this->Value;
+ }
+
+ explicit operator bool() const noexcept { return this->Value != nullptr; }
+ operator const std::string&() const noexcept { return this->operator*(); }
+ operator cm::string_view() const noexcept { return this->operator*(); }
+
+ /**
+ * Does the value indicate a true or ON value?
+ */
+ bool IsOn() const noexcept
+ {
+ return this->Value != nullptr &&
+ cmProp::IsOn(cm::string_view(*this->Value));
+ }
+ /**
+ * Does the value indicate a false or off value ? Note that this is
+ * not the same as !IsOn(...) because there are a number of
+ * ambiguous values such as "/usr/local/bin" a path will result in
+ * IsOn and IsOff both returning false. Note that the special path
+ * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
+ */
+ bool IsOff() const noexcept
+ {
+ return this->Value == nullptr ||
+ cmProp::IsOff(cm::string_view(*this->Value));
+ }
+ /** Return true if value is NOTFOUND or ends in -NOTFOUND. */
+ bool IsNOTFOUND() const noexcept
+ {
+ return this->Value != nullptr &&
+ cmProp::IsNOTFOUND(cm::string_view(*this->Value));
+ }
+ bool IsEmpty() const noexcept
+ {
+ return this->Value == nullptr || this->Value->empty();
+ }
+
+ bool IsSet() const noexcept
+ {
+ return !this->IsEmpty() && !this->IsNOTFOUND();
+ }
+
+ /**
+ * Does a string indicate a true or ON value?
+ */
+ static bool IsOn(const char* value) noexcept
+ {
+ return value != nullptr && IsOn(cm::string_view(value));
+ }
+ static bool IsOn(cm::string_view) noexcept;
+
+ /**
+ * Compare method has same semantic as std::optional::compare
+ */
+ int Compare(cmProp value) const noexcept;
+ int Compare(cm::string_view value) const noexcept;
+
+ /**
+ * Does a string indicate a false or off value ? Note that this is
+ * not the same as !IsOn(...) because there are a number of
+ * ambiguous values such as "/usr/local/bin" a path will result in
+ * IsOn and IsOff both returning false. Note that the special path
+ * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
+ */
+ static bool IsOff(const char* value) noexcept
+ {
+ return value == nullptr || IsOff(cm::string_view(value));
+ }
+ static bool IsOff(cm::string_view) noexcept;
+
+ /** Return true if value is NOTFOUND or ends in -NOTFOUND. */
+ static bool IsNOTFOUND(const char* value) noexcept
+ {
+ return value == nullptr || IsNOTFOUND(cm::string_view(value));
+ }
+ static bool IsNOTFOUND(cm::string_view) noexcept;
+
+ static bool IsEmpty(const char* value) noexcept
+ {
+ return value == nullptr || *value == '\0';
+ }
+ static bool IsEmpty(cm::string_view value) noexcept { return value.empty(); }
+
+private:
+ static std::string Empty;
+ const std::string* Value = nullptr;
+};
+
+std::ostream& operator<<(std::ostream& o, cmProp v);
+
+inline bool operator==(cmProp l, cmProp r) noexcept
+{
+ return l.Compare(r) == 0;
+}
+inline bool operator!=(cmProp l, cmProp r) noexcept
{
- return p ? p->c_str() : nullptr;
+ return l.Compare(r) != 0;
+}
+inline bool operator<(cmProp l, cmProp r) noexcept
+{
+ return l.Compare(r) < 0;
+}
+inline bool operator<=(cmProp l, cmProp r) noexcept
+{
+ return l.Compare(r) <= 0;
+}
+inline bool operator>(cmProp l, cmProp r) noexcept
+{
+ return l.Compare(r) > 0;
+}
+inline bool operator>=(cmProp l, cmProp r) noexcept
+{
+ return l.Compare(r) >= 0;
}
-inline const char* cmToCStrSafe(cmProp p)
+inline bool operator==(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) == 0;
+}
+inline bool operator!=(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) != 0;
+}
+inline bool operator<(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) < 0;
+}
+inline bool operator<=(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) <= 0;
+}
+inline bool operator>(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) > 0;
+}
+inline bool operator>=(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) >= 0;
+}
+
+inline bool operator==(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) == 0;
+}
+inline bool operator!=(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) != 0;
+}
+inline bool operator<(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) < 0;
+}
+inline bool operator<=(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) <= 0;
+}
+inline bool operator>(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) > 0;
+}
+inline bool operator>=(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) >= 0;
+}
+
+/**
+ * Temporary wrapper
+ */
+inline const char* cmToCStr(cmProp p)
{
- return p ? p->c_str() : "";
+ return p.GetCStr();
}
diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx
index 06e151a..3e3a44b 100644
--- a/Source/cmPropertyMap.cxx
+++ b/Source/cmPropertyMap.cxx
@@ -46,7 +46,7 @@ cmProp cmPropertyMap::GetPropertyValue(const std::string& name) const
{
auto it = this->Map_.find(name);
if (it != this->Map_.end()) {
- return &it->second;
+ return cmProp(it->second);
}
return nullptr;
}
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 898d862..57fcd2d 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -384,39 +384,3 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile,
}
return true;
}
-
-bool cmQtAutoGen::FileRead(std::string& content, std::string const& filename,
- std::string* error)
-{
- content.clear();
- if (!cmSystemTools::FileExists(filename, true)) {
- if (error != nullptr) {
- *error = "Not a file.";
- }
- return false;
- }
-
- unsigned long const length = cmSystemTools::FileLength(filename);
- cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
-
- // Use lambda to save destructor calls of ifs
- return [&ifs, length, &content, error]() -> bool {
- if (!ifs) {
- if (error != nullptr) {
- *error = "Opening the file for reading failed.";
- }
- return false;
- }
- content.reserve(length);
- using IsIt = std::istreambuf_iterator<char>;
- content.assign(IsIt{ ifs }, IsIt{});
- if (!ifs) {
- content.clear();
- if (error != nullptr) {
- *error = "Reading from the file failed.";
- }
- return false;
- }
- return true;
- }();
-}
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index b9ae360..466a954 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -100,9 +100,6 @@ public:
std::vector<std::string> const& newOpts,
bool isQt5);
- static bool FileRead(std::string& content, std::string const& filename,
- std::string* error = nullptr);
-
/** @class RccLister
* @brief Lists files in qrc resource files
*/
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 6cc8328..4dd78e5 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -902,13 +902,6 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// The reason is that their file names might be discovered from source files
// at generation time.
if (this->MocOrUicEnabled()) {
- std::set<std::string> uicIncludes;
- auto collectUicIncludes = [&](std::unique_ptr<cmSourceFile> const& sf) {
- std::string content;
- FileRead(content, sf->GetFullPath());
- this->AutoUicHelpers.CollectUicIncludes(uicIncludes, content);
- };
-
for (const auto& sf : this->Makefile->GetSourceFiles()) {
// sf->GetExtension() is only valid after sf->ResolveFullPath() ...
// Since we're iterating over source files that might be not in the
@@ -921,10 +914,6 @@ bool cmQtAutoGenInitializer::InitScanFiles()
std::string const& extLower =
cmSystemTools::LowerCase(sf->GetExtension());
- bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
- bool const skipUic =
- (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC) ||
- !this->Uic.Enabled);
if (cm->IsAHeaderExtension(extLower)) {
if (!cm::contains(this->AutogenTarget.Headers, sf.get())) {
auto muf = makeMUFile(sf.get(), fullPath, {}, false);
@@ -932,9 +921,6 @@ bool cmQtAutoGenInitializer::InitScanFiles()
addMUHeader(std::move(muf), extLower);
}
}
- if (!skipUic && !sf->GetIsGenerated()) {
- collectUicIncludes(sf);
- }
} else if (cm->IsACLikeSourceExtension(extLower)) {
if (!cm::contains(this->AutogenTarget.Sources, sf.get())) {
auto muf = makeMUFile(sf.get(), fullPath, {}, false);
@@ -942,11 +928,11 @@ bool cmQtAutoGenInitializer::InitScanFiles()
addMUSource(std::move(muf));
}
}
- if (!skipUic && !sf->GetIsGenerated()) {
- collectUicIncludes(sf);
- }
} else if (this->Uic.Enabled && (extLower == kw.ui)) {
// .ui file
+ bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
+ bool const skipUic =
+ (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC));
if (!skipUic) {
// Check if the .ui file has uic options
std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS);
@@ -956,22 +942,35 @@ bool cmQtAutoGenInitializer::InitScanFiles()
this->Uic.UiFilesWithOptions.emplace_back(fullPath,
cmExpandedList(uicOpts));
}
+
+ auto uiHeaderRelativePath = cmSystemTools::RelativePath(
+ this->LocalGen->GetCurrentSourceDirectory(),
+ cmSystemTools::GetFilenamePath(fullPath));
+
+ // Avoid creating a path containing adjacent slashes
+ if (!uiHeaderRelativePath.empty() &&
+ uiHeaderRelativePath.back() != '/') {
+ uiHeaderRelativePath += '/';
+ }
+
+ auto uiHeaderFilePath = cmStrCat(
+ '/', uiHeaderRelativePath, "ui_"_s,
+ cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s);
+
+ ConfigString uiHeader;
+ std::string uiHeaderGenex;
+ this->ConfigFileNamesAndGenex(
+ uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s),
+ uiHeaderFilePath);
+
+ this->Uic.UiHeaders.emplace_back(
+ std::make_pair(uiHeader, uiHeaderGenex));
} else {
// Register skipped .ui file
this->Uic.SkipUi.insert(fullPath);
}
}
}
-
- for (const auto& include : uicIncludes) {
- ConfigString uiHeader;
- std::string uiHeaderGenex;
- this->ConfigFileNamesAndGenex(uiHeader, uiHeaderGenex,
- cmStrCat(this->Dir.Build, "/include"_s),
- cmStrCat("/"_s, include));
- this->Uic.UiHeaders.emplace_back(
- std::make_pair(uiHeader, uiHeaderGenex));
- }
}
// Process GENERATED sources and headers
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index 3ec87d2..e76817b 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -17,7 +17,6 @@
#include "cmFilePathChecksum.h"
#include "cmQtAutoGen.h"
-#include "cmQtAutoUicHelpers.h"
class cmGeneratorTarget;
class cmGlobalGenerator;
@@ -171,7 +170,6 @@ private:
std::string ConfigDefault;
std::vector<std::string> ConfigsList;
std::string TargetsFolder;
- cmQtAutoUicHelpers AutoUicHelpers;
/** Common directories. */
struct
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index 0c6b5e6..568926e 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -121,6 +121,43 @@ bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename)
return success;
}
+bool cmQtAutoGenerator::FileRead(std::string& content,
+ std::string const& filename,
+ std::string* error)
+{
+ content.clear();
+ if (!cmSystemTools::FileExists(filename, true)) {
+ if (error != nullptr) {
+ *error = "Not a file.";
+ }
+ return false;
+ }
+
+ unsigned long const length = cmSystemTools::FileLength(filename);
+ cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
+
+ // Use lambda to save destructor calls of ifs
+ return [&ifs, length, &content, error]() -> bool {
+ if (!ifs) {
+ if (error != nullptr) {
+ *error = "Opening the file for reading failed.";
+ }
+ return false;
+ }
+ content.reserve(length);
+ using IsIt = std::istreambuf_iterator<char>;
+ content.assign(IsIt{ ifs }, IsIt{});
+ if (!ifs) {
+ content.clear();
+ if (error != nullptr) {
+ *error = "Reading from the file failed.";
+ }
+ return false;
+ }
+ return true;
+ }();
+}
+
bool cmQtAutoGenerator::FileWrite(std::string const& filename,
std::string const& content,
std::string* error)
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index 66399d7..5c3a8ad 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -70,6 +70,8 @@ public:
// -- File system methods
static bool MakeParentDirectory(std::string const& filename);
+ static bool FileRead(std::string& content, std::string const& filename,
+ std::string* error = nullptr);
static bool FileWrite(std::string const& filename,
std::string const& content,
std::string* error = nullptr);
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 86d54f9..2753fd5 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -30,7 +30,6 @@
#include "cmGeneratedFileStream.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
-#include "cmQtAutoUicHelpers.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkerPool.h"
@@ -282,7 +281,7 @@ public:
std::vector<std::string> Options;
std::unordered_map<std::string, UiFile> UiFiles;
std::vector<std::string> SearchPaths;
- cmQtAutoUicHelpers AutoUicHelpers;
+ cmsys::RegularExpression RegExpInclude;
};
/** Uic shared variables. */
@@ -762,7 +761,11 @@ std::string cmQtAutoMocUicT::MocSettingsT::MacrosString() const
return res;
}
-cmQtAutoMocUicT::UicSettingsT::UicSettingsT() = default;
+cmQtAutoMocUicT::UicSettingsT::UicSettingsT()
+{
+ this->RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
+ "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
+}
cmQtAutoMocUicT::UicSettingsT::~UicSettingsT() = default;
@@ -1053,7 +1056,16 @@ void cmQtAutoMocUicT::JobParseT::UicIncludes()
}
std::set<std::string> includes;
- this->UicConst().AutoUicHelpers.CollectUicIncludes(includes, this->Content);
+ {
+ const char* contentChars = this->Content.c_str();
+ cmsys::RegularExpression const& regExp = this->UicConst().RegExpInclude;
+ cmsys::RegularExpressionMatch match;
+ while (regExp.find(contentChars, match)) {
+ includes.emplace(match.match(2));
+ // Forward content pointer
+ contentChars += match.end();
+ }
+ }
this->CreateKeys(this->FileHandle->ParseData->Uic.Include, includes,
UiUnderscoreLength);
}
diff --git a/Source/cmQtAutoUicHelpers.cxx b/Source/cmQtAutoUicHelpers.cxx
deleted file mode 100644
index 751ae08..0000000
--- a/Source/cmQtAutoUicHelpers.cxx
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoUicHelpers.h"
-
-cmQtAutoUicHelpers::cmQtAutoUicHelpers()
-{
- RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
- "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
-}
-
-void cmQtAutoUicHelpers::CollectUicIncludes(std::set<std::string>& includes,
- const std::string& content) const
-{
- if (content.find("ui_") == std::string::npos) {
- return;
- }
-
- const char* contentChars = content.c_str();
- cmsys::RegularExpressionMatch match;
- while (this->RegExpInclude.find(contentChars, match)) {
- includes.emplace(match.match(2));
- // Forward content pointer
- contentChars += match.end();
- }
-}
diff --git a/Source/cmQtAutoUicHelpers.h b/Source/cmQtAutoUicHelpers.h
deleted file mode 100644
index 6b09a31..0000000
--- a/Source/cmQtAutoUicHelpers.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#pragma once
-
-#include <set>
-#include <string>
-
-#include "cmsys/RegularExpression.hxx"
-
-class cmQtAutoUicHelpers
-{
-public:
- cmQtAutoUicHelpers();
- virtual ~cmQtAutoUicHelpers() = default;
- void CollectUicIncludes(std::set<std::string>& includes,
- const std::string& content) const;
-
-private:
- cmsys::RegularExpression RegExpInclude;
-};
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index 3f3c8d5..f2b5cc4 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -342,7 +342,7 @@ cmProp cmSourceFile::GetPropertyForUser(const std::string& prop)
// if it is requested by the user.
if (prop == propLANGUAGE) {
// The pointer is valid until `this->Language` is modified.
- return &this->GetOrDetermineLanguage();
+ return cmProp(this->GetOrDetermineLanguage());
}
// Special handling for GENERATED property.
@@ -355,9 +355,9 @@ cmProp cmSourceFile::GetPropertyForUser(const std::string& prop)
(policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD)
? CheckScope::GlobalAndLocal
: CheckScope::Global)) {
- return &propTRUE;
+ return cmProp(propTRUE);
}
- return &propFALSE;
+ return cmProp(propFALSE);
}
// Perform the normal property lookup.
@@ -371,7 +371,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
if (this->FullPath.empty()) {
return nullptr;
}
- return &this->FullPath;
+ return cmProp(this->FullPath);
}
// Check for the properties with backtraces.
@@ -382,7 +382,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->IncludeDirectories, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propCOMPILE_OPTIONS) {
@@ -392,7 +392,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->CompileOptions, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propCOMPILE_DEFINITIONS) {
@@ -402,7 +402,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->CompileDefinitions, ";");
- return &output;
+ return cmProp(output);
}
cmProp retVal = this->Properties.GetPropertyValue(prop);
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index 37ed4c1..499317d 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -57,10 +57,10 @@ int ParseStd(std::string const& level)
return -1;
}
-struct StanardLevelComputer
+struct StandardLevelComputer
{
- explicit StanardLevelComputer(std::string lang, std::vector<int> levels,
- std::vector<std::string> levelsStr)
+ explicit StandardLevelComputer(std::string lang, std::vector<int> levels,
+ std::vector<std::string> levelsStr)
: Language(std::move(lang))
, Levels(std::move(levels))
, LevelsAsStrings(std::move(levelsStr))
@@ -308,31 +308,33 @@ struct StanardLevelComputer
std::vector<std::string> LevelsAsStrings;
};
-std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping =
- { { "C",
- StanardLevelComputer{
+std::unordered_map<std::string, StandardLevelComputer>
+ StandardComputerMapping = {
+ { "C",
+ StandardLevelComputer{
"C", std::vector<int>{ 90, 99, 11, 17, 23 },
std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
{ "CXX",
- StanardLevelComputer{
+ StandardLevelComputer{
"CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
{ "CUDA",
- StanardLevelComputer{
+ StandardLevelComputer{
"CUDA", std::vector<int>{ 03, 11, 14, 17, 20, 23 },
std::vector<std::string>{ "03", "11", "14", "17", "20", "23" } } },
{ "OBJC",
- StanardLevelComputer{
+ StandardLevelComputer{
"OBJC", std::vector<int>{ 90, 99, 11, 17, 23 },
std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
{ "OBJCXX",
- StanardLevelComputer{
+ StandardLevelComputer{
"OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
{ "HIP",
- StanardLevelComputer{
+ StandardLevelComputer{
"HIP", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
- std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } } };
+ std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } }
+ };
}
std::string cmStandardLevelResolver::GetCompileOptionDef(
@@ -387,7 +389,11 @@ bool cmStandardLevelResolver::CheckCompileFeaturesAvailable(
return false;
}
- const char* features = this->CompileFeaturesAvailable(lang, error);
+ if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) {
+ return true;
+ }
+
+ cmProp features = this->CompileFeaturesAvailable(lang, error);
if (!features) {
return false;
}
@@ -465,7 +471,7 @@ bool cmStandardLevelResolver::CompileFeatureKnown(
return false;
}
-const char* cmStandardLevelResolver::CompileFeaturesAvailable(
+cmProp cmStandardLevelResolver::CompileFeaturesAvailable(
const std::string& lang, std::string* error) const
{
if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) {
@@ -507,7 +513,7 @@ const char* cmStandardLevelResolver::CompileFeaturesAvailable(
}
return nullptr;
}
- return cmToCStr(featuresKnown);
+ return featuresKnown;
}
bool cmStandardLevelResolver::GetNewRequiredStandard(
diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h
index d84fbcb..c01a3b1 100644
--- a/Source/cmStandardLevelResolver.h
+++ b/Source/cmStandardLevelResolver.h
@@ -30,8 +30,8 @@ public:
const std::string& feature, std::string& lang,
std::string* error) const;
- const char* CompileFeaturesAvailable(const std::string& lang,
- std::string* error) const;
+ cmProp CompileFeaturesAvailable(const std::string& lang,
+ std::string* error) const;
bool GetNewRequiredStandard(const std::string& targetName,
const std::string& feature,
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index ce6eb31..bde3e2e 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -26,7 +26,9 @@
#include "cmSystemTools.h"
#include "cmake.h"
-cmState::cmState()
+cmState::cmState(Mode mode, ProjectKind projectKind)
+ : StateMode(mode)
+ , StateProjectKind(projectKind)
{
this->CacheManager = cm::make_unique<cmCacheManager>();
this->GlobVerificationManager = cm::make_unique<cmGlobVerificationManager>();
@@ -381,16 +383,6 @@ void cmState::ClearEnabledLanguages()
this->EnabledLanguages.clear();
}
-bool cmState::GetIsInTryCompile() const
-{
- return this->IsInTryCompile;
-}
-
-void cmState::SetIsInTryCompile(bool b)
-{
- this->IsInTryCompile = b;
-}
-
bool cmState::GetIsGeneratorMultiConfig() const
{
return this->IsGeneratorMultiConfig;
@@ -593,8 +585,9 @@ cmProp cmState::GetGlobalProperty(const std::string& prop)
std::vector<std::string> commands = this->GetCommandNames();
this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str());
} else if (prop == "IN_TRY_COMPILE") {
- this->SetGlobalProperty("IN_TRY_COMPILE",
- this->IsInTryCompile ? "1" : "0");
+ this->SetGlobalProperty(
+ "IN_TRY_COMPILE",
+ this->StateProjectKind == ProjectKind::TryCompile ? "1" : "0");
} else if (prop == "GENERATOR_IS_MULTI_CONFIG") {
this->SetGlobalProperty("GENERATOR_IS_MULTI_CONFIG",
this->IsGeneratorMultiConfig ? "1" : "0");
@@ -610,47 +603,47 @@ cmProp cmState::GetGlobalProperty(const std::string& prop)
if (prop == "CMAKE_C_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmProp(s_out);
}
if (prop == "CMAKE_C90_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_C90_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmProp(s_out);
}
if (prop == "CMAKE_C99_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_C99_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmProp(s_out);
}
if (prop == "CMAKE_C11_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_C11_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmProp(s_out);
}
if (prop == "CMAKE_CXX_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmProp(s_out);
}
if (prop == "CMAKE_CXX98_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_CXX98_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmProp(s_out);
}
if (prop == "CMAKE_CXX11_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_CXX11_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmProp(s_out);
}
if (prop == "CMAKE_CXX14_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmProp(s_out);
}
if (prop == "CMAKE_CUDA_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_CUDA_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmProp(s_out);
}
#undef STRING_LIST_ELEMENT
@@ -771,17 +764,12 @@ unsigned int cmState::GetCacheMinorVersion() const
cmState::Mode cmState::GetMode() const
{
- return this->CurrentMode;
+ return this->StateMode;
}
std::string cmState::GetModeString() const
{
- return ModeToString(this->CurrentMode);
-}
-
-void cmState::SetMode(cmState::Mode mode)
-{
- this->CurrentMode = mode;
+ return ModeToString(this->StateMode);
}
std::string cmState::ModeToString(cmState::Mode mode)
@@ -803,6 +791,11 @@ std::string cmState::ModeToString(cmState::Mode mode)
return "UNKNOWN";
}
+cmState::ProjectKind cmState::GetProjectKind() const
+{
+ return this->StateProjectKind;
+}
+
std::string const& cmState::GetBinaryDirectory() const
{
return this->BinaryDirectory;
diff --git a/Source/cmState.h b/Source/cmState.h
index 9951b9a..8561fc0 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -35,12 +35,6 @@ class cmState
friend class cmStateSnapshot;
public:
- cmState();
- ~cmState();
-
- cmState(const cmState&) = delete;
- cmState& operator=(const cmState&) = delete;
-
enum Mode
{
Unknown,
@@ -51,6 +45,18 @@ public:
CPack,
};
+ enum class ProjectKind
+ {
+ Normal,
+ TryCompile,
+ };
+
+ cmState(Mode mode, ProjectKind projectKind = ProjectKind::Normal);
+ ~cmState();
+
+ cmState(const cmState&) = delete;
+ cmState& operator=(const cmState&) = delete;
+
static const std::string& GetTargetTypeName(
cmStateEnums::TargetType targetType);
@@ -141,9 +147,6 @@ public:
void SetEnabledLanguages(std::vector<std::string> const& langs);
void ClearEnabledLanguages();
- bool GetIsInTryCompile() const;
- void SetIsInTryCompile(bool b);
-
bool GetIsGeneratorMultiConfig() const;
void SetIsGeneratorMultiConfig(bool b);
@@ -207,10 +210,11 @@ public:
Mode GetMode() const;
std::string GetModeString() const;
- void SetMode(Mode mode);
static std::string ModeToString(Mode mode);
+ ProjectKind GetProjectKind() const;
+
private:
friend class cmake;
void AddCacheEntry(const std::string& key, const char* value,
@@ -248,7 +252,6 @@ private:
std::string SourceDirectory;
std::string BinaryDirectory;
- bool IsInTryCompile = false;
bool IsGeneratorMultiConfig = false;
bool WindowsShell = false;
bool WindowsVSIDE = false;
@@ -258,5 +261,6 @@ private:
bool NMake = false;
bool MSYSShell = false;
bool NinjaMulti = false;
- Mode CurrentMode = Unknown;
+ Mode StateMode = Unknown;
+ ProjectKind StateProjectKind = ProjectKind::Normal;
};
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index c898dd4..b90cf7e 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -450,17 +450,17 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const
if (prop == "PARENT_DIRECTORY") {
cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent();
if (parent.IsValid()) {
- return &parent.GetDirectory().GetCurrentSource();
+ return cmProp(parent.GetDirectory().GetCurrentSource());
}
- return &output;
+ return cmProp(output);
}
if (prop == kBINARY_DIR) {
output = this->GetCurrentBinary();
- return &output;
+ return cmProp(output);
}
if (prop == kSOURCE_DIR) {
output = this->GetCurrentSource();
- return &output;
+ return cmProp(output);
}
if (prop == kSUBDIRECTORIES) {
std::vector<std::string> child_dirs;
@@ -471,15 +471,15 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const
child_dirs.push_back(ci.GetDirectory().GetCurrentSource());
}
output = cmJoin(child_dirs, ";");
- return &output;
+ return cmProp(output);
}
if (prop == kBUILDSYSTEM_TARGETS) {
output = cmJoin(this->DirectoryState->NormalTargetNames, ";");
- return &output;
+ return cmProp(output);
}
if (prop == "IMPORTED_TARGETS"_s) {
output = cmJoin(this->DirectoryState->ImportedTargetNames, ";");
- return &output;
+ return cmProp(output);
}
if (prop == "LISTFILE_STACK") {
@@ -491,38 +491,38 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const
}
std::reverse(listFiles.begin(), listFiles.end());
output = cmJoin(listFiles, ";");
- return &output;
+ return cmProp(output);
}
if (prop == "CACHE_VARIABLES") {
output = cmJoin(this->Snapshot_.State->GetCacheEntryKeys(), ";");
- return &output;
+ return cmProp(output);
}
if (prop == "VARIABLES") {
std::vector<std::string> res = this->Snapshot_.ClosureKeys();
cm::append(res, this->Snapshot_.State->GetCacheEntryKeys());
std::sort(res.begin(), res.end());
output = cmJoin(res, ";");
- return &output;
+ return cmProp(output);
}
if (prop == "INCLUDE_DIRECTORIES") {
output = cmJoin(this->GetIncludeDirectoriesEntries(), ";");
- return &output;
+ return cmProp(output);
}
if (prop == "COMPILE_OPTIONS") {
output = cmJoin(this->GetCompileOptionsEntries(), ";");
- return &output;
+ return cmProp(output);
}
if (prop == "COMPILE_DEFINITIONS") {
output = cmJoin(this->GetCompileDefinitionsEntries(), ";");
- return &output;
+ return cmProp(output);
}
if (prop == "LINK_OPTIONS") {
output = cmJoin(this->GetLinkOptionsEntries(), ";");
- return &output;
+ return cmProp(output);
}
if (prop == "LINK_DIRECTORIES") {
output = cmJoin(this->GetLinkDirectoriesEntries(), ";");
- return &output;
+ return cmProp(output);
}
cmProp retVal = this->DirectoryState->Properties.GetPropertyValue(prop);
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index fbf47ef..6f13d89 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -201,8 +201,7 @@ bool cmStateSnapshot::HasDefinedPolicyCMP0011()
return !this->Position->Policies->IsEmpty();
}
-std::string const* cmStateSnapshot::GetDefinition(
- std::string const& name) const
+cmProp cmStateSnapshot::GetDefinition(std::string const& name) const
{
assert(this->Position->Vars.IsValid());
return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root);
diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h
index d06cba3..a5fe7e2 100644
--- a/Source/cmStateSnapshot.h
+++ b/Source/cmStateSnapshot.h
@@ -12,6 +12,7 @@
#include "cmLinkedTree.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmStateTypes.h"
class cmState;
@@ -23,7 +24,7 @@ public:
cmStateSnapshot(cmState* state = nullptr);
cmStateSnapshot(cmState* state, cmStateDetail::PositionType position);
- std::string const* GetDefinition(std::string const& name) const;
+ cmProp GetDefinition(std::string const& name) const;
bool IsInitialized(std::string const& name) const;
void SetDefinition(std::string const& name, cm::string_view value);
void RemoveDefinition(std::string const& name);
diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx
index 5bb6e7b..acb5e5b 100644
--- a/Source/cmStringAlgorithms.cxx
+++ b/Source/cmStringAlgorithms.cxx
@@ -227,76 +227,6 @@ bool cmIsInternallyOn(cm::string_view val)
(val[3] == 'N' || val[3] == 'n');
}
-bool cmIsNOTFOUND(cm::string_view val)
-{
- return (val == "NOTFOUND") || cmHasLiteralSuffix(val, "-NOTFOUND");
-}
-
-bool cmIsOn(cm::string_view val)
-{
- switch (val.size()) {
- case 1:
- return val[0] == '1' || val[0] == 'Y' || val[0] == 'y';
- case 2:
- return //
- (val[0] == 'O' || val[0] == 'o') && //
- (val[1] == 'N' || val[1] == 'n');
- case 3:
- return //
- (val[0] == 'Y' || val[0] == 'y') && //
- (val[1] == 'E' || val[1] == 'e') && //
- (val[2] == 'S' || val[2] == 's');
- case 4:
- return //
- (val[0] == 'T' || val[0] == 't') && //
- (val[1] == 'R' || val[1] == 'r') && //
- (val[2] == 'U' || val[2] == 'u') && //
- (val[3] == 'E' || val[3] == 'e');
- default:
- break;
- }
-
- return false;
-}
-
-bool cmIsOff(cm::string_view val)
-{
- switch (val.size()) {
- case 0:
- return true;
- case 1:
- return val[0] == '0' || val[0] == 'N' || val[0] == 'n';
- case 2:
- return //
- (val[0] == 'N' || val[0] == 'n') && //
- (val[1] == 'O' || val[1] == 'o');
- case 3:
- return //
- (val[0] == 'O' || val[0] == 'o') && //
- (val[1] == 'F' || val[1] == 'f') && //
- (val[2] == 'F' || val[2] == 'f');
- case 5:
- return //
- (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');
- case 6:
- return //
- (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');
- default:
- break;
- }
-
- return cmIsNOTFOUND(val);
-}
-
bool cmStrToLong(const char* str, long* value)
{
errno = 0;
diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h
index 6b458ec..531678a 100644
--- a/Source/cmStringAlgorithms.h
+++ b/Source/cmStringAlgorithms.h
@@ -14,25 +14,12 @@
#include <cm/string_view>
+#include "cmProperty.h"
#include "cmRange.h"
/** String range type. */
using cmStringRange = cmRange<std::vector<std::string>::const_iterator>;
-/** Check for non-empty string. */
-inline bool cmNonempty(const char* str)
-{
- return str && *str;
-}
-inline bool cmNonempty(cm::string_view str)
-{
- return !str.empty();
-}
-inline bool cmNonempty(std::string const* str)
-{
- return str && !str->empty();
-}
-
/** Returns length of a literal string. */
template <size_t N>
constexpr size_t cmStrLen(const char (&/*str*/)[N])
@@ -175,6 +162,10 @@ public:
cmAlphaNum(unsigned long long int val);
cmAlphaNum(float val);
cmAlphaNum(double val);
+ cmAlphaNum(cmProp value)
+ : View_(*value)
+ {
+ }
cm::string_view View() const { return this->View_; }
@@ -227,20 +218,44 @@ inline bool cmIsInternallyOn(const char* val)
return cmIsInternallyOn(cm::string_view(val));
}
+/** Check for non-empty Property/Variable value. */
+inline bool cmNonempty(cm::string_view val)
+{
+ return !cmProp::IsEmpty(val);
+}
+inline bool cmNonempty(const char* val)
+{
+ return !cmProp::IsEmpty(val);
+}
+inline bool cmNonempty(cmProp val)
+{
+ return !val.IsEmpty();
+}
+
/** Return true if value is NOTFOUND or ends in -NOTFOUND. */
-bool cmIsNOTFOUND(cm::string_view val);
+inline bool cmIsNOTFOUND(cm::string_view val)
+{
+ return cmProp::IsNOTFOUND(val);
+}
+inline bool cmIsNOTFOUND(cmProp val)
+{
+ return val.IsNOTFOUND();
+}
/**
* Does a string indicate a true or ON value? This is not the same as ifdef.
*/
-bool cmIsOn(cm::string_view val);
+inline bool cmIsOn(cm::string_view val)
+{
+ return cmProp::IsOn(val);
+}
inline bool cmIsOn(const char* val)
{
- return val && cmIsOn(cm::string_view(val));
+ return cmProp::IsOn(val);
}
-inline bool cmIsOn(std::string const* val)
+inline bool cmIsOn(cmProp val)
{
- return val && cmIsOn(*val);
+ return val.IsOn();
}
/**
@@ -250,14 +265,17 @@ inline bool cmIsOn(std::string const* val)
* IsON and IsOff both returning false. Note that the special path
* NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
*/
-bool cmIsOff(cm::string_view val);
+inline bool cmIsOff(cm::string_view val)
+{
+ return cmProp::IsOff(val);
+}
inline bool cmIsOff(const char* val)
{
- return !val || cmIsOff(cm::string_view(val));
+ return cmProp::IsOff(val);
}
-inline bool cmIsOff(std::string const* val)
+inline bool cmIsOff(cmProp val)
{
- return !val || cmIsOff(*val);
+ return val.IsOff();
}
/** Returns true if string @a str starts with the character @a prefix. */
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 10d2e50..54fe7a1 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -20,6 +20,7 @@
#include <cm3p/uv.h>
#include "cmDuration.h"
+#include "cmELF.h"
#include "cmMessageMetadata.h"
#include "cmProcessOutput.h"
#include "cmRange.h"
@@ -46,10 +47,6 @@
# include "cmCryptoHash.h"
#endif
-#if defined(CMake_USE_ELF_PARSER)
-# include "cmELF.h"
-#endif
-
#if defined(CMake_USE_MACH_PARSER)
# include "cmMachO.h"
#endif
@@ -1632,7 +1629,10 @@ bool cmSystemTools::CreateTar(const std::string& outFileName,
cmArchiveWrite a(fout, compress, format.empty() ? "paxr" : format,
compressionLevel);
- a.Open();
+ if (!a.Open()) {
+ cmSystemTools::Error(a.GetError());
+ return false;
+ }
a.SetMTime(mtime);
a.SetVerbose(verbose);
bool tarCreatedSuccessfully = true;
@@ -2446,14 +2446,12 @@ void cmSystemTools::MakefileColorEcho(int color, const char* message,
bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
std::string& soname)
{
-// For ELF shared libraries use a real parser to get the correct
-// soname.
-#if defined(CMake_USE_ELF_PARSER)
+ // For ELF shared libraries use a real parser to get the correct
+ // soname.
cmELF elf(fullPath.c_str());
if (elf) {
return elf.GetSOName(soname);
}
-#endif
// If the file is not a symlink we have no guess for its soname.
if (!cmSystemTools::FileIsSymlink(fullPath)) {
@@ -2491,7 +2489,6 @@ bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath,
return false;
}
-#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER)
std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have,
cm::string_view const& want)
{
@@ -2523,9 +2520,7 @@ std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have,
// The desired rpath was not found.
return std::string::npos;
}
-#endif
-#if defined(CMake_USE_ELF_PARSER)
namespace {
struct cmSystemToolsRPathInfo
{
@@ -2539,10 +2534,10 @@ using EmptyCallback = std::function<bool(std::string*, const cmELF&)>;
using AdjustCallback = std::function<bool(
cm::optional<std::string>&, const std::string&, const char*, std::string*)>;
-// FIXME: Dispatch if multiple formats are supported.
-bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback,
- const AdjustCallback& adjustCallback, std::string* emsg,
- bool* changed)
+cm::optional<bool> AdjustRPathELF(std::string const& file,
+ const EmptyCallback& emptyCallback,
+ const AdjustCallback& adjustCallback,
+ std::string* emsg, bool* changed)
{
if (changed) {
*changed = false;
@@ -2553,6 +2548,9 @@ bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback,
{
// Parse the ELF binary.
cmELF elf(file.c_str());
+ if (!elf) {
+ return cm::nullopt; // Not a valid ELF file.
+ }
// Get the RPATH and RUNPATH entries from it.
int se_count = 0;
@@ -2686,14 +2684,14 @@ std::function<bool(std::string*, const cmELF&)> MakeEmptyCallback(
}
return false;
};
-};
+}
}
-bool cmSystemTools::ChangeRPath(std::string const& file,
- std::string const& oldRPath,
- std::string const& newRPath,
- bool removeEnvironmentRPath, std::string* emsg,
- bool* changed)
+cm::optional<bool> ChangeRPathELF(std::string const& file,
+ std::string const& oldRPath,
+ std::string const& newRPath,
+ bool removeEnvironmentRPath,
+ std::string* emsg, bool* changed)
{
auto adjustCallback = [oldRPath, newRPath, removeEnvironmentRPath](
cm::optional<std::string>& outRPath,
@@ -2741,13 +2739,13 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
return true;
};
- return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg,
- changed);
+ return AdjustRPathELF(file, MakeEmptyCallback(newRPath), adjustCallback,
+ emsg, changed);
}
-bool cmSystemTools::SetRPath(std::string const& file,
- std::string const& newRPath, std::string* emsg,
- bool* changed)
+static cm::optional<bool> SetRPathELF(std::string const& file,
+ std::string const& newRPath,
+ std::string* emsg, bool* changed)
{
auto adjustCallback = [newRPath](cm::optional<std::string>& outRPath,
const std::string& inRPath,
@@ -2759,22 +2757,31 @@ bool cmSystemTools::SetRPath(std::string const& file,
return true;
};
- return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg,
- changed);
+ return AdjustRPathELF(file, MakeEmptyCallback(newRPath), adjustCallback,
+ emsg, changed);
}
-#elif defined(CMake_USE_XCOFF_PARSER)
-bool cmSystemTools::ChangeRPath(std::string const& file,
- std::string const& oldRPath,
- std::string const& newRPath,
- bool removeEnvironmentRPath, std::string* emsg,
- bool* changed)
+static cm::optional<bool> ChangeRPathXCOFF(std::string const& file,
+ std::string const& oldRPath,
+ std::string const& newRPath,
+ bool removeEnvironmentRPath,
+ std::string* emsg, bool* changed)
{
if (changed) {
*changed = false;
}
-
+#if !defined(CMake_USE_XCOFF_PARSER)
+ (void)file;
+ (void)oldRPath;
+ (void)newRPath;
+ (void)removeEnvironmentRPath;
+ (void)emsg;
+ return cm::nullopt;
+#else
bool chg = false;
cmXCOFF xcoff(file.c_str(), cmXCOFF::Mode::ReadWrite);
+ if (!xcoff) {
+ return cm::nullopt; // Not a valid XCOFF file
+ }
if (cm::optional<cm::string_view> maybeLibPath = xcoff.GetLibPath()) {
cm::string_view libPath = *maybeLibPath;
// Make sure the current rpath contains the old rpath.
@@ -2830,31 +2837,47 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
*changed = chg;
}
return true;
+#endif
}
-bool cmSystemTools::SetRPath(std::string const& /*file*/,
- std::string const& /*newRPath*/,
- std::string* /*emsg*/, bool* /*changed*/)
+static cm::optional<bool> SetRPathXCOFF(std::string const& /*file*/,
+ std::string const& /*newRPath*/,
+ std::string* /*emsg*/,
+ bool* /*changed*/)
{
- return false;
+ return cm::nullopt; // Not implemented.
}
-#else
-bool cmSystemTools::ChangeRPath(std::string const& /*file*/,
- std::string const& /*oldRPath*/,
- std::string const& /*newRPath*/,
- bool /*removeEnvironmentRPath*/,
- std::string* /*emsg*/, bool* /*changed*/)
+
+bool cmSystemTools::ChangeRPath(std::string const& file,
+ std::string const& oldRPath,
+ std::string const& newRPath,
+ bool removeEnvironmentRPath, std::string* emsg,
+ bool* changed)
{
+ if (cm::optional<bool> result = ChangeRPathELF(
+ file, oldRPath, newRPath, removeEnvironmentRPath, emsg, changed)) {
+ return result.value();
+ }
+ if (cm::optional<bool> result = ChangeRPathXCOFF(
+ file, oldRPath, newRPath, removeEnvironmentRPath, emsg, changed)) {
+ return result.value();
+ }
return false;
}
-bool cmSystemTools::SetRPath(std::string const& /*file*/,
- std::string const& /*newRPath*/,
- std::string* /*emsg*/, bool* /*changed*/)
+bool cmSystemTools::SetRPath(std::string const& file,
+ std::string const& newRPath, std::string* emsg,
+ bool* changed)
{
+ if (cm::optional<bool> result = SetRPathELF(file, newRPath, emsg, changed)) {
+ return result.value();
+ }
+ if (cm::optional<bool> result =
+ SetRPathXCOFF(file, newRPath, emsg, changed)) {
+ return result.value();
+ }
return false;
}
-#endif
bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
const char* lhss, const char* rhss)
@@ -2989,10 +3012,8 @@ int cmSystemTools::strverscmp(std::string const& lhs, std::string const& rhs)
return cm_strverscmp(lhs.c_str(), rhs.c_str());
}
-// FIXME: Dispatch if multiple formats are supported.
-#if defined(CMake_USE_ELF_PARSER)
-bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
- bool* removed)
+static cm::optional<bool> RemoveRPathELF(std::string const& file,
+ std::string* emsg, bool* removed)
{
if (removed) {
*removed = false;
@@ -3005,6 +3026,9 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
{
// Parse the ELF binary.
cmELF elf(file.c_str());
+ if (!elf) {
+ return cm::nullopt; // Not a valid ELF file.
+ }
// Get the RPATH and RUNPATH entries from it and sort them by index
// in the dynamic section header.
@@ -3054,8 +3078,7 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
entriesErased++;
continue;
}
- if (cmELF::TagMipsRldMapRel != 0 &&
- it->first == cmELF::TagMipsRldMapRel) {
+ if (it->first == cmELF::TagMipsRldMapRel && elf.IsMIPS()) {
// Background: debuggers need to know the "linker map" which contains
// the addresses each dynamic object is loaded at. Most arches use
// the DT_DEBUG tag which the dynamic linker writes to (directly) and
@@ -3131,15 +3154,22 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
}
return true;
}
-#elif defined(CMake_USE_XCOFF_PARSER)
-bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
- bool* removed)
+
+static cm::optional<bool> RemoveRPathXCOFF(std::string const& file,
+ std::string* emsg, bool* removed)
{
if (removed) {
*removed = false;
}
-
+#if !defined(CMake_USE_XCOFF_PARSER)
+ (void)file;
+ (void)emsg;
+ return cm::nullopt; // Cannot handle XCOFF files.
+#else
cmXCOFF xcoff(file.c_str(), cmXCOFF::Mode::ReadWrite);
+ if (!xcoff) {
+ return cm::nullopt; // Not a valid XCOFF file.
+ }
bool rm = xcoff.RemoveLibPath();
if (!xcoff) {
if (emsg) {
@@ -3152,55 +3182,60 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
*removed = rm;
}
return true;
+#endif
}
-#else
-bool cmSystemTools::RemoveRPath(std::string const& /*file*/,
- std::string* /*emsg*/, bool* /*removed*/)
+bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
+ bool* removed)
{
+ if (cm::optional<bool> result = RemoveRPathELF(file, emsg, removed)) {
+ return result.value();
+ }
+ if (cm::optional<bool> result = RemoveRPathXCOFF(file, emsg, removed)) {
+ return result.value();
+ }
return false;
}
-#endif
-// FIXME: Dispatch if multiple formats are supported.
bool cmSystemTools::CheckRPath(std::string const& file,
std::string const& newRPath)
{
-#if defined(CMake_USE_ELF_PARSER)
// Parse the ELF binary.
cmELF elf(file.c_str());
-
- // Get the RPATH or RUNPATH entry from it.
- cmELF::StringEntry const* se = elf.GetRPath();
- if (!se) {
- se = elf.GetRunPath();
- }
-
- // Make sure the current rpath contains the new rpath.
- if (newRPath.empty()) {
+ if (elf) {
+ // Get the RPATH or RUNPATH entry from it.
+ cmELF::StringEntry const* se = elf.GetRPath();
if (!se) {
- return true;
+ se = elf.GetRunPath();
}
- } else {
- if (se &&
- cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos) {
- return true;
+
+ // Make sure the current rpath contains the new rpath.
+ if (newRPath.empty()) {
+ if (!se) {
+ return true;
+ }
+ } else {
+ if (se &&
+ cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos) {
+ return true;
+ }
}
+ return false;
}
- return false;
-#elif defined(CMake_USE_XCOFF_PARSER)
+#if defined(CMake_USE_XCOFF_PARSER)
// Parse the XCOFF binary.
cmXCOFF xcoff(file.c_str());
- if (cm::optional<cm::string_view> libPath = xcoff.GetLibPath()) {
- if (cmSystemToolsFindRPath(*libPath, newRPath) != std::string::npos) {
- return true;
+ if (xcoff) {
+ if (cm::optional<cm::string_view> libPath = xcoff.GetLibPath()) {
+ if (cmSystemToolsFindRPath(*libPath, newRPath) != std::string::npos) {
+ return true;
+ }
}
+ return false;
}
- return false;
-#else
+#endif
(void)file;
(void)newRPath;
return false;
-#endif
}
bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir)
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 7622700..656afc6 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -157,7 +157,7 @@ cmProp cmTargetPropertyComputer::GetSources<cmTarget>(
}
static std::string srcs;
srcs = ss.str();
- return &srcs;
+ return cmProp(srcs);
}
class cmTargetInternals
@@ -189,6 +189,7 @@ public:
std::map<std::string, BTs<std::string>> LanguageStandardProperties;
std::vector<std::string> IncludeDirectoriesEntries;
std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces;
+ std::vector<std::string> InstallIncludeDirectoriesEntries;
std::vector<std::string> CompileOptionsEntries;
std::vector<cmListFileBacktrace> CompileOptionsBacktraces;
std::vector<std::string> CompileFeaturesEntries;
@@ -1075,6 +1076,17 @@ std::set<std::string> const& cmTarget::GetSystemIncludeDirectories() const
return this->impl->SystemIncludeDirectories;
}
+void cmTarget::AddInstallIncludeDirectories(cmStringRange const& incs)
+{
+ std::copy(incs.begin(), incs.end(),
+ std::back_inserter(this->impl->InstallIncludeDirectoriesEntries));
+}
+
+cmStringRange cmTarget::GetInstallIncludeDirectoriesEntries() const
+{
+ return cmMakeRange(this->impl->InstallIncludeDirectoriesEntries);
+}
+
cmStringRange cmTarget::GetIncludeDirectoriesEntries() const
{
return cmMakeRange(this->impl->IncludeDirectoriesEntries);
@@ -1737,7 +1749,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
if (propertyIter == this->impl->LanguageStandardProperties.end()) {
return nullptr;
}
- return &(propertyIter->second.Value);
+ return cmProp(propertyIter->second.Value);
}
if (prop == propLINK_LIBRARIES) {
if (this->impl->LinkImplementationPropertyEntries.empty()) {
@@ -1746,11 +1758,11 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->LinkImplementationPropertyEntries, ";");
- return &output;
+ return cmProp(output);
}
// the type property returns what type the target is
if (prop == propTYPE) {
- return &cmState::GetTargetTypeName(this->GetType());
+ return cmProp(cmState::GetTargetTypeName(this->GetType()));
}
if (prop == propINCLUDE_DIRECTORIES) {
if (this->impl->IncludeDirectoriesEntries.empty()) {
@@ -1759,7 +1771,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->IncludeDirectoriesEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propCOMPILE_FEATURES) {
if (this->impl->CompileFeaturesEntries.empty()) {
@@ -1768,7 +1780,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->CompileFeaturesEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propCOMPILE_OPTIONS) {
if (this->impl->CompileOptionsEntries.empty()) {
@@ -1777,7 +1789,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->CompileOptionsEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propCOMPILE_DEFINITIONS) {
if (this->impl->CompileDefinitionsEntries.empty()) {
@@ -1786,7 +1798,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->CompileDefinitionsEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propLINK_OPTIONS) {
if (this->impl->LinkOptionsEntries.empty()) {
@@ -1795,7 +1807,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->LinkOptionsEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propLINK_DIRECTORIES) {
if (this->impl->LinkDirectoriesEntries.empty()) {
@@ -1805,7 +1817,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->LinkDirectoriesEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
if (this->impl->Utilities.empty()) {
@@ -1822,7 +1834,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
return item.Value.first;
});
output = cmJoin(utilities, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propPRECOMPILE_HEADERS) {
if (this->impl->PrecompileHeadersEntries.empty()) {
@@ -1831,26 +1843,27 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->PrecompileHeadersEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propIMPORTED) {
- return this->IsImported() ? &propTRUE : &propFALSE;
+ return this->IsImported() ? cmProp(propTRUE) : cmProp(propFALSE);
}
if (prop == propIMPORTED_GLOBAL) {
- return this->IsImportedGloballyVisible() ? &propTRUE : &propFALSE;
+ return this->IsImportedGloballyVisible() ? cmProp(propTRUE)
+ : cmProp(propFALSE);
}
if (prop == propNAME) {
- return &this->GetName();
+ return cmProp(this->GetName());
}
if (prop == propBINARY_DIR) {
- return &this->impl->Makefile->GetStateSnapshot()
- .GetDirectory()
- .GetCurrentBinary();
+ return cmProp(this->impl->Makefile->GetStateSnapshot()
+ .GetDirectory()
+ .GetCurrentBinary());
}
if (prop == propSOURCE_DIR) {
- return &this->impl->Makefile->GetStateSnapshot()
- .GetDirectory()
- .GetCurrentSource();
+ return cmProp(this->impl->Makefile->GetStateSnapshot()
+ .GetDirectory()
+ .GetCurrentSource());
}
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 30d9f5d..29130c7 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -237,6 +237,9 @@ public:
void AddSystemIncludeDirectories(std::set<std::string> const& incs);
std::set<std::string> const& GetSystemIncludeDirectories() const;
+ void AddInstallIncludeDirectories(cmStringRange const& incs);
+ cmStringRange GetInstallIncludeDirectoriesEntries() const;
+
BTs<std::string> const* GetLanguageStandardProperty(
const std::string& propertyName) const;
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
index 1e38d84..19fc931 100644
--- a/Source/cmTargetExport.h
+++ b/Source/cmTargetExport.h
@@ -29,7 +29,6 @@ public:
cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
- std::string InterfaceIncludeDirectories;
///@}
bool NamelinkOnly = false;
diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
index f2be318..a749b53 100644
--- a/Source/cmTargetPropertyComputer.h
+++ b/Source/cmTargetPropertyComputer.h
@@ -65,7 +65,7 @@ private:
context)) {
return nullptr;
}
- return &ComputeLocationForBuild(tgt);
+ return cmProp(ComputeLocationForBuild(tgt));
}
// Support "LOCATION_<CONFIG>".
@@ -76,7 +76,7 @@ private:
return nullptr;
}
std::string configName = prop.substr(9);
- return &ComputeLocation(tgt, configName);
+ return cmProp(ComputeLocation(tgt, configName));
}
// Support "<CONFIG>_LOCATION".
@@ -89,7 +89,7 @@ private:
context)) {
return nullptr;
}
- return &ComputeLocation(tgt, configName);
+ return cmProp(ComputeLocation(tgt, configName));
}
}
}
diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx
index a26bef3..5bc10c2 100644
--- a/Source/cmTest.cxx
+++ b/Source/cmTest.cxx
@@ -32,7 +32,7 @@ void cmTest::SetCommand(std::vector<std::string> const& command)
this->Command = command;
}
-const char* cmTest::GetProperty(const std::string& prop) const
+cmProp cmTest::GetProperty(const std::string& prop) const
{
cmProp retVal = this->Properties.GetPropertyValue(prop);
if (!retVal) {
@@ -40,12 +40,12 @@ const char* cmTest::GetProperty(const std::string& prop) const
this->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TEST);
if (chain) {
if (cmProp p = this->Makefile->GetProperty(prop, chain)) {
- return p->c_str();
+ return p;
}
}
return nullptr;
}
- return retVal->c_str();
+ return retVal;
}
bool cmTest::GetPropertyAsBool(const std::string& prop) const
diff --git a/Source/cmTest.h b/Source/cmTest.h
index f33b7e2..63e5e87 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -8,6 +8,7 @@
#include <vector>
#include "cmListFileCache.h"
+#include "cmProperty.h"
#include "cmPropertyMap.h"
class cmMakefile;
@@ -36,7 +37,7 @@ public:
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
- const char* GetProperty(const std::string& prop) const;
+ cmProp GetProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
cmPropertyMap& GetProperties() { return this->Properties; }
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 056696d..cfea4cf 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -18,6 +18,10 @@
#include <cstring>
#include <sstream>
+#ifdef __MINGW32__
+# include <libloaderapi.h>
+#endif
+
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -159,6 +163,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
case 'M':
case 'S':
case 'U':
+ case 'V':
case 'w':
case 'y':
case 'Y':
@@ -187,6 +192,24 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
}
}
+#ifdef __MINGW32__
+ /* See a bug in MinGW: https://sourceforge.net/p/mingw-w64/bugs/793/. A work
+ * around is to try to use strftime() from ucrtbase.dll. */
+ using T = size_t(WINAPI*)(char*, size_t, const char*, const struct tm*);
+ auto loadStrftime = [] {
+ auto handle =
+ LoadLibraryExA("ucrtbase.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ if (handle) {
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wcast-function-type"
+ return reinterpret_cast<T>(GetProcAddress(handle, "strftime"));
+# pragma GCC diagnostic pop
+ }
+ return strftime;
+ };
+ static T strftime = loadStrftime();
+#endif
+
char buffer[16];
size_t size =
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index bda2f91..03d1bbb 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -490,10 +490,7 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element("Platform", this->Platform);
cmProp projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
- if (!projLabel) {
- projLabel = &this->Name;
- }
- e1.Element("ProjectName", *projLabel);
+ e1.Element("ProjectName", projLabel ? projLabel : this->Name);
{
cmProp targetFramework =
this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK");
@@ -3543,8 +3540,6 @@ void cmVisualStudio10TargetGenerator::WriteNasmOptions(
}
Elem e2(e1, "NASM");
- std::vector<std::string> includes =
- this->GetIncludes(configName, "ASM_NASM");
OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2);
nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM");
nasmOptions.OutputFlagMap();
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index 327c1c7..b8297ce 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -16,13 +16,14 @@
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmOutputConverter.h"
#include "cmSystemTools.h"
#include "cmake.h"
class cmWhileFunctionBlocker : public cmFunctionBlocker
{
public:
- cmWhileFunctionBlocker(cmMakefile* mf);
+ cmWhileFunctionBlocker(cmMakefile* mf, std::vector<cmListFileArgument> args);
~cmWhileFunctionBlocker() override;
cm::string_view StartCommandName() const override { return "while"_s; }
@@ -34,14 +35,15 @@ public:
bool Replay(std::vector<cmListFileFunction> functions,
cmExecutionStatus& inStatus) override;
- std::vector<cmListFileArgument> Args;
-
private:
cmMakefile* Makefile;
+ std::vector<cmListFileArgument> Args;
};
-cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf)
- : Makefile(mf)
+cmWhileFunctionBlocker::cmWhileFunctionBlocker(
+ cmMakefile* const mf, std::vector<cmListFileArgument> args)
+ : Makefile{ mf }
+ , Args{ std::move(args) }
{
this->Makefile->PushLoopBlock();
}
@@ -60,39 +62,29 @@ bool cmWhileFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
cmExecutionStatus& inStatus)
{
- cmMakefile& mf = inStatus.GetMakefile();
- std::string errorString;
-
- std::vector<cmExpandedCommandArgument> expandedArguments;
- mf.ExpandArguments(this->Args, expandedArguments);
- MessageType messageType;
+ auto& mf = inStatus.GetMakefile();
cmListFileBacktrace whileBT =
mf.GetBacktrace().Push(this->GetStartingContext());
- cmConditionEvaluator conditionEvaluator(mf, whileBT);
-
- bool isTrue =
- conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
-
- while (isTrue) {
- if (!errorString.empty()) {
- std::string err = "had incorrect arguments: ";
- for (cmListFileArgument const& arg : this->Args) {
- err += (arg.Delim ? "\"" : "");
- err += arg.Value;
- err += (arg.Delim ? "\"" : "");
- err += " ";
- }
- err += "(";
- err += errorString;
- err += ").";
- mf.GetCMakeInstance()->IssueMessage(messageType, err, whileBT);
- if (messageType == MessageType::FATAL_ERROR) {
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
- }
+ std::vector<cmExpandedCommandArgument> expandedArguments;
+ // At least same size expected for `expandedArguments` as `Args`
+ expandedArguments.reserve(this->Args.size());
+
+ auto expandArgs = [&mf](std::vector<cmListFileArgument> const& args,
+ std::vector<cmExpandedCommandArgument>& out)
+ -> std::vector<cmExpandedCommandArgument>& {
+ out.clear();
+ mf.ExpandArguments(args, out);
+ return out;
+ };
+
+ std::string errorString;
+ MessageType messageType;
+
+ for (cmConditionEvaluator conditionEvaluator(mf, whileBT);
+ conditionEvaluator.IsTrue(expandArgs(this->Args, expandedArguments),
+ errorString, messageType);) {
// Invoke all the functions that were collected in the block.
for (cmListFileFunction const& fn : functions) {
cmExecutionStatus status(mf);
@@ -111,11 +103,22 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
return true;
}
}
- expandedArguments.clear();
- mf.ExpandArguments(this->Args, expandedArguments);
- isTrue =
- conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
}
+
+ if (!errorString.empty()) {
+ std::string err = "had incorrect arguments:\n ";
+ for (auto const& i : expandedArguments) {
+ err += " ";
+ err += cmOutputConverter::EscapeForCMake(i.GetValue());
+ }
+ err += "\n";
+ err += errorString;
+ mf.GetCMakeInstance()->IssueMessage(messageType, err, whileBT);
+ if (messageType == MessageType::FATAL_ERROR) {
+ cmSystemTools::SetFatalErrorOccured();
+ }
+ }
+
return true;
}
@@ -128,11 +131,9 @@ bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
}
// create a function blocker
- {
- cmMakefile& makefile = status.GetMakefile();
- auto fb = cm::make_unique<cmWhileFunctionBlocker>(&makefile);
- fb->Args = args;
- makefile.AddFunctionBlocker(std::move(fb));
- }
+ auto& makefile = status.GetMakefile();
+ makefile.AddFunctionBlocker(
+ cm::make_unique<cmWhileFunctionBlocker>(&makefile, args));
+
return true;
}
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 73f5ad5..7f8f654 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -114,7 +114,9 @@
# include "cmExtraSublimeTextGenerator.h"
#endif
-#if defined(__linux__) || defined(_WIN32)
+// NOTE: the __linux__ macro is predefined on Android host too, but
+// main CMakeLists.txt filters out this generator by host name.
+#if (defined(__linux__) && !defined(__ANDROID__)) || defined(_WIN32)
# include "cmGlobalGhsMultiGenerator.h"
#endif
@@ -156,17 +158,16 @@ static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
}
#endif
-cmake::cmake(Role role, cmState::Mode mode)
+cmake::cmake(Role role, cmState::Mode mode, cmState::ProjectKind projectKind)
: CMakeWorkingDirectory(cmSystemTools::GetCurrentWorkingDirectory())
, FileTimeCache(cm::make_unique<cmFileTimeCache>())
#ifndef CMAKE_BOOTSTRAP
, VariableWatch(cm::make_unique<cmVariableWatch>())
#endif
- , State(cm::make_unique<cmState>())
+ , State(cm::make_unique<cmState>(mode, projectKind))
, Messenger(cm::make_unique<cmMessenger>())
{
this->TraceFile.close();
- this->State->SetMode(mode);
this->CurrentSnapshot = this->State->CreateBaseSnapshot();
#ifdef __APPLE__
@@ -1843,7 +1844,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
std::vector<std::string> argsSplit = cmExpandedList(var, true);
// erase the property to avoid infinite recursion
this->State->SetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
- if (this->State->GetIsInTryCompile()) {
+ if (this->GetIsInTryCompile()) {
return 0;
}
std::vector<SaveCacheEntry> saved;
@@ -2111,7 +2112,7 @@ int cmake::ActualConfigure()
// reset any system configuration information, except for when we are
// InTryCompile. With TryCompile the system info is taken from the parent's
// info to save time
- if (!this->State->GetIsInTryCompile()) {
+ if (!this->GetIsInTryCompile()) {
this->GlobalGenerator->ClearEnabledLanguages();
this->TruncateOutputLog("CMakeOutput.log");
@@ -2529,7 +2530,7 @@ void cmake::AddDefaultGenerators()
this->Generators.push_back(cmGlobalMinGWMakefileGenerator::NewFactory());
#endif
#if !defined(CMAKE_BOOTSTRAP)
-# if defined(__linux__) || defined(_WIN32)
+# if (defined(__linux__) && !defined(__ANDROID__)) || defined(_WIN32)
this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory());
# endif
this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory());
@@ -2622,19 +2623,14 @@ void cmake::SetProgressCallback(ProgressCallbackType f)
void cmake::UpdateProgress(const std::string& msg, float prog)
{
- if (this->ProgressCallback && !this->State->GetIsInTryCompile()) {
+ if (this->ProgressCallback && !this->GetIsInTryCompile()) {
this->ProgressCallback(msg, prog);
}
}
bool cmake::GetIsInTryCompile() const
{
- return this->State->GetIsInTryCompile();
-}
-
-void cmake::SetIsInTryCompile(bool b)
-{
- this->State->SetIsInTryCompile(b);
+ return this->State->GetProjectKind() == cmState::ProjectKind::TryCompile;
}
void cmake::AppendGlobalGeneratorsDocumentation(
diff --git a/Source/cmake.h b/Source/cmake.h
index 5a2a88f..12cce7e 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -168,7 +168,8 @@ public:
static const int DEFAULT_BUILD_PARALLEL_LEVEL = 0;
/// Default constructor
- cmake(Role role, cmState::Mode mode);
+ cmake(Role role, cmState::Mode mode,
+ cmState::ProjectKind projectKind = cmState::ProjectKind::Normal);
/// Destructor
~cmake();
@@ -356,7 +357,6 @@ public:
//! Is this cmake running as a result of a TRY_COMPILE command
bool GetIsInTryCompile() const;
- void SetIsInTryCompile(bool b);
#ifndef CMAKE_BOOTSTRAP
void SetWarningFromPreset(const std::string& name,
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 1f4c0b8..1e0f497 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -385,18 +385,15 @@ int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
return ret;
}
-int HandleLWYU(const std::string& runCmd, const std::string& /* sourceFile */,
+int HandleLWYU(const std::string& runCmd, const std::string& sourceFile,
const std::vector<std::string>&)
{
// Construct the ldd -r -u (link what you use lwyu) command line
// ldd -u -r lwuy target
- std::vector<std::string> lwyu_cmd;
- lwyu_cmd.emplace_back("ldd");
- lwyu_cmd.emplace_back("-u");
- lwyu_cmd.emplace_back("-r");
- lwyu_cmd.push_back(runCmd);
+ std::vector<std::string> lwyu_cmd = cmExpandedList(runCmd, true);
+ lwyu_cmd.push_back(sourceFile);
- // Run the ldd -u -r command line.
+ // Run the lwyu check command line, currently ldd is expected.
// Capture its stdout and hide its stderr.
// Ignore its return code because the tool always returns non-zero
// if there are any warnings, but we just want to warn.