summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx43
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.h7
-rw-r--r--Source/CPack/WiX/cmWIXSourceWriter.h4
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx28
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx448
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.h33
-rw-r--r--Source/CPack/cmCPackExternalGenerator.cxx10
-rw-r--r--Source/CPack/cmCPackGenerator.cxx94
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx2
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx10
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx25
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx25
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx21
-rw-r--r--Source/CTest/cmCTestGenericHandler.cxx2
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx21
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx145
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.h3
-rw-r--r--Source/CTest/cmCTestReadCustomFilesCommand.cxx2
-rw-r--r--Source/CTest/cmCTestRunTest.cxx8
-rw-r--r--Source/CTest/cmCTestStartCommand.cxx5
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx12
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx2
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx11
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx12
-rw-r--r--Source/CTest/cmCTestTestHandler.h5
-rw-r--r--Source/CTest/cmCTestUpdateCommand.cxx5
-rw-r--r--Source/CTest/cmProcess.cxx6
-rw-r--r--Source/Checks/cm_cxx_features.cmake5
-rw-r--r--Source/Checks/cm_cxx_filesystem.cxx10
-rw-r--r--Source/CursesDialog/ccmake.cxx16
-rw-r--r--Source/CursesDialog/form/CMakeLists.txt8
-rw-r--r--Source/CursesDialog/form/frm_driver.c4
-rw-r--r--Source/QtDialog/CMakeLists.txt179
-rw-r--r--Source/QtDialog/CMakeSetup.cxx8
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx6
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h1
-rw-r--r--Source/QtDialog/QCMake.cxx13
-rw-r--r--Source/QtDialog/QCMake.h4
-rw-r--r--Source/QtDialog/QCMakeCacheView.cxx33
-rw-r--r--Source/QtDialog/QCMakeCacheView.h1
-rw-r--r--Source/QtDialog/QCMakeWidgets.cxx18
-rw-r--r--Source/cmAddLibraryCommand.cxx26
-rw-r--r--Source/cmAuxSourceDirectoryCommand.cxx2
-rw-r--r--Source/cmCMakeLanguageCommand.h2
-rw-r--r--Source/cmCTest.cxx72
-rw-r--r--Source/cmCTest.h26
-rw-r--r--Source/cmCacheManager.cxx5
-rw-r--r--Source/cmCommonTargetGenerator.cxx2
-rw-r--r--Source/cmComputeComponentGraph.cxx8
-rw-r--r--Source/cmComputeComponentGraph.h3
-rw-r--r--Source/cmComputeLinkDepends.cxx5
-rw-r--r--Source/cmComputeLinkInformation.cxx72
-rw-r--r--Source/cmComputeLinkInformation.h6
-rw-r--r--Source/cmComputeTargetDepends.cxx189
-rw-r--r--Source/cmComputeTargetDepends.h19
-rw-r--r--Source/cmConfigure.cmake.h.in1
-rw-r--r--Source/cmConfigureFileCommand.cxx6
-rw-r--r--Source/cmCoreTryCompile.cxx619
-rw-r--r--Source/cmCoreTryCompile.h4
-rw-r--r--Source/cmCreateTestSourceList.cxx2
-rw-r--r--Source/cmDefinitions.cxx14
-rw-r--r--Source/cmDefinitions.h4
-rw-r--r--Source/cmDependsFortran.cxx2
-rw-r--r--Source/cmExportCommand.cxx8
-rw-r--r--Source/cmExportFileGenerator.cxx5
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx46
-rw-r--r--Source/cmExtraCodeLiteGenerator.cxx3
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx26
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx7
-rw-r--r--Source/cmFileAPI.cxx2
-rw-r--r--Source/cmFileAPICodemodel.cxx81
-rw-r--r--Source/cmFileCommand.cxx65
-rw-r--r--Source/cmFileCopier.cxx2
-rw-r--r--Source/cmFindCommon.cxx8
-rw-r--r--Source/cmFindPackageCommand.cxx10
-rw-r--r--Source/cmFindProgramCommand.cxx61
-rw-r--r--Source/cmGeneratedFileStream.cxx30
-rw-r--r--Source/cmGeneratedFileStream.h19
-rw-r--r--Source/cmGeneratorExpression.cxx6
-rw-r--r--Source/cmGeneratorExpression.h2
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx8
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h1
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.cxx8
-rw-r--r--Source/cmGeneratorExpressionNode.cxx62
-rw-r--r--Source/cmGeneratorTarget.cxx367
-rw-r--r--Source/cmGeneratorTarget.h32
-rw-r--r--Source/cmGetFilenameComponentCommand.cxx2
-rw-r--r--Source/cmGetPropertyCommand.cxx10
-rw-r--r--Source/cmGetTargetPropertyCommand.cxx10
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx7
-rw-r--r--Source/cmGhsMultiTargetGenerator.h2
-rw-r--r--Source/cmGlobalCommonGenerator.cxx39
-rw-r--r--Source/cmGlobalCommonGenerator.h4
-rw-r--r--Source/cmGlobalGenerator.cxx147
-rw-r--r--Source/cmGlobalGenerator.h3
-rw-r--r--Source/cmGlobalGeneratorFactory.h2
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx14
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx78
-rw-r--r--Source/cmGlobalNinjaGenerator.h15
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx41
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx103
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h22
-rw-r--r--Source/cmGlobalVisualStudio14Generator.cxx6
-rw-r--r--Source/cmGlobalVisualStudio14Generator.h6
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx4
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx15
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx4
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx6
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx38
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.h2
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx425
-rw-r--r--Source/cmGlobalXCodeGenerator.h14
-rw-r--r--Source/cmGraphVizWriter.cxx53
-rw-r--r--Source/cmGraphVizWriter.h11
-rw-r--r--Source/cmInstallCommand.cxx8
-rw-r--r--Source/cmJsonObjects.cxx6
-rw-r--r--Source/cmLinkItemGraphVisitor.cxx7
-rw-r--r--Source/cmLinkLineDeviceComputer.cxx25
-rw-r--r--Source/cmListFileCache.h26
-rw-r--r--Source/cmLocalCommonGenerator.cxx6
-rw-r--r--Source/cmLocalGenerator.cxx305
-rw-r--r--Source/cmLocalGenerator.h7
-rw-r--r--Source/cmLocalGhsMultiGenerator.cxx3
-rw-r--r--Source/cmLocalNinjaGenerator.cxx45
-rw-r--r--Source/cmLocalNinjaGenerator.h8
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx10
-rw-r--r--Source/cmLocalVisualStudio10Generator.cxx2
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx23
-rw-r--r--Source/cmMakefile.cxx794
-rw-r--r--Source/cmMakefile.h72
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx4
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx4
-rw-r--r--Source/cmMakefileTargetGenerator.cxx35
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx13
-rw-r--r--Source/cmNinjaTargetGenerator.cxx36
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx3
-rw-r--r--Source/cmPolicies.cxx30
-rw-r--r--Source/cmPolicies.h20
-rw-r--r--Source/cmProjectCommand.cxx2
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.cxx4
-rw-r--r--Source/cmQtAutoGenInitializer.cxx21
-rw-r--r--Source/cmRulePlaceholderExpander.cxx2
-rw-r--r--Source/cmSearchPath.cxx2
-rw-r--r--Source/cmServerProtocol.cxx5
-rw-r--r--Source/cmServerProtocol.h1
-rw-r--r--Source/cmSourceFile.cxx34
-rw-r--r--Source/cmSourceFileLocation.cxx4
-rw-r--r--Source/cmStandardLevelResolver.cxx538
-rw-r--r--Source/cmStandardLevelResolver.h59
-rw-r--r--Source/cmState.cxx3
-rw-r--r--Source/cmStateDirectory.cxx3
-rw-r--r--Source/cmStateSnapshot.cxx9
-rw-r--r--Source/cmStateSnapshot.h1
-rw-r--r--Source/cmString.cxx2
-rw-r--r--Source/cmString.hxx2
-rw-r--r--Source/cmStringAlgorithms.h32
-rw-r--r--Source/cmSystemTools.cxx2
-rw-r--r--Source/cmTarget.cxx235
-rw-r--r--Source/cmTarget.h11
-rw-r--r--Source/cmTargetCompileFeaturesCommand.cxx4
-rw-r--r--Source/cmTargetPropCommandBase.cxx2
-rw-r--r--Source/cmTargetPropertyComputer.cxx69
-rw-r--r--Source/cmTargetPropertyComputer.h6
-rw-r--r--Source/cmTestGenerator.cxx123
-rw-r--r--Source/cmTimestamp.cxx2
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx95
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h2
-rw-r--r--Source/cmXCodeScheme.cxx5
-rw-r--r--Source/cmake.cxx77
-rw-r--r--Source/cmake.h42
-rw-r--r--Source/cmakemain.cxx142
-rw-r--r--Source/cmcmd.cxx62
-rw-r--r--Source/kwsys/CTestConfig.cmake4
-rw-r--r--Source/kwsys/Glob.cxx2
-rw-r--r--Source/kwsys/Glob.hxx.in4
-rw-r--r--Source/kwsys/ProcessUNIX.c6
-rw-r--r--Source/kwsys/SystemInformation.cxx29
-rw-r--r--Source/kwsys/SystemTools.cxx46
-rw-r--r--Source/kwsys/SystemTools.hxx.in9
-rw-r--r--Source/kwsys/testProcess.c11
-rw-r--r--Source/kwsys/testSystemTools.cxx22
183 files changed, 4372 insertions, 3186 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 1b6bb00..ee8767f 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -412,6 +412,8 @@ set(SRCS
cmSourceFileLocationKind.h
cmSourceGroup.cxx
cmSourceGroup.h
+ cmStandardLevelResolver.cxx
+ cmStandardLevelResolver.h
cmState.cxx
cmState.h
cmStateDirectory.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index cdadbe7..9b2b4ac 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 18)
-set(CMake_VERSION_PATCH 1)
+set(CMake_VERSION_PATCH 20200820)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 72af10b..8b3644f 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -221,6 +221,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
this->LightExtensions.insert("WixUIExtension");
CollectExtensions("CPACK_WIX_EXTENSIONS", this->LightExtensions);
CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions);
+ CollectXmlNamespaces("CPACK_WIX_CUSTOM_XMLNS", this->CustomXmlNamespaces);
const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE");
if (patchFilePath) {
@@ -322,6 +323,7 @@ void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
cmWIXSourceWriter includeFile(this->Logger, includeFilename,
this->ComponentGuidType,
cmWIXSourceWriter::INCLUDE_ELEMENT_ROOT);
+ InjectXmlNamespaces(includeFile);
CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_GUID");
CopyDefinition(includeFile, "CPACK_WIX_UPGRADE_GUID");
@@ -345,6 +347,7 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile()
cmWIXSourceWriter includeFile(this->Logger, includeFilename,
this->ComponentGuidType,
cmWIXSourceWriter::INCLUDE_ELEMENT_ROOT);
+ InjectXmlNamespaces(includeFile);
std::string prefix = "CPACK_WIX_PROPERTY_";
std::vector<std::string> options = GetOptions();
@@ -393,6 +396,7 @@ void cmCPackWIXGenerator::CreateWiXProductFragmentIncludeFile()
cmWIXSourceWriter includeFile(this->Logger, includeFilename,
this->ComponentGuidType,
cmWIXSourceWriter::INCLUDE_ELEMENT_ROOT);
+ InjectXmlNamespaces(includeFile);
this->Patch->ApplyFragment("#PRODUCT", includeFile);
}
@@ -432,6 +436,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
cmWIXDirectoriesSourceWriter directoryDefinitions(
this->Logger, directoryDefinitionsFilename, this->ComponentGuidType);
+ InjectXmlNamespaces(directoryDefinitions);
directoryDefinitions.BeginElement("Fragment");
std::string installRoot;
@@ -453,6 +458,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
cmWIXFilesSourceWriter fileDefinitions(this->Logger, fileDefinitionsFilename,
this->ComponentGuidType);
+ InjectXmlNamespaces(fileDefinitions);
fileDefinitions.BeginElement("Fragment");
@@ -463,6 +469,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
cmWIXFeaturesSourceWriter featureDefinitions(
this->Logger, featureDefinitionsFilename, this->ComponentGuidType);
+ InjectXmlNamespaces(featureDefinitions);
featureDefinitions.BeginElement("Fragment");
@@ -1147,6 +1154,35 @@ void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName,
extensions.insert(list.begin(), list.end());
}
+void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName,
+ xmlns_map_t& namespaces)
+{
+ const char* variableContent = GetOption(variableName.c_str());
+ if (!variableContent) {
+ return;
+ }
+
+ std::vector<std::string> list = cmExpandedList(variableContent);
+ for (std::string const& str : list) {
+ auto pos = str.find('=');
+ if (pos != std::string::npos) {
+ auto name = str.substr(0, pos);
+ auto value = str.substr(pos + 1);
+ namespaces.emplace(std::make_pair(name, value));
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Invalid element in CPACK_WIX_CUSTOM_XMLNS ignored: "
+ << "\"" << str << "\"" << std::endl);
+ }
+ }
+ std::ostringstream oss;
+ for (auto& ns : namespaces) {
+ oss << " xmlns:" << ns.first << "=\""
+ << cmWIXSourceWriter::EscapeAttributeValue(ns.second) << '"';
+ }
+ SetOption("CPACK_WIX_CUSTOM_XMLNS_EXPANDED", oss.str().c_str());
+}
+
void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName,
std::ostream& stream)
{
@@ -1172,3 +1208,10 @@ std::string cmCPackWIXGenerator::RelativePathWithoutComponentPrefix(
return path.substr(pos + 1);
}
+
+void cmCPackWIXGenerator::InjectXmlNamespaces(cmWIXSourceWriter& sourceWriter)
+{
+ for (auto& ns : this->CustomXmlNamespaces) {
+ sourceWriter.AddAttributeUnlessEmpty("xmlns:" + ns.first, ns.second);
+ }
+}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
index d5a16ec..b9c37e9 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.h
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -49,6 +49,7 @@ private:
using id_map_t = std::map<std::string, std::string>;
using ambiguity_map_t = std::map<std::string, size_t>;
using extension_set_t = std::set<std::string>;
+ using xmlns_map_t = std::map<std::string, std::string>;
enum class DefinitionType
{
@@ -147,16 +148,22 @@ private:
void CollectExtensions(std::string const& variableName,
extension_set_t& extensions);
+ void CollectXmlNamespaces(std::string const& variableName,
+ xmlns_map_t& namespaces);
+
void AddCustomFlags(std::string const& variableName, std::ostream& stream);
std::string RelativePathWithoutComponentPrefix(std::string const& path);
+ void InjectXmlNamespaces(cmWIXSourceWriter& sourceWriter);
+
std::vector<std::string> WixSources;
id_map_t PathToIdMap;
ambiguity_map_t IdAmbiguityCounter;
extension_set_t CandleExtensions;
extension_set_t LightExtensions;
+ xmlns_map_t CustomXmlNamespaces;
std::string CPackTopLevel;
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h
index 8cc2070..6030ea3 100644
--- a/Source/CPack/WiX/cmWIXSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXSourceWriter.h
@@ -50,6 +50,8 @@ public:
std::string CreateGuidFromComponentId(std::string const& componentId);
+ static std::string EscapeAttributeValue(std::string const& value);
+
protected:
cmCPackLog* Logger;
@@ -64,8 +66,6 @@ private:
void Indent(size_t count);
- static std::string EscapeAttributeValue(std::string const& value);
-
cmsys::ofstream File;
State State;
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 3d5fe6b..560e5c1 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -696,57 +696,57 @@ int cmCPackDebGenerator::createDeb()
const char* debian_pkg_source =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
- if (debian_pkg_source && *debian_pkg_source) {
+ if (cmNonempty(debian_pkg_source)) {
controlValues["Source"] = debian_pkg_source;
}
const char* debian_pkg_dep =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS");
- if (debian_pkg_dep && *debian_pkg_dep) {
+ if (cmNonempty(debian_pkg_dep)) {
controlValues["Depends"] = debian_pkg_dep;
}
const char* debian_pkg_rec =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS");
- if (debian_pkg_rec && *debian_pkg_rec) {
+ if (cmNonempty(debian_pkg_rec)) {
controlValues["Recommends"] = debian_pkg_rec;
}
const char* debian_pkg_sug =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS");
- if (debian_pkg_sug && *debian_pkg_sug) {
+ if (cmNonempty(debian_pkg_sug)) {
controlValues["Suggests"] = debian_pkg_sug;
}
const char* debian_pkg_url =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE");
- if (debian_pkg_url && *debian_pkg_url) {
+ if (cmNonempty(debian_pkg_url)) {
controlValues["Homepage"] = debian_pkg_url;
}
const char* debian_pkg_predep =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PREDEPENDS");
- if (debian_pkg_predep && *debian_pkg_predep) {
+ if (cmNonempty(debian_pkg_predep)) {
controlValues["Pre-Depends"] = debian_pkg_predep;
}
const char* debian_pkg_enhances =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ENHANCES");
- if (debian_pkg_enhances && *debian_pkg_enhances) {
+ if (cmNonempty(debian_pkg_enhances)) {
controlValues["Enhances"] = debian_pkg_enhances;
}
const char* debian_pkg_breaks =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_BREAKS");
- if (debian_pkg_breaks && *debian_pkg_breaks) {
+ if (cmNonempty(debian_pkg_breaks)) {
controlValues["Breaks"] = debian_pkg_breaks;
}
const char* debian_pkg_conflicts =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONFLICTS");
- if (debian_pkg_conflicts && *debian_pkg_conflicts) {
+ if (cmNonempty(debian_pkg_conflicts)) {
controlValues["Conflicts"] = debian_pkg_conflicts;
}
const char* debian_pkg_provides =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES");
- if (debian_pkg_provides && *debian_pkg_provides) {
+ if (cmNonempty(debian_pkg_provides)) {
controlValues["Provides"] = debian_pkg_provides;
}
const char* debian_pkg_replaces =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_REPLACES");
- if (debian_pkg_replaces && *debian_pkg_replaces) {
+ if (cmNonempty(debian_pkg_replaces)) {
controlValues["Replaces"] = debian_pkg_replaces;
}
@@ -756,7 +756,7 @@ int cmCPackDebGenerator::createDeb()
const char* debian_pkg_shlibs =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SHLIBS");
const bool gen_shibs = this->IsOn("CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS") &&
- debian_pkg_shlibs && *debian_pkg_shlibs;
+ cmNonempty(debian_pkg_shlibs);
if (gen_shibs) {
cmGeneratedFileStream out;
out.Open(shlibsfilename, false, true);
@@ -832,11 +832,11 @@ int cmCPackDebGenerator::createDbgsymDDeb()
const char* debian_pkg_source =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
- if (debian_pkg_source && *debian_pkg_source) {
+ if (cmNonempty(debian_pkg_source)) {
controlValues["Source"] = debian_pkg_source;
}
const char* debian_build_ids = this->GetOption("GEN_BUILD_IDS");
- if (debian_build_ids && *debian_build_ids) {
+ if (cmNonempty(debian_build_ids)) {
controlValues["Build-Ids"] = debian_build_ids;
}
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index fe7abf4..cefb906 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -8,7 +8,9 @@
#include <map>
#include <CoreFoundation/CoreFoundation.h>
+#include <cm3p/kwiml/abi.h>
+#include "cmsys/Base64.h"
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
@@ -18,6 +20,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmXMLWriter.h"
#ifdef HAVE_CoreServices
// For the old LocaleStringToLangAndRegionCodes() function, to convert
@@ -26,36 +29,28 @@
# include <CoreServices/CoreServices.h>
#endif
-static const char* SLAHeader =
- "data 'LPic' (5000) {\n"
- " $\"0002 0011 0003 0001 0000 0000 0002 0000\"\n"
- " $\"0008 0003 0000 0001 0004 0000 0004 0005\"\n"
- " $\"0000 000E 0006 0001 0005 0007 0000 0007\"\n"
- " $\"0008 0000 0047 0009 0000 0034 000A 0001\"\n"
- " $\"0035 000B 0001 0020 000C 0000 0011 000D\"\n"
- " $\"0000 005B 0004 0000 0033 000F 0001 000C\"\n"
- " $\"0010 0000 000B 000E 0000\"\n"
- "};\n"
- "\n";
-
-static const char* SLASTREnglish =
- "resource 'STR#' (5002, \"English\") {\n"
- " {\n"
- " \"English\",\n"
- " \"Agree\",\n"
- " \"Disagree\",\n"
- " \"Print\",\n"
- " \"Save...\",\n"
- " \"You agree to the License Agreement terms when you click \"\n"
- " \"the \\\"Agree\\\" button.\",\n"
- " \"Software License Agreement\",\n"
- " \"This text cannot be saved. This disk may be full or locked, "
- "or the \"\n"
- " \"file may be locked.\",\n"
- " \"Unable to print. Make sure you have selected a printer.\"\n"
- " }\n"
- "};\n"
- "\n";
+static const uint16_t DefaultLpic[] = {
+ /* clang-format off */
+ 0x0002, 0x0011, 0x0003, 0x0001, 0x0000, 0x0000, 0x0002, 0x0000,
+ 0x0008, 0x0003, 0x0000, 0x0001, 0x0004, 0x0000, 0x0004, 0x0005,
+ 0x0000, 0x000E, 0x0006, 0x0001, 0x0005, 0x0007, 0x0000, 0x0007,
+ 0x0008, 0x0000, 0x0047, 0x0009, 0x0000, 0x0034, 0x000A, 0x0001,
+ 0x0035, 0x000B, 0x0001, 0x0020, 0x000C, 0x0000, 0x0011, 0x000D,
+ 0x0000, 0x005B, 0x0004, 0x0000, 0x0033, 0x000F, 0x0001, 0x000C,
+ 0x0010, 0x0000, 0x000B, 0x000E, 0x0000
+ /* clang-format on */
+};
+
+static const std::vector<std::string> DefaultMenu = {
+ { "English", "Agree", "Disagree", "Print", "Save...",
+ // NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
+ "You agree to the License Agreement terms when "
+ "you click the \"Agree\" button.",
+ "Software License Agreement",
+ "This text cannot be saved. "
+ "This disk may be full or locked, or the file may be locked.",
+ "Unable to print. Make sure you have selected a printer." }
+};
cmCPackDragNDropGenerator::cmCPackDragNDropGenerator()
: singleLicense(false)
@@ -523,22 +518,43 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
}
}
+ // Create the final compressed read-only disk image ...
+ std::ostringstream final_image_command;
+ final_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
+ final_image_command << " convert \"" << temp_image << "\"";
+ final_image_command << " -format ";
+ final_image_command << cpack_dmg_format;
+ final_image_command << " -imagekey";
+ final_image_command << " zlib-level=9";
+ final_image_command << " -o \"" << output_file << "\"";
+
+ std::string convert_error;
+
+ if (!this->RunCommand(final_image_command, &convert_error)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error compressing disk image." << std::endl
+ << convert_error
+ << std::endl);
+
+ return 0;
+ }
+
if (!cpack_license_file.empty() || !slaDirectory.empty()) {
// Use old hardcoded style if sla_dir is not set
bool oldStyle = slaDirectory.empty();
- std::string sla_r =
- cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/sla.r");
+ std::string sla_xml =
+ cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/sla.xml");
std::vector<std::string> languages;
if (!oldStyle) {
cmExpandList(cpack_dmg_languages, languages);
}
- cmGeneratedFileStream ofs(sla_r);
- ofs << "#include <CoreServices/CoreServices.r>\n\n";
+ std::vector<uint16_t> header_data;
if (oldStyle) {
- ofs << SLAHeader;
- ofs << "\n";
+ header_data = std::vector<uint16_t>(
+ DefaultLpic,
+ DefaultLpic + (sizeof(DefaultLpic) / sizeof(*DefaultLpic)));
} else {
/*
* LPic Layout
@@ -558,8 +574,6 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
* }
*/
- // Create vector first for readability, then iterate to write to ofs
- std::vector<uint16_t> header_data;
header_data.push_back(0);
header_data.push_back(languages.size());
for (size_t i = 0; i < languages.size(); ++i) {
@@ -596,52 +610,50 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
header_data.push_back(0);
#endif
}
- ofs << "data 'LPic' (5000) {\n";
- ofs << std::hex << std::uppercase << std::setfill('0');
-
- for (size_t i = 0; i < header_data.size(); ++i) {
- if (i % 8 == 0) {
- ofs << " $\"";
- }
-
- ofs << std::setw(4) << header_data[i];
+ }
- if (i % 8 == 7 || i == header_data.size() - 1) {
- ofs << "\"\n";
- } else {
- ofs << " ";
- }
+ RezDoc rez;
+
+ {
+ RezDict lpic = { {}, 5000, {} };
+ lpic.Data.reserve(header_data.size() * sizeof(header_data[0]));
+ for (uint16_t x : header_data) {
+ // LPic header is big-endian.
+ char* d = reinterpret_cast<char*>(&x);
+#if KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE
+ lpic.Data.push_back(d[1]);
+ lpic.Data.push_back(d[0]);
+#else
+ lpic.Data.push_back(d[0]);
+ lpic.Data.push_back(d[1]);
+#endif
}
- ofs << "};\n\n";
- // Reset ofs options
- ofs << std::dec << std::nouppercase << std::setfill(' ');
+ rez.LPic.Entries.emplace_back(std::move(lpic));
}
bool have_write_license_error = false;
std::string error;
if (oldStyle) {
- if (!this->WriteLicense(ofs, 0, "", cpack_license_file, &error)) {
+ if (!this->WriteLicense(rez, 0, "", cpack_license_file, &error)) {
have_write_license_error = true;
}
} else {
for (size_t i = 0; i < languages.size() && !have_write_license_error;
++i) {
if (singleLicense) {
- if (!this->WriteLicense(ofs, i + 5000, languages[i],
+ if (!this->WriteLicense(rez, i + 5000, languages[i],
cpack_license_file, &error)) {
have_write_license_error = true;
}
} else {
- if (!this->WriteLicense(ofs, i + 5000, languages[i], "", &error)) {
+ if (!this->WriteLicense(rez, i + 5000, languages[i], "", &error)) {
have_write_license_error = true;
}
}
}
}
- ofs.Close();
-
if (have_write_license_error) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error writing license file to SLA." << std::endl
@@ -650,96 +662,27 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
return 0;
}
- if (temp_image_format != "UDZO") {
- temp_image_format = "UDZO";
- // convert to UDZO to enable unflatten/flatten
- std::string temp_udzo = cmStrCat(
- this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp-udzo.dmg");
+ this->WriteRezXML(sla_xml, rez);
- std::ostringstream udco_image_command;
- udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
- udco_image_command << " convert \"" << temp_image << "\"";
- udco_image_command << " -format UDZO";
- udco_image_command << " -ov -o \"" << temp_udzo << "\"";
-
- if (!this->RunCommand(udco_image_command, &error)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error converting to UDCO dmg for adding SLA."
- << std::endl
- << error << std::endl);
- return 0;
- }
- temp_image = temp_udzo;
- }
-
- // unflatten dmg
- std::ostringstream unflatten_command;
- unflatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
- unflatten_command << " unflatten ";
- unflatten_command << "\"" << temp_image << "\"";
-
- if (!this->RunCommand(unflatten_command, &error)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error unflattening dmg for adding SLA." << std::endl
- << error
- << std::endl);
- return 0;
- }
-
- // Rez the SLA
+ // Create the final compressed read-only disk image ...
std::ostringstream embed_sla_command;
- embed_sla_command << this->GetOption("CPACK_COMMAND_REZ");
- const char* sysroot = this->GetOption("CPACK_OSX_SYSROOT");
- if (sysroot && sysroot[0] != '\0') {
- embed_sla_command << " -isysroot \"" << sysroot << "\"";
- }
- embed_sla_command << " \"" << sla_r << "\"";
- embed_sla_command << " -a -o ";
- embed_sla_command << "\"" << temp_image << "\"";
-
- if (!this->RunCommand(embed_sla_command, &error)) {
+ embed_sla_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
+ embed_sla_command << " udifrez";
+ embed_sla_command << " -xml";
+ embed_sla_command << " \"" << sla_xml << "\"";
+ embed_sla_command << " FIXME_WHY_IS_THIS_ARGUMENT_NEEDED";
+ embed_sla_command << " \"" << output_file << "\"";
+ std::string embed_error;
+ if (!this->RunCommand(embed_sla_command, &embed_error)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding SLA." << std::endl
- << error << std::endl);
- return 0;
- }
-
- // flatten dmg
- std::ostringstream flatten_command;
- flatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
- flatten_command << " flatten ";
- flatten_command << "\"" << temp_image << "\"";
+ "Error compressing disk image." << std::endl
+ << embed_error
+ << std::endl);
- if (!this->RunCommand(flatten_command, &error)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error flattening dmg for adding SLA." << std::endl
- << error
- << std::endl);
return 0;
}
}
- // Create the final compressed read-only disk image ...
- std::ostringstream final_image_command;
- final_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
- final_image_command << " convert \"" << temp_image << "\"";
- final_image_command << " -format ";
- final_image_command << cpack_dmg_format;
- final_image_command << " -imagekey";
- final_image_command << " zlib-level=9";
- final_image_command << " -o \"" << output_file << "\"";
-
- std::string convert_error;
-
- if (!this->RunCommand(final_image_command, &convert_error)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error compressing disk image." << std::endl
- << convert_error
- << std::endl);
-
- return 0;
- }
-
return 1;
}
@@ -788,10 +731,67 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix(
return GetComponentPackageFileName(package_file_name, componentName, false);
}
-bool cmCPackDragNDropGenerator::WriteLicense(
- cmGeneratedFileStream& outputStream, int licenseNumber,
- std::string licenseLanguage, const std::string& licenseFile,
- std::string* error)
+void cmCPackDragNDropGenerator::WriteRezXML(std::string const& file,
+ RezDoc const& rez)
+{
+ cmGeneratedFileStream fxml(file);
+ cmXMLWriter xml(fxml);
+ xml.StartDocument();
+ xml.StartElement("plist");
+ xml.Attribute("version", "1.0");
+ xml.StartElement("dict");
+ this->WriteRezArray(xml, rez.LPic);
+ this->WriteRezArray(xml, rez.Menu);
+ this->WriteRezArray(xml, rez.Text);
+ this->WriteRezArray(xml, rez.RTF);
+ xml.EndElement(); // dict
+ xml.EndElement(); // plist
+ xml.EndDocument();
+ fxml.Close();
+}
+
+void cmCPackDragNDropGenerator::WriteRezArray(cmXMLWriter& xml,
+ RezArray const& array)
+{
+ if (array.Entries.empty()) {
+ return;
+ }
+ xml.StartElement("key");
+ xml.Content(array.Key);
+ xml.EndElement(); // key
+ xml.StartElement("array");
+ for (RezDict const& dict : array.Entries) {
+ this->WriteRezDict(xml, dict);
+ }
+ xml.EndElement(); // array
+}
+
+void cmCPackDragNDropGenerator::WriteRezDict(cmXMLWriter& xml,
+ RezDict const& dict)
+{
+ std::vector<char> base64buf(dict.Data.size() * 3 / 2 + 5);
+ size_t base64len =
+ cmsysBase64_Encode(dict.Data.data(), dict.Data.size(),
+ reinterpret_cast<unsigned char*>(base64buf.data()), 0);
+ std::string base64data(base64buf.data(), base64len);
+ /* clang-format off */
+ xml.StartElement("dict");
+ xml.StartElement("key"); xml.Content("Attributes"); xml.EndElement();
+ xml.StartElement("string"); xml.Content("0x0000"); xml.EndElement();
+ xml.StartElement("key"); xml.Content("Data"); xml.EndElement();
+ xml.StartElement("data"); xml.Content(base64data); xml.EndElement();
+ xml.StartElement("key"); xml.Content("ID"); xml.EndElement();
+ xml.StartElement("string"); xml.Content(dict.ID); xml.EndElement();
+ xml.StartElement("key"); xml.Content("Name"); xml.EndElement();
+ xml.StartElement("string"); xml.Content(dict.Name); xml.EndElement();
+ xml.EndElement(); // dict
+ /* clang-format on */
+}
+
+bool cmCPackDragNDropGenerator::WriteLicense(RezDoc& rez, size_t licenseNumber,
+ std::string licenseLanguage,
+ const std::string& licenseFile,
+ std::string* error)
{
if (!licenseFile.empty() && !singleLicense) {
licenseNumber = 5002;
@@ -799,11 +799,11 @@ bool cmCPackDragNDropGenerator::WriteLicense(
}
// License file
- std::string license_format = "TEXT";
+ RezArray* licenseArray = &rez.Text;
std::string actual_license;
if (!licenseFile.empty()) {
if (cmHasLiteralSuffix(licenseFile, ".rtf")) {
- license_format = "RTF ";
+ licenseArray = &rez.RTF;
}
actual_license = licenseFile;
} else {
@@ -812,85 +812,86 @@ bool cmCPackDragNDropGenerator::WriteLicense(
if (cmSystemTools::FileExists(license_wo_ext + ".txt")) {
actual_license = license_wo_ext + ".txt";
} else {
- license_format = "RTF ";
+ licenseArray = &rez.RTF;
actual_license = license_wo_ext + ".rtf";
}
}
- // License header
- outputStream << "data '" << license_format << "' (" << licenseNumber
- << ", \"" << licenseLanguage << "\") {\n";
// License body
- cmsys::ifstream license_ifs;
- license_ifs.open(actual_license.c_str());
- if (license_ifs.is_open()) {
- while (license_ifs.good()) {
- std::string line;
- std::getline(license_ifs, line);
- if (!line.empty()) {
- EscapeQuotesAndBackslashes(line);
- std::vector<std::string> lines;
- if (!this->BreakLongLine(line, lines, error)) {
- return false;
- }
- for (auto const& l : lines) {
- outputStream << " \"" << l << "\"\n";
- }
- }
- outputStream << " \"\\n\"\n";
+ {
+ RezDict license = { licenseLanguage, licenseNumber, {} };
+ std::vector<std::string> lines;
+ if (!this->ReadFile(actual_license, lines, error)) {
+ return false;
}
- license_ifs.close();
+ this->EncodeLicense(license, lines);
+ licenseArray->Entries.emplace_back(std::move(license));
}
- // End of License
- outputStream << "};\n\n";
- if (!licenseFile.empty() && !singleLicense) {
- outputStream << SLASTREnglish;
- } else {
- // Menu header
- outputStream << "resource 'STR#' (" << licenseNumber << ", \""
- << licenseLanguage << "\") {\n";
- outputStream << " {\n";
-
- // Menu body
- cmsys::ifstream menu_ifs;
- menu_ifs.open(
- (slaDirectory + "/" + licenseLanguage + ".menu.txt").c_str());
- if (menu_ifs.is_open()) {
- size_t lines_written = 0;
- while (menu_ifs.good()) {
- // Lines written from original file, not from broken up lines
- std::string line;
- std::getline(menu_ifs, line);
- if (!line.empty()) {
- EscapeQuotesAndBackslashes(line);
- std::vector<std::string> lines;
- if (!this->BreakLongLine(line, lines, error)) {
- return false;
- }
- for (size_t i = 0; i < lines.size(); ++i) {
- std::string comma;
- // We need a comma after every complete string,
- // but not on the very last line
- if (lines_written != 8 && i == lines.size() - 1) {
- comma = ",";
- } else {
- comma = "";
- }
- outputStream << " \"" << lines[i] << "\"" << comma << "\n";
- }
- ++lines_written;
- }
+ // Menu body
+ {
+ RezDict menu = { licenseLanguage, licenseNumber, {} };
+ if (!licenseFile.empty() && !singleLicense) {
+ this->EncodeMenu(menu, DefaultMenu);
+ } else {
+ std::vector<std::string> lines;
+ std::string actual_menu =
+ slaDirectory + "/" + licenseLanguage + ".menu.txt";
+ if (!this->ReadFile(actual_menu, lines, error)) {
+ return false;
}
- menu_ifs.close();
+ this->EncodeMenu(menu, lines);
}
+ rez.Menu.Entries.emplace_back(std::move(menu));
+ }
+
+ return true;
+}
+
+void cmCPackDragNDropGenerator::EncodeLicense(
+ RezDict& dict, std::vector<std::string> const& lines)
+{
+ // License text uses CR newlines.
+ for (std::string const& l : lines) {
+ dict.Data.insert(dict.Data.end(), l.begin(), l.end());
+ dict.Data.push_back('\r');
+ }
+ dict.Data.push_back('\r');
+}
- // End of menu
- outputStream << " }\n";
- outputStream << "};\n";
- outputStream << "\n";
+void cmCPackDragNDropGenerator::EncodeMenu(
+ RezDict& dict, std::vector<std::string> const& lines)
+{
+ // Menu resources start with a big-endian uint16_t for number of lines:
+ {
+ uint16_t numLines = static_cast<uint16_t>(lines.size());
+ char* d = reinterpret_cast<char*>(&numLines);
+#if KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE
+ dict.Data.push_back(d[1]);
+ dict.Data.push_back(d[0]);
+#else
+ dict.Data.push_back(d[0]);
+ dict.Data.push_back(d[1]);
+#endif
}
+ // Each line starts with a uint8_t length, plus the bytes themselves:
+ for (std::string const& l : lines) {
+ dict.Data.push_back(static_cast<unsigned char>(l.length()));
+ dict.Data.insert(dict.Data.end(), l.begin(), l.end());
+ }
+}
+bool cmCPackDragNDropGenerator::ReadFile(std::string const& file,
+ std::vector<std::string>& lines,
+ std::string* error)
+{
+ cmsys::ifstream ifs(file);
+ std::string line;
+ while (std::getline(ifs, line)) {
+ if (!this->BreakLongLine(line, lines, error)) {
+ return false;
+ }
+ }
return true;
}
@@ -898,7 +899,7 @@ bool cmCPackDragNDropGenerator::BreakLongLine(const std::string& line,
std::vector<std::string>& lines,
std::string* error)
{
- const size_t max_line_length = 512;
+ const size_t max_line_length = 255;
size_t line_length = max_line_length;
for (size_t i = 0; i < line.size(); i += line_length) {
line_length = max_line_length;
@@ -913,25 +914,10 @@ bool cmCPackDragNDropGenerator::BreakLongLine(const std::string& line,
if (line_length == 0) {
*error = "Please make sure there are no words "
"(or character sequences not broken up by spaces or newlines) "
- "in your license file which are more than 512 characters long.";
+ "in your license file which are more than 255 characters long.";
return false;
}
lines.push_back(line.substr(i, line_length));
}
return true;
}
-
-void cmCPackDragNDropGenerator::EscapeQuotesAndBackslashes(std::string& line)
-{
- std::string::size_type backslash_pos = line.find('\\');
- while (backslash_pos != std::string::npos) {
- line.replace(backslash_pos, 1, "\\\\");
- backslash_pos = line.find('\\', backslash_pos + 2);
- }
-
- std::string::size_type quote_pos = line.find('\"');
- while (quote_pos != std::string::npos) {
- line.replace(quote_pos, 1, "\\\"");
- quote_pos = line.find('\"', quote_pos + 2);
- }
-}
diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h
index f8c86c0..dbd190c 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.h
+++ b/Source/CPack/cmCPackDragNDropGenerator.h
@@ -14,6 +14,7 @@
#include "cmCPackGenerator.h"
class cmGeneratedFileStream;
+class cmXMLWriter;
/** \class cmCPackDragNDropGenerator
* \brief A generator for OSX drag-n-drop installs
@@ -45,12 +46,40 @@ private:
std::string slaDirectory;
bool singleLicense;
- bool WriteLicense(cmGeneratedFileStream& outputStream, int licenseNumber,
+ struct RezDict
+ {
+ std::string Name;
+ size_t ID;
+ std::vector<unsigned char> Data;
+ };
+
+ struct RezArray
+ {
+ std::string Key;
+ std::vector<RezDict> Entries;
+ };
+
+ struct RezDoc
+ {
+ RezArray LPic = { "LPic", {} };
+ RezArray Menu = { "STR#", {} };
+ RezArray Text = { "TEXT", {} };
+ RezArray RTF = { "RTF ", {} };
+ };
+
+ void WriteRezXML(std::string const& file, RezDoc const& rez);
+ void WriteRezArray(cmXMLWriter& xml, RezArray const& array);
+ void WriteRezDict(cmXMLWriter& xml, RezDict const& dict);
+
+ bool WriteLicense(RezDoc& rez, size_t licenseNumber,
std::string licenseLanguage,
const std::string& licenseFile, std::string* error);
+ void EncodeLicense(RezDict& dict, std::vector<std::string> const& lines);
+ void EncodeMenu(RezDict& dict, std::vector<std::string> const& lines);
+ bool ReadFile(std::string const& file, std::vector<std::string>& lines,
+ std::string* error);
bool BreakLongLine(const std::string& line, std::vector<std::string>& lines,
std::string* error);
- void EscapeQuotesAndBackslashes(std::string& line);
};
#endif
diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx
index 11e1aec..0bc8456 100644
--- a/Source/CPack/cmCPackExternalGenerator.cxx
+++ b/Source/CPack/cmCPackExternalGenerator.cxx
@@ -61,7 +61,7 @@ int cmCPackExternalGenerator::PackageFiles()
}
const char* packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT");
- if (packageScript && *packageScript) {
+ if (cmNonempty(packageScript)) {
if (!cmSystemTools::FileIsFullPath(packageScript)) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
@@ -75,6 +75,12 @@ int cmCPackExternalGenerator::PackageFiles()
if (cmSystemTools::GetErrorOccuredFlag() || !res) {
return 0;
}
+
+ const char* builtPackagesStr =
+ this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES");
+ if (builtPackagesStr) {
+ cmExpandList(builtPackagesStr, this->packageFileNames, false);
+ }
}
return 1;
@@ -205,7 +211,7 @@ int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON(
const char* defaultDirectoryPermissions =
this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
- if (defaultDirectoryPermissions && *defaultDirectoryPermissions) {
+ if (cmNonempty(defaultDirectoryPermissions)) {
root["defaultDirectoryPermissions"] = defaultDirectoryPermissions;
}
if (cmIsInternallyOn(this->Parent->GetOption("CPACK_SET_DESTDIR"))) {
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 288dc58..3880f65 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -216,7 +216,7 @@ int cmCPackGenerator::InstallProject()
mode_t* default_dir_mode = nullptr;
const char* default_dir_install_permissions =
this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
- if (default_dir_install_permissions && *default_dir_install_permissions) {
+ if (cmNonempty(default_dir_install_permissions)) {
std::vector<std::string> items =
cmExpandedList(default_dir_install_permissions);
for (const auto& arg : items) {
@@ -264,6 +264,23 @@ int cmCPackGenerator::InstallProject()
return 0;
}
+ // Run pre-build actions
+ const char* preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS");
+ if (preBuildScripts) {
+ const auto scripts = cmExpandedList(preBuildScripts, false);
+ for (const auto& script : scripts) {
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "Executing pre-build script: " << script << std::endl);
+
+ if (!this->MakefileMap->ReadListFile(script)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "The pre-build script not found: " << script
+ << std::endl);
+ return 0;
+ }
+ }
+ }
+
if (setDestDir) {
cmSystemTools::PutEnv("DESTDIR=");
}
@@ -276,7 +293,7 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
{
(void)setDestDir;
const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS");
- if (installCommands && *installCommands) {
+ if (cmNonempty(installCommands)) {
std::string tempInstallDirectoryEnv =
cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory);
cmSystemTools::PutEnv(tempInstallDirectoryEnv);
@@ -327,13 +344,14 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
}
const char* installDirectories =
this->GetOption("CPACK_INSTALLED_DIRECTORIES");
- if (installDirectories && *installDirectories) {
+ if (cmNonempty(installDirectories)) {
std::vector<std::string> installDirectoriesVector =
cmExpandedList(installDirectories);
if (installDirectoriesVector.size() % 2 != 0) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
- "CPACK_INSTALLED_DIRECTORIES should contain pairs of <directory> and "
+ "CPACK_INSTALLED_DIRECTORIES should contain pairs of <directory> "
+ "and "
"<subdirectory>. The <subdirectory> can be '.' to be installed in "
"the toplevel directory of installation."
<< std::endl);
@@ -475,10 +493,10 @@ int cmCPackGenerator::InstallProjectViaInstallScript(
"- Install script: " << installScript << std::endl);
if (setDestDir) {
- // For DESTDIR based packaging, use the *project* CMAKE_INSTALL_PREFIX
- // underneath the tempInstallDirectory. The value of the project's
- // CMAKE_INSTALL_PREFIX is sent in here as the value of the
- // CPACK_INSTALL_PREFIX variable.
+ // For DESTDIR based packaging, use the *project*
+ // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The
+ // value of the project's CMAKE_INSTALL_PREFIX is sent in here as the
+ // value of the CPACK_INSTALL_PREFIX variable.
std::string dir;
if (this->GetOption("CPACK_INSTALL_PREFIX")) {
@@ -523,7 +541,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR");
std::string absoluteDestFiles;
- if (cmakeProjects && *cmakeProjects) {
+ if (cmNonempty(cmakeProjects)) {
if (!cmakeGenerator) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_INSTALL_CMAKE_PROJECTS is specified, but "
@@ -576,7 +594,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
std::string installTypesVar = "CPACK_" +
cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES";
const char* installTypes = this->GetOption(installTypesVar);
- if (installTypes && *installTypes) {
+ if (cmNonempty(installTypes)) {
std::vector<std::string> installTypesVector =
cmExpandedList(installTypes);
for (std::string const& installType : installTypesVector) {
@@ -589,7 +607,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
std::string componentsVar =
"CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component);
const char* components = this->GetOption(componentsVar);
- if (components && *components) {
+ if (cmNonempty(components)) {
cmExpandList(components, componentsVector);
for (std::string const& comp : componentsVector) {
project.Components.push_back(
@@ -753,7 +771,7 @@ int cmCPackGenerator::InstallCMakeProject(
const char* default_dir_inst_permissions =
this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
- if (default_dir_inst_permissions && *default_dir_inst_permissions) {
+ if (cmNonempty(default_dir_inst_permissions)) {
mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS",
default_dir_inst_permissions);
}
@@ -811,7 +829,7 @@ int cmCPackGenerator::InstallCMakeProject(
* - Because it was already used for component install
* in order to put things in subdirs...
*/
- cmSystemTools::PutEnv(std::string("DESTDIR=") + tempInstallDirectory);
+ cmSystemTools::PutEnv("DESTDIR=" + tempInstallDirectory);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Creating directory: '" << dir << "'" << std::endl);
@@ -965,7 +983,7 @@ void cmCPackGenerator::SetOptionIfNotSet(const std::string& op,
const char* value)
{
const char* def = this->MakefileMap->GetDefinition(op);
- if (def && *def) {
+ if (cmNonempty(def)) {
return;
}
this->SetOption(op, value);
@@ -1076,6 +1094,25 @@ int cmCPackGenerator::DoPackage()
return 0;
}
}
+ // Run post-build actions
+ const char* postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS");
+ if (postBuildScripts) {
+ this->MakefileMap->AddDefinition("CPACK_PACKAGE_FILES",
+ cmJoin(this->packageFileNames, ";"));
+
+ const auto scripts = cmExpandedList(postBuildScripts, false);
+ for (const auto& script : scripts) {
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "Executing post-build script: " << script << std::endl);
+
+ if (!this->MakefileMap->ReadListFile(script)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "The post-build script not found: " << script
+ << std::endl);
+ return 0;
+ }
+ }
+ }
/* Prepare checksum algorithm*/
const char* algo = this->GetOption("CPACK_PACKAGE_CHECKSUM");
@@ -1178,7 +1215,7 @@ bool cmCPackGenerator::IsOn(const std::string& name) const
bool cmCPackGenerator::IsSetToOff(const std::string& op) const
{
const char* ret = this->MakefileMap->GetDefinition(op);
- if (ret && *ret) {
+ if (cmNonempty(ret)) {
return cmIsOff(ret);
}
return false;
@@ -1289,7 +1326,7 @@ bool cmCPackGenerator::ConfigureFile(const std::string& inName,
bool copyOnly /* = false */)
{
return this->MakefileMap->ConfigureFile(inName, outName, copyOnly, true,
- false) == 1;
+ false, true) == 1;
}
int cmCPackGenerator::CleanTemporaryDirectory()
@@ -1378,7 +1415,8 @@ int cmCPackGenerator::PrepareGroupingKind()
<< std::endl);
}
- // if user specified packaging method, override the default packaging method
+ // if user specified packaging method, override the default packaging
+ // method
if (method != UNKNOWN_COMPONENT_PACKAGE_METHOD) {
componentPackageMethod = method;
}
@@ -1471,7 +1509,7 @@ cmCPackInstallationType* cmCPackGenerator::GetInstallationType(
installType->Name = name;
const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
- if (displayName && *displayName) {
+ if (cmNonempty(displayName)) {
installType->DisplayName = displayName;
} else {
installType->DisplayName = installType->Name;
@@ -1493,7 +1531,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
"CPACK_COMPONENT_" + cmsys::SystemTools::UpperCase(name);
component->Name = name;
const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
- if (displayName && *displayName) {
+ if (cmNonempty(displayName)) {
component->DisplayName = displayName;
} else {
component->DisplayName = component->Name;
@@ -1505,17 +1543,17 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
cmIsOn(this->GetOption("CPACK_DOWNLOAD_ALL"));
const char* archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE");
- if (archiveFile && *archiveFile) {
+ if (cmNonempty(archiveFile)) {
component->ArchiveFile = archiveFile;
}
const char* plist = this->GetOption(macroPrefix + "_PLIST");
- if (plist && *plist) {
+ if (cmNonempty(plist)) {
component->Plist = plist;
}
const char* groupName = this->GetOption(macroPrefix + "_GROUP");
- if (groupName && *groupName) {
+ if (cmNonempty(groupName)) {
component->Group = GetComponentGroup(projectName, groupName);
component->Group->Components.push_back(component);
} else {
@@ -1523,13 +1561,13 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
}
const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
- if (description && *description) {
+ if (cmNonempty(description)) {
component->Description = description;
}
// Determine the installation types.
const char* installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES");
- if (installTypes && *installTypes) {
+ if (cmNonempty(installTypes)) {
std::vector<std::string> installTypesVector =
cmExpandedList(installTypes);
for (std::string const& installType : installTypesVector) {
@@ -1540,7 +1578,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
// Determine the component dependencies.
const char* depends = this->GetOption(macroPrefix + "_DEPENDS");
- if (depends && *depends) {
+ if (cmNonempty(depends)) {
std::vector<std::string> dependsVector = cmExpandedList(depends);
for (std::string const& depend : dependsVector) {
cmCPackComponent* child = GetComponent(projectName, depend);
@@ -1564,21 +1602,21 @@ cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup(
// Define the group
group->Name = name;
const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
- if (displayName && *displayName) {
+ if (cmNonempty(displayName)) {
group->DisplayName = displayName;
} else {
group->DisplayName = group->Name;
}
const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
- if (description && *description) {
+ if (cmNonempty(description)) {
group->Description = description;
}
group->IsBold = this->IsOn(macroPrefix + "_BOLD_TITLE");
group->IsExpandedByDefault = this->IsOn(macroPrefix + "_EXPANDED");
const char* parentGroupName =
this->GetOption(macroPrefix + "_PARENT_GROUP");
- if (parentGroupName && *parentGroupName) {
+ if (cmNonempty(parentGroupName)) {
group->ParentGroup = GetComponentGroup(projectName, parentGroupName);
group->ParentGroup->Subgroups.push_back(group);
} else {
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 058b090..2109b4e 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -696,7 +696,7 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
const char* userUploadDirectory =
this->GetOption("CPACK_UPLOAD_DIRECTORY");
std::string uploadDirectory;
- if (userUploadDirectory && *userUploadDirectory) {
+ if (cmNonempty(userUploadDirectory)) {
uploadDirectory = userUploadDirectory;
} else {
uploadDirectory =
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index db426b2..a18cbb4 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -182,10 +182,9 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
std::vector<std::string> extraPaths;
std::vector<std::string> failed;
fullPath = cmCTestTestHandler::FindExecutable(
- this->CTest, this->ConfigSample.c_str(), resultingConfig, extraPaths,
- failed);
+ this->CTest, this->ConfigSample, resultingConfig, extraPaths, failed);
if (!fullPath.empty() && !resultingConfig.empty()) {
- this->CTest->SetConfigType(resultingConfig.c_str());
+ this->CTest->SetConfigType(resultingConfig);
}
out << "Using config sample with results: " << fullPath << " and "
<< resultingConfig << std::endl;
@@ -296,9 +295,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
extraPaths.push_back(tempPath);
}
std::vector<std::string> failed;
- fullPath =
- cmCTestTestHandler::FindExecutable(this->CTest, this->TestCommand.c_str(),
- resultingConfig, extraPaths, failed);
+ fullPath = cmCTestTestHandler::FindExecutable(
+ this->CTest, this->TestCommand, resultingConfig, extraPaths, failed);
if (!cmSystemTools::FileExists(fullPath)) {
out << "Could not find path to executable, perhaps it was not built: "
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index 44fdc29..8aab167 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -12,6 +12,7 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
@@ -38,10 +39,9 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
this->Handler = handler;
- const char* ctestBuildCommand =
- this->Makefile->GetDefinition("CTEST_BUILD_COMMAND");
- if (ctestBuildCommand && *ctestBuildCommand) {
- this->CTest->SetCTestConfiguration("MakeCommand", ctestBuildCommand,
+ cmProp ctestBuildCommand = this->Makefile->GetDef("CTEST_BUILD_COMMAND");
+ if (cmNonempty(ctestBuildCommand)) {
+ this->CTest->SetCTestConfiguration("MakeCommand", *ctestBuildCommand,
this->Quiet);
} else {
const char* cmakeGeneratorName =
@@ -56,7 +56,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
const char* cmakeBuildConfiguration = !this->Configuration.empty()
? this->Configuration.c_str()
- : ((ctestBuildConfiguration && *ctestBuildConfiguration)
+ : (cmNonempty(ctestBuildConfiguration)
? ctestBuildConfiguration
: this->CTest->GetConfigType().c_str());
@@ -67,7 +67,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
? this->Target.c_str()
: this->Makefile->GetDefinition("CTEST_BUILD_TARGET");
- if (cmakeGeneratorName && *cmakeGeneratorName) {
+ if (cmNonempty(cmakeGeneratorName)) {
if (!cmakeBuildConfiguration) {
cmakeBuildConfiguration = "Release";
}
@@ -108,7 +108,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"SetMakeCommand:" << buildCommand << "\n",
this->Quiet);
- this->CTest->SetCTestConfiguration("MakeCommand", buildCommand.c_str(),
+ this->CTest->SetCTestConfiguration("MakeCommand", buildCommand,
this->Quiet);
} else {
std::ostringstream ostr;
@@ -123,16 +123,15 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
}
}
- if (const char* useLaunchers =
- this->Makefile->GetDefinition("CTEST_USE_LAUNCHERS")) {
- this->CTest->SetCTestConfiguration("UseLaunchers", useLaunchers,
+ if (cmProp useLaunchers = this->Makefile->GetDef("CTEST_USE_LAUNCHERS")) {
+ this->CTest->SetCTestConfiguration("UseLaunchers", *useLaunchers,
this->Quiet);
}
- if (const char* labelsForSubprojects =
- this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
+ if (cmProp labelsForSubprojects =
+ this->Makefile->GetDef("CTEST_LABELS_FOR_SUBPROJECTS")) {
this->CTest->SetCTestConfiguration("LabelsForSubprojects",
- labelsForSubprojects, this->Quiet);
+ *labelsForSubprojects, this->Quiet);
}
handler->SetQuiet(this->Quiet);
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index f42c3f1..ac57130 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -12,6 +12,7 @@
#include "cmCTestConfigureHandler.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
@@ -38,16 +39,16 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
return nullptr;
}
- const char* ctestConfigureCommand =
- this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND");
+ cmProp ctestConfigureCommand =
+ this->Makefile->GetDef("CTEST_CONFIGURE_COMMAND");
- if (ctestConfigureCommand && *ctestConfigureCommand) {
+ if (cmNonempty(ctestConfigureCommand)) {
this->CTest->SetCTestConfiguration("ConfigureCommand",
- ctestConfigureCommand, this->Quiet);
+ *ctestConfigureCommand, this->Quiet);
} else {
const char* cmakeGeneratorName =
this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
- if (cmakeGeneratorName && *cmakeGeneratorName) {
+ if (cmNonempty(cmakeGeneratorName)) {
const std::string& source_dir =
this->CTest->GetCTestConfiguration("SourceDirectory");
if (source_dir.empty()) {
@@ -107,7 +108,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
const char* cmakeGeneratorPlatform =
this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_PLATFORM");
- if (cmakeGeneratorPlatform && *cmakeGeneratorPlatform) {
+ if (cmNonempty(cmakeGeneratorPlatform)) {
cmakeConfigureCommand += " \"-A";
cmakeConfigureCommand += cmakeGeneratorPlatform;
cmakeConfigureCommand += "\"";
@@ -115,7 +116,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
const char* cmakeGeneratorToolset =
this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_TOOLSET");
- if (cmakeGeneratorToolset && *cmakeGeneratorToolset) {
+ if (cmNonempty(cmakeGeneratorToolset)) {
cmakeConfigureCommand += " \"-T";
cmakeConfigureCommand += cmakeGeneratorToolset;
cmakeConfigureCommand += "\"";
@@ -125,8 +126,8 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
cmakeConfigureCommand += source_dir;
cmakeConfigureCommand += "\"";
- this->CTest->SetCTestConfiguration(
- "ConfigureCommand", cmakeConfigureCommand.c_str(), this->Quiet);
+ this->CTest->SetCTestConfiguration("ConfigureCommand",
+ cmakeConfigureCommand, this->Quiet);
} else {
this->SetError(
"Configure command is not specified. If this is a "
@@ -136,10 +137,10 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
}
}
- if (const char* labelsForSubprojects =
- this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
+ if (cmProp labelsForSubprojects =
+ this->Makefile->GetDef("CTEST_LABELS_FOR_SUBPROJECTS")) {
this->CTest->SetCTestConfiguration("LabelsForSubprojects",
- labelsForSubprojects, this->Quiet);
+ *labelsForSubprojects, this->Quiet);
}
cmCTestConfigureHandler* handler = this->CTest->GetConfigureHandler();
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index b839c10..093b2d1 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -469,8 +469,8 @@ int cmCTestCoverageHandler::ProcessHandler()
}
const std::string fileName = cmSystemTools::GetFilenameName(fullFileName);
- std::string shortFileName =
- this->CTest->GetShortPathToFile(fullFileName.c_str());
+ const std::string shortFileName =
+ this->CTest->GetShortPathToFile(fullFileName);
const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov =
file.second;
covLogXML.StartElement("File");
@@ -538,7 +538,7 @@ int cmCTestCoverageHandler::ProcessHandler()
covSumXML.StartElement("File");
covSumXML.Attribute("Name", fileName);
covSumXML.Attribute("FullPath",
- this->CTest->GetShortPathToFile(fullFileName.c_str()));
+ this->CTest->GetShortPathToFile(fullFileName));
covSumXML.Attribute("Covered", tested + untested > 0 ? "true" : "false");
covSumXML.Element("LOCTested", tested);
covSumXML.Element("LOCUnTested", untested);
@@ -1887,8 +1887,8 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
// start the file output
covLogXML.StartElement("File");
covLogXML.Attribute("Name", i->first);
- covLogXML.Attribute(
- "FullPath", this->CTest->GetShortPathToFile(i->second.c_str()));
+ covLogXML.Attribute("FullPath",
+ this->CTest->GetShortPathToFile(i->second));
covLogXML.StartElement("Report");
// write the bullseye header
line = 0;
@@ -2064,8 +2064,7 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
total_untested += (totalFunctions - functionsCalled);
std::string fileName = cmSystemTools::GetFilenameName(file);
- std::string shortFileName =
- this->CTest->GetShortPathToFile(file.c_str());
+ std::string shortFileName = this->CTest->GetShortPathToFile(file);
float cper = static_cast<float>(percentBranch + percentFunction);
if (totalBranches > 0) {
@@ -2266,7 +2265,7 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir)
// is the end of the target-wide labels.
inTarget = false;
- source = this->CTest->GetShortPathToFile(line.c_str());
+ source = this->CTest->GetShortPathToFile(line);
// Label the source with the target labels.
LabelSet& labelSet = this->SourceLabels[source];
@@ -2320,7 +2319,7 @@ bool cmCTestCoverageHandler::IsFilteredOut(std::string const& source)
// The source is filtered out if it does not have any labels in
// common with the filter set.
- std::string shortSrc = this->CTest->GetShortPathToFile(source.c_str());
+ std::string shortSrc = this->CTest->GetShortPathToFile(source);
auto li = this->SourceLabels.find(shortSrc);
if (li != this->SourceLabels.end()) {
return !this->IntersectsFilter(li->second);
@@ -2342,14 +2341,14 @@ std::set<std::string> cmCTestCoverageHandler::FindUncoveredFiles(
std::vector<std::string> files = gl.GetFiles();
for (std::string const& f : files) {
if (this->ShouldIDoCoverage(f, cont->SourceDir, cont->BinaryDir)) {
- extraMatches.insert(this->CTest->GetShortPathToFile(f.c_str()));
+ extraMatches.insert(this->CTest->GetShortPathToFile(f));
}
}
}
if (!extraMatches.empty()) {
for (auto const& i : cont->TotalCoverage) {
- std::string shortPath = this->CTest->GetShortPathToFile(i.first.c_str());
+ std::string shortPath = this->CTest->GetShortPathToFile(i.first);
extraMatches.erase(shortPath);
}
}
diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx
index cc0b4ed..a71f550 100644
--- a/Source/CTest/cmCTestGenericHandler.cxx
+++ b/Source/CTest/cmCTestGenericHandler.cxx
@@ -100,7 +100,7 @@ bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part,
<< std::endl);
return false;
}
- this->CTest->AddSubmitFile(part, ostr.str().c_str());
+ this->CTest->AddSubmitFile(part, ostr.str());
return true;
}
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index a755632..03b7173 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -14,6 +14,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
@@ -125,23 +126,21 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
// CTEST_CONFIGURATION_TYPE script variable if it is defined.
// The current script value trumps the -C argument on the command
// line.
- const char* ctestConfigType =
- this->Makefile->GetDefinition("CTEST_CONFIGURATION_TYPE");
+ cmProp ctestConfigType = this->Makefile->GetDef("CTEST_CONFIGURATION_TYPE");
if (ctestConfigType) {
- this->CTest->SetConfigType(ctestConfigType);
+ this->CTest->SetConfigType(*ctestConfigType);
}
if (!this->Build.empty()) {
this->CTest->SetCTestConfiguration(
- "BuildDirectory", cmSystemTools::CollapseFullPath(this->Build).c_str(),
+ "BuildDirectory", cmSystemTools::CollapseFullPath(this->Build),
this->Quiet);
} else {
std::string const& bdir =
this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY");
if (!bdir.empty()) {
this->CTest->SetCTestConfiguration(
- "BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(),
- this->Quiet);
+ "BuildDirectory", cmSystemTools::CollapseFullPath(bdir), this->Quiet);
} else {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"CTEST_BINARY_DIRECTORY not set" << std::endl;);
@@ -151,20 +150,18 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
cmCTestLog(this->CTest, DEBUG,
"Set source directory to: " << this->Source << std::endl);
this->CTest->SetCTestConfiguration(
- "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(),
+ "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source),
this->Quiet);
} else {
this->CTest->SetCTestConfiguration(
"SourceDirectory",
cmSystemTools::CollapseFullPath(
- this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY"))
- .c_str(),
+ this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY")),
this->Quiet);
}
- if (const char* changeId =
- this->Makefile->GetDefinition("CTEST_CHANGE_ID")) {
- this->CTest->SetCTestConfiguration("ChangeId", changeId, this->Quiet);
+ if (cmProp changeId = this->Makefile->GetDef("CTEST_CHANGE_ID")) {
+ this->CTest->SetCTestConfiguration("ChangeId", *changeId, this->Quiet);
}
cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 85b8ab1..8b31e4b 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -326,6 +326,9 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
case cmCTestMemCheckHandler::BOUNDS_CHECKER:
xml.Attribute("Checker", "BoundsChecker");
break;
+ case cmCTestMemCheckHandler::CUDA_MEMCHECK:
+ xml.Attribute("Checker", "CudaMemcheck");
+ break;
case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
xml.Attribute("Checker", "AddressSanitizer");
break;
@@ -351,7 +354,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
cmCTestMemCheckHandler::TestResultsVector::size_type cc;
for (cmCTestTestResult const& result : this->TestResults) {
std::string testPath = result.Path + "/" + result.Name;
- xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
+ xml.Element("Test", this->CTest->GetShortPathToFile(testPath));
}
xml.EndElement(); // TestList
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
@@ -465,6 +468,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
} else if (testerName.find("BC") != std::string::npos) {
this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
+ } else if (testerName.find("cuda-memcheck") != std::string::npos) {
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::CUDA_MEMCHECK;
} else {
this->MemoryTesterStyle = cmCTestMemCheckHandler::UNKNOWN;
}
@@ -485,6 +490,11 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
this->MemoryTester =
this->CTest->GetCTestConfiguration("BoundsCheckerCommand");
this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
+ } else if (cmSystemTools::FileExists(
+ this->CTest->GetCTestConfiguration("CudaMemcheckCommand"))) {
+ this->MemoryTester =
+ this->CTest->GetCTestConfiguration("CudaMemcheckCommand");
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::CUDA_MEMCHECK;
}
if (this->CTest->GetCTestConfiguration("MemoryCheckType") ==
"AddressSanitizer") {
@@ -528,6 +538,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
} else if (checkType == "DrMemory") {
this->MemoryTesterStyle = cmCTestMemCheckHandler::DRMEMORY;
+ } else if (checkType == "CudaMemcheck") {
+ this->MemoryTesterStyle = cmCTestMemCheckHandler::CUDA_MEMCHECK;
}
}
if (this->MemoryTester.empty()) {
@@ -553,6 +565,10 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
.empty()) {
memoryTesterOptions =
this->CTest->GetCTestConfiguration("DrMemoryCommandOptions");
+ } else if (!this->CTest->GetCTestConfiguration("CudaMemcheckCommandOptions")
+ .empty()) {
+ memoryTesterOptions =
+ this->CTest->GetCTestConfiguration("CudaMemcheckCommandOptions");
}
this->MemoryTesterOptions =
cmSystemTools::ParseArguments(memoryTesterOptions);
@@ -686,6 +702,18 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
this->MemoryTesterOptions.emplace_back("/M");
break;
}
+ case cmCTestMemCheckHandler::CUDA_MEMCHECK: {
+ // cuda-memcheck separates flags from arguments by spaces
+ if (this->MemoryTesterOptions.empty()) {
+ this->MemoryTesterOptions.emplace_back("--tool");
+ this->MemoryTesterOptions.emplace_back("memcheck");
+ this->MemoryTesterOptions.emplace_back("--leak-check");
+ this->MemoryTesterOptions.emplace_back("full");
+ }
+ this->MemoryTesterDynamicOptions.emplace_back("--log-file");
+ this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile);
+ break;
+ }
// these are almost the same but the env var used is different
case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
case cmCTestMemCheckHandler::LEAK_SANITIZER:
@@ -771,6 +799,8 @@ bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str,
return this->ProcessMemCheckSanitizerOutput(str, log, results);
case cmCTestMemCheckHandler::BOUNDS_CHECKER:
return this->ProcessMemCheckBoundsCheckerOutput(str, log, results);
+ case cmCTestMemCheckHandler::CUDA_MEMCHECK:
+ return this->ProcessMemCheckCudaOutput(str, log, results);
default:
log.append("\nMemory checking style used was: ");
log.append("None that I know");
@@ -1103,6 +1133,119 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
return defects == 0;
}
+bool cmCTestMemCheckHandler::ProcessMemCheckCudaOutput(
+ const std::string& str, std::string& log, std::vector<int>& results)
+{
+ std::vector<std::string> lines;
+ cmsys::SystemTools::Split(str, lines);
+ bool unlimitedOutput = false;
+ if (str.find("CTEST_FULL_OUTPUT") != std::string::npos ||
+ this->CustomMaximumFailedTestOutputSize == 0) {
+ unlimitedOutput = true;
+ }
+
+ std::string::size_type cc;
+
+ std::ostringstream ostr;
+ log.clear();
+
+ int defects = 0;
+
+ cmsys::RegularExpression memcheckLine("^========");
+
+ cmsys::RegularExpression leakExpr("== Leaked [0-9,]+ bytes at");
+
+ // list of matchers for output messages that contain variable content
+ // (addresses, sizes, ...) or can be shortened in general. the first match is
+ // used as a error name.
+ std::vector<cmsys::RegularExpression> matchers{
+ // API errors
+ "== Malloc/Free error encountered: (.*)",
+ "== Program hit error ([^ ]*).* on CUDA API call to",
+ "== Program hit ([^ ]*).* on CUDA API call to",
+ // memcheck
+ "== (Invalid .*) of size [0-9,]+", "== (Fatal UVM [CG]PU fault)",
+ // racecheck
+ "== .* (Potential .* hazard detected)", "== .* (Race reported)",
+ // synccheck
+ "== (Barrier error)",
+ // initcheck
+ "== (Uninitialized .* memory read)", "== (Unused memory)",
+ "== (Host API memory access error)",
+ // generic error: ignore ERROR SUMMARY, CUDA-MEMCHECK and others
+ "== ([A-Z][a-z].*)"
+ };
+
+ std::vector<std::string::size_type> nonMemcheckOutput;
+ auto sttime = std::chrono::steady_clock::now();
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Start test: " << lines.size() << std::endl, this->Quiet);
+ std::string::size_type totalOutputSize = 0;
+ for (cc = 0; cc < lines.size(); cc++) {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "test line " << lines[cc] << std::endl, this->Quiet);
+
+ if (memcheckLine.find(lines[cc])) {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "cuda-memcheck line " << lines[cc] << std::endl,
+ this->Quiet);
+ int failure = -1;
+ auto& line = lines[cc];
+ if (leakExpr.find(line)) {
+ failure = static_cast<int>(this->FindOrAddWarning("Memory leak"));
+ } else {
+ for (auto& matcher : matchers) {
+ if (matcher.find(line)) {
+ failure =
+ static_cast<int>(this->FindOrAddWarning(matcher.match(1)));
+ break;
+ }
+ }
+ }
+
+ if (failure >= 0) {
+ ostr << "<b>" << this->ResultStrings[failure] << "</b> ";
+ if (results.empty() || unsigned(failure) > results.size() - 1) {
+ results.push_back(1);
+ } else {
+ results[failure]++;
+ }
+ defects++;
+ }
+ totalOutputSize += lines[cc].size();
+ ostr << lines[cc] << std::endl;
+ } else {
+ nonMemcheckOutput.push_back(cc);
+ }
+ }
+ // Now put all all the non cuda-memcheck output into the test output
+ // This should be last in case it gets truncated by the output
+ // limiting code
+ for (std::string::size_type i : nonMemcheckOutput) {
+ totalOutputSize += lines[i].size();
+ ostr << lines[i] << std::endl;
+ if (!unlimitedOutput &&
+ totalOutputSize >
+ static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)) {
+ ostr << "....\n";
+ ostr << "Test Output for this test has been truncated see testing"
+ " machine logs for full output,\n";
+ ostr << "or put CTEST_FULL_OUTPUT in the output of "
+ "this test program.\n";
+ break; // stop the copy of output if we are full
+ }
+ }
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "End test (elapsed: "
+ << cmDurationTo<unsigned int>(
+ std::chrono::steady_clock::now() - sttime)
+ << "s)" << std::endl,
+ this->Quiet);
+ log = ostr.str();
+ this->DefectCount += defects;
+ return defects == 0;
+}
+
// PostProcessTest memcheck results
void cmCTestMemCheckHandler::PostProcessTest(cmCTestTestResult& res, int test)
{
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index 52667f8..63ab573 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -46,6 +46,7 @@ private:
DRMEMORY,
BOUNDS_CHECKER,
// checkers after here do not use the standard error list
+ CUDA_MEMCHECK,
ADDRESS_SANITIZER,
LEAK_SANITIZER,
THREAD_SANITIZER,
@@ -137,6 +138,8 @@ private:
std::vector<int>& results);
bool ProcessMemCheckPurifyOutput(const std::string& str, std::string& log,
std::vector<int>& results);
+ bool ProcessMemCheckCudaOutput(const std::string& str, std::string& log,
+ std::vector<int>& results);
bool ProcessMemCheckSanitizerOutput(const std::string& str, std::string& log,
std::vector<int>& results);
bool ProcessMemCheckBoundsCheckerOutput(const std::string& str,
diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.cxx b/Source/CTest/cmCTestReadCustomFilesCommand.cxx
index ed14d06..a25cca4 100644
--- a/Source/CTest/cmCTestReadCustomFilesCommand.cxx
+++ b/Source/CTest/cmCTestReadCustomFilesCommand.cxx
@@ -15,7 +15,7 @@ bool cmCTestReadCustomFilesCommand::InitialPass(
}
for (std::string const& arg : args) {
- this->CTest->ReadCustomConfigurationFileTree(arg.c_str(), this->Makefile);
+ this->CTest->ReadCustomConfigurationFileTree(arg, this->Makefile);
}
return true;
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 2c8e385..4d65c9b 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -619,11 +619,11 @@ void cmCTestRunTest::ComputeArguments()
cmCTestMemCheckHandler* handler =
static_cast<cmCTestMemCheckHandler*>(this->TestHandler);
this->ActualCommand = handler->MemoryTester;
- this->TestProperties->Args[1] = this->TestHandler->FindTheExecutable(
- this->TestProperties->Args[1].c_str());
+ this->TestProperties->Args[1] =
+ this->TestHandler->FindTheExecutable(this->TestProperties->Args[1]);
} else {
- this->ActualCommand = this->TestHandler->FindTheExecutable(
- this->TestProperties->Args[1].c_str());
+ this->ActualCommand =
+ this->TestHandler->FindTheExecutable(this->TestProperties->Args[1]);
++j; // skip the executable (it will be actualCommand)
}
std::string testCommand =
diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx
index fe68406..6398d66 100644
--- a/Source/CTest/cmCTestStartCommand.cxx
+++ b/Source/CTest/cmCTestStartCommand.cxx
@@ -94,10 +94,9 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
std::string sourceDir = cmSystemTools::CollapseFullPath(src_dir);
std::string binaryDir = cmSystemTools::CollapseFullPath(bld_dir);
- this->CTest->SetCTestConfiguration("SourceDirectory", sourceDir.c_str(),
- this->Quiet);
- this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir.c_str(),
+ this->CTest->SetCTestConfiguration("SourceDirectory", sourceDir,
this->Quiet);
+ this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir, this->Quiet);
if (smodel) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index 279216e..026e98f 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -35,12 +35,12 @@ std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone()
cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
{
- const char* submitURL = !this->SubmitURL.empty()
- ? this->SubmitURL.c_str()
- : this->Makefile->GetDefinition("CTEST_SUBMIT_URL");
+ const std::string* submitURL = !this->SubmitURL.empty()
+ ? &this->SubmitURL
+ : this->Makefile->GetDef("CTEST_SUBMIT_URL");
if (submitURL) {
- this->CTest->SetCTestConfiguration("SubmitURL", submitURL, this->Quiet);
+ this->CTest->SetCTestConfiguration("SubmitURL", *submitURL, this->Quiet);
} else {
this->CTest->SetCTestConfigurationFromCMakeVariable(
this->Makefile, "DropMethod", "CTEST_DROP_METHOD", this->Quiet);
@@ -108,7 +108,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
if (this->PartsMentioned) {
auto parts =
cmMakeRange(this->Parts).transform([this](std::string const& arg) {
- return this->CTest->GetPartFromName(arg.c_str());
+ return this->CTest->GetPartFromName(arg);
});
handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end()));
}
@@ -177,7 +177,7 @@ void cmCTestSubmitCommand::CheckArguments(
!this->Files.empty() || cm::contains(keywords, "FILES");
cm::erase_if(this->Parts, [this](std::string const& arg) -> bool {
- cmCTest::Part p = this->CTest->GetPartFromName(arg.c_str());
+ cmCTest::Part p = this->CTest->GetPartFromName(arg);
if (p == cmCTest::PartCount) {
std::ostringstream e;
e << "Part name \"" << arg << "\" is invalid.";
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index ea36df5..5b54573 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -797,7 +797,7 @@ int cmCTestSubmitHandler::ProcessHandler()
gfile = gfile.substr(glen);
cmCTestOptionalLog(this->CTest, DEBUG,
"Glob file: " << gfile << std::endl, this->Quiet);
- this->CTest->AddSubmitFile(cmCTest::PartCoverage, gfile.c_str());
+ this->CTest->AddSubmitFile(cmCTest::PartCoverage, gfile);
}
} else {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem globbing" << std::endl);
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index c71b409..cbc3c0c 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -13,6 +13,7 @@
#include "cmCTestTestHandler.h"
#include "cmDuration.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
void cmCTestTestCommand::BindArguments()
@@ -116,13 +117,13 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
unsigned long testLoad;
const char* ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD");
if (!this->TestLoad.empty()) {
- if (!cmStrToULong(this->TestLoad.c_str(), &testLoad)) {
+ if (!cmStrToULong(this->TestLoad, &testLoad)) {
testLoad = 0;
cmCTestLog(this->CTest, WARNING,
"Invalid value for 'TEST_LOAD' : " << this->TestLoad
<< std::endl);
}
- } else if (ctestTestLoad && *ctestTestLoad) {
+ } else if (cmNonempty(ctestTestLoad)) {
if (!cmStrToULong(ctestTestLoad, &testLoad)) {
testLoad = 0;
cmCTestLog(this->CTest, WARNING,
@@ -134,10 +135,10 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
}
handler->SetTestLoad(testLoad);
- if (const char* labelsForSubprojects =
- this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
+ if (cmProp labelsForSubprojects =
+ this->Makefile->GetDef("CTEST_LABELS_FOR_SUBPROJECTS")) {
this->CTest->SetCTestConfiguration("LabelsForSubprojects",
- labelsForSubprojects, this->Quiet);
+ *labelsForSubprojects, this->Quiet);
}
handler->SetQuiet(this->Quiet);
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index d0dbaae..70e84ee 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1374,7 +1374,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.StartElement("TestList");
for (cmCTestTestResult const& result : this->TestResults) {
std::string testPath = result.Path + "/" + result.Name;
- xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
+ xml.Element("Test", this->CTest->GetShortPathToFile(testPath));
}
xml.EndElement(); // TestList
for (cmCTestTestResult& result : this->TestResults) {
@@ -1483,8 +1483,8 @@ void cmCTestTestHandler::WriteTestResultHeader(cmXMLWriter& xml,
}
std::string testPath = result.Path + "/" + result.Name;
xml.Element("Name", result.Name);
- xml.Element("Path", this->CTest->GetShortPathToFile(result.Path.c_str()));
- xml.Element("FullName", this->CTest->GetShortPathToFile(testPath.c_str()));
+ xml.Element("Path", this->CTest->GetShortPathToFile(result.Path));
+ xml.Element("FullName", this->CTest->GetShortPathToFile(testPath));
xml.Element("FullCommandLine", result.FullCommandLine);
}
@@ -1546,12 +1546,12 @@ int cmCTestTestHandler::ExecuteCommands(std::vector<std::string>& vec)
}
// Find the appropriate executable to run for a test
-std::string cmCTestTestHandler::FindTheExecutable(const char* exe)
+std::string cmCTestTestHandler::FindTheExecutable(const std::string& exe)
{
std::string resConfig;
std::vector<std::string> extraPaths;
std::vector<std::string> failedPaths;
- if (strcmp(exe, "NOT_AVAILABLE") == 0) {
+ if (exe == "NOT_AVAILABLE") {
return exe;
}
return cmCTestTestHandler::FindExecutable(this->CTest, exe, resConfig,
@@ -1607,7 +1607,7 @@ void cmCTestTestHandler::AddConfigurations(
// Find the appropriate executable to run for a test
std::string cmCTestTestHandler::FindExecutable(
- cmCTest* ctest, const char* testCommand, std::string& resultingConfig,
+ cmCTest* ctest, const std::string& testCommand, std::string& resultingConfig,
std::vector<std::string>& extraPaths, std::vector<std::string>& failed)
{
// now run the compiled test if we can find it
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 0d88c30..b26f8a6 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -198,7 +198,8 @@ public:
std::string filepath, std::string& filename);
// full signature static method to find an executable
- static std::string FindExecutable(cmCTest* ctest, const char* testCommand,
+ static std::string FindExecutable(cmCTest* ctest,
+ const std::string& testCommand,
std::string& resultingConfig,
std::vector<std::string>& extraPaths,
std::vector<std::string>& failed);
@@ -309,7 +310,7 @@ private:
/**
* Find the executable for a test
*/
- std::string FindTheExecutable(const char* exe);
+ std::string FindTheExecutable(const std::string& exe);
std::string GetTestStatus(cmCTestTestResult const&);
void ExpandTestsToRunInformation(size_t numPossibleTests);
diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx
index 673eb9a..95cae13 100644
--- a/Source/CTest/cmCTestUpdateCommand.cxx
+++ b/Source/CTest/cmCTestUpdateCommand.cxx
@@ -11,14 +11,13 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
{
if (!this->Source.empty()) {
this->CTest->SetCTestConfiguration(
- "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(),
+ "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source),
this->Quiet);
} else {
this->CTest->SetCTestConfiguration(
"SourceDirectory",
cmSystemTools::CollapseFullPath(
- this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY"))
- .c_str(),
+ this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY")),
this->Quiet);
}
std::string source_dir =
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index a549117..9ee1c17 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -545,17 +545,17 @@ std::string cmProcess::GetExitExceptionString()
# endif
# ifdef SIGABRT
case SIGABRT:
- exception_str = "Child aborted";
+ exception_str = "Subprocess aborted";
break;
# endif
# ifdef SIGKILL
case SIGKILL:
- exception_str = "Child killed";
+ exception_str = "Subprocess killed";
break;
# endif
# ifdef SIGTERM
case SIGTERM:
- exception_str = "Child terminated";
+ exception_str = "Subprocess terminated";
break;
# endif
# ifdef SIGHUP
diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake
index 50ccc7c..e726fc7 100644
--- a/Source/Checks/cm_cxx_features.cmake
+++ b/Source/Checks/cm_cxx_features.cmake
@@ -63,3 +63,8 @@ if(CMake_HAVE_CXX_MAKE_UNIQUE)
set(CMake_HAVE_CXX_UNIQUE_PTR 1)
endif()
cm_check_cxx_feature(unique_ptr)
+if (NOT CMAKE_CXX_STANDARD LESS "17")
+ cm_check_cxx_feature(filesystem)
+else()
+ set(CMake_HAVE_CXX_FILESYSTEM FALSE)
+endif()
diff --git a/Source/Checks/cm_cxx_filesystem.cxx b/Source/Checks/cm_cxx_filesystem.cxx
new file mode 100644
index 0000000..e508d1c
--- /dev/null
+++ b/Source/Checks/cm_cxx_filesystem.cxx
@@ -0,0 +1,10 @@
+
+#include <filesystem>
+
+int main()
+{
+ std::filesystem::path p1("/a/b/c");
+ std::filesystem::path p2("/a/b/c");
+
+ return p1 == p2 ? 0 : 1;
+}
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index 9a26db5..85e256b 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -2,11 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include <csignal>
+#include <cstdio>
+#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
+#include <unistd.h>
+
#include "cmsys/Encoding.hxx"
#include "cmCursesColor.h"
@@ -54,7 +58,12 @@ void onsig(int /*unused*/)
{
if (cmCursesForm::CurrentForm) {
endwin();
- initscr(); /* Initialization */
+ if (initscr() == nullptr) {
+ static const char errmsg[] = "Error: ncurses initialization failed\n";
+ auto r = write(STDERR_FILENO, errmsg, sizeof(errmsg) - 1);
+ static_cast<void>(r);
+ exit(1);
+ }
noecho(); /* Echo off */
cbreak(); /* nl- or cr not needed */
keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
@@ -124,7 +133,10 @@ int main(int argc, char const* const* argv)
cmCursesForm::DebugStart();
}
- initscr(); /* Initialization */
+ if (initscr() == nullptr) {
+ fprintf(stderr, "Error: ncurses initialization failed\n");
+ exit(1);
+ }
noecho(); /* Echo off */
cbreak(); /* nl- or cr not needed */
keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt
index b468f5b..21c499e 100644
--- a/Source/CursesDialog/form/CMakeLists.txt
+++ b/Source/CursesDialog/form/CMakeLists.txt
@@ -3,6 +3,14 @@
project(CMAKE_FORM)
+# Disable warnings to avoid changing 3rd party code.
+if(CMAKE_C_COMPILER_ID MATCHES
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
+elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
+endif()
+
configure_file(cmFormConfigure.h.in "${CMAKE_CURRENT_BINARY_DIR}/cmFormConfigure.h")
add_library(cmForm
diff --git a/Source/CursesDialog/form/frm_driver.c b/Source/CursesDialog/form/frm_driver.c
index e4e72aa..112ab08 100644
--- a/Source/CursesDialog/form/frm_driver.c
+++ b/Source/CursesDialog/form/frm_driver.c
@@ -2983,7 +2983,7 @@ INLINE static FIELD *Right_Neighbour_Field(FIELD * field)
| Function : static FIELD *Upper_Neighbour_Field(FIELD * field)
|
| Description : Because of the row-major nature of sorting the fields,
-| its more difficult to define whats the upper neighbour
+| its more difficult to define what's the upper neighbour
| field really means. We define that it must be on a
| 'previous' line (cyclic order!) and is the rightmost
| field laying on the left side of the given field. If
@@ -3030,7 +3030,7 @@ static FIELD *Upper_Neighbour_Field(FIELD * field)
| Function : static FIELD *Down_Neighbour_Field(FIELD * field)
|
| Description : Because of the row-major nature of sorting the fields,
-| its more difficult to define whats the down neighbour
+| its more difficult to define what's the down neighbour
| field really means. We define that it must be on a
| 'next' line (cyclic order!) and is the leftmost
| field laying on the right side of the given field. If
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 98dd0e2..e6d6b17 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -3,111 +3,79 @@
project(QtDialog)
CMake_OPTIONAL_COMPONENT(cmake-gui)
-find_package(Qt5Widgets QUIET)
-if (Qt5Widgets_FOUND)
- include_directories(${Qt5Widgets_INCLUDE_DIRS})
- add_definitions(${Qt5Widgets_DEFINITONS})
- macro(qt4_wrap_ui)
- qt5_wrap_ui(${ARGN})
- endmacro()
- macro(qt4_wrap_cpp)
- qt5_wrap_cpp(${ARGN})
- endmacro()
- macro(qt4_add_resources)
- qt5_add_resources(${ARGN})
- endmacro()
+find_package(Qt5Widgets REQUIRED)
- set(CMake_QT_LIBRARIES ${Qt5Widgets_LIBRARIES})
- set(QT_QTMAIN_LIBRARY ${Qt5Core_QTMAIN_LIBRARIES})
+set(CMake_QT_EXTRA_LIBRARIES)
- # Try to find the package WinExtras for the task bar progress
- if(WIN32)
- find_package(Qt5WinExtras QUIET)
- if (Qt5WinExtras_FOUND)
- include_directories(${Qt5WinExtras_INCLUDE_DIRS})
- add_definitions(-DQT_WINEXTRAS)
- list(APPEND CMake_QT_LIBRARIES ${Qt5WinExtras_LIBRARIES})
- endif()
+# Try to find the package WinExtras for the task bar progress
+if(WIN32)
+ find_package(Qt5WinExtras QUIET)
+ if (Qt5WinExtras_FOUND)
+ add_definitions(-DQT_WINEXTRAS)
+ list(APPEND CMake_QT_EXTRA_LIBRARIES Qt5::WinExtras)
endif()
+endif()
- # Remove this when the minimum version of Qt is 4.6.
- add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0)
-
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
- if(CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES)
- list(APPEND CMake_QT_LIBRARIES ${CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES})
- set_property(SOURCE CMakeSetup.cxx
- PROPERTY COMPILE_DEFINITIONS USE_QXcbIntegrationPlugin)
- endif()
+if(CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES)
+ list(APPEND CMake_QT_EXTRA_LIBRARIES ${CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES})
+ set_property(SOURCE CMakeSetup.cxx
+ PROPERTY COMPILE_DEFINITIONS USE_QXcbIntegrationPlugin)
+endif()
- if(CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
- list(APPEND CMake_QT_LIBRARIES ${CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES})
- set_property(SOURCE CMakeSetup.cxx
- PROPERTY COMPILE_DEFINITIONS USE_QWindowsIntegrationPlugin)
- endif()
+if(CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
+ list(APPEND CMake_QT_EXTRA_LIBRARIES ${CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES})
+ set_property(SOURCE CMakeSetup.cxx
+ PROPERTY COMPILE_DEFINITIONS USE_QWindowsIntegrationPlugin)
+endif()
- # We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows.
- # FIXME: This should be part of Qt5 CMake scripts, but unfortunately
- # Qt5 support is missing there.
- if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
- macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var)
- get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION)
- if(EXISTS "${_qt_plugin_path}")
- get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME)
- get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH)
- get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME)
- if(APPLE)
- set(_qt_plugin_dir "PlugIns")
- elseif(WIN32)
- set(_qt_plugin_dir "plugins")
- endif()
- set(_qt_plugin_dest "${_qt_plugin_dir}/${_qt_plugin_type}")
- install(FILES "${_qt_plugin_path}"
- DESTINATION "${_qt_plugin_dest}"
- ${COMPONENT})
- set(${_qt_plugins_var}
- "${${_qt_plugins_var}};\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}")
- else()
- message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found")
+# We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows.
+# FIXME: This should be part of Qt5 CMake scripts, but unfortunately
+# Qt5 support is missing there.
+if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
+ macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var)
+ get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION)
+ if(EXISTS "${_qt_plugin_path}")
+ get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME)
+ get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH)
+ get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME)
+ if(APPLE)
+ set(_qt_plugin_dir "PlugIns")
+ elseif(WIN32)
+ set(_qt_plugin_dir "plugins")
endif()
- endmacro()
- if(APPLE)
- install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS)
- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
- "[Paths]\nPlugins = ${_qt_plugin_dir}\n")
- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
- DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources"
+ set(_qt_plugin_dest "${_qt_plugin_dir}/${_qt_plugin_type}")
+ install(FILES "${_qt_plugin_path}"
+ DESTINATION "${_qt_plugin_dest}"
${COMPONENT})
- elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
- install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS)
- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
- "[Paths]\nPlugins = ../${_qt_plugin_dir}\n")
- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
- DESTINATION bin
- ${COMPONENT})
- endif()
- endif()
-
- if(TARGET Qt5::Core)
- get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION)
- get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH)
- if(APPLE)
- get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH)
+ set(${_qt_plugins_var}
+ "${${_qt_plugins_var}};\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}")
+ else()
+ message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found")
endif()
+ endmacro()
+ if(APPLE)
+ install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS)
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ "[Paths]\nPlugins = ${_qt_plugin_dir}\n")
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources"
+ ${COMPONENT})
+ elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
+ install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS)
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ "[Paths]\nPlugins = ../${_qt_plugin_dir}\n")
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
+ DESTINATION bin
+ ${COMPONENT})
endif()
-else()
- set(QT_MIN_VERSION "4.4.0")
- find_package(Qt4 REQUIRED)
- if(NOT QT4_FOUND)
- message(SEND_ERROR "Failed to find Qt 4.4 or greater.")
- return()
- endif()
-
- include(${QT_USE_FILE})
-
- set(CMake_QT_LIBRARIES ${QT_LIBRARIES})
+endif()
+get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION)
+get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH)
+if(APPLE)
+ get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH)
endif()
set(SRCS
@@ -116,6 +84,7 @@ set(SRCS
CMakeSetup.cxx
CMakeSetupDialog.cxx
CMakeSetupDialog.h
+ Compilers.h
FirstConfigure.cxx
FirstConfigure.h
QCMake.cxx
@@ -129,7 +98,7 @@ set(SRCS
WarningMessagesDialog.cxx
WarningMessagesDialog.h
)
-QT4_WRAP_UI(UI_SRCS
+qt5_wrap_ui(UI_SRCS
CMakeSetupDialog.ui
Compilers.ui
CrossCompiler.ui
@@ -137,7 +106,7 @@ QT4_WRAP_UI(UI_SRCS
RegexExplorer.ui
WarningMessagesDialog.ui
)
-QT4_WRAP_CPP(MOC_SRCS
+qt5_wrap_cpp(MOC_SRCS
AddCacheEntry.h
Compilers.h
CMakeSetupDialog.h
@@ -148,14 +117,24 @@ QT4_WRAP_CPP(MOC_SRCS
RegexExplorer.h
WarningMessagesDialog.h
)
-QT4_ADD_RESOURCES(RC_SRCS CMakeSetup.qrc)
+qt5_add_resources(RC_SRCS CMakeSetup.qrc)
+
+if (FALSE) # CMake's bootstrap binary does not support automoc
+ set(CMAKE_AUTOMOC 1)
+ set(CMAKE_AUTORCC 1)
+ set(CMAKE_AUTOUIC 1)
+else ()
+ list(APPEND SRCS
+ ${UI_SRCS}
+ ${MOC_SRCS}
+ ${RC_SRCS})
+endif ()
-set(SRCS ${SRCS} ${UI_SRCS} ${MOC_SRCS} ${RC_SRCS})
if(WIN32)
- set(SRCS ${SRCS} CMakeSetup.rc)
+ list(APPEND SRCS CMakeSetup.rc)
endif()
if(APPLE)
- set(SRCS ${SRCS} CMakeSetup.icns)
+ list(APPEND SRCS CMakeSetup.icns)
set(MACOSX_BUNDLE_ICON_FILE CMakeSetup.icns)
set_source_files_properties(CMakeSetup.icns PROPERTIES
MACOSX_PACKAGE_LOCATION Resources)
@@ -172,7 +151,7 @@ endif()
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE})
-target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES})
+target_link_libraries(cmake-gui CMakeLib Qt5::Core Qt5::Widgets ${CMake_QT_EXTRA_LIBRARIES})
if(WIN32)
target_sources(cmake-gui PRIVATE $<TARGET_OBJECTS:CMakeVersion>)
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index 9d928b2..7ef5a72 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -115,14 +115,6 @@ int main(int argc, char** argv)
QTextCodec* utf8_codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(utf8_codec);
-#if QT_VERSION < 0x050000
- // clean out standard Qt paths for plugins, which we don't use anyway
- // when creating Mac bundles, it potentially causes problems
- foreach (QString p, QApplication::libraryPaths()) {
- QApplication::removeLibraryPath(p);
- }
-#endif
-
// tell the cmake library where cmake is
QDir cmExecDir(QApplication::applicationDirPath());
#if defined(Q_OS_MAC)
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 6dbfe11..fcc8408 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -152,9 +152,6 @@ CMakeSetupDialog::CMakeSetupDialog()
this->WarnUninitializedAction =
OptionsMenu->addAction(tr("&Warn Uninitialized (--warn-uninitialized)"));
this->WarnUninitializedAction->setCheckable(true);
- this->WarnUnusedAction =
- OptionsMenu->addAction(tr("&Warn Unused (--warn-unused-vars)"));
- this->WarnUnusedAction->setCheckable(true);
QAction* debugAction = OptionsMenu->addAction(tr("&Debug Output"));
debugAction->setCheckable(true);
@@ -290,9 +287,6 @@ void CMakeSetupDialog::initialize()
QObject::connect(this->WarnUninitializedAction, SIGNAL(triggered(bool)),
this->CMakeThread->cmakeInstance(),
SLOT(setWarnUninitializedMode(bool)));
- QObject::connect(this->WarnUnusedAction, SIGNAL(triggered(bool)),
- this->CMakeThread->cmakeInstance(),
- SLOT(setWarnUnusedMode(bool)));
if (!this->SourceDirectory->text().isEmpty() ||
!this->BinaryDirectory->lineEdit()->text().isEmpty()) {
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index d1e2035..914be12 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -111,7 +111,6 @@ protected:
QAction* ConfigureAction;
QAction* GenerateAction;
QAction* WarnUninitializedAction;
- QAction* WarnUnusedAction;
QAction* InstallForCommandLineAction;
State CurrentState;
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index 776af81..6090256 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -21,7 +21,6 @@ QCMake::QCMake(QObject* p)
: QObject(p)
{
this->WarnUninitializedMode = false;
- this->WarnUnusedMode = false;
qRegisterMetaType<QCMakeProperty>();
qRegisterMetaType<QCMakePropertyList>();
@@ -170,7 +169,6 @@ void QCMake::configure()
this->CMakeInstance->SetGeneratorToolset(this->Toolset.toLocal8Bit().data());
this->CMakeInstance->LoadCache();
this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode);
- this->CMakeInstance->SetWarnUnused(this->WarnUnusedMode);
this->CMakeInstance->PreLoadCMakeFiles();
InterruptFlag = 0;
@@ -340,10 +338,10 @@ void QCMake::interrupt()
bool QCMake::interruptCallback()
{
-#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
- return this->InterruptFlag;
-#else
+#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
return this->InterruptFlag.load();
+#else
+ return this->InterruptFlag.loadRelaxed();
#endif
}
@@ -478,11 +476,6 @@ void QCMake::setWarnUninitializedMode(bool value)
this->WarnUninitializedMode = value;
}
-void QCMake::setWarnUnusedMode(bool value)
-{
- this->WarnUnusedMode = value;
-}
-
void QCMake::checkOpenPossible()
{
std::string data = this->BinaryDirectory.toLocal8Bit().data();
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
index 110a971..39555d6 100644
--- a/Source/QtDialog/QCMake.h
+++ b/Source/QtDialog/QCMake.h
@@ -114,8 +114,6 @@ public slots:
void setDeprecatedWarningsAsErrors(bool value);
/// set whether to run cmake with warnings about uninitialized variables
void setWarnUninitializedMode(bool value);
- /// set whether to run cmake with warnings about unused variables
- void setWarnUnusedMode(bool value);
/// check if project IDE open is possible and emit openPossible signal
void checkOpenPossible();
@@ -175,8 +173,6 @@ protected:
void stderrCallback(std::string const& msg);
bool WarnUninitializedMode;
- bool WarnUnusedMode;
- bool WarnUnusedAllMode;
QString SourceDirectory;
QString BinaryDirectory;
QString Generator;
diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx
index 9b24fbd..3bf4409 100644
--- a/Source/QtDialog/QCMakeCacheView.cxx
+++ b/Source/QtDialog/QCMakeCacheView.cxx
@@ -155,11 +155,7 @@ QModelIndex QCMakeCacheView::moveCursor(CursorAction act,
void QCMakeCacheView::setShowAdvanced(bool s)
{
-#if QT_VERSION >= 040300
- // new 4.3 API that needs to be called. what about an older Qt?
this->SearchFilter->invalidate();
-#endif
-
this->AdvancedFilter->setShowAdvanced(s);
}
@@ -209,9 +205,7 @@ void QCMakeCacheModel::clear()
void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
{
-#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
this->beginResetModel();
-#endif
QSet<QCMakeProperty> newProps;
QSet<QCMakeProperty> newProps2;
@@ -335,11 +329,7 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
}
this->blockSignals(b);
-#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
this->endResetModel();
-#else
- this->reset();
-#endif
}
QCMakeCacheModel::ViewType QCMakeCacheModel::viewType() const
@@ -349,9 +339,7 @@ QCMakeCacheModel::ViewType QCMakeCacheModel::viewType() const
void QCMakeCacheModel::setViewType(QCMakeCacheModel::ViewType t)
{
-#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
this->beginResetModel();
-#endif
this->View = t;
@@ -368,11 +356,7 @@ void QCMakeCacheModel::setViewType(QCMakeCacheModel::ViewType t)
this->setProperties(oldProps);
this->setProperties(props);
this->blockSignals(b);
-#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
this->endResetModel();
-#else
- this->reset();
-#endif
}
void QCMakeCacheModel::setPropertyData(const QModelIndex& idx1,
@@ -498,8 +482,7 @@ QCMakePropertyList QCMakeCacheModel::properties() const
// go to the next in the tree
while (!idxs.isEmpty() &&
(
-#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && \
- QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
(idxs.last().row() + 1) >= rowCount(idxs.last().parent()) ||
#endif
!idxs.last().sibling(idxs.last().row() + 1, 0).isValid())) {
@@ -659,20 +642,6 @@ bool QCMakeCacheModelDelegate::editorEvent(QEvent* e,
return success;
}
-// Issue 205903 fixed in Qt 4.5.0.
-// Can remove this function and FileDialogFlag when minimum Qt version is 4.5
-bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* evt)
-{
- // workaround for what looks like a bug in Qt on macOS
- // where it doesn't create a QWidget wrapper for the native file dialog
- // so the Qt library ends up assuming the focus was lost to something else
-
- if (evt->type() == QEvent::FocusOut && this->FileDialogFlag) {
- return false;
- }
- return QItemDelegate::eventFilter(object, evt);
-}
-
void QCMakeCacheModelDelegate::setModelData(QWidget* editor,
QAbstractItemModel* model,
const QModelIndex& index) const
diff --git a/Source/QtDialog/QCMakeCacheView.h b/Source/QtDialog/QCMakeCacheView.h
index bea1965..a252708 100644
--- a/Source/QtDialog/QCMakeCacheView.h
+++ b/Source/QtDialog/QCMakeCacheView.h
@@ -144,7 +144,6 @@ public:
bool editorEvent(QEvent* event, QAbstractItemModel* model,
const QStyleOptionViewItem& option,
const QModelIndex& index);
- bool eventFilter(QObject* object, QEvent* event);
void setModelData(QWidget* editor, QAbstractItemModel* model,
const QModelIndex& index) const;
QSize sizeHint(const QStyleOptionViewItem& option,
diff --git a/Source/QtDialog/QCMakeWidgets.cxx b/Source/QtDialog/QCMakeWidgets.cxx
index 332a770..d16ea58 100644
--- a/Source/QtDialog/QCMakeWidgets.cxx
+++ b/Source/QtDialog/QCMakeWidgets.cxx
@@ -4,9 +4,9 @@
#include <utility>
-#include <QDirModel>
#include <QFileDialog>
#include <QFileInfo>
+#include <QFileSystemModel>
#include <QResizeEvent>
#include <QToolButton>
@@ -88,20 +88,20 @@ void QCMakePathEditor::chooseFile()
}
}
-// use same QDirModel for all completers
-static QDirModel* fileDirModel()
+// use same QFileSystemModel for all completers
+static QFileSystemModel* fileDirModel()
{
- static QDirModel* m = nullptr;
+ static QFileSystemModel* m = nullptr;
if (!m) {
- m = new QDirModel();
+ m = new QFileSystemModel();
}
return m;
}
-static QDirModel* pathDirModel()
+static QFileSystemModel* pathDirModel()
{
- static QDirModel* m = nullptr;
+ static QFileSystemModel* m = nullptr;
if (!m) {
- m = new QDirModel();
+ m = new QFileSystemModel();
m->setFilter(QDir::AllDirs | QDir::Drives | QDir::NoDotAndDotDot);
}
return m;
@@ -110,7 +110,7 @@ static QDirModel* pathDirModel()
QCMakeFileCompleter::QCMakeFileCompleter(QObject* o, bool dirs)
: QCompleter(o)
{
- QDirModel* m = dirs ? pathDirModel() : fileDirModel();
+ QFileSystemModel* m = dirs ? pathDirModel() : fileDirModel();
this->setModel(m);
}
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index 3e5d764..f262fac 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -2,8 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddLibraryCommand.h"
-#include <cmext/algorithm>
-
#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
@@ -111,20 +109,10 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
"INTERFACE library specified with conflicting ALIAS type.");
return false;
}
- if (excludeFromAll) {
- status.SetError(
- "INTERFACE library may not be used with EXCLUDE_FROM_ALL.");
- return false;
- }
++s;
type = cmStateEnums::INTERFACE_LIBRARY;
haveSpecifiedType = true;
} else if (*s == "EXCLUDE_FROM_ALL") {
- if (type == cmStateEnums::INTERFACE_LIBRARY) {
- status.SetError(
- "INTERFACE library may not be used with EXCLUDE_FROM_ALL.");
- return false;
- }
++s;
excludeFromAll = true;
} else if (*s == "IMPORTED") {
@@ -143,10 +131,6 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
}
if (type == cmStateEnums::INTERFACE_LIBRARY) {
- if (s != args.end()) {
- status.SetError("INTERFACE library requires no source arguments.");
- return false;
- }
if (importGlobal && !importTarget) {
status.SetError(
"INTERFACE library specified as GLOBAL, but not as IMPORTED.");
@@ -302,8 +286,6 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
}
}
- std::vector<std::string> srclists;
-
if (type == cmStateEnums::INTERFACE_LIBRARY) {
if (!cmGeneratorExpression::IsValidTargetName(libName) ||
libName.find("::") != std::string::npos) {
@@ -311,14 +293,10 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
cmStrCat("Invalid name for INTERFACE library target: ", libName));
return false;
}
-
- mf.AddLibrary(libName, type, srclists, excludeFromAll);
- return true;
}
- cm::append(srclists, s, args.end());
-
- mf.AddLibrary(libName, type, srclists, excludeFromAll);
+ std::vector<std::string> srcs(s, args.end());
+ mf.AddLibrary(libName, type, srcs, excludeFromAll);
return true;
}
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index d6f7500e..53d4cb4 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -55,7 +55,7 @@ bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args,
auto ext = cm::string_view(file).substr(dotpos + 1);
// Process only source files
auto cm = mf.GetCMakeInstance();
- if (dotpos > 0 && cm->IsSourceExtension(ext)) {
+ if (dotpos > 0 && cm->IsACLikeSourceExtension(ext)) {
std::string fullname = cmStrCat(templateDirectory, '/', file);
// add the file as a class file so
// depends can be done
diff --git a/Source/cmCMakeLanguageCommand.h b/Source/cmCMakeLanguageCommand.h
index 7306515..aeb8f60 100644
--- a/Source/cmCMakeLanguageCommand.h
+++ b/Source/cmCMakeLanguageCommand.h
@@ -11,7 +11,7 @@ class cmExecutionStatus;
struct cmListFileArgument;
/**
- * \brief Calls a scripted or build-in command
+ * \brief Calls a scripted or built-in command
*
*/
bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index bca7540..a5fde89 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -394,7 +394,7 @@ bool cmCTest::ShouldCompressTestOutput()
return this->Impl->CompressTestOutput;
}
-cmCTest::Part cmCTest::GetPartFromName(const char* name)
+cmCTest::Part cmCTest::GetPartFromName(const std::string& name)
{
// Look up by lower-case to make names case-insensitive.
std::string lower_name = cmSystemTools::LowerCase(name);
@@ -458,8 +458,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cmGlobalGenerator gg(&cm);
cmMakefile mf(&gg, cm.GetCurrentSnapshot());
- if (!this->ReadCustomConfigurationFileTree(this->Impl->BinaryDir.c_str(),
- &mf)) {
+ if (!this->ReadCustomConfigurationFileTree(this->Impl->BinaryDir, &mf)) {
cmCTestOptionalLog(
this, DEBUG, "Cannot find custom configuration file tree" << std::endl,
quiet);
@@ -523,7 +522,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
std::string model;
if (cmSystemTools::GetLineFromStream(tfin, model) &&
!this->Impl->Parts[PartStart] && !command) {
- this->Impl->TestModel = GetTestModelFromString(model.c_str());
+ this->Impl->TestModel = GetTestModelFromString(model);
}
tfin.close();
}
@@ -579,7 +578,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
cmSystemTools::GetLineFromStream(tfin, tag);
cmSystemTools::GetLineFromStream(tfin, group);
if (cmSystemTools::GetLineFromStream(tfin, modelStr)) {
- model = GetTestModelFromString(modelStr.c_str());
+ model = GetTestModelFromString(modelStr);
}
tfin.close();
}
@@ -793,7 +792,7 @@ int cmCTest::GetTestModel() const
return this->Impl->TestModel;
}
-bool cmCTest::SetTest(const char* ttype, bool report)
+bool cmCTest::SetTest(const std::string& ttype, bool report)
{
if (cmSystemTools::LowerCase(ttype) == "all") {
for (Part p = PartStart; p != PartCount; p = Part(p + 1)) {
@@ -841,6 +840,7 @@ bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name,
}
}
std::string filename = testingDir + "/" + name;
+ stream.SetTempExt("tmp");
stream.Open(filename);
if (!stream) {
cmCTestLog(this, ERROR_MESSAGE,
@@ -855,7 +855,7 @@ bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name,
return true;
}
-bool cmCTest::AddIfExists(Part part, const char* file)
+bool cmCTest::AddIfExists(Part part, const std::string& file)
{
if (this->CTestFileExists(file)) {
this->AddSubmitFile(part, file);
@@ -1007,7 +1007,7 @@ int cmCTest::ProcessSteps()
if (this->Impl->Parts[PartNotes]) {
this->UpdateCTestConfiguration();
if (!this->Impl->NotesFiles.empty()) {
- this->GenerateNotesFile(this->Impl->NotesFiles.c_str());
+ this->GenerateNotesFile(this->Impl->NotesFiles);
}
}
if (this->Impl->Parts[PartSubmit]) {
@@ -1036,9 +1036,9 @@ std::string cmCTest::GetTestModelString()
return "Experimental";
}
-int cmCTest::GetTestModelFromString(const char* str)
+int cmCTest::GetTestModelFromString(const std::string& str)
{
- if (!str) {
+ if (str.empty()) {
return cmCTest::EXPERIMENTAL;
}
std::string rstr = cmSystemTools::LowerCase(str);
@@ -1564,9 +1564,9 @@ int cmCTest::GenerateNotesFile(std::vector<std::string> const& files)
return 0;
}
-int cmCTest::GenerateNotesFile(const char* cfiles)
+int cmCTest::GenerateNotesFile(const std::string& cfiles)
{
- if (!cfiles) {
+ if (cfiles.empty()) {
return 1;
}
@@ -1649,14 +1649,14 @@ bool cmCTest::SubmitExtraFiles(std::vector<std::string> const& files)
<< std::endl;);
return false;
}
- this->AddSubmitFile(PartExtraFiles, file.c_str());
+ this->AddSubmitFile(PartExtraFiles, file);
}
return true;
}
-bool cmCTest::SubmitExtraFiles(const char* cfiles)
+bool cmCTest::SubmitExtraFiles(const std::string& cfiles)
{
- if (!cfiles) {
+ if (cfiles.empty()) {
return true;
}
@@ -1940,7 +1940,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
else if (this->CheckArgument(arg, "-C"_s, "--build-config") &&
i < args.size() - 1) {
i++;
- this->SetConfigType(args[i].c_str());
+ this->SetConfigType(args[i]);
}
else if (this->CheckArgument(arg, "--debug"_s)) {
@@ -2015,7 +2015,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
else if (this->CheckArgument(arg, "-O"_s, "--output-log") &&
i < args.size() - 1) {
i++;
- this->SetOutputLogFileName(args[i].c_str());
+ this->SetOutputLogFileName(args[i]);
}
else if (this->CheckArgument(arg, "--tomorrow-tag"_s)) {
@@ -2047,7 +2047,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
this->Impl->ProduceXML = true;
this->SetTest("Notes");
i++;
- this->SetNotesFiles(args[i].c_str());
+ this->SetNotesFiles(args[i]);
return true;
}
@@ -2304,7 +2304,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
this->Impl->ProduceXML = true;
this->SetTest("Submit");
i++;
- if (!this->SubmitExtraFiles(args[i].c_str())) {
+ if (!this->SubmitExtraFiles(args[i])) {
return 0;
}
}
@@ -2375,7 +2375,7 @@ bool cmCTest::HandleTestActionArgument(const char* ctestExec, size_t& i,
(i < args.size() - 1)) {
this->Impl->ProduceXML = true;
i++;
- if (!this->SetTest(args[i].c_str(), false)) {
+ if (!this->SetTest(args[i], false)) {
success = false;
cmCTestLog(this, ERROR_MESSAGE,
"CTest -T called with incorrect option: " << args[i]
@@ -2490,11 +2490,8 @@ int cmCTest::RunCMakeAndTest(std::string* output)
return retv;
}
-void cmCTest::SetNotesFiles(const char* notes)
+void cmCTest::SetNotesFiles(const std::string& notes)
{
- if (!notes) {
- return;
- }
this->Impl->NotesFiles = notes;
}
@@ -2560,7 +2557,8 @@ void cmCTest::SetScheduleType(std::string const& type)
this->Impl->ScheduleType = type;
}
-int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
+int cmCTest::ReadCustomConfigurationFileTree(const std::string& dir,
+ cmMakefile* mf)
{
bool found = false;
cmCTestLog(this, DEBUG,
@@ -2647,7 +2645,7 @@ void cmCTest::PopulateCustomInteger(cmMakefile* mf, const std::string& def,
val = atoi(dval);
}
-std::string cmCTest::GetShortPathToFile(const char* cfname)
+std::string cmCTest::GetShortPathToFile(const std::string& cfname)
{
const std::string& sourceDir = cmSystemTools::CollapseFullPath(
this->GetCTestConfiguration("SourceDirectory"));
@@ -2711,18 +2709,17 @@ void cmCTest::EmptyCTestConfiguration()
this->Impl->CTestConfiguration.clear();
}
-void cmCTest::SetCTestConfiguration(const char* name, const char* value,
+void cmCTest::SetCTestConfiguration(const char* name, const std::string& value,
bool suppress)
{
cmCTestOptionalLog(this, HANDLER_VERBOSE_OUTPUT,
- "SetCTestConfiguration:"
- << name << ":" << (value ? value : "(null)") << "\n",
+ "SetCTestConfiguration:" << name << ":" << value << "\n",
suppress);
if (!name) {
return;
}
- if (!value) {
+ if (value.empty()) {
this->Impl->CTestConfiguration.erase(name);
return;
}
@@ -2927,7 +2924,7 @@ std::string cmCTest::GetBuildID() const
return this->Impl->BuildID;
}
-void cmCTest::AddSubmitFile(Part part, const char* name)
+void cmCTest::AddSubmitFile(Part part, const std::string& name)
{
this->Impl->Parts[part].SubmitFiles.emplace_back(name);
}
@@ -2963,9 +2960,9 @@ void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr)
this->Impl->CTestConfigurationOverwrites[key] = value;
}
-void cmCTest::SetConfigType(const char* ct)
+void cmCTest::SetConfigType(const std::string& ct)
{
- this->Impl->ConfigType = ct ? ct : "";
+ this->Impl->ConfigType = ct;
cmSystemTools::ReplaceString(this->Impl->ConfigType, ".\\", "");
std::string confTypeEnv = "CMAKE_CONFIG_TYPE=" + this->Impl->ConfigType;
cmSystemTools::PutEnv(confTypeEnv);
@@ -2975,8 +2972,7 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable(
cmMakefile* mf, const char* dconfig, const std::string& cmake_var,
bool suppress)
{
- const char* ctvar;
- ctvar = mf->GetDefinition(cmake_var);
+ cmProp ctvar = mf->GetDef(cmake_var);
if (!ctvar) {
return false;
}
@@ -2984,7 +2980,7 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable(
"SetCTestConfigurationFromCMakeVariable:"
<< dconfig << ":" << cmake_var << std::endl,
suppress);
- this->SetCTestConfiguration(dconfig, ctvar, suppress);
+ this->SetCTestConfiguration(dconfig, *ctvar, suppress);
return true;
}
@@ -3085,9 +3081,9 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args,
return result;
}
-void cmCTest::SetOutputLogFileName(const char* name)
+void cmCTest::SetOutputLogFileName(const std::string& name)
{
- if (name) {
+ if (!name.empty()) {
this->Impl->OutputLogFile = cm::make_unique<cmGeneratedFileStream>(name);
} else {
this->Impl->OutputLogFile.reset();
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index a39b8fe..1e0fb8c 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -64,7 +64,7 @@ public:
/** Get a testing part id from its string name. Returns PartCount
if the string does not name a valid part. */
- Part GetPartFromName(const char* name);
+ Part GetPartFromName(const std::string& name);
/** Process Command line arguments */
int Run(std::vector<std::string>&, std::string* output = nullptr);
@@ -127,12 +127,12 @@ public:
* Check if CTest file exists
*/
bool CTestFileExists(const std::string& filename);
- bool AddIfExists(Part part, const char* file);
+ bool AddIfExists(Part part, const std::string& file);
/**
* Set the cmake test
*/
- bool SetTest(const char*, bool report = true);
+ bool SetTest(const std::string&, bool report = true);
/**
* Set the cmake test mode (experimental, nightly, continuous).
@@ -141,11 +141,11 @@ public:
int GetTestModel() const;
std::string GetTestModelString();
- static int GetTestModelFromString(const char* str);
+ static int GetTestModelFromString(const std::string& str);
static std::string CleanString(const std::string& str,
std::string::size_type spos = 0);
std::string GetCTestConfiguration(const std::string& name);
- void SetCTestConfiguration(const char* name, const char* value,
+ void SetCTestConfiguration(const char* name, const std::string& value,
bool suppress = false);
void EmptyCTestConfiguration();
@@ -161,7 +161,7 @@ public:
cmCTest& operator=(const cmCTest&) = delete;
/** Set the notes files to be created. */
- void SetNotesFiles(const char* notes);
+ void SetNotesFiles(const std::string& notes);
void PopulateCustomVector(cmMakefile* mf, const std::string& definition,
std::vector<std::string>& vec);
@@ -272,7 +272,7 @@ public:
* This means if the file is in binary or
* source directory, it will become /.../relative/path/to/file
*/
- std::string GetShortPathToFile(const char* fname);
+ std::string GetShortPathToFile(const std::string& fname);
enum
{
@@ -354,14 +354,14 @@ public:
int GenerateDoneFile();
/** Submit extra files to the server */
- bool SubmitExtraFiles(const char* files);
+ bool SubmitExtraFiles(const std::string& files);
bool SubmitExtraFiles(std::vector<std::string> const& files);
/** Set the output log file name */
- void SetOutputLogFileName(const char* name);
+ void SetOutputLogFileName(const std::string& name);
/** Set the visual studio or Xcode config type */
- void SetConfigType(const char* ct);
+ void SetConfigType(const std::string& ct);
/** Various log types */
enum
@@ -399,14 +399,14 @@ public:
std::string GetBuildID() const;
/** Add file to be submitted */
- void AddSubmitFile(Part part, const char* name);
+ void AddSubmitFile(Part part, const std::string& name);
std::vector<std::string> const& GetSubmitFiles(Part part) const;
void ClearSubmitFiles(Part part);
/**
* Read the custom configuration files and apply them to the current ctest
*/
- int ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf);
+ int ReadCustomConfigurationFileTree(const std::string& dir, cmMakefile* mf);
std::vector<std::string>& GetInitialCommandLineArguments();
@@ -462,7 +462,7 @@ public:
void SetRunCurrentScript(bool value);
private:
- int GenerateNotesFile(const char* files);
+ int GenerateNotesFile(const std::string& files);
void BlockTestErrorDiagnostics();
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 35bd681..95686ea 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -578,10 +578,7 @@ cmProp cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const
bool cmCacheManager::CacheEntry::GetPropertyAsBool(
const std::string& prop) const
{
- if (cmProp value = this->GetProperty(prop)) {
- return cmIsOn(*value);
- }
- return false;
+ return cmIsOn(this->GetProperty(prop));
}
void cmCacheManager::CacheEntry::SetProperty(const std::string& prop,
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 051eff6..8aee27c 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -41,7 +41,7 @@ std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const
const char* cmCommonTargetGenerator::GetFeature(const std::string& feature,
const std::string& config)
{
- return this->GeneratorTarget->GetFeature(feature, config);
+ return this->GeneratorTarget->GetFeature(feature, config)->c_str();
}
void cmCommonTargetGenerator::AddModuleDefinitionFlag(
diff --git a/Source/cmComputeComponentGraph.cxx b/Source/cmComputeComponentGraph.cxx
index 81cd878..6591fb1 100644
--- a/Source/cmComputeComponentGraph.cxx
+++ b/Source/cmComputeComponentGraph.cxx
@@ -8,6 +8,12 @@
cmComputeComponentGraph::cmComputeComponentGraph(Graph const& input)
: InputGraph(input)
{
+}
+
+cmComputeComponentGraph::~cmComputeComponentGraph() = default;
+
+void cmComputeComponentGraph::Compute()
+{
// Identify components.
this->Tarjan();
@@ -17,8 +23,6 @@ cmComputeComponentGraph::cmComputeComponentGraph(Graph const& input)
this->TransferEdges();
}
-cmComputeComponentGraph::~cmComputeComponentGraph() = default;
-
void cmComputeComponentGraph::Tarjan()
{
int n = static_cast<int>(this->InputGraph.size());
diff --git a/Source/cmComputeComponentGraph.h b/Source/cmComputeComponentGraph.h
index 202888c..b873131 100644
--- a/Source/cmComputeComponentGraph.h
+++ b/Source/cmComputeComponentGraph.h
@@ -31,6 +31,9 @@ public:
cmComputeComponentGraph(Graph const& input);
~cmComputeComponentGraph();
+ /** Run the computation. */
+ void Compute();
+
/** Get the adjacency list of the component graph. */
Graph const& GetComponentGraph() const { return this->ComponentGraph; }
EdgeList const& GetComponentGraphEdges(int c) const
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index e9bf5a5..8ca2168 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -253,13 +253,13 @@ cmComputeLinkDepends::Compute()
// Compute the final set of link entries.
// Iterate in reverse order so we can keep only the last occurrence
// of a shared library.
- std::set<int> emmitted;
+ std::set<int> emitted;
for (int i : cmReverseRange(this->FinalLinkOrder)) {
LinkEntry const& e = this->EntryList[i];
cmGeneratorTarget const* t = e.Target;
// Entries that we know the linker will re-use do not need to be repeated.
bool uniquify = t && t->GetType() == cmStateEnums::SHARED_LIBRARY;
- if (!uniquify || emmitted.insert(i).second) {
+ if (!uniquify || emitted.insert(i).second) {
this->FinalLinkEntries.push_back(e);
}
}
@@ -626,6 +626,7 @@ void cmComputeLinkDepends::OrderLinkEntires()
// constraints disallow it.
this->CCG =
cm::make_unique<cmComputeComponentGraph>(this->EntryConstraintGraph);
+ this->CCG->Compute();
// The component graph is guaranteed to be acyclic. Start a DFS
// from every entry to compute a topological order for the
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 4c5f57d..43cceae 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -515,7 +515,7 @@ bool cmComputeLinkInformation::Compute()
// Restore the target link type so the correct system runtime
// libraries are found.
cmProp lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC");
- if (lss && cmIsOn(*lss)) {
+ if (cmIsOn(lss)) {
this->SetCurrentLinkType(LinkStatic);
} else {
this->SetCurrentLinkType(this->StartLinkType);
@@ -832,8 +832,7 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
// We can support link type switching only if all needed flags are
// known.
- if (static_link_type_flag && *static_link_type_flag &&
- shared_link_type_flag && *shared_link_type_flag) {
+ if (cmNonempty(static_link_type_flag) && cmNonempty(shared_link_type_flag)) {
this->LinkTypeEnabled = true;
this->StaticLinkTypeFlag = static_link_type_flag;
this->SharedLinkTypeFlag = shared_link_type_flag;
@@ -841,7 +840,7 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
// Lookup the starting link type from the target (linked statically?).
cmProp lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC");
- this->StartLinkType = (lss && cmIsOn(*lss)) ? LinkStatic : LinkShared;
+ this->StartLinkType = cmIsOn(lss) ? LinkStatic : LinkShared;
this->CurrentLinkType = this->StartLinkType;
}
@@ -849,31 +848,31 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
{
// Get possible library name prefixes.
cmMakefile* mf = this->Makefile;
- this->AddLinkPrefix(mf->GetDefinition("CMAKE_STATIC_LIBRARY_PREFIX"));
- this->AddLinkPrefix(mf->GetDefinition("CMAKE_SHARED_LIBRARY_PREFIX"));
+ this->AddLinkPrefix(mf->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX"));
+ this->AddLinkPrefix(mf->GetSafeDefinition("CMAKE_SHARED_LIBRARY_PREFIX"));
// Import library names should be matched and treated as shared
// libraries for the purposes of linking.
- this->AddLinkExtension(mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
+ this->AddLinkExtension(mf->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
LinkShared);
- this->AddLinkExtension(mf->GetDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"),
+ this->AddLinkExtension(mf->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"),
LinkStatic);
- this->AddLinkExtension(mf->GetDefinition("CMAKE_SHARED_LIBRARY_SUFFIX"),
+ this->AddLinkExtension(mf->GetSafeDefinition("CMAKE_SHARED_LIBRARY_SUFFIX"),
LinkShared);
- this->AddLinkExtension(mf->GetDefinition("CMAKE_LINK_LIBRARY_SUFFIX"),
+ this->AddLinkExtension(mf->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"),
LinkUnknown);
if (const char* linkSuffixes =
mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS")) {
std::vector<std::string> linkSuffixVec = cmExpandedList(linkSuffixes);
for (std::string const& i : linkSuffixVec) {
- this->AddLinkExtension(i.c_str(), LinkUnknown);
+ this->AddLinkExtension(i, LinkUnknown);
}
}
if (const char* sharedSuffixes =
mf->GetDefinition("CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES")) {
std::vector<std::string> sharedSuffixVec = cmExpandedList(sharedSuffixes);
for (std::string const& i : sharedSuffixVec) {
- this->AddLinkExtension(i.c_str(), LinkShared);
+ this->AddLinkExtension(i, LinkShared);
}
}
@@ -903,7 +902,7 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
fprintf(stderr, "any regex [%s]\n", reg_any.c_str());
#endif
- this->ExtractAnyLibraryName.compile(reg_any.c_str());
+ this->ExtractAnyLibraryName.compile(reg_any);
// Create a regex to match static library names.
if (!this->StaticLinkExtensions.empty()) {
@@ -912,7 +911,7 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
fprintf(stderr, "static regex [%s]\n", reg_static.c_str());
#endif
- this->ExtractStaticLibraryName.compile(reg_static.c_str());
+ this->ExtractStaticLibraryName.compile(reg_static);
}
// Create a regex to match shared library names.
@@ -924,20 +923,21 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
fprintf(stderr, "shared regex [%s]\n", reg_shared.c_str());
#endif
- this->ExtractSharedLibraryName.compile(reg_shared.c_str());
+ this->ExtractSharedLibraryName.compile(reg_shared);
}
}
-void cmComputeLinkInformation::AddLinkPrefix(const char* p)
+void cmComputeLinkInformation::AddLinkPrefix(std::string const& p)
{
- if (p && *p) {
+ if (!p.empty()) {
this->LinkPrefixes.insert(p);
}
}
-void cmComputeLinkInformation::AddLinkExtension(const char* e, LinkType type)
+void cmComputeLinkInformation::AddLinkExtension(std::string const& e,
+ LinkType type)
{
- if (e && *e) {
+ if (!e.empty()) {
if (type == LinkStatic) {
this->StaticLinkExtensions.emplace_back(e);
}
@@ -962,7 +962,7 @@ std::string cmComputeLinkInformation::CreateExtensionRegex(
// Store this extension choice with the "." escaped.
libext += "\\";
#if defined(_WIN32) && !defined(__CYGWIN__)
- libext += this->NoCaseExpression(i.c_str());
+ libext += this->NoCaseExpression(i);
#else
libext += i;
#endif
@@ -980,21 +980,19 @@ std::string cmComputeLinkInformation::CreateExtensionRegex(
return libext;
}
-std::string cmComputeLinkInformation::NoCaseExpression(const char* str)
+std::string cmComputeLinkInformation::NoCaseExpression(std::string const& str)
{
std::string ret;
- ret.reserve(strlen(str) * 4);
- const char* s = str;
- while (*s) {
- if (*s == '.') {
- ret += *s;
+ ret.reserve(str.size() * 4);
+ for (char c : str) {
+ if (c == '.') {
+ ret += c;
} else {
ret += '[';
- ret += static_cast<char>(tolower(*s));
- ret += static_cast<char>(toupper(*s));
+ ret += static_cast<char>(tolower(c));
+ ret += static_cast<char>(toupper(c));
ret += ']';
}
- s++;
}
return ret;
}
@@ -1688,7 +1686,7 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(
}
}
-static void cmCLI_ExpandListUnique(const char* str,
+static void cmCLI_ExpandListUnique(std::string const& str,
std::vector<std::string>& out,
std::set<std::string>& emitted)
{
@@ -1735,7 +1733,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
if (use_install_rpath) {
std::string install_rpath;
this->Target->GetInstallRPATH(this->Config, install_rpath);
- cmCLI_ExpandListUnique(install_rpath.c_str(), runtimeDirs, emitted);
+ cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted);
}
if (use_build_rpath) {
// Add directories explicitly specified by user
@@ -1743,7 +1741,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
if (this->Target->GetBuildRPATH(this->Config, build_rpath)) {
// This will not resolve entries to use $ORIGIN, the user is expected to
// do that if necessary.
- cmCLI_ExpandListUnique(build_rpath.c_str(), runtimeDirs, emitted);
+ cmCLI_ExpandListUnique(build_rpath, runtimeDirs, emitted);
}
}
if (use_build_rpath || use_link_rpath) {
@@ -1769,7 +1767,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
std::string d = ri;
if (!rootPath.empty() && cmHasPrefix(d, rootPath)) {
d.erase(0, rootPath.size());
- } else if (stagePath && *stagePath && cmHasPrefix(d, stagePath)) {
+ } else if (cmNonempty(stagePath) && cmHasPrefix(d, stagePath)) {
d.erase(0, strlen(stagePath));
d = cmStrCat(installPrefix, '/', d);
cmSystemTools::ConvertToUnixSlashes(d);
@@ -1800,7 +1798,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
std::string d = ri;
if (!rootPath.empty() && cmHasPrefix(d, rootPath)) {
d.erase(0, rootPath.size());
- } else if (stagePath && *stagePath && cmHasPrefix(d, stagePath)) {
+ } else if (cmNonempty(stagePath) && cmHasPrefix(d, stagePath)) {
d.erase(0, strlen(stagePath));
d = cmStrCat(installPrefix, '/', d);
cmSystemTools::ConvertToUnixSlashes(d);
@@ -1823,8 +1821,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
"CMAKE_" + li + "_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH";
if (this->Makefile->IsOn(useVar)) {
std::string dirVar = "CMAKE_" + li + "_IMPLICIT_LINK_DIRECTORIES";
- if (const char* dirs = this->Makefile->GetDefinition(dirVar)) {
- cmCLI_ExpandListUnique(dirs, runtimeDirs, emitted);
+ if (cmProp dirs = this->Makefile->GetDef(dirVar)) {
+ cmCLI_ExpandListUnique(*dirs, runtimeDirs, emitted);
}
}
}
@@ -1832,7 +1830,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
// Add runtime paths required by the platform to always be
// present. This is done even when skipping rpath support.
- cmCLI_ExpandListUnique(this->RuntimeAlways.c_str(), runtimeDirs, emitted);
+ cmCLI_ExpandListUnique(this->RuntimeAlways, runtimeDirs, emitted);
}
std::string cmComputeLinkInformation::GetRPathString(bool for_install) const
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index e50d369..544ff23 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -144,11 +144,11 @@ private:
cmsys::RegularExpression ExtractSharedLibraryName;
cmsys::RegularExpression ExtractAnyLibraryName;
std::string SharedRegexString;
- void AddLinkPrefix(const char* p);
- void AddLinkExtension(const char* e, LinkType type);
+ void AddLinkPrefix(std::string const& p);
+ void AddLinkExtension(std::string const& e, LinkType type);
std::string CreateExtensionRegex(std::vector<std::string> const& exts,
LinkType type);
- std::string NoCaseExpression(const char* str);
+ std::string NoCaseExpression(std::string const& str);
// Handling of link items.
void AddTargetItem(BT<std::string> const& item,
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 41f5346..1f22ce6 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -17,10 +17,12 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
@@ -115,18 +117,32 @@ bool cmComputeTargetDepends::Compute()
if (this->DebugMode) {
this->DisplayGraph(this->InitialGraph, "initial");
}
+ cmComputeComponentGraph ccg1(this->InitialGraph);
+ ccg1.Compute();
+ if (!this->CheckComponents(ccg1)) {
+ return false;
+ }
+
+ // Compute the intermediate graph.
+ this->CollectSideEffects();
+ this->ComputeIntermediateGraph();
+ if (this->DebugMode) {
+ this->DisplaySideEffects();
+ this->DisplayGraph(this->IntermediateGraph, "intermediate");
+ }
// Identify components.
- cmComputeComponentGraph ccg(this->InitialGraph);
+ cmComputeComponentGraph ccg2(this->IntermediateGraph);
+ ccg2.Compute();
if (this->DebugMode) {
- this->DisplayComponents(ccg);
+ this->DisplayComponents(ccg2, "intermediate");
}
- if (!this->CheckComponents(ccg)) {
+ if (!this->CheckComponents(ccg2)) {
return false;
}
// Compute the final dependency graph.
- if (!this->ComputeFinalDepends(ccg)) {
+ if (!this->ComputeFinalDepends(ccg2)) {
return false;
}
if (this->DebugMode) {
@@ -184,7 +200,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
{
// Get the depender.
cmGeneratorTarget const* depender = this->Targets[depender_index];
- if (depender->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!depender->IsInBuildSystem()) {
return;
}
@@ -196,18 +212,20 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
std::set<cmLinkItem> emitted;
std::vector<std::string> const& configs =
- depender->Makefile->GetGeneratorConfigs();
+ depender->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
for (std::string const& it : configs) {
- cmLinkImplementation const* impl = depender->GetLinkImplementation(it);
-
// A target should not depend on itself.
emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace()));
emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace()));
- for (cmLinkImplItem const& lib : impl->Libraries) {
- // Don't emit the same library twice for this target.
- if (emitted.insert(lib).second) {
- this->AddTargetDepend(depender_index, lib, true, false);
- this->AddInterfaceDepends(depender_index, lib, it, emitted);
+
+ if (cmLinkImplementation const* impl =
+ depender->GetLinkImplementation(it)) {
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ // Don't emit the same library twice for this target.
+ if (emitted.insert(lib).second) {
+ this->AddTargetDepend(depender_index, lib, true, false);
+ this->AddInterfaceDepends(depender_index, lib, it, emitted);
+ }
}
}
@@ -356,10 +374,9 @@ void cmComputeTargetDepends::AddTargetDepend(
int depender_index, cmGeneratorTarget const* dependee,
cmListFileBacktrace const& dependee_backtrace, bool linking, bool cross)
{
- if (dependee->IsImported() ||
- dependee->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- // Skip IMPORTED and INTERFACE targets but follow their utility
- // dependencies.
+ if (!dependee->IsInBuildSystem()) {
+ // Skip targets that are not in the buildsystem but follow their
+ // utility dependencies.
std::set<cmLinkItem> const& utils = dependee->GetUtilityItems();
for (cmLinkItem const& i : utils) {
if (cmGeneratorTarget const* transitive_dependee = i.Target) {
@@ -380,6 +397,111 @@ void cmComputeTargetDepends::AddTargetDepend(
}
}
+void cmComputeTargetDepends::CollectSideEffects()
+{
+ this->SideEffects.resize(0);
+ this->SideEffects.resize(this->InitialGraph.size());
+
+ int n = static_cast<int>(this->InitialGraph.size());
+ std::set<int> visited;
+ for (int i = 0; i < n; ++i) {
+ this->CollectSideEffectsForTarget(visited, i);
+ }
+}
+
+void cmComputeTargetDepends::CollectSideEffectsForTarget(
+ std::set<int>& visited, int depender_index)
+{
+ if (!visited.count(depender_index)) {
+ auto& se = this->SideEffects[depender_index];
+ visited.insert(depender_index);
+ this->Targets[depender_index]->AppendCustomCommandSideEffects(
+ se.CustomCommandSideEffects);
+ this->Targets[depender_index]->AppendLanguageSideEffects(
+ se.LanguageSideEffects);
+
+ for (auto const& edge : this->InitialGraph[depender_index]) {
+ this->CollectSideEffectsForTarget(visited, edge);
+ auto const& dse = this->SideEffects[edge];
+ se.CustomCommandSideEffects.insert(dse.CustomCommandSideEffects.cbegin(),
+ dse.CustomCommandSideEffects.cend());
+ for (auto const& it : dse.LanguageSideEffects) {
+ se.LanguageSideEffects[it.first].insert(it.second.cbegin(),
+ it.second.cend());
+ }
+ }
+ }
+}
+
+void cmComputeTargetDepends::ComputeIntermediateGraph()
+{
+ this->IntermediateGraph.resize(0);
+ this->IntermediateGraph.resize(this->InitialGraph.size());
+
+ int n = static_cast<int>(this->InitialGraph.size());
+ for (int i = 0; i < n; ++i) {
+ auto const& initialEdges = this->InitialGraph[i];
+ auto& intermediateEdges = this->IntermediateGraph[i];
+ cmGeneratorTarget const* gt = this->Targets[i];
+ if (gt->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ gt->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ intermediateEdges = initialEdges;
+ } else {
+ if (cmProp optimizeDependencies =
+ gt->GetProperty("OPTIMIZE_DEPENDENCIES")) {
+ if (cmIsOn(optimizeDependencies)) {
+ this->OptimizeLinkDependencies(gt, intermediateEdges, initialEdges);
+ } else {
+ intermediateEdges = initialEdges;
+ }
+ } else {
+ intermediateEdges = initialEdges;
+ }
+ }
+ }
+}
+
+void cmComputeTargetDepends::OptimizeLinkDependencies(
+ cmGeneratorTarget const* gt, cmGraphEdgeList& outputEdges,
+ cmGraphEdgeList const& inputEdges)
+{
+ std::set<int> emitted;
+ for (auto const& edge : inputEdges) {
+ if (edge.IsStrong()) {
+ // Preserve strong edges
+ outputEdges.push_back(edge);
+ } else {
+ auto const& dse = this->SideEffects[edge];
+
+ // Add edges that have custom command side effects
+ for (cmGeneratorTarget const* dep : dse.CustomCommandSideEffects) {
+ auto index = this->TargetIndex[dep];
+ if (!emitted.count(index)) {
+ emitted.insert(index);
+ outputEdges.push_back(
+ cmGraphEdge(index, false, edge.IsCross(), edge.GetBacktrace()));
+ }
+ }
+
+ // Add edges that have language side effects for languages we
+ // care about
+ for (auto const& lang : gt->GetAllConfigCompileLanguages()) {
+ auto it = dse.LanguageSideEffects.find(lang);
+ if (it != dse.LanguageSideEffects.end()) {
+ for (cmGeneratorTarget const* dep : it->second) {
+ auto index = this->TargetIndex[dep];
+ if (!emitted.count(index)) {
+ emitted.insert(index);
+ outputEdges.push_back(cmGraphEdge(index, false, edge.IsCross(),
+ edge.GetBacktrace()));
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
void cmComputeTargetDepends::DisplayGraph(Graph const& graph,
const std::string& name)
{
@@ -400,10 +522,39 @@ void cmComputeTargetDepends::DisplayGraph(Graph const& graph,
fprintf(stderr, "\n");
}
+void cmComputeTargetDepends::DisplaySideEffects()
+{
+ fprintf(stderr, "The side effects are:\n");
+ int n = static_cast<int>(SideEffects.size());
+ for (int depender_index = 0; depender_index < n; ++depender_index) {
+ cmGeneratorTarget const* depender = this->Targets[depender_index];
+ fprintf(stderr, "target %d is [%s]\n", depender_index,
+ depender->GetName().c_str());
+ if (!this->SideEffects[depender_index].CustomCommandSideEffects.empty()) {
+ fprintf(stderr, " custom commands\n");
+ for (auto const* gt :
+ this->SideEffects[depender_index].CustomCommandSideEffects) {
+ fprintf(stderr, " from target %d [%s]\n", this->TargetIndex[gt],
+ gt->GetName().c_str());
+ }
+ }
+ for (auto const& it :
+ this->SideEffects[depender_index].LanguageSideEffects) {
+ fprintf(stderr, " language %s\n", it.first.c_str());
+ for (auto const* gt : it.second) {
+ fprintf(stderr, " from target %d [%s]\n", this->TargetIndex[gt],
+ gt->GetName().c_str());
+ }
+ }
+ }
+ fprintf(stderr, "\n");
+}
+
void cmComputeTargetDepends::DisplayComponents(
- cmComputeComponentGraph const& ccg)
+ cmComputeComponentGraph const& ccg, const std::string& name)
{
- fprintf(stderr, "The strongly connected components are:\n");
+ fprintf(stderr, "The strongly connected components for the %s graph are:\n",
+ name.c_str());
std::vector<NodeList> const& components = ccg.GetComponents();
int n = static_cast<int>(components.size());
for (int c = 0; c < n; ++c) {
diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h
index e0d625f..277521d 100644
--- a/Source/cmComputeTargetDepends.h
+++ b/Source/cmComputeTargetDepends.h
@@ -42,6 +42,13 @@ public:
cmTargetDependSet& deps);
private:
+ struct TargetSideEffects
+ {
+ std::set<cmGeneratorTarget const*> CustomCommandSideEffects;
+ std::map<std::string, std::set<cmGeneratorTarget const*>>
+ LanguageSideEffects;
+ };
+
void CollectTargets();
void CollectDepends();
void CollectTargetDepends(int depender_index);
@@ -50,6 +57,12 @@ private:
void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee,
cmListFileBacktrace const& dependee_backtrace,
bool linking, bool cross);
+ void CollectSideEffects();
+ void CollectSideEffectsForTarget(std::set<int>& visited, int depender_index);
+ void ComputeIntermediateGraph();
+ void OptimizeLinkDependencies(cmGeneratorTarget const* gt,
+ cmGraphEdgeList& outputEdges,
+ cmGraphEdgeList const& inputEdges);
bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name,
const std::string& config,
@@ -74,11 +87,15 @@ private:
using EdgeList = cmGraphEdgeList;
using Graph = cmGraphAdjacencyList;
Graph InitialGraph;
+ Graph IntermediateGraph;
Graph FinalGraph;
+ std::vector<TargetSideEffects> SideEffects;
void DisplayGraph(Graph const& graph, const std::string& name);
+ void DisplaySideEffects();
// Deal with connected components.
- void DisplayComponents(cmComputeComponentGraph const& ccg);
+ void DisplayComponents(cmComputeComponentGraph const& ccg,
+ const std::string& name);
bool CheckComponents(cmComputeComponentGraph const& ccg);
void ComplainAboutBadComponent(cmComputeComponentGraph const& ccg, int c,
bool strong = false);
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 4de1c5d..97e7856 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -19,7 +19,6 @@
#cmakedefine HAVE_UNSETENV
#cmakedefine CMAKE_USE_ELF_PARSER
#cmakedefine CMAKE_USE_MACH_PARSER
-#cmakedefine CMake_HAVE_CXX_MAKE_UNIQUE
#define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@
#define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@"
#define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@"
diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx
index 5b3045d..68322cc 100644
--- a/Source/cmConfigureFileCommand.cxx
+++ b/Source/cmConfigureFileCommand.cxx
@@ -60,6 +60,7 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
}
bool copyOnly = false;
bool escapeQuotes = false;
+ bool use_source_permissions = true;
static std::set<cm::string_view> noopOptions = {
/* Legacy. */
@@ -87,6 +88,8 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
escapeQuotes = true;
} else if (args[i] == "@ONLY") {
atOnly = true;
+ } else if (args[i] == "NO_SOURCE_PERMISSIONS") {
+ use_source_permissions = false;
} else if (noopOptions.find(args[i]) != noopOptions.end()) {
/* Ignore no-op options. */
} else {
@@ -102,7 +105,8 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
}
if (!status.GetMakefile().ConfigureFile(
- inputFile, outputFile, copyOnly, atOnly, escapeQuotes, newLineStyle)) {
+ inputFile, outputFile, copyOnly, atOnly, escapeQuotes,
+ use_source_permissions, newLineStyle)) {
status.SetError("Problem configuring file");
return false;
}
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 8550d04..63c1484 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -18,6 +18,7 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -25,77 +26,205 @@
#include "cmVersion.h"
#include "cmake.h"
-static std::string const kCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN =
- "CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN";
-static std::string const kCMAKE_C_COMPILER_TARGET = "CMAKE_C_COMPILER_TARGET";
-static std::string const kCMAKE_C_LINK_NO_PIE_SUPPORTED =
- "CMAKE_C_LINK_NO_PIE_SUPPORTED";
-static std::string const kCMAKE_C_LINK_PIE_SUPPORTED =
- "CMAKE_C_LINK_PIE_SUPPORTED";
-static std::string const kCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN =
- "CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN";
-static std::string const kCMAKE_CXX_COMPILER_TARGET =
- "CMAKE_CXX_COMPILER_TARGET";
-static std::string const kCMAKE_CXX_LINK_NO_PIE_SUPPORTED =
- "CMAKE_CXX_LINK_NO_PIE_SUPPORTED";
-static std::string const kCMAKE_CXX_LINK_PIE_SUPPORTED =
- "CMAKE_CXX_LINK_PIE_SUPPORTED";
-static std::string const kCMAKE_CUDA_ARCHITECTURES =
- "CMAKE_CUDA_ARCHITECTURES";
-static std::string const kCMAKE_CUDA_COMPILER_TARGET =
- "CMAKE_CUDA_COMPILER_TARGET";
-static std::string const kCMAKE_CUDA_RUNTIME_LIBRARY =
- "CMAKE_CUDA_RUNTIME_LIBRARY";
-static std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS";
-static std::string const kCMAKE_LINK_SEARCH_END_STATIC =
+namespace {
+class LanguageStandardState
+{
+public:
+ LanguageStandardState(std::string&& lang)
+ : IsEnabled(false)
+ , DidStandard(false)
+ , DidStandardRequired(false)
+ , DidExtensions(false)
+ , StandardFlag(lang + "_STANDARD")
+ , RequiredFlag(lang + "_STANDARD_REQUIRED")
+ , ExtensionFlag(lang + "_EXTENSIONS")
+ {
+ }
+
+ void Enabled(bool isEnabled) { this->IsEnabled = isEnabled; }
+
+ bool UpdateIfMatches(std::vector<std::string> const& argv, size_t& index)
+ {
+ bool updated = false;
+ if (argv[index] == this->StandardFlag) {
+ this->DidStandard = true;
+ this->StandardValue = argv[++index];
+ updated = true;
+ } else if (argv[index] == this->RequiredFlag) {
+ this->DidStandardRequired = true;
+ this->RequiredValue = argv[++index];
+ updated = true;
+ } else if (argv[index] == this->ExtensionFlag) {
+ this->DidExtensions = true;
+ this->ExtensionValue = argv[++index];
+ updated = true;
+ }
+ return updated;
+ }
+
+ bool Validate(cmMakefile* const makefile) const
+ {
+ if (this->DidStandard) {
+ makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(this->StandardFlag,
+ " allowed only in source file signature."));
+ return false;
+ }
+ if (this->DidStandardRequired) {
+ makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(this->RequiredFlag,
+ " allowed only in source file signature."));
+ return false;
+ }
+ if (this->DidExtensions) {
+ makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(this->ExtensionFlag,
+ " allowed only in source file signature."));
+ return false;
+ }
+
+ return true;
+ }
+
+ bool DidNone() const
+ {
+ return !this->DidStandard && !this->DidStandardRequired &&
+ !this->DidExtensions;
+ }
+
+ void LoadUnsetPropertyValues(cmMakefile* const makefile, bool honorStandard,
+ bool warnCMP0067,
+ std::vector<std::string>& warnCMP0067Variables)
+ {
+ if (!this->IsEnabled) {
+ return;
+ }
+
+ auto lookupStdVar = [&](std::string const& var) -> std::string {
+ std::string value = makefile->GetSafeDefinition(var);
+ if (warnCMP0067 && !value.empty()) {
+ value.clear();
+ warnCMP0067Variables.push_back(var);
+ }
+ return value;
+ };
+
+ if (honorStandard || warnCMP0067) {
+ if (!this->DidStandard) {
+ this->StandardValue =
+ lookupStdVar(cmStrCat("CMAKE_", this->StandardFlag));
+ }
+ if (!this->DidStandardRequired) {
+ this->RequiredValue =
+ lookupStdVar(cmStrCat("CMAKE_", this->RequiredFlag));
+ }
+ if (!this->DidExtensions) {
+ this->ExtensionValue =
+ lookupStdVar(cmStrCat("CMAKE_", this->ExtensionFlag));
+ }
+ }
+ }
+
+ void WriteProperties(FILE* fout, std::string const& targetName) const
+ {
+ if (!this->IsEnabled) {
+ return;
+ }
+
+ auto writeProp = [&](std::string const& prop, std::string const& value) {
+ fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n",
+ targetName.c_str(),
+ cmOutputConverter::EscapeForCMake(prop).c_str(),
+ cmOutputConverter::EscapeForCMake(value).c_str());
+ };
+
+ if (!this->StandardValue.empty()) {
+ writeProp(this->StandardFlag, this->StandardValue);
+ }
+ if (!this->RequiredValue.empty()) {
+ writeProp(this->RequiredFlag, this->RequiredValue);
+ }
+ if (!this->ExtensionValue.empty()) {
+ writeProp(this->ExtensionFlag, this->ExtensionValue);
+ }
+ }
+
+private:
+ bool IsEnabled;
+ bool DidStandard;
+ bool DidStandardRequired;
+ bool DidExtensions;
+
+ std::string StandardFlag;
+ std::string RequiredFlag;
+ std::string ExtensionFlag;
+
+ std::string StandardValue;
+ std::string RequiredValue;
+ std::string ExtensionValue;
+};
+
+constexpr size_t lang_property_start = 0;
+constexpr size_t lang_property_size = 4;
+constexpr size_t pie_property_start = 4;
+constexpr size_t pie_property_size = 2;
+#define SETUP_LANGUAGE(name, lang) \
+ static const std::string name[lang_property_size + pie_property_size + 1] = \
+ { "CMAKE_" #lang "_COMPILER_EXTERNAL_TOOLCHAIN", \
+ "CMAKE_" #lang "_COMPILER_TARGET", \
+ "CMAKE_" #lang "_LINK_NO_PIE_SUPPORTED", \
+ "CMAKE_" #lang "_PIE_SUPPORTED", "" }
+
+// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
+SETUP_LANGUAGE(c_properties, C);
+// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
+SETUP_LANGUAGE(cxx_properties, CXX);
+
+// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
+SETUP_LANGUAGE(cuda_properties, CUDA);
+// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
+SETUP_LANGUAGE(fortran_properties, Fortran);
+// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
+SETUP_LANGUAGE(objc_properties, OBJC);
+// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
+SETUP_LANGUAGE(objcxx_properties, OBJCXX);
+// NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
+SETUP_LANGUAGE(swift_properties, Swift);
+#undef SETUP_LANGUAGE
+
+std::string const kCMAKE_CUDA_ARCHITECTURES = "CMAKE_CUDA_ARCHITECTURES";
+std::string const kCMAKE_CUDA_RUNTIME_LIBRARY = "CMAKE_CUDA_RUNTIME_LIBRARY";
+std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS";
+std::string const kCMAKE_LINK_SEARCH_END_STATIC =
"CMAKE_LINK_SEARCH_END_STATIC";
-static std::string const kCMAKE_LINK_SEARCH_START_STATIC =
+std::string const kCMAKE_LINK_SEARCH_START_STATIC =
"CMAKE_LINK_SEARCH_START_STATIC";
-static std::string const kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT =
+std::string const kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT =
"CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT";
-static std::string const kCMAKE_OSX_ARCHITECTURES = "CMAKE_OSX_ARCHITECTURES";
-static std::string const kCMAKE_OSX_DEPLOYMENT_TARGET =
- "CMAKE_OSX_DEPLOYMENT_TARGET";
-static std::string const kCMAKE_OSX_SYSROOT = "CMAKE_OSX_SYSROOT";
-static std::string const kCMAKE_APPLE_ARCH_SYSROOTS =
- "CMAKE_APPLE_ARCH_SYSROOTS";
-static std::string const kCMAKE_POSITION_INDEPENDENT_CODE =
+std::string const kCMAKE_OSX_ARCHITECTURES = "CMAKE_OSX_ARCHITECTURES";
+std::string const kCMAKE_OSX_DEPLOYMENT_TARGET = "CMAKE_OSX_DEPLOYMENT_TARGET";
+std::string const kCMAKE_OSX_SYSROOT = "CMAKE_OSX_SYSROOT";
+std::string const kCMAKE_APPLE_ARCH_SYSROOTS = "CMAKE_APPLE_ARCH_SYSROOTS";
+std::string const kCMAKE_POSITION_INDEPENDENT_CODE =
"CMAKE_POSITION_INDEPENDENT_CODE";
-static std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT";
-static std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE";
-static std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK";
-static std::string const kCMAKE_Swift_COMPILER_TARGET =
- "CMAKE_Swift_COMPILER_TARGET";
-static std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES =
+std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT";
+std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE";
+std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK";
+std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES =
"CMAKE_TRY_COMPILE_OSX_ARCHITECTURES";
-static std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES =
+std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES =
"CMAKE_TRY_COMPILE_PLATFORM_VARIABLES";
-static std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED";
+std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED";
/* GHS Multi platform variables */
-static std::set<std::string> ghs_platform_vars{
+std::set<std::string> const ghs_platform_vars{
"GHS_TARGET_PLATFORM", "GHS_PRIMARY_TARGET", "GHS_TOOLSET_ROOT",
"GHS_OS_ROOT", "GHS_OS_DIR", "GHS_BSP_NAME",
"GHS_OS_DIR_OPTION"
};
-
-static void writeProperty(FILE* fout, std::string const& targetName,
- std::string const& prop, std::string const& value)
-{
- fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n", targetName.c_str(),
- cmOutputConverter::EscapeForCMake(prop).c_str(),
- cmOutputConverter::EscapeForCMake(value).c_str());
-}
-
-std::string cmCoreTryCompile::LookupStdVar(std::string const& var,
- bool warnCMP0067)
-{
- std::string value = this->Makefile->GetSafeDefinition(var);
- if (warnCMP0067 && !value.empty()) {
- value.clear();
- this->WarnCMP0067.push_back(var);
- }
- return value;
}
int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
@@ -107,9 +236,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
this->SrcFileSignature = true;
cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE;
- const std::string* tt =
- this->Makefile->GetDef("CMAKE_TRY_COMPILE_TARGET_TYPE");
- if (!isTryRun && tt && !tt->empty()) {
+ cmProp tt = this->Makefile->GetDef("CMAKE_TRY_COMPILE_TARGET_TYPE");
+ if (!isTryRun && cmNonempty(tt)) {
if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) {
targetType = cmStateEnums::EXECUTABLE;
} else if (*tt ==
@@ -137,21 +265,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
std::string outputVariable;
std::string copyFile;
std::string copyFileError;
- std::string cStandard;
- std::string objcStandard;
- std::string cxxStandard;
- std::string objcxxStandard;
- std::string cudaStandard;
- std::string cStandardRequired;
- std::string cxxStandardRequired;
- std::string objcStandardRequired;
- std::string objcxxStandardRequired;
- std::string cudaStandardRequired;
- std::string cExtensions;
- std::string cxxExtensions;
- std::string objcExtensions;
- std::string objcxxExtensions;
- std::string cudaExtensions;
+ LanguageStandardState cState("C");
+ LanguageStandardState cudaState("CUDA");
+ LanguageStandardState cxxState("CXX");
+ LanguageStandardState objcState("OBJC");
+ LanguageStandardState objcxxState("OBJCXX");
std::vector<std::string> targets;
std::vector<std::string> linkOptions;
std::string libsToLink = " ";
@@ -160,21 +278,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
bool didOutputVariable = false;
bool didCopyFile = false;
bool didCopyFileError = false;
- bool didCStandard = false;
- bool didCxxStandard = false;
- bool didObjCStandard = false;
- bool didObjCxxStandard = false;
- bool didCudaStandard = false;
- bool didCStandardRequired = false;
- bool didCxxStandardRequired = false;
- bool didObjCStandardRequired = false;
- bool didObjCxxStandardRequired = false;
- bool didCudaStandardRequired = false;
- bool didCExtensions = false;
- bool didCxxExtensions = false;
- bool didObjCExtensions = false;
- bool didObjCxxExtensions = false;
- bool didCudaExtensions = false;
bool useSources = argv[2] == "SOURCES";
std::vector<std::string> sources;
@@ -188,21 +291,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
DoingOutputVariable,
DoingCopyFile,
DoingCopyFileError,
- DoingCStandard,
- DoingCxxStandard,
- DoingObjCStandard,
- DoingObjCxxStandard,
- DoingCudaStandard,
- DoingCStandardRequired,
- DoingCxxStandardRequired,
- DoingObjCStandardRequired,
- DoingObjCxxStandardRequired,
- DoingCudaStandardRequired,
- DoingCExtensions,
- DoingCxxExtensions,
- DoingObjCExtensions,
- DoingObjCxxExtensions,
- DoingCudaExtensions,
DoingSources,
DoingCMakeInternal
};
@@ -226,51 +314,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (argv[i] == "COPY_FILE_ERROR") {
doing = DoingCopyFileError;
didCopyFileError = true;
- } else if (argv[i] == "C_STANDARD") {
- doing = DoingCStandard;
- didCStandard = true;
- } else if (argv[i] == "CXX_STANDARD") {
- doing = DoingCxxStandard;
- didCxxStandard = true;
- } else if (argv[i] == "OBJC_STANDARD") {
- doing = DoingObjCStandard;
- didObjCStandard = true;
- } else if (argv[i] == "OBJCXX_STANDARD") {
- doing = DoingObjCxxStandard;
- didObjCxxStandard = true;
- } else if (argv[i] == "CUDA_STANDARD") {
- doing = DoingCudaStandard;
- didCudaStandard = true;
- } else if (argv[i] == "C_STANDARD_REQUIRED") {
- doing = DoingCStandardRequired;
- didCStandardRequired = true;
- } else if (argv[i] == "CXX_STANDARD_REQUIRED") {
- doing = DoingCxxStandardRequired;
- didCxxStandardRequired = true;
- } else if (argv[i] == "OBJC_STANDARD_REQUIRED") {
- doing = DoingObjCStandardRequired;
- didObjCStandardRequired = true;
- } else if (argv[i] == "OBJCXX_STANDARD_REQUIRED") {
- doing = DoingObjCxxStandardRequired;
- didObjCxxStandardRequired = true;
- } else if (argv[i] == "CUDA_STANDARD_REQUIRED") {
- doing = DoingCudaStandardRequired;
- didCudaStandardRequired = true;
- } else if (argv[i] == "C_EXTENSIONS") {
- doing = DoingCExtensions;
- didCExtensions = true;
- } else if (argv[i] == "CXX_EXTENSIONS") {
- doing = DoingCxxExtensions;
- didCxxExtensions = true;
- } else if (argv[i] == "OBJC_EXTENSIONS") {
- doing = DoingObjCExtensions;
- didObjCExtensions = true;
- } else if (argv[i] == "OBJCXX_EXTENSIONS") {
- doing = DoingObjCxxExtensions;
- didObjCxxExtensions = true;
- } else if (argv[i] == "CUDA_EXTENSIONS") {
- doing = DoingCudaExtensions;
- didCudaExtensions = true;
+ } else if (cState.UpdateIfMatches(argv, i) ||
+ cxxState.UpdateIfMatches(argv, i) ||
+ cudaState.UpdateIfMatches(argv, i) ||
+ objcState.UpdateIfMatches(argv, i) ||
+ objcxxState.UpdateIfMatches(argv, i)) {
+ continue;
} else if (argv[i] == "__CMAKE_INTERNAL") {
doing = DoingCMakeInternal;
} else if (doing == DoingCMakeFlags) {
@@ -315,51 +364,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (doing == DoingCopyFileError) {
copyFileError = argv[i];
doing = DoingNone;
- } else if (doing == DoingCStandard) {
- cStandard = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCxxStandard) {
- cxxStandard = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCStandard) {
- objcStandard = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCxxStandard) {
- objcxxStandard = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCudaStandard) {
- cudaStandard = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCStandardRequired) {
- cStandardRequired = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCxxStandardRequired) {
- cxxStandardRequired = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCStandardRequired) {
- objcStandardRequired = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCxxStandardRequired) {
- objcxxStandardRequired = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCudaStandardRequired) {
- cudaStandardRequired = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCExtensions) {
- cExtensions = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCxxExtensions) {
- cxxExtensions = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCExtensions) {
- objcExtensions = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCxxExtensions) {
- objcxxExtensions = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCudaExtensions) {
- cudaExtensions = argv[i];
- doing = DoingNone;
} else if (doing == DoingSources) {
sources.push_back(argv[i]);
} else if (doing == DoingCMakeInternal) {
@@ -411,59 +415,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
return -1;
}
- if (didCStandard && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "C_STANDARD allowed only in source file signature.");
- return -1;
- }
- if (didCxxStandard && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CXX_STANDARD allowed only in source file signature.");
- return -1;
- }
- if (didCudaStandard && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CUDA_STANDARD allowed only in source file signature.");
- return -1;
- }
- if (didCStandardRequired && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "C_STANDARD_REQUIRED allowed only in source file signature.");
- return -1;
- }
- if (didCxxStandardRequired && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CXX_STANDARD_REQUIRED allowed only in source file signature.");
- return -1;
- }
- if (didCudaStandardRequired && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CUDA_STANDARD_REQUIRED allowed only in source file signature.");
- return -1;
- }
- if (didCExtensions && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "C_EXTENSIONS allowed only in source file signature.");
- return -1;
- }
- if (didCxxExtensions && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CXX_EXTENSIONS allowed only in source file signature.");
- return -1;
- }
- if (didCudaExtensions && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CUDA_EXTENSIONS allowed only in source file signature.");
- return -1;
+ if (!this->SrcFileSignature) {
+ if (!cState.Validate(this->Makefile)) {
+ return -1;
+ }
+ if (!cudaState.Validate(this->Makefile)) {
+ return -1;
+ }
+ if (!cxxState.Validate(this->Makefile)) {
+ return -1;
+ }
+ if (!objcState.Validate(this->Makefile)) {
+ return -1;
+ }
+ if (!objcxxState.Validate(this->Makefile)) {
+ return -1;
+ }
}
// compute the binary dir when TRY_COMPILE is called with a src file
@@ -721,12 +688,23 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
// Forward a set of variables to the inner project cache.
{
std::set<std::string> vars;
- vars.insert(kCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN);
- vars.insert(kCMAKE_C_COMPILER_TARGET);
- vars.insert(kCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN);
- vars.insert(kCMAKE_CXX_COMPILER_TARGET);
+ vars.insert(&c_properties[lang_property_start],
+ &c_properties[lang_property_start + lang_property_size]);
+ vars.insert(&cxx_properties[lang_property_start],
+ &cxx_properties[lang_property_start + lang_property_size]);
+ vars.insert(&cuda_properties[lang_property_start],
+ &cuda_properties[lang_property_start + lang_property_size]);
+ vars.insert(
+ &fortran_properties[lang_property_start],
+ &fortran_properties[lang_property_start + lang_property_size]);
+ vars.insert(&objc_properties[lang_property_start],
+ &objc_properties[lang_property_start + lang_property_size]);
+ vars.insert(
+ &objcxx_properties[lang_property_start],
+ &objcxx_properties[lang_property_start + lang_property_size]);
+ vars.insert(&swift_properties[lang_property_start],
+ &swift_properties[lang_property_start + lang_property_size]);
vars.insert(kCMAKE_CUDA_ARCHITECTURES);
- vars.insert(kCMAKE_CUDA_COMPILER_TARGET);
vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY);
vars.insert(kCMAKE_ENABLE_EXPORTS);
vars.insert(kCMAKE_LINK_SEARCH_END_STATIC);
@@ -739,7 +717,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
vars.insert(kCMAKE_SYSROOT);
vars.insert(kCMAKE_SYSROOT_COMPILE);
vars.insert(kCMAKE_SYSROOT_LINK);
- vars.insert(kCMAKE_Swift_COMPILER_TARGET);
vars.insert(kCMAKE_WARN_DEPRECATED);
vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s);
@@ -753,10 +730,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
cmPolicies::NEW) {
// To ensure full support of PIE, propagate cache variables
// driving the link options
- vars.insert(kCMAKE_C_LINK_PIE_SUPPORTED);
- vars.insert(kCMAKE_C_LINK_NO_PIE_SUPPORTED);
- vars.insert(kCMAKE_CXX_LINK_PIE_SUPPORTED);
- vars.insert(kCMAKE_CXX_LINK_NO_PIE_SUPPORTED);
+ vars.insert(&c_properties[pie_property_start],
+ &c_properties[pie_property_start + pie_property_size]);
+ vars.insert(&cxx_properties[pie_property_start],
+ &cxx_properties[pie_property_start + pie_property_size]);
+ vars.insert(&cuda_properties[pie_property_start],
+ &cuda_properties[pie_property_start + pie_property_size]);
+ vars.insert(
+ &fortran_properties[pie_property_start],
+ &fortran_properties[pie_property_start + pie_property_size]);
+ vars.insert(&objc_properties[pie_property_start],
+ &objc_properties[pie_property_start + pie_property_size]);
+ vars.insert(
+ &objcxx_properties[pie_property_start],
+ &objcxx_properties[pie_property_start + pie_property_size]);
+ vars.insert(&swift_properties[pie_property_start],
+ &swift_properties[pie_property_start + pie_property_size]);
}
/* for the TRY_COMPILEs we want to be able to specify the architecture.
@@ -819,21 +808,17 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
fprintf(fout, ")\n");
- bool const testC = testLangs.find("C") != testLangs.end();
- bool const testObjC = testLangs.find("OBJC") != testLangs.end();
- bool const testCxx = testLangs.find("CXX") != testLangs.end();
- bool const testObjCxx = testLangs.find("OBJCXX") != testLangs.end();
- bool const testCuda = testLangs.find("CUDA") != testLangs.end();
+ cState.Enabled(testLangs.find("C") != testLangs.end());
+ cxxState.Enabled(testLangs.find("CXX") != testLangs.end());
+ cudaState.Enabled(testLangs.find("CUDA") != testLangs.end());
+ objcState.Enabled(testLangs.find("OBJC") != testLangs.end());
+ objcxxState.Enabled(testLangs.find("OBJCXX") != testLangs.end());
bool warnCMP0067 = false;
bool honorStandard = true;
- if (!didCStandard && !didCxxStandard && !didObjCStandard &&
- !didObjCxxStandard && !didCudaStandard && !didCStandardRequired &&
- !didCxxStandardRequired && !didObjCStandardRequired &&
- !didObjCxxStandardRequired && !didCudaStandardRequired &&
- !didCExtensions && !didCxxExtensions && !didObjCExtensions &&
- !didObjCxxExtensions && !didCudaExtensions) {
+ if (cState.DidNone() && cxxState.DidNone() && objcState.DidNone() &&
+ objcxxState.DidNone() && cudaState.DidNone()) {
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) {
case cmPolicies::WARN:
warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
@@ -855,46 +840,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
- if (honorStandard || warnCMP0067) {
+ std::vector<std::string> warnCMP0067Variables;
- auto testLanguage =
- [&](bool testLang, bool didLangStandard, bool didLangStandardRequired,
- bool didLangExtensions, std::string& langStandard,
- std::string& langStandardRequired, std::string& langExtensions,
- const std::string& lang) {
- if (testLang) {
- if (!didLangStandard) {
- langStandard = this->LookupStdVar(
- cmStrCat("CMAKE_", lang, "_STANDARD"), warnCMP0067);
- }
- if (!didLangStandardRequired) {
- langStandardRequired = this->LookupStdVar(
- cmStrCat("CMAKE_", lang, "_STANDARD_REQUIRED"), warnCMP0067);
- }
- if (!didLangExtensions) {
- langExtensions = this->LookupStdVar(
- cmStrCat("CMAKE_", lang, "_EXTENSIONS"), warnCMP0067);
- }
- }
- };
-
- testLanguage(testC, didCStandard, didCStandardRequired, didCExtensions,
- cStandard, cStandardRequired, cExtensions, "C");
- testLanguage(testObjC, didObjCStandard, didObjCStandardRequired,
- didObjCExtensions, objcStandard, objcStandardRequired,
- objcExtensions, "OBJC");
- testLanguage(testCxx, didCxxStandard, didCxxStandardRequired,
- didCxxExtensions, cxxStandard, cxxStandardRequired,
- cxxExtensions, "CXX");
- testLanguage(testObjCxx, didObjCxxStandard, didObjCxxStandardRequired,
- didObjCxxExtensions, objcxxStandard, objcxxStandardRequired,
- objcxxExtensions, "OBJCXX");
- testLanguage(testCuda, didCudaStandard, didCudaStandardRequired,
- didCudaExtensions, cudaStandard, cudaStandardRequired,
- cudaExtensions, "CUDA");
- }
+ cState.LoadUnsetPropertyValues(this->Makefile, honorStandard, warnCMP0067,
+ warnCMP0067Variables);
+ cxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
+ warnCMP0067, warnCMP0067Variables);
+ cudaState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
+ warnCMP0067, warnCMP0067Variables);
+ objcState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
+ warnCMP0067, warnCMP0067Variables);
+ objcxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
+ warnCMP0067, warnCMP0067Variables);
- if (!this->WarnCMP0067.empty()) {
+ if (!warnCMP0067Variables.empty()) {
std::ostringstream w;
/* clang-format off */
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0067) << "\n"
@@ -902,43 +861,17 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
"is not honoring language standard variables in the test project:\n"
;
/* clang-format on */
- for (std::string const& vi : this->WarnCMP0067) {
+ for (std::string const& vi : warnCMP0067Variables) {
w << " " << vi << "\n";
}
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
- auto writeLanguageProperties = [&](bool testLang,
- const std::string& langStandard,
- const std::string& langStandardRequired,
- const std::string& langExtensions,
- const std::string& lang) {
- if (testLang) {
- if (!langStandard.empty()) {
- writeProperty(fout, targetName, cmStrCat(lang, "_STANDARD"),
- langStandard);
- }
- if (!langStandardRequired.empty()) {
- writeProperty(fout, targetName, cmStrCat(lang, "_STANDARD_REQUIRED"),
- langStandardRequired);
- }
- if (!langExtensions.empty()) {
- writeProperty(fout, targetName, cmStrCat(lang, "_EXTENSIONS"),
- langExtensions);
- }
- }
- };
-
- writeLanguageProperties(testC, cStandard, cStandardRequired, cExtensions,
- "C");
- writeLanguageProperties(testObjC, objcStandard, objcStandardRequired,
- objcExtensions, "OBJC");
- writeLanguageProperties(testCxx, cxxStandard, cxxStandardRequired,
- cxxExtensions, "CXX");
- writeLanguageProperties(testObjCxx, objcxxStandard, objcxxStandardRequired,
- objcxxExtensions, "OBJCXX");
- writeLanguageProperties(testCuda, cudaStandard, cudaStandardRequired,
- cudaExtensions, "CUDA");
+ cState.WriteProperties(fout, targetName);
+ cxxState.WriteProperties(fout, targetName);
+ cudaState.WriteProperties(fout, targetName);
+ objcState.WriteProperties(fout, targetName);
+ objcxxState.WriteProperties(fout, targetName);
if (!linkOptions.empty()) {
std::vector<std::string> options;
@@ -1112,14 +1045,14 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
const char* config =
this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
// if a config was specified try that first
- if (config && config[0]) {
+ if (cmNonempty(config)) {
std::string tmp = cmStrCat('/', config);
searchDirs.push_back(std::move(tmp));
}
searchDirs.emplace_back("/Debug");
#if defined(__APPLE__)
std::string app = "/" + targetName + ".app";
- if (config && config[0]) {
+ if (cmNonempty(config)) {
std::string tmp = cmStrCat('/', config, app);
searchDirs.push_back(std::move(tmp));
}
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
index ae714a6..916572a 100644
--- a/Source/cmCoreTryCompile.h
+++ b/Source/cmCoreTryCompile.h
@@ -47,10 +47,6 @@ protected:
std::string OutputFile;
std::string FindErrorMessage;
bool SrcFileSignature = false;
-
-private:
- std::vector<std::string> WarnCMP0067;
- std::string LookupStdVar(std::string const& var, bool warnCMP0067);
};
#endif
diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx
index 9d492ba..9c4deea 100644
--- a/Source/cmCreateTestSourceList.cxx
+++ b/Source/cmCreateTestSourceList.cxx
@@ -127,7 +127,7 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args,
mf.AddDefinition("CMAKE_FORWARD_DECLARE_TESTS", forwardDeclareCode);
mf.AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES", functionMapCode);
bool res = true;
- if (!mf.ConfigureFile(configFile, driver, false, true, false)) {
+ if (!mf.ConfigureFile(configFile, driver, false, true, false, true)) {
res = false;
}
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx
index 69a6427..4a4f87d 100644
--- a/Source/cmDefinitions.cxx
+++ b/Source/cmDefinitions.cxx
@@ -19,7 +19,6 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key,
{
auto it = begin->Map.find(cm::String::borrow(key));
if (it != begin->Map.end()) {
- it->second.Used = true;
return it->second;
}
}
@@ -108,16 +107,3 @@ void cmDefinitions::Unset(const std::string& key)
{
this->Map[key] = Def();
}
-
-std::vector<std::string> cmDefinitions::UnusedKeys() const
-{
- std::vector<std::string> keys;
- keys.reserve(this->Map.size());
- // Consider local definitions.
- for (auto const& mi : this->Map) {
- if (!mi.second.Used) {
- keys.push_back(*mi.first.str_if_stable());
- }
- }
- return keys;
-}
diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h
index 0e38fb1..d57750a 100644
--- a/Source/cmDefinitions.h
+++ b/Source/cmDefinitions.h
@@ -48,9 +48,6 @@ public:
/** Unset a definition. */
void Unset(const std::string& key);
- /** List of unused keys. */
- std::vector<std::string> UnusedKeys() const;
-
private:
/** String with existence boolean. */
struct Def
@@ -62,7 +59,6 @@ private:
{
}
cm::String Value;
- bool Used = false;
};
static Def NoDef;
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 8f02d95..54418df 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -395,7 +395,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
<< ' ' << stampFileForShell;
cmMakefile* mf = this->LocalGenerator->GetMakefile();
const char* cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID");
- if (cid && *cid) {
+ if (cmNonempty(cid)) {
makeDepends << ' ' << cid;
}
makeDepends << '\n';
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 9f8a821..352eaf2 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -223,11 +223,9 @@ bool cmExportCommand(std::vector<std::string> const& args,
ebfg->SetExportOld(arguments.ExportOld);
// Compute the set of configurations exported.
- std::vector<std::string> configurationTypes;
- mf.GetConfigurations(configurationTypes);
- if (configurationTypes.empty()) {
- configurationTypes.emplace_back();
- }
+ std::vector<std::string> configurationTypes =
+ mf.GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+
for (std::string const& ct : configurationTypes) {
ebfg->AddConfiguration(ct);
}
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 4d0e099..58aa391 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -567,8 +567,9 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
if (gtarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
getCompatibleInterfaceProperties(gtarget, ifaceProperties, "");
- std::vector<std::string> configNames;
- gtarget->Target->GetMakefile()->GetConfigurations(configNames);
+ std::vector<std::string> configNames =
+ gtarget->Target->GetMakefile()->GetGeneratorConfigs(
+ cmMakefile::ExcludeEmptyConfig);
for (std::string const& cn : configNames) {
getCompatibleInterfaceProperties(gtarget, ifaceProperties, cn);
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 32b0ca9..511168b 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -95,7 +95,7 @@ struct Tree
std::string path; // only one component of the path
std::vector<Tree> folders;
std::set<std::string> files;
- void InsertPath(const std::vector<std::string>& splitted,
+ void InsertPath(const std::vector<std::string>& split,
std::vector<std::string>::size_type start,
const std::string& fileName);
void BuildVirtualFolder(cmXMLWriter& xml) const;
@@ -106,34 +106,34 @@ struct Tree
const std::string& fsPath) const;
};
-void Tree::InsertPath(const std::vector<std::string>& splitted,
+void Tree::InsertPath(const std::vector<std::string>& split,
std::vector<std::string>::size_type start,
const std::string& fileName)
{
- if (start == splitted.size()) {
+ if (start == split.size()) {
files.insert(fileName);
return;
}
for (Tree& folder : folders) {
- if (folder.path == splitted[start]) {
- if (start + 1 < splitted.size()) {
- folder.InsertPath(splitted, start + 1, fileName);
+ if (folder.path == split[start]) {
+ if (start + 1 < split.size()) {
+ folder.InsertPath(split, start + 1, fileName);
return;
}
- // last part of splitted
+ // last part of split
folder.files.insert(fileName);
return;
}
}
// Not found in folders, thus insert
Tree newFolder;
- newFolder.path = splitted[start];
- if (start + 1 < splitted.size()) {
- newFolder.InsertPath(splitted, start + 1, fileName);
+ newFolder.path = split[start];
+ if (start + 1 < split.size()) {
+ newFolder.InsertPath(split, start + 1, fileName);
folders.push_back(newFolder);
return;
}
- // last part of splitted
+ // last part of split
newFolder.files.insert(fileName);
folders.push_back(newFolder);
}
@@ -224,11 +224,11 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
const std::string& relative = cmSystemTools::RelativePath(
it.second[0]->GetSourceDirectory(), listFile);
- std::vector<std::string> splitted;
- cmSystemTools::SplitPath(relative, splitted, false);
+ std::vector<std::string> split;
+ cmSystemTools::SplitPath(relative, split, false);
// Split filename from path
- std::string fileName = *(splitted.end() - 1);
- splitted.erase(splitted.end() - 1, splitted.end());
+ std::string fileName = *(split.end() - 1);
+ split.erase(split.end() - 1, split.end());
// We don't want paths with CMakeFiles in them
// or do we?
@@ -236,13 +236,12 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
//
// Also we can disable external (outside the project) files by setting ON
// CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable.
- const bool excludeExternal =
- cmIsOn(it.second[0]->GetMakefile()->GetSafeDefinition(
- "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES"));
- if (!splitted.empty() &&
+ const bool excludeExternal = it.second[0]->GetMakefile()->IsOn(
+ "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES");
+ if (!split.empty() &&
(!excludeExternal || (relative.find("..") == std::string::npos)) &&
relative.find("CMakeFiles") == std::string::npos) {
- tree.InsertPath(splitted, 1, fileName);
+ tree.InsertPath(split, 1, fileName);
}
}
}
@@ -370,7 +369,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
std::string lang = s->GetOrDetermineLanguage();
if (lang == "C" || lang == "CXX" || lang == "CUDA") {
std::string const& srcext = s->GetExtension();
- isCFile = cm->IsSourceExtension(srcext);
+ isCFile = cm->IsACLikeSourceExtension(srcext);
}
std::string const& fullPath = s->ResolveFullPath();
@@ -380,9 +379,8 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
cmSystemTools::RelativePath(lg->GetSourceDirectory(), fullPath);
// Do not add this file if it has ".." in relative path and
// if CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable is on.
- const bool excludeExternal =
- cmIsOn(lg->GetMakefile()->GetSafeDefinition(
- "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES"));
+ const bool excludeExternal = lg->GetMakefile()->IsOn(
+ "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES");
if (excludeExternal &&
(relative.find("..") != std::string::npos)) {
continue;
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index bf7555d..95cfb0a 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -227,8 +227,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
cmSystemTools::LowerCase(s->GetExtension());
// check whether it is a source or a include file
// then put it accordingly into one of the two containers
- if (cm->IsSourceExtension(extLower) || cm->IsCudaExtension(extLower) ||
- cm->IsFortranExtension(extLower)) {
+ if (cm->IsAKnownSourceExtension(extLower)) {
cFiles[fullPath] = s;
} else {
otherFiles.insert(fullPath);
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 7bc4536..b6c0a7a 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -604,7 +604,7 @@ void cmExtraEclipseCDT4Generator::AppendIncludeDirectories(
void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
{
- std::set<std::string> emmited;
+ std::set<std::string> emitted;
const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0];
const cmMakefile* mf = lg->GetMakefile();
@@ -751,7 +751,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
xml.EndElement();
// add pre-processor definitions to allow eclipse to gray out sections
- emmited.clear();
+ emitted.clear();
for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) {
if (cmProp cdefs =
@@ -780,8 +780,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
}
// insert the definition if not already added.
- if (emmited.find(def) == emmited.end()) {
- emmited.insert(def);
+ if (emitted.find(def) == emitted.end()) {
+ emitted.insert(def);
xml.StartElement("pathentry");
xml.Attribute("kind", "mac");
xml.Attribute("name", def);
@@ -812,8 +812,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
}
// insert the definition if not already added.
- if (emmited.find(def) == emmited.end()) {
- emmited.insert(def);
+ if (emitted.find(def) == emitted.end()) {
+ emitted.insert(def);
xml.StartElement("pathentry");
xml.Attribute("kind", "mac");
xml.Attribute("name", def);
@@ -844,8 +844,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
}
// insert the definition if not already added.
- if (emmited.find(def) == emmited.end()) {
- emmited.insert(def);
+ if (emitted.find(def) == emitted.end()) {
+ emitted.insert(def);
xml.StartElement("pathentry");
xml.Attribute("kind", "mac");
xml.Attribute("name", def);
@@ -858,7 +858,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
}
// include dirs
- emmited.clear();
+ emitted.clear();
for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) {
const auto& targets = lgen->GetGeneratorTargets();
for (const auto& target : targets) {
@@ -868,7 +868,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
std::vector<std::string> includeDirs;
std::string config = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
lgen->GetIncludeDirectories(includeDirs, target.get(), "C", config);
- this->AppendIncludeDirectories(xml, includeDirs, emmited);
+ this->AppendIncludeDirectories(xml, includeDirs, emitted);
}
}
// now also the system include directories, in case we found them in
@@ -879,14 +879,14 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
std::string systemIncludeDirs =
mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
std::vector<std::string> dirs = cmExpandedList(systemIncludeDirs);
- this->AppendIncludeDirectories(xml, dirs, emmited);
+ this->AppendIncludeDirectories(xml, dirs, emitted);
}
compiler = mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
if (this->CXXEnabled && !compiler.empty()) {
std::string systemIncludeDirs =
mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
std::vector<std::string> dirs = cmExpandedList(systemIncludeDirs);
- this->AppendIncludeDirectories(xml, dirs, emmited);
+ this->AppendIncludeDirectories(xml, dirs, emitted);
}
xml.EndElement(); // storageModule
@@ -895,7 +895,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
xml.StartElement("storageModule");
xml.Attribute("moduleId", "org.eclipse.cdt.make.core.buildtargets");
xml.StartElement("buildTargets");
- emmited.clear();
+ emitted.clear();
const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
const std::string& makeArgs =
mf->GetSafeDefinition("CMAKE_ECLIPSE_MAKE_ARGUMENTS");
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 613a943..3e265a0 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -349,6 +349,13 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
if (language.empty()) {
language = "C";
}
+
+ // explicitly add the explicit language flag before any other flag
+ // this way backwards compatibility with user flags is maintained
+ if (source->GetProperty("LANGUAGE")) {
+ lg->AppendFeatureOptions(flags, language, "EXPLICIT_LANGUAGE");
+ }
+
std::string const& config =
lg->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index 594969b..c2ab2f1 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -665,7 +665,7 @@ std::string cmFileAPI::NoSupportedVersion(
// The "codemodel" object kind.
-static unsigned int const CodeModelV2Minor = 1;
+static unsigned int const CodeModelV2Minor = 2;
void cmFileAPI::BuildClientRequestCodeModel(
ClientRequest& r, std::vector<RequestVersion> const& versions)
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index fe331ec..55fb115 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -175,6 +175,38 @@ public:
}
};
+template <typename T>
+class JBTs
+{
+public:
+ JBTs(T v = T(), std::vector<JBTIndex> ids = std::vector<JBTIndex>())
+ : Value(std::move(v))
+ , Backtraces(std::move(ids))
+ {
+ }
+ T Value;
+ std::vector<JBTIndex> Backtraces;
+ friend bool operator==(JBTs<T> const& l, JBTs<T> const& r)
+ {
+ if ((l.Value == r.Value) && (l.Backtraces.size() == r.Backtraces.size())) {
+ for (size_t i = 0; i < l.Backtraces.size(); i++) {
+ if (l.Backtraces[i].Index != r.Backtraces[i].Index) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ static bool ValueEq(JBTs<T> const& l, JBTs<T> const& r)
+ {
+ return l.Value == r.Value;
+ }
+ static bool ValueLess(JBTs<T> const& l, JBTs<T> const& r)
+ {
+ return l.Value < r.Value;
+ }
+};
+
class BacktraceData
{
std::string TopSource;
@@ -277,6 +309,7 @@ struct CompileData
std::string Language;
std::string Sysroot;
+ JBTs<std::string> LanguageStandard;
std::vector<JBT<std::string>> Flags;
std::vector<JBT<std::string>> Defines;
std::vector<JBT<std::string>> PrecompileHeaders;
@@ -287,6 +320,7 @@ struct CompileData
return (l.Language == r.Language && l.Sysroot == r.Sysroot &&
l.Flags == r.Flags && l.Defines == r.Defines &&
l.PrecompileHeaders == r.PrecompileHeaders &&
+ l.LanguageStandard == r.LanguageStandard &&
l.Includes == r.Includes);
}
};
@@ -320,6 +354,12 @@ struct hash<CompileData>
result = result ^ hash<std::string>()(i.Value) ^
hash<Json::ArrayIndex>()(i.Backtrace.Index);
}
+ if (!in.LanguageStandard.Value.empty()) {
+ result = result ^ hash<std::string>()(in.LanguageStandard.Value);
+ for (JBTIndex backtrace : in.LanguageStandard.Backtraces) {
+ result = result ^ hash<Json::ArrayIndex>()(backtrace.Index);
+ }
+ }
return result;
}
};
@@ -363,6 +403,16 @@ class Target
return JBT<T>(bt.Value, this->Backtraces.Add(bt.Backtrace));
}
+ template <typename T>
+ JBTs<T> ToJBTs(BTs<T> const& bts)
+ {
+ std::vector<JBTIndex> ids;
+ for (cmListFileBacktrace const& backtrace : bts.Backtraces) {
+ ids.emplace_back(this->Backtraces.Add(backtrace));
+ }
+ return JBTs<T>(bts.Value, ids);
+ }
+
void ProcessLanguages();
void ProcessLanguage(std::string const& lang);
@@ -377,6 +427,7 @@ class Target
Json::Value DumpCompileData(CompileData const& cd);
Json::Value DumpInclude(CompileData::IncludeEntry const& inc);
Json::Value DumpPrecompileHeader(JBT<std::string> const& header);
+ Json::Value DumpLanguageStandard(JBTs<std::string> const& standard);
Json::Value DumpDefine(JBT<std::string> const& def);
Json::Value DumpSources();
Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
@@ -438,7 +489,7 @@ Json::Value Codemodel::DumpConfigurations()
const auto& makefiles = gg->GetMakefiles();
if (!makefiles.empty()) {
std::vector<std::string> const& configs =
- makefiles[0]->GetGeneratorConfigs();
+ makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
for (std::string const& config : configs) {
configurations.append(this->DumpConfiguration(config));
}
@@ -574,7 +625,7 @@ Json::Value CodemodelConfig::DumpTargets()
for (cmGeneratorTarget* gt : targetList) {
if (gt->GetType() == cmStateEnums::GLOBAL_TARGET ||
- gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ !gt->IsInBuildSystem()) {
continue;
}
@@ -838,6 +889,11 @@ void Target::ProcessLanguage(std::string const& lang)
for (BT<std::string> const& pch : precompileHeaders) {
cd.PrecompileHeaders.emplace_back(this->ToJBT(pch));
}
+ BTs<std::string> const* languageStandard =
+ this->GT->GetLanguageStandardProperty(lang, this->Config);
+ if (languageStandard) {
+ cd.LanguageStandard = this->ToJBTs(*languageStandard);
+ }
}
Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si)
@@ -996,6 +1052,9 @@ CompileData Target::MergeCompileData(CompileData const& fd)
// All compile groups share the precompile headers of the target.
cd.PrecompileHeaders = td.PrecompileHeaders;
+ // All compile groups share the language standard of the target.
+ cd.LanguageStandard = td.LanguageStandard;
+
// Use target-wide flags followed by source-specific flags.
cd.Flags.reserve(td.Flags.size() + fd.Flags.size());
cd.Flags.insert(cd.Flags.end(), td.Flags.begin(), td.Flags.end());
@@ -1153,6 +1212,10 @@ Json::Value Target::DumpCompileData(CompileData const& cd)
}
result["precompileHeaders"] = std::move(precompileHeaders);
}
+ if (!cd.LanguageStandard.Value.empty()) {
+ result["languageStandard"] =
+ this->DumpLanguageStandard(cd.LanguageStandard);
+ }
return result;
}
@@ -1176,6 +1239,20 @@ Json::Value Target::DumpPrecompileHeader(JBT<std::string> const& header)
return precompileHeader;
}
+Json::Value Target::DumpLanguageStandard(JBTs<std::string> const& standard)
+{
+ Json::Value languageStandard = Json::objectValue;
+ languageStandard["standard"] = standard.Value;
+ if (!standard.Backtraces.empty()) {
+ Json::Value backtraces = Json::arrayValue;
+ for (JBTIndex backtrace : standard.Backtraces) {
+ backtraces.append(backtrace.Index);
+ }
+ languageStandard["backtraces"] = backtraces;
+ }
+ return languageStandard;
+}
+
Json::Value Target::DumpDefine(JBT<std::string> const& def)
{
Json::Value define = Json::objectValue;
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 7101e22..8d20d35 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -1394,8 +1394,10 @@ size_t cmWriteToFileCallback(void* ptr, size_t size, size_t nmemb, void* data)
{
int realsize = static_cast<int>(size * nmemb);
cmsys::ofstream* fout = static_cast<cmsys::ofstream*>(data);
- const char* chPtr = static_cast<char*>(ptr);
- fout->write(chPtr, realsize);
+ if (fout) {
+ const char* chPtr = static_cast<char*>(ptr);
+ fout->write(chPtr, realsize);
+ }
return realsize;
}
@@ -1551,15 +1553,14 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
{
#if !defined(CMAKE_BOOTSTRAP)
auto i = args.begin();
- if (args.size() < 3) {
- status.SetError("DOWNLOAD must be called with at least three arguments.");
+ if (args.size() < 2) {
+ status.SetError("DOWNLOAD must be called with at least two arguments.");
return false;
}
++i; // Get rid of subcommand
std::string url = *i;
++i;
- std::string file = *i;
- ++i;
+ std::string file;
long timeout = 0;
long inactivity_timeout = 0;
@@ -1690,6 +1691,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
return false;
}
curl_headers.push_back(*i);
+ } else if (file.empty()) {
+ file = *i;
} else {
// Do not return error for compatibility reason.
std::string err = cmStrCat("Unexpected argument: ", *i);
@@ -1697,11 +1700,18 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
}
++i;
}
+ // Can't calculate hash if we don't save the file.
+ // TODO Incrementally calculate hash in the write callback as the file is
+ // being downloaded so this check can be relaxed.
+ if (file.empty() && hash) {
+ status.SetError("DOWNLOAD cannot calculate hash if file is not saved.");
+ return false;
+ }
// If file exists already, and caller specified an expected md5 or sha,
// and the existing file already has the expected hash, then simply
// return.
//
- if (cmSystemTools::FileExists(file) && hash.get()) {
+ if (!file.empty() && cmSystemTools::FileExists(file) && hash.get()) {
std::string msg;
std::string actualHash = hash->HashFile(file);
if (actualHash == expectedHash) {
@@ -1716,20 +1726,26 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
// Make sure parent directory exists so we can write to the file
// as we receive downloaded bits from curl...
//
- std::string dir = cmSystemTools::GetFilenamePath(file);
- if (!dir.empty() && !cmSystemTools::FileExists(dir) &&
- !cmSystemTools::MakeDirectory(dir)) {
- std::string errstring = "DOWNLOAD error: cannot create directory '" + dir +
- "' - Specify file by full path name and verify that you "
- "have directory creation and file write privileges.";
- status.SetError(errstring);
- return false;
+ if (!file.empty()) {
+ std::string dir = cmSystemTools::GetFilenamePath(file);
+ if (!dir.empty() && !cmSystemTools::FileExists(dir) &&
+ !cmSystemTools::MakeDirectory(dir)) {
+ std::string errstring = "DOWNLOAD error: cannot create directory '" +
+ dir +
+ "' - Specify file by full path name and verify that you "
+ "have directory creation and file write privileges.";
+ status.SetError(errstring);
+ return false;
+ }
}
- cmsys::ofstream fout(file.c_str(), std::ios::binary);
- if (!fout) {
- status.SetError("DOWNLOAD cannot open file for write.");
- return false;
+ cmsys::ofstream fout;
+ if (!file.empty()) {
+ fout.open(file.c_str(), std::ios::binary);
+ if (!fout) {
+ status.SetError("DOWNLOAD cannot open file for write.");
+ return false;
+ }
}
# if defined(_WIN32)
@@ -1791,7 +1807,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
cmFileCommandVectorOfChar chunkDebug;
- res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fout);
+ res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA,
+ file.empty() ? nullptr : &fout);
check_curl_result(res, "DOWNLOAD cannot set write data: ");
res = ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &chunkDebug);
@@ -1865,8 +1882,10 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
// Explicitly flush/close so we can measure the md5 accurately.
//
- fout.flush();
- fout.close();
+ if (!file.empty()) {
+ fout.flush();
+ fout.close();
+ }
// Verify MD5 sum if requested:
//
@@ -2918,7 +2937,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
}
fout.SetCopyIfDifferent(true);
- // copy intput to output and expand variables from input at the same time
+ // copy input to output and expand variables from input at the same time
std::stringstream sin(input, std::ios::in);
std::string inLine;
std::string outLine;
diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx
index 627e05b..5d44a06 100644
--- a/Source/cmFileCopier.cxx
+++ b/Source/cmFileCopier.cxx
@@ -173,7 +173,7 @@ bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode)
// check if default dir creation permissions were set
const char* default_dir_install_permissions = this->Makefile->GetDefinition(
"CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
- if (default_dir_install_permissions && *default_dir_install_permissions) {
+ if (cmNonempty(default_dir_install_permissions)) {
std::vector<std::string> items =
cmExpandedList(default_dir_install_permissions);
for (const auto& arg : items) {
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index 3e97150..3401eff 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -208,10 +208,10 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
const char* sysrootLink =
this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK");
const char* rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
- const bool noSysroot = !sysroot || !*sysroot;
- const bool noCompileSysroot = !sysrootCompile || !*sysrootCompile;
- const bool noLinkSysroot = !sysrootLink || !*sysrootLink;
- const bool noRootPath = !rootPath || !*rootPath;
+ const bool noSysroot = !cmNonempty(sysroot);
+ const bool noCompileSysroot = !cmNonempty(sysrootCompile);
+ const bool noLinkSysroot = !cmNonempty(sysrootLink);
+ const bool noRootPath = !cmNonempty(rootPath);
if (noSysroot && noCompileSysroot && noLinkSysroot && noRootPath) {
return;
}
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 8d5b177..ae06047 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -1121,7 +1121,7 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found)
std::vector<std::string> foundContents;
cmProp foundProp =
this->Makefile->GetState()->GetGlobalProperty("PACKAGES_FOUND");
- if (foundProp && !foundProp->empty()) {
+ if (cmNonempty(foundProp)) {
cmExpandList(*foundProp, foundContents, false);
auto nameIt =
std::find(foundContents.begin(), foundContents.end(), this->Name);
@@ -1133,7 +1133,7 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found)
std::vector<std::string> notFoundContents;
cmProp notFoundProp =
this->Makefile->GetState()->GetGlobalProperty("PACKAGES_NOT_FOUND");
- if (notFoundProp && !notFoundProp->empty()) {
+ if (cmNonempty(notFoundProp)) {
cmExpandList(*notFoundProp, notFoundContents, false);
auto nameIt =
std::find(notFoundContents.begin(), notFoundContents.end(), this->Name);
@@ -1166,9 +1166,9 @@ void cmFindPackageCommand::AppendSuccessInformation()
std::string found = cmStrCat(this->Name, "_FOUND");
std::string upperFound = cmSystemTools::UpperCase(found);
- const char* upperResult = this->Makefile->GetDefinition(upperFound);
- const char* result = this->Makefile->GetDefinition(found);
- bool packageFound = ((cmIsOn(result)) || (cmIsOn(upperResult)));
+ bool upperResult = this->Makefile->IsOn(upperFound);
+ bool result = this->Makefile->IsOn(found);
+ bool packageFound = (result || upperResult);
this->AppendToFoundProperty(packageFound);
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index 4b88bea..77728ec 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -4,6 +4,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -19,6 +20,7 @@ struct cmFindProgramHelper
cmFindProgramHelper(cmMakefile* makefile, cmFindBase const* base)
: DebugSearches("find_program", base)
, Makefile(makefile)
+ , PolicyCMP0109(makefile->GetPolicyStatus(cmPolicies::CMP0109))
{
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
// Consider platform-specific extensions.
@@ -48,6 +50,8 @@ struct cmFindProgramHelper
cmFindBaseDebugState DebugSearches;
cmMakefile* Makefile;
+ cmPolicies::PolicyStatus PolicyCMP0109;
+
void AddName(std::string const& name) { this->Names.push_back(name); }
void SetName(std::string const& name)
{
@@ -85,7 +89,7 @@ struct cmFindProgramHelper
this->TestNameExt = cmStrCat(name, ext);
this->TestPath =
cmSystemTools::CollapseFullPath(this->TestNameExt, path);
- bool exists = cmSystemTools::FileExists(this->TestPath, true);
+ bool exists = this->FileIsExecutable(this->TestPath);
exists ? this->DebugSearches.FoundAt(this->TestPath)
: this->DebugSearches.FailedAt(this->TestPath);
if (exists) {
@@ -95,6 +99,48 @@ struct cmFindProgramHelper
}
return false;
}
+ bool FileIsExecutable(std::string const& file) const
+ {
+ switch (this->PolicyCMP0109) {
+ case cmPolicies::OLD:
+ return cmSystemTools::FileExists(file, true);
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ return cmSystemTools::FileIsExecutable(file);
+ default:
+ break;
+ }
+ bool const isExeOld = cmSystemTools::FileExists(file, true);
+ bool const isExeNew = cmSystemTools::FileIsExecutable(file);
+ if (isExeNew == isExeOld) {
+ return isExeNew;
+ }
+ if (isExeNew) {
+ this->Makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0109),
+ "\n"
+ "The file\n"
+ " ",
+ file,
+ "\n"
+ "is executable but not readable. "
+ "CMake is ignoring it for compatibility."));
+ } else {
+ this->Makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0109),
+ "\n"
+ "The file\n"
+ " ",
+ file,
+ "\n"
+ "is readable but not executable. "
+ "CMake is using it for compatibility."));
+ }
+ return isExeOld;
+ }
};
cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status)
@@ -266,14 +312,13 @@ std::string cmFindProgramCommand::GetBundleExecutable(
if (executableURL != nullptr) {
const int MAX_OSX_PATH_SIZE = 1024;
- char buffer[MAX_OSX_PATH_SIZE];
+ UInt8 buffer[MAX_OSX_PATH_SIZE];
- // Convert the CFString to a C string
- CFStringGetCString(CFURLGetString(executableURL), buffer,
- MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8);
-
- // And finally to a c++ string
- executable = bundlePath + "/Contents/MacOS/" + std::string(buffer);
+ if (CFURLGetFileSystemRepresentation(executableURL, false, buffer,
+ MAX_OSX_PATH_SIZE)) {
+ executable = bundlePath + "/Contents/MacOS/" +
+ std::string(reinterpret_cast<char*>(buffer));
+ }
// Only release CFURLRef if it's not null
CFRelease(executableURL);
}
diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx
index 9cee0e6..2768547 100644
--- a/Source/cmGeneratedFileStream.cxx
+++ b/Source/cmGeneratedFileStream.cxx
@@ -14,10 +14,11 @@
#endif
cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding)
+ : OriginalLocale(getloc())
{
#ifndef CMAKE_BOOTSTRAP
if (encoding != codecvt::None) {
- imbue(std::locale(getloc(), new codecvt(encoding)));
+ imbue(std::locale(OriginalLocale, new codecvt(encoding)));
}
#else
static_cast<void>(encoding);
@@ -122,10 +123,17 @@ void cmGeneratedFileStreamBase::Open(std::string const& name)
// Create the name of the temporary file.
this->TempName = name;
#if defined(__VMS)
- this->TempName += "_tmp";
+ this->TempName += "_";
#else
- this->TempName += ".tmp";
+ this->TempName += ".";
#endif
+ if (!this->TempExt.empty()) {
+ this->TempName += this->TempExt;
+ } else {
+ char buf[64];
+ sprintf(buf, "tmp%05x", cmSystemTools::RandomSeed() & 0xFFFFF);
+ this->TempName += buf;
+ }
// Make sure the temporary file that will be used is not present.
cmSystemTools::RemoveFile(this->TempName);
@@ -216,3 +224,19 @@ void cmGeneratedFileStream::SetName(const std::string& fname)
{
this->Name = fname;
}
+
+void cmGeneratedFileStream::SetTempExt(std::string const& ext)
+{
+ this->TempExt = ext;
+}
+
+void cmGeneratedFileStream::WriteRaw(std::string const& data)
+{
+#ifndef CMAKE_BOOTSTRAP
+ std::locale activeLocale = this->imbue(this->OriginalLocale);
+ this->write(data.data(), data.size());
+ this->imbue(activeLocale);
+#else
+ this->write(data.data(), data.size());
+#endif
+}
diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h
index a9088ac..f6da86e 100644
--- a/Source/cmGeneratedFileStream.h
+++ b/Source/cmGeneratedFileStream.h
@@ -43,6 +43,9 @@ protected:
// The name of the final destination file for the output.
std::string Name;
+ // The extension of the temporary file.
+ std::string TempExt;
+
// The name of the temporary file.
std::string TempName;
@@ -138,6 +141,22 @@ public:
* the output file to be changed during the use of cmGeneratedFileStream.
*/
void SetName(const std::string& fname);
+
+ /**
+ * Set set a custom temporary file extension used with 'Open'.
+ * This does not work if the file was opened by the constructor.
+ */
+ void SetTempExt(std::string const& ext);
+
+ /**
+ * Writes the given string directly to the file without changing the
+ * encoding.
+ */
+ void WriteRaw(std::string const& data);
+
+private:
+ // The original locale of the stream (performs no encoding conversion).
+ std::locale OriginalLocale;
};
#endif
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 6e293d5..840f511 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -406,9 +406,3 @@ const std::string& cmGeneratorExpressionInterpreter::Evaluate(
this->LocalGenerator, this->Config, this->HeadTarget, &dagChecker, nullptr,
this->Language);
}
-
-const std::string& cmGeneratorExpressionInterpreter::Evaluate(
- const char* expression, const std::string& property)
-{
- return this->Evaluate(std::string(expression ? expression : ""), property);
-}
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 75bba02..09d8b88 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -199,8 +199,6 @@ public:
const std::string& Evaluate(std::string expression,
const std::string& property);
- const std::string& Evaluate(const char* expression,
- const std::string& property);
protected:
cmGeneratorExpression GeneratorExpression;
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 4f379cd..e223f15 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -154,6 +154,14 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression() const
return this->Top()->Property == "INTERFACE_POSITION_INDEPENDENT_CODE";
}
+bool cmGeneratorExpressionDAGChecker::EvaluatingCompileExpression() const
+{
+ cm::string_view property(this->Top()->Property);
+
+ return property == "INCLUDE_DIRECTORIES"_s ||
+ property == "COMPILE_DEFINITIONS"_s || property == "COMPILE_OPTIONS"_s;
+}
+
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression() const
{
cm::string_view property(this->Top()->Property);
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index c2c5b6b..ac2314c 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -68,6 +68,7 @@ struct cmGeneratorExpressionDAGChecker
bool EvaluatingGenexExpression() const;
bool EvaluatingPICExpression() const;
+ bool EvaluatingCompileExpression() const;
bool EvaluatingLinkExpression() const;
bool EvaluatingLinkOptionsExpression() const;
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index 9e8707d..1107adb 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -157,12 +157,8 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
std::map<std::string, std::string> outputFiles;
- std::vector<std::string> allConfigs;
- lg->GetMakefile()->GetConfigurations(allConfigs);
-
- if (allConfigs.empty()) {
- allConfigs.emplace_back();
- }
+ std::vector<std::string> allConfigs =
+ lg->GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
std::vector<std::string> enabledLanguages;
cmGlobalGenerator* gg = lg->GetGlobalGenerator();
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index e4fb67e..fdc8f29 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -37,6 +37,7 @@
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmRange.h"
+#include "cmStandardLevelResolver.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
@@ -881,7 +882,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
{
ConfigurationTestNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const override { return OneOrZeroParameters; }
+ int NumExpectedParameters() const override { return ZeroOrMoreParameters; }
std::string Evaluate(
const std::vector<std::string>& parameters,
@@ -899,13 +900,15 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
return std::string();
}
context->HadContextSensitiveCondition = true;
- if (context->Config.empty()) {
- return parameters.front().empty() ? "1" : "0";
- }
-
- if (cmsysString_strcasecmp(parameters.front().c_str(),
- context->Config.c_str()) == 0) {
- return "1";
+ for (auto& param : parameters) {
+ if (context->Config.empty()) {
+ if (param.empty()) {
+ return "1";
+ }
+ } else if (cmsysString_strcasecmp(param.c_str(),
+ context->Config.c_str()) == 0) {
+ return "1";
+ }
}
if (context->CurrentTarget && context->CurrentTarget->IsImported()) {
@@ -922,10 +925,12 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
"MAP_IMPORTED_CONFIG_", cmSystemTools::UpperCase(context->Config));
if (cmProp mapValue = context->CurrentTarget->GetProperty(mapProp)) {
cmExpandList(cmSystemTools::UpperCase(*mapValue), mappedConfigs);
- return cm::contains(mappedConfigs,
- cmSystemTools::UpperCase(parameters.front()))
- ? "1"
- : "0";
+
+ for (auto& param : parameters) {
+ if (cm::contains(mappedConfigs, cmSystemTools::UpperCase(param))) {
+ return "1";
+ }
+ }
}
}
}
@@ -962,9 +967,10 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
{
- if (context->Language.empty()) {
+ if (context->Language.empty() &&
+ (!dagChecker || !dagChecker->EvaluatingCompileExpression())) {
reportError(
context, content->GetOriginalExpression(),
"$<COMPILE_LANGUAGE:...> may only be used to specify include "
@@ -1009,7 +1015,9 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagChecker) const override
{
- if (!context->HeadTarget || context->Language.empty()) {
+ if (!context->HeadTarget ||
+ (context->Language.empty() &&
+ (!dagChecker || !dagChecker->EvaluatingCompileExpression()))) {
// reportError(context, content->GetOriginalExpression(), "");
reportError(
context, content->GetOriginalExpression(),
@@ -1468,8 +1476,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
if (isInterfaceProperty) {
- return target->EvaluateInterfaceProperty(propertyName, context,
- dagCheckerParent);
+ return cmGeneratorExpression::StripEmptyListElements(
+ target->EvaluateInterfaceProperty(propertyName, context,
+ dagCheckerParent));
}
cmGeneratorExpressionDAGChecker dagChecker(
@@ -1555,8 +1564,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
if (!interfacePropertyName.empty()) {
- result = this->EvaluateDependentExpression(result, context->LG, context,
- target, &dagChecker, target);
+ result = cmGeneratorExpression::StripEmptyListElements(
+ this->EvaluateDependentExpression(result, context->LG, context, target,
+ &dagChecker, target));
std::string linkedTargetsContent = getLinkedTargetsContent(
target, interfacePropertyName, context, &dagChecker);
if (!linkedTargetsContent.empty()) {
@@ -1703,12 +1713,12 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
static LangMap availableFeatures;
LangMap testedFeatures;
-
+ cmStandardLevelResolver standardResolver(context->LG->GetMakefile());
for (std::string const& p : parameters) {
std::string error;
std::string lang;
- if (!context->LG->GetMakefile()->CompileFeatureKnown(
- context->HeadTarget->Target, p, lang, &error)) {
+ if (!standardResolver.CompileFeatureKnown(
+ context->HeadTarget->Target->GetName(), p, lang, &error)) {
reportError(context, content->GetOriginalExpression(), error);
return std::string();
}
@@ -1716,7 +1726,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
if (availableFeatures.find(lang) == availableFeatures.end()) {
const char* featuresKnown =
- context->LG->GetMakefile()->CompileFeaturesAvailable(lang, &error);
+ standardResolver.CompileFeaturesAvailable(lang, &error);
if (!featuresKnown) {
reportError(context, content->GetOriginalExpression(), error);
return std::string();
@@ -1741,10 +1751,10 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
// All features known for the language are always available.
continue;
}
- if (!context->LG->GetMakefile()->HaveStandardAvailable(
- target->Target, lit.first, it)) {
+ if (!standardResolver.HaveStandardAvailable(target, lit.first,
+ context->Config, it)) {
if (evalLL) {
- cmProp l = target->GetProperty(lit.first + "_STANDARD");
+ cmProp l = target->GetLanguageStandard(lit.first, context->Config);
if (!l) {
l = standardDefault;
}
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index ab6a26c..9611e14 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -43,6 +43,7 @@
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceFileLocationKind.h"
+#include "cmStandardLevelResolver.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -364,7 +365,7 @@ std::string cmGeneratorTarget::GetExportName() const
{
cmProp exportName = this->GetProperty("EXPORT_NAME");
- if (exportName && !exportName->empty()) {
+ if (cmNonempty(exportName)) {
if (!cmGeneratorExpression::IsValidTargetName(*exportName)) {
std::ostringstream e;
e << "EXPORT_NAME property \"" << *exportName << "\" for \""
@@ -379,11 +380,6 @@ std::string cmGeneratorTarget::GetExportName() const
cmProp cmGeneratorTarget::GetProperty(const std::string& prop) const
{
- if (!cmTargetPropertyComputer::PassesWhitelist(
- this->GetType(), prop, this->Makefile->GetMessenger(),
- this->GetBacktrace())) {
- return nullptr;
- }
if (cmProp result = cmTargetPropertyComputer::GetProperty(
this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) {
return result;
@@ -801,7 +797,8 @@ void cmGeneratorTarget::GetObjectSources(
void cmGeneratorTarget::ComputeObjectMapping()
{
- auto const& configs = this->Makefile->GetGeneratorConfigs();
+ auto const& configs =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
std::set<std::string> configSet(configs.begin(), configs.end());
if (configSet == this->VisitedConfigsForObjects) {
return;
@@ -813,18 +810,18 @@ void cmGeneratorTarget::ComputeObjectMapping()
}
}
-const char* cmGeneratorTarget::GetFeature(const std::string& feature,
- const std::string& config) const
+cmProp cmGeneratorTarget::GetFeature(const std::string& feature,
+ const std::string& config) const
{
if (!config.empty()) {
std::string featureConfig =
cmStrCat(feature, '_', cmSystemTools::UpperCase(config));
if (cmProp value = this->GetProperty(featureConfig)) {
- return value->c_str();
+ return value;
}
}
if (cmProp value = this->GetProperty(feature)) {
- return value->c_str();
+ return value;
}
return this->LocalGenerator->GetFeature(feature, config);
}
@@ -851,10 +848,9 @@ const char* cmGeneratorTarget::GetLinkPIEProperty(
bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
std::string const& config) const
{
- const char* feature = "INTERPROCEDURAL_OPTIMIZATION";
- const bool result = cmIsOn(this->GetFeature(feature, config));
+ cmProp feature = this->GetFeature("INTERPROCEDURAL_OPTIMIZATION", config);
- if (!result) {
+ if (!cmIsOn(feature)) {
// 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies
return false;
}
@@ -947,6 +943,61 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
return it != this->ExplicitObjectName.end();
}
+BTs<std::string> const* cmGeneratorTarget::GetLanguageStandardProperty(
+ std::string const& lang, std::string const& config) const
+{
+ std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang);
+ auto langStandardIter = this->LanguageStandardMap.find(key);
+ if (langStandardIter != this->LanguageStandardMap.end()) {
+ return &langStandardIter->second;
+ }
+
+ return this->Target->GetLanguageStandardProperty(
+ cmStrCat(lang, "_STANDARD"));
+}
+
+cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang,
+ std::string const& config) const
+{
+ BTs<std::string> const* languageStandard =
+ this->GetLanguageStandardProperty(lang, config);
+
+ if (languageStandard) {
+ return &(languageStandard->Value);
+ }
+
+ return nullptr;
+}
+
+cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport(
+ std::string const& lang, const char* suffix) const
+{
+ cmProp propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix));
+ if (propertyValue == nullptr) {
+ // Check if we should use the value set by another language.
+ if (lang == "OBJC") {
+ propertyValue = this->GetPropertyWithPairedLanguageSupport("C", suffix);
+ } else if (lang == "OBJCXX" || lang == "CUDA") {
+ propertyValue =
+ this->GetPropertyWithPairedLanguageSupport("CXX", suffix);
+ }
+ }
+ return propertyValue;
+}
+
+cmProp cmGeneratorTarget::GetLanguageExtensions(std::string const& lang) const
+{
+ return this->GetPropertyWithPairedLanguageSupport(lang, "_EXTENSIONS");
+}
+
+bool cmGeneratorTarget::GetLanguageStandardRequired(
+ std::string const& lang) const
+{
+ cmProp p =
+ this->GetPropertyWithPairedLanguageSupport(lang, "_STANDARD_REQUIRED");
+ return cmIsOn(p);
+}
+
void cmGeneratorTarget::GetModuleDefinitionSources(
std::vector<cmSourceFile const*>& data, const std::string& config) const
{
@@ -1033,6 +1084,62 @@ std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPostBuildCommands()
return this->Target->GetPostBuildCommands();
}
+void cmGeneratorTarget::AppendCustomCommandSideEffects(
+ std::set<cmGeneratorTarget const*>& sideEffects) const
+{
+ if (!this->GetPreBuildCommands().empty() ||
+ !this->GetPreLinkCommands().empty() ||
+ !this->GetPostBuildCommands().empty()) {
+ sideEffects.insert(this);
+ } else {
+ for (auto const& source : this->GetAllConfigSources()) {
+ if (source.Source->GetCustomCommand() != nullptr) {
+ sideEffects.insert(this);
+ break;
+ }
+ }
+ }
+}
+
+void cmGeneratorTarget::AppendLanguageSideEffects(
+ std::map<std::string, std::set<cmGeneratorTarget const*>>& sideEffects) const
+{
+ static const std::set<cm::string_view> LANGS_WITH_NO_SIDE_EFFECTS = {
+ "C"_s, "CXX"_s, "OBJC"_s, "OBJCXX"_s, "ASM"_s, "CUDA"_s,
+ };
+
+ for (auto const& lang : this->GetAllConfigCompileLanguages()) {
+ if (!LANGS_WITH_NO_SIDE_EFFECTS.count(lang)) {
+ sideEffects[lang].insert(this);
+ }
+ }
+}
+
+bool cmGeneratorTarget::IsInBuildSystem() const
+{
+ if (this->IsImported()) {
+ return false;
+ }
+ switch (this->Target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
+ return true;
+ case cmStateEnums::INTERFACE_LIBRARY:
+ // An INTERFACE library is in the build system if it has SOURCES.
+ if (!this->SourceEntries.empty()) {
+ return true;
+ }
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ break;
+ }
+ return false;
+}
+
bool cmGeneratorTarget::IsImported() const
{
return this->Target->IsImported();
@@ -1043,6 +1150,11 @@ bool cmGeneratorTarget::IsImportedGloballyVisible() const
return this->Target->IsImportedGloballyVisible();
}
+bool cmGeneratorTarget::CanCompileSources() const
+{
+ return this->Target->CanCompileSources();
+}
+
const std::string& cmGeneratorTarget::GetLocationForBuild() const
{
static std::string location;
@@ -1137,7 +1249,7 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
// If this target itself has a non-empty property value, we are done.
cmProp p = this->GetProperty(prop);
- maybeInterfaceProp = p && !p->empty();
+ maybeInterfaceProp = cmNonempty(p);
// Otherwise, recurse to interface dependencies.
if (!maybeInterfaceProp) {
@@ -1309,7 +1421,7 @@ void AddSwiftImplicitIncludeDirectories(
for (const cmLinkImplItem& library : libraries->Libraries) {
if (const cmGeneratorTarget* dependency = library.Target) {
- if (dependency->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!dependency->IsInBuildSystem()) {
continue;
}
if (cm::contains(dependency->GetAllConfigCompileLanguages(),
@@ -1466,7 +1578,6 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
std::string const& config) const
{
std::vector<BT<std::string>> files;
- assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
// At configure-time, this method can be called as part of getting the
@@ -1658,9 +1769,11 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
if (sf->GetCustomCommand()) {
kind = SourceKindCustomCommand;
- // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
- // NOLINTNEXTLINE(bugprone-branch-clone)
- } else if (this->Target->GetType() == cmStateEnums::UTILITY) {
+ } else if (this->Target->GetType() == cmStateEnums::UTILITY ||
+ this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY
+ // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
+ // NOLINTNEXTLINE(bugprone-branch-clone)
+ ) {
kind = SourceKindExtra;
} else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) {
kind = SourceKindUnityBatched;
@@ -1726,8 +1839,8 @@ cmGeneratorTarget::GetAllConfigSources() const
void cmGeneratorTarget::ComputeAllConfigSources() const
{
- std::vector<std::string> configs;
- this->Makefile->GetConfigurations(configs);
+ std::vector<std::string> configs =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
std::map<cmSourceFile const*, size_t> index;
@@ -1787,12 +1900,12 @@ std::string cmGeneratorTarget::GetCompilePDBName(
std::string configUpper = cmSystemTools::UpperCase(config);
std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper);
cmProp config_name = this->GetProperty(configProp);
- if (config_name && !config_name->empty()) {
+ if (cmNonempty(config_name)) {
return prefix + *config_name + ".pdb";
}
cmProp name = this->GetProperty("COMPILE_PDB_NAME");
- if (name && !name->empty()) {
+ if (cmNonempty(name)) {
return prefix + *name + ".pdb";
}
@@ -1939,7 +2052,7 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
std::string sepVar =
cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP");
const char* sep = this->Makefile->GetDefinition(sepVar);
- if (sep && *sep) {
+ if (cmNonempty(sep)) {
// TODO: Add ELF check to ABI detection and get rid of
// CMAKE_EXECUTABLE_FORMAT.
if (const char* fmt =
@@ -2239,7 +2352,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree(
cmProp install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
- if (install_name_dir && !install_name_dir->empty()) {
+ if (cmNonempty(install_name_dir)) {
dir = *install_name_dir;
cmGeneratorExpression::ReplaceInstallPrefix(dir, installPrefix);
dir =
@@ -2385,6 +2498,12 @@ private:
cmGeneratorTarget::LinkClosure const* cmGeneratorTarget::GetLinkClosure(
const std::string& config) const
{
+ // There is no link implementation for targets that cannot compile sources.
+ if (!this->CanCompileSources()) {
+ static LinkClosure const empty = { {}, {} };
+ return &empty;
+ }
+
std::string key(cmSystemTools::UpperCase(config));
auto i = this->LinkClosureMap.find(key);
if (i == this->LinkClosureMap.end()) {
@@ -2701,6 +2820,12 @@ const std::vector<const cmGeneratorTarget*>&
cmGeneratorTarget::GetLinkImplementationClosure(
const std::string& config) const
{
+ // There is no link implementation for targets that cannot compile sources.
+ if (!this->CanCompileSources()) {
+ static std::vector<const cmGeneratorTarget*> const empty;
+ return empty;
+ }
+
LinkImplClosure& tgts = this->LinkImplClosureMap[config];
if (!tgts.Done) {
tgts.Done = true;
@@ -2708,6 +2833,7 @@ cmGeneratorTarget::GetLinkImplementationClosure(
cmLinkImplementationLibraries const* impl =
this->GetLinkImplementationLibraries(config);
+ assert(impl);
for (cmLinkImplItem const& lib : impl->Libraries) {
processILibs(config, this, lib,
@@ -2757,29 +2883,26 @@ cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target)
this->CurrentEntry = nullptr;
// Queue all the source files already specified for the target.
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- std::set<cmSourceFile*> emitted;
- std::vector<std::string> const& configs =
- this->Makefile->GetGeneratorConfigs();
- for (std::string const& c : configs) {
- std::vector<cmSourceFile*> sources;
- this->GeneratorTarget->GetSourceFiles(sources, c);
- for (cmSourceFile* sf : sources) {
- const std::set<cmGeneratorTarget const*> tgts =
- this->GlobalGenerator->GetFilenameTargetDepends(sf);
- if (cm::contains(tgts, this->GeneratorTarget)) {
- std::ostringstream e;
- e << "Evaluation output file\n \"" << sf->ResolveFullPath()
- << "\"\ndepends on the sources of a target it is used in. This "
- "is a dependency loop and is not allowed.";
- this->GeneratorTarget->LocalGenerator->IssueMessage(
- MessageType::FATAL_ERROR, e.str());
- return;
- }
- if (emitted.insert(sf).second &&
- this->SourcesQueued.insert(sf).second) {
- this->SourceQueue.push(sf);
- }
+ std::set<cmSourceFile*> emitted;
+ std::vector<std::string> const& configs =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+ for (std::string const& c : configs) {
+ std::vector<cmSourceFile*> sources;
+ this->GeneratorTarget->GetSourceFiles(sources, c);
+ for (cmSourceFile* sf : sources) {
+ const std::set<cmGeneratorTarget const*> tgts =
+ this->GlobalGenerator->GetFilenameTargetDepends(sf);
+ if (cm::contains(tgts, this->GeneratorTarget)) {
+ std::ostringstream e;
+ e << "Evaluation output file\n \"" << sf->ResolveFullPath()
+ << "\"\ndepends on the sources of a target it is used in. This "
+ "is a dependency loop and is not allowed.";
+ this->GeneratorTarget->LocalGenerator->IssueMessage(
+ MessageType::FATAL_ERROR, e.str());
+ return;
+ }
+ if (emitted.insert(sf).second && this->SourcesQueued.insert(sf).second) {
+ this->SourceQueue.push(sf);
}
}
}
@@ -2971,7 +3094,7 @@ void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
// Queue the custom command dependencies.
std::set<std::string> emitted;
std::vector<std::string> const& configs =
- this->Makefile->GetGeneratorConfigs();
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
for (std::string const& conf : configs) {
this->FollowCommandDepends(cc, conf, emitted);
}
@@ -3111,7 +3234,7 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
} else {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- "Uknown CUDA architecture specifier \"" + std::string(specifier) +
+ "Unknown CUDA architecture specifier \"" + std::string(specifier) +
"\".");
}
}
@@ -3360,23 +3483,24 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
&dagChecker, entries);
if (this->Makefile->IsOn("APPLE")) {
- cmLinkImplementationLibraries const* impl =
- this->GetLinkImplementationLibraries(config);
- for (cmLinkImplItem const& lib : impl->Libraries) {
- std::string libDir = cmSystemTools::CollapseFullPath(
- lib.AsStr(), this->Makefile->GetHomeOutputDirectory());
-
- static cmsys::RegularExpression frameworkCheck(
- "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
- if (!frameworkCheck.find(libDir)) {
- continue;
- }
+ if (cmLinkImplementationLibraries const* impl =
+ this->GetLinkImplementationLibraries(config)) {
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ std::string libDir = cmSystemTools::CollapseFullPath(
+ lib.AsStr(), this->Makefile->GetHomeOutputDirectory());
+
+ static cmsys::RegularExpression frameworkCheck(
+ "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
+ if (!frameworkCheck.find(libDir)) {
+ continue;
+ }
- libDir = frameworkCheck.match(1);
+ libDir = frameworkCheck.match(1);
- EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace());
- ee.Values.emplace_back(std::move(libDir));
- entries.Entries.emplace_back(std::move(ee));
+ EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace());
+ ee.Values.emplace_back(std::move(libDir));
+ entries.Entries.emplace_back(std::move(ee));
+ }
}
}
@@ -3827,7 +3951,7 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config,
cmStrCat(generatorTarget->LocalGenerator->GetCurrentBinaryDirectory(),
"/CMakeFiles/", generatorTarget->GetName(), ".dir/cmake_pch");
- // For GCC the source extension will be tranformed into .h[xx].gch
+ // For GCC the source extension will be transformed into .h[xx].gch
if (!this->Makefile->IsOn("CMAKE_LINK_PCH")) {
const std::map<std::string, std::string> languageToExtension = {
{ "C", ".h.c" },
@@ -4414,12 +4538,75 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
{
+ // Compute the language standard based on the compile features.
+ cmStandardLevelResolver standardResolver(this->Makefile);
std::vector<BT<std::string>> features = this->GetCompileFeatures(config);
for (BT<std::string> const& f : features) {
- if (!this->Makefile->AddRequiredTargetFeature(this->Target, f.Value)) {
+ std::string lang;
+ if (!standardResolver.CompileFeatureKnown(this->Target->GetName(), f.Value,
+ lang, nullptr)) {
+ return false;
+ }
+
+ std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang);
+ cmProp currentLanguageStandard = this->GetLanguageStandard(lang, config);
+
+ std::string newRequiredStandard;
+ if (!standardResolver.GetNewRequiredStandard(
+ this->Target->GetName(), f.Value, currentLanguageStandard,
+ newRequiredStandard)) {
return false;
}
+
+ if (!newRequiredStandard.empty()) {
+ BTs<std::string>& languageStandardProperty =
+ this->LanguageStandardMap[key];
+ if (languageStandardProperty.Value != newRequiredStandard) {
+ languageStandardProperty.Value = newRequiredStandard;
+ languageStandardProperty.Backtraces.clear();
+ }
+ languageStandardProperty.Backtraces.emplace_back(f.Backtrace);
+ }
+ }
+
+ return true;
+}
+
+bool cmGeneratorTarget::ComputeCompileFeatures(
+ std::string const& config, std::set<LanguagePair> const& languagePairs) const
+{
+ for (const auto& language : languagePairs) {
+ BTs<std::string> const* generatorTargetLanguageStandard =
+ this->GetLanguageStandardProperty(language.first, config);
+ if (!generatorTargetLanguageStandard) {
+ // If the standard isn't explicitly set we copy it over from the
+ // specified paired language.
+ std::string key =
+ cmStrCat(cmSystemTools::UpperCase(config), '-', language.first);
+ BTs<std::string> const* standardToCopy =
+ this->GetLanguageStandardProperty(language.second, config);
+ if (standardToCopy != nullptr) {
+ this->LanguageStandardMap[key] = *standardToCopy;
+ generatorTargetLanguageStandard = &this->LanguageStandardMap[key];
+ } else {
+ cmProp defaultStandard = this->Makefile->GetDef(
+ cmStrCat("CMAKE_", language.second, "_STANDARD_DEFAULT"));
+ if (defaultStandard != nullptr) {
+ this->LanguageStandardMap[key] = BTs<std::string>(*defaultStandard);
+ generatorTargetLanguageStandard = &this->LanguageStandardMap[key];
+ }
+ }
+
+ // Custom updates for the CUDA standard.
+ if (generatorTargetLanguageStandard != nullptr &&
+ language.first == "CUDA") {
+ if (generatorTargetLanguageStandard->Value == "98") {
+ this->LanguageStandardMap[key].Value = "03";
+ }
+ }
+ }
}
+
return true;
}
@@ -5297,8 +5484,7 @@ bool getTypedProperty<bool>(cmGeneratorTarget const* tgt,
}
cmProp value = tgt->GetProperty(prop);
- return cmIsOn(
- genexInterpreter->Evaluate(value ? value->c_str() : nullptr, prop));
+ return cmIsOn(genexInterpreter->Evaluate(value ? *value : "", prop));
}
template <>
@@ -5312,8 +5498,7 @@ const char* getTypedProperty<const char*>(
return value ? value->c_str() : nullptr;
}
- return genexInterpreter->Evaluate(value ? value->c_str() : nullptr, prop)
- .c_str();
+ return genexInterpreter->Evaluate(value ? *value : "", prop).c_str();
}
template <>
@@ -5327,7 +5512,7 @@ std::string getTypedProperty<std::string>(
return valueAsString(value ? value->c_str() : nullptr);
}
- return genexInterpreter->Evaluate(value ? value->c_str() : nullptr, prop);
+ return genexInterpreter->Evaluate(value ? *value : "", prop);
}
template <typename PropertyType>
@@ -5728,7 +5913,7 @@ std::string cmGeneratorTarget::GetRuntimeLinkLibrary(
// not it is overridden by a property.
cmProp runtimeLibraryDefault = this->Makefile->GetDef(
cmStrCat("CMAKE_", lang, "_RUNTIME_LIBRARY_DEFAULT"));
- if (!runtimeLibraryDefault || runtimeLibraryDefault->empty()) {
+ if (!cmNonempty(runtimeLibraryDefault)) {
return std::string();
}
cmProp runtimeLibraryValue =
@@ -6410,15 +6595,20 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
iface.HadHeadSensitiveCondition,
iface.HadContextSensitiveCondition,
iface.HadLinkLanguageSensitiveCondition);
- } else if (!cmp0022NEW)
+ return;
+ }
+
// 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.
- {
- // The link implementation is the default link interface.
- cmLinkImplementationLibraries const* impl =
- this->GetLinkImplementationLibrariesInternal(config, headTarget);
+ if (cmp0022NEW) {
+ return;
+ }
+
+ // The link implementation is the default link interface.
+ if (cmLinkImplementationLibraries const* impl =
+ this->GetLinkImplementationLibrariesInternal(config, headTarget)) {
iface.Libraries.insert(iface.Libraries.end(), impl->Libraries.begin(),
impl->Libraries.end());
if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
@@ -6712,8 +6902,8 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
const std::string& config, bool secondPass) const
{
- // There is no link implementation for imported targets.
- if (this->IsImported()) {
+ // There is no link implementation for targets that cannot compile sources.
+ if (!this->CanCompileSources()) {
return nullptr;
}
@@ -6737,7 +6927,7 @@ bool cmGeneratorTarget::GetConfigCommonSourceFiles(
std::vector<cmSourceFile*>& files) const
{
std::vector<std::string> const& configs =
- this->Makefile->GetGeneratorConfigs();
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
auto it = configs.begin();
const std::string& firstConfig = *it;
@@ -6861,7 +7051,7 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const
bool cmGeneratorTarget::IsDeprecated() const
{
cmProp deprecation = this->GetProperty("DEPRECATION");
- return deprecation && !deprecation->empty();
+ return cmNonempty(deprecation);
}
std::string cmGeneratorTarget::GetDeprecation() const
@@ -6876,6 +7066,11 @@ std::string cmGeneratorTarget::GetDeprecation() const
void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages,
const std::string& config) const
{
+ // Targets that do not compile anything have no languages.
+ if (!this->CanCompileSources()) {
+ return;
+ }
+
std::vector<cmSourceFile*> sourceFiles;
this->GetSourceFiles(sourceFiles, config);
for (cmSourceFile* src : sourceFiles) {
@@ -6926,7 +7121,7 @@ bool cmGeneratorTarget::IsCSharpOnly() const
// Consider an explicit linker language property, but *not* the
// computed linker language that may depend on linked targets.
cmProp linkLang = this->GetProperty("LINKER_LANGUAGE");
- if (linkLang && !linkLang->empty()) {
+ if (cmNonempty(linkLang)) {
languages.insert(*linkLang);
}
return languages.size() == 1 && languages.count("CSharp") > 0;
@@ -6971,8 +7166,8 @@ cmLinkImplementationLibraries const*
cmGeneratorTarget::GetLinkImplementationLibrariesInternal(
const std::string& config, cmGeneratorTarget const* head) const
{
- // There is no link implementation for imported targets.
- if (this->IsImported()) {
+ // There is no link implementation for targets that cannot compile sources.
+ if (!this->CanCompileSources()) {
return nullptr;
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 3aedbf5..69c5faf 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -45,14 +45,22 @@ public:
cmGlobalGenerator* GetGlobalGenerator() const;
+ bool IsInBuildSystem() const;
bool IsImported() const;
bool IsImportedGloballyVisible() const;
+ bool CanCompileSources() const;
const std::string& GetLocation(const std::string& config) const;
std::vector<cmCustomCommand> const& GetPreBuildCommands() const;
std::vector<cmCustomCommand> const& GetPreLinkCommands() const;
std::vector<cmCustomCommand> const& GetPostBuildCommands() const;
+ void AppendCustomCommandSideEffects(
+ std::set<cmGeneratorTarget const*>& sideEffects) const;
+ void AppendLanguageSideEffects(
+ std::map<std::string, std::set<cmGeneratorTarget const*>>& sideEffects)
+ const;
+
#define DECLARE_TARGET_POLICY(POLICY) \
cmPolicies::PolicyStatus GetPolicyStatus##POLICY() const \
{ \
@@ -148,6 +156,16 @@ public:
bool HasExplicitObjectName(cmSourceFile const* file) const;
void AddExplicitObjectName(cmSourceFile const* sf);
+ BTs<std::string> const* GetLanguageStandardProperty(
+ std::string const& lang, std::string const& config) const;
+
+ cmProp GetLanguageStandard(std::string const& lang,
+ std::string const& config) const;
+
+ cmProp GetLanguageExtensions(std::string const& lang) const;
+
+ bool GetLanguageStandardRequired(std::string const& lang) const;
+
void GetModuleDefinitionSources(std::vector<cmSourceFile const*>&,
const std::string& config) const;
void GetExternalObjects(std::vector<cmSourceFile const*>&,
@@ -165,8 +183,8 @@ public:
void ComputeObjectMapping();
- const char* GetFeature(const std::string& feature,
- const std::string& config) const;
+ cmProp GetFeature(const std::string& feature,
+ const std::string& config) const;
const char* GetLinkPIEProperty(const std::string& config) const;
@@ -515,6 +533,11 @@ public:
bool ComputeCompileFeatures(std::string const& config) const;
+ using LanguagePair = std::pair<std::string, std::string>;
+ bool ComputeCompileFeatures(
+ std::string const& config,
+ std::set<LanguagePair> const& languagePairs) const;
+
/**
* Trace through the source files in this target and add al source files
* that they depend on, used by all generators
@@ -1038,6 +1061,11 @@ private:
bool GetRPATH(const std::string& config, const std::string& prop,
std::string& rpath) const;
+ mutable std::map<std::string, BTs<std::string>> LanguageStandardMap;
+
+ cmProp GetPropertyWithPairedLanguageSupport(std::string const& lang,
+ const char* suffix) const;
+
public:
const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
const std::string& config) const;
diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx
index 811421a..38bffbf 100644
--- a/Source/cmGetFilenameComponentCommand.cxx
+++ b/Source/cmGetFilenameComponentCommand.cxx
@@ -14,6 +14,7 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,
{
if (args.size() < 3) {
status.SetError("called with incorrect number of arguments");
+ cmSystemTools::SetFatalErrorOccured();
return false;
}
@@ -114,6 +115,7 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,
} else {
std::string err = "unknown component " + args[2];
status.SetError(err);
+ cmSystemTools::SetFatalErrorOccured();
return false;
}
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index cba7704..cdfd8c8 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -17,7 +17,6 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmTargetPropertyComputer.h"
#include "cmTest.h"
#include "cmake.h"
@@ -364,12 +363,9 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
cmProp prop_cstr = nullptr;
cmListFileBacktrace bt = status.GetMakefile().GetBacktrace();
cmMessenger* messenger = status.GetMakefile().GetMessenger();
- if (cmTargetPropertyComputer::PassesWhitelist(
- target->GetType(), propertyName, messenger, bt)) {
- prop_cstr = target->GetComputedProperty(propertyName, messenger, bt);
- if (!prop_cstr) {
- prop_cstr = target->GetProperty(propertyName);
- }
+ prop_cstr = target->GetComputedProperty(propertyName, messenger, bt);
+ if (!prop_cstr) {
+ prop_cstr = target->GetProperty(propertyName);
}
return StoreResult(infoType, status.GetMakefile(), variable,
prop_cstr ? prop_cstr->c_str() : nullptr);
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index 8a304be..78a17d2 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -12,7 +12,6 @@
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmTarget.h"
-#include "cmTargetPropertyComputer.h"
class cmMessenger;
@@ -46,12 +45,9 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
cmProp prop_cstr = nullptr;
cmListFileBacktrace bt = mf.GetBacktrace();
cmMessenger* messenger = mf.GetMessenger();
- if (cmTargetPropertyComputer::PassesWhitelist(tgt->GetType(), args[2],
- messenger, bt)) {
- prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt);
- if (!prop_cstr) {
- prop_cstr = tgt->GetProperty(args[2]);
- }
+ prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt);
+ if (!prop_cstr) {
+ prop_cstr = tgt->GetProperty(args[2]);
}
if (prop_cstr) {
prop = *prop_cstr;
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 97580d6..1589c47 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -550,10 +550,9 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
*/
for (auto& sg : groupFilesList) {
std::ostream* fout;
- cmProp noSourceGroupFile =
- this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE");
- bool useProjectFile = (noSourceGroupFile && cmIsOn(*noSourceGroupFile)) ||
- cmIsOn(this->Makefile->GetDefinition("CMAKE_GHS_NO_SOURCE_GROUP_FILE"));
+ bool useProjectFile =
+ cmIsOn(this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE")) ||
+ this->Makefile->IsOn("CMAKE_GHS_NO_SOURCE_GROUP_FILE");
if (useProjectFile || sg.empty()) {
fout = &fout_proj;
} else {
diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h
index f03ca44..5f26387 100644
--- a/Source/cmGhsMultiTargetGenerator.h
+++ b/Source/cmGhsMultiTargetGenerator.h
@@ -43,7 +43,7 @@ private:
void SetCompilerFlags(std::string const& config,
const std::string& language);
- std::string GetDefines(const std::string& langugae,
+ std::string GetDefines(const std::string& language,
std::string const& config);
void WriteIncludes(std::ostream& fout, const std::string& config,
diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx
index 9dc86f4..9e5bbca 100644
--- a/Source/cmGlobalCommonGenerator.cxx
+++ b/Source/cmGlobalCommonGenerator.cxx
@@ -5,8 +5,12 @@
#include <memory>
#include <utility>
+#include <cmext/algorithm>
+
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
#include "cmProperty.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
@@ -31,26 +35,30 @@ cmGlobalCommonGenerator::ComputeDirectoryTargets() const
lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
DirectoryTarget& dirTarget = dirTargets[currentBinaryDir];
dirTarget.LG = lg.get();
+ const std::vector<std::string>& configs =
+ lg->GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
// The directory-level rule should depend on the target-level rules
// for all targets in the directory.
for (const auto& gt : lg->GetGeneratorTargets()) {
cmStateEnums::TargetType const type = gt->GetType();
- if (type != cmStateEnums::EXECUTABLE &&
- type != cmStateEnums::STATIC_LIBRARY &&
- type != cmStateEnums::SHARED_LIBRARY &&
- type != cmStateEnums::MODULE_LIBRARY &&
- type != cmStateEnums::OBJECT_LIBRARY &&
- type != cmStateEnums::UTILITY) {
+ if (type == cmStateEnums::GLOBAL_TARGET || !gt->IsInBuildSystem()) {
continue;
}
DirectoryTarget::Target t;
t.GT = gt.get();
- if (cmProp exclude = gt->GetProperty("EXCLUDE_FROM_ALL")) {
- if (cmIsOn(*exclude)) {
- // This target has been explicitly excluded.
- t.ExcludeFromAll = true;
- } else {
+ const std::string EXCLUDE_FROM_ALL("EXCLUDE_FROM_ALL");
+ if (cmProp exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) {
+ for (const std::string& config : configs) {
+ cmGeneratorExpressionInterpreter genexInterpreter(lg.get(), config,
+ gt.get());
+ if (cmIsOn(genexInterpreter.Evaluate(*exclude, EXCLUDE_FROM_ALL))) {
+ // This target has been explicitly excluded.
+ t.ExcludedFromAllInConfigs.push_back(config);
+ }
+ }
+
+ if (t.ExcludedFromAllInConfigs.empty()) {
// This target has been explicitly un-excluded. The directory-level
// rule for every directory between this and the root should depend
// on the target-level rule for this target.
@@ -78,3 +86,12 @@ cmGlobalCommonGenerator::ComputeDirectoryTargets() const
return dirTargets;
}
+
+bool cmGlobalCommonGenerator::IsExcludedFromAllInConfig(
+ const DirectoryTarget::Target& t, const std::string& config)
+{
+ if (this->IsMultiConfig()) {
+ return cm::contains(t.ExcludedFromAllInConfigs, config);
+ }
+ return !t.ExcludedFromAllInConfigs.empty();
+}
diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h
index 7d16dac..f97b5f4 100644
--- a/Source/cmGlobalCommonGenerator.h
+++ b/Source/cmGlobalCommonGenerator.h
@@ -30,7 +30,7 @@ public:
struct Target
{
cmGeneratorTarget const* GT = nullptr;
- bool ExcludeFromAll = false;
+ std::vector<std::string> ExcludedFromAllInConfigs;
};
std::vector<Target> Targets;
struct Dir
@@ -41,6 +41,8 @@ public:
std::vector<Dir> Children;
};
std::map<std::string, DirectoryTarget> ComputeDirectoryTargets() const;
+ bool IsExcludedFromAllInConfig(const DirectoryTarget::Target& t,
+ const std::string& config);
};
#endif
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 4dc4092..cad5d1f 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -235,6 +235,14 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
}
cmProp cname =
this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp);
+
+ // Split compiler from arguments
+ std::vector<std::string> cnameArgVec;
+ if (cname && !cname->empty()) {
+ cmExpandList(*cname, cnameArgVec);
+ cname = &cnameArgVec.front();
+ }
+
std::string changeVars;
if (cname && !optional) {
std::string cnameString;
@@ -302,31 +310,12 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const
bool failed = false;
for (const auto& localGen : this->LocalGenerators) {
for (const auto& target : localGen->GetGeneratorTargets()) {
- if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
- target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
- target->GetType() == cmStateEnums::TargetType::UTILITY) {
+ if (!target->CanCompileSources() ||
+ cmIsOn(target->GetProperty("ghs_integrity_app"))) {
continue;
}
- if (cmProp p = target->GetProperty("ghs_integrity_app")) {
- if (cmIsOn(*p)) {
- continue;
- }
- }
- std::vector<std::string> configs;
- target->Makefile->GetConfigurations(configs);
- std::vector<cmSourceFile*> srcs;
- if (configs.empty()) {
- target->GetSourceFiles(srcs, "");
- } else {
- for (std::string const& config : configs) {
- target->GetSourceFiles(srcs, config);
- if (!srcs.empty()) {
- break;
- }
- }
- }
- if (srcs.empty()) {
+ if (target->GetAllConfigSources().empty()) {
std::ostringstream e;
e << "No SOURCES given to target: " << target->GetName();
this->GetCMakeInstance()->IssueMessage(
@@ -349,7 +338,8 @@ bool cmGlobalGenerator::CheckTargetsForType() const
if (target->GetType() == cmStateEnums::EXECUTABLE &&
target->GetPropertyAsBool("WIN32_EXECUTABLE")) {
std::vector<std::string> const& configs =
- target->Makefile->GetGeneratorConfigs();
+ target->Makefile->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig);
for (std::string const& config : configs) {
if (target->GetLinkerLanguage(config) == "Swift") {
this->GetCMakeInstance()->IssueMessage(
@@ -374,16 +364,10 @@ bool cmGlobalGenerator::CheckTargetsForPchCompilePdb() const
bool failed = false;
for (const auto& generator : this->LocalGenerators) {
for (const auto& target : generator->GetGeneratorTargets()) {
- if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
- target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
- target->GetType() == cmStateEnums::TargetType::UTILITY) {
+ if (!target->CanCompileSources() ||
+ cmIsOn(target->GetProperty("ghs_integrity_app"))) {
continue;
}
- if (cmProp p = target->GetProperty("ghs_integrity_app")) {
- if (cmIsOn(*p)) {
- continue;
- }
- }
std::string const& reuseFrom =
target->GetSafeProperty("PRECOMPILE_HEADERS_REUSE_FROM");
@@ -425,15 +409,13 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
"all generators must specify this->FindMakeProgramFile");
return false;
}
- if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") ||
- cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
+ if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
std::string setMakeProgram = mf->GetModulesFile(this->FindMakeProgramFile);
if (!setMakeProgram.empty()) {
mf->ReadListFile(setMakeProgram);
}
}
- if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") ||
- cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
+ if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
std::ostringstream err;
err << "CMake was unable to find a build program corresponding to \""
<< this->GetName() << "\". CMAKE_MAKE_PROGRAM is not set. You "
@@ -596,6 +578,16 @@ void cmGlobalGenerator::EnableLanguage(
mf->ReadListFile(fpath);
}
}
+
+ if (readCMakeSystem) {
+ // Find the native build tool for this generator.
+ // This has to be done early so that MSBuild can be used to examine the
+ // cross-compilation environment.
+ if (!this->FindMakeProgram(mf)) {
+ return;
+ }
+ }
+
// Load the CMakeDetermineSystem.cmake file and find out
// what platform we are running on
if (!mf->GetDefinition("CMAKE_SYSTEM")) {
@@ -667,11 +659,6 @@ void cmGlobalGenerator::EnableLanguage(
cmSystemTools::SetFatalErrorOccured();
return;
}
-
- // Find the native build tool for this generator.
- if (!this->FindMakeProgram(mf)) {
- return;
- }
}
// Check that the languages are supported by the generator and its
@@ -794,7 +781,7 @@ void cmGlobalGenerator::EnableLanguage(
std::string compilerEnv = cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR");
std::ostringstream noCompiler;
const char* compilerFile = mf->GetDefinition(compilerName);
- if (!compilerFile || !*compilerFile || cmIsNOTFOUND(compilerFile)) {
+ if (!cmNonempty(compilerFile) || cmIsNOTFOUND(compilerFile)) {
/* clang-format off */
noCompiler <<
"No " << compilerName << " could be found.\n"
@@ -1442,12 +1429,10 @@ bool cmGlobalGenerator::Compute()
localGen->AddHelperCommands();
}
- // Finalize the set of compile features for each target.
- // FIXME: This turns into calls to cmMakefile::AddRequiredTargetFeature
- // which actually modifies the <lang>_STANDARD target property
- // on the original cmTarget instance. It accumulates features
- // across all configurations. Some refactoring is needed to
- // compute a per-config resulta purely during generation.
+ // Perform up-front computation in order to handle errors (such as unknown
+ // features) at this point. While processing the compile features we also
+ // calculate and cache the language standard required by the compile
+ // features.
for (const auto& localGen : this->LocalGenerators) {
if (!localGen->ComputeTargetCompileFeatures()) {
return false;
@@ -1612,9 +1597,7 @@ bool cmGlobalGenerator::AddAutomaticSources()
for (const auto& lg : this->LocalGenerators) {
lg->CreateEvaluationFileOutputs();
for (const auto& gt : lg->GetGeneratorTargets()) {
- if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
- gt->GetType() == cmStateEnums::UTILITY ||
- gt->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ if (!gt->CanCompileSources()) {
continue;
}
lg->AddUnityBuild(gt.get());
@@ -1626,9 +1609,7 @@ bool cmGlobalGenerator::AddAutomaticSources()
}
for (const auto& lg : this->LocalGenerators) {
for (const auto& gt : lg->GetGeneratorTargets()) {
- if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
- gt->GetType() == cmStateEnums::UTILITY ||
- gt->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ if (!gt->CanCompileSources()) {
continue;
}
// Handle targets that re-use a PCH from an above-handled target.
@@ -1698,8 +1679,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
cmPolicies::PolicyStatus polSt =
mf->GetPolicyStatus(cmPolicies::CMP0043);
if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
- std::vector<std::string> configs;
- mf->GetConfigurations(configs);
+ std::vector<std::string> configs =
+ mf->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
for (std::string const& c : configs) {
std::string defPropName =
@@ -1988,8 +1969,9 @@ int cmGlobalGenerator::Build(
std::string makeCommandStr;
output += "\nRun Build Command(s):";
- for (auto command = makeCommand.begin(); command != makeCommand.end();
- ++command) {
+ retVal = 0;
+ for (auto command = makeCommand.begin();
+ command != makeCommand.end() && retVal == 0; ++command) {
makeCommandStr = command->Printable();
if (command != makeCommand.end()) {
makeCommandStr += " && ";
@@ -2179,13 +2161,38 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
}
bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
- cmGeneratorTarget* target) const
+ const cmGeneratorTarget* target) const
{
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
return true;
}
- if (cmProp exclude = target->GetProperty("EXCLUDE_FROM_ALL")) {
- return cmIsOn(*exclude);
+ cmMakefile* mf = root->GetMakefile();
+ const std::string EXCLUDE_FROM_ALL = "EXCLUDE_FROM_ALL";
+ if (cmProp exclude = target->GetProperty(EXCLUDE_FROM_ALL)) {
+ // Expand the property value per configuration.
+ unsigned int trueCount = 0;
+ unsigned int falseCount = 0;
+ const std::vector<std::string>& configs =
+ mf->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+ for (const std::string& config : configs) {
+ cmGeneratorExpressionInterpreter genexInterpreter(root, config, target);
+ if (cmIsOn(genexInterpreter.Evaluate(*exclude, EXCLUDE_FROM_ALL))) {
+ ++trueCount;
+ } else {
+ ++falseCount;
+ }
+ }
+
+ // Check whether the genex expansion of the property agrees in all
+ // configurations.
+ if (trueCount && falseCount) {
+ std::ostringstream e;
+ e << "The EXCLUDE_FROM_ALL property of target \"" << target->GetName()
+ << "\" varies by configuration. This is not supported by the \""
+ << root->GetGlobalGenerator()->GetName() << "\" generator.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ }
+ return trueCount;
}
// This target is included in its directory. Check whether the
// directory is excluded.
@@ -2445,7 +2452,7 @@ void cmGlobalGenerator::AddGlobalTarget_Package(
gti.WorkingDir = mf->GetCurrentBinaryDirectory();
cmCustomCommandLine singleLine;
singleLine.push_back(cmSystemTools::GetCPackCommand());
- if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') {
+ if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') {
singleLine.push_back("-C");
singleLine.push_back(cmakeCfgIntDir);
}
@@ -2530,7 +2537,7 @@ void cmGlobalGenerator::AddGlobalTarget_Test(
singleLine.push_back(arg);
}
}
- if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') {
+ if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') {
singleLine.push_back("-C");
singleLine.push_back(cmakeCfgIntDir);
} else // TODO: This is a hack. Should be something to do with the
@@ -2611,7 +2618,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
"installation rules have been specified",
mf->GetBacktrace());
} else if (this->InstallTargetEnabled && !skipInstallRules) {
- if (!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.') {
+ if (!(cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.')) {
std::set<std::string>* componentsSet = &this->InstallComponents;
std::ostringstream ostr;
if (!componentsSet->empty()) {
@@ -2650,7 +2657,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
cmd = "cmake";
}
singleLine.push_back(cmd);
- if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') {
+ if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') {
std::string cfgArg = "-DBUILD_TYPE=";
bool useEPN = this->UseEffectivePlatformName(mf.get());
if (useEPN) {
@@ -3045,7 +3052,7 @@ void cmGlobalGenerator::WriteSummary()
for (const auto& lg : this->LocalGenerators) {
for (const auto& tgt : lg->GetGeneratorTargets()) {
- if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!tgt->IsInBuildSystem()) {
continue;
}
this->WriteSummary(tgt.get());
@@ -3123,7 +3130,8 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
fout << "# Source files and their labels\n";
std::vector<cmSourceFile*> sources;
std::vector<std::string> const& configs =
- target->Target->GetMakefile()->GetGeneratorConfigs();
+ target->Target->GetMakefile()->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig);
for (std::string const& c : configs) {
target->GetSourceFiles(sources, c);
}
@@ -3222,8 +3230,9 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile()
const auto& lg = this->LocalGenerators[0];
cmMakefile* mf = lg->GetMakefile();
- std::vector<std::string> configs;
- std::string config = mf->GetConfigurations(configs, false);
+ std::vector<std::string> configs =
+ mf->GetGeneratorConfigs(cmMakefile::OnlyMultiConfig);
+ std::string config = mf->GetDefaultConfiguration();
std::string path = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
"/CPackProperties.cmake");
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 57c7808..c2c80c2 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -542,7 +542,8 @@ protected:
bool IsExcluded(cmStateSnapshot const& root,
cmStateSnapshot const& snp) const;
bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const;
- bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) const;
+ bool IsExcluded(cmLocalGenerator* root,
+ const cmGeneratorTarget* target) const;
virtual void InitializeProgressMarks() {}
struct GlobalTargetInfo
diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h
index 3709365..13cfe4d 100644
--- a/Source/cmGlobalGeneratorFactory.h
+++ b/Source/cmGlobalGeneratorFactory.h
@@ -44,7 +44,7 @@ public:
/** Get the list of supported platforms name for this generator */
virtual std::vector<std::string> GetKnownPlatforms() const = 0;
- /** If the generator suports platforms, get its default. */
+ /** If the generator supports platforms, get its default. */
virtual std::string GetDefaultPlatformName() const = 0;
};
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index d36adfb..7c87131 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -218,10 +218,11 @@ void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd,
{
const char* ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT");
- if (!ghsRoot || ghsRoot[0] == '\0') {
- ghsRoot = DEFAULT_TOOLSET_ROOT;
+ if (cmNonempty(ghsRoot)) {
+ tsd = ghsRoot;
+ } else {
+ tsd = DEFAULT_TOOLSET_ROOT;
}
- tsd = ghsRoot;
if (ts.empty()) {
std::vector<std::string> output;
@@ -467,11 +468,10 @@ void cmGlobalGhsMultiGenerator::WriteAllTarget(
this->ProjectTargets.push_back(t);
}
for (cmGeneratorTarget const* t : sortedProjectTargets) {
- if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!t->IsInBuildSystem()) {
continue;
}
- cmProp p = t->GetProperty("EXCLUDE_FROM_ALL");
- if (!(p && cmIsOn(*p))) {
+ if (!IsExcluded(t->GetLocalGenerator(), t)) {
defaultTargets.push_back(t);
}
}
@@ -635,7 +635,7 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(
std::string tgt;
const char* t =
this->GetCMakeInstance()->GetCacheDefinition("GHS_PRIMARY_TARGET");
- if (t && *t != '\0') {
+ if (cmNonempty(t)) {
tgt = t;
this->GetCMakeInstance()->MarkCliAsUsed("GHS_PRIMARY_TARGET");
} else {
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 843b0f4..f0fa1f4 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -5,9 +5,9 @@
#include <algorithm>
#include <cctype>
#include <cstdio>
-#include <iterator>
#include <sstream>
+#include <cm/iterator>
#include <cm/memory>
#include <cmext/algorithm>
#include <cmext/memory>
@@ -518,7 +518,8 @@ void cmGlobalNinjaGenerator::Generate()
if (cmSystemTools::GetErrorOccuredFlag()) {
this->RulesFileStream->setstate(std::ios::failbit);
- for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) {
+ for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig)) {
this->GetImplFileStream(config)->setstate(std::ios::failbit);
this->GetConfigFileStream(config)->setstate(std::ios::failbit);
}
@@ -1092,6 +1093,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
}
// FALLTHROUGH
case cmStateEnums::GLOBAL_TARGET:
+ case cmStateEnums::INTERFACE_LIBRARY:
case cmStateEnums::UTILITY: {
std::string path =
cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/',
@@ -1104,8 +1106,8 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
break;
}
- default:
- return;
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ break;
}
}
@@ -1127,7 +1129,7 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
cmNinjaDeps outs;
for (cmTargetDepend const& targetDep :
this->GetTargetDirectDepends(target)) {
- if (targetDep->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!targetDep->IsInBuildSystem()) {
continue;
}
if (targetDep.IsCross()) {
@@ -1169,7 +1171,7 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
cmNinjaOuts this_outs; // this will be the new cache entry
for (auto const& dep_target : this->GetTargetDirectDepends(target)) {
- if (dep_target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ if (!dep_target->IsInBuildSystem() ||
(this->EnableCrossConfigBuild() && !dep_target.IsCross())) {
continue;
}
@@ -1188,7 +1190,7 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
// finally generate the outputs of the target itself, if applicable
cmNinjaDeps outs;
if (!omit_self) {
- this->AppendTargetOutputs(target, outs, config);
+ this->AppendTargetOutputs(target, outs, config, DependOnTargetArtifact);
}
outputs.insert(outs.begin(), outs.end());
}
@@ -1200,14 +1202,15 @@ void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
std::string outputPath = this->NinjaOutputPath(alias);
std::string buildAlias = this->BuildAlias(outputPath, config);
cmNinjaDeps outputs;
- this->AppendTargetOutputs(target, outputs, config);
+ this->AppendTargetOutputs(target, outputs, config, DependOnTargetArtifact);
// Mark the target's outputs as ambiguous to ensure that no other target
// uses the output as an alias.
for (std::string const& output : outputs) {
this->TargetAliases[output].GeneratorTarget = nullptr;
this->DefaultTargetAliases[output].GeneratorTarget = nullptr;
for (const std::string& config2 :
- this->Makefiles.front()->GetGeneratorConfigs()) {
+ this->Makefiles.front()->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig)) {
this->Configs[config2].TargetAliases[output].GeneratorTarget = nullptr;
}
}
@@ -1265,11 +1268,12 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
if (ta.second.Config == "all") {
for (auto const& config : this->CrossConfigs) {
this->AppendTargetOutputs(ta.second.GeneratorTarget,
- build.ExplicitDeps, config);
+ build.ExplicitDeps, config,
+ DependOnTargetArtifact);
}
} else {
this->AppendTargetOutputs(ta.second.GeneratorTarget, build.ExplicitDeps,
- ta.second.Config);
+ ta.second.Config, DependOnTargetArtifact);
}
this->WriteBuild(this->EnableCrossConfigBuild() &&
(ta.second.Config == "all" ||
@@ -1280,7 +1284,8 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
}
if (this->IsMultiConfig()) {
- for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) {
+ for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig)) {
for (auto const& ta : this->Configs[config].TargetAliases) {
// Don't write ambiguous aliases.
if (!ta.second.GeneratorTarget) {
@@ -1296,7 +1301,8 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
build.Outputs.front() = ta.first;
build.ExplicitDeps.clear();
this->AppendTargetOutputs(ta.second.GeneratorTarget,
- build.ExplicitDeps, config);
+ build.ExplicitDeps, config,
+ DependOnTargetArtifact);
this->WriteBuild(*this->GetConfigFileStream(config), build);
}
}
@@ -1318,7 +1324,8 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
build.ExplicitDeps.clear();
for (auto const& config : this->DefaultConfigs) {
this->AppendTargetOutputs(ta.second.GeneratorTarget,
- build.ExplicitDeps, config);
+ build.ExplicitDeps, config,
+ DependOnTargetArtifact);
}
this->WriteBuild(*this->GetDefaultFileStream(), build);
}
@@ -1339,11 +1346,9 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
cmGlobalNinjaGenerator::WriteDivider(os);
std::string const& currentBinaryDir = it.first;
DirectoryTarget const& dt = it.second;
- std::vector<std::string> configs;
- dt.LG->GetMakefile()->GetConfigurations(configs, true);
- if (configs.empty()) {
- configs.emplace_back();
- }
+ std::vector<std::string> configs =
+ dt.LG->GetMakefile()->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig);
// Setup target
cmNinjaDeps configDeps;
@@ -1356,8 +1361,9 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
build.Outputs.front() = this->BuildAlias(buildDirAllTarget, config);
configDeps.emplace_back(build.Outputs.front());
for (DirectoryTarget::Target const& t : dt.Targets) {
- if (!t.ExcludeFromAll) {
- this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config);
+ if (!IsExcludedFromAllInConfig(t, config)) {
+ this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config,
+ DependOnTargetArtifact);
}
}
for (DirectoryTarget::Dir const& d : dt.Children) {
@@ -1538,7 +1544,8 @@ void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
this->WriteTargetClean(os);
this->WriteTargetHelp(os);
- for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) {
+ for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig)) {
this->WriteTargetDefault(*this->GetConfigFileStream(config));
}
@@ -1712,11 +1719,8 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake";
std::string cleanScriptAbs =
cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel);
- std::vector<std::string> configs;
- this->Makefiles[0]->GetConfigurations(configs, true);
- if (configs.empty()) {
- configs.emplace_back();
- }
+ std::vector<std::string> configs =
+ this->Makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
// Check if there are additional files to clean
bool empty = true;
@@ -1810,7 +1814,8 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
WriteRule(*this->RulesFileStream, rule);
}
- auto const configs = this->Makefiles.front()->GetGeneratorConfigs();
+ auto const configs = this->Makefiles.front()->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig);
// Write build
{
@@ -2489,7 +2494,8 @@ bool cmGlobalNinjaMultiGenerator::OpenBuildFileStreams()
<< "# This file contains build statements common to all "
"configurations.\n\n";
- for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) {
+ for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig)) {
// Open impl file.
if (!this->OpenFileStream(this->ImplFileStreams[config],
GetNinjaImplFilename(config))) {
@@ -2529,7 +2535,8 @@ void cmGlobalNinjaMultiGenerator::CloseBuildFileStreams()
this->DefaultFileStream.reset();
} // No error if it wasn't open
- for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) {
+ for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig)) {
if (this->ImplFileStreams[config]) {
this->ImplFileStreams[config].reset();
} else {
@@ -2571,7 +2578,8 @@ std::string cmGlobalNinjaMultiGenerator::GetNinjaConfigFilename(
void cmGlobalNinjaMultiGenerator::AddRebuildManifestOutputs(
cmNinjaDeps& outputs) const
{
- for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) {
+ for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig)) {
outputs.push_back(this->NinjaOutputPath(GetNinjaImplFilename(config)));
outputs.push_back(this->NinjaOutputPath(GetNinjaConfigFilename(config)));
}
@@ -2583,11 +2591,9 @@ void cmGlobalNinjaMultiGenerator::AddRebuildManifestOutputs(
void cmGlobalNinjaMultiGenerator::GetQtAutoGenConfigs(
std::vector<std::string>& configs) const
{
- auto const oldSize = configs.size();
- this->Makefiles.front()->GetConfigurations(configs);
- if (configs.size() == oldSize) {
- configs.emplace_back();
- }
+ auto allConfigs =
+ this->Makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+ configs.insert(configs.end(), cm::cbegin(allConfigs), cm::cend(allConfigs));
}
bool cmGlobalNinjaMultiGenerator::InspectConfigTypeVariables()
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 44e632f..10f5cf6 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -318,14 +318,13 @@ public:
virtual std::string OrderDependsTargetForTarget(
cmGeneratorTarget const* target, const std::string& config) const;
- void AppendTargetOutputs(
- cmGeneratorTarget const* target, cmNinjaDeps& outputs,
- const std::string& config,
- cmNinjaTargetDepends depends = DependOnTargetArtifact);
- void AppendTargetDepends(
- cmGeneratorTarget const* target, cmNinjaDeps& outputs,
- const std::string& config, const std::string& fileConfig,
- cmNinjaTargetDepends depends = DependOnTargetArtifact);
+ void AppendTargetOutputs(cmGeneratorTarget const* target,
+ cmNinjaDeps& outputs, const std::string& config,
+ cmNinjaTargetDepends depends);
+ void AppendTargetDepends(cmGeneratorTarget const* target,
+ cmNinjaDeps& outputs, const std::string& config,
+ const std::string& fileConfig,
+ cmNinjaTargetDepends depends);
void AppendTargetDependsClosure(cmGeneratorTarget const* target,
cmNinjaDeps& outputs,
const std::string& config);
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index c31983b..37a77fa 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -143,7 +143,7 @@ void cmGlobalUnixMakefileGenerator3::Generate()
total += pmi.second.NumberOfActions;
}
- // write each target's progress.make this loop is done twice. Bascially the
+ // write each target's progress.make this loop is done twice. Basically the
// Generate pass counts all the actions, the first loop below determines
// how many actions have progress updates for each target and writes to
// corrrect variable values for everything except the all targets. The
@@ -387,12 +387,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(
cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(lGenerator);
// for all of out targets
for (const auto& tgt : lg.GetGeneratorTargets()) {
- if ((tgt->GetType() == cmStateEnums::EXECUTABLE) ||
- (tgt->GetType() == cmStateEnums::STATIC_LIBRARY) ||
- (tgt->GetType() == cmStateEnums::SHARED_LIBRARY) ||
- (tgt->GetType() == cmStateEnums::MODULE_LIBRARY) ||
- (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
- (tgt->GetType() == cmStateEnums::UTILITY)) {
+ if (tgt->IsInBuildSystem() &&
+ tgt->GetType() != cmStateEnums::GLOBAL_TARGET) {
std::string tname = cmStrCat(lg.GetRelativeTargetDirectory(tgt.get()),
"/DependInfo.cmake");
cmSystemTools::ConvertToUnixSlashes(tname);
@@ -416,7 +412,7 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
std::vector<std::string> depends;
for (DirectoryTarget::Target const& t : dt.Targets) {
// Add this to the list of depends rules in this directory.
- if ((!check_all || !t.ExcludeFromAll) &&
+ if ((!check_all || t.ExcludedFromAllInConfigs.empty()) &&
(!check_relink ||
t.GT->NeedRelinkBeforeInstall(lg->GetConfigName()))) {
// The target may be from a different directory; use its local gen.
@@ -635,17 +631,12 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
for (const auto& gtarget : lg.GetGeneratorTargets()) {
// Don't emit the same rule twice (e.g. two targets with the same
// simple name)
- int type = gtarget->GetType();
std::string name = gtarget->GetName();
if (!name.empty() && emitted.insert(name).second &&
// Handle user targets here. Global targets are handled in
// the local generator on a per-directory basis.
- ((type == cmStateEnums::EXECUTABLE) ||
- (type == cmStateEnums::STATIC_LIBRARY) ||
- (type == cmStateEnums::SHARED_LIBRARY) ||
- (type == cmStateEnums::MODULE_LIBRARY) ||
- (type == cmStateEnums::OBJECT_LIBRARY) ||
- (type == cmStateEnums::UTILITY))) {
+ (gtarget->IsInBuildSystem() &&
+ gtarget->GetType() != cmStateEnums::GLOBAL_TARGET)) {
// Add a rule to build the target by name.
lg.WriteDivider(ruleFileStream);
ruleFileStream << "# Target rules for targets named " << name
@@ -709,15 +700,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
// for each target Generate the rule files for each target.
for (const auto& gtarget : lg.GetGeneratorTargets()) {
- int type = gtarget->GetType();
std::string name = gtarget->GetName();
if (!name.empty() &&
- ((type == cmStateEnums::EXECUTABLE) ||
- (type == cmStateEnums::STATIC_LIBRARY) ||
- (type == cmStateEnums::SHARED_LIBRARY) ||
- (type == cmStateEnums::MODULE_LIBRARY) ||
- (type == cmStateEnums::OBJECT_LIBRARY) ||
- (type == cmStateEnums::UTILITY))) {
+ (gtarget->IsInBuildSystem() &&
+ gtarget->GetType() != cmStateEnums::GLOBAL_TARGET)) {
std::string makefileName;
// Add a rule to build the target by name.
localName = lg.GetRelativeTargetDirectory(gtarget.get());
@@ -845,8 +831,7 @@ void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks()
for (const auto& gt : lg->GetGeneratorTargets()) {
cmLocalGenerator* tlg = gt->GetLocalGenerator();
- if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
- gt->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ if (!gt->IsInBuildSystem() || IsExcluded(lg.get(), gt.get())) {
continue;
}
@@ -881,7 +866,7 @@ size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInTarget(
if (emitted.insert(target).second) {
count = this->ProgressMap[target].Marks.size();
for (cmTargetDepend const& depend : this->GetTargetDirectDepends(target)) {
- if (depend->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!depend->IsInBuildSystem()) {
continue;
}
count += this->CountProgressMarksInTarget(depend, emitted);
@@ -938,7 +923,7 @@ void cmGlobalUnixMakefileGenerator3::AppendGlobalTargetDepends(
for (cmTargetDepend const& i : this->GetTargetDirectDepends(target)) {
// Create the target-level dependency.
cmGeneratorTarget const* dep = i;
- if (dep->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!dep->IsInBuildSystem()) {
continue;
}
cmLocalUnixMakefileGenerator3* lg3 =
@@ -986,7 +971,9 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
(type == cmStateEnums::STATIC_LIBRARY) ||
(type == cmStateEnums::SHARED_LIBRARY) ||
(type == cmStateEnums::MODULE_LIBRARY) ||
- (type == cmStateEnums::OBJECT_LIBRARY)) {
+ (type == cmStateEnums::OBJECT_LIBRARY) ||
+ (type == cmStateEnums::INTERFACE_LIBRARY &&
+ target->IsInBuildSystem())) {
project_targets.insert(target->GetName());
} else if (type == cmStateEnums::GLOBAL_TARGET) {
globals_targets.insert(target->GetName());
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 5dac072..3805546 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -138,9 +138,6 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
"ProductDir",
vc10Express, cmSystemTools::KeyWOW64_32);
this->CudaEnabled = false;
- this->SystemIsWindowsCE = false;
- this->SystemIsWindowsPhone = false;
- this->SystemIsWindowsStore = false;
this->MSBuildCommandInitialized = false;
{
std::string envPlatformToolset;
@@ -511,18 +508,16 @@ bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf)
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
- std::string v = this->GetInstalledNsightTegraVersion();
- if (v.empty()) {
- mf->IssueMessage(MessageType::FATAL_ERROR,
- "CMAKE_SYSTEM_NAME is 'Android' but "
- "'NVIDIA Nsight Tegra Visual Studio Edition' "
- "is not installed.");
- return false;
+ if (mf->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM") == "Tegra-Android") {
+ if (!this->InitializeTegraAndroid(mf)) {
+ return false;
+ }
+ } else {
+ this->SystemIsAndroid = true;
+ if (!this->InitializeAndroid(mf)) {
+ return false;
+ }
}
- this->DefaultPlatformName = "Tegra-Android";
- this->DefaultPlatformToolset = "Default";
- this->NsightTegraVersion = v;
- mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v);
}
return true;
@@ -564,6 +559,31 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsStore(cmMakefile* mf)
return false;
}
+bool cmGlobalVisualStudio10Generator::InitializeTegraAndroid(cmMakefile* mf)
+{
+ std::string v = this->GetInstalledNsightTegraVersion();
+ if (v.empty()) {
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ "CMAKE_SYSTEM_NAME is 'Android' but "
+ "'NVIDIA Nsight Tegra Visual Studio Edition' "
+ "is not installed.");
+ return false;
+ }
+ this->DefaultPlatformName = "Tegra-Android";
+ this->DefaultPlatformToolset = "Default";
+ this->NsightTegraVersion = v;
+ mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v);
+ return true;
+}
+
+bool cmGlobalVisualStudio10Generator::InitializeAndroid(cmMakefile* mf)
+{
+ std::ostringstream e;
+ e << this->GetName() << " does not support Android.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return false;
+}
+
bool cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset(
std::string& toolset) const
{
@@ -598,6 +618,28 @@ void cmGlobalVisualStudio10Generator::Generate()
{
this->LongestSource = LongestSourcePath();
this->cmGlobalVisualStudio8Generator::Generate();
+ if (!this->AndroidExecutableWarnings.empty() &&
+ !this->CMakeInstance->GetIsInTryCompile()) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "You are using Visual Studio tools for Android, which does not support "
+ "standalone executables. However, the following executable targets do "
+ "not have the ANDROID_GUI property set, and thus will not be built as "
+ "expected. They will be built as shared libraries with executable "
+ "filenames:\n"
+ " ";
+ /* clang-format on */
+ bool first = true;
+ for (auto const& name : this->AndroidExecutableWarnings) {
+ if (!first) {
+ e << ", ";
+ }
+ first = false;
+ e << name;
+ }
+ this->CMakeInstance->IssueMessage(MessageType::WARNING, e.str());
+ }
if (this->LongestSource.Length > 0) {
cmLocalGenerator* lg = this->LongestSource.Target->GetLocalGenerator();
std::ostringstream e;
@@ -664,8 +706,14 @@ std::string const& cmGlobalVisualStudio10Generator::GetPlatformToolsetString()
if (!this->GeneratorToolset.empty()) {
return this->GeneratorToolset;
}
- if (!this->DefaultPlatformToolset.empty()) {
- return this->DefaultPlatformToolset;
+ if (this->SystemIsAndroid) {
+ if (!this->DefaultAndroidToolset.empty()) {
+ return this->DefaultAndroidToolset;
+ }
+ } else {
+ if (!this->DefaultPlatformToolset.empty()) {
+ return this->DefaultPlatformToolset;
+ }
}
static std::string const empty;
return empty;
@@ -879,7 +927,10 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
epg.Attribute("Label", "Globals");
cmXMLElement(epg, "ProjectGuid")
.Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
- cmXMLElement(epg, "Keyword").Content("Win32Proj");
+ cmXMLElement(epg, "Keyword")
+ .Content(mf->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android"
+ ? "Android"
+ : "Win32Proj");
cmXMLElement(epg, "Platform").Content(this->GetPlatformName());
if (this->GetSystemName() == "WindowsPhone") {
cmXMLElement(epg, "ApplicationType").Content("Windows Phone");
@@ -889,15 +940,21 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
cmXMLElement(epg, "ApplicationType").Content("Windows Store");
cmXMLElement(epg, "ApplicationTypeRevision")
.Content(this->GetApplicationTypeRevision());
+ } else if (this->GetSystemName() == "Android") {
+ cmXMLElement(epg, "ApplicationType").Content("Android");
+ cmXMLElement(epg, "ApplicationTypeRevision")
+ .Content(this->GetApplicationTypeRevision());
}
if (!this->WindowsTargetPlatformVersion.empty()) {
cmXMLElement(epg, "WindowsTargetPlatformVersion")
.Content(this->WindowsTargetPlatformVersion);
}
- if (this->GetPlatformName() == "ARM64") {
- cmXMLElement(epg, "WindowsSDKDesktopARM64Support").Content("true");
- } else if (this->GetPlatformName() == "ARM") {
- cmXMLElement(epg, "WindowsSDKDesktopARMSupport").Content("true");
+ if (this->GetSystemName() != "Android") {
+ if (this->GetPlatformName() == "ARM64") {
+ cmXMLElement(epg, "WindowsSDKDesktopARM64Support").Content("true");
+ } else if (this->GetPlatformName() == "ARM") {
+ cmXMLElement(epg, "WindowsSDKDesktopARMSupport").Content("true");
+ }
}
}
cmXMLElement(eprj, "Import")
@@ -1209,6 +1266,10 @@ std::string cmGlobalVisualStudio10Generator::GetInstalledNsightTegraVersion()
std::string cmGlobalVisualStudio10Generator::GetApplicationTypeRevision() const
{
+ if (this->GetSystemName() == "Android") {
+ return this->GetAndroidApplicationTypeRevision();
+ }
+
// Return the first two '.'-separated components of the Windows version.
std::string::size_type end1 = this->SystemVersion.find('.');
std::string::size_type end2 =
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index b8c18b4..0c53537 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -4,6 +4,7 @@
#define cmGlobalVisualStudio10Generator_h
#include <memory>
+#include <set>
#include "cmGlobalVisualStudio8Generator.h"
#include "cmVisualStudio10ToolsetOptions.h"
@@ -43,6 +44,11 @@ public:
void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
bool optional) override;
+ void AddAndroidExecutableWarning(const std::string& name)
+ {
+ this->AndroidExecutableWarnings.insert(name);
+ }
+
bool IsCudaEnabled() const { return this->CudaEnabled; }
/** Generating for Nsight Tegra VS plugin? */
@@ -100,6 +106,9 @@ public:
/** Return true if building for WindowsStore */
bool TargetsWindowsStore() const { return this->SystemIsWindowsStore; }
+ /** Return true if building for Android */
+ bool TargetsAndroid() const { return this->SystemIsAndroid; }
+
const char* GetCMakeCFGIntDir() const override { return "$(Configuration)"; }
bool Find64BitTools(cmMakefile* mf);
@@ -128,6 +137,8 @@ public:
/** Return the first two components of CMAKE_SYSTEM_VERSION. */
std::string GetApplicationTypeRevision() const;
+ virtual const char* GetAndroidApplicationTypeRevision() const { return ""; }
+
cmIDEFlagTable const* GetClFlagTable() const;
cmIDEFlagTable const* GetCSharpFlagTable() const;
cmIDEFlagTable const* GetRcFlagTable() const;
@@ -148,6 +159,8 @@ protected:
virtual bool InitializeWindowsCE(cmMakefile* mf);
virtual bool InitializeWindowsPhone(cmMakefile* mf);
virtual bool InitializeWindowsStore(cmMakefile* mf);
+ virtual bool InitializeTegraAndroid(cmMakefile* mf);
+ virtual bool InitializeAndroid(cmMakefile* mf);
virtual bool ProcessGeneratorToolsetField(std::string const& key,
std::string const& value);
@@ -171,6 +184,7 @@ protected:
std::string GeneratorToolsetCudaCustomDir;
std::string DefaultPlatformToolset;
std::string DefaultPlatformToolsetHostArchitecture;
+ std::string DefaultAndroidToolset;
std::string WindowsTargetPlatformVersion;
std::string SystemName;
std::string SystemVersion;
@@ -185,9 +199,10 @@ protected:
std::string DefaultNasmFlagTableName;
std::string DefaultRCFlagTableName;
bool SupportsUnityBuilds = false;
- bool SystemIsWindowsCE;
- bool SystemIsWindowsPhone;
- bool SystemIsWindowsStore;
+ bool SystemIsWindowsCE = false;
+ bool SystemIsWindowsPhone = false;
+ bool SystemIsWindowsStore = false;
+ bool SystemIsAndroid = false;
private:
class Factory;
@@ -211,6 +226,7 @@ private:
std::string MSBuildCommand;
bool MSBuildCommandInitialized;
cmVisualStudio10ToolsetOptions ToolsetOptions;
+ std::set<std::string> AndroidExecutableWarnings;
virtual std::string FindMSBuildCommand();
std::string FindDevEnvCommand() override;
std::string GetVSMakeProgram() override { return this->GetMSBuildCommand(); }
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index f549b6a..451d448 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -109,6 +109,7 @@ cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator(
"ProductDir",
vc14Express, cmSystemTools::KeyWOW64_32);
this->DefaultPlatformToolset = "v140";
+ this->DefaultAndroidToolset = "Clang_3_8";
this->DefaultCLFlagTableName = "v140";
this->DefaultCSharpFlagTableName = "v140";
this->DefaultLibFlagTableName = "v14";
@@ -159,6 +160,11 @@ bool cmGlobalVisualStudio14Generator::InitializeWindowsStore(cmMakefile* mf)
return true;
}
+bool cmGlobalVisualStudio14Generator::InitializeAndroid(cmMakefile*)
+{
+ return true;
+}
+
bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf,
bool required)
{
diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h
index ccc2917..39353f2 100644
--- a/Source/cmGlobalVisualStudio14Generator.h
+++ b/Source/cmGlobalVisualStudio14Generator.h
@@ -23,12 +23,18 @@ public:
bool MatchesGeneratorName(const std::string& name) const override;
+ const char* GetAndroidApplicationTypeRevision() const override
+ {
+ return "2.0";
+ }
+
protected:
cmGlobalVisualStudio14Generator(cmake* cm, const std::string& name,
std::string const& platformInGeneratorName);
bool InitializeWindows(cmMakefile* mf) override;
bool InitializeWindowsStore(cmMakefile* mf) override;
+ bool InitializeAndroid(cmMakefile* mf) override;
bool SelectWindowsStoreToolset(std::string& toolset) const override;
// These aren't virtual because we need to check if the selected version
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 7ada325..0083c40 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -19,8 +19,8 @@ void cmGlobalVisualStudio71Generator::WriteSLNFile(
std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators)
{
- std::vector<std::string> configs;
- root->GetMakefile()->GetConfigurations(configs);
+ std::vector<std::string> configs =
+ root->GetMakefile()->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
// Write out the header for a SLN file
this->WriteSLNHeader(fout);
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 428c748..f8b438a 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -339,7 +339,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
// loop over again and write out configurations for each target
// in the solution
for (cmGeneratorTarget const* target : projectTargets) {
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
continue;
}
cmProp expath = target->GetProperty("EXTERNAL_MSPROJECT");
@@ -369,7 +369,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
for (cmGeneratorTarget const* target : projectTargets) {
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
continue;
}
bool written = false;
@@ -436,7 +436,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetDepends(
std::ostream& fout, OrderedTargetDependSet const& projectTargets)
{
for (cmGeneratorTarget const* target : projectTargets) {
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
continue;
}
cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
@@ -568,8 +568,9 @@ void cmGlobalVisualStudio7Generator::WriteSLNFooter(std::ostream& fout)
std::string cmGlobalVisualStudio7Generator::WriteUtilityDepend(
cmGeneratorTarget const* target)
{
- std::vector<std::string> configs;
- target->Target->GetMakefile()->GetConfigurations(configs);
+ std::vector<std::string> configs =
+ target->Target->GetMakefile()->GetGeneratorConfigs(
+ cmMakefile::ExcludeEmptyConfig);
std::string pname = cmStrCat(target->GetName(), "_UTILITY");
std::string fname =
cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/',
@@ -693,9 +694,7 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
}
// inspect EXCLUDE_FROM_DEFAULT_BUILD[_<CONFIG>] properties
for (std::string const& i : configs) {
- const char* propertyValue =
- target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i);
- if (cmIsOff(propertyValue)) {
+ if (cmIsOff(target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i))) {
activeConfigs.insert(i);
}
}
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 29ca154..fcdfc50 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -325,7 +325,7 @@ void cmGlobalVisualStudio8Generator::WriteProjectDepends(
TargetDependSet const& unordered = this->GetTargetDirectDepends(gt);
OrderedTargetDependSet depends(unordered, std::string());
for (cmTargetDepend const& i : depends) {
- if (i->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!i->IsInBuildSystem()) {
continue;
}
std::string guid = this->GetGUID(i->GetName());
@@ -341,7 +341,7 @@ bool cmGlobalVisualStudio8Generator::NeedLinkLibraryDependencies(
if (cmGeneratorTarget* depTarget =
target->GetLocalGenerator()->FindGeneratorTargetToUse(
ui.Value.first)) {
- if (depTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+ if (depTarget->IsInBuildSystem() &&
depTarget->GetProperty("EXTERNAL_MSPROJECT")) {
// This utility dependency names an external .vcproj target.
// We use LinkLibraryDependencies="true" to link to it without
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index c688da2..001d876 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -368,7 +368,7 @@ cmGlobalVisualStudioGenerator::GetTargetLinkClosure(cmGeneratorTarget* target)
void cmGlobalVisualStudioGenerator::FollowLinkDepends(
const cmGeneratorTarget* target, std::set<const cmGeneratorTarget*>& linked)
{
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
return;
}
if (linked.insert(target).second &&
@@ -509,7 +509,7 @@ std::string cmGlobalVisualStudioGenerator::GetStartupProjectName(
cmLocalGenerator const* root) const
{
cmProp n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT");
- if (n && !n->empty()) {
+ if (cmNonempty(n)) {
std::string startup = *n;
if (this->FindTarget(startup)) {
return startup;
@@ -810,7 +810,7 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
// a target with none of its own sources, e.g. when also using
// object libraries.
cmProp linkLang = gt->GetProperty("LINKER_LANGUAGE");
- if (linkLang && !linkLang->empty()) {
+ if (cmNonempty(linkLang)) {
languages.insert(*linkLang);
}
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index 605dc8b..e2e045c 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -100,6 +100,24 @@ static const char* VSVersionToToolset(
return "";
}
+static const char* VSVersionToAndroidToolset(
+ cmGlobalVisualStudioGenerator::VSVersion v)
+{
+ switch (v) {
+ case cmGlobalVisualStudioGenerator::VS9:
+ case cmGlobalVisualStudioGenerator::VS10:
+ case cmGlobalVisualStudioGenerator::VS11:
+ case cmGlobalVisualStudioGenerator::VS12:
+ return "";
+ case cmGlobalVisualStudioGenerator::VS14:
+ return "Clang_3_8";
+ case cmGlobalVisualStudioGenerator::VS15:
+ case cmGlobalVisualStudioGenerator::VS16:
+ return "Clang_5_0";
+ }
+ return "";
+}
+
static const char vs15generatorName[] = "Visual Studio 15 2017";
// Map generator name without year to name with year.
@@ -284,6 +302,7 @@ cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator(
this->Version = version;
this->ExpressEdition = false;
this->DefaultPlatformToolset = VSVersionToToolset(this->Version);
+ this->DefaultAndroidToolset = VSVersionToAndroidToolset(this->Version);
this->DefaultCLFlagTableName = VSVersionToToolset(this->Version);
this->DefaultCSharpFlagTableName = VSVersionToToolset(this->Version);
this->DefaultLinkFlagTableName = VSVersionToToolset(this->Version);
@@ -408,6 +427,25 @@ bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const
vsInstanceVersion > vsInstanceVersion16_7_P2);
}
+const char*
+cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision()
+ const
+{
+ switch (this->Version) {
+ case cmGlobalVisualStudioGenerator::VS9:
+ case cmGlobalVisualStudioGenerator::VS10:
+ case cmGlobalVisualStudioGenerator::VS11:
+ case cmGlobalVisualStudioGenerator::VS12:
+ return "";
+ case cmGlobalVisualStudioGenerator::VS14:
+ return "2.0";
+ case cmGlobalVisualStudioGenerator::VS15:
+ case cmGlobalVisualStudioGenerator::VS16:
+ return "3.0";
+ }
+ return "";
+}
+
std::string cmGlobalVisualStudioVersionedGenerator::GetAuxiliaryToolset() const
{
const char* version = this->GetPlatformToolsetVersion();
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h
index cbd3ba7..d5b8337 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.h
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.h
@@ -36,6 +36,8 @@ public:
bool IsStdOutEncodingSupported() const override;
+ const char* GetAndroidApplicationTypeRevision() const override;
+
protected:
cmGlobalVisualStudioVersionedGenerator(
VSVersion version, cmake* cm, const std::string& name,
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index b28395a..793f6f7 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -173,6 +173,7 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(
this->RootObject = nullptr;
this->MainGroupChildren = nullptr;
+ this->FrameworkGroup = nullptr;
this->CurrentMakefile = nullptr;
this->CurrentLocalGenerator = nullptr;
this->XcodeBuildCommandInitialized = false;
@@ -476,6 +477,9 @@ void cmGlobalXCodeGenerator::Generate()
}
}
+ // cache the enabled languages for source file type queries
+ this->GetEnabledLanguages(this->EnabledLangs);
+
this->SetGenerationRoot(root);
// now create the project
this->OutputXCodeProject(root, keyVal.second);
@@ -673,6 +677,7 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects()
this->GroupNameMap.clear();
this->TargetGroup.clear();
this->FileRefs.clear();
+ this->ExternalLibRefs.clear();
}
void cmGlobalXCodeGenerator::addObject(std::unique_ptr<cmXCodeObject> obj)
@@ -741,7 +746,7 @@ std::string GetGroupMapKeyFromPath(cmGeneratorTarget* target,
return key;
}
-cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
+cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeBuildFileFromPath(
const std::string& fullpath, cmGeneratorTarget* target,
const std::string& lang, cmSourceFile* sf)
{
@@ -827,6 +832,14 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
default:
break;
}
+
+ // explicitly add the explicit language flag before any other flag
+ // this way backwards compatibility with user flags is maintained
+ if (sf->GetProperty("LANGUAGE")) {
+ this->CurrentLocalGenerator->AppendFeatureOptions(flags, lang,
+ "EXPLICIT_LANGUAGE");
+ }
+
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (cmProp cflags = sf->GetProperty(COMPILE_FLAGS)) {
lg->AppendFlags(flags, genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS));
@@ -869,7 +882,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true));
cmXCodeObject* buildFile =
- this->CreateXCodeSourceFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf);
+ this->CreateXCodeBuildFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf);
cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
settings->AddAttributeIfNotEmpty("COMPILER_FLAGS",
@@ -922,14 +935,40 @@ void cmGlobalXCodeGenerator::AddXCodeProjBuildRule(
}
}
-std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
- const std::string& lang,
- bool& keepLastKnownFileType)
+bool IsLibraryExtension(const std::string& fileExt)
+{
+ return (fileExt == ".framework" || fileExt == ".a" || fileExt == ".o" ||
+ fileExt == ".dylib" || fileExt == ".tbd");
+}
+bool IsLibraryType(const std::string& fileType)
+{
+ return (fileType == "wrapper.framework" || fileType == "archive.ar" ||
+ fileType == "compiled.mach-o.objfile" ||
+ fileType == "compiled.mach-o.dylib" ||
+ fileType == "sourcecode.text-based-dylib-definition");
+}
+
+std::string GetDirectoryValueFromFileExtension(const std::string& dirExt)
+{
+ std::string ext = cmSystemTools::LowerCase(dirExt);
+ if (ext == "framework") {
+ return "wrapper.framework";
+ }
+ if (ext == "xcassets") {
+ return "folder.assetcatalog";
+ }
+ return "folder";
+}
+
+std::string GetSourcecodeValueFromFileExtension(
+ const std::string& _ext, const std::string& lang,
+ bool& keepLastKnownFileType, const std::vector<std::string>& enabled_langs)
{
std::string ext = cmSystemTools::LowerCase(_ext);
std::string sourcecode = "sourcecode";
if (ext == "o") {
+ keepLastKnownFileType = true;
sourcecode = "compiled.mach-o.objfile";
} else if (ext == "xctest") {
sourcecode = "wrapper.cfbundle";
@@ -939,9 +978,9 @@ std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
} else if (ext == "storyboard") {
keepLastKnownFileType = true;
sourcecode = "file.storyboard";
- } else if (ext == "mm") {
+ } else if (ext == "mm" && !cm::contains(enabled_langs, "OBJCXX")) {
sourcecode += ".cpp.objcpp";
- } else if (ext == "m") {
+ } else if (ext == "m" && !cm::contains(enabled_langs, "OBJC")) {
sourcecode += ".c.objc";
} else if (ext == "swift") {
sourcecode += ".swift";
@@ -973,6 +1012,14 @@ std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
sourcecode += ".metal";
} else if (ext == "mig") {
sourcecode += ".mig";
+ } else if (ext == "tbd") {
+ sourcecode += ".text-based-dylib-definition";
+ } else if (ext == "a") {
+ keepLastKnownFileType = true;
+ sourcecode = "archive.ar";
+ } else if (ext == "dylib") {
+ keepLastKnownFileType = true;
+ sourcecode = "compiled.mach-o.dylib";
}
// else
// {
@@ -989,20 +1036,6 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
const std::string& fullpath, cmGeneratorTarget* target,
const std::string& lang, cmSourceFile* sf)
{
- std::string key = GetGroupMapKeyFromPath(target, fullpath);
- cmXCodeObject* fileRef = this->FileRefs[key];
- if (!fileRef) {
- fileRef = this->CreateObject(cmXCodeObject::PBXFileReference);
- fileRef->SetComment(fullpath);
- this->FileRefs[key] = fileRef;
- }
- cmXCodeObject* group = this->GroupMap[key];
- cmXCodeObject* children = group->GetObject("children");
- if (!children->HasObject(fileRef)) {
- children->AddObject(fileRef);
- }
- fileRef->AddAttribute("fileEncoding", this->CreateString("4"));
-
bool useLastKnownFileType = false;
std::string fileType;
if (sf) {
@@ -1013,38 +1046,70 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
fileType = *l;
}
}
+ // Make a copy so that we can override it later
+ std::string path = fullpath;
+ // Compute the extension without leading '.'.
+ std::string ext = cmSystemTools::GetFilenameLastExtension(path);
+ if (!ext.empty()) {
+ ext = ext.substr(1);
+ }
if (fileType.empty()) {
- // Compute the extension without leading '.'.
- std::string ext = cmSystemTools::GetFilenameLastExtension(fullpath);
- if (!ext.empty()) {
- ext = ext.substr(1);
+ // If file has no extension it's either a raw executable or might
+ // be a direct reference to binary within a framework (bad practice!)
+ // so this is where we change the path to the point to framework
+ // directory.
+ if (ext.empty()) {
+ auto parentDir = cmSystemTools::GetParentDirectory(path);
+ auto parentExt = cmSystemTools::GetFilenameLastExtension(parentDir);
+ if (parentExt == ".framework") {
+ path = parentDir;
+ ext = parentExt.substr(1);
+ }
}
-
// If fullpath references a directory, then we need to specify
// lastKnownFileType as folder in order for Xcode to be able to
// open the contents of the folder.
// (Xcode 4.6 does not like explicitFileType=folder).
- if (cmSystemTools::FileIsDirectory(fullpath)) {
- fileType = (ext == "xcassets" ? "folder.assetcatalog" : "folder");
+ if (cmSystemTools::FileIsDirectory(path)) {
+ fileType = GetDirectoryValueFromFileExtension(ext);
useLastKnownFileType = true;
} else {
- fileType =
- GetSourcecodeValueFromFileExtension(ext, lang, useLastKnownFileType);
+ fileType = GetSourcecodeValueFromFileExtension(
+ ext, lang, useLastKnownFileType, this->EnabledLangs);
}
}
+ std::string key = GetGroupMapKeyFromPath(target, path);
+ cmXCodeObject* fileRef = this->FileRefs[key];
+ if (!fileRef) {
+ fileRef = this->CreateObject(cmXCodeObject::PBXFileReference);
+ fileRef->SetComment(path);
+ this->FileRefs[key] = fileRef;
+ }
+ fileRef->AddAttribute("fileEncoding", this->CreateString("4"));
fileRef->AddAttribute(useLastKnownFileType ? "lastKnownFileType"
: "explicitFileType",
this->CreateString(fileType));
-
// Store the file path relative to the top of the source tree.
- std::string path = this->RelativeToSource(fullpath);
+ if (!IsLibraryType(fileType)) {
+ path = this->RelativeToSource(path);
+ }
std::string name = cmSystemTools::GetFilenameName(path);
const char* sourceTree =
cmSystemTools::FileIsFullPath(path) ? "<absolute>" : "SOURCE_ROOT";
fileRef->AddAttribute("name", this->CreateString(name));
fileRef->AddAttribute("path", this->CreateString(path));
fileRef->AddAttribute("sourceTree", this->CreateString(sourceTree));
+
+ cmXCodeObject* group = this->GroupMap[key];
+ if (!group && IsLibraryType(fileType)) {
+ group = this->FrameworkGroup;
+ this->GroupMap[key] = group;
+ }
+ cmXCodeObject* children = group->GetObject("children");
+ if (!children->HasObject(fileRef)) {
+ children->AddObject(fileRef);
+ }
return fileRef;
}
@@ -1077,11 +1142,8 @@ void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen)
this->CurrentMakefile = gen->GetMakefile();
// Select the current set of configuration types.
- this->CurrentConfigurationTypes.clear();
- this->CurrentMakefile->GetConfigurations(this->CurrentConfigurationTypes);
- if (this->CurrentConfigurationTypes.empty()) {
- this->CurrentConfigurationTypes.emplace_back();
- }
+ this->CurrentConfigurationTypes =
+ this->CurrentMakefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
}
struct cmSourceFilePathCompare
@@ -1137,11 +1199,12 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
return true;
}
- if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!gtgt->IsInBuildSystem()) {
return true;
}
if (gtgt->GetType() == cmStateEnums::UTILITY ||
+ gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
if (!t) {
@@ -1152,23 +1215,24 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
}
// organize the sources
- std::vector<cmSourceFile*> classes;
- if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ std::vector<cmSourceFile*> commonSourceFiles;
+ if (!gtgt->GetConfigCommonSourceFiles(commonSourceFiles)) {
return false;
}
// Add CMakeLists.txt file for user convenience.
- this->AddXCodeProjBuildRule(gtgt, classes);
+ this->AddXCodeProjBuildRule(gtgt, commonSourceFiles);
// Add the Info.plist we are about to generate for an App Bundle.
if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
std::string plist = this->ComputeInfoPListLocation(gtgt);
cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
plist, true, cmSourceFileLocationKind::Known);
- classes.push_back(sf);
+ commonSourceFiles.push_back(sf);
}
- std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
+ std::sort(commonSourceFiles.begin(), commonSourceFiles.end(),
+ cmSourceFilePathCompare());
gtgt->ComputeObjectMapping();
@@ -1176,16 +1240,19 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
std::vector<cmXCodeObject*> headerFiles;
std::vector<cmXCodeObject*> resourceFiles;
std::vector<cmXCodeObject*> sourceFiles;
- for (auto sourceFile : classes) {
+ for (auto sourceFile : commonSourceFiles) {
cmXCodeObject* xsf = this->CreateXCodeSourceFile(
this->CurrentLocalGenerator, sourceFile, gtgt);
cmXCodeObject* fr = xsf->GetObject("fileRef");
cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
+ if (!filetype) {
+ filetype = fr->GetObject()->GetObject("lastKnownFileType");
+ }
cmGeneratorTarget::SourceFileFlags tsFlags =
gtgt->GetTargetSourceFileFlags(sourceFile);
- if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
+ if (filetype && IsLibraryType(filetype->GetString())) {
if (sourceFile->GetObjectLibrary().empty()) {
externalObjFiles.push_back(xsf);
}
@@ -1275,7 +1342,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
using mapOfVectorOfSourceFiles =
std::map<std::string, std::vector<cmSourceFile*>>;
mapOfVectorOfSourceFiles bundleFiles;
- for (auto sourceFile : classes) {
+ for (auto sourceFile : commonSourceFiles) {
cmGeneratorTarget::SourceFileFlags tsFlags =
gtgt->GetTargetSourceFileFlags(sourceFile);
if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
@@ -1323,7 +1390,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
using mapOfVectorOfSourceFiles =
std::map<std::string, std::vector<cmSourceFile*>>;
mapOfVectorOfSourceFiles bundleFiles;
- for (auto sourceFile : classes) {
+ for (auto sourceFile : commonSourceFiles) {
cmGeneratorTarget::SourceFileFlags tsFlags =
gtgt->GetTargetSourceFileFlags(sourceFile);
if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
@@ -1353,22 +1420,20 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
}
}
- // create framework build phase
+ // always create framework build phase
cmXCodeObject* frameworkBuildPhase = nullptr;
- if (!externalObjFiles.empty()) {
- frameworkBuildPhase =
- this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
- frameworkBuildPhase->SetComment("Frameworks");
- frameworkBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- frameworkBuildPhase->AddAttribute("files", buildFiles);
- for (auto& externalObjFile : externalObjFiles) {
- buildFiles->AddObject(externalObjFile);
- }
- frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
- }
+ frameworkBuildPhase =
+ this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
+ frameworkBuildPhase->SetComment("Frameworks");
+ frameworkBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ frameworkBuildPhase->AddAttribute("files", buildFiles);
+ for (auto& externalObjFile : externalObjFiles) {
+ buildFiles->AddObject(externalObjFile);
+ }
+ frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
// create list of build phases and create the Xcode target
cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST);
@@ -1781,7 +1846,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
cmXCodeObject* buildSettings,
const std::string& configName)
{
- if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!gtgt->IsInBuildSystem()) {
return;
}
@@ -2472,7 +2537,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
this->XCodeObjectMap[gtgt] = target;
// Add source files without build rules for editing convenience.
- if (gtgt->GetType() == cmStateEnums::UTILITY &&
+ if (gtgt->GetType() != cmStateEnums::GLOBAL_TARGET &&
gtgt->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
std::vector<cmSourceFile*> sources;
if (!gtgt->GetConfigCommonSourceFiles(sources)) {
@@ -2614,7 +2679,7 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType(
cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget(
cmGeneratorTarget* gtgt, cmXCodeObject* buildPhases)
{
- if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!gtgt->IsInBuildSystem()) {
return nullptr;
}
cmXCodeObject* target = this->CreateObject(cmXCodeObject::PBXNativeTarget);
@@ -2757,7 +2822,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
cmSystemTools::Error("Error no target on xobject\n");
return;
}
- if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!gt->IsInBuildSystem()) {
return;
}
@@ -2768,6 +2833,190 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
}
+ // Separate libraries into ones that can be linked using "Link Binary With
+ // Libraries" build phase and the ones that can't. Only targets that build
+ // Apple bundles (.app, .framework, .bundle) can use this feature and only
+ // targets that represent actual libraries (static or dynamic, local or
+ // imported) not objects and not executables will be used. These are
+ // limitations imposed by CMake use-cases - otherwise a lot of things break.
+ // The rest will be linked using linker flags (OTHER_LDFLAGS setting in Xcode
+ // project).
+ std::map<std::string, std::vector<cmComputeLinkInformation::Item const*>>
+ configItemMap;
+ auto addToLinkerArguments =
+ [&configItemMap](const std::string& configName,
+ cmComputeLinkInformation::Item const* libItemPtr) {
+ auto& linkVector = configItemMap[configName];
+ if (std::find_if(linkVector.begin(), linkVector.end(),
+ [libItemPtr](cmComputeLinkInformation::Item const* p) {
+ return p == libItemPtr;
+ }) == linkVector.end()) {
+ linkVector.push_back(libItemPtr);
+ }
+ };
+ std::vector<cmComputeLinkInformation::Item const*> linkPhaseTargetVector;
+ std::map<std::string, std::vector<std::string>> targetConfigMap;
+ using ConfigItemPair =
+ std::pair<std::string, cmComputeLinkInformation::Item const*>;
+ std::map<std::string, std::vector<ConfigItemPair>> targetItemMap;
+ std::map<std::string, std::vector<std::string>> targetProductNameMap;
+ for (auto const& configName : this->CurrentConfigurationTypes) {
+ cmComputeLinkInformation* cli = gt->GetLinkInformation(configName);
+ if (!cli) {
+ continue;
+ }
+ for (auto const& libItem : cli->GetItems()) {
+ if (gt->IsBundleOnApple() &&
+ (gt->GetType() == cmStateEnums::EXECUTABLE ||
+ gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ gt->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ gt->GetType() == cmStateEnums::UNKNOWN_LIBRARY) &&
+ ((libItem.Target &&
+ (libItem.Target->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ libItem.Target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ libItem.Target->GetType() == cmStateEnums::MODULE_LIBRARY)) ||
+ (!libItem.Target && libItem.IsPath))) {
+ // Add unique configuration name to target-config map for later
+ // checks
+ std::string libName;
+ if (libItem.Target) {
+ libName = libItem.Target->GetName();
+ } else {
+ libName = cmSystemTools::GetFilenameName(libItem.Value.Value);
+ const auto libExt = cmSystemTools::GetFilenameExtension(libName);
+ if (!IsLibraryExtension(libExt)) {
+ // Add this library item to a regular linker flag list
+ addToLinkerArguments(configName, &libItem);
+ continue;
+ }
+ }
+ auto& configVector = targetConfigMap[libName];
+ if (std::find(configVector.begin(), configVector.end(), configName) ==
+ configVector.end()) {
+ configVector.push_back(configName);
+ }
+ // Add a pair of config and item to target-item map
+ auto& itemVector = targetItemMap[libName];
+ itemVector.emplace_back(ConfigItemPair(configName, &libItem));
+ // Add product file-name to a lib-product map
+ auto productName = cmSystemTools::GetFilenameName(libItem.Value.Value);
+ auto& productVector = targetProductNameMap[libName];
+ if (std::find(productVector.begin(), productVector.end(),
+ productName) == productVector.end()) {
+ productVector.push_back(productName);
+ }
+ } else {
+ // Add this library item to a regular linker flag list
+ addToLinkerArguments(configName, &libItem);
+ }
+ }
+ }
+
+ // Go through target library map and separate libraries that are linked
+ // in all configurations and produce only single product, from the rest.
+ // Only these will be linked through "Link Binary With Libraries" build
+ // phase.
+ for (auto const& targetLibConfigs : targetConfigMap) {
+ // Add this library to "Link Binary With Libraries" build phase if it's
+ // linked in all configurations and it has only one product name
+ auto& itemVector = targetItemMap[targetLibConfigs.first];
+ auto& productVector = targetProductNameMap[targetLibConfigs.first];
+ if (targetLibConfigs.second == this->CurrentConfigurationTypes &&
+ productVector.size() == 1) {
+ // Add this library to "Link Binary With Libraries" list
+ linkPhaseTargetVector.push_back(itemVector[0].second);
+ } else {
+ for (auto const& libItem : targetItemMap[targetLibConfigs.first]) {
+ // Add this library item to a regular linker flag list
+ addToLinkerArguments(libItem.first, libItem.second);
+ }
+ }
+ }
+
+ // Add libraries to "Link Binary With Libraries" build phase and collect
+ // their search paths. Xcode does not support per-configuration linking
+ // in this build phase so we don't have to do this for each configuration
+ // separately.
+ std::vector<std::string> linkSearchPaths;
+ for (auto const& libItem : linkPhaseTargetVector) {
+ // Add target output directory as a library search path
+ std::string linkDir;
+ if (libItem->Target) {
+ linkDir = cmSystemTools::GetParentDirectory(
+ libItem->Target->GetLocationForBuild());
+ } else {
+ linkDir = cmSystemTools::GetParentDirectory(libItem->Value.Value);
+ }
+ if (std::find(linkSearchPaths.begin(), linkSearchPaths.end(), linkDir) ==
+ linkSearchPaths.end()) {
+ linkSearchPaths.push_back(linkDir);
+ }
+ // Add target dependency
+ if (libItem->Target && !libItem->Target->IsImported()) {
+ for (auto const& configName : this->CurrentConfigurationTypes) {
+ target->AddDependTarget(configName, libItem->Target->GetName());
+ }
+ }
+ // Get the library target
+ auto* libTarget = FindXCodeTarget(libItem->Target);
+ cmXCodeObject* buildFile;
+ if (!libTarget) {
+ if (libItem->IsPath) {
+ // Get or create a direct file ref in the root project
+ auto it = this->ExternalLibRefs.find(libItem->Value.Value);
+ if (it == this->ExternalLibRefs.end()) {
+ buildFile = CreateXCodeBuildFileFromPath(libItem->Value.Value, gt,
+ "", nullptr);
+ this->ExternalLibRefs.emplace(libItem->Value.Value, buildFile);
+ } else {
+ buildFile = it->second;
+ }
+ } else {
+ // Add this library item back to a regular linker flag list
+ for (const auto& conf : configItemMap) {
+ addToLinkerArguments(conf.first, libItem);
+ }
+ continue;
+ }
+ } else {
+ // Add the target output file as a build reference for other targets
+ // to link against
+ auto* fileRefObject = libTarget->GetObject("productReference");
+ if (!fileRefObject) {
+ // Add this library item back to a regular linker flag list
+ for (const auto& conf : configItemMap) {
+ addToLinkerArguments(conf.first, libItem);
+ }
+ continue;
+ }
+ auto it = FileRefToBuildFileMap.find(fileRefObject);
+ if (it == FileRefToBuildFileMap.end()) {
+ buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
+ buildFile->AddAttribute("fileRef", fileRefObject);
+ FileRefToBuildFileMap[fileRefObject] = buildFile;
+ } else {
+ buildFile = it->second;
+ }
+ }
+ // Add this reference to current target
+ auto* buildPhases = target->GetObject("buildPhases");
+ if (!buildPhases) {
+ continue;
+ }
+ auto* frameworkBuildPhase =
+ buildPhases->GetObject(cmXCodeObject::PBXFrameworksBuildPhase);
+ if (!frameworkBuildPhase) {
+ continue;
+ }
+ auto* buildFiles = frameworkBuildPhase->GetObject("files");
+ if (!buildFiles) {
+ continue;
+ }
+ if (!buildFiles->HasObject(buildFile)) {
+ buildFiles->AddObject(buildFile);
+ }
+ }
+
// Loop over configuration types and set per-configuration info.
for (auto const& configName : this->CurrentConfigurationTypes) {
{
@@ -2795,21 +3044,20 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
// Compute the link library and directory information.
- cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName);
- if (!pcli) {
+ cmComputeLinkInformation* cli = gt->GetLinkInformation(configName);
+ if (!cli) {
continue;
}
- cmComputeLinkInformation& cli = *pcli;
// Add dependencies directly on library files.
- for (auto const& libDep : cli.GetDepends()) {
+ for (auto const& libDep : cli->GetDepends()) {
target->AddDependLibrary(configName, libDep);
}
// add the library search paths
{
std::string linkDirs;
- for (auto const& libDir : cli.GetDirectories()) {
+ for (auto const& libDir : cli->GetDirectories()) {
if (!libDir.empty() && libDir != "/usr/lib") {
// Now add the same one but append
// $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it:
@@ -2820,15 +3068,22 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
linkDirs += this->XCodeEscapePath(libDir);
}
}
+ // Add previously collected paths where to look for libraries
+ // that were added to "Link Binary With Libraries"
+ for (auto& linkDir : linkSearchPaths) {
+ linkDirs += " ";
+ linkDirs += this->XCodeEscapePath(linkDir);
+ }
this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
linkDirs.c_str(), configName);
}
- // now add the link libraries
+ // now add the left-over link libraries
{
std::string linkLibs;
const char* sep = "";
- for (auto const& libName : cli.GetItems()) {
+ for (auto const& libItem : configItemMap[configName]) {
+ auto const& libName = *libItem;
linkLibs += sep;
sep = " ";
if (libName.IsPath) {
@@ -2859,13 +3114,9 @@ bool cmGlobalXCodeGenerator::CreateGroups(
// end up with (empty anyhow) ZERO_CHECK, install, or test source
// groups:
//
- if (gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
- continue;
- }
- if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- continue;
- }
- if (gtgt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+ if (!gtgt->IsInBuildSystem() ||
+ gtgt->GetType() == cmStateEnums::GLOBAL_TARGET ||
+ gtgt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
continue;
}
@@ -3009,6 +3260,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->ClearXCodeObjects();
this->RootObject = nullptr;
this->MainGroupChildren = nullptr;
+ this->FrameworkGroup = nullptr;
cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
cmXCodeObject* listObjs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
@@ -3043,6 +3295,15 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
productGroup->AddAttribute("children", productGroupChildren);
this->MainGroupChildren->AddObject(productGroup);
+ this->FrameworkGroup = this->CreateObject(cmXCodeObject::PBXGroup);
+ this->FrameworkGroup->AddAttribute("name", this->CreateString("Frameworks"));
+ this->FrameworkGroup->AddAttribute("sourceTree",
+ this->CreateString("<group>"));
+ cmXCodeObject* frameworkGroupChildren =
+ this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ this->FrameworkGroup->AddAttribute("children", frameworkGroupChildren);
+ this->MainGroupChildren->AddObject(this->FrameworkGroup);
+
this->RootObject = this->CreateObject(cmXCodeObject::PBXProject);
this->RootObject->SetComment("Project object");
@@ -3121,7 +3382,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
buildSettings->AddAttribute("ONLY_ACTIVE_ARCH", this->CreateString("YES"));
// When targeting macOS, use only the host architecture.
if (this->SystemName == "Darwin"_s &&
- (!sysroot || !*sysroot ||
+ (!cmNonempty(sysroot) ||
cmSystemTools::LowerCase(sysroot).find("macos") !=
std::string::npos)) {
buildSettings->AddAttribute("ARCHS",
@@ -3131,7 +3392,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
// Tell Xcode to use ARCHS (ONLY_ACTIVE_ARCH defaults to NO).
buildSettings->AddAttribute("ARCHS", this->CreateString(archs));
}
- if (deploymentTarget && *deploymentTarget) {
+ if (cmNonempty(deploymentTarget)) {
buildSettings->AddAttribute(GetDeploymentPlatform(root->GetMakefile()),
this->CreateString(deploymentTarget));
}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index e2d1b3a..7018de7 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -28,7 +28,7 @@ struct cmDocumentationEntry;
/** \class cmGlobalXCodeGenerator
* \brief Write a Unix makefiles.
*
- * cmGlobalXCodeGenerator manages UNIX build process for a tree
+ * cmGlobalXCodeGenerator manages Xcode build process for a tree
*/
class cmGlobalXCodeGenerator : public cmGlobalGenerator
{
@@ -204,10 +204,10 @@ private:
cmGeneratorTarget* target,
const std::string& lang,
cmSourceFile* sf);
- cmXCodeObject* CreateXCodeSourceFileFromPath(const std::string& fullpath,
- cmGeneratorTarget* target,
- const std::string& lang,
- cmSourceFile* sf);
+ cmXCodeObject* CreateXCodeBuildFileFromPath(const std::string& fullpath,
+ cmGeneratorTarget* target,
+ const std::string& lang,
+ cmSourceFile* sf);
cmXCodeObject* CreateXCodeFileReference(cmSourceFile* sf,
cmGeneratorTarget* target);
cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen, cmSourceFile* sf,
@@ -282,6 +282,7 @@ private:
std::string PostBuildMakeTarget(std::string const& tName,
std::string const& configName);
cmXCodeObject* MainGroupChildren;
+ cmXCodeObject* FrameworkGroup;
cmMakefile* CurrentMakefile;
cmLocalGenerator* CurrentLocalGenerator;
std::vector<std::string> CurrentConfigurationTypes;
@@ -295,13 +296,16 @@ private:
std::map<std::string, cmXCodeObject*> GroupNameMap;
std::map<std::string, cmXCodeObject*> TargetGroup;
std::map<std::string, cmXCodeObject*> FileRefs;
+ std::map<std::string, cmXCodeObject*> ExternalLibRefs;
std::map<cmGeneratorTarget const*, cmXCodeObject*> XCodeObjectMap;
+ std::map<cmXCodeObject*, cmXCodeObject*> FileRefToBuildFileMap;
std::vector<std::string> Architectures;
std::string ObjectDirArchDefault;
std::string ObjectDirArch;
std::string SystemName;
std::string GeneratorToolset;
std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex;
+ std::vector<std::string> EnabledLangs;
};
#endif
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index c23156d..8a7728e 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGraphVizWriter.h"
+#include <algorithm>
#include <cctype>
#include <iostream>
#include <memory>
@@ -125,14 +126,6 @@ cmGraphVizWriter::cmGraphVizWriter(std::string const& fileName,
cmGraphVizWriter::~cmGraphVizWriter()
{
this->WriteFooter(this->GlobalFileStream);
-
- for (auto& fileStream : this->PerTargetFileStreams) {
- this->WriteFooter(*fileStream.second);
- }
-
- for (auto& fileStream : this->TargetDependersFileStreams) {
- this->WriteFooter(*fileStream.second);
- }
}
void cmGraphVizWriter::VisitGraph(std::string const&)
@@ -151,20 +144,10 @@ void cmGraphVizWriter::OnItem(cmLinkItem const& item)
++NextNodeId;
this->WriteNode(this->GlobalFileStream, item);
-
- if (this->GeneratePerTarget) {
- this->CreateTargetFile(this->PerTargetFileStreams, item);
- }
-
- if (this->GenerateDependers) {
- this->CreateTargetFile(this->TargetDependersFileStreams, item,
- ".dependers");
- }
}
-void cmGraphVizWriter::CreateTargetFile(FileStreamMap& fileStreamMap,
- cmLinkItem const& item,
- std::string const& fileNameSuffix)
+std::unique_ptr<cmGeneratedFileStream> cmGraphVizWriter::CreateTargetFile(
+ cmLinkItem const& item, std::string const& fileNameSuffix)
{
auto const pathSafeItemName = PathSafeString(item.AsStr());
auto const perTargetFileName =
@@ -175,7 +158,7 @@ void cmGraphVizWriter::CreateTargetFile(FileStreamMap& fileStreamMap,
this->WriteHeader(*perTargetFileStream, item.AsStr());
this->WriteNode(*perTargetFileStream, item);
- fileStreamMap.emplace(item.AsStr(), std::move(perTargetFileStream));
+ return perTargetFileStream;
}
void cmGraphVizWriter::OnDirectLink(cmLinkItem const& depender,
@@ -260,7 +243,7 @@ void cmGraphVizWriter::ReadSettings(
do { \
const char* value = mf.GetDefinition(cmakeDefinition); \
if (value) { \
- (var) = mf.IsOn(cmakeDefinition); \
+ (var) = cmIsOn(value); \
} \
} while (false)
@@ -323,13 +306,12 @@ void cmGraphVizWriter::Write()
}
if (this->GeneratePerTarget) {
- WritePerTargetConnections<DependeesDir>(PerTargetConnections,
- PerTargetFileStreams);
+ WritePerTargetConnections<DependeesDir>(PerTargetConnections);
}
if (this->GenerateDependers) {
WritePerTargetConnections<DependersDir>(TargetDependersConnections,
- TargetDependersFileStreams);
+ ".dependers");
}
}
@@ -368,7 +350,7 @@ void cmGraphVizWriter::FindAllConnections(const ConnectionsMap& connectionMap,
template <typename DirFunc>
void cmGraphVizWriter::WritePerTargetConnections(
- const ConnectionsMap& connections, const FileStreamMap& streams)
+ const ConnectionsMap& connections, const std::string& fileNameSuffix)
{
// the per target connections must be extended by indirect dependencies
ConnectionsMap extendedConnections;
@@ -387,7 +369,9 @@ void cmGraphVizWriter::WritePerTargetConnections(
}
const Connections& cons = conPerTarget.second;
- auto fileStream = streams.at(rootItem.AsStr()).get();
+
+ std::unique_ptr<cmGeneratedFileStream> fileStream =
+ this->CreateTargetFile(rootItem, fileNameSuffix);
for (const Connection& con : cons) {
const cmLinkItem& src = DirFunc::src(con);
@@ -395,6 +379,8 @@ void cmGraphVizWriter::WritePerTargetConnections(
this->WriteNode(*fileStream, con.dst);
this->WriteConnection(*fileStream, src, dst, con.scopeType);
}
+
+ this->WriteFooter(*fileStream);
}
}
@@ -567,16 +553,23 @@ bool cmGraphVizWriter::TargetTypeEnabled(
std::string cmGraphVizWriter::ItemNameWithAliases(
std::string const& itemName) const
{
- auto nameWithAliases = itemName;
-
+ std::vector<std::string> items;
for (auto const& lg : this->GlobalGenerator->GetLocalGenerators()) {
for (auto const& aliasTargets : lg->GetMakefile()->GetAliasTargets()) {
if (aliasTargets.second == itemName) {
- nameWithAliases += "\\n(" + aliasTargets.first + ")";
+ items.push_back(aliasTargets.first);
}
}
}
+ std::sort(items.begin(), items.end());
+ items.erase(std::unique(items.begin(), items.end()), items.end());
+
+ auto nameWithAliases = itemName;
+ for(auto const& item : items) {
+ nameWithAliases += "\\n(" + item + ")";
+ }
+
return nameWithAliases;
}
diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h
index 9766068..d1300ac 100644
--- a/Source/cmGraphVizWriter.h
+++ b/Source/cmGraphVizWriter.h
@@ -46,9 +46,6 @@ public:
void Write();
private:
- using FileStreamMap =
- std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>;
-
struct Connection
{
Connection(cmLinkItem s, cmLinkItem d, std::string scope)
@@ -76,8 +73,8 @@ private:
void WriteNode(cmGeneratedFileStream& fs, cmLinkItem const& item);
- void CreateTargetFile(FileStreamMap& fileStreamMap, cmLinkItem const& target,
- std::string const& fileNameSuffix = "");
+ std::unique_ptr<cmGeneratedFileStream> CreateTargetFile(
+ cmLinkItem const& target, std::string const& fileNameSuffix = "");
void WriteConnection(cmGeneratedFileStream& fs,
cmLinkItem const& dependerTargetName,
@@ -95,7 +92,7 @@ private:
template <typename DirFunc>
void WritePerTargetConnections(const ConnectionsMap& connections,
- const FileStreamMap& streams);
+ const std::string& fileNameSuffix = "");
bool ItemExcluded(cmLinkItem const& item);
bool ItemNameFilteredOut(std::string const& itemName);
@@ -111,8 +108,6 @@ private:
std::string FileName;
cmGeneratedFileStream GlobalFileStream;
- FileStreamMap PerTargetFileStreams;
- FileStreamMap TargetDependersFileStreams;
ConnectionsMap PerTargetConnections;
ConnectionsMap TargetDependersConnections;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 178af73..83609e2 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -680,7 +680,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) {
cmProp files = target.GetProperty("PRIVATE_HEADER");
- if (files && !files->empty()) {
+ if (cmNonempty(files)) {
std::vector<std::string> relFiles = cmExpandedList(*files);
std::vector<std::string> absFiles;
if (!helper.MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) {
@@ -702,7 +702,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
files = target.GetProperty("PUBLIC_HEADER");
- if (files && !files->empty()) {
+ if (cmNonempty(files)) {
std::vector<std::string> relFiles = cmExpandedList(*files);
std::vector<std::string> absFiles;
if (!helper.MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) {
@@ -724,7 +724,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
files = target.GetProperty("RESOURCE");
- if (files && !files->empty()) {
+ if (cmNonempty(files)) {
std::vector<std::string> relFiles = cmExpandedList(*files);
std::vector<std::string> absFiles;
if (!helper.MakeFilesFullPath("RESOURCE", relFiles, absFiles)) {
@@ -1157,7 +1157,7 @@ bool HandleDirectoryMode(std::vector<std::string> const& args,
} else if (doing == DoingRegex) {
literal_args += " REGEX \"";
// Match rules are case-insensitive on some platforms.
-#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
+#if defined(_WIN32) || defined(__APPLE__)
std::string regex = cmSystemTools::LowerCase(args[i]);
#else
std::string regex = args[i];
diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx
index 9f17f15..3a2e3be 100644
--- a/Source/cmJsonObjects.cxx
+++ b/Source/cmJsonObjects.cxx
@@ -51,11 +51,7 @@ std::vector<std::string> getConfigurations(const cmake* cm)
return configurations;
}
- makefiles[0]->GetConfigurations(configurations);
- if (configurations.empty()) {
- configurations.emplace_back();
- }
- return configurations;
+ return makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
}
bool hasString(const Json::Value& v, const std::string& s)
diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx
index acc23c8..dfdd3ff 100644
--- a/Source/cmLinkItemGraphVisitor.cxx
+++ b/Source/cmLinkItemGraphVisitor.cxx
@@ -24,15 +24,12 @@ void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item)
void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
cmLinkItem const& rootItem)
{
- if (this->LinkVisited(item, rootItem)) {
- return;
- }
-
if (item.Target == nullptr) {
return;
}
- for (auto const& config : item.Target->Makefile->GetGeneratorConfigs()) {
+ for (auto const& config : item.Target->Makefile->GetGeneratorConfigs(
+ cmMakefile::IncludeEmptyConfig)) {
this->VisitLinks(item, rootItem, config);
}
}
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index c50a786..5739fec 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -191,21 +191,18 @@ bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg,
target.GetLinkClosure(config);
if (cm::contains(closure->Languages, "CUDA")) {
- if (cmProp separableCompilation =
- target.GetProperty("CUDA_SEPARABLE_COMPILATION")) {
- if (cmIsOn(*separableCompilation)) {
- bool doDeviceLinking = false;
- switch (target.GetType()) {
- case cmStateEnums::SHARED_LIBRARY:
- case cmStateEnums::MODULE_LIBRARY:
- case cmStateEnums::EXECUTABLE:
- doDeviceLinking = true;
- break;
- default:
- break;
- }
- return doDeviceLinking;
+ if (cmIsOn(target.GetProperty("CUDA_SEPARABLE_COMPILATION"))) {
+ bool doDeviceLinking = false;
+ switch (target.GetType()) {
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::EXECUTABLE:
+ doDeviceLinking = true;
+ break;
+ default:
+ break;
}
+ return doDeviceLinking;
}
cmComputeLinkInformation* pcli = target.GetLinkInformation(config);
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 89902ff..0b4414d 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -175,6 +175,32 @@ public:
std::ostream& operator<<(std::ostream& os, BT<std::string> const& s);
+// Wrap type T as a value with potentially multiple backtraces. For purposes
+// of ordering and equality comparison, only the original value is used. The
+// backtrace is considered incidental.
+template <typename T>
+class BTs
+{
+public:
+ BTs(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace())
+ : Value(std::move(v))
+ {
+ Backtraces.emplace_back(std::move(bt));
+ }
+ T Value;
+ std::vector<cmListFileBacktrace> Backtraces;
+ friend bool operator==(BTs<T> const& l, BTs<T> const& r)
+ {
+ return l.Value == r.Value;
+ }
+ friend bool operator<(BTs<T> const& l, BTs<T> const& r)
+ {
+ return l.Value < r.Value;
+ }
+ friend bool operator==(BTs<T> const& l, T const& r) { return l.Value == r; }
+ friend bool operator==(T const& l, BTs<T> const& r) { return l == r.Value; }
+};
+
std::vector<BT<std::string>> ExpandListWithBacktrace(
std::string const& list,
cmListFileBacktrace const& bt = cmListFileBacktrace());
diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx
index 278ec8b..44db842 100644
--- a/Source/cmLocalCommonGenerator.cxx
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -17,10 +17,8 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
: cmLocalGenerator(gg, mf)
, WorkingDirectory(std::move(wd))
{
- this->Makefile->GetConfigurations(this->ConfigNames);
- if (this->ConfigNames.empty()) {
- this->ConfigNames.emplace_back();
- }
+ this->ConfigNames =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
}
cmLocalCommonGenerator::~cmLocalCommonGenerator() = default;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index c15ca7c..2380cce 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -39,6 +39,7 @@
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceFileLocationKind.h"
+#include "cmStandardLevelResolver.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
@@ -129,7 +130,7 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
this->LinkerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
}
- if (std::string const* appleArchSysroots =
+ if (cmProp appleArchSysroots =
this->Makefile->GetDef("CMAKE_APPLE_ARCH_SYSROOTS")) {
std::string const& appleArchs =
this->Makefile->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES");
@@ -220,7 +221,7 @@ void cmLocalGenerator::ComputeObjectMaxPath()
this->ObjectPathMax = 1000;
#endif
const char* plen = this->Makefile->GetDefinition("CMAKE_OBJECT_PATH_MAX");
- if (plen && *plen) {
+ if (cmNonempty(plen)) {
unsigned int pmax;
if (sscanf(plen, "%u", &pmax) == 1) {
if (pmax >= 128) {
@@ -283,7 +284,7 @@ void cmLocalGenerator::TraceDependencies()
// Generate the rule files for each target.
const auto& targets = this->GetGeneratorTargets();
for (const auto& target : targets) {
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
continue;
}
target->TraceDependencies();
@@ -297,9 +298,9 @@ void cmLocalGenerator::GenerateTestFiles()
}
// Compute the set of configurations.
- std::vector<std::string> configurationTypes;
- const std::string& config =
- this->Makefile->GetConfigurations(configurationTypes, false);
+ std::vector<std::string> configurationTypes =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::OnlyMultiConfig);
+ std::string config = this->Makefile->GetDefaultConfiguration();
std::string file =
cmStrCat(this->StateSnapshot.GetDirectory().GetCurrentBinary(),
@@ -379,7 +380,7 @@ void cmLocalGenerator::GenerateTestFiles()
void cmLocalGenerator::CreateEvaluationFileOutputs()
{
std::vector<std::string> const& configs =
- this->Makefile->GetGeneratorConfigs();
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
for (std::string const& c : configs) {
this->CreateEvaluationFileOutputs(c);
}
@@ -433,7 +434,7 @@ void cmLocalGenerator::GenerateInstallRules()
prefix_win32 = "C:";
}
const char* project_name = this->Makefile->GetDefinition("PROJECT_NAME");
- if (project_name && project_name[0]) {
+ if (cmNonempty(project_name)) {
prefix_win32 += "/Program Files/";
prefix_win32 += project_name;
} else {
@@ -462,9 +463,9 @@ void cmLocalGenerator::GenerateInstallRules()
}
// Compute the set of configurations.
- std::vector<std::string> configurationTypes;
- const std::string& config =
- this->Makefile->GetConfigurations(configurationTypes, false);
+ std::vector<std::string> configurationTypes =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::OnlyMultiConfig);
+ std::string config = this->Makefile->GetDefaultConfiguration();
// Choose a default install configuration.
std::string default_config = config;
@@ -753,16 +754,13 @@ cmGeneratorTarget* cmLocalGenerator::FindLocalNonAliasGeneratorTarget(
void cmLocalGenerator::ComputeTargetManifest()
{
// Collect the set of configuration types.
- std::vector<std::string> configNames;
- this->Makefile->GetConfigurations(configNames);
- if (configNames.empty()) {
- configNames.emplace_back();
- }
+ std::vector<std::string> configNames =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
// Add our targets to the manifest for each configuration.
const auto& targets = this->GetGeneratorTargets();
for (const auto& target : targets) {
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
continue;
}
for (std::string const& c : configNames) {
@@ -774,11 +772,8 @@ void cmLocalGenerator::ComputeTargetManifest()
bool cmLocalGenerator::ComputeTargetCompileFeatures()
{
// Collect the set of configuration types.
- std::vector<std::string> configNames;
- this->Makefile->GetConfigurations(configNames);
- if (configNames.empty()) {
- configNames.emplace_back();
- }
+ std::vector<std::string> configNames =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
using LanguagePair = std::pair<std::string, std::string>;
std::vector<LanguagePair> pairedLanguages{ { "OBJC", "C" },
@@ -802,40 +797,9 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures()
// Now that C/C++ _STANDARD values have been computed
// set the values to ObjC/ObjCXX _STANDARD variables
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- auto copyStandardToObjLang = [&](LanguagePair const& lang) -> bool {
- if (!target->GetProperty(cmStrCat(lang.first, "_STANDARD"))) {
- cmProp standard =
- target->GetProperty(cmStrCat(lang.second, "_STANDARD"));
- if (!standard) {
- standard = this->Makefile->GetDef(
- cmStrCat("CMAKE_", lang.second, "_STANDARD_DEFAULT"));
- }
- target->Target->SetProperty(cmStrCat(lang.first, "_STANDARD"),
- standard ? standard->c_str() : nullptr);
- return true;
- }
- return false;
- };
- auto copyPropertyToObjLang = [&](LanguagePair const& lang,
- const char* property) {
- if (!target->GetProperty(cmStrCat(lang.first, property)) &&
- target->GetProperty(cmStrCat(lang.second, property))) {
- cmProp p = target->GetProperty(cmStrCat(lang.second, property));
- target->Target->SetProperty(cmStrCat(lang.first, property),
- p ? p->c_str() : nullptr);
- }
- };
- for (auto const& lang : pairedLanguages) {
- if (copyStandardToObjLang(lang)) {
- copyPropertyToObjLang(lang, "_STANDARD_REQUIRED");
- copyPropertyToObjLang(lang, "_EXTENSIONS");
- }
- }
- if (cmProp standard = target->GetProperty("CUDA_STANDARD")) {
- if (*standard == "98") {
- target->Target->SetProperty("CUDA_STANDARD", "03");
- }
+ if (target->CanCompileSources()) {
+ for (std::string const& c : configNames) {
+ target->ComputeCompileFeatures(c, inferredEnabledLanguages);
}
}
}
@@ -929,7 +893,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
emitted.insert("/System/Library/Frameworks");
#endif
for (std::string const& i : includes) {
- if (fwSearchFlag && *fwSearchFlag && this->Makefile->IsOn("APPLE") &&
+ if (cmNonempty(fwSearchFlag) && this->Makefile->IsOn("APPLE") &&
cmSystemTools::IsPathToFramework(i)) {
std::string const frameworkDir =
cmSystemTools::CollapseFullPath(cmStrCat(i, "/../"));
@@ -1025,12 +989,13 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
this->AppendCompileOptions(flags, targetCompileOpts);
}
+ cmStandardLevelResolver standardResolver(this->Makefile);
for (auto const& it : target->GetMaxLanguageStandards()) {
- cmProp standard = target->GetProperty(it.first + "_STANDARD");
+ cmProp standard = target->GetLanguageStandard(it.first, config);
if (!standard) {
continue;
}
- if (this->Makefile->IsLaterStandard(it.first, *standard, it.second)) {
+ if (standardResolver.IsLaterStandard(it.first, *standard, it.second)) {
std::ostringstream e;
e << "The COMPILE_FEATURES property of target \"" << target->GetName()
<< "\" was evaluated when computing the link "
@@ -1050,7 +1015,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
}
std::string compReqFlag;
- this->AddCompilerRequirementFlag(compReqFlag, target, lang);
+ this->AddCompilerRequirementFlag(compReqFlag, target, lang, config);
if (!compReqFlag.empty()) {
flags.emplace_back(std::move(compReqFlag));
}
@@ -1308,7 +1273,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
}
}
- // Emit remaining non implicit user direcories.
+ // Emit remaining non implicit user directories.
for (BT<std::string> const& udr : userDirs) {
if (notExcluded(udr.Value)) {
emitBT(udr);
@@ -1578,9 +1543,8 @@ void cmLocalGenerator::GetTargetFlags(
frameworkPath, linkPath);
}
- if (cmIsOn(this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) {
- std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_") +
- linkLanguage + std::string("_FLAGS");
+ if (this->Makefile->IsOn("BUILD_SHARED_LIBS")) {
+ std::string sFlagVar = "CMAKE_SHARED_BUILD_" + linkLanguage + "_FLAGS";
exeFlags += this->Makefile->GetSafeDefinition(sFlagVar);
exeFlags += " ";
}
@@ -1689,7 +1653,7 @@ static std::string GetFrameworkFlags(const std::string& lang,
std::string fwSearchFlagVar = "CMAKE_" + lang + "_FRAMEWORK_SEARCH_FLAG";
const char* fwSearchFlag = mf->GetDefinition(fwSearchFlagVar);
- if (!(fwSearchFlag && *fwSearchFlag)) {
+ if (!cmNonempty(fwSearchFlag)) {
return std::string();
}
@@ -1928,7 +1892,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
std::string sysrootFlagVar =
std::string("CMAKE_") + lang + "_SYSROOT_FLAG";
const char* sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar);
- if (sysrootFlag && *sysrootFlag) {
+ if (cmNonempty(sysrootFlag)) {
if (!this->AppleArchSysroots.empty() &&
!this->AllAppleArchSysrootsAreTheSame(archs, sysroot)) {
for (std::string const& arch : archs) {
@@ -1957,8 +1921,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
std::string("CMAKE_") + lang + "_OSX_DEPLOYMENT_TARGET_FLAG";
const char* deploymentTargetFlag =
this->Makefile->GetDefinition(deploymentTargetFlagVar);
- if (deploymentTargetFlag && *deploymentTargetFlag && deploymentTarget &&
- *deploymentTarget) {
+ if (cmNonempty(deploymentTargetFlag) && cmNonempty(deploymentTarget)) {
flags += " ";
flags += deploymentTargetFlag;
flags += deploymentTarget;
@@ -1975,6 +1938,9 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
this->AddConfigVariableFlags(flags, cmStrCat("CMAKE_", lang, "_FLAGS"),
config);
+ std::string const& compiler = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_COMPILER_ID"));
+
if (lang == "Swift") {
if (cmProp v = target->GetProperty("Swift_LANGUAGE_VERSION")) {
if (cmSystemTools::VersionCompare(
@@ -1988,9 +1954,6 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
target->AddCUDAArchitectureFlags(flags);
target->AddCUDAToolkitFlags(flags);
- std::string const& compiler =
- this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID");
-
if (compiler == "Clang") {
bool separable = target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION");
@@ -2002,12 +1965,29 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
}
}
}
-
+ // Add VFS Overlay for Clang compiliers
+ if (compiler == "Clang") {
+ if (const char* vfsOverlay =
+ this->Makefile->GetDefinition("CMAKE_CLANG_VFS_OVERLAY")) {
+ std::string const& compilerSimulateId =
+ this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_SIMULATE_ID"));
+ if (compilerSimulateId == "MSVC") {
+ this->AppendCompileOptions(
+ flags,
+ std::vector<std::string>{ "-Xclang", "-ivfsoverlay", "-Xclang",
+ vfsOverlay });
+ } else {
+ this->AppendCompileOptions(
+ flags, std::vector<std::string>{ "-ivfsoverlay", vfsOverlay });
+ }
+ }
+ }
// Add MSVC runtime library flags. This is activated by the presence
// of a default selection whether or not it is overridden by a property.
cmProp msvcRuntimeLibraryDefault =
this->Makefile->GetDef("CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT");
- if (msvcRuntimeLibraryDefault && !msvcRuntimeLibraryDefault->empty()) {
+ if (cmNonempty(msvcRuntimeLibraryDefault)) {
cmProp msvcRuntimeLibraryValue =
target->GetProperty("MSVC_RUNTIME_LIBRARY");
if (!msvcRuntimeLibraryValue) {
@@ -2046,7 +2026,7 @@ void cmLocalGenerator::AddLanguageFlagsForLinking(
// when linking in order to use the matching standard library.
// FIXME: If CMake gains an abstraction for standard library
// selection, this will have to be reconciled with it.
- this->AddCompilerRequirementFlag(flags, target, lang);
+ this->AddCompilerRequirementFlag(flags, target, lang, config);
}
this->AddLanguageFlags(flags, target, lang, config);
@@ -2189,156 +2169,20 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
}
void cmLocalGenerator::AddCompilerRequirementFlag(
- std::string& flags, cmGeneratorTarget const* target, const std::string& lang)
+ std::string& flags, cmGeneratorTarget const* target, const std::string& lang,
+ const std::string& config)
{
- if (lang.empty()) {
- return;
- }
- const char* defaultStd =
- this->Makefile->GetDefinition("CMAKE_" + lang + "_STANDARD_DEFAULT");
- if (!defaultStd || !*defaultStd) {
- // This compiler has no notion of language standard levels.
- return;
- }
- std::string extProp = lang + "_EXTENSIONS";
- bool ext = true;
- if (cmProp extPropValue = target->GetProperty(extProp)) {
- if (cmIsOff(*extPropValue)) {
- ext = false;
- }
- }
- std::string stdProp = lang + "_STANDARD";
- cmProp standardProp = target->GetProperty(stdProp);
- if (!standardProp) {
- if (ext) {
- // No language standard is specified and extensions are not disabled.
- // Check if this compiler needs a flag to enable extensions.
- std::string const option_flag =
- "CMAKE_" + lang + "_EXTENSION_COMPILE_OPTION";
- if (const char* opt =
- target->Target->GetMakefile()->GetDefinition(option_flag)) {
- std::vector<std::string> optVec = cmExpandedList(opt);
- for (std::string const& i : optVec) {
- this->AppendFlagEscape(flags, i);
- }
- }
- }
- return;
- }
-
- std::string const type = ext ? "EXTENSION" : "STANDARD";
+ cmStandardLevelResolver standardResolver(this->Makefile);
- if (target->GetPropertyAsBool(lang + "_STANDARD_REQUIRED")) {
- std::string option_flag =
- "CMAKE_" + lang + *standardProp + "_" + type + "_COMPILE_OPTION";
-
- const char* opt =
- target->Target->GetMakefile()->GetDefinition(option_flag);
- if (!opt) {
- std::ostringstream e;
- e << "Target \"" << target->GetName()
- << "\" requires the language "
- "dialect \""
- << lang << *standardProp << "\" "
- << (ext ? "(with compiler extensions)" : "")
- << ", but CMake "
- "does not know the compile flags to use to enable it.";
- this->IssueMessage(MessageType::FATAL_ERROR, e.str());
- } else {
- std::vector<std::string> optVec = cmExpandedList(opt);
- for (std::string const& i : optVec) {
- this->AppendFlagEscape(flags, i);
- }
- }
- return;
- }
-
- static std::map<std::string, std::vector<std::string>> langStdMap;
- if (langStdMap.empty()) {
- // Maintain sorted order, most recent first.
- langStdMap["CXX"].emplace_back("20");
- langStdMap["CXX"].emplace_back("17");
- langStdMap["CXX"].emplace_back("14");
- langStdMap["CXX"].emplace_back("11");
- langStdMap["CXX"].emplace_back("98");
-
- langStdMap["OBJCXX"].emplace_back("20");
- langStdMap["OBJCXX"].emplace_back("17");
- langStdMap["OBJCXX"].emplace_back("14");
- langStdMap["OBJCXX"].emplace_back("11");
- langStdMap["OBJCXX"].emplace_back("98");
-
- langStdMap["C"].emplace_back("11");
- langStdMap["C"].emplace_back("99");
- langStdMap["C"].emplace_back("90");
-
- langStdMap["OBJC"].emplace_back("11");
- langStdMap["OBJC"].emplace_back("99");
- langStdMap["OBJC"].emplace_back("90");
-
- langStdMap["CUDA"].emplace_back("20");
- langStdMap["CUDA"].emplace_back("17");
- langStdMap["CUDA"].emplace_back("14");
- langStdMap["CUDA"].emplace_back("11");
- langStdMap["CUDA"].emplace_back("03");
- }
-
- std::string standard(*standardProp);
- if (lang == "CUDA" && standard == "98") {
- standard = "03";
- }
- std::vector<std::string>& stds = langStdMap[lang];
-
- auto stdIt = std::find(stds.begin(), stds.end(), standard);
- if (stdIt == stds.end()) {
-
- std::string e =
- lang + "_STANDARD is set to invalid value '" + standard + "'";
- this->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, e, target->GetBacktrace());
- return;
- }
-
- auto defaultStdIt = std::find(stds.begin(), stds.end(), defaultStd);
- if (defaultStdIt == stds.end()) {
- std::string e = "CMAKE_" + lang +
- "_STANDARD_DEFAULT is set to invalid value '" + std::string(defaultStd) +
- "'";
- this->IssueMessage(MessageType::INTERNAL_ERROR, e);
- return;
- }
-
- // If the standard requested is older than the compiler's default
- // then we need to use a flag to change it. The comparison is
- // greater-or-equal because the standards are stored in backward
- // chronological order.
- if (stdIt >= defaultStdIt) {
- std::string option_flag =
- "CMAKE_" + lang + *stdIt + "_" + type + "_COMPILE_OPTION";
-
- std::string const& opt =
- target->Target->GetMakefile()->GetRequiredDefinition(option_flag);
- std::vector<std::string> optVec = cmExpandedList(opt);
- for (std::string const& i : optVec) {
- this->AppendFlagEscape(flags, i);
- }
- return;
- }
-
- // The standard requested is at least as new as the compiler's default,
- // and the standard request is not required. Decay to the newest standard
- // for which a flag is defined.
- for (; stdIt < defaultStdIt; ++stdIt) {
- std::string option_flag =
- cmStrCat("CMAKE_", lang, *stdIt, "_", type, "_COMPILE_OPTION");
-
- if (const char* opt =
- target->Target->GetMakefile()->GetDefinition(option_flag)) {
+ std::string const& optionFlagDef =
+ standardResolver.GetCompileOptionDef(target, lang, config);
+ if (!optionFlagDef.empty()) {
+ auto opt = target->Target->GetMakefile()->GetDefinition(optionFlagDef);
+ if (opt) {
std::vector<std::string> optVec = cmExpandedList(opt);
for (std::string const& i : optVec) {
this->AppendFlagEscape(flags, i);
}
- return;
}
}
}
@@ -2583,11 +2427,8 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags,
void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
{
- std::vector<std::string> configsList;
- std::string configDefault = this->Makefile->GetConfigurations(configsList);
- if (configsList.empty()) {
- configsList.push_back(configDefault);
- }
+ std::vector<std::string> configsList =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
for (std::string const& config : configsList) {
// FIXME: Refactor collection of sources to not evaluate object
@@ -3236,7 +3077,7 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
if (!lang.empty()) {
const char* df =
this->Makefile->GetDefinition(cmStrCat("CMAKE_", lang, "_DEFINE_FLAG"));
- if (df && *df) {
+ if (cmNonempty(df)) {
dflag = df;
}
}
@@ -3291,8 +3132,8 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags,
}
}
-const char* cmLocalGenerator::GetFeature(const std::string& feature,
- const std::string& config)
+cmProp cmLocalGenerator::GetFeature(const std::string& feature,
+ const std::string& config)
{
std::string featureName = feature;
// TODO: Define accumulation policy for features (prepend, append,
@@ -3304,7 +3145,7 @@ const char* cmLocalGenerator::GetFeature(const std::string& feature,
cmStateSnapshot snp = this->StateSnapshot;
while (snp.IsValid()) {
if (cmProp value = snp.GetDirectory().GetProperty(featureName)) {
- return value->c_str();
+ return value;
}
snp = snp.GetBuildsystemDirectoryParent();
}
@@ -3845,8 +3686,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
{
// Find the Info.plist template.
cmProp in = target->GetProperty("MACOSX_BUNDLE_INFO_PLIST");
- std::string inFile =
- (in && !in->empty()) ? *in : "MacOSXBundleInfo.plist.in";
+ std::string inFile = cmNonempty(in) ? *in : "MacOSXBundleInfo.plist.in";
if (!cmSystemTools::FileIsFullPath(inFile)) {
std::string inMod = this->Makefile->GetModulesFile(inFile);
if (!inMod.empty()) {
@@ -3876,7 +3716,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_SHORT_VERSION_STRING");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_BUNDLE_VERSION");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_COPYRIGHT");
- mf->ConfigureFile(inFile, fname, false, false, false);
+ mf->ConfigureFile(inFile, fname, false, false, false, true);
}
void cmLocalGenerator::GenerateFrameworkInfoPList(
@@ -3885,8 +3725,7 @@ void cmLocalGenerator::GenerateFrameworkInfoPList(
{
// Find the Info.plist template.
cmProp in = target->GetProperty("MACOSX_FRAMEWORK_INFO_PLIST");
- std::string inFile =
- (in && !in->empty()) ? *in : "MacOSXFrameworkInfo.plist.in";
+ std::string inFile = cmNonempty(in) ? *in : "MacOSXFrameworkInfo.plist.in";
if (!cmSystemTools::FileIsFullPath(inFile)) {
std::string inMod = this->Makefile->GetModulesFile(inFile);
if (!inMod.empty()) {
@@ -3912,7 +3751,7 @@ void cmLocalGenerator::GenerateFrameworkInfoPList(
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_IDENTIFIER");
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_SHORT_VERSION_STRING");
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_BUNDLE_VERSION");
- mf->ConfigureFile(inFile, fname, false, false, false);
+ mf->ConfigureFile(inFile, fname, false, false, false, true);
}
namespace {
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index f2d9145..0c51a65 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -20,6 +20,7 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmStateSnapshot.h"
class cmComputeLinkInformation;
@@ -123,7 +124,8 @@ public:
const std::string& config);
void AddCompilerRequirementFlag(std::string& flags,
cmGeneratorTarget const* target,
- const std::string& lang);
+ const std::string& lang,
+ const std::string& config);
//! Append flags to a string.
virtual void AppendFlags(std::string& flags,
const std::string& newFlags) const;
@@ -208,8 +210,7 @@ public:
void AppendFeatureOptions(std::string& flags, const std::string& lang,
const char* feature);
- const char* GetFeature(const std::string& feature,
- const std::string& config);
+ cmProp GetFeature(const std::string& feature, const std::string& config);
/** \brief Get absolute path to dependency \a name
*
diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx
index 098fa5a..a23ad57 100644
--- a/Source/cmLocalGhsMultiGenerator.cxx
+++ b/Source/cmLocalGhsMultiGenerator.cxx
@@ -11,7 +11,6 @@
#include "cmGhsMultiTargetGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmSourceFile.h"
-#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -33,7 +32,7 @@ std::string cmLocalGhsMultiGenerator::GetTargetDirectory(
void cmLocalGhsMultiGenerator::GenerateTargetsDepthFirst(
cmGeneratorTarget* target, std::vector<cmGeneratorTarget*>& remaining)
{
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
return;
}
// Find this target in the list of remaining targets.
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 87e8aa4..eb841d9 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -84,13 +84,31 @@ void cmLocalNinjaGenerator::Generate()
if (!showIncludesPrefix.empty()) {
cmGlobalNinjaGenerator::WriteComment(this->GetRulesFileStream(),
"localized /showIncludes string");
- this->GetRulesFileStream()
- << "msvc_deps_prefix = " << showIncludesPrefix << "\n\n";
+ this->GetRulesFileStream() << "msvc_deps_prefix = ";
+#ifdef WIN32
+ // Ninja uses the ANSI Windows APIs, so strings in the rules file
+ // typically need to be ANSI encoded. However, in this case the compiler
+ // is being invoked using the UTF-8 codepage so the /showIncludes prefix
+ // will be UTF-8 encoded on stdout. Ninja can't successfully compare this
+ // UTF-8 encoded prefix to the ANSI encoded msvc_deps_prefix if it
+ // contains any non-ASCII characters and dependency checking will fail.
+ // As a workaround, leave the msvc_deps_prefix UTF-8 encoded even though
+ // the rest of the file is ANSI encoded.
+ if (GetConsoleOutputCP() == CP_UTF8 && GetACP() != CP_UTF8) {
+ this->GetRulesFileStream().WriteRaw(showIncludesPrefix);
+ } else {
+ this->GetRulesFileStream() << showIncludesPrefix;
+ }
+#else
+ // It's safe to use the standard encoding on other platforms.
+ this->GetRulesFileStream() << showIncludesPrefix;
+#endif
+ this->GetRulesFileStream() << "\n\n";
}
}
for (const auto& target : this->GetGeneratorTargets()) {
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
continue;
}
auto tg = cmNinjaTargetGenerator::New(target.get());
@@ -102,9 +120,10 @@ void cmLocalNinjaGenerator::Generate()
this->GetGlobalGenerator()->IsMultiConfig()) {
cmNinjaBuild phonyAlias("phony");
this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
- target.get(), phonyAlias.Outputs, "");
+ target.get(), phonyAlias.Outputs, "", DependOnTargetArtifact);
this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
- target.get(), phonyAlias.ExplicitDeps, config);
+ target.get(), phonyAlias.ExplicitDeps, config,
+ DependOnTargetArtifact);
this->GetGlobalNinjaGenerator()->WriteBuild(
*this->GetGlobalNinjaGenerator()->GetConfigFileStream(config),
phonyAlias);
@@ -115,11 +134,12 @@ void cmLocalNinjaGenerator::Generate()
if (!this->GetGlobalNinjaGenerator()->GetDefaultConfigs().empty()) {
cmNinjaBuild phonyAlias("phony");
this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
- target.get(), phonyAlias.Outputs, "");
+ target.get(), phonyAlias.Outputs, "", DependOnTargetArtifact);
for (auto const& config :
this->GetGlobalNinjaGenerator()->GetDefaultConfigs()) {
this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
- target.get(), phonyAlias.ExplicitDeps, config);
+ target.get(), phonyAlias.ExplicitDeps, config,
+ DependOnTargetArtifact);
}
this->GetGlobalNinjaGenerator()->WriteBuild(
*this->GetGlobalNinjaGenerator()->GetDefaultFileStream(),
@@ -127,10 +147,11 @@ void cmLocalNinjaGenerator::Generate()
}
cmNinjaBuild phonyAlias("phony");
this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
- target.get(), phonyAlias.Outputs, "all");
+ target.get(), phonyAlias.Outputs, "all", DependOnTargetArtifact);
for (auto const& config : this->GetConfigNames()) {
this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
- target.get(), phonyAlias.ExplicitDeps, config);
+ target.get(), phonyAlias.ExplicitDeps, config,
+ DependOnTargetArtifact);
}
this->GetGlobalNinjaGenerator()->WriteBuild(
*this->GetGlobalNinjaGenerator()->GetDefaultFileStream(),
@@ -355,8 +376,8 @@ void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target,
cmNinjaDeps& outputs,
const std::string& config)
{
- this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs,
- config);
+ this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs, config,
+ DependOnTargetArtifact);
}
void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target,
@@ -668,7 +689,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
{
cmProp property_value = this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM");
- if (!property_value || property_value->empty()) {
+ if (!cmNonempty(property_value)) {
return std::string();
}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index ef160e7..73c0cde 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -66,10 +66,10 @@ public:
void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs,
const std::string& config);
- void AppendTargetDepends(
- cmGeneratorTarget* target, cmNinjaDeps& outputs, const std::string& config,
- const std::string& fileConfig,
- cmNinjaTargetDepends depends = DependOnTargetArtifact);
+ void AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs,
+ const std::string& config,
+ const std::string& fileConfig,
+ cmNinjaTargetDepends depends);
void AddCustomCommandTarget(cmCustomCommand const* cc,
cmGeneratorTarget* target);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index de1461a..8acd1e3 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -101,7 +101,7 @@ void cmLocalUnixMakefileGenerator3::Generate()
cmGlobalUnixMakefileGenerator3* gg =
static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
for (const auto& target : this->GetGeneratorTargets()) {
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
continue;
}
std::unique_ptr<cmMakefileTargetGenerator> tg(
@@ -137,7 +137,7 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles(
std::map<std::string, LocalObjectInfo>& localObjectFiles)
{
for (const auto& gt : this->GetGeneratorTargets()) {
- if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!gt->CanCompileSources()) {
continue;
}
std::vector<cmSourceFile const*> objectSources;
@@ -950,7 +950,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
std::string launcher;
// Short-circuit if there is no launcher.
const char* val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM");
- if (val && *val) {
+ if (cmNonempty(val)) {
// Expand rule variables referenced in the given launcher command.
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = target->GetName().c_str();
@@ -1744,7 +1744,7 @@ public:
return false;
}
// If it's an absolute path, check if it starts with the source
- // direcotory:
+ // directory:
return (
!(IsInDirectory(SourceDir, path) || IsInDirectory(BinaryDir, path)));
}
@@ -1807,7 +1807,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
std::string cidVar =
cmStrCat("CMAKE_", implicitLang.first, "_COMPILER_ID");
const char* cid = this->Makefile->GetDefinition(cidVar);
- if (cid && *cid) {
+ if (cmNonempty(cid)) {
cmakefileStream << "set(CMAKE_" << implicitLang.first
<< "_COMPILER_ID \"" << cid << "\")\n";
}
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index 9076e26..6c7d6c6 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -69,7 +69,7 @@ cmLocalVisualStudio10Generator::~cmLocalVisualStudio10Generator()
void cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst(
cmGeneratorTarget* target, std::vector<cmGeneratorTarget*>& remaining)
{
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!target->IsInBuildSystem()) {
return;
}
// Find this target in the list of remaining targets.
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 5d50e2d..50ffe8d 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -66,7 +66,7 @@ void cmLocalVisualStudio7Generator::AddHelperCommands()
// Now create GUIDs for targets
const auto& tgts = this->GetGeneratorTargets();
for (const auto& l : tgts) {
- if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!l->IsInBuildSystem()) {
continue;
}
cmProp path = l->GetProperty("EXTERNAL_MSPROJECT");
@@ -129,7 +129,7 @@ void cmLocalVisualStudio7Generator::WriteProjectFiles()
// Create the project file for each target.
for (const auto& l : tgts) {
- if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!l->IsInBuildSystem()) {
continue;
}
// INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
@@ -629,9 +629,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
break;
case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
+ case cmStateEnums::INTERFACE_LIBRARY:
configType = "10";
CM_FALLTHROUGH;
- default:
+ case cmStateEnums::UNKNOWN_LIBRARY:
targetBuilds = false;
break;
}
@@ -1331,8 +1332,8 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
const std::string& libName,
cmGeneratorTarget* target)
{
- std::vector<std::string> configs;
- this->Makefile->GetConfigurations(configs);
+ std::vector<std::string> configs =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
// We may be modifying the source groups temporarily, so make a copy.
std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
@@ -1580,8 +1581,9 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
std::string cmLocalVisualStudio7Generator::ComputeLongestObjectDirectory(
cmGeneratorTarget const* target) const
{
- std::vector<std::string> configs;
- target->Target->GetMakefile()->GetConfigurations(configs);
+ std::vector<std::string> configs =
+ target->Target->GetMakefile()->GetGeneratorConfigs(
+ cmMakefile::ExcludeEmptyConfig);
// Compute the maximum length configuration name.
std::string config_max;
@@ -1637,7 +1639,8 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
std::string source = sf->GetFullPath();
if (source != libName || target->GetType() == cmStateEnums::UTILITY ||
- target->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ target->GetType() == cmStateEnums::GLOBAL_TARGET ||
+ target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
// Look up the source kind and configs.
std::map<cmSourceFile const*, size_t>::const_iterator map_it =
sources.Index.find(sf);
@@ -1936,6 +1939,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran(
const char* keyword = p ? p->c_str() : "Console Application";
const char* projectType = 0;
switch (target->GetType()) {
+ case cmStateEnums::OBJECT_LIBRARY:
case cmStateEnums::STATIC_LIBRARY:
projectType = "typeStaticLibrary";
if (keyword) {
@@ -1957,7 +1961,8 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran(
break;
case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
- default:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ case cmStateEnums::UNKNOWN_LIBRARY:
break;
}
if (projectType) {
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index db5cee9..5cfe5f1 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -20,8 +20,10 @@
#include <cmext/algorithm>
#include <cmext/string_view>
-#include <cm3p/json/value.h>
-#include <cm3p/json/writer.h>
+#ifndef CMAKE_BOOTSTRAP
+# include <cm3p/json/value.h>
+# include <cm3p/json/writer.h>
+#endif
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
@@ -34,6 +36,7 @@
#include "cmExecutionStatus.h"
#include "cmExpandedCommandArgument.h" // IWYU pragma: keep
#include "cmExportBuildFileGenerator.h"
+#include "cmFSPermissions.h"
#include "cmFileLockPool.h"
#include "cmFunctionBlocker.h"
#include "cmGeneratedFileStream.h"
@@ -68,6 +71,8 @@
class cmMessenger;
+using namespace cmFSPermissions;
+
cmDirectoryId::cmDirectoryId(std::string s)
: String(std::move(s))
{
@@ -82,7 +87,6 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
{
this->IsSourceFileTryCompile = false;
- this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars();
this->SuppressSideEffects = false;
@@ -194,7 +198,7 @@ void cmMakefile::MaybeWarnCMP0074(std::string const& pkg)
std::string env;
cmSystemTools::GetEnv(varName, env);
- bool const haveVar = var && *var;
+ bool const haveVar = cmNonempty(var);
bool const haveEnv = !env.empty();
if ((haveVar || haveEnv) && this->WarnedCMP0074.insert(varName).second) {
std::ostringstream w;
@@ -750,7 +754,6 @@ void cmMakefile::ReadListFile(cmListFile const& listFile,
break;
}
}
- this->CheckForUnusedVariables();
this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile);
this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile);
@@ -1434,8 +1437,8 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent)
if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
cmProp p = parent->GetProperty("COMPILE_DEFINITIONS");
this->SetProperty("COMPILE_DEFINITIONS", p ? p->c_str() : nullptr);
- std::vector<std::string> configs;
- this->GetConfigurations(configs);
+ std::vector<std::string> configs =
+ this->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
for (std::string const& config : configs) {
std::string defPropName =
cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config));
@@ -1513,8 +1516,6 @@ void cmMakefile::PopFunctionScope(bool reportError)
#endif
this->PopLoopBlockBarrier();
-
- this->CheckForUnusedVariables();
}
void cmMakefile::PushMacroScope(std::string const& fileName,
@@ -1661,7 +1662,8 @@ void cmMakefile::Configure()
this->SetCheckCMP0000(true);
// Implicitly set the version for the user.
- this->SetPolicyVersion("2.4", std::string());
+ cmPolicies::ApplyPolicyVersion(this, 2, 4, 0,
+ cmPolicies::WarnCompat::Off);
}
}
bool hasProject = false;
@@ -1860,9 +1862,6 @@ void cmMakefile::AddSystemIncludeDirectories(const std::set<std::string>& incs)
void cmMakefile::AddDefinition(const std::string& name, cm::string_view value)
{
- if (this->VariableInitialized(name)) {
- this->LogUnused("changing definition", name);
- }
this->StateSnapshot.SetDefinition(name, value);
#ifndef CMAKE_BOOTSTRAP
@@ -1923,16 +1922,6 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value,
this->StateSnapshot.RemoveDefinition(name);
}
-void cmMakefile::CheckForUnusedVariables() const
-{
- if (!this->WarnUnused) {
- return;
- }
- for (const std::string& key : this->StateSnapshot.UnusedKeys()) {
- this->LogUnused("out of scope", key);
- }
-}
-
void cmMakefile::MarkVariableAsUsed(const std::string& var)
{
this->StateSnapshot.GetDefinition(var);
@@ -1960,29 +1949,8 @@ void cmMakefile::MaybeWarnUninitialized(std::string const& variable,
}
}
-void cmMakefile::LogUnused(const char* reason, const std::string& name) const
-{
- if (this->WarnUnused) {
- std::string path;
- if (!this->ExecutionStatusStack.empty()) {
- path = this->GetExecutionContext().FilePath;
- } else {
- path = cmStrCat(this->GetCurrentSourceDirectory(), "/CMakeLists.txt");
- }
-
- if (this->CheckSystemVars || this->IsProjectFile(path.c_str())) {
- std::ostringstream msg;
- msg << "unused variable (" << reason << ") \'" << name << "\'";
- this->IssueMessage(MessageType::AUTHOR_WARNING, msg.str());
- }
- }
-}
-
void cmMakefile::RemoveDefinition(const std::string& name)
{
- if (this->VariableInitialized(name)) {
- this->LogUnused("unsetting", name);
- }
this->StateSnapshot.RemoveDefinition(name);
#ifndef CMAKE_BOOTSTRAP
cmVariableWatch* vv = this->GetVariableWatch();
@@ -2555,8 +2523,7 @@ void cmMakefile::ExpandVariablesCMP0019()
bool cmMakefile::IsOn(const std::string& name) const
{
- const char* value = this->GetDefinition(name);
- return cmIsOn(value);
+ return cmIsOn(this->GetDef(name));
}
bool cmMakefile::IsSet(const std::string& name) const
@@ -3287,25 +3254,28 @@ void cmMakefile::RemoveVariablesInString(std::string& source,
}
}
-std::string cmMakefile::GetConfigurations(std::vector<std::string>& configs,
- bool singleConfig) const
+std::string cmMakefile::GetDefaultConfiguration() const
{
if (this->GetGlobalGenerator()->IsMultiConfig()) {
- this->GetDefExpandList("CMAKE_CONFIGURATION_TYPES", configs);
- return "";
- }
- const std::string& buildType = this->GetSafeDefinition("CMAKE_BUILD_TYPE");
- if (singleConfig && !buildType.empty()) {
- configs.push_back(buildType);
+ return std::string{};
}
- return buildType;
+ return this->GetSafeDefinition("CMAKE_BUILD_TYPE");
}
-std::vector<std::string> cmMakefile::GetGeneratorConfigs() const
+std::vector<std::string> cmMakefile::GetGeneratorConfigs(
+ GeneratorConfigQuery mode) const
{
std::vector<std::string> configs;
- GetConfigurations(configs);
- if (configs.empty()) {
+ if (this->GetGlobalGenerator()->IsMultiConfig() ||
+ mode == cmMakefile::OnlyMultiConfig) {
+ this->GetDefExpandList("CMAKE_CONFIGURATION_TYPES", configs);
+ } else {
+ const std::string& buildType = this->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ if (!buildType.empty()) {
+ configs.emplace_back(buildType);
+ }
+ }
+ if (mode == cmMakefile::IncludeEmptyConfig && configs.empty()) {
configs.emplace_back();
}
return configs;
@@ -3725,7 +3695,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,
if (cmakeArgs) {
// FIXME: Workaround to ignore unused CLI variables in try-compile.
//
- // Ideally we should use SetArgs to honor options like --warn-unused-vars.
+ // Ideally we should use SetArgs for options like --no-warn-unused-cli.
// However, there is a subtle problem when certain arguments are passed to
// a macro wrapping around try_compile or try_run that does not escape
// semicolons in its parameters but just passes ${ARGV} or ${ARGN}. In
@@ -3744,7 +3714,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,
// the value VAR=a is sufficient for the try_compile or try_run to get the
// correct result. Calling SetArgs here would break such projects that
// previously built. Instead we work around the issue by never reporting
- // unused arguments and ignoring options such as --warn-unused-vars.
+ // unused arguments and ignoring options such as --no-warn-unused-cli.
cm.SetWarnUnusedCli(false);
// cm.SetArgs(*cmakeArgs, true);
@@ -3998,6 +3968,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output,
int cmMakefile::ConfigureFile(const std::string& infile,
const std::string& outfile, bool copyonly,
bool atOnly, bool escapeQuotes,
+ bool use_source_permissions,
cmNewLineStyle newLine)
{
int res = 1;
@@ -4021,7 +3992,13 @@ int cmMakefile::ConfigureFile(const std::string& infile,
this->AddCMakeOutputFile(soutfile);
mode_t perm = 0;
- cmSystemTools::GetPermissions(sinfile, perm);
+ if (!use_source_permissions) {
+ perm = perm | mode_owner_read | mode_owner_write | mode_group_read |
+ mode_world_read;
+ } else {
+ cmSystemTools::GetPermissions(sinfile, perm);
+ }
+
std::string::size_type pos = soutfile.rfind('/');
if (pos != std::string::npos) {
std::string path = soutfile.substr(0, pos);
@@ -4030,6 +4007,13 @@ int cmMakefile::ConfigureFile(const std::string& infile,
if (copyonly) {
if (!cmSystemTools::CopyFileIfDifferent(sinfile, soutfile)) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ cmSystemTools::GetLastSystemError());
+ return 0;
+ }
+ if (!cmSystemTools::SetPermissions(soutfile, perm)) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ cmSystemTools::GetLastSystemError());
return 0;
}
} else {
@@ -4080,9 +4064,15 @@ int cmMakefile::ConfigureFile(const std::string& infile,
fin.close();
fout.close();
if (!cmSystemTools::CopyFileIfDifferent(tempOutputFile, soutfile)) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ cmSystemTools::GetLastSystemError());
res = 0;
} else {
- cmSystemTools::SetPermissions(soutfile, perm);
+ if (!cmSystemTools::SetPermissions(soutfile, perm)) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ cmSystemTools::GetLastSystemError());
+ res = 0;
+ }
}
cmSystemTools::RemoveFile(tempOutputFile);
}
@@ -4127,8 +4117,7 @@ cmProp cmMakefile::GetProperty(const std::string& prop, bool chain) const
bool cmMakefile::GetPropertyAsBool(const std::string& prop) const
{
- cmProp p = this->GetProperty(prop);
- return p && cmIsOn(*p);
+ return cmIsOn(this->GetProperty(prop));
}
std::vector<std::string> cmMakefile::GetPropertyKeys() const
@@ -4240,8 +4229,6 @@ void cmMakefile::PopScope()
this->PopLoopBlockBarrier();
- this->CheckForUnusedVariables();
-
this->PopSnapshot();
}
@@ -4557,7 +4544,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
// Deprecate old policies, especially those that require a lot
// of code to maintain the old behavior.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0071 &&
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0072 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
@@ -4599,7 +4586,7 @@ void cmMakefile::PopSnapshot(bool reportError)
// cmStateSnapshot manages nested policy scopes within it.
// Since the scope corresponding to the snapshot is closing,
// reject any still-open nested policy scopes with an error.
- while (!this->StateSnapshot.CanPopPolicyScope()) {
+ while (this->StateSnapshot.CanPopPolicyScope()) {
if (reportError) {
this->IssueMessage(MessageType::FATAL_ERROR,
"cmake_policy PUSH without matching POP");
@@ -4615,7 +4602,8 @@ void cmMakefile::PopSnapshot(bool reportError)
bool cmMakefile::SetPolicyVersion(std::string const& version_min,
std::string const& version_max)
{
- return cmPolicies::ApplyPolicyVersion(this, version_min, version_max);
+ return cmPolicies::ApplyPolicyVersion(this, version_min, version_max,
+ cmPolicies::WarnCompat::On);
}
bool cmMakefile::HasCMP0054AlreadyBeenReported(
@@ -4651,674 +4639,6 @@ bool cmMakefile::IgnoreErrorsCMP0061() const
return ignoreErrors;
}
-#define FEATURE_STRING(F) , #F
-static const char* const C_FEATURES[] = { nullptr FOR_EACH_C_FEATURE(
- FEATURE_STRING) };
-
-static const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE(
- FEATURE_STRING) };
-
-static const char* const CUDA_FEATURES[] = { nullptr FOR_EACH_CUDA_FEATURE(
- FEATURE_STRING) };
-#undef FEATURE_STRING
-
-static const char* const C_STANDARDS[] = { "90", "99", "11" };
-static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17", "20" };
-static const char* const CUDA_STANDARDS[] = { "03", "11", "14", "17", "20" };
-
-bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
- const std::string& feature,
- std::string* error) const
-{
- if (cmGeneratorExpression::Find(feature) != std::string::npos) {
- target->AppendProperty("COMPILE_FEATURES", feature);
- return true;
- }
-
- std::string lang;
- if (!this->CompileFeatureKnown(target, feature, lang, error)) {
- return false;
- }
-
- const char* features = this->CompileFeaturesAvailable(lang, error);
- if (!features) {
- return false;
- }
-
- std::vector<std::string> availableFeatures = cmExpandedList(features);
- if (!cm::contains(availableFeatures, feature)) {
- std::ostringstream e;
- e << "The compiler feature \"" << feature << "\" is not known to " << lang
- << " compiler\n\""
- << this->GetDefinition("CMAKE_" + lang + "_COMPILER_ID")
- << "\"\nversion "
- << this->GetDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << ".";
- if (error) {
- *error = e.str();
- } else {
- this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
- this->Backtrace);
- }
- return false;
- }
-
- target->AppendProperty("COMPILE_FEATURES", feature);
-
- if (lang == "C" || lang == "OBJC") {
- return this->AddRequiredTargetCFeature(target, feature, lang, error);
- }
- if (lang == "CUDA") {
- return this->AddRequiredTargetCudaFeature(target, feature, lang, error);
- }
- return this->AddRequiredTargetCxxFeature(target, feature, lang, error);
-}
-
-bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
- const std::string& feature,
- std::string& lang,
- std::string* error) const
-{
- assert(cmGeneratorExpression::Find(feature) == std::string::npos);
-
- bool isCFeature =
- std::find_if(cm::cbegin(C_FEATURES) + 1, cm::cend(C_FEATURES),
- cmStrCmp(feature)) != cm::cend(C_FEATURES);
- if (isCFeature) {
- lang = "C";
- return true;
- }
- bool isCxxFeature =
- std::find_if(cm::cbegin(CXX_FEATURES) + 1, cm::cend(CXX_FEATURES),
- cmStrCmp(feature)) != cm::cend(CXX_FEATURES);
- if (isCxxFeature) {
- lang = "CXX";
- return true;
- }
- bool isCudaFeature =
- std::find_if(cm::cbegin(CUDA_FEATURES) + 1, cm::cend(CUDA_FEATURES),
- cmStrCmp(feature)) != cm::cend(CUDA_FEATURES);
- if (isCudaFeature) {
- lang = "CUDA";
- return true;
- }
- std::ostringstream e;
- if (error) {
- e << "specified";
- } else {
- e << "Specified";
- }
- e << " unknown feature \"" << feature
- << "\" for "
- "target \""
- << target->GetName() << "\".";
- if (error) {
- *error = e.str();
- } else {
- this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
- this->Backtrace);
- }
- return false;
-}
-
-const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang,
- std::string* error) const
-{
- if (!this->GlobalGenerator->GetLanguageEnabled(lang)) {
- std::ostringstream e;
- if (error) {
- e << "cannot";
- } else {
- e << "Cannot";
- }
- e << " use features from non-enabled language " << lang;
- if (error) {
- *error = e.str();
- } else {
- this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
- this->Backtrace);
- }
- return nullptr;
- }
-
- const char* featuresKnown =
- this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES");
-
- if (!featuresKnown || !*featuresKnown) {
- std::ostringstream e;
- if (error) {
- e << "no";
- } else {
- e << "No";
- }
- e << " known features for " << lang << " compiler\n\""
- << this->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID")
- << "\"\nversion "
- << this->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << ".";
- if (error) {
- *error = e.str();
- } else {
- this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
- this->Backtrace);
- }
- return nullptr;
- }
- return featuresKnown;
-}
-
-bool cmMakefile::HaveStandardAvailable(cmTarget const* target,
- std::string const& lang,
- const std::string& feature) const
-{
- if (lang == "C" || lang == "OBJC") {
- return this->HaveCStandardAvailable(target, feature, lang);
- }
- if (lang == "CUDA") {
- return this->HaveCudaStandardAvailable(target, feature, lang);
- }
- return this->HaveCxxStandardAvailable(target, feature, lang);
-}
-
-bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const
-{
- cmProp defaultCStandard =
- this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
- if (!defaultCStandard) {
- this->IssueMessage(
- MessageType::INTERNAL_ERROR,
- cmStrCat("CMAKE_", lang,
- "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
- "not fully configured for this compiler."));
- // Return true so the caller does not try to lookup the default standard.
- return true;
- }
- if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
- cmStrCmp(*defaultCStandard)) == cm::cend(C_STANDARDS)) {
- const std::string e = cmStrCat("The CMAKE_", lang,
- "_STANDARD_DEFAULT variable contains an "
- "invalid value: \"",
- *defaultCStandard, "\".");
- this->IssueMessage(MessageType::INTERNAL_ERROR, e);
- return false;
- }
-
- bool needC90 = false;
- bool needC99 = false;
- bool needC11 = false;
-
- this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
-
- cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD"));
- if (!existingCStandard) {
- existingCStandard = defaultCStandard;
- }
-
- if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
- cmStrCmp(*existingCStandard)) == cm::cend(C_STANDARDS)) {
- const std::string e = cmStrCat(
- "The ", lang, "_STANDARD property on target \"", target->GetName(),
- "\" contained an invalid value: \"", *existingCStandard, "\".");
- this->IssueMessage(MessageType::FATAL_ERROR, e);
- return false;
- }
-
- const char* const* existingCIt = existingCStandard
- ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
- cmStrCmp(*existingCStandard))
- : cm::cend(C_STANDARDS);
-
- if (needC11 && existingCStandard &&
- existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
- cm::cend(C_STANDARDS), cmStrCmp("11"))) {
- return false;
- }
- if (needC99 && existingCStandard &&
- existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
- cm::cend(C_STANDARDS), cmStrCmp("99"))) {
- return false;
- }
- if (needC90 && existingCStandard &&
- existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
- cm::cend(C_STANDARDS), cmStrCmp("90"))) {
- return false;
- }
- return true;
-}
-
-bool cmMakefile::IsLaterStandard(std::string const& lang,
- std::string const& lhs,
- std::string const& rhs)
-{
- if (lang == "C" || lang == "OBJC") {
- const char* const* rhsIt = std::find_if(
- cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(rhs));
-
- return std::find_if(rhsIt, cm::cend(C_STANDARDS), cmStrCmp(lhs)) !=
- cm::cend(C_STANDARDS);
- }
- if (lang == "CUDA") {
- const char* const* rhsIt = std::find_if(
- cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), cmStrCmp(rhs));
-
- return std::find_if(rhsIt, cm::cend(CUDA_STANDARDS), cmStrCmp(lhs)) !=
- cm::cend(CUDA_STANDARDS);
- }
-
- const char* const* rhsIt = std::find_if(
- cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(rhs));
-
- return std::find_if(rhsIt, cm::cend(CXX_STANDARDS), cmStrCmp(lhs)) !=
- cm::cend(CXX_STANDARDS);
-}
-
-bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const
-{
- cmProp defaultCxxStandard =
- this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
- if (!defaultCxxStandard) {
- this->IssueMessage(
- MessageType::INTERNAL_ERROR,
- cmStrCat("CMAKE_", lang,
- "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
- "not fully configured for this compiler."));
- // Return true so the caller does not try to lookup the default standard.
- return true;
- }
- if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
- cmStrCmp(*defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) {
- const std::string e =
- cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ",
- "invalid value: \"", *defaultCxxStandard, "\".");
- this->IssueMessage(MessageType::INTERNAL_ERROR, e);
- return false;
- }
-
- bool needCxx98 = false;
- bool needCxx11 = false;
- bool needCxx14 = false;
- bool needCxx17 = false;
- bool needCxx20 = false;
- this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
- needCxx17, needCxx20);
-
- cmProp existingCxxStandard =
- target->GetProperty(cmStrCat(lang, "_STANDARD"));
- if (!existingCxxStandard) {
- existingCxxStandard = defaultCxxStandard;
- }
-
- const char* const* existingCxxLevel =
- std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
- cmStrCmp(*existingCxxStandard));
- if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
- const std::string e = cmStrCat(
- "The ", lang, "_STANDARD property on target \"", target->GetName(),
- "\" contained an invalid value: \"", *existingCxxStandard, "\".");
- this->IssueMessage(MessageType::FATAL_ERROR, e);
- return false;
- }
-
- /* clang-format off */
- const char* const* needCxxLevel =
- needCxx20 ? &CXX_STANDARDS[4]
- : needCxx17 ? &CXX_STANDARDS[3]
- : needCxx14 ? &CXX_STANDARDS[2]
- : needCxx11 ? &CXX_STANDARDS[1]
- : needCxx98 ? &CXX_STANDARDS[0]
- : nullptr;
- /* clang-format on */
-
- return !needCxxLevel || needCxxLevel <= existingCxxLevel;
-}
-
-void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
- std::string const& lang,
- bool& needCxx98, bool& needCxx11,
- bool& needCxx14, bool& needCxx17,
- bool& needCxx20) const
-{
- if (const char* propCxx98 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "98_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propCxx98);
- needCxx98 = cm::contains(props, feature);
- }
- if (const char* propCxx11 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propCxx11);
- needCxx11 = cm::contains(props, feature);
- }
- if (const char* propCxx14 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propCxx14);
- needCxx14 = cm::contains(props, feature);
- }
- if (const char* propCxx17 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propCxx17);
- needCxx17 = cm::contains(props, feature);
- }
- if (const char* propCxx20 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propCxx20);
- needCxx20 = cm::contains(props, feature);
- }
-}
-
-bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
- const std::string& feature,
- std::string const& lang,
- std::string* error) const
-{
- bool needCxx98 = false;
- bool needCxx11 = false;
- bool needCxx14 = false;
- bool needCxx17 = false;
- bool needCxx20 = false;
-
- this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
- needCxx17, needCxx20);
-
- cmProp existingCxxStandard =
- target->GetProperty(cmStrCat(lang, "_STANDARD"));
- if (existingCxxStandard == nullptr) {
- cmProp defaultCxxStandard =
- this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
- if (defaultCxxStandard && !defaultCxxStandard->empty()) {
- existingCxxStandard = defaultCxxStandard;
- }
- }
- const char* const* existingCxxLevel = nullptr;
- if (existingCxxStandard) {
- existingCxxLevel =
- std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
- cmStrCmp(*existingCxxStandard));
- if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
- const std::string e = cmStrCat(
- "The ", lang, "_STANDARD property on target \"", target->GetName(),
- "\" contained an invalid value: \"", *existingCxxStandard, "\".");
- if (error) {
- *error = e;
- } else {
- this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
- this->Backtrace);
- }
- return false;
- }
- }
-
- /* clang-format off */
- const char* const* needCxxLevel =
- needCxx20 ? &CXX_STANDARDS[4]
- : needCxx17 ? &CXX_STANDARDS[3]
- : needCxx14 ? &CXX_STANDARDS[2]
- : needCxx11 ? &CXX_STANDARDS[1]
- : needCxx98 ? &CXX_STANDARDS[0]
- : nullptr;
- /* clang-format on */
-
- if (needCxxLevel) {
- // Ensure the C++ language level is high enough to support
- // the needed C++ features.
- if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
- target->SetProperty(cmStrCat(lang, "_STANDARD"), *needCxxLevel);
- }
- }
-
- return true;
-}
-
-bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const
-{
- cmProp defaultCudaStandard =
- this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
- if (!defaultCudaStandard) {
- this->IssueMessage(
- MessageType::INTERNAL_ERROR,
- cmStrCat("CMAKE_", lang,
- "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
- "not fully configured for this compiler."));
- // Return true so the caller does not try to lookup the default standard.
- return true;
- }
- if (std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS),
- cmStrCmp(*defaultCudaStandard)) ==
- cm::cend(CUDA_STANDARDS)) {
- const std::string e =
- cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ",
- "invalid value: \"", *defaultCudaStandard, "\".");
- this->IssueMessage(MessageType::INTERNAL_ERROR, e);
- return false;
- }
-
- bool needCuda03 = false;
- bool needCuda11 = false;
- bool needCuda14 = false;
- bool needCuda17 = false;
- bool needCuda20 = false;
- this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11,
- needCuda14, needCuda17, needCuda20);
-
- cmProp existingCudaStandard =
- target->GetProperty(cmStrCat(lang, "_STANDARD"));
- if (!existingCudaStandard) {
- existingCudaStandard = defaultCudaStandard;
- }
-
- const char* const* existingCudaLevel =
- std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS),
- cmStrCmp(*existingCudaStandard));
- if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) {
- const std::string e = cmStrCat(
- "The ", lang, "_STANDARD property on target \"", target->GetName(),
- "\" contained an invalid value: \"", *existingCudaStandard, "\".");
- this->IssueMessage(MessageType::FATAL_ERROR, e);
- return false;
- }
-
- /* clang-format off */
- const char* const* needCudaLevel =
- needCuda20 ? &CUDA_STANDARDS[4]
- : needCuda17 ? &CUDA_STANDARDS[3]
- : needCuda14 ? &CUDA_STANDARDS[2]
- : needCuda11 ? &CUDA_STANDARDS[1]
- : needCuda03 ? &CUDA_STANDARDS[0]
- : nullptr;
- /* clang-format on */
-
- return !needCudaLevel || needCudaLevel <= existingCudaLevel;
-}
-
-void cmMakefile::CheckNeededCudaLanguage(const std::string& feature,
- std::string const& lang,
- bool& needCuda03, bool& needCuda11,
- bool& needCuda14, bool& needCuda17,
- bool& needCuda20) const
-{
- if (const char* propCuda03 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "03_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propCuda03);
- needCuda03 = cm::contains(props, feature);
- }
- if (const char* propCuda11 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propCuda11);
- needCuda11 = cm::contains(props, feature);
- }
- if (const char* propCuda14 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propCuda14);
- needCuda14 = cm::contains(props, feature);
- }
- if (const char* propCuda17 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propCuda17);
- needCuda17 = cm::contains(props, feature);
- }
- if (const char* propCuda20 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propCuda20);
- needCuda20 = cm::contains(props, feature);
- }
-}
-
-bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target,
- const std::string& feature,
- std::string const& lang,
- std::string* error) const
-{
- bool needCuda03 = false;
- bool needCuda11 = false;
- bool needCuda14 = false;
- bool needCuda17 = false;
- bool needCuda20 = false;
-
- this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11,
- needCuda14, needCuda17, needCuda20);
-
- cmProp existingCudaStandard =
- target->GetProperty(cmStrCat(lang, "_STANDARD"));
- if (existingCudaStandard == nullptr) {
- cmProp defaultCudaStandard =
- this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
- if (defaultCudaStandard && !defaultCudaStandard->empty()) {
- existingCudaStandard = defaultCudaStandard;
- }
- }
- const char* const* existingCudaLevel = nullptr;
- if (existingCudaStandard) {
- existingCudaLevel =
- std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS),
- cmStrCmp(*existingCudaStandard));
- if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) {
- const std::string e = cmStrCat(
- "The ", lang, "_STANDARD property on target \"", target->GetName(),
- "\" contained an invalid value: \"", *existingCudaStandard, "\".");
- if (error) {
- *error = e;
- } else {
- this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
- this->Backtrace);
- }
- return false;
- }
- }
-
- /* clang-format off */
- const char* const* needCudaLevel =
- needCuda20 ? &CUDA_STANDARDS[4]
- : needCuda17 ? &CUDA_STANDARDS[3]
- : needCuda14 ? &CUDA_STANDARDS[2]
- : needCuda11 ? &CUDA_STANDARDS[1]
- : needCuda03 ? &CUDA_STANDARDS[0]
- : nullptr;
- /* clang-format on */
-
- if (needCudaLevel) {
- // Ensure the CUDA language level is high enough to support
- // the needed CUDA features.
- if (!existingCudaLevel || existingCudaLevel < needCudaLevel) {
- target->SetProperty("CUDA_STANDARD", *needCudaLevel);
- }
- }
-
- return true;
-}
-
-void cmMakefile::CheckNeededCLanguage(const std::string& feature,
- std::string const& lang, bool& needC90,
- bool& needC99, bool& needC11) const
-{
- if (const char* propC90 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "90_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propC90);
- needC90 = cm::contains(props, feature);
- }
- if (const char* propC99 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "99_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propC99);
- needC99 = cm::contains(props, feature);
- }
- if (const char* propC11 =
- this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) {
- std::vector<std::string> props = cmExpandedList(propC11);
- needC11 = cm::contains(props, feature);
- }
-}
-
-bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
- const std::string& feature,
- std::string const& lang,
- std::string* error) const
-{
- bool needC90 = false;
- bool needC99 = false;
- bool needC11 = false;
-
- this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
-
- cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD"));
- if (existingCStandard == nullptr) {
- cmProp defaultCStandard =
- this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
- if (defaultCStandard && !defaultCStandard->empty()) {
- existingCStandard = defaultCStandard;
- }
- }
- if (existingCStandard) {
- if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
- cmStrCmp(*existingCStandard)) == cm::cend(C_STANDARDS)) {
- const std::string e = cmStrCat(
- "The ", lang, "_STANDARD property on target \"", target->GetName(),
- "\" contained an invalid value: \"", *existingCStandard, "\".");
- if (error) {
- *error = e;
- } else {
- this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
- this->Backtrace);
- }
- return false;
- }
- }
- const char* const* existingCIt = existingCStandard
- ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
- cmStrCmp(*existingCStandard))
- : cm::cend(C_STANDARDS);
-
- bool setC90 = needC90 && !existingCStandard;
- bool setC99 = needC99 && !existingCStandard;
- bool setC11 = needC11 && !existingCStandard;
-
- if (needC11 && existingCStandard &&
- existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
- cm::cend(C_STANDARDS), cmStrCmp("11"))) {
- setC11 = true;
- } else if (needC99 && existingCStandard &&
- existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
- cm::cend(C_STANDARDS),
- cmStrCmp("99"))) {
- setC99 = true;
- } else if (needC90 && existingCStandard &&
- existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
- cm::cend(C_STANDARDS),
- cmStrCmp("90"))) {
- setC90 = true;
- }
-
- if (setC11) {
- target->SetProperty(cmStrCat(lang, "_STANDARD"), "11");
- } else if (setC99) {
- target->SetProperty(cmStrCat(lang, "_STANDARD"), "99");
- } else if (setC90) {
- target->SetProperty(cmStrCat(lang, "_STANDARD"), "90");
- }
- return true;
-}
-
cmMakefile::FunctionPushPop::FunctionPushPop(cmMakefile* mf,
const std::string& fileName,
cmPolicies::PolicyMap const& pm)
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 45d7109..80d80d3 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -342,12 +342,19 @@ public:
*/
void SetProjectName(std::string const& name);
- /** Get the configurations to be generated. */
- std::string GetConfigurations(std::vector<std::string>& configs,
- bool single = true) const;
+ /* Get the default configuration */
+ std::string GetDefaultConfiguration() const;
+
+ enum GeneratorConfigQuery
+ {
+ IncludeEmptyConfig, // Include "" aka noconfig
+ ExcludeEmptyConfig, // Exclude "" aka noconfig
+ OnlyMultiConfig,
+ };
/** Get the configurations for dependency checking. */
- std::vector<std::string> GetGeneratorConfigs() const;
+ std::vector<std::string> GetGeneratorConfigs(
+ GeneratorConfigQuery mode) const;
/**
* Set the name of the library.
@@ -686,6 +693,7 @@ public:
*/
int ConfigureFile(const std::string& infile, const std::string& outfile,
bool copyonly, bool atOnly, bool escapeQuotes,
+ bool use_source_permissions,
cmNewLineStyle = cmNewLineStyle());
/**
@@ -925,21 +933,6 @@ public:
bool PolicyOptionalWarningEnabled(std::string const& var);
- bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature,
- std::string* error = nullptr) const;
-
- bool CompileFeatureKnown(cmTarget const* target, const std::string& feature,
- std::string& lang, std::string* error) const;
-
- const char* CompileFeaturesAvailable(const std::string& lang,
- std::string* error) const;
-
- bool HaveStandardAvailable(cmTarget const* target, std::string const& lang,
- const std::string& feature) const;
-
- bool IsLaterStandard(std::string const& lang, std::string const& lhs,
- std::string const& rhs);
-
void PushLoopBlock();
void PopLoopBlock();
bool IsLoopBlock() const;
@@ -985,9 +978,6 @@ protected:
// add link libraries and directories to the target
void AddGlobalLinkInformation(cmTarget& target);
- // Check for a an unused variable
- void LogUnused(const char* reason, const std::string& name) const;
-
mutable std::set<cmListFileContext> CMP0054ReportedIds;
// libraries, classes, and executables
@@ -1162,44 +1152,6 @@ private:
*/
bool MightHaveCustomCommand(const std::string& name) const;
- bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature,
- std::string const& lang,
- std::string* error = nullptr) const;
- bool AddRequiredTargetCxxFeature(cmTarget* target,
- const std::string& feature,
- std::string const& lang,
- std::string* error = nullptr) const;
- bool AddRequiredTargetCudaFeature(cmTarget* target,
- const std::string& feature,
- std::string const& lang,
- std::string* error = nullptr) const;
-
- void CheckNeededCLanguage(const std::string& feature,
- std::string const& lang, bool& needC90,
- bool& needC99, bool& needC11) const;
- void CheckNeededCxxLanguage(const std::string& feature,
- std::string const& lang, bool& needCxx98,
- bool& needCxx11, bool& needCxx14,
- bool& needCxx17, bool& needCxx20) const;
- void CheckNeededCudaLanguage(const std::string& feature,
- std::string const& lang, bool& needCuda03,
- bool& needCuda11, bool& needCuda14,
- bool& needCuda17, bool& needCuda20) const;
-
- bool HaveCStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const;
- bool HaveCxxStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const;
- bool HaveCudaStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const;
-
- void CheckForUnusedVariables() const;
-
- // Unused variable flags
- bool WarnUnused;
bool CheckSystemVars;
bool CheckCMP0000;
std::set<std::string> WarnedCMP0074;
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 446f225..bc288ac 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -218,7 +218,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
const char* val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_LINK");
- if (val && *val) {
+ if (cmNonempty(val)) {
launcher = cmStrCat(val, ' ');
}
@@ -583,7 +583,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
const char* val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_LINK");
- if (val && *val) {
+ if (cmNonempty(val)) {
launcher = cmStrCat(val, ' ');
}
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 5809b4a..1c25fc4 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -356,7 +356,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
std::string launcher;
const char* val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_LINK");
- if (val && *val) {
+ if (cmNonempty(val)) {
launcher = cmStrCat(val, ' ');
}
@@ -809,7 +809,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
std::string launcher;
const char* val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_LINK");
- if (val && *val) {
+ if (cmNonempty(val)) {
launcher = cmStrCat(val, ' ');
}
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 8396fa3..fae1d76 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -71,6 +71,7 @@ std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New(
case cmStateEnums::OBJECT_LIBRARY:
result = cm::make_unique<cmMakefileLibraryTargetGenerator>(tgt);
break;
+ case cmStateEnums::INTERFACE_LIBRARY:
case cmStateEnums::UTILITY:
result = cm::make_unique<cmMakefileUtilityTargetGenerator>(tgt);
break;
@@ -197,8 +198,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
}
// add custom commands to the clean rules?
- cmProp clean_no_custom = this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
- bool clean = clean_no_custom ? cmIsOff(*clean_no_custom) : true;
+ bool clean = cmIsOff(this->Makefile->GetProperty("CLEAN_NO_CUSTOM"));
// First generate the object rule files. Save a list of all object
// files for this target.
@@ -532,6 +532,13 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// Build the set of compiler flags.
std::string flags;
+ // explicitly add the explicit language flag before any other flag
+ // this way backwards compatibility with user flags is maintained
+ if (source.GetProperty("LANGUAGE")) {
+ this->LocalGenerator->AppendFeatureOptions(flags, lang,
+ "EXPLICIT_LANGUAGE");
+ }
+
// Add language-specific flags.
std::string langFlags = cmStrCat("$(", lang, "_FLAGS", filterArch, ")");
this->LocalGenerator->AppendFlags(flags, langFlags);
@@ -800,7 +807,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
lang == "OBJC" || lang == "OBJCXX")) {
std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
- if (clauncher && !clauncher->empty()) {
+ if (cmNonempty(clauncher)) {
compilerLauncher = *clauncher;
}
}
@@ -815,8 +822,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
cmProp cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
std::string const cppcheck_prop = lang + "_CPPCHECK";
cmProp cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
- if ((iwyu && !iwyu->empty()) || (tidy && !tidy->empty()) ||
- (cpplint && !cpplint->empty()) || (cppcheck && !cppcheck->empty())) {
+ if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) ||
+ cmNonempty(cppcheck)) {
std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile";
if (!compilerLauncher.empty()) {
// In __run_co_compile case the launcher command is supplied
@@ -825,30 +832,30 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
compilerLauncher.clear();
}
- if (iwyu && !iwyu->empty()) {
+ if (cmNonempty(iwyu)) {
run_iwyu += " --iwyu=";
run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu);
}
- if (tidy && !tidy->empty()) {
+ if (cmNonempty(tidy)) {
run_iwyu += " --tidy=";
const char* driverMode = this->Makefile->GetDefinition(
"CMAKE_" + lang + "_CLANG_TIDY_DRIVER_MODE");
- if (!(driverMode && *driverMode)) {
+ if (!cmNonempty(driverMode)) {
driverMode = lang == "C" ? "gcc" : "g++";
}
run_iwyu += this->LocalGenerator->EscapeForShell(
cmStrCat(*tidy, ";--extra-arg-before=--driver-mode=", driverMode));
}
- if (cpplint && !cpplint->empty()) {
+ if (cmNonempty(cpplint)) {
run_iwyu += " --cpplint=";
run_iwyu += this->LocalGenerator->EscapeForShell(*cpplint);
}
- if (cppcheck && !cppcheck->empty()) {
+ if (cmNonempty(cppcheck)) {
run_iwyu += " --cppcheck=";
run_iwyu += this->LocalGenerator->EscapeForShell(*cppcheck);
}
- if ((tidy && !tidy->empty()) || (cpplint && !cpplint->empty()) ||
- (cppcheck && !cppcheck->empty())) {
+ if (cmNonempty(tidy) || (cmNonempty(cpplint)) ||
+ (cmNonempty(cppcheck))) {
run_iwyu += " --source=";
run_iwyu += sourceFile;
}
@@ -875,7 +882,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
{
const char* val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_COMPILE");
- if (val && *val) {
+ if (cmNonempty(val)) {
launcher = cmStrCat(val, ' ');
}
}
@@ -1851,7 +1858,7 @@ void cmMakefileTargetGenerator::GenDefFile(
this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
cmOutputConverter::SHELL);
const char* nm_executable = this->Makefile->GetDefinition("CMAKE_NM");
- if (nm_executable && *nm_executable) {
+ if (cmNonempty(nm_executable)) {
cmd += " --nm=";
cmd += this->LocalCommonGenerator->ConvertToOutputFormat(
nm_executable, cmOutputConverter::SHELL);
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 32ab9f8..bde5ee7 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -239,7 +239,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(
std::string launcher;
const char* val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
- if (val && *val) {
+ if (cmNonempty(val)) {
launcher = cmStrCat(val, ' ');
}
@@ -376,7 +376,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
std::string launcher;
const char* val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
- if (val && *val) {
+ if (cmNonempty(val)) {
launcher = cmStrCat(val, ' ');
}
@@ -739,7 +739,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement(
// Gather order-only dependencies.
this->GetLocalGenerator()->AppendTargetDepends(
- this->GetGeneratorTarget(), build.OrderOnlyDeps, config, config);
+ this->GetGeneratorTarget(), build.OrderOnlyDeps, config, config,
+ DependOnTargetArtifact);
// Write the build statement for this target.
bool usedResponseFile = false;
@@ -1091,7 +1092,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
obj_list_file, cmOutputConverter::SHELL);
const char* nm_executable = GetMakefile()->GetDefinition("CMAKE_NM");
- if (nm_executable && *nm_executable) {
+ if (cmNonempty(nm_executable)) {
cmd += " --nm=";
cmd += this->LocalCommonGenerator->ConvertToOutputFormat(
nm_executable, cmOutputConverter::SHELL);
@@ -1160,8 +1161,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
globalGen->IsMultiConfig() ? cmStrCat('.', config) : "", ".rsp"));
// Gather order-only dependencies.
- this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps,
- config, fileConfig);
+ this->GetLocalGenerator()->AppendTargetDepends(
+ gt, linkBuild.OrderOnlyDeps, config, fileConfig, DependOnTargetArtifact);
// Add order-only dependencies on versioning symlinks of shared libs we link.
if (!this->GeneratorTarget->IsDLLPlatform()) {
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index d406c99..57f526e 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -51,6 +51,7 @@ std::unique_ptr<cmNinjaTargetGenerator> cmNinjaTargetGenerator::New(
return cm::make_unique<cmNinjaNormalTargetGenerator>(target);
case cmStateEnums::UTILITY:
+ case cmStateEnums::INTERFACE_LIBRARY:
case cmStateEnums::GLOBAL_TARGET:
return cm::make_unique<cmNinjaUtilityTargetGenerator>(target);
@@ -65,7 +66,8 @@ cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target)
, LocalGenerator(
static_cast<cmLocalNinjaGenerator*>(target->GetLocalGenerator()))
{
- for (auto const& fileConfig : target->Makefile->GetGeneratorConfigs()) {
+ for (auto const& fileConfig :
+ target->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig)) {
this->Configs[fileConfig].MacOSXContentGenerator =
cm::make_unique<MacOSXContentGeneratorType>(this, fileConfig);
}
@@ -188,7 +190,16 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
}
}
- std::string flags = this->GetFlags(language, config, filterArch);
+ std::string flags;
+ // explicitly add the explicit language flag before any other flag
+ // this way backwards compatibility with user flags is maintained
+ if (source->GetProperty("LANGUAGE")) {
+ this->LocalGenerator->AppendFeatureOptions(flags, language,
+ "EXPLICIT_LANGUAGE");
+ flags += " ";
+ }
+
+ flags += this->GetFlags(language, config, filterArch);
// Add Fortran format flags.
if (language == "Fortran") {
@@ -652,7 +663,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
std::string launcher;
const char* val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_COMPILE");
- if (val && *val) {
+ if (cmNonempty(val)) {
launcher = cmStrCat(val, ' ');
}
@@ -803,7 +814,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
lang == "OBJC" || lang == "OBJCXX")) {
std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER");
cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
- if (clauncher && !clauncher->empty()) {
+ if (cmNonempty(clauncher)) {
compilerLauncher = *clauncher;
}
}
@@ -818,8 +829,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
cmProp cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
std::string const cppcheck_prop = cmStrCat(lang, "_CPPCHECK");
cmProp cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
- if ((iwyu && !iwyu->empty()) || (tidy && !tidy->empty()) ||
- (cpplint && !cpplint->empty()) || (cppcheck && !cppcheck->empty())) {
+ if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) ||
+ cmNonempty(cppcheck)) {
std::string run_iwyu = cmStrCat(cmakeCmd, " -E __run_co_compile");
if (!compilerLauncher.empty()) {
// In __run_co_compile case the launcher command is supplied
@@ -829,31 +840,30 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
this->LocalGenerator->EscapeForShell(compilerLauncher));
compilerLauncher.clear();
}
- if (iwyu && !iwyu->empty()) {
+ if (cmNonempty(iwyu)) {
run_iwyu += cmStrCat(" --iwyu=",
this->GetLocalGenerator()->EscapeForShell(*iwyu));
}
- if (tidy && !tidy->empty()) {
+ if (cmNonempty(tidy)) {
run_iwyu += " --tidy=";
const char* driverMode = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_CLANG_TIDY_DRIVER_MODE"));
- if (!(driverMode && *driverMode)) {
+ if (!cmNonempty(driverMode)) {
driverMode = lang == "C" ? "gcc" : "g++";
}
run_iwyu += this->GetLocalGenerator()->EscapeForShell(
cmStrCat(*tidy, ";--extra-arg-before=--driver-mode=", driverMode));
}
- if (cpplint && !cpplint->empty()) {
+ if (cmNonempty(cpplint)) {
run_iwyu += cmStrCat(
" --cpplint=", this->GetLocalGenerator()->EscapeForShell(*cpplint));
}
- if (cppcheck && !cppcheck->empty()) {
+ if (cmNonempty(cppcheck)) {
run_iwyu +=
cmStrCat(" --cppcheck=",
this->GetLocalGenerator()->EscapeForShell(*cppcheck));
}
- if ((tidy && !tidy->empty()) || (cpplint && !cpplint->empty()) ||
- (cppcheck && !cppcheck->empty())) {
+ if (cmNonempty(tidy) || cmNonempty(cpplint) || cmNonempty(cppcheck)) {
run_iwyu += " --source=$in";
}
run_iwyu += " -- ";
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 8d863c3..9508bb9 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -101,7 +101,8 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config)
lg->AppendTargetOutputs(genTarget, gg->GetByproductsForCleanTarget(),
config);
}
- lg->AppendTargetDepends(genTarget, deps, config, config);
+ lg->AppendTargetDepends(genTarget, deps, config, config,
+ DependOnTargetArtifact);
if (commands.empty()) {
phonyBuild.Comment = "Utility command for " + this->GetTargetName();
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index dea3f8a..01e8c04 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -7,9 +7,11 @@
#include <sstream>
#include <vector>
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmState.h"
+#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -157,7 +159,8 @@ static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy,
bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf,
std::string const& version_min,
- std::string const& version_max)
+ std::string const& version_max,
+ WarnCompat warnCompat)
{
// Parse components of the minimum version.
unsigned int minMajor = 2;
@@ -244,13 +247,34 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf,
polPatch = maxPatch;
}
- return cmPolicies::ApplyPolicyVersion(mf, polMajor, polMinor, polPatch);
+ return cmPolicies::ApplyPolicyVersion(mf, polMajor, polMinor, polPatch,
+ warnCompat);
}
bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
unsigned int minorVer,
- unsigned int patchVer)
+ unsigned int patchVer,
+ WarnCompat warnCompat)
{
+ // Warn about policy versions for which support will be removed.
+ if (warnCompat == WarnCompat::On &&
+ (majorVer < 2 || (majorVer == 2 && minorVer < 8) ||
+ (majorVer == 2 && minorVer == 8 && patchVer < 12)) &&
+ // Avoid warning on calls generated by install(EXPORT)
+ // in CMake versions prior to 3.18.
+ !(majorVer == 2 && minorVer == 6 && patchVer == 0 &&
+ mf->GetStateSnapshot().CanPopPolicyScope() &&
+ cmSystemTools::Strucmp(mf->GetBacktrace().Top().Name.c_str(),
+ "cmake_policy") == 0)) {
+ mf->IssueMessage(
+ MessageType::DEPRECATION_WARNING,
+ "Compatibility with CMake < 2.8.12 will be removed from "
+ "a future version of CMake.\n"
+ "Update the VERSION argument <min> value or use a ...<max> suffix "
+ "to tell CMake that the project does not need compatibility with "
+ "older versions.");
+ }
+
// now loop over all the policies and set them as appropriate
std::vector<cmPolicies::PolicyID> ancientPolicies;
for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT;
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index a82f421..0c00ffb 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -320,7 +320,13 @@ class cmMakefile;
SELECT(POLICY, CMP0107, "An ALIAS target cannot overwrite another target.", \
3, 18, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0108, "A target cannot link to itself through an alias.", \
- 3, 18, 0, cmPolicies::WARN)
+ 3, 18, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0109, \
+ "find_program() requires permission to execute but not to read.", 3, \
+ 19, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0110, \
+ "add_test() supports arbitrary characters in test names.", 3, 19, 0, \
+ cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -396,12 +402,20 @@ public:
//! Get the default status for a policy
static cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id);
+ enum class WarnCompat
+ {
+ Off,
+ On
+ };
+
//! Set a policy level for this listfile
static bool ApplyPolicyVersion(cmMakefile* mf,
std::string const& version_min,
- std::string const& version_max);
+ std::string const& version_max,
+ WarnCompat warnCompat);
static bool ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
- unsigned int minorVer, unsigned int patchVer);
+ unsigned int minorVer, unsigned int patchVer,
+ WarnCompat warnCompat);
//! return a warning string for a given policy
static std::string GetPolicyWarning(cmPolicies::PolicyID id);
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 2ec66d9..bb6db92 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -303,7 +303,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,
std::string vw;
for (std::string const& i : vv) {
const char* const v = mf.GetDefinition(i);
- if (v && *v) {
+ if (cmNonempty(v)) {
if (cmp0048 == cmPolicies::WARN) {
if (!injectedProjectCommand) {
vw += "\n ";
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index 3d4f5d7..fac2bbf 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -50,7 +50,7 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
{
cmMakefile* makefile = localGen->GetMakefile();
// Detect global autogen target name
- if (cmIsOn(makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET"))) {
+ if (makefile->IsOn("CMAKE_GLOBAL_AUTOGEN_TARGET")) {
std::string targetName =
makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET_NAME");
if (targetName.empty()) {
@@ -61,7 +61,7 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
}
// Detect global autorcc target name
- if (cmIsOn(makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET"))) {
+ if (makefile->IsOn("CMAKE_GLOBAL_AUTORCC_TARGET")) {
std::string targetName =
makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET_NAME");
if (targetName.empty()) {
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 1132852..06957b0 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -315,10 +315,9 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
{
// Configurations
this->MultiConfig = this->GlobalGen->IsMultiConfig();
- this->ConfigDefault = this->Makefile->GetConfigurations(this->ConfigsList);
- if (this->ConfigsList.empty()) {
- this->ConfigsList.push_back(this->ConfigDefault);
- }
+ this->ConfigDefault = this->Makefile->GetDefaultConfiguration();
+ this->ConfigsList =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
// Verbosity
{
@@ -490,7 +489,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
if (this->Moc.Enabled) {
// Path prefix
- if (cmIsOn(this->GenTarget->GetSafeProperty("AUTOMOC_PATH_PREFIX"))) {
+ if (cmIsOn(this->GenTarget->GetProperty("AUTOMOC_PATH_PREFIX"))) {
this->Moc.PathPrefix = true;
}
@@ -789,9 +788,9 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// Register files that will be scanned by moc or uic
if (this->MocOrUicEnabled()) {
- if (cm->IsHeaderExtension(extLower)) {
+ if (cm->IsAHeaderExtension(extLower)) {
addMUHeader(makeMUFile(sf, fullPath, true), extLower);
- } else if (cm->IsSourceExtension(extLower)) {
+ } else if (cm->IsACLikeSourceExtension(extLower)) {
addMUSource(makeMUFile(sf, fullPath, true));
}
}
@@ -863,7 +862,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
if (sf != nullptr) {
auto eMuf = makeMUFile(sf, fullPath, true);
- // Ony process moc/uic when the parent is processed as well
+ // Only process moc/uic when the parent is processed as well
if (!muf.MocIt) {
eMuf->MocIt = false;
}
@@ -895,14 +894,14 @@ bool cmQtAutoGenInitializer::InitScanFiles()
std::string const& extLower =
cmSystemTools::LowerCase(sf->GetExtension());
- if (cm->IsHeaderExtension(extLower)) {
+ if (cm->IsAHeaderExtension(extLower)) {
if (!cm::contains(this->AutogenTarget.Headers, sf.get())) {
auto muf = makeMUFile(sf.get(), fullPath, false);
if (muf->SkipMoc || muf->SkipUic) {
addMUHeader(std::move(muf), extLower);
}
}
- } else if (cm->IsSourceExtension(extLower)) {
+ } else if (cm->IsACLikeSourceExtension(extLower)) {
if (!cm::contains(this->AutogenTarget.Sources, sf.get())) {
auto muf = makeMUFile(sf.get(), fullPath, false);
if (muf->SkipMoc || muf->SkipUic) {
@@ -1654,7 +1653,7 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
};
for (std::string const& prop : props) {
cmProp propName = this->Makefile->GetState()->GetGlobalProperty(prop);
- if (propName && !propName->empty()) {
+ if (cmNonempty(propName)) {
groupName = *propName;
property = prop;
break;
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
index 254131b..4ff81c1 100644
--- a/Source/cmRulePlaceholderExpander.cxx
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -261,7 +261,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
this->VariableMappings["CMAKE_" + compIt->second +
"_COMPILE_OPTIONS_SYSROOT"];
- // if there is a required first argument to the compiler add it
+ // if there are required arguments to the compiler add it
// to the compiler string
if (!compilerArg1.empty()) {
ret += " ";
diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx
index 766d347..eb8fcaf 100644
--- a/Source/cmSearchPath.cxx
+++ b/Source/cmSearchPath.cxx
@@ -180,7 +180,7 @@ void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths,
if (subdir == "include" || subdir == "lib") {
const char* arch =
this->FC->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE");
- if (arch && *arch) {
+ if (cmNonempty(arch)) {
if (this->FC->Makefile->IsDefinitionSet("CMAKE_SYSROOT") &&
this->FC->Makefile->IsDefinitionSet(
"CMAKE_PREFIX_LIBRARY_ARCHITECTURE")) {
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index 4f7131f..e586fd9 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -136,6 +136,7 @@ bool cmServerProtocol::Activate(cmServer* server,
this->m_Server = server;
this->m_CMakeInstance =
cm::make_unique<cmake>(cmake::RoleProject, cmState::Project);
+ this->m_WarnUnused = false;
const bool result = this->DoActivate(request, errorMessage);
if (!result) {
this->m_CMakeInstance = nullptr;
@@ -636,7 +637,7 @@ cmServerResponse cmServerProtocol1::ProcessGlobalSettings(
obj[kTRACE_KEY] = cm->GetTrace();
obj[kTRACE_EXPAND_KEY] = cm->GetTraceExpand();
obj[kWARN_UNINITIALIZED_KEY] = cm->GetWarnUninitialized();
- obj[kWARN_UNUSED_KEY] = cm->GetWarnUnused();
+ obj[kWARN_UNUSED_KEY] = m_WarnUnused;
obj[kWARN_UNUSED_CLI_KEY] = cm->GetWarnUnusedCli();
obj[kCHECK_SYSTEM_VARS_KEY] = cm->GetCheckSystemVars();
@@ -682,7 +683,7 @@ cmServerResponse cmServerProtocol1::ProcessSetGlobalSettings(
setBool(request, kTRACE_EXPAND_KEY, [cm](bool e) { cm->SetTraceExpand(e); });
setBool(request, kWARN_UNINITIALIZED_KEY,
[cm](bool e) { cm->SetWarnUninitialized(e); });
- setBool(request, kWARN_UNUSED_KEY, [cm](bool e) { cm->SetWarnUnused(e); });
+ setBool(request, kWARN_UNUSED_KEY, [this](bool e) { m_WarnUnused = e; });
setBool(request, kWARN_UNUSED_CLI_KEY,
[cm](bool e) { cm->SetWarnUnusedCli(e); });
setBool(request, kCHECK_SYSTEM_VARS_KEY,
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
index c71b7bf..6009e23 100644
--- a/Source/cmServerProtocol.h
+++ b/Source/cmServerProtocol.h
@@ -94,6 +94,7 @@ protected:
// Implement protocol specific activation tasks here. Called from Activate().
virtual bool DoActivate(const cmServerRequest& request,
std::string* errorMessage);
+ bool m_WarnUnused = false; // storage for legacy option
private:
std::unique_ptr<cmake> m_CMakeInstance;
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index f525439..ef44a57 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSourceFile.h"
-#include <array>
#include <utility>
#include "cmGlobalGenerator.h"
@@ -130,13 +129,11 @@ bool cmSourceFile::FindFullPath(std::string* error)
// Location path
std::string const& lPath = this->Location.GetFullPath();
// List of extension lists
- std::array<std::vector<std::string> const*, 2> const extsLists = {
- { &makefile->GetCMakeInstance()->GetSourceExtensions(),
- &makefile->GetCMakeInstance()->GetHeaderExtensions() }
- };
+ std::vector<std::string> exts =
+ makefile->GetCMakeInstance()->GetAllExtensions();
// Tries to find the file in a given directory
- auto findInDir = [this, &extsLists, &lPath](std::string const& dir) -> bool {
+ auto findInDir = [this, &exts, &lPath](std::string const& dir) -> bool {
// Compute full path
std::string const fullPath = cmSystemTools::CollapseFullPath(lPath, dir);
// Try full path
@@ -145,14 +142,12 @@ bool cmSourceFile::FindFullPath(std::string* error)
return true;
}
// Try full path with extension
- for (auto& exts : extsLists) {
- for (std::string const& ext : *exts) {
- if (!ext.empty()) {
- std::string extPath = cmStrCat(fullPath, '.', ext);
- if (cmSystemTools::FileExists(extPath)) {
- this->FullPath = extPath;
- return true;
- }
+ for (std::string const& ext : exts) {
+ if (!ext.empty()) {
+ std::string extPath = cmStrCat(fullPath, '.', ext);
+ if (cmSystemTools::FileExists(extPath)) {
+ this->FullPath = extPath;
+ return true;
}
}
}
@@ -175,11 +170,9 @@ bool cmSourceFile::FindFullPath(std::string* error)
// Compose error
std::string err =
cmStrCat("Cannot find source file:\n ", lPath, "\nTried extensions");
- for (auto exts : extsLists) {
- for (std::string const& ext : *exts) {
- err += " .";
- err += ext;
- }
+ for (std::string const& ext : exts) {
+ err += " .";
+ err += ext;
}
if (error != nullptr) {
*error = std::move(err);
@@ -387,8 +380,7 @@ const char* cmSourceFile::GetSafeProperty(const std::string& prop) const
bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const
{
- cmProp p = this->GetProperty(prop);
- return p && cmIsOn(*p);
+ return cmIsOn(this->GetProperty(prop));
}
void cmSourceFile::SetProperties(cmPropertyMap properties)
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index e852c05..222bafa 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -101,7 +101,7 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name)
cmMakefile const* mf = this->Makefile;
auto cm = mf->GetCMakeInstance();
if (!gg->GetLanguageFromExtension(ext.c_str()).empty() ||
- cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext)) {
+ cm->IsAKnownExtension(ext)) {
// This is a known extension. Use the given filename with extension.
this->Name = cmSystemTools::GetFilenameName(name);
this->AmbiguousExtension = false;
@@ -157,7 +157,7 @@ bool cmSourceFileLocation::MatchesAmbiguousExtension(
auto ext = cm::string_view(this->Name).substr(loc.Name.size() + 1);
cmMakefile const* mf = this->Makefile;
auto cm = mf->GetCMakeInstance();
- return cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext);
+ return cm->IsAKnownExtension(ext);
}
bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc)
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
new file mode 100644
index 0000000..6dbab98
--- /dev/null
+++ b/Source/cmStandardLevelResolver.cxx
@@ -0,0 +1,538 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmStandardLevelResolver.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <sstream>
+#include <stdexcept>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <cm/iterator>
+#include <cmext/algorithm>
+
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmProperty.h"
+#include "cmStringAlgorithms.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+namespace {
+
+#define FEATURE_STRING(F) , #F
+const char* const C_FEATURES[] = { nullptr FOR_EACH_C_FEATURE(
+ FEATURE_STRING) };
+
+const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE(
+ FEATURE_STRING) };
+
+const char* const CUDA_FEATURES[] = { nullptr FOR_EACH_CUDA_FEATURE(
+ FEATURE_STRING) };
+#undef FEATURE_STRING
+
+struct StandardNeeded
+{
+ int index;
+ int value;
+};
+
+struct StanardLevelComputer
+{
+ explicit StanardLevelComputer(std::string lang, std::vector<int> levels,
+ std::vector<std::string> levelsStr)
+ : Language(std::move(lang))
+ , Levels(std::move(levels))
+ , LevelsAsStrings(std::move(levelsStr))
+ {
+ assert(levels.size() == levelsStr.size());
+ }
+
+ std::string GetCompileOptionDef(cmMakefile* makefile,
+ cmGeneratorTarget const* target,
+ std::string const& config) const
+ {
+
+ const auto& stds = this->Levels;
+ const auto& stdsStrings = this->LevelsAsStrings;
+
+ const char* defaultStd = makefile->GetDefinition(
+ cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT"));
+ if (!cmNonempty(defaultStd)) {
+ // this compiler has no notion of language standard levels
+ return std::string{};
+ }
+
+ bool ext = true;
+ if (cmProp extPropValue = target->GetLanguageExtensions(this->Language)) {
+ if (cmIsOff(*extPropValue)) {
+ ext = false;
+ }
+ }
+
+ cmProp standardProp = target->GetLanguageStandard(this->Language, config);
+ if (!standardProp) {
+ if (ext) {
+ // No language standard is specified and extensions are not disabled.
+ // Check if this compiler needs a flag to enable extensions.
+ return cmStrCat("CMAKE_", this->Language, "_EXTENSION_COMPILE_OPTION");
+ }
+ return std::string{};
+ }
+
+ std::string const type = ext ? "EXTENSION" : "STANDARD";
+
+ if (target->GetLanguageStandardRequired(this->Language)) {
+ std::string option_flag = cmStrCat(
+ "CMAKE_", this->Language, *standardProp, "_", type, "_COMPILE_OPTION");
+
+ const char* opt =
+ target->Target->GetMakefile()->GetDefinition(option_flag);
+ if (!opt) {
+ std::ostringstream e;
+ e << "Target \"" << target->GetName()
+ << "\" requires the language "
+ "dialect \""
+ << this->Language << *standardProp << "\" "
+ << (ext ? "(with compiler extensions)" : "")
+ << ", but CMake "
+ "does not know the compile flags to use to enable it.";
+ makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ }
+ return option_flag;
+ }
+
+ std::string standardStr(*standardProp);
+ if (this->Language == "CUDA" && standardStr == "98") {
+ standardStr = "03";
+ }
+
+ int standardValue = -1;
+ int defaultValue = -1;
+ try {
+ standardValue = std::stoi(standardStr);
+ defaultValue = std::stoi(defaultStd);
+ } catch (std::invalid_argument&) {
+ // fall through as we want an error
+ // when we can't find the bad value in the `stds` vector
+ }
+
+ auto stdIt = std::find(cm::cbegin(stds), cm::cend(stds), standardValue);
+ if (stdIt == cm::cend(stds)) {
+ std::string e =
+ cmStrCat(this->Language, "_STANDARD is set to invalid value '",
+ standardStr, "'");
+ makefile->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
+ target->GetBacktrace());
+ return std::string{};
+ }
+
+ auto defaultStdIt =
+ std::find(cm::cbegin(stds), cm::cend(stds), defaultValue);
+ if (defaultStdIt == cm::cend(stds)) {
+ std::string e = cmStrCat("CMAKE_", this->Language,
+ "_STANDARD_DEFAULT is set to invalid value '",
+ defaultStd, "'");
+ makefile->IssueMessage(MessageType::INTERNAL_ERROR, e);
+ return std::string{};
+ }
+
+ // If the standard requested is older than the compiler's default
+ // then we need to use a flag to change it.
+ if (stdIt <= defaultStdIt) {
+ auto offset = std::distance(cm::cbegin(stds), stdIt);
+ return cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type,
+ "_COMPILE_OPTION");
+ }
+
+ // The standard requested is at least as new as the compiler's default,
+ // and the standard request is not required. Decay to the newest standard
+ // for which a flag is defined.
+ for (; defaultStdIt < stdIt; --stdIt) {
+ auto offset = std::distance(cm::cbegin(stds), stdIt);
+ std::string option_flag =
+ cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type,
+ "_COMPILE_OPTION");
+ if (target->Target->GetMakefile()->GetDefinition(option_flag)) {
+ return option_flag;
+ }
+ }
+
+ return std::string{};
+ }
+
+ bool GetNewRequiredStandard(cmMakefile* makefile,
+ std::string const& targetName,
+ const std::string& feature,
+ cmProp currentLangStandardValue,
+ std::string& newRequiredStandard,
+ std::string* error) const
+ {
+ if (currentLangStandardValue) {
+ newRequiredStandard = *currentLangStandardValue;
+ } else {
+ newRequiredStandard.clear();
+ }
+
+ auto needed = this->HighestStandardNeeded(makefile, feature);
+
+ cmProp existingStandard = currentLangStandardValue;
+ if (existingStandard == nullptr) {
+ cmProp defaultStandard = makefile->GetDef(
+ cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT"));
+ if (cmNonempty(defaultStandard)) {
+ existingStandard = defaultStandard;
+ }
+ }
+
+ auto existingLevelIter = cm::cend(this->Levels);
+ if (existingStandard) {
+ existingLevelIter =
+ std::find(cm::cbegin(this->Levels), cm::cend(this->Levels),
+ std::stoi(*existingStandard));
+ if (existingLevelIter == cm::cend(this->Levels)) {
+ const std::string e =
+ cmStrCat("The ", this->Language, "_STANDARD property on target \"",
+ targetName, "\" contained an invalid value: \"",
+ *existingStandard, "\".");
+ if (error) {
+ *error = e;
+ } else {
+ makefile->IssueMessage(MessageType::FATAL_ERROR, e);
+ }
+ return false;
+ }
+ }
+
+ if (needed.index != -1) {
+ // Ensure the C++ language level is high enough to support
+ // the needed C++ features.
+ if (existingLevelIter == cm::cend(this->Levels) ||
+ existingLevelIter < this->Levels.begin() + needed.index) {
+ newRequiredStandard = this->LevelsAsStrings[needed.index];
+ }
+ }
+
+ return true;
+ }
+
+ bool HaveStandardAvailable(cmMakefile* makefile,
+ cmGeneratorTarget const* target,
+ std::string const& config,
+ std::string const& feature) const
+ {
+ cmProp defaultStandard = makefile->GetDef(
+ cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT"));
+ if (!defaultStandard) {
+ makefile->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("CMAKE_", this->Language,
+ "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
+ "not fully configured for this compiler."));
+ // Return true so the caller does not try to lookup the default standard.
+ return true;
+ }
+ // convert defaultStandard to an integer
+ if (std::find(cm::cbegin(this->Levels), cm::cend(this->Levels),
+ std::stoi(*defaultStandard)) == cm::cend(this->Levels)) {
+ const std::string e = cmStrCat("The CMAKE_", this->Language,
+ "_STANDARD_DEFAULT variable contains an "
+ "invalid value: \"",
+ *defaultStandard, "\".");
+ makefile->IssueMessage(MessageType::INTERNAL_ERROR, e);
+ return false;
+ }
+
+ cmProp existingStandard =
+ target->GetLanguageStandard(this->Language, config);
+ if (!existingStandard) {
+ existingStandard = defaultStandard;
+ }
+
+ auto existingLevelIter =
+ std::find(cm::cbegin(this->Levels), cm::cend(this->Levels),
+ std::stoi(*existingStandard));
+ if (existingLevelIter == cm::cend(this->Levels)) {
+ const std::string e =
+ cmStrCat("The ", this->Language, "_STANDARD property on target \"",
+ target->GetName(), "\" contained an invalid value: \"",
+ *existingStandard, "\".");
+ makefile->IssueMessage(MessageType::FATAL_ERROR, e);
+ return false;
+ }
+
+ auto needed = this->HighestStandardNeeded(makefile, feature);
+
+ return (needed.index == -1) ||
+ (this->Levels.begin() + needed.index) <= existingLevelIter;
+ }
+
+ StandardNeeded HighestStandardNeeded(cmMakefile* makefile,
+ std::string const& feature) const
+ {
+ std::string prefix = cmStrCat("CMAKE_", this->Language);
+ StandardNeeded maxLevel = { -1, -1 };
+ for (size_t i = 0; i < this->Levels.size(); ++i) {
+ if (const char* prop = makefile->GetDefinition(
+ cmStrCat(prefix, this->LevelsAsStrings[i], "_COMPILE_FEATURES"))) {
+ std::vector<std::string> props = cmExpandedList(prop);
+ if (cm::contains(props, feature)) {
+ maxLevel = { static_cast<int>(i), this->Levels[i] };
+ }
+ }
+ }
+ return maxLevel;
+ }
+
+ bool IsLaterStandard(int lhs, int rhs) const
+ {
+ auto rhsIt =
+ std::find(cm::cbegin(this->Levels), cm::cend(this->Levels), rhs);
+
+ return std::find(rhsIt, cm::cend(this->Levels), lhs) !=
+ cm::cend(this->Levels);
+ }
+
+ std::string Language;
+ std::vector<int> Levels;
+ std::vector<std::string> LevelsAsStrings;
+};
+
+std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping =
+ {
+ { "C",
+ StanardLevelComputer{ "C", std::vector<int>{ 90, 99, 11 },
+ std::vector<std::string>{ "90", "99", "11" } } },
+ { "CXX",
+ StanardLevelComputer{
+ "CXX", std::vector<int>{ 98, 11, 14, 17, 20 },
+ std::vector<std::string>{ "98", "11", "14", "17", "20" } } },
+ { "CUDA",
+ StanardLevelComputer{
+ "CUDA", std::vector<int>{ 03, 11, 14, 17, 20 },
+ std::vector<std::string>{ "03", "11", "14", "17", "20" } } },
+ { "OBJC",
+ StanardLevelComputer{ "OBJC", std::vector<int>{ 90, 99, 11 },
+ std::vector<std::string>{ "90", "99", "11" } } },
+ { "OBJCXX",
+ StanardLevelComputer{
+ "OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20 },
+ std::vector<std::string>{ "98", "11", "14", "17", "20" } } },
+ };
+}
+
+std::string cmStandardLevelResolver::GetCompileOptionDef(
+ cmGeneratorTarget const* target, std::string const& lang,
+ std::string const& config) const
+{
+ const auto& mapping = StandardComputerMapping.find(lang);
+ if (mapping == cm::cend(StandardComputerMapping)) {
+ return std::string{};
+ }
+
+ return mapping->second.GetCompileOptionDef(this->Makefile, target, config);
+}
+
+bool cmStandardLevelResolver::AddRequiredTargetFeature(
+ cmTarget* target, const std::string& feature, std::string* error) const
+{
+ if (cmGeneratorExpression::Find(feature) != std::string::npos) {
+ target->AppendProperty("COMPILE_FEATURES", feature);
+ return true;
+ }
+
+ std::string lang;
+ if (!this->CheckCompileFeaturesAvailable(target->GetName(), feature, lang,
+ error)) {
+ return false;
+ }
+
+ target->AppendProperty("COMPILE_FEATURES", feature);
+
+ // FIXME: Add a policy to avoid updating the <LANG>_STANDARD target
+ // property due to COMPILE_FEATURES. The language standard selection
+ // should be done purely at generate time based on whatever the project
+ // code put in these properties explicitly. That is mostly true now,
+ // but for compatibility we need to continue updating the property here.
+ std::string newRequiredStandard;
+ bool newRequired = this->GetNewRequiredStandard(
+ target->GetName(), feature,
+ target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard,
+ error);
+ if (!newRequiredStandard.empty()) {
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard);
+ }
+ return newRequired;
+}
+
+bool cmStandardLevelResolver::CheckCompileFeaturesAvailable(
+ const std::string& targetName, const std::string& feature, std::string& lang,
+ std::string* error) const
+{
+ if (!this->CompileFeatureKnown(targetName, feature, lang, error)) {
+ return false;
+ }
+
+ const char* features = this->CompileFeaturesAvailable(lang, error);
+ if (!features) {
+ return false;
+ }
+
+ std::vector<std::string> availableFeatures = cmExpandedList(features);
+ if (!cm::contains(availableFeatures, feature)) {
+ std::ostringstream e;
+ e << "The compiler feature \"" << feature << "\" is not known to " << lang
+ << " compiler\n\""
+ << this->Makefile->GetDefinition("CMAKE_" + lang + "_COMPILER_ID")
+ << "\"\nversion "
+ << this->Makefile->GetDefinition("CMAKE_" + lang + "_COMPILER_VERSION")
+ << ".";
+ if (error) {
+ *error = e.str();
+ } else {
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool cmStandardLevelResolver::CompileFeatureKnown(
+ const std::string& targetName, const std::string& feature, std::string& lang,
+ std::string* error) const
+{
+ assert(cmGeneratorExpression::Find(feature) == std::string::npos);
+
+ bool isCFeature =
+ std::find_if(cm::cbegin(C_FEATURES) + 1, cm::cend(C_FEATURES),
+ cmStrCmp(feature)) != cm::cend(C_FEATURES);
+ if (isCFeature) {
+ lang = "C";
+ return true;
+ }
+ bool isCxxFeature =
+ std::find_if(cm::cbegin(CXX_FEATURES) + 1, cm::cend(CXX_FEATURES),
+ cmStrCmp(feature)) != cm::cend(CXX_FEATURES);
+ if (isCxxFeature) {
+ lang = "CXX";
+ return true;
+ }
+ bool isCudaFeature =
+ std::find_if(cm::cbegin(CUDA_FEATURES) + 1, cm::cend(CUDA_FEATURES),
+ cmStrCmp(feature)) != cm::cend(CUDA_FEATURES);
+ if (isCudaFeature) {
+ lang = "CUDA";
+ return true;
+ }
+ std::ostringstream e;
+ if (error) {
+ e << "specified";
+ } else {
+ e << "Specified";
+ }
+ e << " unknown feature \"" << feature
+ << "\" for "
+ "target \""
+ << targetName << "\".";
+ if (error) {
+ *error = e.str();
+ } else {
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ }
+ return false;
+}
+
+const char* cmStandardLevelResolver::CompileFeaturesAvailable(
+ const std::string& lang, std::string* error) const
+{
+ if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) {
+ std::ostringstream e;
+ if (error) {
+ e << "cannot";
+ } else {
+ e << "Cannot";
+ }
+ e << " use features from non-enabled language " << lang;
+ if (error) {
+ *error = e.str();
+ } else {
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ }
+ return nullptr;
+ }
+
+ const char* featuresKnown =
+ this->Makefile->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES");
+
+ if (!cmNonempty(featuresKnown)) {
+ std::ostringstream e;
+ if (error) {
+ e << "no";
+ } else {
+ e << "No";
+ }
+ e << " known features for " << lang << " compiler\n\""
+ << this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID")
+ << "\"\nversion "
+ << this->Makefile->GetSafeDefinition("CMAKE_" + lang +
+ "_COMPILER_VERSION")
+ << ".";
+ if (error) {
+ *error = e.str();
+ } else {
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ }
+ return nullptr;
+ }
+ return featuresKnown;
+}
+
+bool cmStandardLevelResolver::GetNewRequiredStandard(
+ const std::string& targetName, const std::string& feature,
+ cmProp currentLangStandardValue, std::string& newRequiredStandard,
+ std::string* error) const
+{
+ std::string lang;
+ if (!this->CheckCompileFeaturesAvailable(targetName, feature, lang, error)) {
+ return false;
+ }
+
+ auto mapping = StandardComputerMapping.find(lang);
+ if (mapping != cm::cend(StandardComputerMapping)) {
+ return mapping->second.GetNewRequiredStandard(
+ this->Makefile, targetName, feature, currentLangStandardValue,
+ newRequiredStandard, error);
+ }
+ return false;
+}
+
+bool cmStandardLevelResolver::HaveStandardAvailable(
+ cmGeneratorTarget const* target, std::string const& lang,
+ std::string const& config, const std::string& feature) const
+{
+ auto mapping = StandardComputerMapping.find(lang);
+ if (mapping != cm::cend(StandardComputerMapping)) {
+ return mapping->second.HaveStandardAvailable(this->Makefile, target,
+ config, feature);
+ }
+ return false;
+}
+
+bool cmStandardLevelResolver::IsLaterStandard(std::string const& lang,
+ std::string const& lhs,
+ std::string const& rhs) const
+{
+ auto mapping = StandardComputerMapping.find(lang);
+ if (mapping != cm::cend(StandardComputerMapping)) {
+ return mapping->second.IsLaterStandard(std::stoi(lhs), std::stoi(rhs));
+ }
+ return false;
+}
diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h
new file mode 100644
index 0000000..959a5f9
--- /dev/null
+++ b/Source/cmStandardLevelResolver.h
@@ -0,0 +1,59 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmStandardLevelResolver_h
+#define cmStandardLevelResolver_h
+
+#include <string>
+
+#include "cmProperty.h"
+
+class cmMakefile;
+class cmGeneratorTarget;
+class cmTarget;
+
+class cmStandardLevelResolver
+{
+
+public:
+ explicit cmStandardLevelResolver(cmMakefile* makefile)
+ : Makefile(makefile)
+ {
+ }
+
+ std::string GetCompileOptionDef(cmGeneratorTarget const* target,
+ std::string const& lang,
+ std::string const& config) const;
+
+ bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature,
+ std::string* error = nullptr) const;
+
+ bool CompileFeatureKnown(const std::string& targetName,
+ const std::string& feature, std::string& lang,
+ std::string* error) const;
+
+ const char* CompileFeaturesAvailable(const std::string& lang,
+ std::string* error) const;
+
+ bool GetNewRequiredStandard(const std::string& targetName,
+ const std::string& feature,
+ cmProp currentLangStandardValue,
+ std::string& newRequiredStandard,
+ std::string* error = nullptr) const;
+
+ bool HaveStandardAvailable(cmGeneratorTarget const* target,
+ std::string const& lang,
+ std::string const& config,
+ const std::string& feature) const;
+
+ bool IsLaterStandard(std::string const& lang, std::string const& lhs,
+ std::string const& rhs) const;
+
+private:
+ bool CheckCompileFeaturesAvailable(const std::string& targetName,
+ const std::string& feature,
+ std::string& lang,
+ std::string* error) const;
+
+ cmMakefile* Makefile;
+};
+#endif
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 0b6b40f..73f166c 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -623,8 +623,7 @@ cmProp cmState::GetGlobalProperty(const std::string& prop)
bool cmState::GetGlobalPropertyAsBool(const std::string& prop)
{
- cmProp p = this->GetGlobalProperty(prop);
- return p && cmIsOn(*p);
+ return cmIsOn(this->GetGlobalProperty(prop));
}
void cmState::SetSourceDirectory(std::string const& sourceDirectory)
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index a4fe663..796bb1f 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -648,8 +648,7 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const
bool cmStateDirectory::GetPropertyAsBool(const std::string& prop) const
{
- cmProp p = this->GetProperty(prop);
- return p && cmIsOn(*p);
+ return cmIsOn(this->GetProperty(prop));
}
std::vector<std::string> cmStateDirectory::GetPropertyKeys() const
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index c223431..bf8e331 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -148,7 +148,7 @@ bool cmStateSnapshot::PopPolicy()
bool cmStateSnapshot::CanPopPolicyScope()
{
- return this->Position->Policies == this->Position->PolicyScope;
+ return this->Position->Policies != this->Position->PolicyScope;
}
void cmStateSnapshot::SetPolicy(cmPolicies::PolicyID id,
@@ -232,11 +232,6 @@ void cmStateSnapshot::RemoveDefinition(std::string const& name)
this->Position->Vars->Unset(name);
}
-std::vector<std::string> cmStateSnapshot::UnusedKeys() const
-{
- return this->Position->Vars->UnusedKeys();
-}
-
std::vector<std::string> cmStateSnapshot::ClosureKeys() const
{
return cmDefinitions::ClosureKeys(this->Position->Vars,
@@ -328,7 +323,7 @@ void cmStateSnapshot::SetDefaultDefinitions()
#if defined(__CYGWIN__)
std::string legacy;
if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) &&
- cmIsOn(legacy.c_str())) {
+ cmIsOn(legacy)) {
this->SetDefinition("WIN32", "1");
this->SetDefinition("CMAKE_HOST_WIN32", "1");
}
diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h
index 021fd53..c19f174 100644
--- a/Source/cmStateSnapshot.h
+++ b/Source/cmStateSnapshot.h
@@ -28,7 +28,6 @@ public:
bool IsInitialized(std::string const& name) const;
void SetDefinition(std::string const& name, cm::string_view value);
void RemoveDefinition(std::string const& name);
- std::vector<std::string> UnusedKeys() const;
std::vector<std::string> ClosureKeys() const;
bool RaiseScope(std::string const& var, const char* varDef);
diff --git a/Source/cmString.cxx b/Source/cmString.cxx
index 2a0c125..898b828 100644
--- a/Source/cmString.cxx
+++ b/Source/cmString.cxx
@@ -17,7 +17,7 @@ static std::string const empty_string_;
void String::internally_mutate_to_stable_string()
{
// We assume that only one thread mutates this instance at
- // a time even if we point to a shared string buffer refernced
+ // a time even if we point to a shared string buffer referenced
// by other threads.
*this = String(data(), size());
}
diff --git a/Source/cmString.hxx b/Source/cmString.hxx
index 87bfdff..40fe20d 100644
--- a/Source/cmString.hxx
+++ b/Source/cmString.hxx
@@ -383,7 +383,7 @@ public:
instance is mutated or destroyed. */
std::string const* str_if_stable() const;
- /** Get a refernce to a normal std::string. The reference
+ /** Get a reference to a normal std::string. The reference
is valid until this instance is mutated or destroyed. */
std::string const& str();
diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h
index a5ecca7..4b0090b 100644
--- a/Source/cmStringAlgorithms.h
+++ b/Source/cmStringAlgorithms.h
@@ -20,6 +20,20 @@
/** 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();
+}
+
/** Callable string comparison struct. */
struct cmStrCmp
{
@@ -205,10 +219,11 @@ bool cmIsNOTFOUND(cm::string_view val);
bool cmIsOn(cm::string_view val);
inline bool cmIsOn(const char* val)
{
- if (!val) {
- return false;
- }
- return cmIsOn(cm::string_view(val));
+ return val && cmIsOn(cm::string_view(val));
+}
+inline bool cmIsOn(std::string const* val)
+{
+ return val && cmIsOn(*val);
}
/**
@@ -221,10 +236,11 @@ inline bool cmIsOn(const char* val)
bool cmIsOff(cm::string_view val);
inline bool cmIsOff(const char* val)
{
- if (!val) {
- return true;
- }
- return cmIsOff(cm::string_view(val));
+ return !val || cmIsOff(cm::string_view(val));
+}
+inline bool cmIsOff(std::string const* val)
+{
+ return !val || cmIsOff(*val);
}
/** Returns true if string @a str starts with the character @a prefix. */
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 1e78d36..798c29a 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1213,7 +1213,7 @@ bool cmSystemTools::UnsetEnv(const char* value)
{
# if !defined(HAVE_UNSETENV)
std::string var = cmStrCat(value, '=');
- return cmSystemTools::PutEnv(var.c_str());
+ return cmSystemTools::PutEnv(var);
# else
unsetenv(value);
return true;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 36e1ad5..60416a3 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -7,6 +7,7 @@
#include <cstring>
#include <initializer_list>
#include <iterator>
+#include <map>
#include <set>
#include <sstream>
#include <unordered_set>
@@ -185,6 +186,7 @@ public:
std::vector<cmInstallTargetGenerator*> InstallGenerators;
std::set<std::string> SystemIncludeDirectories;
cmTarget::LinkLibraryVectorType OriginalLinkLibraries;
+ std::map<std::string, BTs<std::string>> LanguageStandardProperties;
std::vector<std::string> IncludeDirectoriesEntries;
std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces;
std::vector<std::string> CompileOptionsEntries;
@@ -214,6 +216,15 @@ public:
std::string ProcessSourceItemCMP0049(const std::string& s);
};
+namespace {
+#define SETUP_COMMON_LANGUAGE_PROPERTIES(lang) \
+ initProp(#lang "_COMPILER_LAUNCHER"); \
+ initProp(#lang "_STANDARD"); \
+ initProp(#lang "_STANDARD_REQUIRED"); \
+ initProp(#lang "_EXTENSIONS"); \
+ initProp(#lang "_VISIBILITY_PRESET")
+}
+
cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
Visibility vis, cmMakefile* mf, PerConfig perConfig)
: impl(cm::make_unique<cmTargetInternals>())
@@ -270,8 +281,14 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
};
// Setup default property values.
- if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
- this->GetType() != cmStateEnums::UTILITY) {
+ if (this->CanCompileSources()) {
+
+ SETUP_COMMON_LANGUAGE_PROPERTIES(C);
+ SETUP_COMMON_LANGUAGE_PROPERTIES(OBJC);
+ SETUP_COMMON_LANGUAGE_PROPERTIES(CXX);
+ SETUP_COMMON_LANGUAGE_PROPERTIES(OBJCXX);
+ SETUP_COMMON_LANGUAGE_PROPERTIES(CUDA);
+
initProp("ANDROID_API");
initProp("ANDROID_API_MIN");
initProp("ANDROID_ARCH");
@@ -333,38 +350,22 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("NO_SYSTEM_FROM_IMPORTED");
initProp("BUILD_WITH_INSTALL_NAME_DIR");
initProp("C_CLANG_TIDY");
- initProp("C_COMPILER_LAUNCHER");
initProp("C_CPPLINT");
initProp("C_CPPCHECK");
initProp("C_INCLUDE_WHAT_YOU_USE");
initProp("LINK_WHAT_YOU_USE");
- initProp("C_STANDARD");
- initProp("C_STANDARD_REQUIRED");
- initProp("C_EXTENSIONS");
- initProp("OBJC_COMPILER_LAUNCHER");
- initProp("OBJC_STANDARD");
- initProp("OBJC_STANDARD_REQUIRED");
- initProp("OBJC_EXTENSIONS");
initProp("CXX_CLANG_TIDY");
- initProp("CXX_COMPILER_LAUNCHER");
initProp("CXX_CPPLINT");
initProp("CXX_CPPCHECK");
initProp("CXX_INCLUDE_WHAT_YOU_USE");
- initProp("CXX_STANDARD");
- initProp("CXX_STANDARD_REQUIRED");
- initProp("CXX_EXTENSIONS");
- initProp("OBJCXX_COMPILER_LAUNCHER");
- initProp("OBJCXX_STANDARD");
- initProp("OBJCXX_STANDARD_REQUIRED");
- initProp("OBJCXX_EXTENSIONS");
- initProp("CUDA_STANDARD");
- initProp("CUDA_STANDARD_REQUIRED");
- initProp("CUDA_EXTENSIONS");
- initProp("CUDA_COMPILER_LAUNCHER");
initProp("CUDA_SEPARABLE_COMPILATION");
initProp("CUDA_RESOLVE_DEVICE_SYMBOLS");
initProp("CUDA_RUNTIME_LIBRARY");
initProp("CUDA_ARCHITECTURES");
+ initProp("VISIBILITY_INLINES_HIDDEN");
+ initProp("JOB_POOL_COMPILE");
+ initProp("JOB_POOL_LINK");
+ initProp("JOB_POOL_PRECOMPILE_HEADER");
initProp("LINK_SEARCH_START_STATIC");
initProp("LINK_SEARCH_END_STATIC");
initProp("Swift_LANGUAGE_VERSION");
@@ -372,9 +373,11 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("VS_JUST_MY_CODE_DEBUGGING");
initProp("DISABLE_PRECOMPILE_HEADERS");
initProp("UNITY_BUILD");
+ initProp("OPTIMIZE_DEPENDENCIES");
initPropValue("UNITY_BUILD_BATCH_SIZE", "8");
initPropValue("UNITY_BUILD_MODE", "BATCH");
initPropValue("PCH_WARN_INVALID", "ON");
+
#ifdef __APPLE__
if (this->GetGlobalGenerator()->IsXcode()) {
initProp("XCODE_SCHEME_ADDRESS_SANITIZER");
@@ -399,16 +402,15 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
#endif
}
- if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- initProp("FOLDER");
+ initProp("FOLDER");
- if (this->GetGlobalGenerator()->IsXcode()) {
- initProp("XCODE_GENERATE_SCHEME");
- }
+ if (this->GetGlobalGenerator()->IsXcode()) {
+ initProp("XCODE_GENERATE_SCHEME");
}
// Setup per-configuration property default values.
- if (this->GetType() != cmStateEnums::UTILITY) {
+ if (this->GetType() != cmStateEnums::UTILITY &&
+ this->GetType() != cmStateEnums::GLOBAL_TARGET) {
static const auto configProps = {
/* clang-format needs this comment to break after the opening brace */
"ARCHIVE_OUTPUT_DIRECTORY_", "LIBRARY_OUTPUT_DIRECTORY_",
@@ -417,8 +419,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
"INTERPROCEDURAL_OPTIMIZATION_"
};
// Collect the set of configuration types.
- std::vector<std::string> configNames;
- mf->GetConfigurations(configNames);
+ std::vector<std::string> configNames =
+ mf->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
for (std::string const& configName : configNames) {
std::string configUpper = cmSystemTools::UpperCase(configName);
for (auto const& prop : configProps) {
@@ -485,16 +487,6 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
impl->Makefile->GetLinkDirectoriesBacktraces());
}
- if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
- this->GetType() != cmStateEnums::UTILITY) {
- initProp("C_VISIBILITY_PRESET");
- initProp("CXX_VISIBILITY_PRESET");
- initProp("OBJC_VISIBILITY_PRESET");
- initProp("OBJCXX_VISIBILITY_PRESET");
- initProp("CUDA_VISIBILITY_PRESET");
- initProp("VISIBILITY_INLINES_HIDDEN");
- }
-
if (impl->TargetType == cmStateEnums::EXECUTABLE) {
initProp("ANDROID_GUI");
initProp("CROSSCOMPILING_EMULATOR");
@@ -503,6 +495,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
impl->TargetType == cmStateEnums::MODULE_LIBRARY) {
this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
+ } else if (this->CanCompileSources()) {
+ initProp("POSITION_INDEPENDENT_CODE");
}
if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
impl->TargetType == cmStateEnums::EXECUTABLE) {
@@ -510,11 +504,6 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("WINDOWS_EXPORT_ALL_SYMBOLS");
}
- if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
- this->GetType() != cmStateEnums::UTILITY) {
- initProp("POSITION_INDEPENDENT_CODE");
- }
-
// Record current policies for later use.
impl->Makefile->RecordPolicies(impl->PolicyMap);
@@ -526,36 +515,26 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
impl->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW);
}
- if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
- this->GetType() != cmStateEnums::UTILITY) {
- initProp("JOB_POOL_COMPILE");
- initProp("JOB_POOL_LINK");
- initProp("JOB_POOL_PRECOMPILE_HEADER");
- }
-
if (impl->TargetType <= cmStateEnums::GLOBAL_TARGET) {
initProp("DOTNET_TARGET_FRAMEWORK");
initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
}
- if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
-
- // check for "CMAKE_VS_GLOBALS" variable and set up target properties
- // if any
- const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
- if (globals) {
- const std::string genName = mf->GetGlobalGenerator()->GetName();
- if (cmHasLiteralPrefix(genName, "Visual Studio")) {
- std::vector<std::string> props = cmExpandedList(globals);
- const std::string vsGlobal = "VS_GLOBAL_";
- for (const std::string& i : props) {
- // split NAME=VALUE
- const std::string::size_type assignment = i.find('=');
- if (assignment != std::string::npos) {
- const std::string propName = vsGlobal + i.substr(0, assignment);
- const std::string propValue = i.substr(assignment + 1);
- initPropValue(propName, propValue.c_str());
- }
+ // check for "CMAKE_VS_GLOBALS" variable and set up target properties
+ // if any
+ const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
+ if (globals) {
+ const std::string genName = mf->GetGlobalGenerator()->GetName();
+ if (cmHasLiteralPrefix(genName, "Visual Studio")) {
+ std::vector<std::string> props = cmExpandedList(globals);
+ const std::string vsGlobal = "VS_GLOBAL_";
+ for (const std::string& i : props) {
+ // split NAME=VALUE
+ const std::string::size_type assignment = i.find('=');
+ if (assignment != std::string::npos) {
+ const std::string propName = vsGlobal + i.substr(0, assignment);
+ const std::string propValue = i.substr(assignment + 1);
+ initPropValue(propName, propValue.c_str());
}
}
}
@@ -598,6 +577,40 @@ cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
return impl->Makefile->GetGlobalGenerator();
}
+BTs<std::string> const* cmTarget::GetLanguageStandardProperty(
+ const std::string& propertyName) const
+{
+ auto entry = impl->LanguageStandardProperties.find(propertyName);
+ if (entry != impl->LanguageStandardProperties.end()) {
+ return &entry->second;
+ }
+
+ return nullptr;
+}
+
+void cmTarget::SetLanguageStandardProperty(std::string const& lang,
+ std::string const& value,
+ const std::string& feature)
+{
+ cmListFileBacktrace featureBacktrace;
+ for (size_t i = 0; i < impl->CompileFeaturesEntries.size(); i++) {
+ if (impl->CompileFeaturesEntries[i] == feature) {
+ if (i < impl->CompileFeaturesBacktraces.size()) {
+ featureBacktrace = impl->CompileFeaturesBacktraces[i];
+ }
+ break;
+ }
+ }
+
+ BTs<std::string>& languageStandardProperty =
+ impl->LanguageStandardProperties[cmStrCat(lang, "_STANDARD")];
+ if (languageStandardProperty.Value != value) {
+ languageStandardProperty.Value = value;
+ languageStandardProperty.Backtraces.clear();
+ }
+ languageStandardProperty.Backtraces.emplace_back(featureBacktrace);
+}
+
void cmTarget::AddUtility(std::string const& name, bool cross, cmMakefile* mf)
{
impl->Utilities.insert(BT<std::pair<std::string, bool>>(
@@ -636,6 +649,12 @@ bool cmTarget::IsAppBundleOnApple() const
this->GetPropertyAsBool("MACOSX_BUNDLE"));
}
+bool cmTarget::IsAndroidGuiExecutable() const
+{
+ return (this->GetType() == cmStateEnums::EXECUTABLE && impl->IsAndroid &&
+ this->GetPropertyAsBool("ANDROID_GUI"));
+}
+
std::vector<cmCustomCommand> const& cmTarget::GetPreBuildCommands() const
{
return impl->PreBuildCommands;
@@ -1121,12 +1140,12 @@ cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const
void cmTarget::SetProperty(const std::string& prop, const char* value)
{
- if (!cmTargetPropertyComputer::PassesWhitelist(
- this->GetType(), prop, impl->Makefile->GetMessenger(),
- impl->Makefile->GetBacktrace())) {
- return;
- }
#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
+ MAKE_STATIC_PROP(C_STANDARD);
+ MAKE_STATIC_PROP(CXX_STANDARD);
+ MAKE_STATIC_PROP(CUDA_STANDARD);
+ MAKE_STATIC_PROP(OBJC_STANDARD);
+ MAKE_STATIC_PROP(OBJCXX_STANDARD);
MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
MAKE_STATIC_PROP(COMPILE_FEATURES);
MAKE_STATIC_PROP(COMPILE_OPTIONS);
@@ -1310,6 +1329,15 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
cmProp tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME");
this->SetProperty("COMPILE_PDB_NAME", tmp ? tmp->c_str() : nullptr);
this->AddUtility(reusedFrom, false, impl->Makefile);
+ } else if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
+ prop == propCUDA_STANDARD || prop == propOBJC_STANDARD ||
+ prop == propOBJCXX_STANDARD) {
+ if (value) {
+ impl->LanguageStandardProperties[prop] =
+ BTs<std::string>(value, impl->Makefile->GetBacktrace());
+ } else {
+ impl->LanguageStandardProperties.erase(prop);
+ }
} else {
impl->Properties.SetProperty(prop, value);
}
@@ -1318,11 +1346,6 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
void cmTarget::AppendProperty(const std::string& prop,
const std::string& value, bool asString)
{
- if (!cmTargetPropertyComputer::PassesWhitelist(
- this->GetType(), prop, impl->Makefile->GetMessenger(),
- impl->Makefile->GetBacktrace())) {
- return;
- }
if (prop == "NAME") {
impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
"NAME property is read-only\n");
@@ -1413,6 +1436,11 @@ void cmTarget::AppendProperty(const std::string& prop,
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) {
impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
prop + " property may not be APPENDed.");
+ } else if (prop == "C_STANDARD" || prop == "CXX_STANDARD" ||
+ prop == "CUDA_STANDARD" || prop == "OBJC_STANDARD" ||
+ prop == "OBJCXX_STANDARD") {
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ prop + " property may not be appended.");
} else {
impl->Properties.AppendProperty(prop, value, asString);
}
@@ -1626,6 +1654,11 @@ cmProp cmTarget::GetComputedProperty(const std::string& prop,
cmProp cmTarget::GetProperty(const std::string& prop) const
{
#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
+ MAKE_STATIC_PROP(C_STANDARD);
+ MAKE_STATIC_PROP(CXX_STANDARD);
+ MAKE_STATIC_PROP(CUDA_STANDARD);
+ MAKE_STATIC_PROP(OBJC_STANDARD);
+ MAKE_STATIC_PROP(OBJCXX_STANDARD);
MAKE_STATIC_PROP(LINK_LIBRARIES);
MAKE_STATIC_PROP(TYPE);
MAKE_STATIC_PROP(INCLUDE_DIRECTORIES);
@@ -1646,6 +1679,11 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
MAKE_STATIC_PROP(TRUE);
#undef MAKE_STATIC_PROP
static std::unordered_set<std::string> const specialProps{
+ propC_STANDARD,
+ propCXX_STANDARD,
+ propCUDA_STANDARD,
+ propOBJC_STANDARD,
+ propOBJCXX_STANDARD,
propLINK_LIBRARIES,
propTYPE,
propINCLUDE_DIRECTORIES,
@@ -1664,6 +1702,15 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
propSOURCES
};
if (specialProps.count(prop)) {
+ if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
+ prop == propCUDA_STANDARD || prop == propOBJC_STANDARD ||
+ prop == propOBJCXX_STANDARD) {
+ auto propertyIter = impl->LanguageStandardProperties.find(prop);
+ if (propertyIter == impl->LanguageStandardProperties.end()) {
+ return nullptr;
+ }
+ return &(propertyIter->second.Value);
+ }
if (prop == propLINK_LIBRARIES) {
if (impl->LinkImplementationPropertyEntries.empty()) {
return nullptr;
@@ -1804,8 +1851,7 @@ std::string const& cmTarget::GetSafeProperty(std::string const& prop) const
bool cmTarget::GetPropertyAsBool(const std::string& prop) const
{
- cmProp p = this->GetProperty(prop);
- return p && cmIsOn(*p);
+ return cmIsOn(this->GetProperty(prop));
}
cmPropertyMap const& cmTarget::GetProperties() const
@@ -1838,6 +1884,27 @@ bool cmTarget::IsPerConfig() const
return impl->PerConfig;
}
+bool cmTarget::CanCompileSources() const
+{
+ if (this->IsImported()) {
+ return false;
+ }
+ switch (this->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
+ return true;
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ case cmStateEnums::GLOBAL_TARGET:
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ break;
+ }
+ return false;
+}
+
const char* cmTarget::GetSuffixVariableInternal(
cmStateEnums::ArtifactType artifact) const
{
@@ -1865,7 +1932,7 @@ const char* cmTarget::GetSuffixVariableInternal(
case cmStateEnums::RuntimeBinaryArtifact:
// Android GUI application packages store the native
// binary as a shared library.
- return (impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
+ return (this->IsAndroidGuiExecutable()
? "CMAKE_SHARED_LIBRARY_SUFFIX"
: "CMAKE_EXECUTABLE_SUFFIX");
case cmStateEnums::ImportLibraryArtifact:
@@ -1906,7 +1973,7 @@ const char* cmTarget::GetPrefixVariableInternal(
case cmStateEnums::RuntimeBinaryArtifact:
// Android GUI application packages store the native
// binary as a shared library.
- return (impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
+ return (this->IsAndroidGuiExecutable()
? "CMAKE_SHARED_LIBRARY_PREFIX"
: "");
case cmStateEnums::ImportLibraryArtifact:
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index f0ddb68..43f1887 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -196,6 +196,7 @@ public:
bool IsImported() const;
bool IsImportedGloballyVisible() const;
bool IsPerConfig() const;
+ bool CanCompileSources() const;
bool GetMappedConfig(std::string const& desired_config, cmProp& loc,
cmProp& imp, std::string& suffix) const;
@@ -209,6 +210,9 @@ public:
//! Return whether this target is an executable Bundle on Apple.
bool IsAppBundleOnApple() const;
+ //! Return whether this target is a GUI executable on Android.
+ bool IsAndroidGuiExecutable() const;
+
//! Get a backtrace from the creation of the target.
cmListFileBacktrace const& GetBacktrace() const;
@@ -233,6 +237,13 @@ public:
void AddSystemIncludeDirectories(std::set<std::string> const& incs);
std::set<std::string> const& GetSystemIncludeDirectories() const;
+ BTs<std::string> const* GetLanguageStandardProperty(
+ const std::string& propertyName) const;
+
+ void SetLanguageStandardProperty(std::string const& lang,
+ std::string const& value,
+ const std::string& feature);
+
cmStringRange GetIncludeDirectoriesEntries() const;
cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
index 06be4f0..aa1abdd 100644
--- a/Source/cmTargetCompileFeaturesCommand.cxx
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -4,6 +4,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmStandardLevelResolver.h"
#include "cmStringAlgorithms.h"
#include "cmTargetPropCommandBase.h"
@@ -29,9 +30,10 @@ private:
const std::vector<std::string>& content,
bool /*prepend*/, bool /*system*/) override
{
+ cmStandardLevelResolver standardResolver(this->Makefile);
for (std::string const& it : content) {
std::string error;
- if (!this->Makefile->AddRequiredTargetFeature(tgt, it, &error)) {
+ if (!standardResolver.AddRequiredTargetFeature(tgt, it, &error)) {
this->SetError(error);
return false; // Not (successfully) handled.
}
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index e714720..9e30136 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -123,7 +123,7 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
}
if (!content.empty()) {
if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
- scope != "INTERFACE") {
+ scope != "INTERFACE" && this->Property != "SOURCES") {
this->SetError("may only set INTERFACE properties on INTERFACE targets");
return false;
}
diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx
index f37995c..b9c9365 100644
--- a/Source/cmTargetPropertyComputer.cxx
+++ b/Source/cmTargetPropertyComputer.cxx
@@ -3,15 +3,12 @@
#include "cmTargetPropertyComputer.h"
-#include <cctype>
#include <sstream>
-#include <unordered_set>
#include "cmMessageType.h"
#include "cmMessenger.h"
#include "cmPolicies.h"
#include "cmStateSnapshot.h"
-#include "cmStringAlgorithms.h"
bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
std::string const& tgtName, cmMessenger* messenger,
@@ -44,69 +41,3 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
return messageType != MessageType::FATAL_ERROR;
}
-
-bool cmTargetPropertyComputer::WhiteListedInterfaceProperty(
- const std::string& prop)
-{
- if (cmHasLiteralPrefix(prop, "INTERFACE_")) {
- return true;
- }
- if (cmHasLiteralPrefix(prop, "_")) {
- return true;
- }
- if (std::islower(prop[0])) {
- return true;
- }
- static std::unordered_set<std::string> const builtIns{
- "COMPATIBLE_INTERFACE_BOOL",
- "COMPATIBLE_INTERFACE_NUMBER_MAX",
- "COMPATIBLE_INTERFACE_NUMBER_MIN",
- "COMPATIBLE_INTERFACE_STRING",
- "DEPRECATION",
- "EXPORT_NAME",
- "EXPORT_PROPERTIES",
- "IMPORTED",
- "IMPORTED_GLOBAL",
- "MANUALLY_ADDED_DEPENDENCIES",
- "NAME",
- "PRIVATE_HEADER",
- "PUBLIC_HEADER",
- "TYPE"
- };
-
- if (builtIns.count(prop)) {
- return true;
- }
-
- if (prop == "IMPORTED_CONFIGURATIONS" || prop == "IMPORTED_LIBNAME" ||
- cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME_") ||
- cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_")) {
- return true;
- }
-
- // This property should not be allowed but was incorrectly added in
- // CMake 3.8. We can't remove it from the whitelist without breaking
- // projects that try to set it. One day we could warn about this, but
- // for now silently accept it.
- if (prop == "NO_SYSTEM_FROM_IMPORTED") {
- return true;
- }
-
- return false;
-}
-
-bool cmTargetPropertyComputer::PassesWhitelist(
- cmStateEnums::TargetType tgtType, std::string const& prop,
- cmMessenger* messenger, cmListFileBacktrace const& context)
-{
- if (tgtType == cmStateEnums::INTERFACE_LIBRARY &&
- !WhiteListedInterfaceProperty(prop)) {
- std::ostringstream e;
- e << "INTERFACE_LIBRARY targets may only have whitelisted properties. "
- "The property \""
- << prop << "\" is not allowed.";
- messenger->IssueMessage(MessageType::FATAL_ERROR, e.str(), context);
- return false;
- }
- return true;
-}
diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
index f87b7c2..bafa43b 100644
--- a/Source/cmTargetPropertyComputer.h
+++ b/Source/cmTargetPropertyComputer.h
@@ -35,12 +35,6 @@ public:
return nullptr;
}
- static bool WhiteListedInterfaceProperty(const std::string& prop);
-
- static bool PassesWhitelist(cmStateEnums::TargetType tgtType,
- std::string const& prop, cmMessenger* messenger,
- cmListFileBacktrace const& context);
-
private:
static bool HandleLocationPropertyPolicy(std::string const& tgtName,
cmMessenger* messenger,
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index af91177..da4593f 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -2,8 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTestGenerator.h"
+#include <algorithm>
+#include <cstddef> // IWYU pragma: keep
+#include <iterator>
#include <memory>
#include <ostream>
+#include <string>
#include <utility>
#include <vector>
@@ -11,7 +15,10 @@
#include "cmGeneratorTarget.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmOutputConverter.h"
+#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmPropertyMap.h"
#include "cmRange.h"
@@ -20,6 +27,52 @@
#include "cmSystemTools.h"
#include "cmTest.h"
+namespace /* anonymous */
+{
+
+bool needToQuoteTestName(const cmMakefile& mf, const std::string& name)
+{
+ // Determine if policy CMP0110 is set to NEW.
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0110)) {
+ case cmPolicies::WARN:
+ // Only warn if a forbidden character is used in the name.
+ if (name.find_first_of("$[] #;\t\n\"\\") != std::string::npos) {
+ mf.IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0110),
+ "\nThe following name given to add_test() is invalid if "
+ "CMP0110 is not set or set to OLD:\n `",
+ name, "´\n"));
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to not quote the test's name.
+ return false;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ default:
+ // NEW behavior is to quote the test's name.
+ return true;
+ }
+}
+
+std::size_t countMaxConsecutiveEqualSigns(const std::string& name)
+{
+ std::size_t max = 0;
+ auto startIt = find(name.begin(), name.end(), '=');
+ auto endIt = startIt;
+ for (; startIt != name.end(); startIt = find(endIt, name.end(), '=')) {
+ endIt =
+ find_if_not(startIt + 1, name.end(), [](char c) { return c == '='; });
+ max =
+ std::max(max, static_cast<std::size_t>(std::distance(startIt, endIt)));
+ }
+ return max;
+}
+
+} // End: anonymous namespace
+
cmTestGenerator::cmTestGenerator(
cmTest* test, std::vector<std::string> const& configurations)
: cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations)
@@ -76,8 +129,21 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
// Set up generator expression evaluation context.
cmGeneratorExpression ge(this->Test->GetBacktrace());
+ // Determine if policy CMP0110 is set to NEW.
+ const bool quote_test_name =
+ needToQuoteTestName(*this->Test->GetMakefile(), this->Test->GetName());
+ // Determine the number of equal-signs needed for quoting test name with
+ // [==[...]==] syntax.
+ const std::string equalSigns(
+ 1 + countMaxConsecutiveEqualSigns(this->Test->GetName()), '=');
+
// Start the test command.
- os << indent << "add_test(" << this->Test->GetName() << " ";
+ if (quote_test_name) {
+ os << indent << "add_test([" << equalSigns << "[" << this->Test->GetName()
+ << "]" << equalSigns << "] ";
+ } else {
+ os << indent << "add_test(" << this->Test->GetName() << " ";
+ }
// Evaluate command line arguments
std::vector<std::string> argv =
@@ -102,7 +168,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
// Prepend with the emulator when cross compiling if required.
cmProp emulator = target->GetProperty("CROSSCOMPILING_EMULATOR");
- if (emulator != nullptr && !emulator->empty()) {
+ if (cmNonempty(emulator)) {
std::vector<std::string> emulatorWithArgs = cmExpandedList(*emulator);
std::string emulatorExe(emulatorWithArgs[0]);
cmSystemTools::ConvertToUnixSlashes(emulatorExe);
@@ -127,8 +193,13 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
os << ")\n";
// Output properties for the test.
- os << indent << "set_tests_properties(" << this->Test->GetName()
- << " PROPERTIES ";
+ if (quote_test_name) {
+ os << indent << "set_tests_properties([" << equalSigns << "["
+ << this->Test->GetName() << "]" << equalSigns << "] PROPERTIES ";
+ } else {
+ os << indent << "set_tests_properties(" << this->Test->GetName()
+ << " PROPERTIES ";
+ }
for (auto const& i : this->Test->GetProperties().GetList()) {
os << " " << i.first << " "
<< cmOutputConverter::EscapeForCMake(
@@ -140,7 +211,21 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent)
{
- os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n";
+ // Determine if policy CMP0110 is set to NEW.
+ const bool quote_test_name =
+ needToQuoteTestName(*this->Test->GetMakefile(), this->Test->GetName());
+ // Determine the number of equal-signs needed for quoting test name with
+ // [==[...]==] syntax.
+ const std::string equalSigns(
+ 1 + countMaxConsecutiveEqualSigns(this->Test->GetName()), '=');
+
+ if (quote_test_name) {
+ os << indent << "add_test([" << equalSigns << "[" << this->Test->GetName()
+ << "]" << equalSigns << "] NOT_AVAILABLE)\n";
+ } else {
+ os << indent << "add_test(" << this->Test->GetName()
+ << " NOT_AVAILABLE)\n";
+ }
}
bool cmTestGenerator::NeedsScriptNoConfig() const
@@ -155,14 +240,27 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent)
{
this->TestGenerated = true;
+ // Determine if policy CMP0110 is set to NEW.
+ const bool quote_test_name =
+ needToQuoteTestName(*this->Test->GetMakefile(), this->Test->GetName());
+ // Determine the number of equal-signs needed for quoting test name with
+ // [==[...]==] syntax.
+ const std::string equalSigns(
+ 1 + countMaxConsecutiveEqualSigns(this->Test->GetName()), '=');
+
// Get the test command line to be executed.
std::vector<std::string> const& command = this->Test->GetCommand();
std::string exe = command[0];
cmSystemTools::ConvertToUnixSlashes(exe);
- fout << indent;
- fout << "add_test(";
- fout << this->Test->GetName() << " \"" << exe << "\"";
+ if (quote_test_name) {
+ fout << indent << "add_test([" << equalSigns << "["
+ << this->Test->GetName() << "]" << equalSigns << "] \"" << exe
+ << "\"";
+ } else {
+ fout << indent << "add_test(" << this->Test->GetName() << " \"" << exe
+ << "\"";
+ }
for (std::string const& arg : cmMakeRange(command).advance(1)) {
// Just double-quote all arguments so they are re-parsed
@@ -182,8 +280,13 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent)
fout << ")\n";
// Output properties for the test.
- fout << indent << "set_tests_properties(" << this->Test->GetName()
- << " PROPERTIES ";
+ if (quote_test_name) {
+ fout << indent << "set_tests_properties([" << equalSigns << "["
+ << this->Test->GetName() << "]" << equalSigns << "] PROPERTIES ";
+ } else {
+ fout << indent << "set_tests_properties(" << this->Test->GetName()
+ << " PROPERTIES ";
+ }
for (auto const& i : this->Test->GetProperties().GetList()) {
fout << " " << i.first << " "
<< cmOutputConverter::EscapeForCMake(i.second);
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 13f73dc..bd6bb3d 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -164,7 +164,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
break;
case 's': // Seconds since UNIX epoch (midnight 1-jan-1970)
{
- // Build a time_t for UNIX epoch and substract from the input "timeT":
+ // Build a time_t for UNIX epoch and subtract from the input "timeT":
struct tm tmUnixEpoch;
memset(&tmUnixEpoch, 0, sizeof(tmUnixEpoch));
tmUnixEpoch.tm_mday = 1;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index a8e424d..db9dc53 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -232,15 +232,17 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
, LocalGenerator(
(cmLocalVisualStudio10Generator*)target->GetLocalGenerator())
{
- this->Makefile->GetConfigurations(this->Configurations);
+ this->Configurations =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
this->NsightTegra = gg->IsNsightTegra();
+ this->Android = gg->TargetsAndroid();
for (int i = 0; i < 4; ++i) {
this->NsightTegraVersion[i] = 0;
}
sscanf(gg->GetNsightTegraVersion().c_str(), "%u.%u.%u.%u",
&this->NsightTegraVersion[0], &this->NsightTegraVersion[1],
&this->NsightTegraVersion[2], &this->NsightTegraVersion[3]);
- this->MSTools = !this->NsightTegra;
+ this->MSTools = !this->NsightTegra && !this->Android;
this->Managed = false;
this->TargetCompileAsWinRT = false;
this->IsMissingFiles = false;
@@ -313,8 +315,7 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
void cmVisualStudio10TargetGenerator::Generate()
{
// do not generate external ms projects
- if (this->GeneratorTarget->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
- this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) {
+ if (this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) {
return;
}
const std::string ProjectFileExtension =
@@ -333,6 +334,13 @@ void cmVisualStudio10TargetGenerator::Generate()
this->ProjectType = csproj;
this->Managed = true;
}
+
+ if (this->Android &&
+ this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
+ !this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
+ this->GlobalGenerator->AddAndroidExecutableWarning(this->Name);
+ }
+
// Tell the global generator the name of the project file
this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME",
this->Name);
@@ -427,8 +435,8 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Attribute("Label", "Globals");
e1.Element("ProjectGuid", "{" + this->GUID + "}");
- if (this->MSTools &&
- this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
+ if ((this->MSTools || this->Android) &&
+ this->GeneratorTarget->IsInBuildSystem()) {
this->WriteApplicationTypeSettings(e1);
this->VerifyNecessaryFiles();
}
@@ -469,7 +477,11 @@ void cmVisualStudio10TargetGenerator::Generate()
cmProp vsGlobalKeyword =
this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
if (!vsGlobalKeyword) {
- e1.Element("Keyword", "Win32Proj");
+ if (this->GlobalGenerator->TargetsAndroid()) {
+ e1.Element("Keyword", "Android");
+ } else {
+ e1.Element("Keyword", "Win32Proj");
+ }
} else {
e1.Element("Keyword", *vsGlobalKeyword);
}
@@ -592,11 +604,11 @@ void cmVisualStudio10TargetGenerator::Generate()
}
break;
case cmStateEnums::UTILITY:
+ case cmStateEnums::INTERFACE_LIBRARY:
case cmStateEnums::GLOBAL_TARGET:
outputType = "Utility";
break;
case cmStateEnums::UNKNOWN_LIBRARY:
- case cmStateEnums::INTERFACE_LIBRARY:
break;
}
e1.Element("OutputType", outputType);
@@ -658,7 +670,7 @@ void cmVisualStudio10TargetGenerator::Generate()
cmStrCat(this->DefaultArtifactDir, "\\nasm.props");
ConvertToWindowsSlash(propsLocal);
this->Makefile->ConfigureFile(propsTemplate, propsLocal, false, true,
- true);
+ true, true);
Elem(e1, "Import").Attribute("Project", propsLocal);
}
}
@@ -1134,14 +1146,17 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
break;
case cmStateEnums::EXECUTABLE:
if (this->NsightTegra &&
- !this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
+ !this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
// Android executables are .so too.
configType = "DynamicLibrary";
+ } else if (this->Android) {
+ configType = "DynamicLibrary";
} else {
configType = "Application";
}
break;
case cmStateEnums::UTILITY:
+ case cmStateEnums::INTERFACE_LIBRARY:
case cmStateEnums::GLOBAL_TARGET:
if (this->NsightTegra) {
// Tegra-Android platform does not understand "Utility".
@@ -1151,7 +1166,6 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
}
break;
case cmStateEnums::UNKNOWN_LIBRARY:
- case cmStateEnums::INTERFACE_LIBRARY:
break;
}
}
@@ -1166,6 +1180,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
}
} else if (this->NsightTegra) {
this->WriteNsightTegraConfigurationValues(e1, c);
+ } else if (this->Android) {
+ this->WriteAndroidConfigurationValues(e1, c);
}
}
}
@@ -1324,6 +1340,24 @@ void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
}
}
+void cmVisualStudio10TargetGenerator::WriteAndroidConfigurationValues(
+ Elem& e1, std::string const&)
+{
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ if (cmProp projectToolsetOverride =
+ this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
+ e1.Element("PlatformToolset", *projectToolsetOverride);
+ } else if (const char* toolset = gg->GetPlatformToolset()) {
+ e1.Element("PlatformToolset", toolset);
+ }
+ if (cmProp stlType =
+ this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
+ if (*stlType != "none") {
+ e1.Element("UseOfStl", *stlType);
+ }
+ }
+}
+
void cmVisualStudio10TargetGenerator::WriteCustomCommands(Elem& e0)
{
this->CSharpCustomCommandNames.clear();
@@ -1941,7 +1975,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
cmProp toolOverride = sf->GetProperty("VS_TOOL_OVERRIDE");
- if (toolOverride && !toolOverride->empty()) {
+ if (cmNonempty(toolOverride)) {
tool = toolOverride->c_str();
}
@@ -1950,12 +1984,12 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
if (this->GlobalGenerator->TargetsWindowsPhone() ||
this->GlobalGenerator->TargetsWindowsStore()) {
cmProp content = sf->GetProperty("VS_DEPLOYMENT_CONTENT");
- if (content && !content->empty()) {
+ if (cmNonempty(content)) {
toolHasSettings = true;
deployContent = *content;
cmProp location = sf->GetProperty("VS_DEPLOYMENT_LOCATION");
- if (location && !location->empty()) {
+ if (cmNonempty(location)) {
deployLocation = *location;
}
}
@@ -2117,7 +2151,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
{
- if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
+ if (this->GeneratorTarget->GetType() == cmStateEnums::GLOBAL_TARGET) {
return;
}
@@ -2258,7 +2292,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
e2.Attribute("UnityFilesDirectory", unityDir);
} else {
// Visual Studio versions prior to 2017 15.8 do not know about unity
- // builds, thus we exclude the files alredy part of unity sources.
+ // builds, thus we exclude the files already part of unity sources.
if (!si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")) {
exclude_configs = si.Configs;
}
@@ -2915,7 +2949,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
}
}
- if (this->MSTools) {
+ if (this->Android) {
+ e2.Element("ObjectFileName", "$(IntDir)%(filename).o");
+ } else if (this->MSTools) {
cmsys::RegularExpression clangToolset("v[0-9]+_clang_.*");
const char* toolset = this->GlobalGenerator->GetPlatformToolset();
if (toolset && clangToolset.find(toolset)) {
@@ -4021,8 +4057,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0)
// output manifest flags <Manifest></Manifest>
this->WriteManifestOptions(e1, c);
if (this->NsightTegra &&
- this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
- this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
+ this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
this->WriteAntBuildOptions(e1, c);
}
}
@@ -4108,7 +4143,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
Elem e1(e0, "ItemGroup");
e1.SetHasElements();
for (cmGeneratorTarget const* dt : depends) {
- if (dt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (!dt->IsInBuildSystem()) {
continue;
}
// skip fortran targets as they can not be processed by MSBuild
@@ -4137,8 +4172,9 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
}
// Don't reference targets that don't produce any output.
- if (dt->GetManagedType(this->Configurations[0]) ==
- cmGeneratorTarget::ManagedType::Undefined) {
+ if (this->Configurations.empty() ||
+ dt->GetManagedType(this->Configurations[0]) ==
+ cmGeneratorTarget::ManagedType::Undefined) {
e2.Element("ReferenceOutputAssembly", "false");
e2.Element("CopyToOutputDirectory", "Never");
}
@@ -4354,6 +4390,7 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1)
bool isAppContainer = false;
bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
+ bool const isAndroid = this->GlobalGenerator->TargetsAndroid();
std::string const& rev = this->GlobalGenerator->GetApplicationTypeRevision();
if (isWindowsPhone || isWindowsStore) {
e1.Element("ApplicationType",
@@ -4391,13 +4428,19 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1)
this->Name + "_$(Configuration)_$(Platform).xap");
}
}
+ } else if (isAndroid) {
+ e1.Element("ApplicationType", "Android");
+ e1.Element("ApplicationTypeRevision",
+ gg->GetAndroidApplicationTypeRevision());
}
if (isAppContainer) {
e1.Element("AppContainerApplication", "true");
- } else if (this->Platform == "ARM64") {
- e1.Element("WindowsSDKDesktopARM64Support", "true");
- } else if (this->Platform == "ARM") {
- e1.Element("WindowsSDKDesktopARMSupport", "true");
+ } else if (!isAndroid) {
+ if (this->Platform == "ARM64") {
+ e1.Element("WindowsSDKDesktopARM64Support", "true");
+ } else if (this->Platform == "ARM") {
+ e1.Element("WindowsSDKDesktopARMSupport", "true");
+ }
}
std::string const& targetPlatformVersion =
gg->GetWindowsTargetPlatformVersion();
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 7c71de3..c54057a 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -70,6 +70,7 @@ private:
void WriteExtraSource(Elem& e1, cmSourceFile const* sf);
void WriteNsightTegraConfigurationValues(Elem& e1,
std::string const& config);
+ void WriteAndroidConfigurationValues(Elem& e1, std::string const& config);
void WriteSource(Elem& e2, cmSourceFile const* sf);
void WriteExcludeFromBuild(Elem& e2,
std::vector<size_t> const& exclude_configs);
@@ -215,6 +216,7 @@ private:
bool MSTools;
bool Managed;
bool NsightTegra;
+ bool Android;
unsigned int NsightTegraVersion[4];
bool TargetCompileAsWinRT;
std::set<std::string> IPOEnabledConfigurations;
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
index f4c2f2d..55e941d 100644
--- a/Source/cmXCodeScheme.cxx
+++ b/Source/cmXCodeScheme.cxx
@@ -33,7 +33,7 @@ void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir,
// Create shared scheme sub-directory tree
//
std::string xcodeSchemeDir = cmStrCat(xcProjDir, "/xcshareddata/xcschemes");
- cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str());
+ cmSystemTools::MakeDirectory(xcodeSchemeDir);
std::string xcodeSchemeFile =
cmStrCat(xcodeSchemeDir, '/', this->TargetName, ".xcscheme");
@@ -324,8 +324,7 @@ bool cmXCodeScheme::WriteLaunchActionBooleanAttribute(
bool defaultValue)
{
cmProp property = Target->GetTarget()->GetProperty(varName);
- bool isOn =
- (property == nullptr && defaultValue) || (property && cmIsOn(*property));
+ bool isOn = (property == nullptr && defaultValue) || cmIsOn(property);
if (isOn) {
xout.Attribute(attrName.c_str(), "YES");
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 162e807..f630a7e 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -64,10 +64,6 @@
# include "cmVariableWatch.h"
#endif
-#if !defined(CMAKE_BOOTSTRAP)
-# define CMAKE_USE_ECLIPSE
-#endif
-
#if defined(__MINGW32__) && defined(CMAKE_BOOTSTRAP)
# define CMAKE_BOOT_MINGW
#endif
@@ -97,20 +93,21 @@
#if defined(CMAKE_USE_WMAKE)
# include "cmGlobalWatcomWMakeGenerator.h"
#endif
-#include "cmGlobalUnixMakefileGenerator3.h"
#if !defined(CMAKE_BOOTSTRAP)
# include "cmGlobalNinjaGenerator.h"
+# include "cmGlobalUnixMakefileGenerator3.h"
+#elif defined(CMAKE_BOOTSTRAP_MAKEFILES)
+# include "cmGlobalUnixMakefileGenerator3.h"
+#elif defined(CMAKE_BOOTSTRAP_NINJA)
+# include "cmGlobalNinjaGenerator.h"
#endif
-#include "cmExtraCodeLiteGenerator.h"
-#if !defined(CMAKE_BOOT_MINGW)
+#if !defined(CMAKE_BOOTSTRAP)
# include "cmExtraCodeBlocksGenerator.h"
-#endif
-#include "cmExtraKateGenerator.h"
-#include "cmExtraSublimeTextGenerator.h"
-
-#ifdef CMAKE_USE_ECLIPSE
+# include "cmExtraCodeLiteGenerator.h"
# include "cmExtraEclipseCDT4Generator.h"
+# include "cmExtraKateGenerator.h"
+# include "cmExtraSublimeTextGenerator.h"
#endif
#if defined(__linux__) || defined(_WIN32)
@@ -201,7 +198,7 @@ cmake::cmake(Role role, cmState::Mode mode)
};
// The "c" extension MUST precede the "C" extension.
- setupExts(this->SourceFileExtensions,
+ setupExts(this->CLikeSourceFileExtensions,
{ "c", "C", "c++", "cc", "cpp", "cxx", "cu", "m", "M", "mm" });
setupExts(this->HeaderFileExtensions,
{ "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" });
@@ -780,8 +777,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
std::cout << "Warn about uninitialized values.\n";
this->SetWarnUninitialized(true);
} else if (cmHasLiteralPrefix(arg, "--warn-unused-vars")) {
- std::cout << "Finding unused variables.\n";
- this->SetWarnUnused(true);
+ // Option was removed.
} else if (cmHasLiteralPrefix(arg, "--no-warn-unused-cli")) {
std::cout << "Not searching for unused variables given on the "
<< "command line.\n";
@@ -1137,13 +1133,9 @@ void cmake::AddDefaultExtraGenerators()
#if !defined(CMAKE_BOOTSTRAP)
this->ExtraGenerators.push_back(cmExtraCodeBlocksGenerator::GetFactory());
this->ExtraGenerators.push_back(cmExtraCodeLiteGenerator::GetFactory());
- this->ExtraGenerators.push_back(cmExtraSublimeTextGenerator::GetFactory());
- this->ExtraGenerators.push_back(cmExtraKateGenerator::GetFactory());
-
-# ifdef CMAKE_USE_ECLIPSE
this->ExtraGenerators.push_back(cmExtraEclipseCDT4Generator::GetFactory());
-# endif
-
+ this->ExtraGenerators.push_back(cmExtraKateGenerator::GetFactory());
+ this->ExtraGenerators.push_back(cmExtraSublimeTextGenerator::GetFactory());
#endif
}
@@ -1383,7 +1375,7 @@ struct SaveCacheEntry
int cmake::HandleDeleteCacheVariables(const std::string& var)
{
- std::vector<std::string> argsSplit = cmExpandedList(std::string(var), true);
+ 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()) {
@@ -1402,8 +1394,13 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
save.key = *i;
warning << *i << "= ";
i++;
- save.value = *i;
- warning << *i << "\n";
+ if (i != argsSplit.end()) {
+ save.value = *i;
+ warning << *i << "\n";
+ } else {
+ warning << "\n";
+ i -= 1;
+ }
cmProp existingValue = this->State->GetCacheEntryValue(save.key);
if (existingValue) {
save.type = this->State->GetCacheEntryType(save.key);
@@ -1499,10 +1496,10 @@ int cmake::Configure()
this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(*value));
value = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
- this->Messenger->SetDeprecatedWarningsAsErrors(value && cmIsOn(*value));
+ this->Messenger->SetDeprecatedWarningsAsErrors(cmIsOn(value));
value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
- this->Messenger->SetSuppressDevWarnings(value && cmIsOn(*value));
+ this->Messenger->SetSuppressDevWarnings(cmIsOn(value));
value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS");
this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(*value));
@@ -1757,6 +1754,9 @@ std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator()
gen = cm::make_unique<cmGlobalNMakeMakefileGenerator>(this);
}
return std::unique_ptr<cmGlobalGenerator>(std::move(gen));
+#elif defined(CMAKE_BOOTSTRAP_NINJA)
+ return std::unique_ptr<cmGlobalGenerator>(
+ cm::make_unique<cmGlobalNinjaGenerator>(this));
#else
return std::unique_ptr<cmGlobalGenerator>(
cm::make_unique<cmGlobalUnixMakefileGenerator3>(this));
@@ -1970,6 +1970,17 @@ void cmake::AddGlobCacheEntry(bool recurse, bool listDirectories,
backtrace);
}
+std::vector<std::string> cmake::GetAllExtensions() const
+{
+ std::vector<std::string> allExt = this->CLikeSourceFileExtensions.ordered;
+ allExt.insert(allExt.end(), this->HeaderFileExtensions.ordered.begin(),
+ this->HeaderFileExtensions.ordered.end());
+ // cuda extensions are also in SourceFileExtensions so we ignore it here
+ allExt.insert(allExt.end(), this->FortranFileExtensions.ordered.begin(),
+ this->FortranFileExtensions.ordered.end());
+ return allExt;
+}
+
std::string cmake::StripExtension(const std::string& file) const
{
auto dotpos = file.rfind('.');
@@ -1979,7 +1990,7 @@ std::string cmake::StripExtension(const std::string& file) const
#else
auto ext = cm::string_view(file).substr(dotpos + 1);
#endif
- if (this->IsSourceExtension(ext) || this->IsHeaderExtension(ext)) {
+ if (this->IsAKnownExtension(ext)) {
return file.substr(0, dotpos);
}
}
@@ -2022,13 +2033,17 @@ void cmake::AddDefaultGenerators()
this->Generators.push_back(cmGlobalMSYSMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalMinGWMakefileGenerator::NewFactory());
#endif
- this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory());
#if !defined(CMAKE_BOOTSTRAP)
# if defined(__linux__) || defined(_WIN32)
this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory());
# endif
+ this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory());
this->Generators.push_back(cmGlobalNinjaGenerator::NewFactory());
this->Generators.push_back(cmGlobalNinjaMultiGenerator::NewFactory());
+#elif defined(CMAKE_BOOTSTRAP_NINJA)
+ this->Generators.push_back(cmGlobalNinjaGenerator::NewFactory());
+#elif defined(CMAKE_BOOTSTRAP_MAKEFILES)
+ this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory());
#endif
#if defined(CMAKE_USE_WMAKE)
this->Generators.push_back(cmGlobalWatcomWMakeGenerator::NewFactory());
@@ -2269,7 +2284,7 @@ int cmake::CheckBuildSystem()
if (this->ClearBuildSystem) {
// Get the generator used for this build system.
const char* genName = mf.GetDefinition("CMAKE_DEPENDS_GENERATOR");
- if (!genName || genName[0] == '\0') {
+ if (!cmNonempty(genName)) {
genName = "Unix Makefiles";
}
@@ -2743,9 +2758,7 @@ int cmake::Build(int jobs, const std::string& dir,
}
projName = *cachedProjectName;
- cmProp cachedVerbose =
- this->State->GetCacheEntryValue("CMAKE_VERBOSE_MAKEFILE");
- if (cachedVerbose && cmIsOn(*cachedVerbose)) {
+ if (cmIsOn(this->State->GetCacheEntryValue("CMAKE_VERBOSE_MAKEFILE"))) {
verbose = true;
}
diff --git a/Source/cmake.h b/Source/cmake.h
index 086ec87..0c4f429 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -264,44 +264,33 @@ public:
this->GeneratorToolsetSet = true;
}
- const std::vector<std::string>& GetSourceExtensions() const
+ bool IsAKnownSourceExtension(cm::string_view ext) const
{
- return this->SourceFileExtensions.ordered;
+ return this->CLikeSourceFileExtensions.Test(ext) ||
+ this->CudaFileExtensions.Test(ext) ||
+ this->FortranFileExtensions.Test(ext);
}
- bool IsSourceExtension(cm::string_view ext) const
+ bool IsACLikeSourceExtension(cm::string_view ext) const
{
- return this->SourceFileExtensions.Test(ext);
+ return this->CLikeSourceFileExtensions.Test(ext);
}
- const std::vector<std::string>& GetHeaderExtensions() const
- {
- return this->HeaderFileExtensions.ordered;
- }
-
- bool IsHeaderExtension(cm::string_view ext) const
- {
- return this->HeaderFileExtensions.Test(ext);
- }
-
- const std::vector<std::string>& GetCudaExtensions() const
+ bool IsAKnownExtension(cm::string_view ext) const
{
- return this->CudaFileExtensions.ordered;
+ return this->IsAKnownSourceExtension(ext) || this->IsAHeaderExtension(ext);
}
- bool IsCudaExtension(cm::string_view ext) const
- {
- return this->CudaFileExtensions.Test(ext);
- }
+ std::vector<std::string> GetAllExtensions() const;
- const std::vector<std::string>& GetFortranExtensions() const
+ const std::vector<std::string>& GetHeaderExtensions() const
{
- return this->FortranFileExtensions.ordered;
+ return this->HeaderFileExtensions.ordered;
}
- bool IsFortranExtension(cm::string_view ext) const
+ bool IsAHeaderExtension(cm::string_view ext) const
{
- return this->FortranFileExtensions.Test(ext);
+ return this->HeaderFileExtensions.Test(ext);
}
// Strips the extension (if present and known) from a filename
@@ -461,8 +450,6 @@ public:
bool GetWarnUninitialized() { return this->WarnUninitialized; }
void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; }
- bool GetWarnUnused() { return this->WarnUnused; }
- void SetWarnUnused(bool b) { this->WarnUnused = b; }
bool GetWarnUnusedCli() { return this->WarnUnusedCli; }
void SetWarnUnusedCli(bool b) { this->WarnUnusedCli = b; }
bool GetCheckSystemVars() { return this->CheckSystemVars; }
@@ -616,7 +603,6 @@ private:
TraceFormat TraceFormatVar = TRACE_HUMAN;
cmGeneratedFileStream TraceFile;
bool WarnUninitialized = false;
- bool WarnUnused = false;
bool WarnUnusedCli = true;
bool CheckSystemVars = false;
std::map<std::string, bool> UsedCliVariables;
@@ -628,7 +614,7 @@ private:
std::string CheckStampList;
std::string VSSolutionFile;
std::string EnvironmentGenerator;
- FileExtensions SourceFileExtensions;
+ FileExtensions CLikeSourceFileExtensions;
FileExtensions HeaderFileExtensions;
FileExtensions CudaFileExtensions;
FileExtensions FortranFileExtensions;
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index d662a9a..4600fc5 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -3,11 +3,13 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cstring>
#include <iostream>
+#include <sstream>
#include <string>
#include <vector>
@@ -69,7 +71,7 @@ const char* cmDocumentationOptions[][2] = {
{ "--open <dir>", "Open generated project in the associated application." },
{ "-N", "View mode only." },
{ "-P <file>", "Process script mode." },
- { "--find-package", "Run in pkg-config like mode." },
+ { "--find-package", "Legacy pkg-config like mode. Do not use." },
{ "--graphviz=[file]",
"Generate graphviz of dependencies, see "
"CMakeGraphVizOptions.cmake for more." },
@@ -91,7 +93,6 @@ const char* cmDocumentationOptions[][2] = {
{ "--trace-redirect=<file>",
"Redirect trace output to a file instead of stderr." },
{ "--warn-uninitialized", "Warn about uninitialized values." },
- { "--warn-unused-vars", "Warn about unused variables." },
{ "--no-warn-unused-cli", "Don't warn about command line options." },
{ "--check-system-vars",
"Find problems with variable usage in system "
@@ -519,6 +520,121 @@ int do_build(int ac, char const* const* av)
#endif
}
+bool parse_default_directory_permissions(const std::string& permissions,
+ std::string& parsedPermissionsVar)
+{
+ std::vector<std::string> parsedPermissions;
+ enum Doing
+ {
+ DoingNone,
+ DoingOwner,
+ DoingGroup,
+ DoingWorld,
+ DoingOwnerAssignment,
+ DoingGroupAssignment,
+ DoingWorldAssignment,
+ };
+ Doing doing = DoingNone;
+
+ auto uniquePushBack = [&parsedPermissions](const std::string& e) {
+ if (std::find(parsedPermissions.begin(), parsedPermissions.end(), e) ==
+ parsedPermissions.end()) {
+ parsedPermissions.push_back(e);
+ }
+ };
+
+ for (auto const& e : permissions) {
+ switch (doing) {
+ case DoingNone:
+ if (e == 'u') {
+ doing = DoingOwner;
+ } else if (e == 'g') {
+ doing = DoingGroup;
+ } else if (e == 'o') {
+ doing = DoingWorld;
+ } else {
+ return false;
+ }
+ break;
+ case DoingOwner:
+ if (e == '=') {
+ doing = DoingOwnerAssignment;
+ } else {
+ return false;
+ }
+ break;
+ case DoingGroup:
+ if (e == '=') {
+ doing = DoingGroupAssignment;
+ } else {
+ return false;
+ }
+ break;
+ case DoingWorld:
+ if (e == '=') {
+ doing = DoingWorldAssignment;
+ } else {
+ return false;
+ }
+ break;
+ case DoingOwnerAssignment:
+ if (e == 'r') {
+ uniquePushBack("OWNER_READ");
+ } else if (e == 'w') {
+ uniquePushBack("OWNER_WRITE");
+ } else if (e == 'x') {
+ uniquePushBack("OWNER_EXECUTE");
+ } else if (e == ',') {
+ doing = DoingNone;
+ } else {
+ return false;
+ }
+ break;
+ case DoingGroupAssignment:
+ if (e == 'r') {
+ uniquePushBack("GROUP_READ");
+ } else if (e == 'w') {
+ uniquePushBack("GROUP_WRITE");
+ } else if (e == 'x') {
+ uniquePushBack("GROUP_EXECUTE");
+ } else if (e == ',') {
+ doing = DoingNone;
+ } else {
+ return false;
+ }
+ break;
+ case DoingWorldAssignment:
+ if (e == 'r') {
+ uniquePushBack("WORLD_READ");
+ } else if (e == 'w') {
+ uniquePushBack("WORLD_WRITE");
+ } else if (e == 'x') {
+ uniquePushBack("WORLD_EXECUTE");
+ } else if (e == ',') {
+ doing = DoingNone;
+ } else {
+ return false;
+ }
+ break;
+ }
+ }
+ if (doing != DoingOwnerAssignment && doing != DoingGroupAssignment &&
+ doing != DoingWorldAssignment) {
+ return false;
+ }
+
+ std::ostringstream oss;
+ for (auto i = 0u; i < parsedPermissions.size(); i++) {
+ if (i != 0) {
+ oss << ";";
+ }
+ oss << parsedPermissions[i];
+ }
+
+ parsedPermissionsVar = oss.str();
+ return true;
+}
+
int do_install(int ac, char const* const* av)
{
#ifdef CMAKE_BOOTSTRAP
@@ -529,6 +645,7 @@ int do_install(int ac, char const* const* av)
std::string config;
std::string component;
+ std::string defaultDirectoryPermissions;
std::string prefix;
std::string dir;
bool strip = false;
@@ -541,6 +658,7 @@ int do_install(int ac, char const* const* av)
DoingConfig,
DoingComponent,
DoingPrefix,
+ DoingDefaultDirectoryPermissions,
};
Doing doing = DoingDir;
@@ -559,6 +677,8 @@ int do_install(int ac, char const* const* av)
(strcmp(av[i], "-v") == 0)) {
verbose = true;
doing = DoingNone;
+ } else if (strcmp(av[i], "--default-directory-permissions") == 0) {
+ doing = DoingDefaultDirectoryPermissions;
} else {
switch (doing) {
case DoingDir:
@@ -577,6 +697,10 @@ int do_install(int ac, char const* const* av)
prefix = av[i];
doing = DoingNone;
break;
+ case DoingDefaultDirectoryPermissions:
+ defaultDirectoryPermissions = av[i];
+ doing = DoingNone;
+ break;
default:
std::cerr << "Unknown argument " << av[i] << std::endl;
dir.clear();
@@ -593,6 +717,8 @@ int do_install(int ac, char const* const* av)
" <dir> = Project binary directory to install.\n"
" --config <cfg> = For multi-configuration tools, choose <cfg>.\n"
" --component <comp> = Component-based install. Only install <comp>.\n"
+ " --default-directory-permissions <permission> \n"
+ " Default install permission. Use default permission <permission>.\n"
" --prefix <prefix> = The installation prefix CMAKE_INSTALL_PREFIX.\n"
" --strip = Performing install/strip.\n"
" -v --verbose = Enable verbose output.\n"
@@ -633,6 +759,18 @@ int do_install(int ac, char const* const* av)
args.emplace_back("-DCMAKE_INSTALL_CONFIG_NAME=" + config);
}
+ if (!defaultDirectoryPermissions.empty()) {
+ std::string parsedPermissionsVar;
+ if (!parse_default_directory_permissions(defaultDirectoryPermissions,
+ parsedPermissionsVar)) {
+ std::cerr << "--default-directory-permissions is in incorrect format"
+ << std::endl;
+ return 1;
+ }
+ args.emplace_back("-DCMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS=" +
+ parsedPermissionsVar);
+ }
+
args.emplace_back("-P");
args.emplace_back(dir + "/cmake_install.cmake");
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index de76d73..15d2fd1 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -126,6 +126,7 @@ void CMakeCommandUsage(const char* program)
<< " touch <file>... - touch a <file>.\n"
<< " touch_nocreate <file>... - touch a <file> but do not create it.\n"
<< " create_symlink old new - create a symbolic link new -> old\n"
+ << " create_hardlink old new - create a hard link new -> old\n"
<< " true - do nothing with an exit code of 0\n"
<< " false - do nothing with an exit code of 1\n"
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -582,12 +583,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
filesDiffer = cmsys::SystemTools::TextFilesDiffer(args[3], args[4]);
} else {
::CMakeCommandUsage(args[0].c_str());
- return 1;
+ return 2;
}
if (filesDiffer) {
- std::cerr << "Files \"" << args[args.size() - 2] << "\" to \""
- << args[args.size() - 1] << "\" are different.\n";
return 1;
}
return 0;
@@ -602,8 +601,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
}
cmsys::ifstream fin(args[3].c_str(), std::ios::in | std::ios::binary);
if (!fin) {
- std::cerr << "could not open object list file: " << args[3].c_str()
- << "\n";
+ std::cerr << "could not open object list file: " << args[3] << "\n";
return 1;
}
std::vector<std::string> files;
@@ -626,13 +624,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
}
FILE* fout = cmsys::SystemTools::Fopen(args[2], "w+");
if (!fout) {
- std::cerr << "could not open output .def file: " << args[2].c_str()
- << "\n";
+ std::cerr << "could not open output .def file: " << args[2] << "\n";
return 1;
}
bindexplib deffile;
if (args.size() >= 5) {
- auto a = args[4];
+ std::string const& a = args[4];
if (cmHasLiteralPrefix(a, "--nm=")) {
deffile.SetNmPath(a.substr(5));
std::cerr << a.substr(5) << "\n";
@@ -640,7 +637,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
std::cerr << "unknown argument: " << a << "\n";
}
}
- for (auto const& file : files) {
+ for (std::string const& file : files) {
std::string const& ext = cmSystemTools::GetFilenameLastExtension(file);
if (cmSystemTools::LowerCase(ext) == ".def") {
if (!deffile.AddDefinitionFile(file.c_str())) {
@@ -1022,7 +1019,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
// Command to create a symbolic link. Fails on platforms not
// supporting them.
if (args[1] == "create_symlink" && args.size() == 4) {
- const char* destinationFileName = args[3].c_str();
+ std::string const& destinationFileName = args[3];
if ((cmSystemTools::FileExists(destinationFileName) ||
cmSystemTools::FileIsSymlink(destinationFileName)) &&
!cmSystemTools::RemoveFile(destinationFileName)) {
@@ -1038,6 +1035,34 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
return 0;
}
+ // Command to create a hard link. Fails on platforms not
+ // supporting them.
+ if (args[1] == "create_hardlink" && args.size() == 4) {
+ const char* SouceFileName = args[2].c_str();
+ const char* destinationFileName = args[3].c_str();
+
+ if (!cmSystemTools::FileExists(SouceFileName)) {
+ std::cerr << "failed to create hard link because source path '"
+ << SouceFileName << "' does not exist \n";
+ return 1;
+ }
+
+ if ((cmSystemTools::FileExists(destinationFileName) ||
+ cmSystemTools::FileIsSymlink(destinationFileName)) &&
+ !cmSystemTools::RemoveFile(destinationFileName)) {
+ std::string emsg = cmSystemTools::GetLastSystemError();
+ std::cerr << "failed to create hard link '" << destinationFileName
+ << "' because existing path cannot be removed: " << emsg
+ << "\n";
+ return 1;
+ }
+
+ if (!cmSystemTools::CreateLink(args[2], args[3])) {
+ return 1;
+ }
+ return 0;
+ }
+
// Command to do nothing with an exit code of 0.
if (args[1] == "true") {
return 0;
@@ -1136,7 +1161,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
return cmcmd::ExecuteLinkScript(args);
}
-#ifndef CMAKE_BOOTSTRAP
+#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_NINJA)
// Internal CMake ninja dependency scanning support.
if (args[1] == "cmake_ninja_depends") {
return cmcmd_cmake_ninja_depends(args.begin() + 2, args.end());
@@ -1379,15 +1404,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
#if defined(_WIN32) && !defined(__CYGWIN__)
// Write registry value
if (args[1] == "write_regv" && args.size() > 3) {
- return cmSystemTools::WriteRegistryValue(args[2].c_str(),
- args[3].c_str())
- ? 0
- : 1;
+ return cmSystemTools::WriteRegistryValue(args[2], args[3]) ? 0 : 1;
}
// Delete registry value
if (args[1] == "delete_regv" && args.size() > 2) {
- return cmSystemTools::DeleteRegistryValue(args[2].c_str()) ? 0 : 1;
+ return cmSystemTools::DeleteRegistryValue(args[2]) ? 0 : 1;
}
// Remove file
@@ -1750,7 +1772,7 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
// args[2] == source_file_path
// args[3] == intermediate_file
// args[4..n] == preprocess+args
- // args[n+1] == --
+ // args[n+1] == ++
// args[n+2...] == llvm-rc+args
if (args.size() < 3) {
std::cerr << "Invalid cmake_llvm_rc arguments";
@@ -1762,7 +1784,11 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
std::vector<std::string> resource_compile;
std::vector<std::string>* pArgTgt = &preprocess;
for (std::string const& arg : cmMakeRange(args).advance(4)) {
- if (arg == "--") {
+ // We use ++ as seperator between the preprocessing step definition and the
+ // rc compilation step becase we need to prepend a -- to seperate the
+ // source file properly from other options when using clang-cl for
+ // preprocessing.
+ if (arg == "++") {
pArgTgt = &resource_compile;
} else {
if (arg.find("SOURCE_DIR") != std::string::npos) {
diff --git a/Source/kwsys/CTestConfig.cmake b/Source/kwsys/CTestConfig.cmake
index 33ea84c..12347b6 100644
--- a/Source/kwsys/CTestConfig.cmake
+++ b/Source/kwsys/CTestConfig.cmake
@@ -3,7 +3,9 @@
set(CTEST_PROJECT_NAME "KWSys")
set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT")
-set(CTEST_DROP_METHOD "http")
+if (NOT CTEST_DROP_METHOD STREQUAL "https")
+ set(CTEST_DROP_METHOD "http")
+endif ()
set(CTEST_DROP_SITE "open.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=PublicDashboard")
set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index 5452f73..c6d4b19 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -27,7 +27,7 @@
#include <cstdio>
#include <cstring>
namespace KWSYS_NAMESPACE {
-#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
+#if defined(_WIN32) || defined(__APPLE__)
// On Windows and Apple, no difference between lower and upper case
# define KWSYS_GLOB_CASE_INDEPENDENT
#endif
diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in
index b5a34d5..e8474e2 100644
--- a/Source/kwsys/Glob.hxx.in
+++ b/Source/kwsys/Glob.hxx.in
@@ -126,8 +126,8 @@ protected:
bool RecurseListDirs;
private:
- Glob(const Glob&); // Not implemented.
- void operator=(const Glob&); // Not implemented.
+ Glob(const Glob&) = delete;
+ void operator=(const Glob&) = delete;
};
} // namespace @KWSYS_NAMESPACE@
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index cc45529..e1e7721 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -2128,17 +2128,17 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
#endif
#ifdef SIGABRT
case SIGABRT:
- KWSYSPE_CASE(Other, "Child aborted");
+ KWSYSPE_CASE(Other, "Subprocess aborted");
break;
#endif
#ifdef SIGKILL
case SIGKILL:
- KWSYSPE_CASE(Other, "Child killed");
+ KWSYSPE_CASE(Other, "Subprocess killed");
break;
#endif
#ifdef SIGTERM
case SIGTERM:
- KWSYSPE_CASE(Other, "Child terminated");
+ KWSYSPE_CASE(Other, "Subprocess terminated");
break;
#endif
#ifdef SIGHUP
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index ed1cdc0..9c34a56 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -863,7 +863,7 @@ void SystemInformation::RunMemoryCheck()
// Hide implementation details in an anonymous namespace.
namespace {
// *****************************************************************************
-#if defined(__linux) || defined(__APPLE__)
+#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__)
int LoadLines(FILE* file, std::vector<std::string>& lines)
{
// Load each line in the given file into a the vector.
@@ -893,7 +893,7 @@ int LoadLines(FILE* file, std::vector<std::string>& lines)
return nRead;
}
-# if defined(__linux)
+# if defined(__linux) || defined(__CYGWIN__)
// *****************************************************************************
int LoadLines(const char* fileName, std::vector<std::string>& lines)
{
@@ -926,7 +926,7 @@ int NameValue(std::vector<std::string> const& lines, std::string const& name,
}
#endif
-#if defined(__linux)
+#if defined(__linux) || defined(__CYGWIN__)
// ****************************************************************************
template <typename T>
int GetFieldsFromFile(const char* fileName, const char** fieldNames, T* values)
@@ -3393,7 +3393,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
pos = buffer.find("processor\t", pos + 1);
}
-#ifdef __linux
+#if defined(__linux) || defined(__CYGWIN__)
// Count sockets.
std::set<int> PhysicalIDs;
std::string idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id");
@@ -3414,8 +3414,8 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
this->NumberOfPhysicalCPU =
NumberOfCoresPerSocket * (unsigned int)NumberOfSockets;
-#else // __CYGWIN__
- // does not have "physical id" entries, neither "cpu cores"
+#else
+ // For systems which do not have "physical id" entries, neither "cpu cores"
// this has to be fixed for hyper-threading.
std::string cpucount =
this->ExtractValueFromCpuInfoFile(buffer, "cpu count");
@@ -3597,7 +3597,7 @@ long long SystemInformationImplementation::GetHostMemoryTotal()
GlobalMemoryStatusEx(&statex);
return statex.ullTotalPhys / 1024;
# endif
-#elif defined(__linux)
+#elif defined(__linux) || defined(__CYGWIN__)
long long memTotal = 0;
int ierr = GetFieldFromFile("/proc/meminfo", "MemTotal:", memTotal);
if (ierr) {
@@ -3712,6 +3712,16 @@ long long SystemInformationImplementation::GetHostMemoryUsed()
GlobalMemoryStatusEx(&statex);
return (statex.ullTotalPhys - statex.ullAvailPhys) / 1024;
# endif
+#elif defined(__CYGWIN__)
+ const char* names[3] = { "MemTotal:", "MemFree:", nullptr };
+ long long values[2] = { 0 };
+ int ierr = GetFieldsFromFile("/proc/meminfo", names, values);
+ if (ierr) {
+ return ierr;
+ }
+ long long& memTotal = values[0];
+ long long& memFree = values[1];
+ return memTotal - memFree;
#elif defined(__linux)
// First try to use MemAvailable, but it only works on newer kernels
const char* names2[3] = { "MemTotal:", "MemAvailable:", nullptr };
@@ -3773,7 +3783,7 @@ long long SystemInformationImplementation::GetProcMemoryUsed()
return -2;
}
return pmc.WorkingSetSize / 1024;
-#elif defined(__linux)
+#elif defined(__linux) || defined(__CYGWIN__)
long long memUsed = 0;
int ierr = GetFieldFromFile("/proc/self/status", "VmRSS:", memUsed);
if (ierr) {
@@ -3850,7 +3860,8 @@ long long SystemInformationImplementation::GetProcessId()
#if defined(_WIN32)
return GetCurrentProcessId();
#elif defined(__linux) || defined(__APPLE__) || defined(__OpenBSD__) || \
- defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+ defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
+ defined(__CYGWIN__)
return getpid();
#else
return -1;
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 25705ea..6144d9c 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -96,19 +96,12 @@
# if defined(_MSC_VER) && _MSC_VER >= 1800
# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
# endif
-#elif defined(__CYGWIN__)
-# include <windows.h>
-# undef _WIN32
#endif
#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
extern char** environ;
#endif
-#ifdef __CYGWIN__
-# include <sys/cygwin.h>
-#endif
-
// getpwnam doesn't exist on Windows and Cray Xt3/Catamount
// same for TIOCGWINSZ
#if defined(_WIN32) || defined(__LIBCATAMOUNT__) || \
@@ -1290,15 +1283,7 @@ bool SystemTools::PathExists(const std::string& path)
if (path.empty()) {
return false;
}
-#if defined(__CYGWIN__)
- // Convert path to native windows path if possible.
- char winpath[MAX_PATH];
- if (SystemTools::PathCygwinToWin32(path.c_str(), winpath)) {
- return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES);
- }
- struct stat st;
- return lstat(path.c_str(), &st) == 0;
-#elif defined(_WIN32)
+#if defined(_WIN32)
return (GetFileAttributesW(Encoding::ToWindowsExtendedPath(path).c_str()) !=
INVALID_FILE_ATTRIBUTES);
#else
@@ -1320,14 +1305,7 @@ bool SystemTools::FileExists(const std::string& filename)
if (filename.empty()) {
return false;
}
-#if defined(__CYGWIN__)
- // Convert filename to native windows path if possible.
- char winpath[MAX_PATH];
- if (SystemTools::PathCygwinToWin32(filename.c_str(), winpath)) {
- return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES);
- }
- return access(filename.c_str(), R_OK) == 0;
-#elif defined(_WIN32)
+#if defined(_WIN32)
DWORD attr =
GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str());
if (attr == INVALID_FILE_ATTRIBUTES) {
@@ -1433,27 +1411,9 @@ int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf)
#endif
}
-#ifdef __CYGWIN__
-bool SystemTools::PathCygwinToWin32(const char* path, char* win32_path)
-{
- auto itr = SystemToolsStatics->Cyg2Win32Map.find(path);
- if (itr != SystemToolsStatics->Cyg2Win32Map.end()) {
- strncpy(win32_path, itr->second.c_str(), MAX_PATH);
- } else {
- if (cygwin_conv_path(CCP_POSIX_TO_WIN_A, path, win32_path, MAX_PATH) !=
- 0) {
- win32_path[0] = 0;
- }
- SystemToolsStatics->Cyg2Win32Map.insert(
- SystemToolsStatic::StringMap::value_type(path, win32_path));
- }
- return win32_path[0] != 0;
-}
-#endif
-
bool SystemTools::Touch(const std::string& filename, bool create)
{
- if (!SystemTools::PathExists(filename)) {
+ if (!SystemTools::FileExists(filename)) {
if (create) {
FILE* file = Fopen(filename, "a+b");
if (file) {
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 5dbb726..74dc176 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -331,15 +331,6 @@ public:
static int Stat(const char* path, Stat_t* buf);
static int Stat(const std::string& path, Stat_t* buf);
-/**
- * Converts Cygwin path to Win32 path. Uses dictionary container for
- * caching and calls to cygwin_conv_to_win32_path from Cygwin dll
- * for actual translation. Returns true on success, else false.
- */
-#ifdef __CYGWIN__
- static bool PathCygwinToWin32(const char* path, char* win32_path);
-#endif
-
/**
* Return file length
*/
diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c
index 0c658f5..eed770c 100644
--- a/Source/kwsys/testProcess.c
+++ b/Source/kwsys/testProcess.c
@@ -450,24 +450,25 @@ static int runChild2(kwsysProcess* kp, const char* cmd[], int state,
printf("The process is still executing.\n");
break;
case kwsysProcess_State_Expired:
- printf("Child was killed when timeout expired.\n");
+ printf("Subprocess was killed when timeout expired.\n");
break;
case kwsysProcess_State_Exited:
- printf("Child exited with value = %d\n", kwsysProcess_GetExitValue(kp));
+ printf("Subprocess exited with value = %d\n",
+ kwsysProcess_GetExitValue(kp));
result = ((exception != kwsysProcess_GetExitException(kp)) ||
(value != kwsysProcess_GetExitValue(kp)));
break;
case kwsysProcess_State_Killed:
- printf("Child was killed by parent.\n");
+ printf("Subprocess was killed by parent.\n");
break;
case kwsysProcess_State_Exception:
- printf("Child terminated abnormally: %s\n",
+ printf("Subprocess terminated abnormally: %s\n",
kwsysProcess_GetExceptionString(kp));
result = ((exception != kwsysProcess_GetExitException(kp)) ||
(value != kwsysProcess_GetExitValue(kp)));
break;
case kwsysProcess_State_Disowned:
- printf("Child was disowned.\n");
+ printf("Subprocess was disowned.\n");
break;
case kwsysProcess_State_Error:
printf("Error in administrating child process: [%s]\n",
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index 1d34614..cfa420d 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -422,6 +422,28 @@ static bool CheckFileOperations()
res = false;
}
+#if !defined(_WIN32)
+ std::string const testBadSymlink(testNewDir + "/badSymlink.txt");
+ std::string const testBadSymlinkTgt(testNewDir + "/missing/symlinkTgt.txt");
+ if (!kwsys::SystemTools::CreateSymlink(testBadSymlinkTgt, testBadSymlink)) {
+ std::cerr << "Problem with CreateSymlink for: " << testBadSymlink << " -> "
+ << testBadSymlinkTgt << std::endl;
+ res = false;
+ }
+
+ if (!kwsys::SystemTools::Touch(testBadSymlink, false)) {
+ std::cerr << "Problem with Touch (no create) for: " << testBadSymlink
+ << std::endl;
+ res = false;
+ }
+#endif
+
+ if (!kwsys::SystemTools::Touch(testNewDir, false)) {
+ std::cerr << "Problem with Touch (no create) for: " << testNewDir
+ << std::endl;
+ res = false;
+ }
+
kwsys::SystemTools::Touch(testNewFile, true);
if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) {
std::cerr << "Problem with RemoveADirectory for: " << testNewDir